1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2020 The ChromiumOS Authors 2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file. 4*bb4ee6a4SAndroid Build Coastguard Worker 5*bb4ee6a4SAndroid Build Coastguard Worker //! Parameters for streams in virtio video devices. 6*bb4ee6a4SAndroid Build Coastguard Worker 7*bb4ee6a4SAndroid Build Coastguard Worker use std::convert::From; 8*bb4ee6a4SAndroid Build Coastguard Worker use std::convert::Into; 9*bb4ee6a4SAndroid Build Coastguard Worker use std::convert::TryFrom; 10*bb4ee6a4SAndroid Build Coastguard Worker 11*bb4ee6a4SAndroid Build Coastguard Worker use base::error; 12*bb4ee6a4SAndroid Build Coastguard Worker use data_model::Le32; 13*bb4ee6a4SAndroid Build Coastguard Worker 14*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::video::command::QueueType; 15*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::video::command::ReadCmdError; 16*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::video::format::*; 17*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::video::protocol::*; 18*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::video::resource::ResourceType; 19*bb4ee6a4SAndroid Build Coastguard Worker 20*bb4ee6a4SAndroid Build Coastguard Worker /// Safe wrapper of `virtio_video_params`. 21*bb4ee6a4SAndroid Build Coastguard Worker /// Note that this struct doesn't have a field corresponding to `queue_type` in 22*bb4ee6a4SAndroid Build Coastguard Worker /// `virtio_video_params`. The type of queue should be stored by one that has an `Params` instance. 23*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Default, Clone)] 24*bb4ee6a4SAndroid Build Coastguard Worker pub struct Params { 25*bb4ee6a4SAndroid Build Coastguard Worker // Use `Option<Format>` instead of `Format` because an image format may not be determined until 26*bb4ee6a4SAndroid Build Coastguard Worker // video decoding is started in the decoder. 27*bb4ee6a4SAndroid Build Coastguard Worker pub format: Option<Format>, 28*bb4ee6a4SAndroid Build Coastguard Worker pub resource_type: ResourceType, 29*bb4ee6a4SAndroid Build Coastguard Worker pub frame_width: u32, 30*bb4ee6a4SAndroid Build Coastguard Worker pub frame_height: u32, 31*bb4ee6a4SAndroid Build Coastguard Worker pub min_buffers: u32, 32*bb4ee6a4SAndroid Build Coastguard Worker pub max_buffers: u32, 33*bb4ee6a4SAndroid Build Coastguard Worker pub crop: Crop, 34*bb4ee6a4SAndroid Build Coastguard Worker pub frame_rate: u32, 35*bb4ee6a4SAndroid Build Coastguard Worker pub plane_formats: Vec<PlaneFormat>, 36*bb4ee6a4SAndroid Build Coastguard Worker } 37*bb4ee6a4SAndroid Build Coastguard Worker 38*bb4ee6a4SAndroid Build Coastguard Worker impl TryFrom<virtio_video_params> for Params { 39*bb4ee6a4SAndroid Build Coastguard Worker type Error = ReadCmdError; 40*bb4ee6a4SAndroid Build Coastguard Worker 41*bb4ee6a4SAndroid Build Coastguard Worker fn try_from( 42*bb4ee6a4SAndroid Build Coastguard Worker virtio_video_params { 43*bb4ee6a4SAndroid Build Coastguard Worker format, 44*bb4ee6a4SAndroid Build Coastguard Worker frame_width, 45*bb4ee6a4SAndroid Build Coastguard Worker frame_height, 46*bb4ee6a4SAndroid Build Coastguard Worker min_buffers, 47*bb4ee6a4SAndroid Build Coastguard Worker max_buffers, 48*bb4ee6a4SAndroid Build Coastguard Worker crop, 49*bb4ee6a4SAndroid Build Coastguard Worker frame_rate, 50*bb4ee6a4SAndroid Build Coastguard Worker num_planes, 51*bb4ee6a4SAndroid Build Coastguard Worker plane_formats, 52*bb4ee6a4SAndroid Build Coastguard Worker .. 53*bb4ee6a4SAndroid Build Coastguard Worker }: virtio_video_params, 54*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Self, Self::Error> { 55*bb4ee6a4SAndroid Build Coastguard Worker let num_planes = Into::<u32>::into(num_planes); // as usize; 56*bb4ee6a4SAndroid Build Coastguard Worker if num_planes as usize > plane_formats.len() { 57*bb4ee6a4SAndroid Build Coastguard Worker error!( 58*bb4ee6a4SAndroid Build Coastguard Worker "num_planes must not exceed {} but {}", 59*bb4ee6a4SAndroid Build Coastguard Worker plane_formats.len(), 60*bb4ee6a4SAndroid Build Coastguard Worker Into::<u32>::into(num_planes) 61*bb4ee6a4SAndroid Build Coastguard Worker ); 62*bb4ee6a4SAndroid Build Coastguard Worker return Err(ReadCmdError::InvalidArgument); 63*bb4ee6a4SAndroid Build Coastguard Worker } 64*bb4ee6a4SAndroid Build Coastguard Worker let plane_formats = plane_formats[0..num_planes as usize] 65*bb4ee6a4SAndroid Build Coastguard Worker .iter() 66*bb4ee6a4SAndroid Build Coastguard Worker .map(|x| Into::<PlaneFormat>::into(*x)) 67*bb4ee6a4SAndroid Build Coastguard Worker .collect::<Vec<_>>(); 68*bb4ee6a4SAndroid Build Coastguard Worker 69*bb4ee6a4SAndroid Build Coastguard Worker Ok(Params { 70*bb4ee6a4SAndroid Build Coastguard Worker format: Format::n(format.into()), 71*bb4ee6a4SAndroid Build Coastguard Worker resource_type: Default::default(), 72*bb4ee6a4SAndroid Build Coastguard Worker frame_width: frame_width.into(), 73*bb4ee6a4SAndroid Build Coastguard Worker frame_height: frame_height.into(), 74*bb4ee6a4SAndroid Build Coastguard Worker min_buffers: min_buffers.into(), 75*bb4ee6a4SAndroid Build Coastguard Worker max_buffers: max_buffers.into(), 76*bb4ee6a4SAndroid Build Coastguard Worker crop: crop.into(), 77*bb4ee6a4SAndroid Build Coastguard Worker frame_rate: frame_rate.into(), 78*bb4ee6a4SAndroid Build Coastguard Worker plane_formats, 79*bb4ee6a4SAndroid Build Coastguard Worker }) 80*bb4ee6a4SAndroid Build Coastguard Worker } 81*bb4ee6a4SAndroid Build Coastguard Worker } 82*bb4ee6a4SAndroid Build Coastguard Worker 83*bb4ee6a4SAndroid Build Coastguard Worker impl TryFrom<virtio_video_params_ext> for Params { 84*bb4ee6a4SAndroid Build Coastguard Worker type Error = ReadCmdError; 85*bb4ee6a4SAndroid Build Coastguard Worker 86*bb4ee6a4SAndroid Build Coastguard Worker fn try_from( 87*bb4ee6a4SAndroid Build Coastguard Worker virtio_video_params_ext { 88*bb4ee6a4SAndroid Build Coastguard Worker base, 89*bb4ee6a4SAndroid Build Coastguard Worker resource_type, 90*bb4ee6a4SAndroid Build Coastguard Worker .. 91*bb4ee6a4SAndroid Build Coastguard Worker }: virtio_video_params_ext, 92*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Self, Self::Error> { 93*bb4ee6a4SAndroid Build Coastguard Worker let mut params = Params::try_from(base)?; 94*bb4ee6a4SAndroid Build Coastguard Worker params.resource_type = match resource_type.into() { 95*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_VIDEO_MEM_TYPE_GUEST_PAGES => ResourceType::GuestPages, 96*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_VIDEO_MEM_TYPE_VIRTIO_OBJECT => ResourceType::VirtioObject, 97*bb4ee6a4SAndroid Build Coastguard Worker _ => return Err(ReadCmdError::InvalidArgument), 98*bb4ee6a4SAndroid Build Coastguard Worker }; 99*bb4ee6a4SAndroid Build Coastguard Worker 100*bb4ee6a4SAndroid Build Coastguard Worker Ok(params) 101*bb4ee6a4SAndroid Build Coastguard Worker } 102*bb4ee6a4SAndroid Build Coastguard Worker } 103*bb4ee6a4SAndroid Build Coastguard Worker 104*bb4ee6a4SAndroid Build Coastguard Worker impl Params { to_virtio_video_params(&self, queue_type: QueueType) -> virtio_video_params105*bb4ee6a4SAndroid Build Coastguard Worker pub fn to_virtio_video_params(&self, queue_type: QueueType) -> virtio_video_params { 106*bb4ee6a4SAndroid Build Coastguard Worker let Params { 107*bb4ee6a4SAndroid Build Coastguard Worker format, 108*bb4ee6a4SAndroid Build Coastguard Worker resource_type: _, 109*bb4ee6a4SAndroid Build Coastguard Worker frame_width, 110*bb4ee6a4SAndroid Build Coastguard Worker frame_height, 111*bb4ee6a4SAndroid Build Coastguard Worker min_buffers, 112*bb4ee6a4SAndroid Build Coastguard Worker max_buffers, 113*bb4ee6a4SAndroid Build Coastguard Worker crop, 114*bb4ee6a4SAndroid Build Coastguard Worker frame_rate, 115*bb4ee6a4SAndroid Build Coastguard Worker plane_formats, 116*bb4ee6a4SAndroid Build Coastguard Worker } = self; 117*bb4ee6a4SAndroid Build Coastguard Worker let num_planes = Le32::from(plane_formats.len() as u32); 118*bb4ee6a4SAndroid Build Coastguard Worker let mut p_fmts: [virtio_video_plane_format; VIRTIO_VIDEO_MAX_PLANES as usize] = 119*bb4ee6a4SAndroid Build Coastguard Worker Default::default(); 120*bb4ee6a4SAndroid Build Coastguard Worker for (i, pf) in plane_formats.iter().enumerate() { 121*bb4ee6a4SAndroid Build Coastguard Worker p_fmts[i] = Into::<virtio_video_plane_format>::into(*pf); 122*bb4ee6a4SAndroid Build Coastguard Worker } 123*bb4ee6a4SAndroid Build Coastguard Worker 124*bb4ee6a4SAndroid Build Coastguard Worker virtio_video_params { 125*bb4ee6a4SAndroid Build Coastguard Worker queue_type: (queue_type as u32).into(), 126*bb4ee6a4SAndroid Build Coastguard Worker format: format 127*bb4ee6a4SAndroid Build Coastguard Worker .map(|f| Le32::from(f as u32)) 128*bb4ee6a4SAndroid Build Coastguard Worker .unwrap_or_else(|| Le32::from(0)), 129*bb4ee6a4SAndroid Build Coastguard Worker frame_width: Le32::from(*frame_width), 130*bb4ee6a4SAndroid Build Coastguard Worker frame_height: Le32::from(*frame_height), 131*bb4ee6a4SAndroid Build Coastguard Worker min_buffers: Le32::from(*min_buffers), 132*bb4ee6a4SAndroid Build Coastguard Worker max_buffers: Le32::from(*max_buffers), 133*bb4ee6a4SAndroid Build Coastguard Worker crop: virtio_video_crop::from(*crop), 134*bb4ee6a4SAndroid Build Coastguard Worker frame_rate: Le32::from(*frame_rate), 135*bb4ee6a4SAndroid Build Coastguard Worker num_planes, 136*bb4ee6a4SAndroid Build Coastguard Worker plane_formats: p_fmts, 137*bb4ee6a4SAndroid Build Coastguard Worker } 138*bb4ee6a4SAndroid Build Coastguard Worker } 139*bb4ee6a4SAndroid Build Coastguard Worker to_virtio_video_params_ext(&self, queue_type: QueueType) -> virtio_video_params_ext140*bb4ee6a4SAndroid Build Coastguard Worker pub fn to_virtio_video_params_ext(&self, queue_type: QueueType) -> virtio_video_params_ext { 141*bb4ee6a4SAndroid Build Coastguard Worker let Params { resource_type, .. } = self; 142*bb4ee6a4SAndroid Build Coastguard Worker 143*bb4ee6a4SAndroid Build Coastguard Worker let resource_type = match *resource_type { 144*bb4ee6a4SAndroid Build Coastguard Worker ResourceType::GuestPages => VIRTIO_VIDEO_MEM_TYPE_GUEST_PAGES, 145*bb4ee6a4SAndroid Build Coastguard Worker ResourceType::VirtioObject => VIRTIO_VIDEO_MEM_TYPE_VIRTIO_OBJECT, 146*bb4ee6a4SAndroid Build Coastguard Worker }; 147*bb4ee6a4SAndroid Build Coastguard Worker 148*bb4ee6a4SAndroid Build Coastguard Worker virtio_video_params_ext { 149*bb4ee6a4SAndroid Build Coastguard Worker base: self.to_virtio_video_params(queue_type), 150*bb4ee6a4SAndroid Build Coastguard Worker resource_type: Le32::from(resource_type), 151*bb4ee6a4SAndroid Build Coastguard Worker padding: Default::default(), 152*bb4ee6a4SAndroid Build Coastguard Worker } 153*bb4ee6a4SAndroid Build Coastguard Worker } 154*bb4ee6a4SAndroid Build Coastguard Worker } 155