// Copyright 2020 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. //! Parameters for streams in virtio video devices. use std::convert::{From, Into, TryFrom}; use data_model::Le32; use sys_util::error; use crate::virtio::video::command::{QueueType, ReadCmdError}; use crate::virtio::video::format::*; use crate::virtio::video::protocol::*; /// Safe wrapper of `virtio_video_params`. /// Note that this struct doesn't have a field corresponding to `queue_type` in /// `virtio_video_params`. The type of queue should be stored by one that has an `Params` instance. #[derive(Debug, Default, Clone)] pub struct Params { // Use `Option` instead of `Format` because an image format may not be determined until // video decoding is started in the decoder. pub format: Option, pub frame_width: u32, pub frame_height: u32, pub min_buffers: u32, pub max_buffers: u32, pub crop: Crop, pub frame_rate: u32, pub plane_formats: Vec, } impl TryFrom for Params { type Error = ReadCmdError; fn try_from( virtio_video_params { format, frame_width, frame_height, min_buffers, max_buffers, crop, frame_rate, num_planes, plane_formats, .. }: virtio_video_params, ) -> Result { let num_planes = Into::::into(num_planes); // as usize; if num_planes as usize > plane_formats.len() { error!( "num_planes must not exceed {} but {}", plane_formats.len(), Into::::into(num_planes) ); return Err(ReadCmdError::InvalidArgument); } let plane_formats = plane_formats[0..num_planes as usize] .iter() .map(|x| Into::::into(*x)) .collect::>(); Ok(Params { format: Format::n(format.into()), frame_width: frame_width.into(), frame_height: frame_height.into(), min_buffers: min_buffers.into(), max_buffers: max_buffers.into(), crop: crop.into(), frame_rate: frame_rate.into(), plane_formats, }) } } impl Params { pub fn to_virtio_video_params(&self, queue_type: QueueType) -> virtio_video_params { let Params { format, frame_width, frame_height, min_buffers, max_buffers, crop, frame_rate, plane_formats, } = self; let num_planes = Le32::from(plane_formats.len() as u32); let mut p_fmts: [virtio_video_plane_format; VIRTIO_VIDEO_MAX_PLANES as usize] = Default::default(); for (i, pf) in plane_formats.iter().enumerate() { p_fmts[i] = Into::::into(*pf); } virtio_video_params { queue_type: (queue_type as u32).into(), format: format .map(|f| Le32::from(f as u32)) .unwrap_or_else(|| Le32::from(0)), frame_width: Le32::from(*frame_width), frame_height: Le32::from(*frame_height), min_buffers: Le32::from(*min_buffers), max_buffers: Le32::from(*max_buffers), crop: virtio_video_crop::from(*crop), frame_rate: Le32::from(*frame_rate), num_planes, plane_formats: p_fmts, } } }