diff options
author | Josep Torra <n770galaxy@gmail.com> | 2014-03-07 20:08:05 +0100 |
---|---|---|
committer | Josep Torra <n770galaxy@gmail.com> | 2014-03-25 15:41:18 +0100 |
commit | 31408c00abcf95ae257fce79640851262eaa858a (patch) | |
tree | 31fc092c4a74056d647a63ea04e725115584d38f | |
parent | 1ed0055071f0becc50b6b299c020c9a4e46c836a (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.c | 61 |
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; |