summary refs log tree commit diff
path: root/devices/src/virtio/video/params.rs
blob: e4bb614a2a2246a62bebb9e9c9f2d2e7a0f23468 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
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,
        }
    }
}