• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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