From d1109775809ab3da77dd9b1b31c3fcbaaea09e07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 22 Jan 2023 00:25:23 +0200 Subject: [PATCH] dav1d: Only drain at most one decoded frame per input frame unless the decoder requires more before accepting new data This works around a race condition in dav1d where the decoder deadlocks if multiple threads are used, and also is generally beneficial as it allows for proper frame threading. Part-of: --- video/dav1d/src/dav1ddec/imp.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/video/dav1d/src/dav1ddec/imp.rs b/video/dav1d/src/dav1ddec/imp.rs index 89f50ef7..66e43095 100644 --- a/video/dav1d/src/dav1ddec/imp.rs +++ b/video/dav1d/src/dav1ddec/imp.rs @@ -380,13 +380,13 @@ impl Dav1dDec { } fn drop_decoded_pictures(&self, state_guard: &mut MutexGuard>) { - while let Ok(Some(pic)) = self.pending_pictures(state_guard) { + while let Ok(Some(pic)) = self.pending_picture(state_guard) { gst::debug!(CAT, imp: self, "Dropping picture {}", pic.offset()); drop(pic); } } - fn pending_pictures( + fn pending_picture( &self, state_guard: &mut MutexGuard>, ) -> Result, gst::FlowError> { @@ -425,9 +425,13 @@ impl Dav1dDec { fn forward_pending_pictures<'s>( &'s self, mut state_guard: MutexGuard<'s, Option>, + drain: bool, ) -> Result>, gst::FlowError> { - while let Some(pic) = self.pending_pictures(&mut state_guard)? { + while let Some(pic) = self.pending_picture(&mut state_guard)? { state_guard = self.handle_picture(state_guard, &pic)?; + if !drain { + break; + } } Ok(state_guard) @@ -709,19 +713,18 @@ impl VideoDecoderImpl for Dav1dDec { { let mut state_guard = self.state.lock().unwrap(); - state_guard = self.forward_pending_pictures(state_guard)?; if self.send_data(&mut state_guard, input_buffer, frame)? == std::ops::ControlFlow::Continue(()) { loop { - state_guard = self.forward_pending_pictures(state_guard)?; + state_guard = self.forward_pending_pictures(state_guard, false)?; if self.send_pending_data(&mut state_guard)? == std::ops::ControlFlow::Break(()) { break; } } } - let _state_guard = self.forward_pending_pictures(state_guard)?; + let _state_guard = self.forward_pending_pictures(state_guard, false)?; } Ok(gst::FlowSuccess::Ok) @@ -750,7 +753,7 @@ impl VideoDecoderImpl for Dav1dDec { if state_guard.is_some() { let state = state_guard.as_mut().unwrap(); self.flush_decoder(state); - let _state_guard = self.forward_pending_pictures(state_guard)?; + let _state_guard = self.forward_pending_pictures(state_guard, true)?; } } @@ -765,7 +768,7 @@ impl VideoDecoderImpl for Dav1dDec { if state_guard.is_some() { let state = state_guard.as_mut().unwrap(); self.flush_decoder(state); - let _state_guard = self.forward_pending_pictures(state_guard)?; + let _state_guard = self.forward_pending_pictures(state_guard, true)?; } }