-
Notifications
You must be signed in to change notification settings - Fork 434
Expand file tree
/
Copy pathsidedata.py
More file actions
135 lines (108 loc) · 4.55 KB
/
sidedata.py
File metadata and controls
135 lines (108 loc) · 4.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
from collections.abc import Mapping
from enum import Enum
import cython
from cython.cimports.libc.stdint import int32_t
from av.sidedata.encparams import VideoEncParams
from av.sidedata.motionvectors import MotionVectors
_cinit_bypass_sentinel = cython.declare(object, object())
class Type(Enum):
"""
Enum class representing different types of frame data in audio/video processing.
Values are mapped to corresponding AV_FRAME_DATA constants from FFmpeg.
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
MATRIXENCODING = lib.AV_FRAME_DATA_MATRIXENCODING
DOWNMIX_INFO = lib.AV_FRAME_DATA_DOWNMIX_INFO
REPLAYGAIN = lib.AV_FRAME_DATA_REPLAYGAIN
DISPLAYMATRIX = lib.AV_FRAME_DATA_DISPLAYMATRIX
AFD = lib.AV_FRAME_DATA_AFD
MOTION_VECTORS = lib.AV_FRAME_DATA_MOTION_VECTORS
SKIP_SAMPLES = lib.AV_FRAME_DATA_SKIP_SAMPLES
AUDIO_SERVICE_TYPE = lib.AV_FRAME_DATA_AUDIO_SERVICE_TYPE
MASTERING_DISPLAY_METADATA = lib.AV_FRAME_DATA_MASTERING_DISPLAY_METADATA
GOP_TIMECODE = lib.AV_FRAME_DATA_GOP_TIMECODE
SPHERICAL = lib.AV_FRAME_DATA_SPHERICAL
CONTENT_LIGHT_LEVEL = lib.AV_FRAME_DATA_CONTENT_LIGHT_LEVEL
ICC_PROFILE = lib.AV_FRAME_DATA_ICC_PROFILE
S12M_TIMECODE = lib.AV_FRAME_DATA_S12M_TIMECODE
DYNAMIC_HDR_PLUS = lib.AV_FRAME_DATA_DYNAMIC_HDR_PLUS
REGIONS_OF_INTEREST = lib.AV_FRAME_DATA_REGIONS_OF_INTEREST
VIDEO_ENC_PARAMS = lib.AV_FRAME_DATA_VIDEO_ENC_PARAMS
SEI_UNREGISTERED = lib.AV_FRAME_DATA_SEI_UNREGISTERED
FILM_GRAIN_PARAMS = lib.AV_FRAME_DATA_FILM_GRAIN_PARAMS
DETECTION_BBOXES = lib.AV_FRAME_DATA_DETECTION_BBOXES
DOVI_RPU_BUFFER = lib.AV_FRAME_DATA_DOVI_RPU_BUFFER
DOVI_METADATA = lib.AV_FRAME_DATA_DOVI_METADATA
DYNAMIC_HDR_VIVID = lib.AV_FRAME_DATA_DYNAMIC_HDR_VIVID
AMBIENT_VIEWING_ENVIRONMENT = lib.AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT
VIDEO_HINT = lib.AV_FRAME_DATA_VIDEO_HINT
@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:
return VideoEncParams(_cinit_bypass_sentinel, frame, index)
else:
return SideData(_cinit_bypass_sentinel, frame, index)
@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(
cython.cast(
cython.pointer[cython.const[int32_t]],
frame.ptr.side_data[i].data,
)
)
)
return 0
@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 instatiate SideData")
self.frame = frame
self.ptr = frame.ptr.side_data[index]
self.metadata = wrap_dictionary(self.ptr.metadata)
@cython.cfunc
def _buffer_size(self) -> cython.size_t:
return self.ptr.size
@cython.cfunc
def _buffer_ptr(self) -> cython.p_void:
return self.ptr.data
@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{cython.cast(cython.uint, self.ptr.data):0x}>"
@property
def type(self):
return Type(self.ptr.type)
@cython.cclass
class _SideDataContainer:
def __init__(self, frame: Frame):
self.frame = frame
self._by_index: list = []
self._by_type: dict = {}
i: cython.Py_ssize_t
data: SideData
for i in range(self.frame.ptr.nb_side_data):
data = wrap_side_data(frame, i)
self._by_index.append(data)
self._by_type[data.type] = data
def __len__(self):
return len(self._by_index)
def __iter__(self):
return iter(self._by_index)
def __getitem__(self, key):
if isinstance(key, int):
return self._by_index[key]
if isinstance(key, str):
return self._by_type[Type[key]]
return self._by_type[key]
class SideDataContainer(_SideDataContainer, Mapping):
pass