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