diff options
author | Sebastian Dröge <sebastian@centricular.com> | 2023-01-22 01:25:23 +0300 |
---|---|---|
committer | Sebastian Dröge <sebastian@centricular.com> | 2023-01-22 01:25:23 +0300 |
commit | d1109775809ab3da77dd9b1b31c3fcbaaea09e07 (patch) | |
tree | f04859cd3fbbbbc499631b36682db0406e26ef73 | |
parent | 4582ae91ab4cc14b17c01a6ba8494fdb0f66f177 (diff) |
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: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1055>
-rw-r--r-- | video/dav1d/src/dav1ddec/imp.rs | 19 |
1 files 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<Option<State>>) { - 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<Option<State>>, ) -> Result<Option<dav1d::Picture>, gst::FlowError> { @@ -425,9 +425,13 @@ impl Dav1dDec { fn forward_pending_pictures<'s>( &'s self, mut state_guard: MutexGuard<'s, Option<State>>, + drain: bool, ) -> Result<MutexGuard<Option<State>>, 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)?; } } |