ffmpeg_the_third/util/frame/
side_data.rs1use std::marker::PhantomData;
2use std::slice;
3
4use super::Frame;
5use crate::ffi::*;
6use crate::utils;
7use crate::DictionaryRef;
8#[cfg(feature = "serialize")]
9use serde::{Deserialize, Serialize};
10
11#[derive(Eq, PartialEq, Copy, Clone, Debug)]
12#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
13pub enum Type {
14 PanScan,
15 A53CC,
16 Stereo3D,
17 MatrixEncoding,
18 DownMixInfo,
19 ReplayGain,
20 DisplayMatrix,
21 AFD,
22 MotionVectors,
23 SkipSamples,
24 AudioServiceType,
25 MasteringDisplayMetadata,
26 GOPTimecode,
27 Spherical,
28
29 ContentLightLevel,
30 IccProfile,
31
32 S12M_TIMECODE,
33
34 DYNAMIC_HDR_PLUS,
35 REGIONS_OF_INTEREST,
36
37 VIDEO_ENC_PARAMS,
38
39 SEI_UNREGISTERED,
40 FILM_GRAIN_PARAMS,
41
42 DETECTION_BBOXES,
43 DOVI_RPU_BUFFER,
44 DOVI_METADATA,
45
46 DYNAMIC_HDR_VIVID,
47
48 #[cfg(feature = "ffmpeg_6_0")]
49 AMBIENT_VIEWING_ENVIRONMENT,
50
51 #[cfg(feature = "ffmpeg_6_1")]
52 VIDEO_HINT,
53
54 #[cfg(feature = "ffmpeg_7_1")]
55 LCEVC,
56 #[cfg(feature = "ffmpeg_7_1")]
57 ViewId,
58
59 #[cfg(feature = "ffmpeg_8_0")]
60 _3DReferenceDisplays,
61
62 #[cfg(feature = "ffmpeg_8_1")]
63 EXIF,
64
65 #[cfg(feature = "ffmpeg_9_0")]
66 DYNAMIC_HDR_SMPTE_2094_APP5,
67 #[cfg(feature = "ffmpeg_9_0")]
68 IAMF_MIX_GAIN_PARAM,
69 #[cfg(feature = "ffmpeg_9_0")]
70 IAMF_DEMIXING_INFO_PARAM,
71 #[cfg(feature = "ffmpeg_9_0")]
72 IAMF_RECON_GAIN_INFO_PARAM,
73 #[cfg(feature = "ffmpeg_9_0")]
74 RAW_COLOR_PARAMS,
75}
76
77impl Type {
78 #[inline]
79 pub fn name(&self) -> &'static str {
80 unsafe { utils::str_from_c_ptr(av_frame_side_data_name((*self).into())) }
81 }
82}
83
84impl From<AVFrameSideDataType> for Type {
85 #[inline(always)]
86 fn from(value: AVFrameSideDataType) -> Self {
87 use AVFrameSideDataType as AV;
88
89 match value {
90 AV::PANSCAN => Type::PanScan,
91 AV::A53_CC => Type::A53CC,
92 AV::STEREO3D => Type::Stereo3D,
93 AV::MATRIXENCODING => Type::MatrixEncoding,
94 AV::DOWNMIX_INFO => Type::DownMixInfo,
95 AV::REPLAYGAIN => Type::ReplayGain,
96 AV::DISPLAYMATRIX => Type::DisplayMatrix,
97 AV::AFD => Type::AFD,
98 AV::MOTION_VECTORS => Type::MotionVectors,
99 AV::SKIP_SAMPLES => Type::SkipSamples,
100 AV::AUDIO_SERVICE_TYPE => Type::AudioServiceType,
101 AV::MASTERING_DISPLAY_METADATA => Type::MasteringDisplayMetadata,
102 AV::GOP_TIMECODE => Type::GOPTimecode,
103 AV::SPHERICAL => Type::Spherical,
104
105 AV::CONTENT_LIGHT_LEVEL => Type::ContentLightLevel,
106 AV::ICC_PROFILE => Type::IccProfile,
107
108 AV::S12M_TIMECODE => Type::S12M_TIMECODE,
109
110 AV::DYNAMIC_HDR_PLUS => Type::DYNAMIC_HDR_PLUS,
111 AV::REGIONS_OF_INTEREST => Type::REGIONS_OF_INTEREST,
112
113 AV::VIDEO_ENC_PARAMS => Type::VIDEO_ENC_PARAMS,
114
115 AV::SEI_UNREGISTERED => Type::SEI_UNREGISTERED,
116 AV::FILM_GRAIN_PARAMS => Type::FILM_GRAIN_PARAMS,
117
118 AV::DETECTION_BBOXES => Type::DETECTION_BBOXES,
119 AV::DOVI_RPU_BUFFER => Type::DOVI_RPU_BUFFER,
120 AV::DOVI_METADATA => Type::DOVI_METADATA,
121
122 AV::DYNAMIC_HDR_VIVID => Type::DYNAMIC_HDR_VIVID,
123
124 #[cfg(feature = "ffmpeg_6_0")]
125 AV::AMBIENT_VIEWING_ENVIRONMENT => Type::AMBIENT_VIEWING_ENVIRONMENT,
126
127 #[cfg(feature = "ffmpeg_6_1")]
128 AV::VIDEO_HINT => Type::VIDEO_HINT,
129
130 #[cfg(feature = "ffmpeg_7_1")]
131 AV::LCEVC => Type::LCEVC,
132 #[cfg(feature = "ffmpeg_7_1")]
133 AV::VIEW_ID => Type::ViewId,
134
135 #[cfg(feature = "ffmpeg_8_0")]
136 AV::_3D_REFERENCE_DISPLAYS => Type::_3DReferenceDisplays,
137
138 #[cfg(feature = "ffmpeg_8_1")]
139 AV::EXIF => Type::EXIF,
140
141 #[cfg(feature = "ffmpeg_9_0")]
142 AV::DYNAMIC_HDR_SMPTE_2094_APP5 => Type::DYNAMIC_HDR_SMPTE_2094_APP5,
143 #[cfg(feature = "ffmpeg_9_0")]
144 AV::IAMF_MIX_GAIN_PARAM => Type::IAMF_MIX_GAIN_PARAM,
145 #[cfg(feature = "ffmpeg_9_0")]
146 AV::IAMF_DEMIXING_INFO_PARAM => Type::IAMF_DEMIXING_INFO_PARAM,
147 #[cfg(feature = "ffmpeg_9_0")]
148 AV::IAMF_RECON_GAIN_INFO_PARAM => Type::IAMF_RECON_GAIN_INFO_PARAM,
149 #[cfg(feature = "ffmpeg_9_0")]
150 AV::RAW_COLOR_PARAMS => Type::RAW_COLOR_PARAMS,
151
152 _ => unimplemented!(),
153 }
154 }
155}
156
157impl From<Type> for AVFrameSideDataType {
158 #[inline(always)]
159 fn from(value: Type) -> AVFrameSideDataType {
160 use AVFrameSideDataType as AV;
161
162 match value {
163 Type::PanScan => AV::PANSCAN,
164 Type::A53CC => AV::A53_CC,
165 Type::Stereo3D => AV::STEREO3D,
166 Type::MatrixEncoding => AV::MATRIXENCODING,
167 Type::DownMixInfo => AV::DOWNMIX_INFO,
168 Type::ReplayGain => AV::REPLAYGAIN,
169 Type::DisplayMatrix => AV::DISPLAYMATRIX,
170 Type::AFD => AV::AFD,
171 Type::MotionVectors => AV::MOTION_VECTORS,
172 Type::SkipSamples => AV::SKIP_SAMPLES,
173 Type::AudioServiceType => AV::AUDIO_SERVICE_TYPE,
174 Type::MasteringDisplayMetadata => AV::MASTERING_DISPLAY_METADATA,
175 Type::GOPTimecode => AV::GOP_TIMECODE,
176 Type::Spherical => AV::SPHERICAL,
177
178 Type::ContentLightLevel => AV::CONTENT_LIGHT_LEVEL,
179 Type::IccProfile => AV::ICC_PROFILE,
180
181 Type::S12M_TIMECODE => AV::S12M_TIMECODE,
182
183 Type::DYNAMIC_HDR_PLUS => AV::DYNAMIC_HDR_PLUS,
184 Type::REGIONS_OF_INTEREST => AV::REGIONS_OF_INTEREST,
185
186 Type::VIDEO_ENC_PARAMS => AV::VIDEO_ENC_PARAMS,
187
188 Type::SEI_UNREGISTERED => AV::SEI_UNREGISTERED,
189 Type::FILM_GRAIN_PARAMS => AV::FILM_GRAIN_PARAMS,
190
191 Type::DETECTION_BBOXES => AV::DETECTION_BBOXES,
192 Type::DOVI_RPU_BUFFER => AV::DOVI_RPU_BUFFER,
193 Type::DOVI_METADATA => AV::DOVI_METADATA,
194
195 Type::DYNAMIC_HDR_VIVID => AV::DYNAMIC_HDR_VIVID,
196
197 #[cfg(feature = "ffmpeg_6_0")]
198 Type::AMBIENT_VIEWING_ENVIRONMENT => AV::AMBIENT_VIEWING_ENVIRONMENT,
199
200 #[cfg(feature = "ffmpeg_6_1")]
201 Type::VIDEO_HINT => AV::VIDEO_HINT,
202
203 #[cfg(feature = "ffmpeg_7_1")]
204 Type::LCEVC => AV::LCEVC,
205 #[cfg(feature = "ffmpeg_7_1")]
206 Type::ViewId => AV::VIEW_ID,
207
208 #[cfg(feature = "ffmpeg_8_0")]
209 Type::_3DReferenceDisplays => AV::_3D_REFERENCE_DISPLAYS,
210
211 #[cfg(feature = "ffmpeg_8_1")]
212 Type::EXIF => AV::EXIF,
213
214 #[cfg(feature = "ffmpeg_9_0")]
215 Type::DYNAMIC_HDR_SMPTE_2094_APP5 => AV::DYNAMIC_HDR_SMPTE_2094_APP5,
216 #[cfg(feature = "ffmpeg_9_0")]
217 Type::IAMF_MIX_GAIN_PARAM => AV::IAMF_MIX_GAIN_PARAM,
218 #[cfg(feature = "ffmpeg_9_0")]
219 Type::IAMF_DEMIXING_INFO_PARAM => AV::IAMF_DEMIXING_INFO_PARAM,
220 #[cfg(feature = "ffmpeg_9_0")]
221 Type::IAMF_RECON_GAIN_INFO_PARAM => AV::IAMF_RECON_GAIN_INFO_PARAM,
222 #[cfg(feature = "ffmpeg_9_0")]
223 Type::RAW_COLOR_PARAMS => AV::RAW_COLOR_PARAMS,
224 }
225 }
226}
227
228pub struct SideData<'a> {
229 ptr: *mut AVFrameSideData,
230
231 _marker: PhantomData<&'a Frame>,
232}
233
234impl<'a> SideData<'a> {
235 #[inline(always)]
236 pub unsafe fn wrap(ptr: *mut AVFrameSideData) -> Self {
237 SideData {
238 ptr,
239 _marker: PhantomData,
240 }
241 }
242
243 #[inline(always)]
244 pub unsafe fn as_ptr(&self) -> *const AVFrameSideData {
245 self.ptr as *const _
246 }
247
248 #[inline(always)]
249 pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFrameSideData {
250 self.ptr
251 }
252}
253
254impl<'a> SideData<'a> {
255 #[inline]
256 pub fn kind(&self) -> Type {
257 unsafe { Type::from((*self.as_ptr()).type_) }
258 }
259
260 #[inline]
261 pub fn data(&self) -> &[u8] {
262 unsafe { slice::from_raw_parts((*self.as_ptr()).data, (*self.as_ptr()).size as usize) }
263 }
264
265 pub fn metadata(&self) -> DictionaryRef<'_> {
266 unsafe { DictionaryRef::from_raw((*self.as_ptr()).metadata) }
267 }
268}
269
270#[cfg(all(test, feature = "ffmpeg_9_0"))]
271mod tests {
272 use super::*;
273
274 #[test]
275 fn ffmpeg_9_side_data_round_trips() {
276 for kind in [
277 Type::DYNAMIC_HDR_SMPTE_2094_APP5,
278 Type::IAMF_MIX_GAIN_PARAM,
279 Type::IAMF_DEMIXING_INFO_PARAM,
280 Type::IAMF_RECON_GAIN_INFO_PARAM,
281 Type::RAW_COLOR_PARAMS,
282 ] {
283 let raw: AVFrameSideDataType = kind.into();
284 assert_eq!(Type::from(raw), kind);
285 }
286 }
287}