1use std::ffi::CStr;
2use std::marker::PhantomData;
3use std::slice;
4use std::str::from_utf8_unchecked;
5
6use super::Frame;
7use crate::DictionaryRef;
8use crate::ffi::AVFrameSideDataType::*;
9use crate::ffi::*;
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 #[cfg(feature = "ffmpeg_6_0")]
63 AMBIENT_VIEWING_ENVIRONMENT,
64
65 #[cfg(feature = "ffmpeg_6_1")]
66 VIDEO_HINT,
67
68 #[cfg(feature = "ffmpeg_7_1")]
69 LCEVC,
70 #[cfg(feature = "ffmpeg_7_1")]
71 VIEW_ID,
72
73 #[cfg(feature = "ffmpeg_8_0")]
74 THREE_D_REFERENCE_DISPLAYS,
75
76 #[cfg(feature = "ffmpeg_8_1")]
77 EXIF,
78
79 #[cfg(feature = "ffmpeg_9_0")]
80 DYNAMIC_HDR_SMPTE_2094_APP5,
81 #[cfg(feature = "ffmpeg_9_0")]
82 IAMF_MIX_GAIN_PARAM,
83 #[cfg(feature = "ffmpeg_9_0")]
84 IAMF_DEMIXING_INFO_PARAM,
85 #[cfg(feature = "ffmpeg_9_0")]
86 IAMF_RECON_GAIN_INFO_PARAM,
87 #[cfg(feature = "ffmpeg_9_0")]
88 RAW_COLOR_PARAMS,
89}
90
91impl Type {
92 #[inline]
93 pub fn name(&self) -> &'static str {
94 unsafe {
95 from_utf8_unchecked(CStr::from_ptr(av_frame_side_data_name((*self).into())).to_bytes())
96 }
97 }
98}
99
100impl From<AVFrameSideDataType> for Type {
101 #[inline(always)]
102 fn from(value: AVFrameSideDataType) -> Self {
103 match value {
104 AV_FRAME_DATA_PANSCAN => Type::PanScan,
105 AV_FRAME_DATA_A53_CC => Type::A53CC,
106 AV_FRAME_DATA_STEREO3D => Type::Stereo3D,
107 AV_FRAME_DATA_MATRIXENCODING => Type::MatrixEncoding,
108 AV_FRAME_DATA_DOWNMIX_INFO => Type::DownMixInfo,
109 AV_FRAME_DATA_REPLAYGAIN => Type::ReplayGain,
110 AV_FRAME_DATA_DISPLAYMATRIX => Type::DisplayMatrix,
111 AV_FRAME_DATA_AFD => Type::AFD,
112 AV_FRAME_DATA_MOTION_VECTORS => Type::MotionVectors,
113 AV_FRAME_DATA_SKIP_SAMPLES => Type::SkipSamples,
114 AV_FRAME_DATA_AUDIO_SERVICE_TYPE => Type::AudioServiceType,
115 AV_FRAME_DATA_MASTERING_DISPLAY_METADATA => Type::MasteringDisplayMetadata,
116 AV_FRAME_DATA_GOP_TIMECODE => Type::GOPTimecode,
117 AV_FRAME_DATA_SPHERICAL => Type::Spherical,
118
119 AV_FRAME_DATA_CONTENT_LIGHT_LEVEL => Type::ContentLightLevel,
120 AV_FRAME_DATA_ICC_PROFILE => Type::IccProfile,
121
122 #[cfg(all(feature = "ffmpeg_4_0", not(feature = "ffmpeg_5_0")))]
123 AV_FRAME_DATA_QP_TABLE_PROPERTIES => Type::QPTableProperties,
124 #[cfg(all(feature = "ffmpeg_4_0", not(feature = "ffmpeg_5_0")))]
125 AV_FRAME_DATA_QP_TABLE_DATA => Type::QPTableData,
126 #[cfg(feature = "ffmpeg_4_1")]
127 AV_FRAME_DATA_S12M_TIMECODE => Type::S12M_TIMECODE,
128
129 #[cfg(feature = "ffmpeg_4_2")]
130 AV_FRAME_DATA_DYNAMIC_HDR_PLUS => Type::DYNAMIC_HDR_PLUS,
131 #[cfg(feature = "ffmpeg_4_2")]
132 AV_FRAME_DATA_REGIONS_OF_INTEREST => Type::REGIONS_OF_INTEREST,
133
134 #[cfg(feature = "ffmpeg_4_3")]
135 AV_FRAME_DATA_VIDEO_ENC_PARAMS => Type::VIDEO_ENC_PARAMS,
136
137 #[cfg(feature = "ffmpeg_4_4")]
138 AV_FRAME_DATA_SEI_UNREGISTERED => Type::SEI_UNREGISTERED,
139 #[cfg(feature = "ffmpeg_4_4")]
140 AV_FRAME_DATA_FILM_GRAIN_PARAMS => Type::FILM_GRAIN_PARAMS,
141
142 #[cfg(feature = "ffmpeg_5_0")]
143 AV_FRAME_DATA_DETECTION_BBOXES => Type::DETECTION_BBOXES,
144 #[cfg(feature = "ffmpeg_5_0")]
145 AV_FRAME_DATA_DOVI_RPU_BUFFER => Type::DOVI_RPU_BUFFER,
146 #[cfg(feature = "ffmpeg_5_0")]
147 AV_FRAME_DATA_DOVI_METADATA => Type::DOVI_METADATA,
148
149 #[cfg(feature = "ffmpeg_5_1")]
150 AV_FRAME_DATA_DYNAMIC_HDR_VIVID => Type::DYNAMIC_HDR_VIVID,
151
152 #[cfg(feature = "ffmpeg_6_0")]
153 AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT => Type::AMBIENT_VIEWING_ENVIRONMENT,
154
155 #[cfg(feature = "ffmpeg_6_1")]
156 AV_FRAME_DATA_VIDEO_HINT => Type::VIDEO_HINT,
157
158 #[cfg(feature = "ffmpeg_7_1")]
159 AV_FRAME_DATA_LCEVC => Type::LCEVC,
160 #[cfg(feature = "ffmpeg_7_1")]
161 AV_FRAME_DATA_VIEW_ID => Type::VIEW_ID,
162
163 #[cfg(feature = "ffmpeg_8_0")]
164 AV_FRAME_DATA_3D_REFERENCE_DISPLAYS => Type::THREE_D_REFERENCE_DISPLAYS,
165
166 #[cfg(feature = "ffmpeg_8_1")]
167 AV_FRAME_DATA_EXIF => Type::EXIF,
168
169 #[cfg(feature = "ffmpeg_9_0")]
170 AV_FRAME_DATA_DYNAMIC_HDR_SMPTE_2094_APP5 => Type::DYNAMIC_HDR_SMPTE_2094_APP5,
171 #[cfg(feature = "ffmpeg_9_0")]
172 AV_FRAME_DATA_IAMF_MIX_GAIN_PARAM => Type::IAMF_MIX_GAIN_PARAM,
173 #[cfg(feature = "ffmpeg_9_0")]
174 AV_FRAME_DATA_IAMF_DEMIXING_INFO_PARAM => Type::IAMF_DEMIXING_INFO_PARAM,
175 #[cfg(feature = "ffmpeg_9_0")]
176 AV_FRAME_DATA_IAMF_RECON_GAIN_INFO_PARAM => Type::IAMF_RECON_GAIN_INFO_PARAM,
177 #[cfg(feature = "ffmpeg_9_0")]
178 AV_FRAME_DATA_RAW_COLOR_PARAMS => Type::RAW_COLOR_PARAMS,
179
180 #[cfg(feature = "non-exhaustive-enums")]
181 _ => unimplemented!(),
182 }
183 }
184}
185
186impl From<Type> for AVFrameSideDataType {
187 #[inline(always)]
188 fn from(value: Type) -> AVFrameSideDataType {
189 match value {
190 Type::PanScan => AV_FRAME_DATA_PANSCAN,
191 Type::A53CC => AV_FRAME_DATA_A53_CC,
192 Type::Stereo3D => AV_FRAME_DATA_STEREO3D,
193 Type::MatrixEncoding => AV_FRAME_DATA_MATRIXENCODING,
194 Type::DownMixInfo => AV_FRAME_DATA_DOWNMIX_INFO,
195 Type::ReplayGain => AV_FRAME_DATA_REPLAYGAIN,
196 Type::DisplayMatrix => AV_FRAME_DATA_DISPLAYMATRIX,
197 Type::AFD => AV_FRAME_DATA_AFD,
198 Type::MotionVectors => AV_FRAME_DATA_MOTION_VECTORS,
199 Type::SkipSamples => AV_FRAME_DATA_SKIP_SAMPLES,
200 Type::AudioServiceType => AV_FRAME_DATA_AUDIO_SERVICE_TYPE,
201 Type::MasteringDisplayMetadata => AV_FRAME_DATA_MASTERING_DISPLAY_METADATA,
202 Type::GOPTimecode => AV_FRAME_DATA_GOP_TIMECODE,
203 Type::Spherical => AV_FRAME_DATA_SPHERICAL,
204
205 Type::ContentLightLevel => AV_FRAME_DATA_CONTENT_LIGHT_LEVEL,
206 Type::IccProfile => AV_FRAME_DATA_ICC_PROFILE,
207
208 #[cfg(all(feature = "ffmpeg_4_0", not(feature = "ffmpeg_5_0")))]
209 Type::QPTableProperties => AV_FRAME_DATA_QP_TABLE_PROPERTIES,
210 #[cfg(all(feature = "ffmpeg_4_0", not(feature = "ffmpeg_5_0")))]
211 Type::QPTableData => AV_FRAME_DATA_QP_TABLE_DATA,
212 #[cfg(feature = "ffmpeg_4_1")]
213 Type::S12M_TIMECODE => AV_FRAME_DATA_S12M_TIMECODE,
214
215 #[cfg(feature = "ffmpeg_4_2")]
216 Type::DYNAMIC_HDR_PLUS => AV_FRAME_DATA_DYNAMIC_HDR_PLUS,
217 #[cfg(feature = "ffmpeg_4_2")]
218 Type::REGIONS_OF_INTEREST => AV_FRAME_DATA_REGIONS_OF_INTEREST,
219
220 #[cfg(feature = "ffmpeg_4_3")]
221 Type::VIDEO_ENC_PARAMS => AV_FRAME_DATA_VIDEO_ENC_PARAMS,
222
223 #[cfg(feature = "ffmpeg_4_4")]
224 Type::SEI_UNREGISTERED => AV_FRAME_DATA_SEI_UNREGISTERED,
225 #[cfg(feature = "ffmpeg_4_4")]
226 Type::FILM_GRAIN_PARAMS => AV_FRAME_DATA_FILM_GRAIN_PARAMS,
227
228 #[cfg(feature = "ffmpeg_5_0")]
229 Type::DETECTION_BBOXES => AV_FRAME_DATA_DETECTION_BBOXES,
230 #[cfg(feature = "ffmpeg_5_0")]
231 Type::DOVI_RPU_BUFFER => AV_FRAME_DATA_DOVI_RPU_BUFFER,
232 #[cfg(feature = "ffmpeg_5_0")]
233 Type::DOVI_METADATA => AV_FRAME_DATA_DOVI_METADATA,
234
235 #[cfg(feature = "ffmpeg_5_1")]
236 Type::DYNAMIC_HDR_VIVID => AV_FRAME_DATA_DYNAMIC_HDR_VIVID,
237
238 #[cfg(feature = "ffmpeg_6_0")]
239 Type::AMBIENT_VIEWING_ENVIRONMENT => AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT,
240
241 #[cfg(feature = "ffmpeg_6_1")]
242 Type::VIDEO_HINT => AV_FRAME_DATA_VIDEO_HINT,
243
244 #[cfg(feature = "ffmpeg_7_1")]
245 Type::LCEVC => AV_FRAME_DATA_LCEVC,
246 #[cfg(feature = "ffmpeg_7_1")]
247 Type::VIEW_ID => AV_FRAME_DATA_VIEW_ID,
248
249 #[cfg(feature = "ffmpeg_8_0")]
250 Type::THREE_D_REFERENCE_DISPLAYS => AV_FRAME_DATA_3D_REFERENCE_DISPLAYS,
251
252 #[cfg(feature = "ffmpeg_8_1")]
253 Type::EXIF => AV_FRAME_DATA_EXIF,
254
255 #[cfg(feature = "ffmpeg_9_0")]
256 Type::DYNAMIC_HDR_SMPTE_2094_APP5 => AV_FRAME_DATA_DYNAMIC_HDR_SMPTE_2094_APP5,
257 #[cfg(feature = "ffmpeg_9_0")]
258 Type::IAMF_MIX_GAIN_PARAM => AV_FRAME_DATA_IAMF_MIX_GAIN_PARAM,
259 #[cfg(feature = "ffmpeg_9_0")]
260 Type::IAMF_DEMIXING_INFO_PARAM => AV_FRAME_DATA_IAMF_DEMIXING_INFO_PARAM,
261 #[cfg(feature = "ffmpeg_9_0")]
262 Type::IAMF_RECON_GAIN_INFO_PARAM => AV_FRAME_DATA_IAMF_RECON_GAIN_INFO_PARAM,
263 #[cfg(feature = "ffmpeg_9_0")]
264 Type::RAW_COLOR_PARAMS => AV_FRAME_DATA_RAW_COLOR_PARAMS,
265 }
266 }
267}
268
269pub struct SideData<'a> {
270 ptr: *mut AVFrameSideData,
271
272 _marker: PhantomData<&'a Frame>,
273}
274
275impl<'a> SideData<'a> {
276 #[inline(always)]
277 pub unsafe fn wrap(ptr: *mut AVFrameSideData) -> Self {
278 SideData {
279 ptr,
280 _marker: PhantomData,
281 }
282 }
283
284 #[inline(always)]
285 pub unsafe fn as_ptr(&self) -> *const AVFrameSideData {
286 self.ptr as *const _
287 }
288
289 #[inline(always)]
290 pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFrameSideData {
291 self.ptr
292 }
293}
294
295impl<'a> SideData<'a> {
296 #[inline]
297 pub fn kind(&self) -> Type {
298 unsafe { Type::from((*self.as_ptr()).type_) }
299 }
300
301 #[inline]
302 pub fn data(&self) -> &[u8] {
303 #[allow(clippy::unnecessary_cast)]
304 unsafe {
305 slice::from_raw_parts((*self.as_ptr()).data, (*self.as_ptr()).size as usize)
306 }
307 }
308
309 #[inline]
310 pub fn metadata(&self) -> DictionaryRef<'_> {
311 unsafe { DictionaryRef::wrap((*self.as_ptr()).metadata) }
312 }
313}