• 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 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