• 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 use std::collections::BTreeMap;
6 use std::fs::File;
7 
8 use base::error;
9 
10 use crate::virtio::video::format::{
11     find_closest_resolution, Format, FormatDesc, Level, PlaneFormat, Profile,
12 };
13 use crate::virtio::video::params::Params;
14 
15 pub type Result<T> = std::result::Result<T, EncoderError>;
16 
17 #[derive(Debug)]
18 pub enum EncoderError {
19     // Invalid argument.
20     InvalidArgument,
21     // Platform failure.
22     PlatformFailure,
23     // Implementation specific error.
24     Implementation(Box<dyn std::error::Error + Send>),
25 }
26 
27 impl std::fmt::Display for EncoderError {
fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result28     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
29         use self::EncoderError::*;
30         match self {
31             InvalidArgument => write!(f, "invalid argument"),
32             PlatformFailure => write!(f, "platform failure"),
33             Implementation(e) => write!(f, "implementation error: {}", e),
34         }
35     }
36 }
37 
38 impl std::error::Error for EncoderError {}
39 
40 pub type InputBufferId = u32;
41 pub type OutputBufferId = u32;
42 
43 #[derive(Debug)]
44 pub enum EncoderEvent {
45     RequireInputBuffers {
46         input_count: u32,
47         input_frame_width: u32,
48         input_frame_height: u32,
49         output_buffer_size: u32,
50     },
51     ProcessedInputBuffer {
52         id: InputBufferId,
53     },
54     ProcessedOutputBuffer {
55         id: OutputBufferId,
56         bytesused: u32,
57         keyframe: bool,
58         timestamp: u64,
59     },
60     FlushResponse {
61         flush_done: bool,
62     },
63     NotifyError {
64         error: EncoderError,
65     },
66 }
67 
68 #[derive(Debug)]
69 pub struct SessionConfig {
70     pub src_params: Params,
71     pub dst_params: Params,
72     pub dst_profile: Profile,
73     pub dst_bitrate: u32,
74     pub dst_h264_level: Option<Level>,
75     pub frame_rate: u32,
76 }
77 
78 #[derive(Debug)]
79 pub struct VideoFramePlane {
80     pub offset: usize,
81     pub stride: usize,
82 }
83 
84 pub trait EncoderSession {
85     /// Encodes the frame provided by `resource`, with planes specified by `plane`.
86     /// `force_keyframe` forces the frame to be encoded as a keyframe.
87     /// When the buffer has been successfully processed, a `ProcessedInputBuffer` event will
88     /// be readable from the event pipe, with the same `InputBufferId` as returned by this
89     /// function.
90     /// When the corresponding encoded data is ready, `ProcessedOutputBuffer` events will be
91     /// readable from the event pipe, with the same timestamp as provided `timestamp`.
encode( &mut self, resource: File, planes: &[VideoFramePlane], timestamp: u64, force_keyframe: bool, ) -> Result<InputBufferId>92     fn encode(
93         &mut self,
94         resource: File,
95         planes: &[VideoFramePlane],
96         timestamp: u64,
97         force_keyframe: bool,
98     ) -> Result<InputBufferId>;
99 
100     /// Provides an output buffer `file` to store encoded output, where `offset` and `size`
101     /// define the region of memory to use.
102     /// When the buffer has been filled with encoded output, a `ProcessedOutputBuffer` event
103     /// will be readable from the event pipe, with the same `OutputBufferId` as returned by this
104     /// function.
use_output_buffer(&mut self, file: File, offset: u32, size: u32) -> Result<OutputBufferId>105     fn use_output_buffer(&mut self, file: File, offset: u32, size: u32) -> Result<OutputBufferId>;
106 
107     /// Requests the encoder to flush. When completed, an `EncoderEvent::FlushResponse` event will
108     /// be readable from the event pipe.
flush(&mut self) -> Result<()>109     fn flush(&mut self) -> Result<()>;
110 
111     /// Requests the encoder to use new encoding parameters provided by `bitrate` and `framerate`.
request_encoding_params_change(&mut self, bitrate: u32, framerate: u32) -> Result<()>112     fn request_encoding_params_change(&mut self, bitrate: u32, framerate: u32) -> Result<()>;
113 
114     /// Returns the event pipe as a pollable file descriptor. When the file descriptor is
115     /// readable, an event can be read by `read_event`.
event_pipe(&self) -> &File116     fn event_pipe(&self) -> &File;
117 
118     /// Performs a blocking read for an encoder event. This function should only be called when
119     /// the file descriptor returned by `event_pipe` is readable.
read_event(&mut self) -> Result<EncoderEvent>120     fn read_event(&mut self) -> Result<EncoderEvent>;
121 }
122 
123 #[derive(Clone)]
124 pub struct EncoderCapabilities {
125     pub input_format_descs: Vec<FormatDesc>,
126     pub output_format_descs: Vec<FormatDesc>,
127     pub coded_format_profiles: BTreeMap<Format, Vec<Profile>>,
128 }
129 
130 impl EncoderCapabilities {
populate_src_params( &self, src_params: &mut Params, desired_format: Format, desired_width: u32, desired_height: u32, mut stride: u32, ) -> Result<()>131     pub fn populate_src_params(
132         &self,
133         src_params: &mut Params,
134         desired_format: Format,
135         desired_width: u32,
136         desired_height: u32,
137         mut stride: u32,
138     ) -> Result<()> {
139         let format_desc = self
140             .input_format_descs
141             .iter()
142             .find(|&format_desc| format_desc.format == desired_format)
143             .unwrap_or(
144                 self.input_format_descs
145                     .get(0)
146                     .ok_or(EncoderError::PlatformFailure)?,
147             );
148 
149         let (allowed_width, allowed_height) =
150             find_closest_resolution(&format_desc.frame_formats, desired_width, desired_height);
151 
152         if stride == 0 {
153             stride = allowed_width;
154         }
155 
156         let plane_formats = match format_desc.format {
157             Format::NV12 => {
158                 let y_plane = PlaneFormat {
159                     plane_size: stride * allowed_height,
160                     stride,
161                 };
162                 let crcb_plane = PlaneFormat {
163                     plane_size: y_plane.plane_size / 2,
164                     stride,
165                 };
166                 vec![y_plane, crcb_plane]
167             }
168             _ => {
169                 return Err(EncoderError::PlatformFailure);
170             }
171         };
172 
173         src_params.frame_width = allowed_width;
174         src_params.frame_height = allowed_height;
175         src_params.format = Some(format_desc.format.clone());
176         src_params.plane_formats = plane_formats;
177         Ok(())
178     }
179 
populate_dst_params( &self, dst_params: &mut Params, desired_format: Format, buffer_size: u32, ) -> Result<()>180     pub fn populate_dst_params(
181         &self,
182         dst_params: &mut Params,
183         desired_format: Format,
184         buffer_size: u32,
185     ) -> Result<()> {
186         // TODO(alexlau): Should the first be the default?
187         let format_desc = self
188             .output_format_descs
189             .iter()
190             .find(move |&format_desc| format_desc.format == desired_format)
191             .unwrap_or(
192                 self.output_format_descs
193                     .get(0)
194                     .ok_or(EncoderError::PlatformFailure)?,
195             );
196         dst_params.format = Some(format_desc.format.clone());
197 
198         // The requested output buffer size might be adjusted by the encoder to match hardware
199         // requirements in RequireInputBuffers.
200         dst_params.plane_formats = vec![PlaneFormat {
201             plane_size: buffer_size,
202             stride: 0,
203         }];
204         Ok(())
205     }
206 
get_profiles(&self, coded_format: &Format) -> Option<&Vec<Profile>>207     pub fn get_profiles(&self, coded_format: &Format) -> Option<&Vec<Profile>> {
208         self.coded_format_profiles.get(coded_format)
209     }
210 
get_default_profile(&self, coded_format: &Format) -> Option<Profile>211     pub fn get_default_profile(&self, coded_format: &Format) -> Option<Profile> {
212         let profiles = self.get_profiles(coded_format)?;
213         match profiles.get(0) {
214             None => {
215                 error!("Format {} exists but no available profiles.", coded_format);
216                 None
217             }
218             Some(profile) => Some(*profile),
219         }
220     }
221 }
222 
223 pub trait Encoder {
224     type Session: EncoderSession;
225 
query_capabilities(&self) -> Result<EncoderCapabilities>226     fn query_capabilities(&self) -> Result<EncoderCapabilities>;
start_session(&mut self, config: SessionConfig) -> Result<Self::Session>227     fn start_session(&mut self, config: SessionConfig) -> Result<Self::Session>;
stop_session(&mut self, session: Self::Session) -> Result<()>228     fn stop_session(&mut self, session: Self::Session) -> Result<()>;
229 }
230