• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 use std::collections::BTreeMap;
6 
7 use base::error;
8 
9 use crate::virtio::video::error::VideoError;
10 use crate::virtio::video::error::VideoResult;
11 use crate::virtio::video::format::find_closest_resolution;
12 use crate::virtio::video::format::Bitrate;
13 use crate::virtio::video::format::Format;
14 use crate::virtio::video::format::FormatDesc;
15 use crate::virtio::video::format::Level;
16 use crate::virtio::video::format::PlaneFormat;
17 use crate::virtio::video::format::Profile;
18 use crate::virtio::video::params::Params;
19 
20 pub type InputBufferId = u32;
21 pub type OutputBufferId = u32;
22 
23 #[derive(Debug)]
24 pub enum EncoderEvent {
25     RequireInputBuffers {
26         input_count: u32,
27         input_frame_width: u32,
28         input_frame_height: u32,
29         output_buffer_size: u32,
30     },
31     ProcessedInputBuffer {
32         id: InputBufferId,
33     },
34     ProcessedOutputBuffer {
35         id: OutputBufferId,
36         bytesused: u32,
37         keyframe: bool,
38         timestamp: u64,
39     },
40     FlushResponse {
41         flush_done: bool,
42     },
43     #[allow(dead_code)]
44     NotifyError {
45         error: VideoError,
46     },
47 }
48 
49 #[derive(Debug)]
50 pub struct SessionConfig {
51     pub src_params: Params,
52     pub dst_params: Params,
53     pub dst_profile: Profile,
54     pub dst_bitrate: Bitrate,
55     pub dst_h264_level: Option<Level>,
56     pub frame_rate: u32,
57 }
58 
59 #[derive(Clone)]
60 pub struct EncoderCapabilities {
61     pub input_format_descs: Vec<FormatDesc>,
62     pub output_format_descs: Vec<FormatDesc>,
63     pub coded_format_profiles: BTreeMap<Format, Vec<Profile>>,
64 }
65 
66 impl EncoderCapabilities {
populate_src_params( &self, src_params: &mut Params, desired_format: Format, desired_width: u32, desired_height: u32, mut stride: u32, ) -> VideoResult<()>67     pub fn populate_src_params(
68         &self,
69         src_params: &mut Params,
70         desired_format: Format,
71         desired_width: u32,
72         desired_height: u32,
73         mut stride: u32,
74     ) -> VideoResult<()> {
75         let format_desc = self
76             .input_format_descs
77             .iter()
78             .find(|&format_desc| format_desc.format == desired_format)
79             .unwrap_or(
80                 self.input_format_descs
81                     .get(0)
82                     .ok_or(VideoError::InvalidFormat)?,
83             );
84 
85         let (allowed_width, allowed_height) =
86             find_closest_resolution(&format_desc.frame_formats, desired_width, desired_height);
87 
88         if stride == 0 {
89             stride = allowed_width;
90         }
91 
92         let plane_formats =
93             PlaneFormat::get_plane_layout(format_desc.format, stride, allowed_height)
94                 .ok_or(VideoError::InvalidFormat)?;
95 
96         src_params.frame_width = allowed_width;
97         src_params.frame_height = allowed_height;
98         src_params.format = Some(format_desc.format);
99         src_params.plane_formats = plane_formats;
100         Ok(())
101     }
102 
populate_dst_params( &self, dst_params: &mut Params, desired_format: Format, buffer_size: u32, ) -> VideoResult<()>103     pub fn populate_dst_params(
104         &self,
105         dst_params: &mut Params,
106         desired_format: Format,
107         buffer_size: u32,
108     ) -> VideoResult<()> {
109         // TODO(alexlau): Should the first be the default?
110         let format_desc = self
111             .output_format_descs
112             .iter()
113             .find(move |&format_desc| format_desc.format == desired_format)
114             .unwrap_or(
115                 self.output_format_descs
116                     .get(0)
117                     .ok_or(VideoError::InvalidFormat)?,
118             );
119         dst_params.format = Some(format_desc.format);
120 
121         // The requested output buffer size might be adjusted by the encoder to match hardware
122         // requirements in RequireInputBuffers.
123         dst_params.plane_formats = vec![PlaneFormat {
124             plane_size: buffer_size,
125             stride: 0,
126         }];
127         Ok(())
128     }
129 
get_profiles(&self, coded_format: &Format) -> Option<&Vec<Profile>>130     pub fn get_profiles(&self, coded_format: &Format) -> Option<&Vec<Profile>> {
131         self.coded_format_profiles.get(coded_format)
132     }
133 
get_default_profile(&self, coded_format: &Format) -> Option<Profile>134     pub fn get_default_profile(&self, coded_format: &Format) -> Option<Profile> {
135         let profiles = self.get_profiles(coded_format)?;
136         match profiles.get(0) {
137             None => {
138                 error!("Format {} exists but no available profiles.", coded_format);
139                 None
140             }
141             Some(profile) => Some(*profile),
142         }
143     }
144 }
145