xref: /aosp_15_r20/external/crosvm/devices/src/virtio/video/params.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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 
7 use std::convert::From;
8 use std::convert::Into;
9 use std::convert::TryFrom;
10 
11 use base::error;
12 use data_model::Le32;
13 
14 use crate::virtio::video::command::QueueType;
15 use crate::virtio::video::command::ReadCmdError;
16 use crate::virtio::video::format::*;
17 use crate::virtio::video::protocol::*;
18 use 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)]
24 pub 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 
38 impl 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 
83 impl 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 
104 impl Params {
to_virtio_video_params(&self, queue_type: QueueType) -> virtio_video_params105     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 
to_virtio_video_params_ext(&self, queue_type: QueueType) -> virtio_video_params_ext140     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 }
155