xref: /aosp_15_r20/external/crosvm/devices/src/virtio/video/params.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2020 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker //! Parameters for streams in virtio video devices.
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker use std::convert::From;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::convert::Into;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::convert::TryFrom;
10*bb4ee6a4SAndroid Build Coastguard Worker 
11*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
12*bb4ee6a4SAndroid Build Coastguard Worker use data_model::Le32;
13*bb4ee6a4SAndroid Build Coastguard Worker 
14*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::video::command::QueueType;
15*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::video::command::ReadCmdError;
16*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::video::format::*;
17*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::video::protocol::*;
18*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::video::resource::ResourceType;
19*bb4ee6a4SAndroid Build Coastguard Worker 
20*bb4ee6a4SAndroid Build Coastguard Worker /// Safe wrapper of `virtio_video_params`.
21*bb4ee6a4SAndroid Build Coastguard Worker /// Note that this struct doesn't have a field corresponding to `queue_type` in
22*bb4ee6a4SAndroid Build Coastguard Worker /// `virtio_video_params`. The type of queue should be stored by one that has an `Params` instance.
23*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Default, Clone)]
24*bb4ee6a4SAndroid Build Coastguard Worker pub struct Params {
25*bb4ee6a4SAndroid Build Coastguard Worker     // Use `Option<Format>` instead of `Format` because an image format may not be determined until
26*bb4ee6a4SAndroid Build Coastguard Worker     // video decoding is started in the decoder.
27*bb4ee6a4SAndroid Build Coastguard Worker     pub format: Option<Format>,
28*bb4ee6a4SAndroid Build Coastguard Worker     pub resource_type: ResourceType,
29*bb4ee6a4SAndroid Build Coastguard Worker     pub frame_width: u32,
30*bb4ee6a4SAndroid Build Coastguard Worker     pub frame_height: u32,
31*bb4ee6a4SAndroid Build Coastguard Worker     pub min_buffers: u32,
32*bb4ee6a4SAndroid Build Coastguard Worker     pub max_buffers: u32,
33*bb4ee6a4SAndroid Build Coastguard Worker     pub crop: Crop,
34*bb4ee6a4SAndroid Build Coastguard Worker     pub frame_rate: u32,
35*bb4ee6a4SAndroid Build Coastguard Worker     pub plane_formats: Vec<PlaneFormat>,
36*bb4ee6a4SAndroid Build Coastguard Worker }
37*bb4ee6a4SAndroid Build Coastguard Worker 
38*bb4ee6a4SAndroid Build Coastguard Worker impl TryFrom<virtio_video_params> for Params {
39*bb4ee6a4SAndroid Build Coastguard Worker     type Error = ReadCmdError;
40*bb4ee6a4SAndroid Build Coastguard Worker 
41*bb4ee6a4SAndroid Build Coastguard Worker     fn try_from(
42*bb4ee6a4SAndroid Build Coastguard Worker         virtio_video_params {
43*bb4ee6a4SAndroid Build Coastguard Worker             format,
44*bb4ee6a4SAndroid Build Coastguard Worker             frame_width,
45*bb4ee6a4SAndroid Build Coastguard Worker             frame_height,
46*bb4ee6a4SAndroid Build Coastguard Worker             min_buffers,
47*bb4ee6a4SAndroid Build Coastguard Worker             max_buffers,
48*bb4ee6a4SAndroid Build Coastguard Worker             crop,
49*bb4ee6a4SAndroid Build Coastguard Worker             frame_rate,
50*bb4ee6a4SAndroid Build Coastguard Worker             num_planes,
51*bb4ee6a4SAndroid Build Coastguard Worker             plane_formats,
52*bb4ee6a4SAndroid Build Coastguard Worker             ..
53*bb4ee6a4SAndroid Build Coastguard Worker         }: virtio_video_params,
54*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<Self, Self::Error> {
55*bb4ee6a4SAndroid Build Coastguard Worker         let num_planes = Into::<u32>::into(num_planes); // as usize;
56*bb4ee6a4SAndroid Build Coastguard Worker         if num_planes as usize > plane_formats.len() {
57*bb4ee6a4SAndroid Build Coastguard Worker             error!(
58*bb4ee6a4SAndroid Build Coastguard Worker                 "num_planes must not exceed {} but {}",
59*bb4ee6a4SAndroid Build Coastguard Worker                 plane_formats.len(),
60*bb4ee6a4SAndroid Build Coastguard Worker                 Into::<u32>::into(num_planes)
61*bb4ee6a4SAndroid Build Coastguard Worker             );
62*bb4ee6a4SAndroid Build Coastguard Worker             return Err(ReadCmdError::InvalidArgument);
63*bb4ee6a4SAndroid Build Coastguard Worker         }
64*bb4ee6a4SAndroid Build Coastguard Worker         let plane_formats = plane_formats[0..num_planes as usize]
65*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
66*bb4ee6a4SAndroid Build Coastguard Worker             .map(|x| Into::<PlaneFormat>::into(*x))
67*bb4ee6a4SAndroid Build Coastguard Worker             .collect::<Vec<_>>();
68*bb4ee6a4SAndroid Build Coastguard Worker 
69*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Params {
70*bb4ee6a4SAndroid Build Coastguard Worker             format: Format::n(format.into()),
71*bb4ee6a4SAndroid Build Coastguard Worker             resource_type: Default::default(),
72*bb4ee6a4SAndroid Build Coastguard Worker             frame_width: frame_width.into(),
73*bb4ee6a4SAndroid Build Coastguard Worker             frame_height: frame_height.into(),
74*bb4ee6a4SAndroid Build Coastguard Worker             min_buffers: min_buffers.into(),
75*bb4ee6a4SAndroid Build Coastguard Worker             max_buffers: max_buffers.into(),
76*bb4ee6a4SAndroid Build Coastguard Worker             crop: crop.into(),
77*bb4ee6a4SAndroid Build Coastguard Worker             frame_rate: frame_rate.into(),
78*bb4ee6a4SAndroid Build Coastguard Worker             plane_formats,
79*bb4ee6a4SAndroid Build Coastguard Worker         })
80*bb4ee6a4SAndroid Build Coastguard Worker     }
81*bb4ee6a4SAndroid Build Coastguard Worker }
82*bb4ee6a4SAndroid Build Coastguard Worker 
83*bb4ee6a4SAndroid Build Coastguard Worker impl TryFrom<virtio_video_params_ext> for Params {
84*bb4ee6a4SAndroid Build Coastguard Worker     type Error = ReadCmdError;
85*bb4ee6a4SAndroid Build Coastguard Worker 
86*bb4ee6a4SAndroid Build Coastguard Worker     fn try_from(
87*bb4ee6a4SAndroid Build Coastguard Worker         virtio_video_params_ext {
88*bb4ee6a4SAndroid Build Coastguard Worker             base,
89*bb4ee6a4SAndroid Build Coastguard Worker             resource_type,
90*bb4ee6a4SAndroid Build Coastguard Worker             ..
91*bb4ee6a4SAndroid Build Coastguard Worker         }: virtio_video_params_ext,
92*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<Self, Self::Error> {
93*bb4ee6a4SAndroid Build Coastguard Worker         let mut params = Params::try_from(base)?;
94*bb4ee6a4SAndroid Build Coastguard Worker         params.resource_type = match resource_type.into() {
95*bb4ee6a4SAndroid Build Coastguard Worker             VIRTIO_VIDEO_MEM_TYPE_GUEST_PAGES => ResourceType::GuestPages,
96*bb4ee6a4SAndroid Build Coastguard Worker             VIRTIO_VIDEO_MEM_TYPE_VIRTIO_OBJECT => ResourceType::VirtioObject,
97*bb4ee6a4SAndroid Build Coastguard Worker             _ => return Err(ReadCmdError::InvalidArgument),
98*bb4ee6a4SAndroid Build Coastguard Worker         };
99*bb4ee6a4SAndroid Build Coastguard Worker 
100*bb4ee6a4SAndroid Build Coastguard Worker         Ok(params)
101*bb4ee6a4SAndroid Build Coastguard Worker     }
102*bb4ee6a4SAndroid Build Coastguard Worker }
103*bb4ee6a4SAndroid Build Coastguard Worker 
104*bb4ee6a4SAndroid Build Coastguard Worker impl Params {
to_virtio_video_params(&self, queue_type: QueueType) -> virtio_video_params105*bb4ee6a4SAndroid Build Coastguard Worker     pub fn to_virtio_video_params(&self, queue_type: QueueType) -> virtio_video_params {
106*bb4ee6a4SAndroid Build Coastguard Worker         let Params {
107*bb4ee6a4SAndroid Build Coastguard Worker             format,
108*bb4ee6a4SAndroid Build Coastguard Worker             resource_type: _,
109*bb4ee6a4SAndroid Build Coastguard Worker             frame_width,
110*bb4ee6a4SAndroid Build Coastguard Worker             frame_height,
111*bb4ee6a4SAndroid Build Coastguard Worker             min_buffers,
112*bb4ee6a4SAndroid Build Coastguard Worker             max_buffers,
113*bb4ee6a4SAndroid Build Coastguard Worker             crop,
114*bb4ee6a4SAndroid Build Coastguard Worker             frame_rate,
115*bb4ee6a4SAndroid Build Coastguard Worker             plane_formats,
116*bb4ee6a4SAndroid Build Coastguard Worker         } = self;
117*bb4ee6a4SAndroid Build Coastguard Worker         let num_planes = Le32::from(plane_formats.len() as u32);
118*bb4ee6a4SAndroid Build Coastguard Worker         let mut p_fmts: [virtio_video_plane_format; VIRTIO_VIDEO_MAX_PLANES as usize] =
119*bb4ee6a4SAndroid Build Coastguard Worker             Default::default();
120*bb4ee6a4SAndroid Build Coastguard Worker         for (i, pf) in plane_formats.iter().enumerate() {
121*bb4ee6a4SAndroid Build Coastguard Worker             p_fmts[i] = Into::<virtio_video_plane_format>::into(*pf);
122*bb4ee6a4SAndroid Build Coastguard Worker         }
123*bb4ee6a4SAndroid Build Coastguard Worker 
124*bb4ee6a4SAndroid Build Coastguard Worker         virtio_video_params {
125*bb4ee6a4SAndroid Build Coastguard Worker             queue_type: (queue_type as u32).into(),
126*bb4ee6a4SAndroid Build Coastguard Worker             format: format
127*bb4ee6a4SAndroid Build Coastguard Worker                 .map(|f| Le32::from(f as u32))
128*bb4ee6a4SAndroid Build Coastguard Worker                 .unwrap_or_else(|| Le32::from(0)),
129*bb4ee6a4SAndroid Build Coastguard Worker             frame_width: Le32::from(*frame_width),
130*bb4ee6a4SAndroid Build Coastguard Worker             frame_height: Le32::from(*frame_height),
131*bb4ee6a4SAndroid Build Coastguard Worker             min_buffers: Le32::from(*min_buffers),
132*bb4ee6a4SAndroid Build Coastguard Worker             max_buffers: Le32::from(*max_buffers),
133*bb4ee6a4SAndroid Build Coastguard Worker             crop: virtio_video_crop::from(*crop),
134*bb4ee6a4SAndroid Build Coastguard Worker             frame_rate: Le32::from(*frame_rate),
135*bb4ee6a4SAndroid Build Coastguard Worker             num_planes,
136*bb4ee6a4SAndroid Build Coastguard Worker             plane_formats: p_fmts,
137*bb4ee6a4SAndroid Build Coastguard Worker         }
138*bb4ee6a4SAndroid Build Coastguard Worker     }
139*bb4ee6a4SAndroid Build Coastguard Worker 
to_virtio_video_params_ext(&self, queue_type: QueueType) -> virtio_video_params_ext140*bb4ee6a4SAndroid Build Coastguard Worker     pub fn to_virtio_video_params_ext(&self, queue_type: QueueType) -> virtio_video_params_ext {
141*bb4ee6a4SAndroid Build Coastguard Worker         let Params { resource_type, .. } = self;
142*bb4ee6a4SAndroid Build Coastguard Worker 
143*bb4ee6a4SAndroid Build Coastguard Worker         let resource_type = match *resource_type {
144*bb4ee6a4SAndroid Build Coastguard Worker             ResourceType::GuestPages => VIRTIO_VIDEO_MEM_TYPE_GUEST_PAGES,
145*bb4ee6a4SAndroid Build Coastguard Worker             ResourceType::VirtioObject => VIRTIO_VIDEO_MEM_TYPE_VIRTIO_OBJECT,
146*bb4ee6a4SAndroid Build Coastguard Worker         };
147*bb4ee6a4SAndroid Build Coastguard Worker 
148*bb4ee6a4SAndroid Build Coastguard Worker         virtio_video_params_ext {
149*bb4ee6a4SAndroid Build Coastguard Worker             base: self.to_virtio_video_params(queue_type),
150*bb4ee6a4SAndroid Build Coastguard Worker             resource_type: Le32::from(resource_type),
151*bb4ee6a4SAndroid Build Coastguard Worker             padding: Default::default(),
152*bb4ee6a4SAndroid Build Coastguard Worker         }
153*bb4ee6a4SAndroid Build Coastguard Worker     }
154*bb4ee6a4SAndroid Build Coastguard Worker }
155