Skip to content

Commit

Permalink
Sync with upstream
Browse files Browse the repository at this point in the history
  • Loading branch information
WyattBlue committed Jul 1, 2024
1 parent fc23236 commit a782980
Show file tree
Hide file tree
Showing 40 changed files with 226 additions and 88 deletions.
18 changes: 0 additions & 18 deletions av/__init__.pyi

This file was deleted.

2 changes: 2 additions & 0 deletions av/_core.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ class _Meta(TypedDict):

library_meta: dict[str, _Meta]
library_versions: dict[str, tuple[int, int, int]]

time_base: int
2 changes: 1 addition & 1 deletion av/about.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "12.1.0"
__version__ = "12.2.0"
8 changes: 7 additions & 1 deletion av/audio/codeccontext.pyi
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from typing import Literal
from typing import Iterator, Literal

from av.codec.context import CodecContext
from av.packet import Packet

from .format import AudioFormat
from .frame import AudioFrame
from .layout import AudioLayout

class AudioCodecContext(CodecContext):
Expand All @@ -14,3 +16,7 @@ class AudioCodecContext(CodecContext):
layout: AudioLayout
format: AudioFormat
type: Literal["audio"]

def encode(self, frame: AudioFrame | None = None) -> list[Packet]: ...
def encode_lazy(self, frame: AudioFrame | None = None) -> Iterator[Packet]: ...
def decode(self, packet: Packet | None = None) -> list[AudioFrame]: ...
16 changes: 16 additions & 0 deletions av/audio/fifo.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from .format import AudioFormat
from .frame import AudioFrame
from .layout import AudioLayout

class AudioFifo:
def write(self, frame: AudioFrame) -> None: ...
def read(self, samples: int = 0, partial: bool = False) -> AudioFrame | None: ...
def read_many(self, samples: int, partial: bool = False) -> list[AudioFrame]: ...
@property
def format(self) -> AudioFormat: ...
@property
def layout(self) -> AudioLayout: ...
@property
def sample_rate(self) -> int: ...
@property
def samples(self) -> int: ...
2 changes: 2 additions & 0 deletions av/audio/format.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ class AudioFormat:
planar: AudioFormat
packed: AudioFormat
container_name: str

def __init__(self, name: str | AudioFormat) -> None: ...
11 changes: 5 additions & 6 deletions av/audio/format.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ cdef class AudioFormat:
def name(self):
"""Canonical name of the sample format.
>>> SampleFormat('s16p').name
>>> AudioFormat('s16p').name
's16p'
"""
Expand All @@ -55,7 +55,7 @@ cdef class AudioFormat:
def bytes(self):
"""Number of bytes per sample.
>>> SampleFormat('s16p').bytes
>>> AudioFormat('s16p').bytes
2
"""
Expand All @@ -65,7 +65,7 @@ cdef class AudioFormat:
def bits(self):
"""Number of bits per sample.
>>> SampleFormat('s16p').bits
>>> AudioFormat('s16p').bits
16
"""
Expand Down Expand Up @@ -95,8 +95,7 @@ cdef class AudioFormat:
Is itself when planar:
>>> from av import AudioFormat as Format
>>> fmt = Format('s16p')
>>> fmt = AudioFormat('s16p')
>>> fmt.planar is fmt
True
Expand All @@ -111,7 +110,7 @@ cdef class AudioFormat:
Is itself when packed:
>>> fmt = Format('s16')
>>> fmt = AudioFormat('s16')
>>> fmt.packed is fmt
True
Expand Down
2 changes: 1 addition & 1 deletion av/audio/layout.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ cdef class AudioLayout:
elif isinstance(layout, str):
c_layout = lib.av_get_channel_layout(layout)
elif isinstance(layout, AudioLayout):
c_layout = layout.layout
c_layout = (<AudioLayout>layout).layout
else:
raise TypeError("layout must be str or int")

Expand Down
2 changes: 1 addition & 1 deletion av/bitstream.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ from av.packet cimport Packet

cdef class BitStreamFilterContext:

cdef const lib.AVBSFContext *ptr
cdef lib.AVBSFContext *ptr

cpdef filter(self, Packet packet=?)
cpdef flush(self)
5 changes: 5 additions & 0 deletions av/buffer.pyi
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
# When Python 3.12 becomes our lowest supported version, we could make this
# class inherit `collections.abc.Buffer`.

class Buffer:
buffer_size: int
buffer_ptr: int
def update(self, input: bytes) -> None: ...
def __buffer__(self, flags: int) -> memoryview: ...
def __bytes__(self) -> bytes: ...
4 changes: 3 additions & 1 deletion av/codec/context.pyi
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from fractions import Fraction
from typing import Any, Literal

from av.enum import EnumFlag, EnumItem
from av.frame import Frame
from av.packet import Packet

from .codec import Codec
Expand Down Expand Up @@ -60,8 +60,10 @@ class CodecContext:
is_encoder: bool
is_decoder: bool
name: str
options: dict[str, str]
type: Literal["video", "audio", "data", "subtitle", "attachment"]
profile: str | None
time_base: Fraction
codec_tag: str
bit_rate: int | None
max_bit_rate: int | None
Expand Down
2 changes: 1 addition & 1 deletion av/codec/context.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ cdef class CodecContext:
def skip_frame(self):
"""One of :class:`.SkipType`.
Wraps ffmpeg:`AVCodecContext.skip_frame`.
Wraps :ffmpeg:`AVCodecContext.skip_frame`.
"""
return SkipType._get(self.ptr.skip_frame, create=True)
Expand Down
6 changes: 6 additions & 0 deletions av/container/input.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ class InputContainer(Container):
def close(self) -> None: ...
def demux(self, *args: Any, **kwargs: Any) -> Iterator[Packet]: ...
@overload
def decode(self, video: int) -> Iterator[VideoFrame]: ...
@overload
def decode(self, audio: int) -> Iterator[AudioFrame]: ...
@overload
def decode(self, subtitles: int) -> Iterator[SubtitleSet]: ...
@overload
def decode(self, *args: VideoStream) -> Iterator[VideoFrame]: ...
@overload
def decode(self, *args: AudioStream) -> Iterator[AudioFrame]: ...
Expand Down
48 changes: 47 additions & 1 deletion av/error.pyi
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import builtins

from .enum import EnumItem

classes: dict[int, Exception]
Expand Down Expand Up @@ -58,4 +60,48 @@ class LookupError(FFmpegError): ...
class HTTPError(FFmpegError): ...
class HTTPClientError(FFmpegError): ...
class UndefinedError(FFmpegError): ...
class InvalidDataError(ValueError): ...
class InvalidDataError(FFmpegError, builtins.ValueError): ...
class BugError(FFmpegError, builtins.RuntimeError): ...
class BufferTooSmallError(FFmpegError, builtins.ValueError): ...
class BSFNotFoundError(LookupError): ...
class DecoderNotFoundError(LookupError): ...
class DemuxerNotFoundError(LookupError): ...
class EncoderNotFoundError(LookupError): ...
class ExitError(FFmpegError): ...
class ExternalError(FFmpegError): ...
class FilterNotFoundError(LookupError): ...
class MuxerNotFoundError(LookupError): ...
class OptionNotFoundError(LookupError): ...
class PatchWelcomeError(FFmpegError): ...
class ProtocolNotFoundError(LookupError): ...
class UnknownError(FFmpegError): ...
class ExperimentalError(FFmpegError): ...
class InputChangedError(FFmpegError): ...
class OutputChangedError(FFmpegError): ...
class HTTPBadRequestError(HTTPClientError): ...
class HTTPUnauthorizedError(HTTPClientError): ...
class HTTPForbiddenError(HTTPClientError): ...
class HTTPNotFoundError(HTTPClientError): ...
class HTTPOtherClientError(HTTPClientError): ...
class HTTPServerError(HTTPError): ...
class PyAVCallbackError(FFmpegError, builtins.RuntimeError): ...
class BrokenPipeError(FFmpegError, builtins.BrokenPipeError): ...
class ChildProcessError(FFmpegError, builtins.ChildProcessError): ...
class ConnectionAbortedError(FFmpegError, builtins.ConnectionAbortedError): ...
class ConnectionRefusedError(FFmpegError, builtins.ConnectionRefusedError): ...
class ConnectionResetError(FFmpegError, builtins.ConnectionResetError): ...
class BlockingIOError(FFmpegError, builtins.BlockingIOError): ...
class EOFError(FFmpegError, builtins.EOFError): ...
class FileExistsError(FFmpegError, builtins.FileExistsError): ...
class FileNotFoundError(FFmpegError, builtins.FileNotFoundError): ...
class InterruptedError(FFmpegError, builtins.InterruptedError): ...
class IsADirectoryError(FFmpegError, builtins.IsADirectoryError): ...
class MemoryError(FFmpegError, builtins.MemoryError): ...
class NotADirectoryError(FFmpegError, builtins.NotADirectoryError): ...
class NotImplementedError(FFmpegError, builtins.NotImplementedError): ...
class OverflowError(FFmpegError, builtins.OverflowError): ...
class OSError(FFmpegError, builtins.OSError): ...
class PermissionError(FFmpegError, builtins.PermissionError): ...
class ProcessLookupError(FFmpegError, builtins.ProcessLookupError): ...
class TimeoutError(FFmpegError, builtins.TimeoutError): ...
class ValueError(FFmpegError, builtins.ValueError): ...
2 changes: 0 additions & 2 deletions av/error.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,6 @@ _extend_builtin("ValueError", (errno.EINVAL, ))
_extend_builtin("MemoryError", (errno.ENOMEM, ))
_extend_builtin("NotImplementedError", (errno.ENOSYS, ))
_extend_builtin("OverflowError", (errno.ERANGE, ))
if IOError is not OSError:
_extend_builtin("IOError", (errno.EIO, ))

# The rest of them (for now)
_extend_builtin("OSError", [code for code in errno.errorcode if code not in classes])
Expand Down
2 changes: 1 addition & 1 deletion av/filter/context.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ from av.filter.graph cimport Graph
cdef class FilterContext:

cdef lib.AVFilterContext *ptr
cdef readonly Graph graph
cdef readonly object _graph
cdef readonly Filter filter

cdef object _inputs
Expand Down
3 changes: 3 additions & 0 deletions av/filter/context.pyi
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from av.filter import Graph
from av.frame import Frame

from .pad import FilterContextPad
Expand All @@ -11,5 +12,7 @@ class FilterContext:
def link_to(
self, input_: FilterContext, output_idx: int = 0, input_idx: int = 0
) -> None: ...
@property
def graph(self) -> Graph: ...
def push(self, frame: Frame) -> None: ...
def pull(self) -> Frame: ...
11 changes: 10 additions & 1 deletion av/filter/context.pyx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import weakref

from av.audio.frame cimport alloc_audio_frame
from av.dictionary cimport _Dictionary
from av.dictionary import Dictionary
Expand All @@ -13,7 +15,7 @@ cdef object _cinit_sentinel = object()

cdef FilterContext wrap_filter_context(Graph graph, Filter filter, lib.AVFilterContext *ptr):
cdef FilterContext self = FilterContext(_cinit_sentinel)
self.graph = graph
self._graph = weakref.ref(graph)
self.filter = filter
self.ptr = ptr
return self
Expand Down Expand Up @@ -72,6 +74,13 @@ cdef class FilterContext:

def link_to(self, FilterContext input_, int output_idx=0, int input_idx=0):
err_check(lib.avfilter_link(self.ptr, output_idx, input_.ptr, input_idx))

@property
def graph(self):
if (graph := self._graph()):
return graph
else:
raise RuntimeError("graph is unallocated")

def push(self, Frame frame):
cdef int res
Expand Down
1 change: 1 addition & 0 deletions av/filter/graph.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ from av.filter.context cimport FilterContext


cdef class Graph:
cdef object __weakref__

cdef lib.AVFilterGraph *ptr

Expand Down
2 changes: 2 additions & 0 deletions av/filter/graph.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,5 @@ class Graph:
) -> FilterContext: ...
def push(self, frame: None | AudioFrame | VideoFrame) -> None: ...
def pull(self) -> VideoFrame | AudioFrame: ...
def vpush(self, frame: VideoFrame | None) -> None: ...
def vpull(self) -> VideoFrame: ...
20 changes: 17 additions & 3 deletions av/filter/graph.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,16 @@ cdef class Graph:
else:
raise ValueError(f"can only AudioFrame, VideoFrame or None; got {type(frame)}")

if len(contexts) != 1:
raise ValueError(f"can only auto-push with single buffer; found {len(contexts)}")
for ctx in contexts:
ctx.push(frame)

contexts[0].push(frame)
def vpush(self, VideoFrame frame):
"""Like `push`, but only for VideoFrames."""
for ctx in self._context_by_type.get("buffer", []):
ctx.push(frame)


# TODO: Test complex filter graphs, add `at: int = 0` arg to pull() and vpull().
def pull(self):
vsinks = self._context_by_type.get("buffersink", [])
asinks = self._context_by_type.get("abuffersink", [])
Expand All @@ -188,3 +193,12 @@ cdef class Graph:
raise ValueError(f"can only auto-pull with single sink; found {nsinks}")

return (vsinks or asinks)[0].pull()

def vpull(self):
"""Like `pull`, but only for VideoFrames."""
vsinks = self._context_by_type.get("buffersink", [])
nsinks = len(vsinks)
if nsinks != 1:
raise ValueError(f"can only auto-pull with single sink; found {nsinks}")

return vsinks[0].pull()
2 changes: 2 additions & 0 deletions av/frame.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ class Frame:
time_base: Fraction
is_corrupt: bool
side_data: dict[str, str]

def make_writable(self) -> None: ...
11 changes: 11 additions & 0 deletions av/frame.pyx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from av.error cimport err_check
from av.utils cimport avrational_to_fraction, to_avrational

from av.sidedata.sidedata import SideDataContainer
Expand Down Expand Up @@ -137,3 +138,13 @@ cdef class Frame:
if self._side_data is None:
self._side_data = SideDataContainer(self)
return self._side_data

def make_writable(self):
"""
Ensures that the frame data is writable. Copy the data to new buffer if it is not.
This is a wrapper around :ffmpeg:`av_frame_make_writable`.
"""
cdef int ret

ret = lib.av_frame_make_writable(self.ptr)
err_check(ret)
3 changes: 1 addition & 2 deletions av/packet.pyi
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from collections.abc import Buffer
from fractions import Fraction

from av.subtitles.subtitle import SubtitleSet

from .buffer import Buffer
from .stream import Stream

class Packet(Buffer):
Expand All @@ -22,4 +22,3 @@ class Packet(Buffer):

def __init__(self, input: int | bytes | None = None) -> None: ...
def decode(self) -> list[SubtitleSet]: ...
def __buffer__(self, arg1) -> memoryview: ...
2 changes: 1 addition & 1 deletion av/packet.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ cdef class Packet(Buffer):
if input is None:
return

if isinstance(input, (int, long)):
if isinstance(input, int):
size = input
else:
source = bytesource(input)
Expand Down
Loading

0 comments on commit a782980

Please sign in to comment.