summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosep Torra <n770galaxy@gmail.com>2014-03-07 20:08:05 +0100
committerJulien Isorce <julien.isorce@collabora.co.uk>2014-03-25 16:07:25 +0000
commit73d83f311c23429f86fc2377f2b2828db5af9898 (patch)
tree31fc092c4a74056d647a63ea04e725115584d38f
parent39ca9f980eeca0610cdc3fec2774681514a16ff2 (diff)
omxvideodec: fixes race condition during seeks
Acording 6.1.3 Seek Event Sequence in the OpenMAX IL 1.1.2 spec document in order to flush the component it needs to be in paused state. https://bugzilla.gnome.org/show_bug.cgi?id=726038
-rw-r--r--omx/gstomxvideodec.c61
1 files changed, 46 insertions, 15 deletions
diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c
index 8a46d40..682ac8f 100644
--- a/omx/gstomxvideodec.c
+++ b/omx/gstomxvideodec.c
@@ -1950,6 +1950,30 @@ gst_omx_video_dec_flush (GstVideoDecoder * decoder)
if (gst_omx_component_get_state (self->dec, 0) == OMX_StateLoaded)
return TRUE;
+ /* 0) Wait until the srcpad loop is stopped,
+ * unlock GST_VIDEO_DECODER_STREAM_LOCK to prevent deadlocks
+ * caused by using this lock from inside the loop function */
+ GST_VIDEO_DECODER_STREAM_UNLOCK (self);
+ gst_pad_stop_task (GST_VIDEO_DECODER_SRC_PAD (decoder));
+ GST_DEBUG_OBJECT (self, "Flushing -- task stopped");
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+
+ /* 1) Pause the components */
+ if (gst_omx_component_get_state (self->dec, 0) == OMX_StateExecuting) {
+ gst_omx_component_set_state (self->dec, OMX_StatePause);
+ gst_omx_component_get_state (self->dec, GST_CLOCK_TIME_NONE);
+ }
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_EGL)
+ if (self->eglimage) {
+ if (gst_omx_component_get_state (self->egl_render, 0) == OMX_StateExecuting) {
+ gst_omx_component_set_state (self->egl_render, OMX_StatePause);
+ gst_omx_component_get_state (self->egl_render, GST_CLOCK_TIME_NONE);
+ }
+ }
+#endif
+
+ /* 2) Flush the ports */
+ GST_DEBUG_OBJECT (self, "flushing ports");
gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, TRUE);
@@ -1960,14 +1984,17 @@ gst_omx_video_dec_flush (GstVideoDecoder * decoder)
}
#endif
- /* Wait until the srcpad loop is finished,
- * unlock GST_VIDEO_DECODER_STREAM_LOCK to prevent deadlocks
- * caused by using this lock from inside the loop function */
- GST_VIDEO_DECODER_STREAM_UNLOCK (self);
- GST_PAD_STREAM_LOCK (GST_VIDEO_DECODER_SRC_PAD (self));
- GST_PAD_STREAM_UNLOCK (GST_VIDEO_DECODER_SRC_PAD (self));
- GST_VIDEO_DECODER_STREAM_LOCK (self);
+ /* 3) Resume components */
+ gst_omx_component_set_state (self->dec, OMX_StateExecuting);
+ gst_omx_component_get_state (self->dec, GST_CLOCK_TIME_NONE);
+#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_EGL)
+ if (self->eglimage) {
+ gst_omx_component_set_state (self->egl_render, OMX_StateExecuting);
+ gst_omx_component_get_state (self->egl_render, GST_CLOCK_TIME_NONE);
+ }
+#endif
+ /* 4) Unset flushing to allow ports to accept data again */
gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, FALSE);
gst_omx_port_set_flushing (self->dec_out_port, 5 * GST_SECOND, FALSE);
@@ -1976,6 +2003,7 @@ gst_omx_video_dec_flush (GstVideoDecoder * decoder)
gst_omx_port_set_flushing (self->egl_in_port, 5 * GST_SECOND, FALSE);
gst_omx_port_set_flushing (self->egl_out_port, 5 * GST_SECOND, FALSE);
err = gst_omx_port_populate (self->egl_out_port);
+ gst_omx_port_mark_reconfigured (self->egl_out_port);
} else {
err = gst_omx_port_populate (self->dec_out_port);
}
@@ -1988,14 +2016,12 @@ gst_omx_video_dec_flush (GstVideoDecoder * decoder)
gst_omx_error_to_string (err), err);
}
- /* Start the srcpad loop again */
+ /* Reset our state */
self->last_upstream_ts = 0;
self->eos = FALSE;
self->downstream_flow_ret = GST_FLOW_OK;
- gst_pad_start_task (GST_VIDEO_DECODER_SRC_PAD (self),
- (GstTaskFunction) gst_omx_video_dec_loop, decoder, NULL);
-
- GST_DEBUG_OBJECT (self, "Flush decoder");
+ self->started = FALSE;
+ GST_DEBUG_OBJECT (self, "Flush finished");
return TRUE;
}
@@ -2025,9 +2051,14 @@ gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder,
return GST_FLOW_EOS;
}
- if (!self->started && !GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame)) {
- gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
- return GST_FLOW_OK;
+ if (!self->started) {
+ if (!GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame)) {
+ gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
+ return GST_FLOW_OK;
+ }
+ GST_DEBUG_OBJECT (self, "Starting task");
+ gst_pad_start_task (GST_VIDEO_DECODER_SRC_PAD (self),
+ (GstTaskFunction) gst_omx_video_dec_loop, decoder, NULL);
}
timestamp = frame->pts;