Initialisation du repository de Beta
This commit is contained in:
commit
14985f6dbb
9469 changed files with 1903273 additions and 0 deletions
0
venv/lib/python3.12/site-packages/av/audio/__init__.pxd
Normal file
0
venv/lib/python3.12/site-packages/av/audio/__init__.pxd
Normal file
2
venv/lib/python3.12/site-packages/av/audio/__init__.py
Normal file
2
venv/lib/python3.12/site-packages/av/audio/__init__.py
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
from .frame import AudioFrame
|
||||
from .stream import AudioStream
|
||||
16
venv/lib/python3.12/site-packages/av/audio/__init__.pyi
Normal file
16
venv/lib/python3.12/site-packages/av/audio/__init__.pyi
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
from typing import Literal
|
||||
|
||||
from .frame import AudioFrame
|
||||
from .stream import AudioStream
|
||||
|
||||
_AudioCodecName = Literal[
|
||||
"aac",
|
||||
"libopus",
|
||||
"mp2",
|
||||
"mp3",
|
||||
"pcm_alaw",
|
||||
"pcm_mulaw",
|
||||
"pcm_s16le",
|
||||
]
|
||||
|
||||
__all__ = ("AudioFrame", "AudioStream")
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
11
venv/lib/python3.12/site-packages/av/audio/codeccontext.pxd
Normal file
11
venv/lib/python3.12/site-packages/av/audio/codeccontext.pxd
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
from av.audio.frame cimport AudioFrame
|
||||
from av.audio.resampler cimport AudioResampler
|
||||
from av.codec.context cimport CodecContext
|
||||
|
||||
|
||||
cdef class AudioCodecContext(CodecContext):
|
||||
# Hold onto the frames that we will decode until we have a full one.
|
||||
cdef AudioFrame next_frame
|
||||
# For encoding.
|
||||
cdef AudioResampler resampler
|
||||
105
venv/lib/python3.12/site-packages/av/audio/codeccontext.py
Normal file
105
venv/lib/python3.12/site-packages/av/audio/codeccontext.py
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
import cython
|
||||
from cython.cimports import libav as lib
|
||||
from cython.cimports.av.audio.format import AudioFormat, get_audio_format
|
||||
from cython.cimports.av.audio.frame import AudioFrame, alloc_audio_frame
|
||||
from cython.cimports.av.audio.layout import AudioLayout, get_audio_layout
|
||||
from cython.cimports.av.frame import Frame
|
||||
from cython.cimports.av.packet import Packet
|
||||
|
||||
|
||||
@cython.cclass
|
||||
class AudioCodecContext(CodecContext):
|
||||
@cython.cfunc
|
||||
def _prepare_frames_for_encode(self, input_frame: Frame | None):
|
||||
frame: AudioFrame | None = input_frame
|
||||
allow_var_frame_size: cython.bint = (
|
||||
self.ptr.codec.capabilities & lib.AV_CODEC_CAP_VARIABLE_FRAME_SIZE
|
||||
)
|
||||
|
||||
# Note that the resampler will simply return an input frame if there is
|
||||
# no resampling to be done. The control flow was just a little easier this way.
|
||||
if not self.resampler:
|
||||
self.resampler = AudioResampler(
|
||||
format=self.format,
|
||||
layout=self.layout,
|
||||
rate=self.ptr.sample_rate,
|
||||
frame_size=None if allow_var_frame_size else self.ptr.frame_size,
|
||||
)
|
||||
frames = self.resampler.resample(frame)
|
||||
if input_frame is None:
|
||||
frames.append(None) # flush if input frame is None
|
||||
|
||||
return frames
|
||||
|
||||
@cython.cfunc
|
||||
def _alloc_next_frame(self) -> Frame:
|
||||
return alloc_audio_frame()
|
||||
|
||||
@cython.cfunc
|
||||
def _setup_decoded_frame(self, frame: Frame, packet: Packet):
|
||||
CodecContext._setup_decoded_frame(self, frame, packet)
|
||||
aframe: AudioFrame = frame
|
||||
aframe._init_user_attributes()
|
||||
|
||||
@property
|
||||
def frame_size(self):
|
||||
"""
|
||||
Number of samples per channel in an audio frame.
|
||||
|
||||
:type: int
|
||||
"""
|
||||
return self.ptr.frame_size
|
||||
|
||||
@property
|
||||
def sample_rate(self):
|
||||
"""
|
||||
Sample rate of the audio data, in samples per second.
|
||||
|
||||
:type: int
|
||||
"""
|
||||
return self.ptr.sample_rate
|
||||
|
||||
@sample_rate.setter
|
||||
def sample_rate(self, value: cython.int):
|
||||
self.ptr.sample_rate = value
|
||||
|
||||
@property
|
||||
def rate(self):
|
||||
"""Another name for :attr:`sample_rate`."""
|
||||
return self.sample_rate
|
||||
|
||||
@rate.setter
|
||||
def rate(self, value):
|
||||
self.sample_rate = value
|
||||
|
||||
@property
|
||||
def channels(self):
|
||||
return self.layout.nb_channels
|
||||
|
||||
@property
|
||||
def layout(self):
|
||||
"""
|
||||
The audio channel layout.
|
||||
|
||||
:type: AudioLayout
|
||||
"""
|
||||
return get_audio_layout(self.ptr.ch_layout)
|
||||
|
||||
@layout.setter
|
||||
def layout(self, value):
|
||||
layout: AudioLayout = AudioLayout(value)
|
||||
self.ptr.ch_layout = layout.layout
|
||||
|
||||
@property
|
||||
def format(self):
|
||||
"""
|
||||
The audio sample format.
|
||||
|
||||
:type: AudioFormat
|
||||
"""
|
||||
return get_audio_format(self.ptr.sample_fmt)
|
||||
|
||||
@format.setter
|
||||
def format(self, value):
|
||||
format: AudioFormat = AudioFormat(value)
|
||||
self.ptr.sample_fmt = format.sample_fmt
|
||||
29
venv/lib/python3.12/site-packages/av/audio/codeccontext.pyi
Normal file
29
venv/lib/python3.12/site-packages/av/audio/codeccontext.pyi
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
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 _Format:
|
||||
def __get__(self, i: object | None, owner: type | None = None) -> AudioFormat: ...
|
||||
def __set__(self, instance: object, value: AudioFormat | str) -> None: ...
|
||||
|
||||
class _Layout:
|
||||
def __get__(self, i: object | None, owner: type | None = None) -> AudioLayout: ...
|
||||
def __set__(self, instance: object, value: AudioLayout | str) -> None: ...
|
||||
|
||||
class AudioCodecContext(CodecContext):
|
||||
frame_size: int
|
||||
sample_rate: int
|
||||
rate: int
|
||||
type: Literal["audio"]
|
||||
format: _Format
|
||||
layout: _Layout
|
||||
@property
|
||||
def channels(self) -> int: ...
|
||||
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]: ...
|
||||
BIN
venv/lib/python3.12/site-packages/av/audio/fifo.cpython-312-x86_64-linux-gnu.so
Executable file
BIN
venv/lib/python3.12/site-packages/av/audio/fifo.cpython-312-x86_64-linux-gnu.so
Executable file
Binary file not shown.
19
venv/lib/python3.12/site-packages/av/audio/fifo.pxd
Normal file
19
venv/lib/python3.12/site-packages/av/audio/fifo.pxd
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
cimport libav as lib
|
||||
from libc.stdint cimport int64_t, uint64_t
|
||||
|
||||
from av.audio.frame cimport AudioFrame
|
||||
|
||||
|
||||
cdef class AudioFifo:
|
||||
|
||||
cdef lib.AVAudioFifo *ptr
|
||||
|
||||
cdef AudioFrame template
|
||||
|
||||
cdef readonly uint64_t samples_written
|
||||
cdef readonly uint64_t samples_read
|
||||
cdef readonly double pts_per_sample
|
||||
|
||||
cpdef write(self, AudioFrame frame)
|
||||
cpdef read(self, int samples=*, bint partial=*)
|
||||
cpdef read_many(self, int samples, bint partial=*)
|
||||
22
venv/lib/python3.12/site-packages/av/audio/fifo.pyi
Normal file
22
venv/lib/python3.12/site-packages/av/audio/fifo.pyi
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
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: ...
|
||||
@property
|
||||
def samples_written(self) -> int: ...
|
||||
@property
|
||||
def samples_read(self) -> int: ...
|
||||
@property
|
||||
def pts_per_sample(self) -> float: ...
|
||||
197
venv/lib/python3.12/site-packages/av/audio/fifo.pyx
Normal file
197
venv/lib/python3.12/site-packages/av/audio/fifo.pyx
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
from av.audio.frame cimport alloc_audio_frame
|
||||
from av.error cimport err_check
|
||||
|
||||
|
||||
cdef class AudioFifo:
|
||||
"""A simple audio sample FIFO (First In First Out) buffer."""
|
||||
|
||||
def __repr__(self):
|
||||
try:
|
||||
result = (
|
||||
f"<av.{self.__class__.__name__} {self.samples} samples of "
|
||||
f"{self.sample_rate}hz {self.layout} {self.format} at 0x{id(self):x}>"
|
||||
)
|
||||
except AttributeError:
|
||||
result = (
|
||||
f"<av.{self.__class__.__name__} uninitialized, use fifo.write(frame),"
|
||||
f" at 0x{id(self):x}>"
|
||||
)
|
||||
return result
|
||||
|
||||
def __dealloc__(self):
|
||||
if self.ptr:
|
||||
lib.av_audio_fifo_free(self.ptr)
|
||||
|
||||
cpdef write(self, AudioFrame frame):
|
||||
"""write(frame)
|
||||
|
||||
Push a frame of samples into the queue.
|
||||
|
||||
:param AudioFrame frame: The frame of samples to push.
|
||||
|
||||
The FIFO will remember the attributes from the first frame, and use those
|
||||
to populate all output frames.
|
||||
|
||||
If there is a :attr:`~.Frame.pts` and :attr:`~.Frame.time_base` and
|
||||
:attr:`~.AudioFrame.sample_rate`, then the FIFO will assert that the incoming
|
||||
timestamps are continuous.
|
||||
|
||||
"""
|
||||
|
||||
if frame is None:
|
||||
raise TypeError("AudioFifo must be given an AudioFrame.")
|
||||
|
||||
if not frame.ptr.nb_samples:
|
||||
return
|
||||
|
||||
if not self.ptr:
|
||||
|
||||
# Hold onto a copy of the attributes of the first frame to populate
|
||||
# output frames with.
|
||||
self.template = alloc_audio_frame()
|
||||
self.template._copy_internal_attributes(frame)
|
||||
self.template._init_user_attributes()
|
||||
|
||||
# Figure out our "time_base".
|
||||
if frame._time_base.num and frame.ptr.sample_rate:
|
||||
self.pts_per_sample = frame._time_base.den / float(frame._time_base.num)
|
||||
self.pts_per_sample /= frame.ptr.sample_rate
|
||||
else:
|
||||
self.pts_per_sample = 0
|
||||
|
||||
self.ptr = lib.av_audio_fifo_alloc(
|
||||
<lib.AVSampleFormat>frame.ptr.format,
|
||||
frame.layout.nb_channels,
|
||||
frame.ptr.nb_samples * 2, # Just a default number of samples; it will adjust.
|
||||
)
|
||||
|
||||
if not self.ptr:
|
||||
raise RuntimeError("Could not allocate AVAudioFifo.")
|
||||
|
||||
# Make sure nothing changed.
|
||||
elif (
|
||||
frame.ptr.format != self.template.ptr.format or
|
||||
# TODO: frame.ptr.ch_layout != self.template.ptr.ch_layout or
|
||||
frame.ptr.sample_rate != self.template.ptr.sample_rate or
|
||||
(frame._time_base.num and self.template._time_base.num and (
|
||||
frame._time_base.num != self.template._time_base.num or
|
||||
frame._time_base.den != self.template._time_base.den
|
||||
))
|
||||
):
|
||||
raise ValueError("Frame does not match AudioFifo parameters.")
|
||||
|
||||
# Assert that the PTS are what we expect.
|
||||
cdef int64_t expected_pts
|
||||
if self.pts_per_sample and frame.ptr.pts != lib.AV_NOPTS_VALUE:
|
||||
expected_pts = <int64_t>(self.pts_per_sample * self.samples_written)
|
||||
if frame.ptr.pts != expected_pts:
|
||||
raise ValueError(
|
||||
"Frame.pts (%d) != expected (%d); fix or set to None." % (frame.ptr.pts, expected_pts)
|
||||
)
|
||||
|
||||
err_check(lib.av_audio_fifo_write(
|
||||
self.ptr,
|
||||
<void **>frame.ptr.extended_data,
|
||||
frame.ptr.nb_samples,
|
||||
))
|
||||
|
||||
self.samples_written += frame.ptr.nb_samples
|
||||
|
||||
cpdef read(self, int samples=0, bint partial=False):
|
||||
"""read(samples=0, partial=False)
|
||||
|
||||
Read samples from the queue.
|
||||
|
||||
:param int samples: The number of samples to pull; 0 gets all.
|
||||
:param bool partial: Allow returning less than requested.
|
||||
:returns: New :class:`AudioFrame` or ``None`` (if empty).
|
||||
|
||||
If the incoming frames had valid a :attr:`~.Frame.time_base`,
|
||||
:attr:`~.AudioFrame.sample_rate` and :attr:`~.Frame.pts`, the returned frames
|
||||
will have accurate timing.
|
||||
|
||||
"""
|
||||
|
||||
if not self.ptr:
|
||||
return
|
||||
|
||||
cdef int buffered_samples = lib.av_audio_fifo_size(self.ptr)
|
||||
if buffered_samples < 1:
|
||||
return
|
||||
|
||||
samples = samples or buffered_samples
|
||||
|
||||
if buffered_samples < samples:
|
||||
if partial:
|
||||
samples = buffered_samples
|
||||
else:
|
||||
return
|
||||
|
||||
cdef AudioFrame frame = alloc_audio_frame()
|
||||
frame._copy_internal_attributes(self.template)
|
||||
frame._init(
|
||||
<lib.AVSampleFormat>self.template.ptr.format,
|
||||
<lib.AVChannelLayout>self.template.ptr.ch_layout,
|
||||
samples,
|
||||
1, # Align?
|
||||
)
|
||||
|
||||
err_check(lib.av_audio_fifo_read(
|
||||
self.ptr,
|
||||
<void **>frame.ptr.extended_data,
|
||||
samples,
|
||||
))
|
||||
|
||||
if self.pts_per_sample:
|
||||
frame.ptr.pts = <uint64_t>(self.pts_per_sample * self.samples_read)
|
||||
else:
|
||||
frame.ptr.pts = lib.AV_NOPTS_VALUE
|
||||
|
||||
self.samples_read += samples
|
||||
|
||||
return frame
|
||||
|
||||
cpdef read_many(self, int samples, bint partial=False):
|
||||
"""read_many(samples, partial=False)
|
||||
|
||||
Read as many frames as we can.
|
||||
|
||||
:param int samples: How large for the frames to be.
|
||||
:param bool partial: If we should return a partial frame.
|
||||
:returns: A ``list`` of :class:`AudioFrame`.
|
||||
|
||||
"""
|
||||
|
||||
cdef AudioFrame frame
|
||||
frames = []
|
||||
while True:
|
||||
frame = self.read(samples, partial=partial)
|
||||
if frame is not None:
|
||||
frames.append(frame)
|
||||
else:
|
||||
break
|
||||
|
||||
return frames
|
||||
|
||||
@property
|
||||
def format(self):
|
||||
"""The :class:`.AudioFormat` of this FIFO."""
|
||||
if not self.ptr:
|
||||
raise AttributeError(f"'{__name__}.AudioFifo' object has no attribute 'format'")
|
||||
return self.template.format
|
||||
@property
|
||||
def layout(self):
|
||||
"""The :class:`.AudioLayout` of this FIFO."""
|
||||
if not self.ptr:
|
||||
raise AttributeError(f"'{__name__}.AudioFifo' object has no attribute 'layout'")
|
||||
return self.template.layout
|
||||
@property
|
||||
def sample_rate(self):
|
||||
if not self.ptr:
|
||||
raise AttributeError(f"'{__name__}.AudioFifo' object has no attribute 'sample_rate'")
|
||||
return self.template.sample_rate
|
||||
|
||||
@property
|
||||
def samples(self):
|
||||
"""Number of audio samples (per channel) in the buffer."""
|
||||
return lib.av_audio_fifo_size(self.ptr) if self.ptr else 0
|
||||
Binary file not shown.
7
venv/lib/python3.12/site-packages/av/audio/format.pxd
Normal file
7
venv/lib/python3.12/site-packages/av/audio/format.pxd
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
cimport libav as lib
|
||||
|
||||
|
||||
cdef class AudioFormat:
|
||||
cdef lib.AVSampleFormat sample_fmt
|
||||
|
||||
cdef AudioFormat get_audio_format(lib.AVSampleFormat format)
|
||||
142
venv/lib/python3.12/site-packages/av/audio/format.py
Normal file
142
venv/lib/python3.12/site-packages/av/audio/format.py
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
import sys
|
||||
|
||||
import cython
|
||||
|
||||
container_format_postfix: str = "le" if sys.byteorder == "little" else "be"
|
||||
_cinit_bypass_sentinel = object()
|
||||
|
||||
|
||||
@cython.cfunc
|
||||
def get_audio_format(c_format: lib.AVSampleFormat) -> AudioFormat:
|
||||
"""Get an AudioFormat without going through a string."""
|
||||
|
||||
if c_format < 0:
|
||||
return None
|
||||
|
||||
format: AudioFormat = AudioFormat(_cinit_bypass_sentinel)
|
||||
format.sample_fmt = c_format
|
||||
return format
|
||||
|
||||
|
||||
@cython.cclass
|
||||
class AudioFormat:
|
||||
"""Descriptor of audio formats."""
|
||||
|
||||
def __cinit__(self, name):
|
||||
if name is _cinit_bypass_sentinel:
|
||||
return
|
||||
|
||||
sample_fmt: lib.AVSampleFormat
|
||||
if isinstance(name, AudioFormat):
|
||||
sample_fmt = cython.cast(AudioFormat, name).sample_fmt
|
||||
else:
|
||||
sample_fmt = lib.av_get_sample_fmt(name)
|
||||
|
||||
if sample_fmt < 0:
|
||||
raise ValueError(f"Not a sample format: {name!r}")
|
||||
|
||||
self.sample_fmt = sample_fmt
|
||||
|
||||
def __repr__(self):
|
||||
return f"<av.AudioFormat {self.name}>"
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Canonical name of the sample format.
|
||||
|
||||
>>> AudioFormat('s16p').name
|
||||
's16p'
|
||||
|
||||
"""
|
||||
return lib.av_get_sample_fmt_name(self.sample_fmt)
|
||||
|
||||
@property
|
||||
def bytes(self):
|
||||
"""Number of bytes per sample.
|
||||
|
||||
>>> AudioFormat('s16p').bytes
|
||||
2
|
||||
|
||||
"""
|
||||
return lib.av_get_bytes_per_sample(self.sample_fmt)
|
||||
|
||||
@property
|
||||
def bits(self):
|
||||
"""Number of bits per sample.
|
||||
|
||||
>>> AudioFormat('s16p').bits
|
||||
16
|
||||
|
||||
"""
|
||||
return lib.av_get_bytes_per_sample(self.sample_fmt) << 3
|
||||
|
||||
@property
|
||||
def is_planar(self):
|
||||
"""Is this a planar format?
|
||||
|
||||
Strictly opposite of :attr:`is_packed`.
|
||||
|
||||
"""
|
||||
return bool(lib.av_sample_fmt_is_planar(self.sample_fmt))
|
||||
|
||||
@property
|
||||
def is_packed(self):
|
||||
"""Is this a packed format?
|
||||
|
||||
Strictly opposite of :attr:`is_planar`.
|
||||
|
||||
"""
|
||||
return not lib.av_sample_fmt_is_planar(self.sample_fmt)
|
||||
|
||||
@property
|
||||
def planar(self):
|
||||
"""The planar variant of this format.
|
||||
|
||||
Is itself when planar:
|
||||
|
||||
>>> fmt = AudioFormat('s16p')
|
||||
>>> fmt.planar is fmt
|
||||
True
|
||||
|
||||
"""
|
||||
if self.is_planar:
|
||||
return self
|
||||
return get_audio_format(lib.av_get_planar_sample_fmt(self.sample_fmt))
|
||||
|
||||
@property
|
||||
def packed(self):
|
||||
"""The packed variant of this format.
|
||||
|
||||
Is itself when packed:
|
||||
|
||||
>>> fmt = AudioFormat('s16')
|
||||
>>> fmt.packed is fmt
|
||||
True
|
||||
|
||||
"""
|
||||
if self.is_packed:
|
||||
return self
|
||||
return get_audio_format(lib.av_get_packed_sample_fmt(self.sample_fmt))
|
||||
|
||||
@property
|
||||
def container_name(self):
|
||||
"""The name of a :class:`ContainerFormat` which directly accepts this data.
|
||||
|
||||
:raises ValueError: when planar, since there are no such containers.
|
||||
|
||||
"""
|
||||
if self.is_planar:
|
||||
raise ValueError("no planar container formats")
|
||||
|
||||
if self.sample_fmt == lib.AV_SAMPLE_FMT_U8:
|
||||
return "u8"
|
||||
elif self.sample_fmt == lib.AV_SAMPLE_FMT_S16:
|
||||
return "s16" + container_format_postfix
|
||||
elif self.sample_fmt == lib.AV_SAMPLE_FMT_S32:
|
||||
return "s32" + container_format_postfix
|
||||
elif self.sample_fmt == lib.AV_SAMPLE_FMT_FLT:
|
||||
return "f32" + container_format_postfix
|
||||
elif self.sample_fmt == lib.AV_SAMPLE_FMT_DBL:
|
||||
return "f64" + container_format_postfix
|
||||
|
||||
raise ValueError("unknown layout")
|
||||
11
venv/lib/python3.12/site-packages/av/audio/format.pyi
Normal file
11
venv/lib/python3.12/site-packages/av/audio/format.pyi
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
class AudioFormat:
|
||||
name: str
|
||||
bytes: int
|
||||
bits: int
|
||||
is_planar: bool
|
||||
is_packed: bool
|
||||
planar: AudioFormat
|
||||
packed: AudioFormat
|
||||
container_name: str
|
||||
|
||||
def __init__(self, name: str | AudioFormat) -> None: ...
|
||||
BIN
venv/lib/python3.12/site-packages/av/audio/frame.cpython-312-x86_64-linux-gnu.so
Executable file
BIN
venv/lib/python3.12/site-packages/av/audio/frame.cpython-312-x86_64-linux-gnu.so
Executable file
Binary file not shown.
31
venv/lib/python3.12/site-packages/av/audio/frame.pxd
Normal file
31
venv/lib/python3.12/site-packages/av/audio/frame.pxd
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
cimport libav as lib
|
||||
from libc.stdint cimport uint8_t, uint64_t
|
||||
|
||||
from av.audio.format cimport AudioFormat
|
||||
from av.audio.layout cimport AudioLayout
|
||||
from av.frame cimport Frame
|
||||
|
||||
|
||||
cdef class AudioFrame(Frame):
|
||||
# For raw storage of the frame's data; don't ever touch this.
|
||||
cdef uint8_t *_buffer
|
||||
cdef size_t _buffer_size
|
||||
|
||||
cdef readonly AudioLayout layout
|
||||
"""
|
||||
The audio channel layout.
|
||||
|
||||
:type: AudioLayout
|
||||
"""
|
||||
|
||||
cdef readonly AudioFormat format
|
||||
"""
|
||||
The audio sample format.
|
||||
|
||||
:type: AudioFormat
|
||||
"""
|
||||
|
||||
cdef _init(self, lib.AVSampleFormat format, lib.AVChannelLayout layout, unsigned int nb_samples, unsigned int align)
|
||||
cdef _init_user_attributes(self)
|
||||
|
||||
cdef AudioFrame alloc_audio_frame()
|
||||
205
venv/lib/python3.12/site-packages/av/audio/frame.py
Normal file
205
venv/lib/python3.12/site-packages/av/audio/frame.py
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
import cython
|
||||
from cython.cimports.av.audio.format import get_audio_format
|
||||
from cython.cimports.av.audio.layout import get_audio_layout
|
||||
from cython.cimports.av.audio.plane import AudioPlane
|
||||
from cython.cimports.av.error import err_check
|
||||
from cython.cimports.av.utils import check_ndarray
|
||||
|
||||
_cinit_bypass_sentinel = object()
|
||||
|
||||
|
||||
@cython.cfunc
|
||||
def alloc_audio_frame() -> AudioFrame:
|
||||
return AudioFrame(_cinit_bypass_sentinel)
|
||||
|
||||
|
||||
format_dtypes = {
|
||||
"dbl": "f8",
|
||||
"dblp": "f8",
|
||||
"flt": "f4",
|
||||
"fltp": "f4",
|
||||
"s16": "i2",
|
||||
"s16p": "i2",
|
||||
"s32": "i4",
|
||||
"s32p": "i4",
|
||||
"u8": "u1",
|
||||
"u8p": "u1",
|
||||
}
|
||||
|
||||
|
||||
@cython.cclass
|
||||
class AudioFrame(Frame):
|
||||
"""A frame of audio."""
|
||||
|
||||
def __cinit__(self, format="s16", layout="stereo", samples=0, align=1):
|
||||
if format is _cinit_bypass_sentinel:
|
||||
return
|
||||
|
||||
cy_format: AudioFormat = AudioFormat(format)
|
||||
cy_layout: AudioLayout = AudioLayout(layout)
|
||||
self._init(cy_format.sample_fmt, cy_layout.layout, samples, align)
|
||||
|
||||
@cython.cfunc
|
||||
def _init(
|
||||
self,
|
||||
format: lib.AVSampleFormat,
|
||||
layout: lib.AVChannelLayout,
|
||||
nb_samples: cython.uint,
|
||||
align: cython.uint,
|
||||
):
|
||||
self.ptr.nb_samples = nb_samples
|
||||
self.ptr.format = format
|
||||
self.ptr.ch_layout = layout
|
||||
|
||||
# Sometimes this is called twice. Oh well.
|
||||
self._init_user_attributes()
|
||||
|
||||
if self.layout.nb_channels != 0 and nb_samples:
|
||||
# Cleanup the old buffer.
|
||||
lib.av_freep(cython.address(self._buffer))
|
||||
|
||||
# Get a new one.
|
||||
self._buffer_size = err_check(
|
||||
lib.av_samples_get_buffer_size(
|
||||
cython.NULL, self.layout.nb_channels, nb_samples, format, align
|
||||
)
|
||||
)
|
||||
self._buffer = cython.cast(
|
||||
cython.pointer[uint8_t], lib.av_malloc(self._buffer_size)
|
||||
)
|
||||
if not self._buffer:
|
||||
raise MemoryError("cannot allocate AudioFrame buffer")
|
||||
|
||||
# Connect the data pointers to the buffer.
|
||||
err_check(
|
||||
lib.avcodec_fill_audio_frame(
|
||||
self.ptr,
|
||||
self.layout.nb_channels,
|
||||
cython.cast(lib.AVSampleFormat, self.ptr.format),
|
||||
self._buffer,
|
||||
self._buffer_size,
|
||||
align,
|
||||
)
|
||||
)
|
||||
|
||||
def __dealloc__(self):
|
||||
lib.av_freep(cython.address(self._buffer))
|
||||
|
||||
@cython.cfunc
|
||||
def _init_user_attributes(self):
|
||||
self.layout = get_audio_layout(self.ptr.ch_layout)
|
||||
self.format = get_audio_format(cython.cast(lib.AVSampleFormat, self.ptr.format))
|
||||
|
||||
def __repr__(self):
|
||||
return (
|
||||
f"<av.{self.__class__.__name__} pts={self.pts}, {self.samples} "
|
||||
f"samples at {self.rate}Hz, {self.layout.name}, {self.format.name} at 0x{id(self):x}>"
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def from_ndarray(array, format="s16", layout="stereo"):
|
||||
"""
|
||||
Construct a frame from a numpy array.
|
||||
"""
|
||||
import numpy as np
|
||||
|
||||
py_format = format if isinstance(format, AudioFormat) else AudioFormat(format)
|
||||
py_layout = layout if isinstance(layout, AudioLayout) else AudioLayout(layout)
|
||||
format = py_format.name
|
||||
|
||||
# map avcodec type to numpy type
|
||||
try:
|
||||
dtype = np.dtype(format_dtypes[format])
|
||||
except KeyError:
|
||||
raise ValueError(
|
||||
f"Conversion from numpy array with format `{format}` is not yet supported"
|
||||
)
|
||||
|
||||
# check input format
|
||||
nb_channels = py_layout.nb_channels
|
||||
check_ndarray(array, dtype, 2)
|
||||
if py_format.is_planar:
|
||||
if array.shape[0] != nb_channels:
|
||||
raise ValueError(
|
||||
f"Expected planar `array.shape[0]` to equal `{nb_channels}` but got `{array.shape[0]}`"
|
||||
)
|
||||
samples = array.shape[1]
|
||||
else:
|
||||
if array.shape[0] != 1:
|
||||
raise ValueError(
|
||||
f"Expected packed `array.shape[0]` to equal `1` but got `{array.shape[0]}`"
|
||||
)
|
||||
samples = array.shape[1] // nb_channels
|
||||
|
||||
frame = AudioFrame(format=py_format, layout=py_layout, samples=samples)
|
||||
for i, plane in enumerate(frame.planes):
|
||||
plane.update(array[i, :])
|
||||
return frame
|
||||
|
||||
@property
|
||||
def planes(self):
|
||||
"""
|
||||
A tuple of :class:`~av.audio.plane.AudioPlane`.
|
||||
|
||||
:type: tuple
|
||||
"""
|
||||
plane_count: cython.int = 0
|
||||
while self.ptr.extended_data[plane_count]:
|
||||
plane_count += 1
|
||||
|
||||
return tuple([AudioPlane(self, i) for i in range(plane_count)])
|
||||
|
||||
@property
|
||||
def samples(self):
|
||||
"""
|
||||
Number of audio samples (per channel).
|
||||
|
||||
:type: int
|
||||
"""
|
||||
return self.ptr.nb_samples
|
||||
|
||||
@property
|
||||
def sample_rate(self):
|
||||
"""
|
||||
Sample rate of the audio data, in samples per second.
|
||||
|
||||
:type: int
|
||||
"""
|
||||
return self.ptr.sample_rate
|
||||
|
||||
@sample_rate.setter
|
||||
def sample_rate(self, value):
|
||||
self.ptr.sample_rate = value
|
||||
|
||||
@property
|
||||
def rate(self):
|
||||
"""Another name for :attr:`sample_rate`."""
|
||||
return self.ptr.sample_rate
|
||||
|
||||
@rate.setter
|
||||
def rate(self, value):
|
||||
self.ptr.sample_rate = value
|
||||
|
||||
def to_ndarray(self):
|
||||
"""Get a numpy array of this frame.
|
||||
|
||||
.. note:: Numpy must be installed.
|
||||
|
||||
"""
|
||||
import numpy as np
|
||||
|
||||
try:
|
||||
dtype = np.dtype(format_dtypes[self.format.name])
|
||||
except KeyError:
|
||||
raise ValueError(
|
||||
f"Conversion from {self.format.name!r} format to numpy array is not supported."
|
||||
)
|
||||
|
||||
if self.format.is_planar:
|
||||
count = self.samples
|
||||
else:
|
||||
count = self.samples * self.layout.nb_channels
|
||||
|
||||
return np.vstack(
|
||||
[np.frombuffer(x, dtype=dtype, count=count) for x in self.planes]
|
||||
)
|
||||
49
venv/lib/python3.12/site-packages/av/audio/frame.pyi
Normal file
49
venv/lib/python3.12/site-packages/av/audio/frame.pyi
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
from typing import Any, Union
|
||||
|
||||
import numpy as np
|
||||
|
||||
from av.frame import Frame
|
||||
|
||||
from .format import AudioFormat
|
||||
from .layout import AudioLayout
|
||||
from .plane import AudioPlane
|
||||
|
||||
format_dtypes: dict[str, str]
|
||||
_SupportedNDarray = Union[
|
||||
np.ndarray[Any, np.dtype[np.float64]], # f8
|
||||
np.ndarray[Any, np.dtype[np.float32]], # f4
|
||||
np.ndarray[Any, np.dtype[np.int32]], # i4
|
||||
np.ndarray[Any, np.dtype[np.int16]], # i2
|
||||
np.ndarray[Any, np.dtype[np.uint8]], # u1
|
||||
]
|
||||
|
||||
class _Format:
|
||||
def __get__(self, i: object | None, owner: type | None = None) -> AudioFormat: ...
|
||||
def __set__(self, instance: object, value: AudioFormat | str) -> None: ...
|
||||
|
||||
class _Layout:
|
||||
def __get__(self, i: object | None, owner: type | None = None) -> AudioLayout: ...
|
||||
def __set__(self, instance: object, value: AudioLayout | str) -> None: ...
|
||||
|
||||
class AudioFrame(Frame):
|
||||
planes: tuple[AudioPlane, ...]
|
||||
samples: int
|
||||
sample_rate: int
|
||||
rate: int
|
||||
format: _Format
|
||||
layout: _Layout
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
format: AudioFormat | str = "s16",
|
||||
layout: AudioLayout | str = "stereo",
|
||||
samples: int = 0,
|
||||
align: int = 1,
|
||||
) -> None: ...
|
||||
@staticmethod
|
||||
def from_ndarray(
|
||||
array: _SupportedNDarray,
|
||||
format: AudioFormat | str = "s16",
|
||||
layout: AudioLayout | str = "stereo",
|
||||
) -> AudioFrame: ...
|
||||
def to_ndarray(self) -> _SupportedNDarray: ...
|
||||
Binary file not shown.
8
venv/lib/python3.12/site-packages/av/audio/layout.pxd
Normal file
8
venv/lib/python3.12/site-packages/av/audio/layout.pxd
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
cimport libav as lib
|
||||
|
||||
|
||||
cdef class AudioLayout:
|
||||
cdef lib.AVChannelLayout layout
|
||||
cdef _init(self, lib.AVChannelLayout layout)
|
||||
|
||||
cdef AudioLayout get_audio_layout(lib.AVChannelLayout c_layout)
|
||||
12
venv/lib/python3.12/site-packages/av/audio/layout.pyi
Normal file
12
venv/lib/python3.12/site-packages/av/audio/layout.pyi
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
from dataclasses import dataclass
|
||||
|
||||
class AudioLayout:
|
||||
name: str
|
||||
nb_channels: int
|
||||
channels: tuple[AudioChannel, ...]
|
||||
def __init__(self, layout: str | AudioLayout): ...
|
||||
|
||||
@dataclass
|
||||
class AudioChannel:
|
||||
name: str
|
||||
description: str
|
||||
82
venv/lib/python3.12/site-packages/av/audio/layout.pyx
Normal file
82
venv/lib/python3.12/site-packages/av/audio/layout.pyx
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
cimport libav as lib
|
||||
from cpython.bytes cimport PyBytes_FromStringAndSize
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass
|
||||
class AudioChannel:
|
||||
name: str
|
||||
description: str
|
||||
|
||||
def __repr__(self):
|
||||
return f"<av.AudioChannel '{self.name}' ({self.description})>"
|
||||
|
||||
cdef object _cinit_bypass_sentinel
|
||||
|
||||
cdef AudioLayout get_audio_layout(lib.AVChannelLayout c_layout):
|
||||
"""Get an AudioLayout from Cython land."""
|
||||
cdef AudioLayout layout = AudioLayout.__new__(AudioLayout, _cinit_bypass_sentinel)
|
||||
layout._init(c_layout)
|
||||
return layout
|
||||
|
||||
|
||||
cdef class AudioLayout:
|
||||
def __init__(self, layout):
|
||||
if layout is _cinit_bypass_sentinel:
|
||||
return
|
||||
|
||||
if type(layout) is str:
|
||||
ret = lib.av_channel_layout_from_string(&c_layout, layout)
|
||||
if ret != 0:
|
||||
raise ValueError(f"Invalid layout: {layout}")
|
||||
elif isinstance(layout, AudioLayout):
|
||||
c_layout = (<AudioLayout>layout).layout
|
||||
else:
|
||||
raise TypeError(f"layout must be of type: string | av.AudioLayout, got {type(layout)}")
|
||||
|
||||
self._init(c_layout)
|
||||
|
||||
cdef _init(self, lib.AVChannelLayout layout):
|
||||
self.layout = layout
|
||||
|
||||
def __repr__(self):
|
||||
return f"<av.{self.__class__.__name__} {self.name!r}>"
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, AudioLayout) and self.name == other.name and self.nb_channels == other.nb_channels
|
||||
|
||||
@property
|
||||
def nb_channels(self):
|
||||
return self.layout.nb_channels
|
||||
|
||||
@property
|
||||
def channels(self):
|
||||
cdef char buf[16]
|
||||
cdef char buf2[128]
|
||||
|
||||
results = []
|
||||
|
||||
for index in range(self.layout.nb_channels):
|
||||
size = lib.av_channel_name(buf, sizeof(buf), lib.av_channel_layout_channel_from_index(&self.layout, index)) - 1
|
||||
size2 = lib.av_channel_description(buf2, sizeof(buf2), lib.av_channel_layout_channel_from_index(&self.layout, index)) - 1
|
||||
results.append(
|
||||
AudioChannel(
|
||||
PyBytes_FromStringAndSize(buf, size).decode("utf-8"),
|
||||
PyBytes_FromStringAndSize(buf2, size2).decode("utf-8"),
|
||||
)
|
||||
)
|
||||
|
||||
return tuple(results)
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""The canonical name of the audio layout."""
|
||||
cdef char layout_name[128]
|
||||
cdef int ret
|
||||
|
||||
ret = lib.av_channel_layout_describe(&self.layout, layout_name, sizeof(layout_name))
|
||||
if ret < 0:
|
||||
raise RuntimeError(f"Failed to get layout name: {ret}")
|
||||
|
||||
return layout_name
|
||||
BIN
venv/lib/python3.12/site-packages/av/audio/plane.cpython-312-x86_64-linux-gnu.so
Executable file
BIN
venv/lib/python3.12/site-packages/av/audio/plane.cpython-312-x86_64-linux-gnu.so
Executable file
Binary file not shown.
6
venv/lib/python3.12/site-packages/av/audio/plane.pxd
Normal file
6
venv/lib/python3.12/site-packages/av/audio/plane.pxd
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
from av.plane cimport Plane
|
||||
|
||||
|
||||
cdef class AudioPlane(Plane):
|
||||
cdef readonly size_t buffer_size
|
||||
cdef size_t _buffer_size(self)
|
||||
13
venv/lib/python3.12/site-packages/av/audio/plane.py
Normal file
13
venv/lib/python3.12/site-packages/av/audio/plane.py
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import cython
|
||||
from cython.cimports.av.audio.frame import AudioFrame
|
||||
|
||||
|
||||
@cython.cclass
|
||||
class AudioPlane(Plane):
|
||||
def __cinit__(self, frame: AudioFrame, index: cython.int):
|
||||
# Only the first linesize is ever populated, but it applies to every plane.
|
||||
self.buffer_size = self.frame.ptr.linesize[0]
|
||||
|
||||
@cython.cfunc
|
||||
def _buffer_size(self) -> cython.size_t:
|
||||
return self.buffer_size
|
||||
4
venv/lib/python3.12/site-packages/av/audio/plane.pyi
Normal file
4
venv/lib/python3.12/site-packages/av/audio/plane.pyi
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
from av.plane import Plane
|
||||
|
||||
class AudioPlane(Plane):
|
||||
buffer_size: int
|
||||
Binary file not shown.
18
venv/lib/python3.12/site-packages/av/audio/resampler.pxd
Normal file
18
venv/lib/python3.12/site-packages/av/audio/resampler.pxd
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
from av.audio.format cimport AudioFormat
|
||||
from av.audio.frame cimport AudioFrame
|
||||
from av.audio.layout cimport AudioLayout
|
||||
from av.filter.graph cimport Graph
|
||||
|
||||
|
||||
cdef class AudioResampler:
|
||||
cdef readonly bint is_passthrough
|
||||
cdef AudioFrame template
|
||||
|
||||
# Destination descriptors
|
||||
cdef readonly AudioFormat format
|
||||
cdef readonly AudioLayout layout
|
||||
cdef readonly int rate
|
||||
cdef readonly unsigned int frame_size
|
||||
|
||||
cdef Graph graph
|
||||
cpdef list resample(self, AudioFrame)
|
||||
122
venv/lib/python3.12/site-packages/av/audio/resampler.py
Normal file
122
venv/lib/python3.12/site-packages/av/audio/resampler.py
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
from errno import EAGAIN
|
||||
|
||||
import cython
|
||||
from cython.cimports.av.filter.context import FilterContext
|
||||
from cython.cimports.av.filter.graph import Graph
|
||||
|
||||
from av.error import FFmpegError
|
||||
|
||||
|
||||
@cython.cclass
|
||||
class AudioResampler:
|
||||
"""AudioResampler(format=None, layout=None, rate=None)
|
||||
|
||||
:param AudioFormat format: The target format, or string that parses to one
|
||||
(e.g. ``"s16"``).
|
||||
:param AudioLayout layout: The target layout, or an int/string that parses
|
||||
to one (e.g. ``"stereo"``).
|
||||
:param int rate: The target sample rate.
|
||||
"""
|
||||
|
||||
def __cinit__(self, format=None, layout=None, rate=None, frame_size=None):
|
||||
if format is not None:
|
||||
self.format = (
|
||||
format if isinstance(format, AudioFormat) else AudioFormat(format)
|
||||
)
|
||||
|
||||
if layout is not None:
|
||||
self.layout = AudioLayout(layout)
|
||||
|
||||
self.rate = int(rate) if rate else 0
|
||||
self.frame_size = int(frame_size) if frame_size else 0
|
||||
self.graph = None
|
||||
|
||||
@cython.ccall
|
||||
def resample(self, frame: AudioFrame | None) -> list:
|
||||
"""resample(frame)
|
||||
|
||||
Convert the ``sample_rate``, ``channel_layout`` and/or ``format`` of
|
||||
a :class:`~.AudioFrame`.
|
||||
|
||||
:param AudioFrame frame: The frame to convert or `None` to flush.
|
||||
:returns: A list of :class:`AudioFrame` in new parameters. If the nothing is to be done return the same frame
|
||||
as a single element list.
|
||||
|
||||
"""
|
||||
# We don't have any input, so don't bother even setting up.
|
||||
if not self.graph and frame is None:
|
||||
return []
|
||||
|
||||
# Shortcut for passthrough.
|
||||
if self.is_passthrough:
|
||||
return [frame]
|
||||
|
||||
# Take source settings from the first frame.
|
||||
if not self.graph:
|
||||
self.template = frame
|
||||
|
||||
# Set some default descriptors.
|
||||
self.format = self.format or frame.format
|
||||
self.layout = self.layout or frame.layout
|
||||
self.rate = self.rate or frame.sample_rate
|
||||
|
||||
# Check if we can passthrough or if there is actually work to do.
|
||||
if (
|
||||
frame.format.sample_fmt == self.format.sample_fmt
|
||||
and frame.layout == self.layout
|
||||
and frame.sample_rate == self.rate
|
||||
and self.frame_size == 0
|
||||
):
|
||||
self.is_passthrough = True
|
||||
return [frame]
|
||||
|
||||
# handle resampling with aformat filter
|
||||
# (similar to configure_output_audio_filter from ffmpeg)
|
||||
self.graph = Graph()
|
||||
extra_args = {}
|
||||
if frame.time_base is not None:
|
||||
extra_args["time_base"] = f"{frame.time_base}"
|
||||
|
||||
abuffer = self.graph.add(
|
||||
"abuffer",
|
||||
sample_rate=f"{frame.sample_rate}",
|
||||
sample_fmt=AudioFormat(frame.format).name,
|
||||
channel_layout=frame.layout.name,
|
||||
**extra_args,
|
||||
)
|
||||
aformat = self.graph.add(
|
||||
"aformat",
|
||||
sample_rates=f"{self.rate}",
|
||||
sample_fmts=self.format.name,
|
||||
channel_layouts=self.layout.name,
|
||||
)
|
||||
abuffersink = self.graph.add("abuffersink")
|
||||
abuffer.link_to(aformat)
|
||||
aformat.link_to(abuffersink)
|
||||
self.graph.configure()
|
||||
|
||||
if self.frame_size > 0:
|
||||
self.graph.set_audio_frame_size(self.frame_size)
|
||||
|
||||
if frame is not None:
|
||||
if (
|
||||
frame.format.sample_fmt != self.template.format.sample_fmt
|
||||
or frame.layout != self.template.layout
|
||||
or frame.sample_rate != self.template.rate
|
||||
):
|
||||
raise ValueError("Frame does not match AudioResampler setup.")
|
||||
|
||||
self.graph.push(frame)
|
||||
|
||||
output: list = []
|
||||
while True:
|
||||
try:
|
||||
output.append(self.graph.pull())
|
||||
except EOFError:
|
||||
break
|
||||
except FFmpegError as e:
|
||||
if e.errno != EAGAIN:
|
||||
raise
|
||||
break
|
||||
|
||||
return output
|
||||
20
venv/lib/python3.12/site-packages/av/audio/resampler.pyi
Normal file
20
venv/lib/python3.12/site-packages/av/audio/resampler.pyi
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
from av.filter.graph import Graph
|
||||
|
||||
from .format import AudioFormat
|
||||
from .frame import AudioFrame
|
||||
from .layout import AudioLayout
|
||||
|
||||
class AudioResampler:
|
||||
rate: int
|
||||
frame_size: int
|
||||
format: AudioFormat
|
||||
graph: Graph | None
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
format: str | int | AudioFormat | None = None,
|
||||
layout: str | int | AudioLayout | None = None,
|
||||
rate: int | None = None,
|
||||
frame_size: int | None = None,
|
||||
) -> None: ...
|
||||
def resample(self, frame: AudioFrame | None) -> list[AudioFrame]: ...
|
||||
Binary file not shown.
9
venv/lib/python3.12/site-packages/av/audio/stream.pxd
Normal file
9
venv/lib/python3.12/site-packages/av/audio/stream.pxd
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
from av.packet cimport Packet
|
||||
from av.stream cimport Stream
|
||||
|
||||
from .frame cimport AudioFrame
|
||||
|
||||
|
||||
cdef class AudioStream(Stream):
|
||||
cpdef encode(self, AudioFrame frame=?)
|
||||
cpdef decode(self, Packet packet=?)
|
||||
46
venv/lib/python3.12/site-packages/av/audio/stream.py
Normal file
46
venv/lib/python3.12/site-packages/av/audio/stream.py
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
import cython
|
||||
from cython.cimports.av.audio.frame import AudioFrame
|
||||
from cython.cimports.av.packet import Packet
|
||||
|
||||
|
||||
@cython.cclass
|
||||
class AudioStream(Stream):
|
||||
def __repr__(self):
|
||||
form = self.format.name if self.format else None
|
||||
return (
|
||||
f"<av.AudioStream #{self.index} {self.name} at {self.rate}Hz,"
|
||||
f" {self.layout.name}, {form} at 0x{id(self):x}>"
|
||||
)
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.codec_context, name)
|
||||
|
||||
@cython.ccall
|
||||
def encode(self, frame: AudioFrame | None = None):
|
||||
"""
|
||||
Encode an :class:`.AudioFrame` and return a list of :class:`.Packet`.
|
||||
|
||||
:rtype: list[Packet]
|
||||
|
||||
.. seealso:: This is mostly a passthrough to :meth:`.CodecContext.encode`.
|
||||
"""
|
||||
|
||||
packets = self.codec_context.encode(frame)
|
||||
packet: Packet
|
||||
for packet in packets:
|
||||
packet._stream = self
|
||||
packet.ptr.stream_index = self.ptr.index
|
||||
|
||||
return packets
|
||||
|
||||
@cython.ccall
|
||||
def decode(self, packet: Packet | None = None):
|
||||
"""
|
||||
Decode a :class:`.Packet` and return a list of :class:`.AudioFrame`.
|
||||
|
||||
:rtype: list[AudioFrame]
|
||||
|
||||
.. seealso:: This is a passthrough to :meth:`.CodecContext.decode`.
|
||||
"""
|
||||
|
||||
return self.codec_context.decode(packet)
|
||||
32
venv/lib/python3.12/site-packages/av/audio/stream.pyi
Normal file
32
venv/lib/python3.12/site-packages/av/audio/stream.pyi
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
from typing import Literal
|
||||
|
||||
from av.packet import Packet
|
||||
from av.stream import Stream
|
||||
|
||||
from .codeccontext import AudioCodecContext
|
||||
from .format import AudioFormat
|
||||
from .frame import AudioFrame
|
||||
from .layout import AudioLayout
|
||||
|
||||
class _Format:
|
||||
def __get__(self, i: object | None, owner: type | None = None) -> AudioFormat: ...
|
||||
def __set__(self, instance: object, value: AudioFormat | str) -> None: ...
|
||||
|
||||
class _Layout:
|
||||
def __get__(self, i: object | None, owner: type | None = None) -> AudioLayout: ...
|
||||
def __set__(self, instance: object, value: AudioLayout | str) -> None: ...
|
||||
|
||||
class AudioStream(Stream):
|
||||
codec_context: AudioCodecContext
|
||||
def encode(self, frame: AudioFrame | None = None) -> list[Packet]: ...
|
||||
def decode(self, packet: Packet | None = None) -> list[AudioFrame]: ...
|
||||
|
||||
# From codec context
|
||||
frame_size: int
|
||||
sample_rate: int
|
||||
bit_rate: int
|
||||
rate: int
|
||||
channels: int
|
||||
type: Literal["audio"]
|
||||
format: _Format
|
||||
layout: _Layout
|
||||
Loading…
Add table
Add a link
Reference in a new issue