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