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 base::{error, RawDescriptor}; 6 use std::convert::TryFrom; 7 8 use libvda::decode::Event as LibvdaEvent; 9 10 use crate::virtio::video::{ 11 decoder::backend::*, 12 error::{VideoError, VideoResult}, 13 format::{Format, Rect}, 14 }; 15 16 impl TryFrom<Format> for libvda::Profile { 17 type Error = VideoError; 18 try_from(format: Format) -> Result<Self, Self::Error>19 fn try_from(format: Format) -> Result<Self, Self::Error> { 20 Ok(match format { 21 Format::VP8 => libvda::Profile::VP8, 22 Format::VP9 => libvda::Profile::VP9Profile0, 23 Format::H264 => libvda::Profile::H264ProfileBaseline, 24 _ => { 25 error!("specified format {} is not supported by VDA", format); 26 return Err(VideoError::InvalidParameter); 27 } 28 }) 29 } 30 } 31 32 impl TryFrom<Format> for libvda::PixelFormat { 33 type Error = VideoError; 34 try_from(format: Format) -> Result<Self, Self::Error>35 fn try_from(format: Format) -> Result<Self, Self::Error> { 36 Ok(match format { 37 Format::NV12 => libvda::PixelFormat::NV12, 38 _ => { 39 error!("specified format {} is not supported by VDA", format); 40 return Err(VideoError::InvalidParameter); 41 } 42 }) 43 } 44 } 45 46 impl From<&FramePlane> for libvda::FramePlane { from(plane: &FramePlane) -> Self47 fn from(plane: &FramePlane) -> Self { 48 libvda::FramePlane { 49 offset: plane.offset, 50 stride: plane.stride, 51 } 52 } 53 } 54 55 impl From<libvda::decode::Event> for DecoderEvent { from(event: libvda::decode::Event) -> Self56 fn from(event: libvda::decode::Event) -> Self { 57 // We cannot use the From trait here since neither libvda::decode::Response 58 // no std::result::Result are defined in the current crate. 59 fn vda_response_to_result(resp: libvda::decode::Response) -> VideoResult<()> { 60 match resp { 61 libvda::decode::Response::Success => Ok(()), 62 resp => Err(VideoError::VdaFailure(resp)), 63 } 64 } 65 66 match event { 67 LibvdaEvent::ProvidePictureBuffers { 68 min_num_buffers, 69 width, 70 height, 71 visible_rect_left, 72 visible_rect_top, 73 visible_rect_right, 74 visible_rect_bottom, 75 } => DecoderEvent::ProvidePictureBuffers { 76 min_num_buffers, 77 width, 78 height, 79 visible_rect: Rect { 80 left: visible_rect_left, 81 top: visible_rect_top, 82 right: visible_rect_right, 83 bottom: visible_rect_bottom, 84 }, 85 }, 86 LibvdaEvent::PictureReady { 87 buffer_id, 88 bitstream_id, 89 left, 90 top, 91 right, 92 bottom, 93 } => DecoderEvent::PictureReady { 94 picture_buffer_id: buffer_id, 95 bitstream_id, 96 visible_rect: Rect { 97 left, 98 top, 99 right, 100 bottom, 101 }, 102 }, 103 LibvdaEvent::NotifyEndOfBitstreamBuffer { bitstream_id } => { 104 DecoderEvent::NotifyEndOfBitstreamBuffer(bitstream_id) 105 } 106 LibvdaEvent::NotifyError(resp) => { 107 DecoderEvent::NotifyError(VideoError::VdaFailure(resp)) 108 } 109 LibvdaEvent::ResetResponse(resp) => { 110 DecoderEvent::ResetCompleted(vda_response_to_result(resp)) 111 } 112 LibvdaEvent::FlushResponse(resp) => { 113 DecoderEvent::FlushCompleted(vda_response_to_result(resp)) 114 } 115 } 116 } 117 } 118 119 pub struct LibvdaSession<'a> { 120 session: libvda::decode::Session<'a>, 121 } 122 123 impl<'a> DecoderSession for LibvdaSession<'a> { set_output_buffer_count(&self, count: usize) -> VideoResult<()>124 fn set_output_buffer_count(&self, count: usize) -> VideoResult<()> { 125 Ok(self.session.set_output_buffer_count(count)?) 126 } 127 decode( &self, bitstream_id: i32, descriptor: RawDescriptor, offset: u32, bytes_used: u32, ) -> VideoResult<()>128 fn decode( 129 &self, 130 bitstream_id: i32, 131 descriptor: RawDescriptor, 132 offset: u32, 133 bytes_used: u32, 134 ) -> VideoResult<()> { 135 Ok(self 136 .session 137 .decode(bitstream_id, descriptor, offset, bytes_used)?) 138 } 139 flush(&self) -> VideoResult<()>140 fn flush(&self) -> VideoResult<()> { 141 Ok(self.session.flush()?) 142 } 143 reset(&self) -> VideoResult<()>144 fn reset(&self) -> VideoResult<()> { 145 Ok(self.session.reset()?) 146 } 147 event_pipe(&self) -> &std::fs::File148 fn event_pipe(&self) -> &std::fs::File { 149 self.session.pipe() 150 } 151 use_output_buffer( &self, picture_buffer_id: i32, format: Format, output_buffer: RawDescriptor, planes: &[FramePlane], modifier: u64, ) -> VideoResult<()>152 fn use_output_buffer( 153 &self, 154 picture_buffer_id: i32, 155 format: Format, 156 output_buffer: RawDescriptor, 157 planes: &[FramePlane], 158 modifier: u64, 159 ) -> VideoResult<()> { 160 let vda_planes: Vec<libvda::FramePlane> = planes.into_iter().map(Into::into).collect(); 161 Ok(self.session.use_output_buffer( 162 picture_buffer_id, 163 libvda::PixelFormat::try_from(format)?, 164 output_buffer, 165 &vda_planes, 166 modifier, 167 )?) 168 } 169 reuse_output_buffer(&self, picture_buffer_id: i32) -> VideoResult<()>170 fn reuse_output_buffer(&self, picture_buffer_id: i32) -> VideoResult<()> { 171 Ok(self.session.reuse_output_buffer(picture_buffer_id)?) 172 } 173 read_event(&mut self) -> VideoResult<DecoderEvent>174 fn read_event(&mut self) -> VideoResult<DecoderEvent> { 175 self.session 176 .read_event() 177 .map(Into::into) 178 .map_err(Into::into) 179 } 180 } 181 182 impl<'a> DecoderBackend for &'a libvda::decode::VdaInstance { 183 type Session = LibvdaSession<'a>; 184 new_session(&self, format: Format) -> VideoResult<Self::Session>185 fn new_session(&self, format: Format) -> VideoResult<Self::Session> { 186 let profile = libvda::Profile::try_from(format)?; 187 let session = self.open_session(profile).map_err(|e| { 188 error!("failed to open a session for {:?}: {}", format, e); 189 VideoError::InvalidOperation 190 })?; 191 192 Ok(LibvdaSession { session }) 193 } 194 } 195