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