]>
Commit | Line | Data |
---|---|---|
1 | // Copyright 2022 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 | //! Wrappers and helpers around `VABuffer`s. | |
6 | ||
7 | mod h264; | |
8 | mod mpeg2; | |
9 | mod vp8; | |
10 | mod vp9; | |
11 | ||
12 | pub use h264::*; | |
13 | pub use mpeg2::*; | |
14 | pub use vp8::*; | |
15 | pub use vp9::*; | |
16 | ||
17 | use std::rc::Rc; | |
18 | ||
19 | use anyhow::Result; | |
20 | use log::error; | |
21 | ||
22 | use crate::bindings; | |
23 | use crate::status::Status; | |
24 | use crate::Context; | |
25 | ||
26 | /// Wrapper type representing a buffer created with `vaCreateBuffer`. | |
27 | pub struct Buffer { | |
28 | context: Rc<Context>, | |
29 | id: bindings::VABufferID, | |
30 | } | |
31 | ||
32 | impl Buffer { | |
33 | /// Creates a new buffer by wrapping a `vaCreateBuffer` call. This is just a helper for | |
34 | /// [`Context::create_buffer`]. | |
35 | pub(crate) fn new(context: Rc<Context>, mut type_: BufferType) -> Result<Self> { | |
36 | let mut buffer_id = 0; | |
37 | ||
38 | let (ptr, size) = match type_ { | |
39 | BufferType::PictureParameter(ref mut picture_param) => match picture_param { | |
40 | PictureParameter::MPEG2(ref mut wrapper) => ( | |
41 | wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void, | |
42 | std::mem::size_of_val(wrapper.inner_mut()), | |
43 | ), | |
44 | PictureParameter::VP8(ref mut wrapper) => ( | |
45 | wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void, | |
46 | std::mem::size_of_val(wrapper.inner_mut()), | |
47 | ), | |
48 | PictureParameter::VP9(ref mut wrapper) => ( | |
49 | wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void, | |
50 | std::mem::size_of_val(wrapper.inner_mut()), | |
51 | ), | |
52 | PictureParameter::H264(ref mut wrapper) => ( | |
53 | wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void, | |
54 | std::mem::size_of_val(wrapper.inner_mut()), | |
55 | ), | |
56 | }, | |
57 | ||
58 | BufferType::SliceParameter(ref mut slice_param) => match slice_param { | |
59 | SliceParameter::MPEG2(ref mut wrapper) => ( | |
60 | wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void, | |
61 | std::mem::size_of_val(wrapper.inner_mut()), | |
62 | ), | |
63 | SliceParameter::VP8(ref mut wrapper) => ( | |
64 | wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void, | |
65 | std::mem::size_of_val(wrapper.inner_mut()), | |
66 | ), | |
67 | SliceParameter::VP9(ref mut wrapper) => ( | |
68 | wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void, | |
69 | std::mem::size_of_val(wrapper.inner_mut()), | |
70 | ), | |
71 | SliceParameter::H264(ref mut wrapper) => ( | |
72 | wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void, | |
73 | std::mem::size_of_val(wrapper.inner_mut()), | |
74 | ), | |
75 | }, | |
76 | ||
77 | BufferType::IQMatrix(ref mut iq_matrix) => match iq_matrix { | |
78 | IQMatrix::MPEG2(ref mut wrapper) => ( | |
79 | wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void, | |
80 | std::mem::size_of_val(wrapper.inner_mut()), | |
81 | ), | |
82 | IQMatrix::VP8(ref mut wrapper) => ( | |
83 | wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void, | |
84 | std::mem::size_of_val(wrapper.inner_mut()), | |
85 | ), | |
86 | IQMatrix::H264(ref mut wrapper) => ( | |
87 | wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void, | |
88 | std::mem::size_of_val(wrapper.inner_mut()), | |
89 | ), | |
90 | }, | |
91 | ||
92 | BufferType::Probability(ref mut wrapper) => ( | |
93 | wrapper.inner_mut() as *mut _ as *mut std::ffi::c_void, | |
94 | std::mem::size_of_val(wrapper.inner_mut()), | |
95 | ), | |
96 | ||
97 | BufferType::SliceData(ref mut data) => { | |
98 | (data.as_mut_ptr() as *mut std::ffi::c_void, data.len()) | |
99 | } | |
100 | }; | |
101 | ||
102 | // Safe because `self` represents a valid `VAContext`. `ptr` and `size` are also ensured to | |
103 | // be correct, as `ptr` is just a cast to `*c_void` from a Rust struct, and `size` is | |
104 | // computed from `std::mem::size_of_val`. | |
105 | Status(unsafe { | |
106 | bindings::vaCreateBuffer( | |
107 | context.display().handle(), | |
108 | context.id(), | |
109 | type_.inner(), | |
110 | size as u32, | |
111 | 1, | |
112 | ptr, | |
113 | &mut buffer_id, | |
114 | ) | |
115 | }) | |
116 | .check()?; | |
117 | ||
118 | Ok(Self { | |
119 | context, | |
120 | id: buffer_id, | |
121 | }) | |
122 | } | |
123 | ||
124 | /// Convenience function to return a `VABufferID` vector from a slice of `Buffer`s in order to | |
125 | /// easily interface with the C API where a buffer array might be needed. | |
126 | pub fn as_id_vec(buffers: &[Self]) -> Vec<bindings::VABufferID> { | |
127 | buffers.iter().map(|buffer| buffer.id).collect() | |
128 | } | |
129 | } | |
130 | ||
131 | impl Drop for Buffer { | |
132 | fn drop(&mut self) { | |
133 | // Safe because `self` represents a valid buffer, created with | |
134 | // vaCreateBuffers. | |
135 | let status = | |
136 | Status(unsafe { bindings::vaDestroyBuffer(self.context.display().handle(), self.id) }) | |
137 | .check(); | |
138 | if status.is_err() { | |
139 | error!("vaDestroyBuffer failed: {}", status.unwrap_err()); | |
140 | } | |
141 | } | |
142 | } | |
143 | ||
144 | /// Abstraction over `VABufferType`s. | |
145 | pub enum BufferType { | |
146 | /// Abstraction over `VAPictureParameterBufferType`. Needed for MPEG2, VP8, VP9, H264. | |
147 | PictureParameter(PictureParameter), | |
148 | /// Abstraction over `VASliceParameterBufferType`. Needed for MPEG2, VP8, VP9, H264. | |
149 | SliceParameter(SliceParameter), | |
150 | /// Abstraction over `VAIQMatrixBufferType`. Needed for VP8, H264. | |
151 | IQMatrix(IQMatrix), | |
152 | /// Abstraction over `VAProbabilityDataBufferType`. Needed for VP8. | |
153 | Probability(vp8::ProbabilityDataBufferVP8), | |
154 | /// Abstraction over `VASliceDataBufferType`. Needed for VP9, H264. | |
155 | SliceData(Vec<u8>), | |
156 | } | |
157 | ||
158 | impl BufferType { | |
159 | /// Returns the inner FFI buffer type. | |
160 | pub(crate) fn inner(&self) -> bindings::VABufferType::Type { | |
161 | match self { | |
162 | BufferType::PictureParameter(_) => bindings::VABufferType::VAPictureParameterBufferType, | |
163 | BufferType::SliceParameter(_) => bindings::VABufferType::VASliceParameterBufferType, | |
164 | BufferType::IQMatrix(_) => bindings::VABufferType::VAIQMatrixBufferType, | |
165 | BufferType::Probability(_) => bindings::VABufferType::VAProbabilityBufferType, | |
166 | BufferType::SliceData { .. } => bindings::VABufferType::VASliceDataBufferType, | |
167 | } | |
168 | } | |
169 | } | |
170 | ||
171 | /// Abstraction over the `PictureParameterBuffer` types we support. | |
172 | pub enum PictureParameter { | |
173 | /// Wrapper over VAPictureParameterBufferMPEG2. | |
174 | MPEG2(mpeg2::PictureParameterBufferMPEG2), | |
175 | /// Wrapper over VAPictureParameterBufferVP8. | |
176 | VP8(vp8::PictureParameterBufferVP8), | |
177 | /// Wrapper over VAPictureParameterBufferVP9. | |
178 | VP9(vp9::PictureParameterBufferVP9), | |
179 | /// Wrapper over VAPictureParameterBufferH264. | |
180 | H264(h264::PictureParameterBufferH264), | |
181 | } | |
182 | ||
183 | /// Abstraction over the `SliceParameterBuffer` types we support | |
184 | pub enum SliceParameter { | |
185 | /// Wrapper over VASliceParameterBufferMPEG2 | |
186 | MPEG2(mpeg2::SliceParameterBufferMPEG2), | |
187 | /// Wrapper over VASliceParameterBufferVP8 | |
188 | VP8(vp8::SliceParameterBufferVP8), | |
189 | /// Wrapper over VASliceParameterBufferVP9 | |
190 | VP9(vp9::SliceParameterBufferVP9), | |
191 | /// Wrapper over VASliceParameterBufferH264 | |
192 | H264(h264::SliceParameterBufferH264), | |
193 | } | |
194 | ||
195 | /// Abstraction over the `IQMatrixBuffer` types we support. | |
196 | pub enum IQMatrix { | |
197 | /// Abstraction over `VAIQMatrixBufferMPEG2` | |
198 | MPEG2(mpeg2::IQMatrixBufferMPEG2), | |
199 | /// Abstraction over `VAIQMatrixBufferVP8` | |
200 | VP8(vp8::IQMatrixBufferVP8), | |
201 | /// Abstraction over `VAIQMatrixBufferH264` | |
202 | H264(h264::IQMatrixBufferH264), | |
203 | } |