1use std::{ffi::CStr, marker::PhantomData, slice, str::from_utf8_unchecked};
2
3use super::Frame;
4use crate::{
5 DictionaryRef,
6 ffi::{AVFrameSideDataType::*, *},
7};
8
9#[derive(Eq, PartialEq, Copy, Clone, Debug)]
10pub enum Type {
11 PanScan,
12 A53CC,
13 Stereo3D,
14 MatrixEncoding,
15 DownMixInfo,
16 ReplayGain,
17 DisplayMatrix,
18 AFD,
19 MotionVectors,
20 SkipSamples,
21 AudioServiceType,
22 MasteringDisplayMetadata,
23 GOPTimecode,
24 Spherical,
25
26 ContentLightLevel,
27 IccProfile,
28
29 #[cfg(all(feature = "ffmpeg_4_0", not(feature = "ffmpeg_5_0")))]
30 QPTableProperties,
31 #[cfg(all(feature = "ffmpeg_4_0", not(feature = "ffmpeg_5_0")))]
32 QPTableData,
33
34 #[cfg(feature = "ffmpeg_4_1")]
35 S12M_TIMECODE,
36
37 #[cfg(feature = "ffmpeg_4_2")]
38 DYNAMIC_HDR_PLUS,
39 #[cfg(feature = "ffmpeg_4_2")]
40 REGIONS_OF_INTEREST,
41
42 #[cfg(feature = "ffmpeg_4_3")]
43 VIDEO_ENC_PARAMS,
44
45 #[cfg(feature = "ffmpeg_4_4")]
46 SEI_UNREGISTERED,
47 #[cfg(feature = "ffmpeg_4_4")]
48 FILM_GRAIN_PARAMS,
49
50 #[cfg(feature = "ffmpeg_5_0")]
51 DETECTION_BBOXES,
52 #[cfg(feature = "ffmpeg_5_0")]
53 DOVI_RPU_BUFFER,
54 #[cfg(feature = "ffmpeg_5_0")]
55 DOVI_METADATA,
56
57 #[cfg(feature = "ffmpeg_5_1")]
58 DYNAMIC_HDR_VIVID,
59
60 #[cfg(feature = "ffmpeg_6_0")]
61 AMBIENT_VIEWING_ENVIRONMENT,
62
63 #[cfg(feature = "ffmpeg_6_1")]
64 VIDEO_HINT,
65
66 #[cfg(feature = "ffmpeg_7_1")]
67 LCEVC,
68 #[cfg(feature = "ffmpeg_7_1")]
69 VIEW_ID,
70
71 #[cfg(feature = "ffmpeg_8_0")]
72 THREE_D_REFERENCE_DISPLAYS,
73}
74
75impl Type {
76 #[inline]
77 pub fn name(&self) -> &'static str {
78 unsafe { from_utf8_unchecked(CStr::from_ptr(av_frame_side_data_name((*self).into())).to_bytes()) }
79 }
80}
81
82impl From<AVFrameSideDataType> for Type {
83 #[inline(always)]
84 fn from(value: AVFrameSideDataType) -> Self {
85 match value {
86 AV_FRAME_DATA_PANSCAN => Type::PanScan,
87 AV_FRAME_DATA_A53_CC => Type::A53CC,
88 AV_FRAME_DATA_STEREO3D => Type::Stereo3D,
89 AV_FRAME_DATA_MATRIXENCODING => Type::MatrixEncoding,
90 AV_FRAME_DATA_DOWNMIX_INFO => Type::DownMixInfo,
91 AV_FRAME_DATA_REPLAYGAIN => Type::ReplayGain,
92 AV_FRAME_DATA_DISPLAYMATRIX => Type::DisplayMatrix,
93 AV_FRAME_DATA_AFD => Type::AFD,
94 AV_FRAME_DATA_MOTION_VECTORS => Type::MotionVectors,
95 AV_FRAME_DATA_SKIP_SAMPLES => Type::SkipSamples,
96 AV_FRAME_DATA_AUDIO_SERVICE_TYPE => Type::AudioServiceType,
97 AV_FRAME_DATA_MASTERING_DISPLAY_METADATA => Type::MasteringDisplayMetadata,
98 AV_FRAME_DATA_GOP_TIMECODE => Type::GOPTimecode,
99 AV_FRAME_DATA_SPHERICAL => Type::Spherical,
100
101 AV_FRAME_DATA_CONTENT_LIGHT_LEVEL => Type::ContentLightLevel,
102 AV_FRAME_DATA_ICC_PROFILE => Type::IccProfile,
103
104 #[cfg(all(feature = "ffmpeg_4_0", not(feature = "ffmpeg_5_0")))]
105 AV_FRAME_DATA_QP_TABLE_PROPERTIES => Type::QPTableProperties,
106 #[cfg(all(feature = "ffmpeg_4_0", not(feature = "ffmpeg_5_0")))]
107 AV_FRAME_DATA_QP_TABLE_DATA => Type::QPTableData,
108 #[cfg(feature = "ffmpeg_4_1")]
109 AV_FRAME_DATA_S12M_TIMECODE => Type::S12M_TIMECODE,
110
111 #[cfg(feature = "ffmpeg_4_2")]
112 AV_FRAME_DATA_DYNAMIC_HDR_PLUS => Type::DYNAMIC_HDR_PLUS,
113 #[cfg(feature = "ffmpeg_4_2")]
114 AV_FRAME_DATA_REGIONS_OF_INTEREST => Type::REGIONS_OF_INTEREST,
115
116 #[cfg(feature = "ffmpeg_4_3")]
117 AV_FRAME_DATA_VIDEO_ENC_PARAMS => Type::VIDEO_ENC_PARAMS,
118
119 #[cfg(feature = "ffmpeg_4_4")]
120 AV_FRAME_DATA_SEI_UNREGISTERED => Type::SEI_UNREGISTERED,
121 #[cfg(feature = "ffmpeg_4_4")]
122 AV_FRAME_DATA_FILM_GRAIN_PARAMS => Type::FILM_GRAIN_PARAMS,
123
124 #[cfg(feature = "ffmpeg_5_0")]
125 AV_FRAME_DATA_DETECTION_BBOXES => Type::DETECTION_BBOXES,
126 #[cfg(feature = "ffmpeg_5_0")]
127 AV_FRAME_DATA_DOVI_RPU_BUFFER => Type::DOVI_RPU_BUFFER,
128 #[cfg(feature = "ffmpeg_5_0")]
129 AV_FRAME_DATA_DOVI_METADATA => Type::DOVI_METADATA,
130
131 #[cfg(feature = "ffmpeg_5_1")]
132 AV_FRAME_DATA_DYNAMIC_HDR_VIVID => Type::DYNAMIC_HDR_VIVID,
133
134 #[cfg(feature = "ffmpeg_6_0")]
135 AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT => Type::AMBIENT_VIEWING_ENVIRONMENT,
136
137 #[cfg(feature = "ffmpeg_6_1")]
138 AV_FRAME_DATA_VIDEO_HINT => Type::VIDEO_HINT,
139
140 #[cfg(feature = "ffmpeg_7_1")]
141 AV_FRAME_DATA_LCEVC => Type::LCEVC,
142 #[cfg(feature = "ffmpeg_7_1")]
143 AV_FRAME_DATA_VIEW_ID => Type::VIEW_ID,
144
145 #[cfg(feature = "ffmpeg_8_0")]
146 AV_FRAME_DATA_3D_REFERENCE_DISPLAYS => Type::THREE_D_REFERENCE_DISPLAYS,
147 }
148 }
149}
150
151impl From<Type> for AVFrameSideDataType {
152 #[inline(always)]
153 fn from(value: Type) -> AVFrameSideDataType {
154 match value {
155 Type::PanScan => AV_FRAME_DATA_PANSCAN,
156 Type::A53CC => AV_FRAME_DATA_A53_CC,
157 Type::Stereo3D => AV_FRAME_DATA_STEREO3D,
158 Type::MatrixEncoding => AV_FRAME_DATA_MATRIXENCODING,
159 Type::DownMixInfo => AV_FRAME_DATA_DOWNMIX_INFO,
160 Type::ReplayGain => AV_FRAME_DATA_REPLAYGAIN,
161 Type::DisplayMatrix => AV_FRAME_DATA_DISPLAYMATRIX,
162 Type::AFD => AV_FRAME_DATA_AFD,
163 Type::MotionVectors => AV_FRAME_DATA_MOTION_VECTORS,
164 Type::SkipSamples => AV_FRAME_DATA_SKIP_SAMPLES,
165 Type::AudioServiceType => AV_FRAME_DATA_AUDIO_SERVICE_TYPE,
166 Type::MasteringDisplayMetadata => AV_FRAME_DATA_MASTERING_DISPLAY_METADATA,
167 Type::GOPTimecode => AV_FRAME_DATA_GOP_TIMECODE,
168 Type::Spherical => AV_FRAME_DATA_SPHERICAL,
169
170 Type::ContentLightLevel => AV_FRAME_DATA_CONTENT_LIGHT_LEVEL,
171 Type::IccProfile => AV_FRAME_DATA_ICC_PROFILE,
172
173 #[cfg(all(feature = "ffmpeg_4_0", not(feature = "ffmpeg_5_0")))]
174 Type::QPTableProperties => AV_FRAME_DATA_QP_TABLE_PROPERTIES,
175 #[cfg(all(feature = "ffmpeg_4_0", not(feature = "ffmpeg_5_0")))]
176 Type::QPTableData => AV_FRAME_DATA_QP_TABLE_DATA,
177 #[cfg(feature = "ffmpeg_4_1")]
178 Type::S12M_TIMECODE => AV_FRAME_DATA_S12M_TIMECODE,
179
180 #[cfg(feature = "ffmpeg_4_2")]
181 Type::DYNAMIC_HDR_PLUS => AV_FRAME_DATA_DYNAMIC_HDR_PLUS,
182 #[cfg(feature = "ffmpeg_4_2")]
183 Type::REGIONS_OF_INTEREST => AV_FRAME_DATA_REGIONS_OF_INTEREST,
184
185 #[cfg(feature = "ffmpeg_4_3")]
186 Type::VIDEO_ENC_PARAMS => AV_FRAME_DATA_VIDEO_ENC_PARAMS,
187
188 #[cfg(feature = "ffmpeg_4_4")]
189 Type::SEI_UNREGISTERED => AV_FRAME_DATA_SEI_UNREGISTERED,
190 #[cfg(feature = "ffmpeg_4_4")]
191 Type::FILM_GRAIN_PARAMS => AV_FRAME_DATA_FILM_GRAIN_PARAMS,
192
193 #[cfg(feature = "ffmpeg_5_0")]
194 Type::DETECTION_BBOXES => AV_FRAME_DATA_DETECTION_BBOXES,
195 #[cfg(feature = "ffmpeg_5_0")]
196 Type::DOVI_RPU_BUFFER => AV_FRAME_DATA_DOVI_RPU_BUFFER,
197 #[cfg(feature = "ffmpeg_5_0")]
198 Type::DOVI_METADATA => AV_FRAME_DATA_DOVI_METADATA,
199
200 #[cfg(feature = "ffmpeg_5_1")]
201 Type::DYNAMIC_HDR_VIVID => AV_FRAME_DATA_DYNAMIC_HDR_VIVID,
202
203 #[cfg(feature = "ffmpeg_6_0")]
204 Type::AMBIENT_VIEWING_ENVIRONMENT => AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT,
205
206 #[cfg(feature = "ffmpeg_6_1")]
207 Type::VIDEO_HINT => AV_FRAME_DATA_VIDEO_HINT,
208
209 #[cfg(feature = "ffmpeg_7_1")]
210 Type::LCEVC => AV_FRAME_DATA_LCEVC,
211 #[cfg(feature = "ffmpeg_7_1")]
212 Type::VIEW_ID => AV_FRAME_DATA_VIEW_ID,
213
214 #[cfg(feature = "ffmpeg_8_0")]
215 Type::THREE_D_REFERENCE_DISPLAYS => AV_FRAME_DATA_3D_REFERENCE_DISPLAYS,
216 }
217 }
218}
219
220pub struct SideData<'a> {
221 ptr: *mut AVFrameSideData,
222
223 _marker: PhantomData<&'a Frame>,
224}
225
226impl<'a> SideData<'a> {
227 #[inline(always)]
228 pub unsafe fn wrap(ptr: *mut AVFrameSideData) -> Self {
229 SideData { ptr, _marker: PhantomData }
230 }
231
232 #[inline(always)]
233 pub unsafe fn as_ptr(&self) -> *const AVFrameSideData {
234 self.ptr as *const _
235 }
236
237 #[inline(always)]
238 pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFrameSideData {
239 self.ptr
240 }
241}
242
243impl<'a> SideData<'a> {
244 #[inline]
245 pub fn kind(&self) -> Type {
246 unsafe { Type::from((*self.as_ptr()).type_) }
247 }
248
249 #[inline]
250 pub fn data(&self) -> &[u8] {
251 #[allow(clippy::unnecessary_cast)]
252 unsafe {
253 slice::from_raw_parts((*self.as_ptr()).data, (*self.as_ptr()).size as usize)
254 }
255 }
256
257 #[inline]
258 pub fn metadata(&self) -> DictionaryRef<'_> {
259 unsafe { DictionaryRef::wrap((*self.as_ptr()).metadata) }
260 }
261}