ffmpeg-the-third 5.0.0+ffmpeg-8.1

Safe FFmpeg wrapper (FFmpeg 5+ compatible fork of the ffmpeg crate)
Documentation
use std::marker::PhantomData;
use std::slice;

use super::Frame;
use crate::ffi::*;
use crate::utils;
use crate::DictionaryRef;
#[cfg(feature = "serialize")]
use serde::{Deserialize, Serialize};

#[derive(Eq, PartialEq, Copy, Clone, Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub enum Type {
    PanScan,
    A53CC,
    Stereo3D,
    MatrixEncoding,
    DownMixInfo,
    ReplayGain,
    DisplayMatrix,
    AFD,
    MotionVectors,
    SkipSamples,
    AudioServiceType,
    MasteringDisplayMetadata,
    GOPTimecode,
    Spherical,

    ContentLightLevel,
    IccProfile,

    S12M_TIMECODE,

    DYNAMIC_HDR_PLUS,
    REGIONS_OF_INTEREST,

    VIDEO_ENC_PARAMS,

    SEI_UNREGISTERED,
    FILM_GRAIN_PARAMS,

    DETECTION_BBOXES,
    DOVI_RPU_BUFFER,
    DOVI_METADATA,

    DYNAMIC_HDR_VIVID,

    #[cfg(feature = "ffmpeg_6_0")]
    AMBIENT_VIEWING_ENVIRONMENT,

    #[cfg(feature = "ffmpeg_6_1")]
    VIDEO_HINT,

    #[cfg(feature = "ffmpeg_7_1")]
    LCEVC,
    #[cfg(feature = "ffmpeg_7_1")]
    ViewId,

    #[cfg(feature = "ffmpeg_8_0")]
    _3DReferenceDisplays,

    #[cfg(feature = "ffmpeg_8_1")]
    EXIF,
}

impl Type {
    #[inline]
    pub fn name(&self) -> &'static str {
        unsafe { utils::str_from_c_ptr(av_frame_side_data_name((*self).into())) }
    }
}

impl From<AVFrameSideDataType> for Type {
    #[inline(always)]
    fn from(value: AVFrameSideDataType) -> Self {
        use AVFrameSideDataType as AV;

        match value {
            AV::PANSCAN => Type::PanScan,
            AV::A53_CC => Type::A53CC,
            AV::STEREO3D => Type::Stereo3D,
            AV::MATRIXENCODING => Type::MatrixEncoding,
            AV::DOWNMIX_INFO => Type::DownMixInfo,
            AV::REPLAYGAIN => Type::ReplayGain,
            AV::DISPLAYMATRIX => Type::DisplayMatrix,
            AV::AFD => Type::AFD,
            AV::MOTION_VECTORS => Type::MotionVectors,
            AV::SKIP_SAMPLES => Type::SkipSamples,
            AV::AUDIO_SERVICE_TYPE => Type::AudioServiceType,
            AV::MASTERING_DISPLAY_METADATA => Type::MasteringDisplayMetadata,
            AV::GOP_TIMECODE => Type::GOPTimecode,
            AV::SPHERICAL => Type::Spherical,

            AV::CONTENT_LIGHT_LEVEL => Type::ContentLightLevel,
            AV::ICC_PROFILE => Type::IccProfile,

            AV::S12M_TIMECODE => Type::S12M_TIMECODE,

            AV::DYNAMIC_HDR_PLUS => Type::DYNAMIC_HDR_PLUS,
            AV::REGIONS_OF_INTEREST => Type::REGIONS_OF_INTEREST,

            AV::VIDEO_ENC_PARAMS => Type::VIDEO_ENC_PARAMS,

            AV::SEI_UNREGISTERED => Type::SEI_UNREGISTERED,
            AV::FILM_GRAIN_PARAMS => Type::FILM_GRAIN_PARAMS,

            AV::DETECTION_BBOXES => Type::DETECTION_BBOXES,
            AV::DOVI_RPU_BUFFER => Type::DOVI_RPU_BUFFER,
            AV::DOVI_METADATA => Type::DOVI_METADATA,

            AV::DYNAMIC_HDR_VIVID => Type::DYNAMIC_HDR_VIVID,

            #[cfg(feature = "ffmpeg_6_0")]
            AV::AMBIENT_VIEWING_ENVIRONMENT => Type::AMBIENT_VIEWING_ENVIRONMENT,

            #[cfg(feature = "ffmpeg_6_1")]
            AV::VIDEO_HINT => Type::VIDEO_HINT,

            #[cfg(feature = "ffmpeg_7_1")]
            AV::LCEVC => Type::LCEVC,
            #[cfg(feature = "ffmpeg_7_1")]
            AV::VIEW_ID => Type::ViewId,

            #[cfg(feature = "ffmpeg_8_0")]
            AV::_3D_REFERENCE_DISPLAYS => Type::_3DReferenceDisplays,

            #[cfg(feature = "ffmpeg_8_1")]
            AV::EXIF => Type::EXIF,

            _ => unimplemented!(),
        }
    }
}

impl From<Type> for AVFrameSideDataType {
    #[inline(always)]
    fn from(value: Type) -> AVFrameSideDataType {
        use AVFrameSideDataType as AV;

        match value {
            Type::PanScan => AV::PANSCAN,
            Type::A53CC => AV::A53_CC,
            Type::Stereo3D => AV::STEREO3D,
            Type::MatrixEncoding => AV::MATRIXENCODING,
            Type::DownMixInfo => AV::DOWNMIX_INFO,
            Type::ReplayGain => AV::REPLAYGAIN,
            Type::DisplayMatrix => AV::DISPLAYMATRIX,
            Type::AFD => AV::AFD,
            Type::MotionVectors => AV::MOTION_VECTORS,
            Type::SkipSamples => AV::SKIP_SAMPLES,
            Type::AudioServiceType => AV::AUDIO_SERVICE_TYPE,
            Type::MasteringDisplayMetadata => AV::MASTERING_DISPLAY_METADATA,
            Type::GOPTimecode => AV::GOP_TIMECODE,
            Type::Spherical => AV::SPHERICAL,

            Type::ContentLightLevel => AV::CONTENT_LIGHT_LEVEL,
            Type::IccProfile => AV::ICC_PROFILE,

            Type::S12M_TIMECODE => AV::S12M_TIMECODE,

            Type::DYNAMIC_HDR_PLUS => AV::DYNAMIC_HDR_PLUS,
            Type::REGIONS_OF_INTEREST => AV::REGIONS_OF_INTEREST,

            Type::VIDEO_ENC_PARAMS => AV::VIDEO_ENC_PARAMS,

            Type::SEI_UNREGISTERED => AV::SEI_UNREGISTERED,
            Type::FILM_GRAIN_PARAMS => AV::FILM_GRAIN_PARAMS,

            Type::DETECTION_BBOXES => AV::DETECTION_BBOXES,
            Type::DOVI_RPU_BUFFER => AV::DOVI_RPU_BUFFER,
            Type::DOVI_METADATA => AV::DOVI_METADATA,

            Type::DYNAMIC_HDR_VIVID => AV::DYNAMIC_HDR_VIVID,

            #[cfg(feature = "ffmpeg_6_0")]
            Type::AMBIENT_VIEWING_ENVIRONMENT => AV::AMBIENT_VIEWING_ENVIRONMENT,

            #[cfg(feature = "ffmpeg_6_1")]
            Type::VIDEO_HINT => AV::VIDEO_HINT,

            #[cfg(feature = "ffmpeg_7_1")]
            Type::LCEVC => AV::LCEVC,
            #[cfg(feature = "ffmpeg_7_1")]
            Type::ViewId => AV::VIEW_ID,

            #[cfg(feature = "ffmpeg_8_0")]
            Type::_3DReferenceDisplays => AV::_3D_REFERENCE_DISPLAYS,

            #[cfg(feature = "ffmpeg_8_1")]
            Type::EXIF => AV::EXIF,
        }
    }
}

pub struct SideData<'a> {
    ptr: *mut AVFrameSideData,

    _marker: PhantomData<&'a Frame>,
}

impl<'a> SideData<'a> {
    #[inline(always)]
    pub unsafe fn wrap(ptr: *mut AVFrameSideData) -> Self {
        SideData {
            ptr,
            _marker: PhantomData,
        }
    }

    #[inline(always)]
    pub unsafe fn as_ptr(&self) -> *const AVFrameSideData {
        self.ptr as *const _
    }

    #[inline(always)]
    pub unsafe fn as_mut_ptr(&mut self) -> *mut AVFrameSideData {
        self.ptr
    }
}

impl<'a> SideData<'a> {
    #[inline]
    pub fn kind(&self) -> Type {
        unsafe { Type::from((*self.as_ptr()).type_) }
    }

    #[inline]
    pub fn data(&self) -> &[u8] {
        unsafe { slice::from_raw_parts((*self.as_ptr()).data, (*self.as_ptr()).size as usize) }
    }

    pub fn metadata(&self) -> DictionaryRef<'_> {
        unsafe { DictionaryRef::from_raw((*self.as_ptr()).metadata) }
    }
}