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:59:48 +0300 |
commit | 3cd6074a8ea2805dafb3ad9a2e96da91f2d21252 (patch) | |
tree | ccf6aa6350304a91206af994b6366945673b49e1 /video/dav1d | |
parent | ab5ee0511b6a090fe09489bf521c14996a10be5f (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/1056>
Diffstat (limited to 'video/dav1d')
-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 89f50ef72..66e430956 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)?; } } |