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