diff --git a/devices/src/virtio/video/decoder/backend/ffmpeg.rs b/devices/src/virtio/video/decoder/backend/ffmpeg.rs index ecba823a92..102abac5eb 100644 --- a/devices/src/virtio/video/decoder/backend/ffmpeg.rs +++ b/devices/src/virtio/video/decoder/backend/ffmpeg.rs @@ -633,7 +633,7 @@ impl DecoderBackend for FfmpegDecoder { profile_iter .filter_map(|p| { - match p.profile as u32 { + match p.profile() { FF_PROFILE_H264_BASELINE => Some(Profile::H264Baseline), FF_PROFILE_H264_MAIN => Some(Profile::H264Main), FF_PROFILE_H264_EXTENDED => Some(Profile::H264Extended), @@ -662,7 +662,7 @@ impl DecoderBackend for FfmpegDecoder { ] } Format::VP9 => profile_iter - .filter_map(|p| match p.profile as u32 { + .filter_map(|p| match p.profile() { FF_PROFILE_VP9_0 => Some(Profile::VP9Profile0), FF_PROFILE_VP9_1 => Some(Profile::VP9Profile1), FF_PROFILE_VP9_2 => Some(Profile::VP9Profile2), @@ -671,7 +671,7 @@ impl DecoderBackend for FfmpegDecoder { }) .collect(), Format::Hevc => profile_iter - .filter_map(|p| match p.profile as u32 { + .filter_map(|p| match p.profile() { FF_PROFILE_HEVC_MAIN => Some(Profile::HevcMain), FF_PROFILE_HEVC_MAIN_10 => Some(Profile::HevcMain10), FF_PROFILE_HEVC_MAIN_STILL_PICTURE => Some(Profile::HevcMainStillPicture), diff --git a/media/ffmpeg/src/avcodec.rs b/media/ffmpeg/src/avcodec.rs index 14630c102b..5fb52174dd 100644 --- a/media/ffmpeg/src/avcodec.rs +++ b/media/ffmpeg/src/avcodec.rs @@ -7,6 +7,7 @@ //! low-level access as the libavcodec functions do. use std::ffi::CStr; +use std::fmt::Debug; use std::fmt::Display; use std::marker::PhantomData; use std::ops::Deref; @@ -139,11 +140,41 @@ impl Iterator for AvCodecIterator { } } +/// Simple wrapper over `AVProfile` that provides helpful methods. +pub struct AvProfile(&'static ffi::AVProfile); + +impl AvProfile { + /// Return the profile id, which can be matched against FF_PROFILE_*. + pub fn profile(&self) -> u32 { + self.0.profile as u32 + } + + /// Return the name of this profile. + pub fn name(&self) -> &'static str { + const INVALID_PROFILE_STR: &str = "invalid profile"; + + // Safe because `CStr::from_ptr` is called on a valid zero-terminated C string. + unsafe { CStr::from_ptr(self.0.name).to_str() }.unwrap_or(INVALID_PROFILE_STR) + } +} + +impl Display for AvProfile { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(self.name()) + } +} + +impl Debug for AvProfile { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + Display::fmt(self, f) + } +} + /// Lightweight abstraction over the array of supported profiles for a given codec. pub struct AvProfileIterator(*const ffi::AVProfile); impl Iterator for AvProfileIterator { - type Item = &'static ffi::AVProfile; + type Item = AvProfile; fn next(&mut self) -> Option { // Safe because the contract of `new` stipulates we have received a valid `AVCodec` @@ -158,7 +189,7 @@ impl Iterator for AvProfileIterator { // Safe because we have been initialized to a static, valid profiles array // which is terminated by FF_PROFILE_UNKNOWN. self.0 = unsafe { self.0.offset(1) }; - Some(profile) + Some(AvProfile(profile)) } } }