From 73d83f311c23429f86fc2377f2b2828db5af9898 Mon Sep 17 00:00:00 2001 From: Josep Torra Date: Fri, 7 Mar 2014 20:08:05 +0100 Subject: [PATCH] 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 --- omx/gstomxvideodec.c | 61 +++++++++++++++++++++++++++++++++++++++------------- 1 file 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; -- 2.7.4