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
This commit is contained in:
Josep Torra 2014-03-07 20:08:05 +01:00 committed by Julien Isorce
parent 39ca9f980e
commit 73d83f311c

View file

@ -1950,6 +1950,30 @@ gst_omx_video_dec_flush (GstVideoDecoder * decoder)
if (gst_omx_component_get_state (self->dec, 0) == OMX_StateLoaded) if (gst_omx_component_get_state (self->dec, 0) == OMX_StateLoaded)
return TRUE; 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_in_port, 5 * GST_SECOND, TRUE);
gst_omx_port_set_flushing (self->dec_out_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 #endif
/* Wait until the srcpad loop is finished, /* 3) Resume components */
* unlock GST_VIDEO_DECODER_STREAM_LOCK to prevent deadlocks gst_omx_component_set_state (self->dec, OMX_StateExecuting);
* caused by using this lock from inside the loop function */ gst_omx_component_get_state (self->dec, GST_CLOCK_TIME_NONE);
GST_VIDEO_DECODER_STREAM_UNLOCK (self); #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_EGL)
GST_PAD_STREAM_LOCK (GST_VIDEO_DECODER_SRC_PAD (self)); if (self->eglimage) {
GST_PAD_STREAM_UNLOCK (GST_VIDEO_DECODER_SRC_PAD (self)); gst_omx_component_set_state (self->egl_render, OMX_StateExecuting);
GST_VIDEO_DECODER_STREAM_LOCK (self); 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_in_port, 5 * GST_SECOND, FALSE);
gst_omx_port_set_flushing (self->dec_out_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_in_port, 5 * GST_SECOND, FALSE);
gst_omx_port_set_flushing (self->egl_out_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); err = gst_omx_port_populate (self->egl_out_port);
gst_omx_port_mark_reconfigured (self->egl_out_port);
} else { } else {
err = gst_omx_port_populate (self->dec_out_port); 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); gst_omx_error_to_string (err), err);
} }
/* Start the srcpad loop again */ /* Reset our state */
self->last_upstream_ts = 0; self->last_upstream_ts = 0;
self->eos = FALSE; self->eos = FALSE;
self->downstream_flow_ret = GST_FLOW_OK; self->downstream_flow_ret = GST_FLOW_OK;
gst_pad_start_task (GST_VIDEO_DECODER_SRC_PAD (self), self->started = FALSE;
(GstTaskFunction) gst_omx_video_dec_loop, decoder, NULL); GST_DEBUG_OBJECT (self, "Flush finished");
GST_DEBUG_OBJECT (self, "Flush decoder");
return TRUE; return TRUE;
} }
@ -2025,9 +2051,14 @@ gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder,
return GST_FLOW_EOS; return GST_FLOW_EOS;
} }
if (!self->started && !GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame)) { if (!self->started) {
gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame); if (!GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame)) {
return GST_FLOW_OK; 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; timestamp = frame->pts;