Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/media/libvda/src/decode/vda_instance.rs
5394 views
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
//! This module provides type safe interfaces for each operation exposed by Chrome's
6
//! VideoDecodeAccelerator.
7
8
use std::os::raw::c_void;
9
use std::rc::Rc;
10
11
use super::bindings;
12
use super::format::*;
13
use super::session::*;
14
use crate::error::*;
15
use crate::format::*;
16
17
/// Represents a backend implementation of libvda.
18
pub enum VdaImplType {
19
Fake,
20
Gavda, // GpuArcVideoDecodeAccelerator
21
Gavd, // GpuArcVideoDecoder
22
}
23
24
/// Represents decoding capabilities of libvda instances.
25
pub struct Capabilities {
26
pub input_formats: Vec<InputFormat>,
27
pub output_formats: Vec<PixelFormat>,
28
}
29
30
// An active connection to the VDA, which closes automatically as it is dropped.
31
pub struct VdaConnection {
32
// `conn_ptr` must be a valid pointer obtained from `decode_bindings::initialize`.
33
conn_ptr: *mut c_void,
34
}
35
36
impl VdaConnection {
37
fn new(typ: VdaImplType) -> Result<Self> {
38
let impl_type = match typ {
39
VdaImplType::Fake => bindings::vda_impl_type_FAKE,
40
VdaImplType::Gavda => bindings::vda_impl_type_GAVDA,
41
VdaImplType::Gavd => bindings::vda_impl_type_GAVD,
42
};
43
44
// Safe because libvda's API is called properly.
45
match unsafe { bindings::initialize(impl_type) } {
46
ptr if ptr.is_null() => Err(Error::InstanceInitFailure),
47
conn_ptr => Ok(VdaConnection { conn_ptr }),
48
}
49
}
50
51
// Returns the raw pointer to the VDA connection instance that can be passed
52
// to bindings functions that require it.
53
pub(super) fn conn_ptr(&self) -> *mut c_void {
54
self.conn_ptr
55
}
56
}
57
58
impl Drop for VdaConnection {
59
fn drop(&mut self) {
60
// Safe because libvda's API is called properly.
61
unsafe { bindings::deinitialize(self.conn_ptr) }
62
}
63
}
64
65
/// Represents a libvda instance.
66
pub struct VdaInstance {
67
connection: Rc<VdaConnection>,
68
caps: Capabilities,
69
}
70
71
impl VdaInstance {
72
/// Creates VdaInstance. `typ` specifies which backend will be used.
73
pub fn new(typ: VdaImplType) -> Result<Self> {
74
let connection = VdaConnection::new(typ)?;
75
76
// Get available input/output formats.
77
// Safe because `conn_ptr` is valid and `get_vda_capabilities()` won't invalidate it.
78
let vda_cap_ptr = unsafe { bindings::get_vda_capabilities(connection.conn_ptr) };
79
if vda_cap_ptr.is_null() {
80
return Err(Error::GetCapabilitiesFailure);
81
}
82
// Safe because `vda_cap_ptr` is not NULL.
83
let vda_cap = unsafe { *vda_cap_ptr };
84
85
// Safe because `input_formats` is valid for |`num_input_formats`| elements if both are
86
// valid.
87
let input_formats = unsafe {
88
InputFormat::from_raw_parts(vda_cap.input_formats, vda_cap.num_input_formats)?
89
};
90
91
// Output formats
92
// Safe because `output_formats` is valid for |`num_output_formats`| elements if both are
93
// valid.
94
let output_formats = unsafe {
95
PixelFormat::from_raw_parts(vda_cap.output_formats, vda_cap.num_output_formats)?
96
};
97
98
Ok(VdaInstance {
99
connection: Rc::new(connection),
100
caps: Capabilities {
101
input_formats,
102
output_formats,
103
},
104
})
105
}
106
107
/// Get media capabilities.
108
pub fn get_capabilities(&self) -> &Capabilities {
109
&self.caps
110
}
111
112
/// Opens a new `Session` for a given `Profile`.
113
pub fn open_session(&self, profile: Profile) -> Result<Session> {
114
Session::new(&self.connection, profile).ok_or(Error::SessionInitFailure(profile))
115
}
116
}
117
118