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