Skip to content

Commit

Permalink
Move encode and decode to concrete classes
Browse files Browse the repository at this point in the history
  • Loading branch information
WyattBlue committed Mar 9, 2024
1 parent 9ad1d91 commit 23ce2a3
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 40 deletions.
14 changes: 11 additions & 3 deletions av/audio/stream.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,19 @@ from av.stream import Stream
from .codeccontext import AudioCodecContext
from .format import AudioFormat
from .frame import AudioFrame
from .layout import AudioLayout

class AudioStream(Stream):
type: Literal["audio"]
format: AudioFormat
codec_context: AudioCodecContext
# From codec context
frame_size: int
sample_rate: int
rate: int
channels: int
channel_layout: int
layout: AudioLayout
format: AudioFormat
type: Literal["audio"]

def encode(self, frame: AudioFrame | None = None) -> list[Packet]: ... # type: ignore[override]
def encode(self, frame: AudioFrame | None = None) -> list[Packet]: ...
def decode(self, packet: Packet | None = None) -> list[AudioFrame]: ...
31 changes: 30 additions & 1 deletion av/audio/stream.pyx
Original file line number Diff line number Diff line change
@@ -1,7 +1,36 @@
from av.packet cimport Packet


cdef class AudioStream(Stream):
def __repr__(self):
form = self.format.name if self.format else None
return (
f"<av.{self.__class__.__name__} #{self.index} {self.name} at {self.rate}Hz,"
f"<av.AudioStream #{self.index} {self.name} at {self.rate}Hz,"
f" {self.layout.name}, {form} at 0x{id(self):x}>"
)

def encode(self, frame=None):
"""
Encode an :class:`.AudioFrame` and return a list of :class:`.Packet`.
:return: :class:`list` of :class:`.Packet`.
.. seealso:: This is mostly a passthrough to :meth:`.CodecContext.encode`.
"""

packets = self.codec_context.encode(frame)
cdef Packet packet
for packet in packets:
packet._stream = self
packet.ptr.stream_index = self.ptr.index

return packets

def decode(self, packet=None):
"""
Decode a :class:`.Packet` and return a list of :class:`.AudioFrame`.
:return: :class:`list` of :class:`.AudioFrame`
.. seealso:: This is a passthrough to :meth:`.CodecContext.decode`.
"""

return self.codec_context.decode(packet)
2 changes: 0 additions & 2 deletions av/stream.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,3 @@ class Stream:
frames: int
language: str | None
type: Literal["video", "audio", "data", "subtitle", "attachment"]

def encode(self, frame: Frame | None = None) -> list[Packet]: ...
19 changes: 0 additions & 19 deletions av/stream.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -146,25 +146,6 @@ cdef class Stream:
# Lets just copy what we want.
err_check(lib.avcodec_parameters_from_context(self.ptr.codecpar, self.codec_context.ptr))

def encode(self, frame=None):
"""
Encode an :class:`.AudioFrame` or :class:`.VideoFrame` and return a list
of :class:`.Packet`.
:return: :class:`list` of :class:`.Packet`.
.. seealso:: This is mostly a passthrough to :meth:`.CodecContext.encode`.
"""
if self.codec_context is None:
raise RuntimeError("Stream.encode requires a valid CodecContext")

packets = self.codec_context.encode(frame)
cdef Packet packet
for packet in packets:
packet._stream = self
packet.ptr.stream_index = self.ptr.index
return packets

cdef _get_side_data(self, lib.AVStream *stream):
# Get DISPLAYMATRIX SideData from a lib.AVStream object.
# Returns: tuple[int, dict[str, Any]]
Expand Down
10 changes: 6 additions & 4 deletions av/video/codeccontext.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,29 @@ from typing import Iterator, Literal
from av.codec.context import CodecContext
from av.packet import Packet

from .format import VideoFormat
from .frame import VideoFrame

class VideoCodecContext(CodecContext):
format: VideoFormat
width: int
height: int
bits_per_codec_sample: int
pix_fmt: str
pix_fmt: str | None
framerate: Fraction
rate: Fraction
gop_size: int
sample_aspect_ratio: Fraction
display_aspect_ratio: Fraction
sample_aspect_ratio: Fraction | None
display_aspect_ratio: Fraction | None
has_b_frames: bool
coded_width: int
coded_height: int
color_range: int
color_primaries: int
color_trc: int
colorspace: int

type: Literal["video"]

def encode(self, frame: VideoFrame | None = None) -> list[Packet]: ...
def encode_lazy(self, frame: VideoFrame | None = None) -> Iterator[Packet]: ...
def decode(self, packet: Packet | None = None) -> list[VideoFrame]: ...
31 changes: 21 additions & 10 deletions av/video/stream.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,31 @@ from .format import VideoFormat
from .frame import VideoFrame

class VideoStream(Stream):
width: int
height: int
format: VideoFormat
pix_fmt: str | None
sample_aspect_ratio: Fraction | None
codec_context: VideoCodecContext
type: Literal["video"]

# from codec context
bit_rate: int | None
max_bit_rate: int | None
bit_rate_tolerance: int
thread_count: int
thread_type: Any
codec_context: VideoCodecContext
# from codec context
format: VideoFormat
width: int
height: int
bits_per_codec_sample: int
pix_fmt: str | None
framerate: Fraction
rate: Fraction
gop_size: int
sample_aspect_ratio: Fraction | None
display_aspect_ratio: Fraction | None
has_b_frames: bool
coded_width: int
coded_height: int
color_range: int
color_primaries: int
color_trc: int
colorspace: int
type: Literal["video"]

def encode(self, frame: VideoFrame | None = None) -> list[Packet]: ... # type: ignore[override]
def encode(self, frame: VideoFrame | None = None) -> list[Packet]: ...
def decode(self, packet: Packet | None = None) -> list[VideoFrame]: ...
32 changes: 31 additions & 1 deletion av/video/stream.pyx
Original file line number Diff line number Diff line change
@@ -1,7 +1,37 @@
from av.packet cimport Packet


cdef class VideoStream(Stream):
def __repr__(self):
return (
f"<av.{self.__class__.__name__} #{self.index} {self.name}, "
f"<av.VideoStream #{self.index} {self.name}, "
f"{self.format.name if self.format else None} {self.codec_context.width}x"
f"{self.codec_context.height} at 0x{id(self):x}>"
)

def encode(self, frame=None):
"""
Encode an :class:`.VideoFrame` and return a list of :class:`.Packet`.
:return: :class:`list` of :class:`.Packet`.
.. seealso:: This is mostly a passthrough to :meth:`.CodecContext.encode`.
"""

packets = self.codec_context.encode(frame)
cdef Packet packet
for packet in packets:
packet._stream = self
packet.ptr.stream_index = self.ptr.index

return packets


def decode(self, packet=None):
"""
Decode a :class:`.Packet` and return a list of :class:`.VideoFrame`.
:return: :class:`list` of :class:`.Frame` subclasses.
.. seealso:: This is a passthrough to :meth:`.CodecContext.decode`.
"""

return self.codec_context.decode(packet)

0 comments on commit 23ce2a3

Please sign in to comment.