devices/virtio/video/
params.rs

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
7use std::convert::From;
8use std::convert::Into;
9use std::convert::TryFrom;
10
11use base::error;
12use data_model::Le32;
13
14use crate::virtio::video::command::QueueType;
15use crate::virtio::video::command::ReadCmdError;
16use crate::virtio::video::format::*;
17use crate::virtio::video::protocol::*;
18use 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)]
24pub 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
38impl 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
83impl 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
104impl Params {
105    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
140    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}