1use std::ffi::CStr;
2use std::marker::PhantomData;
3use std::slice;
4use std::str::from_utf8_unchecked;
5
6use super::Frame;
7use ffi::AVFrameSideDataType::*;
8use ffi::*;
9use DictionaryRef;
10
11#[derive(Eq, PartialEq, Copy, Clone, Debug)]
12pub enum Type {
13 PanScan,
14 A53CC,
15 Stereo3D,
16 MatrixEncoding,
17 DownMixInfo,
18 ReplayGain,
19 DisplayMatrix,
20 AFD,
21 MotionVectors,
22 SkipSamples,
23 AudioServiceType,
24 MasteringDisplayMetadata,
25 GOPTimecode,
26 Spherical,
27
28 ContentLightLevel,
29 IccProfile,
30
31 #[cfg(all(feature = "ffmpeg_4_0", not(feature = "ffmpeg_5_0")))]
32 QPTableProperties,
33 #[cfg(all(feature = "ffmpeg_4_0", not(feature = "ffmpeg_5_0")))]
34 QPTableData,
35
36 #[cfg(feature = "ffmpeg_4_1")]
37 S12M_TIMECODE,
38
39 #[cfg(feature = "ffmpeg_4_2")]
40 DYNAMIC_HDR_PLUS,
41 #[cfg(feature = "ffmpeg_4_2")]
42 REGIONS_OF_INTEREST,
43
44 #[cfg(feature = "ffmpeg_4_3")]
45 VIDEO_ENC_PARAMS,
46
47 #[cfg(feature = "ffmpeg_4_4")]
48 SEI_UNREGISTERED,
49 #[cfg(feature = "ffmpeg_4_4")]
50 FILM_GRAIN_PARAMS,
51
52 #[cfg(feature = "ffmpeg_5_0")]
53 DETECTION_BBOXES,
54 #[cfg(feature = "ffmpeg_5_0")]
55 DOVI_RPU_BUFFER,
56 #[cfg(feature = "ffmpeg_5_0")]
57 DOVI_METADATA,
58
59 #[cfg(feature = "ffmpeg_5_1")]
60 DYNAMIC_HDR_VIVID,
61}
62
63impl Type {
64 #[inline]
65 pub fn name(&self) -> &'static str {
66 unsafe {
67 from_utf8_unchecked(CStr::from_ptr(av_frame_side_data_name((*self).into())).to_bytes())
68 }
69 }
70}
71
72impl From<AVFrameSideDataType> for Type {
73 #[inline(always)]
74 fn from(value: AVFrameSideDataType) -> Self {
75 match value {
76 AV_FRAME_DATA_PANSCAN => Type::PanScan,
77 AV_FRAME_DATA_A53_CC => Type::A53CC,
78 AV_FRAME_DATA_STEREO3D => Type::Stereo3D,
79 AV_FRAME_DATA_MATRIXENCODING => Type::MatrixEncoding,
80 AV_FRAME_DATA_DOWNMIX_INFO => Type::DownMixInfo,
81 AV_FRAME_DATA_REPLAYGAIN => Type::ReplayGain,
82 AV_FRAME_DATA_DISPLAYMATRIX => Type::DisplayMatrix,
83 AV_FRAME_DATA_AFD => Type::AFD,
84 AV_FRAME_DATA_MOTION_VECTORS => Type::MotionVectors,
85 AV_FRAME_DATA_SKIP_SAMPLES => Type::SkipSamples,
86 AV_FRAME_DATA_AUDIO_SERVICE_TYPE => Type::AudioServiceType,
87 AV_FRAME_DATA_MASTERING_DISPLAY_METADATA => Type::MasteringDisplayMetadata,
88 AV_FRAME_DATA_GOP_TIMECODE => Type::GOPTimecode,
89 AV_FRAME_DATA_SPHERICAL => Type::Spherical,
90
91 AV_FRAME_DATA_CONTENT_LIGHT_LEVEL => Type::ContentLightLevel,
92 AV_FRAME_DATA_ICC_PROFILE => Type::IccProfile,
93
94 #[cfg(all(feature = "ffmpeg_4_0", not(feature = "ffmpeg_5_0")))]
95 AV_FRAME_DATA_QP_TABLE_PROPERTIES => Type::QPTableProperties,
96 #[cfg(all(feature = "ffmpeg_4_0", not(feature = "ffmpeg_5_0")))]
97 AV_FRAME_DATA_QP_TABLE_DATA => Type::QPTableData,
98 #[cfg(feature = "ffmpeg_4_1")]
99 AV_FRAME_DATA_S12M_TIMECODE => Type::S12M_TIMECODE,
100
101 #[cfg(feature = "ffmpeg_4_2")]
102 AV_FRAME_DATA_DYNAMIC_HDR_PLUS => Type::DYNAMIC_HDR_PLUS,
103 #[cfg(feature = "ffmpeg_4_2")]
104 AV_FRAME_DATA_REGIONS_OF_INTEREST => Type::REGIONS_OF_INTEREST,
105
106 #[cfg(feature = "ffmpeg_4_3")]
107 AV_FRAME_DATA_VIDEO_ENC_PARAMS => Type::VIDEO_ENC_PARAMS,
108
109 #[cfg(feature = "ffmpeg_4_4")]
110 AV_FRAME_DATA_SEI_UNREGISTERED => Type::SEI_UNREGISTERED,
111 #[cfg(feature = "ffmpeg_4_4")]
112 AV_FRAME_DATA_FILM_GRAIN_PARAMS => Type::FILM_GRAIN_PARAMS,
113
114 #[cfg(feature = "ffmpeg_5_0")]
115 AV_FRAME_DATA_DETECTION_BBOXES => Type::DETECTION_BBOXES,
116 #[cfg(feature = "ffmpeg_5_0")]
117 AV_FRAME_DATA_DOVI_RPU_BUFFER => Type::DOVI_RPU_BUFFER,
118 #[cfg(feature = "ffmpeg_5_0")]
119 AV_FRAME_DATA_DOVI_METADATA => Type::DOVI_METADATA,
120
121 #[cfg(feature = "ffmpeg_5_1")]
122 AV_FRAME_DATA_DYNAMIC_HDR_VIVID => Type::DYNAMIC_HDR_VIVID,
123 }
124 }
125}
126
127impl From<Type> for AVFrameSideDataType {
128 #[inline(always)]
129 fn from(value: Type) -> AVFrameSideDataType {
130 match value {
131 Type::PanScan => AV_FRAME_DATA_PANSCAN,
132 Type::A53CC => AV_FRAME_DATA_A53_CC,
133 Type::Stereo3D => AV_FRAME_DATA_STEREO3D,
134 Type::MatrixEncoding => AV_FRAME_DATA_MATRIXENCODING,
135 Type::DownMixInfo => AV_FRAME_DATA_DOWNMIX_INFO,
136 Type::ReplayGain => AV_FRAME_DATA_REPLAYGAIN,
137 Type::DisplayMatrix => AV_FRAME_DATA_DISPLAYMATRIX,
138 Type::AFD => AV_FRAME_DATA_AFD,
139 Type::MotionVectors => AV_FRAME_DATA_MOTION_VECTORS,
140 Type::SkipSamples => AV_FRAME_DATA_SKIP_SAMPLES,
141 Type::AudioServiceType => AV_FRAME_DATA_AUDIO_SERVICE_TYPE,
142 Type::MasteringDisplayMetadata => AV_FRAME_DATA_MASTERING_DISPLAY_METADATA,
143 Type::GOPTimecode => AV_FRAME_DATA_GOP_TIMECODE,
144 Type::Spherical => AV_FRAME_DATA_SPHERICAL,
145
146 Type::ContentLightLevel => AV_FRAME_DATA_CONTENT_LIGHT_LEVEL,
147 Type::IccProfile => AV_FRAME_DATA_ICC_PROFILE,
148
149 #[cfg(all(feature = "ffmpeg_4_0", not(feature = "ffmpeg_5_0")))]
150 Type::QPTableProperties => AV_FRAME_DATA_QP_TABLE_PROPERTIES,
151 #[cfg(all(feature = "ffmpeg_4_0", not(feature = "ffmpeg_5_0")))]
152 Type::QPTableData => AV_FRAME_DATA_QP_TABLE_DATA,
153 #[cfg(feature = "ffmpeg_4_1")]
154 Type::S12M_TIMECODE => AV_FRAME_DATA_S12M_TIMECODE,
155
156 #[cfg(feature = "ffmpeg_4_2")]
157 Type::DYNAMIC_HDR_PLUS => AV_FRAME_DATA_DYNAMIC_HDR_PLUS,
158 #[cfg(feature = "ffmpeg_4_2")]
159 Type::REGIONS_OF_INTEREST => AV_FRAME_DATA_REGIONS_OF_INTEREST,
160
161 #[cfg(feature = "ffmpeg_4_3")]
162 Type::VIDEO_ENC_PARAMS => AV_FRAME_DATA_VIDEO_ENC_PARAMS,
163
164 #[cfg(feature = "ffmpeg_4_4")]
165 Type::SEI_UNREGISTERED => AV_FRAME_DATA_SEI_UNREGISTERED,
166 #[cfg(feature = "ffmpeg_4_4")]
167 Type::FILM_GRAIN_PARAMS => AV_FRAME_DATA_FILM_GRAIN_PARAMS,
168
169 #[cfg(feature = "ffmpeg_5_0")]
170 Type::DETECTION_BBOXES => AV_FRAME_DATA_DETECTION_BBOXES,
171 #[cfg(feature = "ffmpeg_5_0")]
172 Type::DOVI_RPU_BUFFER => AV_FRAME_DATA_DOVI_RPU_BUFFER,
173 #[cfg(feature = "ffmpeg_5_0")]
174 Type::DOVI_METADATA => AV_FRAME_DATA_DOVI_METADATA,
175
176 #[cfg(feature = "ffmpeg_5_1")]
177 Type::DYNAMIC_HDR_VIVID => AV_FRAME_DATA_DYNAMIC_HDR_VIVID,
178 }
179 }
180}
181
182pub struct SideData<'a> {
183 ptr: *mut AVFrameSideData,
184
185 _marker: PhantomData<&'a Frame>,
186}
187
188impl<'a> SideData<'a> {
189 #[inline(always)]
190 pub unsafe fn wrap(ptr: *mut AVFrameSideData) -> Self {
191 SideData {
192 ptr,
193 _marker: PhantomData,
194 }
195 }
196
197 #[inline(always)]
198 pub unsafe fn as_ptr(&self) -> *const AVFrameSideData {
199 self.ptr as *const _
200 }
201
202 #[inline(always)]
203 pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFrameSideData {
204 self.ptr
205 }
206}
207
208impl<'a> SideData<'a> {
209 #[inline]
210 pub fn kind(&self) -> Type {
211 unsafe { Type::from((*self.as_ptr()).type_) }
212 }
213
214 #[inline]
215 pub fn data(&self) -> &[u8] {
216 unsafe { slice::from_raw_parts((*self.as_ptr()).data, (*self.as_ptr()).size as usize) }
217 }
218
219 #[inline]
220 pub fn metadata(&self) -> DictionaryRef {
221 unsafe { DictionaryRef::wrap((*self.as_ptr()).metadata) }
222 }
223}