Skip to content

Commit e48eb00

Browse files
committed
backend: vaapi: add a handle for post-processing
Add a new handle for post-processing. This use-case requires a surface for non-filtered data (for the decode process), and one surface for the filtered data (for display). This was previously impossible, as we only had one handle. Thus add a new type of handle and unite them through an enum. A next commit will make use of this handle to implement film grain in the AV1 VA-API code.
1 parent cfcc103 commit e48eb00

File tree

6 files changed

+173
-50
lines changed

6 files changed

+173
-50
lines changed

src/backend/vaapi.rs

Lines changed: 166 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -174,47 +174,149 @@ fn supported_formats_for_rt_format(
174174
Ok(supported_formats)
175175
}
176176

177-
/// A decoded frame handle.
178-
pub(crate) type DecodedHandle<M> = Rc<RefCell<GenericBackendHandle<M>>>;
177+
pub(crate) type DecodedHandle<M> = Rc<RefCell<VaDecodedHandle<M>>>;
179178

180-
impl<M: SurfaceMemoryDescriptor> DecodedHandleTrait for DecodedHandle<M> {
179+
/// The handle type used by the decoder backend that takes into account whether
180+
/// post processing is needed.
181+
pub enum VaDecodedHandle<M: SurfaceMemoryDescriptor> {
182+
Generic(GenericBackendHandle<M>),
183+
PostProcessed(PostProcessedHandle<M>),
184+
}
185+
186+
impl<M: SurfaceMemoryDescriptor> VaDecodedHandle<M> {
187+
fn handle(&self) -> &GenericBackendHandle<M> {
188+
match self {
189+
VaDecodedHandle::Generic(h) => h,
190+
VaDecodedHandle::PostProcessed(h) => &h.decode_handle,
191+
}
192+
}
193+
194+
fn handle_mut(&mut self) -> &mut GenericBackendHandle<M> {
195+
match self {
196+
VaDecodedHandle::Generic(h) => h,
197+
VaDecodedHandle::PostProcessed(h) => &mut h.decode_handle,
198+
}
199+
}
200+
201+
pub(crate) fn decoded_surface_id(&self) -> libva::VASurfaceID {
202+
match &self.handle().state {
203+
PictureState::Ready(picture) => picture.surface().id(),
204+
PictureState::Pending(picture) => picture.surface().id(),
205+
PictureState::Invalid => unreachable!(),
206+
}
207+
}
208+
209+
/// Returns the picture of this handle.
210+
pub(crate) fn picture(&self) -> Option<&Picture<PictureSync, PooledSurface<M>>> {
211+
match self {
212+
VaDecodedHandle::Generic(h) => h.picture(),
213+
VaDecodedHandle::PostProcessed(h) => h.picture(),
214+
}
215+
}
216+
}
217+
218+
impl<M: SurfaceMemoryDescriptor> DecodedHandleTrait for Rc<RefCell<VaDecodedHandle<M>>> {
181219
type Descriptor = M;
182220

183221
fn coded_resolution(&self) -> Resolution {
184-
self.borrow().coded_resolution
222+
self.borrow().handle().coded_resolution
185223
}
186224

187225
fn display_resolution(&self) -> Resolution {
188-
self.borrow().display_resolution
226+
self.borrow().handle().display_resolution
189227
}
190228

191229
fn timestamp(&self) -> u64 {
192-
self.borrow().timestamp()
230+
self.borrow().handle().timestamp()
193231
}
194232

195233
fn dyn_picture<'a>(&'a self) -> Box<dyn DynHandle + 'a> {
196234
Box::new(self.borrow())
197235
}
198236

199237
fn is_ready(&self) -> bool {
200-
self.borrow().is_va_ready().unwrap_or(true)
238+
let borrow = self.borrow();
239+
let handle = borrow.handle();
240+
241+
let decode_is_ready = match &handle.state {
242+
PictureState::Ready(_) => Ok(true),
243+
PictureState::Pending(picture) => picture
244+
.surface()
245+
.query_status()
246+
.map(|s| s == libva::VASurfaceStatus::VASurfaceReady),
247+
PictureState::Invalid => unreachable!(),
248+
}
249+
.unwrap_or(true);
250+
251+
match &*self.borrow() {
252+
VaDecodedHandle::Generic(_) => decode_is_ready,
253+
VaDecodedHandle::PostProcessed(h) => {
254+
use std::borrow::Borrow;
255+
let display_surface: &libva::Surface<M> = h.display_surface.borrow();
256+
257+
let display_is_ready = display_surface
258+
.query_status()
259+
.map(|s| s == libva::VASurfaceStatus::VASurfaceReady)
260+
.unwrap_or(true);
261+
262+
decode_is_ready && display_is_ready
263+
}
264+
}
201265
}
202266

203267
fn sync(&self) -> anyhow::Result<()> {
204-
self.borrow_mut().sync().context("while syncing picture")?;
205-
206-
Ok(())
268+
let mut borrow = self.borrow_mut();
269+
let handle = borrow.handle_mut();
270+
handle.sync().context("while syncing picture")?;
271+
272+
match &*borrow {
273+
VaDecodedHandle::Generic(_) => Ok(()),
274+
VaDecodedHandle::PostProcessed(h) => {
275+
use std::borrow::Borrow;
276+
let display_surface: &libva::Surface<M> = h.display_surface.borrow();
277+
display_surface
278+
.sync()
279+
.context("while syncing the display surface")
280+
}
281+
}
207282
}
208283

209284
fn resource(&self) -> std::cell::Ref<M> {
210-
std::cell::Ref::map(self.borrow(), |r| match &r.state {
211-
PictureState::Ready(p) => p.surface().as_ref(),
212-
PictureState::Pending(p) => p.surface().as_ref(),
213-
PictureState::Invalid => unreachable!(),
285+
std::cell::Ref::map(self.borrow(), |r| match r {
286+
VaDecodedHandle::Generic(h) => match &h.state {
287+
PictureState::Ready(p) => p.surface().as_ref(),
288+
PictureState::Pending(p) => p.surface().as_ref(),
289+
PictureState::Invalid => unreachable!(),
290+
},
291+
VaDecodedHandle::PostProcessed(h) => {
292+
/* return the display resource, as this is what most clients care about */
293+
h.display_surface.as_ref()
294+
}
214295
})
215296
}
216297
}
217298

299+
impl<'a, M: SurfaceMemoryDescriptor> DynHandle for std::cell::Ref<'a, VaDecodedHandle<M>> {
300+
fn dyn_mappable_handle<'b>(&'b self) -> anyhow::Result<Box<dyn MappableHandle + 'b>> {
301+
match &**self {
302+
VaDecodedHandle::Generic(h) => {
303+
h.image().map(|i| Box::new(i) as Box<dyn MappableHandle>)
304+
}
305+
VaDecodedHandle::PostProcessed(h) => {
306+
use std::borrow::Borrow;
307+
let surface: &libva::Surface<M> = h.display_surface.borrow();
308+
let image = libva::Image::create_from(
309+
surface,
310+
*h.decode_handle.map_format,
311+
h.decode_handle.coded_resolution.into(),
312+
h.decode_handle.display_resolution.into(),
313+
)?;
314+
Ok(Box::new(image) as Box<dyn MappableHandle>)
315+
}
316+
}
317+
}
318+
}
319+
218320
mod surface_pool {
219321
use std::borrow::Borrow;
220322
use std::cell::RefCell;
@@ -691,6 +793,35 @@ impl StreamMetadataState {
691793
}
692794
}
693795

796+
/// A handle that can be post processed. One surface holds the non-filtered data
797+
/// and is fed to the decode process, the other holds the filtered data and is
798+
/// meant to be displayed.
799+
pub struct PostProcessedHandle<M: SurfaceMemoryDescriptor> {
800+
/// The non-filtered handle. All decoding happens here.
801+
decode_handle: GenericBackendHandle<M>,
802+
/// The filtered surface. We merely display it.
803+
display_surface: PooledSurface<M>,
804+
}
805+
806+
impl<M: SurfaceMemoryDescriptor> PostProcessedHandle<M> {
807+
/// Creates a new pending handle on `surface_id`.
808+
fn new(
809+
picture: Picture<PictureNew, PooledSurface<M>>,
810+
metadata: &ParsedStreamMetadata,
811+
display_surface: PooledSurface<M>,
812+
) -> anyhow::Result<Self> {
813+
Ok(Self {
814+
decode_handle: GenericBackendHandle::new(picture, metadata)?,
815+
display_surface,
816+
})
817+
}
818+
819+
/// Returns the picture of this handle.
820+
pub(crate) fn picture(&self) -> Option<&Picture<PictureSync, PooledSurface<M>>> {
821+
self.decode_handle.picture()
822+
}
823+
}
824+
694825
/// VA-API backend handle.
695826
///
696827
/// This includes the VA picture which can be pending rendering or complete, as well as useful
@@ -777,32 +908,6 @@ impl<M: SurfaceMemoryDescriptor> GenericBackendHandle<M> {
777908
PictureState::Invalid => unreachable!(),
778909
}
779910
}
780-
781-
/// Returns the id of the VA surface backing this handle.
782-
pub(crate) fn surface_id(&self) -> libva::VASurfaceID {
783-
match &self.state {
784-
PictureState::Ready(picture) => picture.surface().id(),
785-
PictureState::Pending(picture) => picture.surface().id(),
786-
PictureState::Invalid => unreachable!(),
787-
}
788-
}
789-
790-
fn is_va_ready(&self) -> Result<bool, VaError> {
791-
match &self.state {
792-
PictureState::Ready(_) => Ok(true),
793-
PictureState::Pending(picture) => picture
794-
.surface()
795-
.query_status()
796-
.map(|s| s == libva::VASurfaceStatus::VASurfaceReady),
797-
PictureState::Invalid => unreachable!(),
798-
}
799-
}
800-
}
801-
802-
impl<'a, M: SurfaceMemoryDescriptor> DynHandle for std::cell::Ref<'a, GenericBackendHandle<M>> {
803-
fn dyn_mappable_handle<'b>(&'b self) -> anyhow::Result<Box<dyn MappableHandle + 'b>> {
804-
self.image().map(|i| Box::new(i) as Box<dyn MappableHandle>)
805-
}
806911
}
807912

808913
/// Rendering state of a VA picture.
@@ -1000,9 +1105,27 @@ where
10001105
{
10011106
let metadata = self.metadata_state.get_parsed()?;
10021107

1003-
Ok(Rc::new(RefCell::new(GenericBackendHandle::new(
1004-
picture, metadata,
1005-
)?)))
1108+
let handle = GenericBackendHandle::new(picture, metadata)?;
1109+
let handle = Rc::new(RefCell::new(VaDecodedHandle::Generic(handle)));
1110+
Ok(handle)
1111+
}
1112+
1113+
/// Process an AV1 picture. AV1 supports film grain, and its use requires a
1114+
/// different type of Handle.
1115+
pub(crate) fn process_av1_picture<Codec: StatelessCodec>(
1116+
&mut self,
1117+
picture: Picture<PictureNew, PooledSurface<M>>,
1118+
display_surface: PooledSurface<M>,
1119+
) -> StatelessBackendResult<<Self as StatelessDecoderBackend<Codec>>::Handle>
1120+
where
1121+
Self: StatelessDecoderBackendPicture<Codec>,
1122+
for<'a> &'a Codec::FormatInfo: VaStreamInfo,
1123+
{
1124+
let metadata = self.metadata_state.get_parsed()?;
1125+
1126+
let handle = PostProcessedHandle::new(picture, metadata, display_surface)?;
1127+
let handle = Rc::new(RefCell::new(VaDecodedHandle::PostProcessed(handle)));
1128+
Ok(handle)
10061129
}
10071130

10081131
/// Gets a set of supported formats for the particular stream being

src/decoder/stateless/av1/vaapi.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ fn build_pic_param<M: SurfaceMemoryDescriptor>(
347347
.iter()
348348
.map(|h| {
349349
if let Some(h) = h {
350-
h.borrow().surface_id()
350+
h.borrow().decoded_surface_id()
351351
} else {
352352
libva::constants::VA_INVALID_SURFACE
353353
}

src/decoder/stateless/h264/vaapi.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ fn surface_id<M: SurfaceMemoryDescriptor>(
116116
) -> libva::VASurfaceID {
117117
match handle {
118118
None => libva::constants::VA_INVALID_SURFACE,
119-
Some(handle) => handle.borrow().surface_id(),
119+
Some(handle) => handle.borrow().decoded_surface_id(),
120120
}
121121
}
122122

src/decoder/stateless/h265/vaapi.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ fn build_pic_param<M: SurfaceMemoryDescriptor>(
343343
let mut reference_frames = vec![];
344344

345345
for ref_pic in dpb.get_all_references() {
346-
let surface_id = ref_pic.1.borrow().surface_id();
346+
let surface_id = ref_pic.1.borrow().decoded_surface_id();
347347
let ref_pic = fill_va_hevc_pic(&ref_pic.0.borrow(), surface_id, rps);
348348
reference_frames.push(ref_pic);
349349
}

src/decoder/stateless/vp8/vaapi.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,19 +225,19 @@ impl<M: SurfaceMemoryDescriptor + 'static> StatelessVp8DecoderBackend for VaapiB
225225
timestamp: u64,
226226
) -> StatelessBackendResult<Self::Handle> {
227227
let last_ref = if let Some(last_ref) = last_ref {
228-
last_ref.borrow().surface_id()
228+
last_ref.borrow().decoded_surface_id()
229229
} else {
230230
libva::constants::VA_INVALID_SURFACE
231231
};
232232

233233
let golden_ref = if let Some(golden_ref) = golden_ref {
234-
golden_ref.borrow().surface_id()
234+
golden_ref.borrow().decoded_surface_id()
235235
} else {
236236
libva::constants::VA_INVALID_SURFACE
237237
};
238238

239239
let alt_ref = if let Some(alt_ref) = alt_ref {
240-
alt_ref.borrow().surface_id()
240+
alt_ref.borrow().decoded_surface_id()
241241
} else {
242242
libva::constants::VA_INVALID_SURFACE
243243
};

src/decoder/stateless/vp9/vaapi.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ impl<M: SurfaceMemoryDescriptor + 'static> StatelessVp9DecoderBackend for VaapiB
255255
.iter()
256256
.map(|h| {
257257
if let Some(h) = h {
258-
h.borrow().surface_id()
258+
h.borrow().decoded_surface_id()
259259
} else {
260260
libva::constants::VA_INVALID_SURFACE
261261
}

0 commit comments

Comments
 (0)