diff --git a/devices/src/virtio/video/decoder/capability.rs b/devices/src/virtio/video/decoder/capability.rs index 0d5b1cd2e7..a08c46c266 100644 --- a/devices/src/virtio/video/decoder/capability.rs +++ b/devices/src/virtio/video/decoder/capability.rs @@ -4,24 +4,13 @@ //! Capablities of the virtio video decoder device. +use std::collections::btree_map::Entry; use std::collections::BTreeMap; +use sys_util::warn; use crate::virtio::video::control::*; use crate::virtio::video::format::*; -fn from_input_format(fmt: &libvda::decode::InputFormat, mask: u64) -> FormatDesc { - let format = match fmt.profile { - libvda::Profile::VP8 => Format::VP8, - libvda::Profile::VP9Profile0 => Format::VP9, - libvda::Profile::H264 => Format::H264, - }; - FormatDesc { - mask, - format, - frame_formats: vec![Default::default()], - } -} - fn from_pixel_format( fmt: &libvda::PixelFormat, mask: u64, @@ -60,11 +49,42 @@ impl Capability { // Raise the first |# of supported raw formats|-th bits because we can assume that any // combination of (a coded format, a raw format) is valid in Chrome. let mask = !(u64::max_value() << caps.output_formats.len()); - let in_fmts = caps - .input_formats - .iter() - .map(|fmt| from_input_format(fmt, mask)) - .collect(); + + let mut in_fmts = vec![]; + let mut profiles: BTreeMap> = Default::default(); + for fmt in caps.input_formats.iter() { + match Profile::from_libvda_profile(fmt.profile) { + Some(profile) => { + let format = profile.to_format(); + in_fmts.push(FormatDesc { + mask, + format, + frame_formats: vec![Default::default()], + }); + match profiles.entry(format) { + Entry::Occupied(mut e) => e.get_mut().push(profile), + Entry::Vacant(e) => { + e.insert(vec![profile]); + } + } + } + None => { + warn!( + "No virtio-video equivalent for libvda profile, skipping: {:?}", + fmt.profile + ); + } + } + } + + let levels: BTreeMap> = if profiles.contains_key(&Format::H264) { + // We only support Level 1.0 for H.264. + vec![(Format::H264, vec![Level::H264_1_0])] + .into_iter() + .collect() + } else { + Default::default() + }; // Prepare {min, max} of {width, height}. // While these values are associated with each input format in libvda, @@ -94,23 +114,6 @@ impl Capability { .map(|fmt| from_pixel_format(fmt, mask, width_range, height_range)) .collect(); - let mut profiles: BTreeMap> = Default::default(); - let mut levels: BTreeMap> = Default::default(); - for fmt in caps.input_formats.iter() { - match fmt.profile { - libvda::Profile::VP8 => { - profiles.insert(Format::VP8, vec![Profile::VP8Profile0]); - } - libvda::Profile::VP9Profile0 => { - profiles.insert(Format::VP9, vec![Profile::VP9Profile0]); - } - libvda::Profile::H264 => { - profiles.insert(Format::H264, vec![Profile::H264Baseline]); - levels.insert(Format::H264, vec![Level::H264_1_0]); - } - }; - } - Capability { in_fmts, out_fmts, diff --git a/devices/src/virtio/video/format.rs b/devices/src/virtio/video/format.rs index fc2c441f47..59a9c85667 100644 --- a/devices/src/virtio/video/format.rs +++ b/devices/src/virtio/video/format.rs @@ -19,12 +19,98 @@ use crate::virtio::Writer; #[derive(PartialEq, Eq, PartialOrd, Ord, N, Clone, Copy, Debug)] #[repr(u32)] pub enum Profile { - VP8Profile0 = VIRTIO_VIDEO_PROFILE_VP8_PROFILE0, - VP9Profile0 = VIRTIO_VIDEO_PROFILE_VP9_PROFILE0, H264Baseline = VIRTIO_VIDEO_PROFILE_H264_BASELINE, + H264Main = VIRTIO_VIDEO_PROFILE_H264_MAIN, + H264Extended = VIRTIO_VIDEO_PROFILE_H264_EXTENDED, + H264High = VIRTIO_VIDEO_PROFILE_H264_HIGH, + H264High10 = VIRTIO_VIDEO_PROFILE_H264_HIGH10PROFILE, + H264High422 = VIRTIO_VIDEO_PROFILE_H264_HIGH422PROFILE, + H264High444PredictiveProfile = VIRTIO_VIDEO_PROFILE_H264_HIGH444PREDICTIVEPROFILE, + H264ScalableBaseline = VIRTIO_VIDEO_PROFILE_H264_SCALABLEBASELINE, + H264ScalableHigh = VIRTIO_VIDEO_PROFILE_H264_SCALABLEHIGH, + H264StereoHigh = VIRTIO_VIDEO_PROFILE_H264_STEREOHIGH, + H264MultiviewHigh = VIRTIO_VIDEO_PROFILE_H264_MULTIVIEWHIGH, + HevcMain = VIRTIO_VIDEO_PROFILE_HEVC_MAIN, + HevcMain10 = VIRTIO_VIDEO_PROFILE_HEVC_MAIN10, + HevcMainStillPicture = VIRTIO_VIDEO_PROFILE_HEVC_MAIN_STILL_PICTURE, + VP8Profile0 = VIRTIO_VIDEO_PROFILE_VP8_PROFILE0, + VP8Profile1 = VIRTIO_VIDEO_PROFILE_VP8_PROFILE1, + VP8Profile2 = VIRTIO_VIDEO_PROFILE_VP8_PROFILE2, + VP8Profile3 = VIRTIO_VIDEO_PROFILE_VP8_PROFILE3, + VP9Profile0 = VIRTIO_VIDEO_PROFILE_VP9_PROFILE0, + VP9Profile1 = VIRTIO_VIDEO_PROFILE_VP9_PROFILE1, + VP9Profile2 = VIRTIO_VIDEO_PROFILE_VP9_PROFILE2, + VP9Profile3 = VIRTIO_VIDEO_PROFILE_VP9_PROFILE3, } impl_try_from_le32_for_enumn!(Profile, "profile"); +macro_rules! impl_libvda_conversion { + ( $( ( $x:ident, $y:ident ) ),* ) => { + pub fn from_libvda_profile(p: libvda::Profile) -> Option { + match p { + $(libvda::Profile::$x => Some(Self::$y),)* + _ => None + } + } + + // TODO(alexlau): Remove this after encoder CL lands. + #[allow(dead_code)] + pub fn to_libvda_profile(&self) -> Option { + match self { + $(Self::$y => Some(libvda::Profile::$x),)* + _ => None + } + } + } +} + +impl Profile { + pub fn to_format(&self) -> Format { + use Profile::*; + match self { + H264Baseline + | H264Main + | H264Extended + | H264High + | H264High10 + | H264High422 + | H264High444PredictiveProfile + | H264ScalableBaseline + | H264ScalableHigh + | H264StereoHigh + | H264MultiviewHigh => Format::H264, + HevcMain | HevcMain10 | HevcMainStillPicture => Format::HEVC, + VP8Profile0 | VP8Profile1 | VP8Profile2 | VP8Profile3 => Format::VP8, + VP9Profile0 | VP9Profile1 | VP9Profile2 | VP9Profile3 => Format::VP9, + } + } + + impl_libvda_conversion!( + (H264ProfileBaseline, H264Baseline), + (H264ProfileMain, H264Main), + (H264ProfileExtended, H264Extended), + (H264ProfileHigh, H264High), + (H264ProfileHigh10Profile, H264High10), + (H264ProfileHigh422Profile, H264High422), + ( + H264ProfileHigh444PredictiveProfile, + H264High444PredictiveProfile + ), + (H264ProfileScalableBaseline, H264ScalableBaseline), + (H264ProfileScalableHigh, H264ScalableHigh), + (H264ProfileStereoHigh, H264StereoHigh), + (H264ProfileMultiviewHigh, H264MultiviewHigh), + (HevcProfileMain, HevcMain), + (HevcProfileMain10, HevcMain10), + (HevcProfileMainStillPicture, HevcMainStillPicture), + (VP8, VP8Profile0), + (VP9Profile0, VP9Profile0), + (VP9Profile1, VP9Profile1), + (VP9Profile2, VP9Profile2), + (VP9Profile3, VP9Profile3) + ); +} + #[derive(PartialEq, Eq, PartialOrd, Ord, N, Clone, Copy, Debug)] #[repr(u32)] pub enum Level { @@ -41,6 +127,7 @@ pub enum Format { // Bitstream formats H264 = VIRTIO_VIDEO_FORMAT_H264, + HEVC = VIRTIO_VIDEO_FORMAT_HEVC, VP8 = VIRTIO_VIDEO_FORMAT_VP8, VP9 = VIRTIO_VIDEO_FORMAT_VP9, }