Skip to main content

ffmpeg_the_third/util/frame/
side_data.rs

1use 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}