summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosep Torra <n770galaxy@gmail.com>2014-03-07 20:08:05 +0100
committerJosep Torra <n770galaxy@gmail.com>2014-03-25 15:41:18 +0100
commit31408c00abcf95ae257fce79640851262eaa858a (patch)
tree31fc092c4a74056d647a63ea04e725115584d38f
parent1ed0055071f0becc50b6b299c020c9a4e46c836a (diff)
omxvideodec: fixes race condition during seeksseeking
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.
-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;