Skip to content

Commit 6dc76f4

Browse files
committed
decoders: vaapi: av1: add film grain support
Use the new VAAPI handle to add film grain support in the VAAPI AV1 decoder. One surface contains the grain and is meant to be displayed, while the other one does not. We need the decode surface to not have any grain, otherwise this would break the decoding process. The number of surfaces is doubled to accomodate for this, but only when film grain is active.
1 parent e48eb00 commit 6dc76f4

File tree

2 files changed

+84
-16
lines changed

2 files changed

+84
-16
lines changed

src/decoder/stateless/av1.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ where
258258
header,
259259
backend_picture,
260260
}) => (self.backend.submit_picture(backend_picture)?, header),
261+
261262
Some(CurrentPicState::ShowExistingFrame { header, handle }) => (handle, header),
262263
None => return Err(anyhow!("Broken stream: no picture to submit")),
263264
};

src/decoder/stateless/av1/vaapi.rs

Lines changed: 83 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use libva::SurfaceMemoryDescriptor;
1212

1313
use crate::backend::vaapi::DecodedHandle as VADecodedHandle;
1414
use crate::backend::vaapi::PoolCreationMode;
15+
use crate::backend::vaapi::PooledSurface;
1516
use crate::backend::vaapi::VaStreamInfo;
1617
use crate::backend::vaapi::VaapiBackend;
1718
use crate::backend::vaapi::VaapiPicture;
@@ -87,7 +88,13 @@ impl VaStreamInfo for &Rc<SequenceHeaderObu> {
8788
}
8889

8990
fn min_num_surfaces(&self) -> usize {
90-
NUM_SURFACES
91+
if self.film_grain_params_present {
92+
/* assume grain will be applied. We need twice the number of surfaces
93+
* for that. */
94+
NUM_SURFACES * 2
95+
} else {
96+
NUM_SURFACES
97+
}
9198
}
9299

93100
fn coded_size(&self) -> (u32, u32) {
@@ -271,6 +278,7 @@ fn build_pic_param<M: SurfaceMemoryDescriptor>(
271278
hdr: &FrameHeaderObu,
272279
seq: &SequenceHeaderObu,
273280
current_frame: libva::VASurfaceID,
281+
current_display_picture: libva::VASurfaceID,
274282
reference_frames: &[Option<VADecodedHandle<M>>; NUM_REF_FRAMES],
275283
) -> anyhow::Result<libva::BufferType> {
276284
let seq_info_fields = libva::AV1SeqFields::new(
@@ -487,8 +495,8 @@ fn build_pic_param<M: SurfaceMemoryDescriptor>(
487495
.context("Invalid matrix_coefficients")?,
488496
&seq_info_fields,
489497
current_frame,
490-
libva::constants::VA_INVALID_SURFACE, /* film grain is unsupported for now */
491-
vec![], /* anchor_frames_list */
498+
current_display_picture,
499+
vec![], /* anchor_frames_list */
492500
u16::try_from(hdr.upscaled_width - 1).context("Invalid frame width")?,
493501
u16::try_from(hdr.frame_height - 1).context("Invalid frame height")?,
494502
0, /* output_frame_width_in_tiles_minus_1 */
@@ -564,8 +572,14 @@ fn build_slice_data_for_tg(tg: TileGroupObu) -> libva::BufferType {
564572
libva::BufferType::SliceData(Vec::from(obu.as_ref()))
565573
}
566574

575+
pub struct Picture<M: SurfaceMemoryDescriptor + 'static> {
576+
va_picture: VaapiPicture<M>,
577+
/// Some if film grain is to be applied.
578+
display_surface: Option<PooledSurface<M>>,
579+
}
580+
567581
impl<M: SurfaceMemoryDescriptor + 'static> StatelessDecoderBackendPicture<Av1> for VaapiBackend<M> {
568-
type Picture = VaapiPicture<M>;
582+
type Picture = Picture<M>;
569583
}
570584

571585
impl<M: SurfaceMemoryDescriptor + 'static> StatelessAV1DecoderBackend for VaapiBackend<M> {
@@ -598,7 +612,7 @@ impl<M: SurfaceMemoryDescriptor + 'static> StatelessAV1DecoderBackend for VaapiB
598612
reference_frames: &[Option<Self::Handle>; NUM_REF_FRAMES],
599613
highest_spatial_layer: Option<u32>,
600614
) -> crate::decoder::stateless::StatelessBackendResult<Self::Picture> {
601-
let surface = match highest_spatial_layer {
615+
let (decode_surface, display_surface) = match highest_spatial_layer {
602616
Some(_) => {
603617
let layer = Resolution {
604618
width: hdr.upscaled_width,
@@ -611,33 +625,77 @@ impl<M: SurfaceMemoryDescriptor + 'static> StatelessAV1DecoderBackend for VaapiB
611625
"No pool available for this layer"
612626
)))?;
613627

614-
pool.borrow_mut()
628+
let decode_surface = pool
629+
.borrow_mut()
615630
.get_surface(pool)
616-
.ok_or(StatelessBackendError::OutOfResources)?
631+
.ok_or(StatelessBackendError::OutOfResources)?;
632+
633+
let display_surface = if hdr.film_grain_params.apply_grain {
634+
Some(
635+
pool.borrow_mut()
636+
.get_surface(pool)
637+
.ok_or(StatelessBackendError::OutOfResources)?,
638+
)
639+
} else {
640+
None
641+
};
642+
643+
(decode_surface, display_surface)
617644
}
618645
None => {
619646
let highest_pool = self.highest_pool();
620-
highest_pool
647+
648+
let decode_surface = highest_pool
621649
.borrow_mut()
622650
.get_surface(highest_pool)
623-
.ok_or(StatelessBackendError::OutOfResources)?
651+
.ok_or(StatelessBackendError::OutOfResources)?;
652+
653+
let display_surface = if hdr.film_grain_params.apply_grain {
654+
Some(
655+
highest_pool
656+
.borrow_mut()
657+
.get_surface(highest_pool)
658+
.ok_or(StatelessBackendError::OutOfResources)?,
659+
)
660+
} else {
661+
None
662+
};
663+
664+
(decode_surface, display_surface)
624665
}
625666
};
626667

627668
let metadata = self.metadata_state.get_parsed()?;
628-
let mut picture = VaPicture::new(timestamp, Rc::clone(&metadata.context), surface);
669+
let mut picture = VaPicture::new(timestamp, Rc::clone(&metadata.context), decode_surface);
629670

630671
let surface_id = picture.surface().id();
672+
let display_surface_id = match display_surface {
673+
Some(ref pooled_surface) => {
674+
use std::borrow::Borrow;
675+
let display_surface: &libva::Surface<M> = pooled_surface.borrow();
676+
display_surface.id()
677+
}
678+
None => libva::constants::VA_INVALID_SURFACE,
679+
};
631680

632-
let pic_param = build_pic_param(hdr, sequence, surface_id, reference_frames)
633-
.context("Failed to build picture parameter")?;
681+
let pic_param = build_pic_param(
682+
hdr,
683+
sequence,
684+
surface_id,
685+
display_surface_id,
686+
reference_frames,
687+
)
688+
.context("Failed to build picture parameter")?;
634689
let pic_param = metadata
635690
.context
636691
.create_buffer(pic_param)
637692
.context("Failed to create picture parameter buffer")?;
638693
picture.add_buffer(pic_param);
639694

640-
Ok(picture)
695+
Ok(Picture {
696+
va_picture: picture,
697+
display_surface,
698+
})
641699
}
642700

643701
fn decode_tile_group(
@@ -655,13 +713,13 @@ impl<M: SurfaceMemoryDescriptor + 'static> StatelessAV1DecoderBackend for VaapiB
655713
.create_buffer(slice_params)
656714
.context("Failed to create slice parameter buffer")?;
657715

658-
picture.add_buffer(buffer);
716+
picture.va_picture.add_buffer(buffer);
659717

660718
let buffer = context
661719
.create_buffer(slice_data)
662720
.context("Failed to create slice data buffer")?;
663721

664-
picture.add_buffer(buffer);
722+
picture.va_picture.add_buffer(buffer);
665723

666724
Ok(())
667725
}
@@ -670,7 +728,16 @@ impl<M: SurfaceMemoryDescriptor + 'static> StatelessAV1DecoderBackend for VaapiB
670728
&mut self,
671729
picture: Self::Picture,
672730
) -> crate::decoder::stateless::StatelessBackendResult<Self::Handle> {
673-
self.process_picture::<Av1>(picture)
731+
let Picture {
732+
va_picture,
733+
display_surface,
734+
} = picture;
735+
736+
if let Some(display_surface) = display_surface {
737+
self.process_av1_picture::<Av1>(va_picture, display_surface)
738+
} else {
739+
self.process_picture::<Av1>(va_picture)
740+
}
674741
}
675742
}
676743

0 commit comments

Comments
 (0)