omxvideodec: always signal drain cond when stopping streaming loop

If for some reason something goes wrong and we stop the streaming loop
we may end up with other threads still waiting on the drain cond.
No more buffers will be produced by the component so they were waiting
forever.

Fix this by always signalling this cond when stopping the streaming
loop.

https://bugzilla.gnome.org/show_bug.cgi?id=796207
This commit is contained in:
Guillaume Desmottes 2018-05-16 17:06:29 +02:00
parent 798bbc9acf
commit fd108f4278
2 changed files with 9 additions and 23 deletions

View file

@ -1532,7 +1532,7 @@ copy_frame (const GstVideoInfo * info, GstBuffer * outbuf)
} }
static void static void
gst_omx_video_enc_pause_loop (GstOMXVideoDec * self, GstFlowReturn flow_ret) gst_omx_video_dec_pause_loop (GstOMXVideoDec * self, GstFlowReturn flow_ret)
{ {
g_mutex_lock (&self->drain_lock); g_mutex_lock (&self->drain_lock);
if (self->draining) { if (self->draining) {
@ -1833,16 +1833,14 @@ component_error:
gst_omx_component_get_last_error_string (self->dec), gst_omx_component_get_last_error_string (self->dec),
gst_omx_component_get_last_error (self->dec))); gst_omx_component_get_last_error (self->dec)));
gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_event_new_eos ()); gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_event_new_eos ());
gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self)); gst_omx_video_dec_pause_loop (self, GST_FLOW_ERROR);
self->downstream_flow_ret = GST_FLOW_ERROR;
self->started = FALSE;
return; return;
} }
flushing: flushing:
{ {
GST_DEBUG_OBJECT (self, "Flushing -- stopping task"); GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
gst_omx_video_enc_pause_loop (self, GST_FLOW_FLUSHING); gst_omx_video_dec_pause_loop (self, GST_FLOW_FLUSHING);
return; return;
} }
@ -1887,8 +1885,6 @@ flow_error:
gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self),
gst_event_new_eos ()); gst_event_new_eos ());
gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
self->started = FALSE;
} else if (flow_ret < GST_FLOW_EOS) { } else if (flow_ret < GST_FLOW_EOS) {
GST_ELEMENT_ERROR (self, STREAM, FAILED, GST_ELEMENT_ERROR (self, STREAM, FAILED,
("Internal data stream error."), ("stream stopped, reason %s", ("Internal data stream error."), ("stream stopped, reason %s",
@ -1896,12 +1892,10 @@ flow_error:
gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self),
gst_event_new_eos ()); gst_event_new_eos ());
gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self));
self->started = FALSE;
} else if (flow_ret == GST_FLOW_FLUSHING) { } else if (flow_ret == GST_FLOW_FLUSHING) {
GST_DEBUG_OBJECT (self, "Flushing -- stopping task"); GST_DEBUG_OBJECT (self, "Flushing -- stopping task");
gst_omx_video_enc_pause_loop (self, flow_ret);
} }
gst_omx_video_dec_pause_loop (self, flow_ret);
GST_VIDEO_DECODER_STREAM_UNLOCK (self); GST_VIDEO_DECODER_STREAM_UNLOCK (self);
return; return;
} }
@ -1911,9 +1905,7 @@ reconfigure_error:
GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL), GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
("Unable to reconfigure output port")); ("Unable to reconfigure output port"));
gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_event_new_eos ()); gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_event_new_eos ());
gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self)); gst_omx_video_dec_pause_loop (self, GST_FLOW_ERROR);
self->downstream_flow_ret = GST_FLOW_ERROR;
self->started = FALSE;
return; return;
} }
@ -1922,9 +1914,7 @@ invalid_buffer:
GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL), GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL),
("Invalid sized input buffer")); ("Invalid sized input buffer"));
gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_event_new_eos ()); gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_event_new_eos ());
gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self)); gst_omx_video_dec_pause_loop (self, GST_FLOW_NOT_NEGOTIATED);
self->downstream_flow_ret = GST_FLOW_NOT_NEGOTIATED;
self->started = FALSE;
GST_VIDEO_DECODER_STREAM_UNLOCK (self); GST_VIDEO_DECODER_STREAM_UNLOCK (self);
return; return;
} }
@ -1933,10 +1923,8 @@ caps_failed:
{ {
GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL), ("Failed to set caps")); GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, (NULL), ("Failed to set caps"));
gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_event_new_eos ()); gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_event_new_eos ());
gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self)); gst_omx_video_dec_pause_loop (self, GST_FLOW_NOT_NEGOTIATED);
GST_VIDEO_DECODER_STREAM_UNLOCK (self); GST_VIDEO_DECODER_STREAM_UNLOCK (self);
self->downstream_flow_ret = GST_FLOW_NOT_NEGOTIATED;
self->started = FALSE;
return; return;
} }
release_error: release_error:
@ -1945,9 +1933,7 @@ release_error:
("Failed to relase output buffer to component: %s (0x%08x)", ("Failed to relase output buffer to component: %s (0x%08x)",
gst_omx_error_to_string (err), err)); gst_omx_error_to_string (err), err));
gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_event_new_eos ()); gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (self), gst_event_new_eos ());
gst_pad_pause_task (GST_VIDEO_DECODER_SRC_PAD (self)); gst_omx_video_dec_pause_loop (self, GST_FLOW_ERROR);
self->downstream_flow_ret = GST_FLOW_ERROR;
self->started = FALSE;
GST_VIDEO_DECODER_STREAM_UNLOCK (self); GST_VIDEO_DECODER_STREAM_UNLOCK (self);
return; return;
} }

View file

@ -74,7 +74,7 @@ struct _GstOMXVideoDec
GMutex drain_lock; GMutex drain_lock;
GCond drain_cond; GCond drain_cond;
/* TRUE if EOS buffers shouldn't be forwarded */ /* TRUE if EOS buffers shouldn't be forwarded */
gboolean draining; gboolean draining; /* protected by drain_lock */
GstFlowReturn downstream_flow_ret; GstFlowReturn downstream_flow_ret;
/* Initially FALSE. Switched to TRUE when all requirements /* Initially FALSE. Switched to TRUE when all requirements