Voice et bot modif

This commit is contained in:
pi 2026-06-16 17:09:34 +00:00
parent 189d56026b
commit 7333a22bcd
10774 changed files with 634644 additions and 933308 deletions

View file

@ -1,19 +1,21 @@
cimport libav as lib
from libc.stdint cimport int32_t, uint8_t
from enum import IntEnum
VideoEncParamsType = IntEnum(
"AVVideoEncParamsType",
{
"NONE": <int>lib.AV_VIDEO_ENC_PARAMS_NONE,
"VP9": <int>lib.AV_VIDEO_ENC_PARAMS_VP9,
"H264": <int>lib.AV_VIDEO_ENC_PARAMS_H264,
"MPEG2": <int>lib.AV_VIDEO_ENC_PARAMS_MPEG2,
},
)
import cython
from cython.cimports import libav as lib
from cython.cimports.av.sidedata.sidedata import SideData
from cython.cimports.libc.stdint import uint8_t
cdef class VideoEncParams(SideData):
class VideoEncParamsType(IntEnum):
NONE = lib.AV_VIDEO_ENC_PARAMS_NONE
VP9 = lib.AV_VIDEO_ENC_PARAMS_VP9
H264 = lib.AV_VIDEO_ENC_PARAMS_H264
MPEG2 = lib.AV_VIDEO_ENC_PARAMS_MPEG2
@cython.final
@cython.cclass
class VideoEncParams(SideData):
def __repr__(self):
return f"<av.sidedata.VideoEncParams, nb_blocks={self.nb_blocks}, codec_type={self.codec_type}, qp={self.qp}>"
@ -25,29 +27,37 @@ cdef class VideoEncParams(SideData):
the values of blocks_offset / block_size are unspecified and should not
be accessed.
"""
return (<lib.AVVideoEncParams*> self.ptr.data).nb_blocks
return cython.cast(
cython.pointer[lib.AVVideoEncParams], self.ptr.data
).nb_blocks
@property
def blocks_offset(self):
"""
Offset in bytes from the beginning of this structure at which the array of blocks starts.
"""
return (<lib.AVVideoEncParams*> self.ptr.data).blocks_offset
return cython.cast(
cython.pointer[lib.AVVideoEncParams], self.ptr.data
).blocks_offset
@property
def block_size(self):
"""
Size of each block in bytes. May not match sizeof(AVVideoBlockParams).
"""
return (<lib.AVVideoEncParams*> self.ptr.data).block_size
return cython.cast(
cython.pointer[lib.AVVideoEncParams], self.ptr.data
).block_size
@property
def codec_type(self):
"""
Type of the parameters (the codec they are used with).
"""
cdef lib.AVVideoEncParamsType t = (<lib.AVVideoEncParams*> self.ptr.data).type
return VideoEncParamsType(<int>t)
t: lib.AVVideoEncParamsType = cython.cast(
cython.pointer[lib.AVVideoEncParams], self.ptr.data
).type
return VideoEncParamsType(cython.cast(cython.int, t))
@property
def qp(self):
@ -57,15 +67,17 @@ cdef class VideoEncParams(SideData):
combined with `delta_qp` and the per-block delta in a manner
documented for each type.
"""
return (<lib.AVVideoEncParams*> self.ptr.data).qp
return cython.cast(cython.pointer[lib.AVVideoEncParams], self.ptr.data).qp
@property
def delta_qp(self):
"""
Quantisation parameter offset from the base (per-frame) qp for a given
plane (first index) and AC/DC coefficients (second index).
"""
cdef lib.AVVideoEncParams *p = <lib.AVVideoEncParams*> self.ptr.data
p: cython.pointer[lib.AVVideoEncParams] = cython.cast(
cython.pointer[lib.AVVideoEncParams], self.ptr.data
)
return [[p.delta_qp[i][j] for j in range(2)] for i in range(4)]
def block_params(self, idx):
@ -85,25 +97,28 @@ cdef class VideoEncParams(SideData):
"""
import numpy as np
cdef int mb_h = (self.frame.ptr.height + 15) // 16
cdef int mb_w = (self.frame.ptr.width + 15) // 16
cdef int nb_mb = mb_h * mb_w
cdef int block_idx
cdef int y
cdef int x
cdef VideoBlockParams block
mb_h: cython.int = (self.frame.ptr.height + 15) // 16
mb_w: cython.int = (self.frame.ptr.width + 15) // 16
nb_mb: cython.int = mb_h * mb_w
block_idx, x, y = cython.declare(cython.int)
block: VideoBlockParams
# Validate number of blocks
if self.nb_blocks != nb_mb:
raise RuntimeError("Expected frame size to match number of blocks in side data")
# Validate type
cdef lib.AVVideoEncParamsType type = (<lib.AVVideoEncParams*> self.ptr.data).type
if type != lib.AVVideoEncParamsType.AV_VIDEO_ENC_PARAMS_MPEG2 and type != lib.AVVideoEncParamsType.AV_VIDEO_ENC_PARAMS_H264:
raise RuntimeError(
"Expected frame size to match number of blocks in side data"
)
type: lib.AVVideoEncParamsType = cython.cast(
cython.pointer[lib.AVVideoEncParams], self.ptr.data
).type
if (
type != lib.AVVideoEncParamsType.AV_VIDEO_ENC_PARAMS_MPEG2
and type != lib.AVVideoEncParamsType.AV_VIDEO_ENC_PARAMS_H264
):
raise ValueError("Expected MPEG2 or H264")
# Create a 2-D map with the number of macroblocks
cdef int32_t[:, ::1] map = np.empty((mb_h, mb_w), dtype=np.int32)
map = np.empty((mb_h, mb_w), dtype=np.int32)
# Fill map with quantization parameter per macroblock
for block_idx in range(nb_mb):
@ -112,14 +127,20 @@ cdef class VideoEncParams(SideData):
x = block.src_x // 16
map[y, x] = self.qp + block.delta_qp
return np.asarray(map)
return map
cdef class VideoBlockParams:
def __init__(self, VideoEncParams video_enc_params, int idx) -> None:
cdef uint8_t* base = <uint8_t*> video_enc_params.ptr.data
cdef Py_ssize_t offset = video_enc_params.blocks_offset + idx * video_enc_params.block_size
self.ptr = <lib.AVVideoBlockParams*> (base + offset)
@cython.final
@cython.cclass
class VideoBlockParams:
def __init__(self, video_enc_params: VideoEncParams, idx: cython.int) -> None:
base: cython.pointer[uint8_t] = cython.cast(
cython.pointer[uint8_t], video_enc_params.ptr.data
)
offset: cython.Py_ssize_t = (
video_enc_params.blocks_offset + idx * video_enc_params.block_size
)
self.ptr = cython.cast(cython.pointer[lib.AVVideoBlockParams], base + offset)
def __repr__(self):
return f"<av.sidedata.VideoBlockParams, src=({self.src_x}, {self.src_y}), size={self.w}x{self.h}, delta_qp={self.delta_qp}>"

View file

@ -4,13 +4,11 @@ from av.frame cimport Frame
from av.sidedata.sidedata cimport SideData
cdef class _MotionVectors(SideData):
cdef class MotionVectors(SideData):
cdef dict _vectors
cdef int _len
cdef Py_ssize_t _len
cdef class MotionVector:
cdef _MotionVectors parent
cdef MotionVectors parent
cdef lib.AVMotionVector *ptr

View file

@ -0,0 +1,136 @@
import cython
from cython.cimports import libav as lib
from cython.cimports.av.sidedata.sidedata import SideData
from cython.cimports.libc.stdint import uintptr_t
_cinit_bypass_sentinel = cython.declare(object, object())
@cython.final
@cython.cclass
class MotionVectors(SideData):
def __init__(self, sentinel, frame: Frame, index: cython.int):
SideData.__init__(self, sentinel, frame, index)
self._vectors = {}
self._len = self.ptr.size // cython.sizeof(lib.AVMotionVector)
def __repr__(self):
return (
f"<av.sidedata.MotionVectors {self.ptr.size} bytes "
f"of {len(self)} vectors at 0x{cython.cast(uintptr_t, self.ptr.data):0x}>"
)
def __len__(self):
return self._len
def __getitem__(self, index: cython.Py_ssize_t):
try:
return self._vectors[index]
except KeyError:
pass
if index >= self._len:
raise IndexError(index)
vector = self._vectors[index] = MotionVector(
_cinit_bypass_sentinel, self, index
)
return vector
def __iter__(self):
"""Iterate over all motion vectors."""
for i in range(self._len):
yield self[i]
def to_ndarray(self):
"""
Convert motion vectors to a NumPy structured array.
Returns a NumPy array with fields corresponding to the AVMotionVector structure.
"""
import numpy as np
return np.frombuffer(
self,
dtype=np.dtype(
[
("source", "int32"),
("w", "uint8"),
("h", "uint8"),
("src_x", "int16"),
("src_y", "int16"),
("dst_x", "int16"),
("dst_y", "int16"),
("flags", "uint64"),
("motion_x", "int32"),
("motion_y", "int32"),
("motion_scale", "uint16"),
],
align=True,
),
)
@cython.final
@cython.cclass
class MotionVector:
"""
Represents a single motion vector from video frame data.
Motion vectors describe the motion of a block of pixels between frames.
"""
def __init__(self, sentinel, parent: MotionVectors, index: cython.int):
if sentinel is not _cinit_bypass_sentinel:
raise RuntimeError("cannot manually instantiate MotionVector")
self.parent = parent
base: cython.pointer[lib.AVMotionVector] = cython.cast(
cython.pointer[lib.AVMotionVector], parent.ptr.data
)
self.ptr = base + index
def __repr__(self):
return (
f"<av.sidedata.MotionVector {self.w}x{self.h} "
f"from ({self.src_x},{self.src_y}) to ({self.dst_x},{self.dst_y})>"
)
@property
def source(self):
return self.ptr.source
@property
def w(self):
return self.ptr.w
@property
def h(self):
return self.ptr.h
@property
def src_x(self):
return self.ptr.src_x
@property
def src_y(self):
return self.ptr.src_y
@property
def dst_x(self):
return self.ptr.dst_x
@property
def dst_y(self):
return self.ptr.dst_y
@property
def motion_x(self):
return self.ptr.motion_x
@property
def motion_y(self):
return self.ptr.motion_y
@property
def motion_scale(self):
return self.ptr.motion_scale

View file

@ -1,16 +1,14 @@
from typing import Any, Sequence, overload
from typing import Any, overload
import numpy as np
from .sidedata import SideData
class MotionVectors(SideData, Sequence[MotionVector]):
class MotionVectors(SideData):
@overload
def __getitem__(self, index: int): ...
def __getitem__(self, index: int) -> MotionVector: ...
@overload
def __getitem__(self, index: slice): ...
@overload
def __getitem__(self, index: int | slice): ...
def __getitem__(self, index: slice) -> list[MotionVector]: ...
def __len__(self) -> int: ...
def to_ndarray(self) -> np.ndarray[Any, Any]: ...

View file

@ -1,104 +0,0 @@
from collections.abc import Sequence
cdef object _cinit_bypass_sentinel = object()
# Cython doesn't let us inherit from the abstract Sequence, so we will subclass
# it later.
cdef class _MotionVectors(SideData):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._vectors = {}
self._len = self.ptr.size // sizeof(lib.AVMotionVector)
def __repr__(self):
return f"<av.sidedata.MotionVectors {self.ptr.size} bytes of {len(self)} vectors at 0x{<unsigned int>self.ptr.data:0x}"
def __getitem__(self, int index):
try:
return self._vectors[index]
except KeyError:
pass
if index >= self._len:
raise IndexError(index)
vector = self._vectors[index] = MotionVector(_cinit_bypass_sentinel, self, index)
return vector
def __len__(self):
return self._len
def to_ndarray(self):
import numpy as np
return np.frombuffer(self, dtype=np.dtype([
("source", "int32"),
("w", "uint8"),
("h", "uint8"),
("src_x", "int16"),
("src_y", "int16"),
("dst_x", "int16"),
("dst_y", "int16"),
("flags", "uint64"),
("motion_x", "int32"),
("motion_y", "int32"),
("motion_scale", "uint16"),
], align=True))
class MotionVectors(_MotionVectors, Sequence):
pass
cdef class MotionVector:
def __init__(self, sentinel, _MotionVectors parent, int index):
if sentinel is not _cinit_bypass_sentinel:
raise RuntimeError("cannot manually instantiate MotionVector")
self.parent = parent
cdef lib.AVMotionVector *base = <lib.AVMotionVector*>parent.ptr.data
self.ptr = base + index
def __repr__(self):
return f"<av.sidedata.MotionVector {self.w}x{self.h} from {self.src_x},{self.src_y} to {self.dst_x},{self.dst_y}>"
@property
def source(self):
return self.ptr.source
@property
def w(self):
return self.ptr.w
@property
def h(self):
return self.ptr.h
@property
def src_x(self):
return self.ptr.src_x
@property
def src_y(self):
return self.ptr.src_y
@property
def dst_x(self):
return self.ptr.dst_x
@property
def dst_y(self):
return self.ptr.dst_y
@property
def motion_x(self):
return self.ptr.motion_x
@property
def motion_y(self):
return self.ptr.motion_y
@property
def motion_scale(self):
return self.ptr.motion_scale

View file

@ -1,23 +1,19 @@
cimport libav as lib
from av.buffer cimport Buffer
from av.dictionary cimport _Dictionary, wrap_dictionary
from av.dictionary cimport Dictionary, wrap_dictionary
from av.frame cimport Frame
cdef class SideData(Buffer):
cdef Frame frame
cdef lib.AVFrameSideData *ptr
cdef _Dictionary metadata
cdef Dictionary metadata
cdef SideData wrap_side_data(Frame frame, int index)
cdef int get_display_rotation(Frame frame)
cdef class _SideDataContainer:
cdef Frame frame
cdef list _by_index
cdef dict _by_type

View file

@ -1,13 +1,13 @@
from libc.stdint cimport int32_t
from collections.abc import Mapping
from enum import Enum
import cython
from cython.cimports.libc.stdint import int32_t, uintptr_t
from av.sidedata.encparams import VideoEncParams
from av.sidedata.motionvectors import MotionVectors
cdef object _cinit_bypass_sentinel = object()
_cinit_bypass_sentinel = cython.declare(object, object())
class Type(Enum):
@ -17,6 +17,7 @@ class Type(Enum):
From: https://github.com/FFmpeg/FFmpeg/blob/master/libavutil/frame.h
"""
PANSCAN = lib.AV_FRAME_DATA_PANSCAN
A53_CC = lib.AV_FRAME_DATA_A53_CC
STEREO3D = lib.AV_FRAME_DATA_STEREO3D
@ -47,7 +48,8 @@ class Type(Enum):
VIDEO_HINT = lib.AV_FRAME_DATA_VIDEO_HINT
cdef SideData wrap_side_data(Frame frame, int index):
@cython.cfunc
def wrap_side_data(frame: Frame, index: cython.int) -> SideData:
if frame.ptr.side_data[index].type == lib.AV_FRAME_DATA_MOTION_VECTORS:
return MotionVectors(_cinit_bypass_sentinel, frame, index)
elif frame.ptr.side_data[index].type == lib.AV_FRAME_DATA_VIDEO_ENC_PARAMS:
@ -56,46 +58,60 @@ cdef SideData wrap_side_data(Frame frame, int index):
return SideData(_cinit_bypass_sentinel, frame, index)
cdef int get_display_rotation(Frame frame):
@cython.cfunc
def get_display_rotation(frame: Frame) -> cython.int:
for i in range(frame.ptr.nb_side_data):
if frame.ptr.side_data[i].type == lib.AV_FRAME_DATA_DISPLAYMATRIX:
return int(lib.av_display_rotation_get(<const int32_t *>frame.ptr.side_data[i].data))
return int(
lib.av_display_rotation_get(
cython.cast(
cython.pointer[cython.const[int32_t]],
frame.ptr.side_data[i].data,
)
)
)
return 0
cdef class SideData(Buffer):
def __init__(self, sentinel, Frame frame, int index):
@cython.cclass
class SideData(Buffer):
def __init__(self, sentinel, frame: Frame, index: cython.int):
if sentinel is not _cinit_bypass_sentinel:
raise RuntimeError("cannot manually instantiate SideData")
raise RuntimeError("cannot manually instatiate SideData")
self.frame = frame
self.ptr = frame.ptr.side_data[index]
self.metadata = wrap_dictionary(self.ptr.metadata)
cdef size_t _buffer_size(self):
@cython.cfunc
def _buffer_size(self) -> cython.size_t:
return self.ptr.size
cdef void* _buffer_ptr(self):
@cython.cfunc
def _buffer_ptr(self) -> cython.p_void:
return self.ptr.data
cdef bint _buffer_writable(self):
@cython.cfunc
def _buffer_writable(self) -> cython.bint:
return False
def __repr__(self):
return f"<av.sidedata.{self.__class__.__name__} {self.ptr.size} bytes of {self.type} at 0x{<unsigned int>self.ptr.data:0x}>"
return f"<av.sidedata.{self.__class__.__name__} {self.ptr.size} bytes of {self.type} at 0x{cython.cast(uintptr_t, self.ptr.data):0x}>"
@property
def type(self):
return Type(self.ptr.type)
cdef class _SideDataContainer:
def __init__(self, Frame frame):
@cython.cclass
class _SideDataContainer:
def __init__(self, frame: Frame):
self.frame = frame
self._by_index = []
self._by_type = {}
self._by_index: list = []
self._by_type: dict = {}
i: cython.Py_ssize_t
data: SideData
cdef int i
cdef SideData data
for i in range(self.frame.ptr.nb_side_data):
data = wrap_side_data(frame, i)
self._by_index.append(data)