diff options
Diffstat (limited to 'devices/src/virtio/video/params.rs')
-rw-r--r-- | devices/src/virtio/video/params.rs | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/devices/src/virtio/video/params.rs b/devices/src/virtio/video/params.rs new file mode 100644 index 0000000..e4bb614 --- /dev/null +++ b/devices/src/virtio/video/params.rs @@ -0,0 +1,111 @@ +// 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<Format>` instead of `Format` because an image format may not be determined until + // video decoding is started in the decoder. + pub format: Option<Format>, + 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<PlaneFormat>, +} + +impl TryFrom<virtio_video_params> 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<Self, Self::Error> { + let num_planes = Into::<u32>::into(num_planes); // as usize; + if num_planes as usize > plane_formats.len() { + error!( + "num_planes must not exceed {} but {}", + plane_formats.len(), + Into::<u32>::into(num_planes) + ); + return Err(ReadCmdError::InvalidArgument); + } + let plane_formats = plane_formats[0..num_planes as usize] + .iter() + .map(|x| Into::<PlaneFormat>::into(*x)) + .collect::<Vec<_>>(); + + 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::<virtio_video_plane_format>::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, + } + } +} |