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