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