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