omx: Let base classes handle EOS

https://bugzilla.gnome.org//show_bug.cgi?id=734774
This commit is contained in:
Sebastian Dröge 2014-08-14 17:36:11 +03:00
parent 19d77004d2
commit d75334456d
8 changed files with 22 additions and 177 deletions

View file

@ -50,8 +50,7 @@ static gboolean gst_omx_audio_dec_set_format (GstAudioDecoder * decoder,
static void gst_omx_audio_dec_flush (GstAudioDecoder * decoder, gboolean hard);
static GstFlowReturn gst_omx_audio_dec_handle_frame (GstAudioDecoder * decoder,
GstBuffer * buffer);
static GstFlowReturn gst_omx_audio_dec_drain (GstOMXAudioDec * self,
gboolean is_eos);
static GstFlowReturn gst_omx_audio_dec_drain (GstOMXAudioDec * self);
enum
{
@ -701,7 +700,6 @@ gst_omx_audio_dec_start (GstAudioDecoder * decoder)
self = GST_OMX_AUDIO_DEC (decoder);
self->last_upstream_ts = 0;
self->eos = FALSE;
self->downstream_flow_ret = GST_FLOW_OK;
return TRUE;
@ -726,7 +724,6 @@ gst_omx_audio_dec_stop (GstAudioDecoder * decoder)
self->downstream_flow_ret = GST_FLOW_FLUSHING;
self->started = FALSE;
self->eos = FALSE;
g_mutex_lock (&self->drain_lock);
self->draining = FALSE;
@ -781,7 +778,7 @@ gst_omx_audio_dec_set_format (GstAudioDecoder * decoder, GstCaps * caps)
GST_DEBUG_OBJECT (self, "Need to disable and drain decoder");
gst_omx_audio_dec_drain (self, FALSE);
gst_omx_audio_dec_drain (self);
gst_omx_audio_dec_flush (decoder, FALSE);
gst_omx_port_set_flushing (out_port, 5 * GST_SECOND, TRUE);
@ -972,7 +969,6 @@ gst_omx_audio_dec_flush (GstAudioDecoder * decoder, gboolean hard)
/* Reset our state */
self->last_upstream_ts = 0;
self->eos = FALSE;
self->downstream_flow_ret = GST_FLOW_OK;
self->started = FALSE;
GST_DEBUG_OBJECT (self, "Flush finished");
@ -1001,13 +997,6 @@ gst_omx_audio_dec_handle_frame (GstAudioDecoder * decoder, GstBuffer * inbuf)
if (inbuf)
gst_buffer_ref (inbuf);
if (self->eos) {
GST_WARNING_OBJECT (self, "Got frame after EOS");
if (inbuf)
gst_buffer_unref (inbuf);
return GST_FLOW_EOS;
}
if (self->downstream_flow_ret != GST_FLOW_OK) {
if (inbuf)
gst_buffer_unref (inbuf);
@ -1021,7 +1010,7 @@ gst_omx_audio_dec_handle_frame (GstAudioDecoder * decoder, GstBuffer * inbuf)
}
if (inbuf == NULL)
return gst_omx_audio_dec_drain (self, TRUE);
return gst_omx_audio_dec_drain (self);
timestamp = GST_BUFFER_TIMESTAMP (inbuf);
duration = GST_BUFFER_DURATION (inbuf);
@ -1272,7 +1261,7 @@ release_error:
}
static GstFlowReturn
gst_omx_audio_dec_drain (GstOMXAudioDec * self, gboolean is_eos)
gst_omx_audio_dec_drain (GstOMXAudioDec * self)
{
GstOMXAudioDecClass *klass;
GstOMXBuffer *buf;
@ -1289,14 +1278,6 @@ gst_omx_audio_dec_drain (GstOMXAudioDec * self, gboolean is_eos)
}
self->started = FALSE;
/* Don't send EOS buffer twice, this doesn't work */
if (self->eos) {
GST_DEBUG_OBJECT (self, "Component is EOS already");
return GST_FLOW_OK;
}
if (is_eos)
self->eos = TRUE;
if ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)) {
GST_WARNING_OBJECT (self, "Component does not support empty EOS buffers");
return GST_FLOW_OK;

View file

@ -76,9 +76,6 @@ struct _GstOMXAudioDec
/* TRUE if EOS buffers shouldn't be forwarded */
gboolean draining;
/* TRUE if upstream is EOS */
gboolean eos;
GstFlowReturn downstream_flow_ret;
};

View file

@ -41,8 +41,6 @@ static gboolean gst_omx_audio_enc_start (GstAudioEncoder * encoder);
static gboolean gst_omx_audio_enc_stop (GstAudioEncoder * encoder);
static gboolean gst_omx_audio_enc_set_format (GstAudioEncoder * encoder,
GstAudioInfo * info);
static gboolean gst_omx_audio_enc_sink_event (GstAudioEncoder * encoder,
GstEvent * event);
static GstFlowReturn gst_omx_audio_enc_handle_frame (GstAudioEncoder *
encoder, GstBuffer * buffer);
static void gst_omx_audio_enc_flush (GstAudioEncoder * encoder);
@ -82,8 +80,6 @@ gst_omx_audio_enc_class_init (GstOMXAudioEncClass * klass)
GST_DEBUG_FUNCPTR (gst_omx_audio_enc_set_format);
audio_encoder_class->handle_frame =
GST_DEBUG_FUNCPTR (gst_omx_audio_enc_handle_frame);
audio_encoder_class->sink_event =
GST_DEBUG_FUNCPTR (gst_omx_audio_enc_sink_event);
klass->cdata.type = GST_OMX_COMPONENT_TYPE_FILTER;
klass->cdata.default_sink_template_caps = "audio/x-raw, "
@ -592,7 +588,6 @@ gst_omx_audio_enc_start (GstAudioEncoder * encoder)
self = GST_OMX_AUDIO_ENC (encoder);
self->last_upstream_ts = 0;
self->eos = FALSE;
self->downstream_flow_ret = GST_FLOW_OK;
return TRUE;
@ -617,7 +612,6 @@ gst_omx_audio_enc_stop (GstAudioEncoder * encoder)
self->downstream_flow_ret = GST_FLOW_FLUSHING;
self->started = FALSE;
self->eos = FALSE;
g_mutex_lock (&self->drain_lock);
self->draining = FALSE;
@ -887,7 +881,7 @@ gst_omx_audio_enc_flush (GstAudioEncoder * encoder)
/* Start the srcpad loop again */
self->last_upstream_ts = 0;
self->downstream_flow_ret = GST_FLOW_OK;
self->eos = FALSE;
self->started = FALSE;
gst_pad_start_task (GST_AUDIO_ENCODER_SRC_PAD (self),
(GstTaskFunction) gst_omx_audio_enc_loop, encoder, NULL);
}
@ -906,11 +900,6 @@ gst_omx_audio_enc_handle_frame (GstAudioEncoder * encoder, GstBuffer * inbuf)
self = GST_OMX_AUDIO_ENC (encoder);
if (self->eos) {
GST_WARNING_OBJECT (self, "Got frame after EOS");
return GST_FLOW_EOS;
}
if (self->downstream_flow_ret != GST_FLOW_OK) {
return self->downstream_flow_ret;
}
@ -1085,77 +1074,6 @@ release_error:
}
}
static gboolean
gst_omx_audio_enc_sink_event (GstAudioEncoder * encoder, GstEvent * event)
{
GstOMXAudioEnc *self;
GstOMXAudioEncClass *klass;
OMX_ERRORTYPE err;
self = GST_OMX_AUDIO_ENC (encoder);
klass = GST_OMX_AUDIO_ENC_GET_CLASS (self);
if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
GstOMXBuffer *buf;
GstOMXAcquireBufferReturn acq_ret;
GST_DEBUG_OBJECT (self, "Sending EOS to the component");
/* Don't send EOS buffer twice, this doesn't work */
if (self->eos) {
GST_DEBUG_OBJECT (self, "Component is already EOS");
return TRUE;
}
self->eos = TRUE;
if ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)) {
GST_WARNING_OBJECT (self, "Component does not support empty EOS buffers");
/* Insert a NULL into the queue to signal EOS */
g_mutex_lock (&self->enc->lock);
g_queue_push_tail (&self->enc_out_port->pending_buffers, NULL);
g_mutex_unlock (&self->enc->lock);
g_mutex_lock (&self->enc->messages_lock);
g_cond_broadcast (&self->enc->messages_cond);
g_mutex_unlock (&self->enc->messages_lock);
return TRUE;
}
/* Make sure to release the base class stream lock, otherwise
* _loop() can't call _finish_frame() and we might block forever
* because no input buffers are released */
GST_AUDIO_ENCODER_STREAM_UNLOCK (self);
/* Send an EOS buffer to the component and let the base
* class drop the EOS event. We will send it later when
* the EOS buffer arrives on the output port. */
acq_ret = gst_omx_port_acquire_buffer (self->enc_in_port, &buf);
if (acq_ret == GST_OMX_ACQUIRE_BUFFER_OK) {
buf->omx_buf->nFilledLen = 0;
buf->omx_buf->nTimeStamp =
gst_util_uint64_scale (self->last_upstream_ts, OMX_TICKS_PER_SECOND,
GST_SECOND);
buf->omx_buf->nTickCount = 0;
buf->omx_buf->nFlags |= OMX_BUFFERFLAG_EOS;
err = gst_omx_port_release_buffer (self->enc_in_port, buf);
if (err != OMX_ErrorNone) {
GST_ERROR_OBJECT (self, "Failed to send EOS to component: %s (0x%08x)",
gst_omx_error_to_string (err), err);
} else {
GST_DEBUG_OBJECT (self, "Sent EOS to the component");
}
} else {
GST_ERROR_OBJECT (self, "Failed to acquire buffer for EOS: %d", acq_ret);
}
GST_AUDIO_ENCODER_STREAM_LOCK (self);
return TRUE;
}
return FALSE;
}
static GstFlowReturn
gst_omx_audio_enc_drain (GstOMXAudioEnc * self)
{
@ -1174,12 +1092,6 @@ gst_omx_audio_enc_drain (GstOMXAudioEnc * self)
}
self->started = FALSE;
/* Don't send EOS buffer twice, this doesn't work */
if (self->eos) {
GST_DEBUG_OBJECT (self, "Component is EOS already");
return GST_FLOW_OK;
}
if ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)) {
GST_WARNING_OBJECT (self, "Component does not support empty EOS buffers");
return GST_FLOW_OK;

View file

@ -60,9 +60,6 @@ struct _GstOMXAudioEnc
GstClockTime last_upstream_ts;
/* TRUE if upstream is EOS */
gboolean eos;
/* Draining state */
GMutex drain_lock;
GCond drain_cond;

View file

@ -75,8 +75,7 @@ static GstFlowReturn gst_omx_video_dec_finish (GstVideoDecoder * decoder);
static gboolean gst_omx_video_dec_decide_allocation (GstVideoDecoder * bdec,
GstQuery * query);
static GstFlowReturn gst_omx_video_dec_drain (GstOMXVideoDec * self,
gboolean is_eos);
static GstFlowReturn gst_omx_video_dec_drain (GstOMXVideoDec * self);
static OMX_ERRORTYPE gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec *
self);
@ -1654,7 +1653,6 @@ gst_omx_video_dec_start (GstVideoDecoder * decoder)
self = GST_OMX_VIDEO_DEC (decoder);
self->last_upstream_ts = 0;
self->eos = FALSE;
self->downstream_flow_ret = GST_FLOW_OK;
return TRUE;
@ -1688,7 +1686,6 @@ gst_omx_video_dec_stop (GstVideoDecoder * decoder)
self->downstream_flow_ret = GST_FLOW_FLUSHING;
self->started = FALSE;
self->eos = FALSE;
g_mutex_lock (&self->drain_lock);
self->draining = FALSE;
@ -1862,7 +1859,7 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
GST_DEBUG_OBJECT (self, "Need to disable and drain decoder");
gst_omx_video_dec_drain (self, FALSE);
gst_omx_video_dec_drain (self);
gst_omx_video_dec_flush (decoder);
gst_omx_port_set_flushing (out_port, 5 * GST_SECOND, TRUE);
@ -2067,15 +2064,7 @@ 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 */
/* 0) 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);
@ -2089,6 +2078,14 @@ gst_omx_video_dec_flush (GstVideoDecoder * decoder)
}
#endif
/* 1) 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);
/* 2) Flush the ports */
GST_DEBUG_OBJECT (self, "flushing ports");
gst_omx_port_set_flushing (self->dec_in_port, 5 * GST_SECOND, TRUE);
@ -2135,7 +2132,6 @@ gst_omx_video_dec_flush (GstVideoDecoder * decoder)
/* Reset our state */
self->last_upstream_ts = 0;
self->eos = FALSE;
self->downstream_flow_ret = GST_FLOW_OK;
self->started = FALSE;
GST_DEBUG_OBJECT (self, "Flush finished");
@ -2162,12 +2158,6 @@ gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder,
GST_DEBUG_OBJECT (self, "Handling frame");
if (self->eos) {
GST_WARNING_OBJECT (self, "Got frame after EOS");
gst_video_codec_frame_unref (frame);
return GST_FLOW_EOS;
}
if (!self->started) {
if (!GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame)) {
gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
@ -2434,11 +2424,11 @@ gst_omx_video_dec_finish (GstVideoDecoder * decoder)
self = GST_OMX_VIDEO_DEC (decoder);
return gst_omx_video_dec_drain (self, TRUE);
return gst_omx_video_dec_drain (self);
}
static GstFlowReturn
gst_omx_video_dec_drain (GstOMXVideoDec * self, gboolean is_eos)
gst_omx_video_dec_drain (GstOMXVideoDec * self)
{
GstOMXVideoDecClass *klass;
GstOMXBuffer *buf;
@ -2455,14 +2445,6 @@ gst_omx_video_dec_drain (GstOMXVideoDec * self, gboolean is_eos)
}
self->started = FALSE;
/* Don't send EOS buffer twice, this doesn't work */
if (self->eos) {
GST_DEBUG_OBJECT (self, "Component is EOS already");
return GST_FLOW_OK;
}
if (is_eos)
self->eos = TRUE;
if ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)) {
GST_WARNING_OBJECT (self, "Component does not support empty EOS buffers");
return GST_FLOW_OK;

View file

@ -74,9 +74,6 @@ struct _GstOMXVideoDec
/* TRUE if EOS buffers shouldn't be forwarded */
gboolean draining;
/* TRUE if upstream is EOS */
gboolean eos;
GstFlowReturn downstream_flow_ret;
#ifdef USE_OMX_TARGET_RPI
GstOMXComponent *egl_render;

View file

@ -83,8 +83,7 @@ static gboolean gst_omx_video_enc_propose_allocation (GstVideoEncoder * encoder,
static GstCaps *gst_omx_video_enc_getcaps (GstVideoEncoder * encoder,
GstCaps * filter);
static GstFlowReturn gst_omx_video_enc_drain (GstOMXVideoEnc * self,
gboolean at_eos);
static GstFlowReturn gst_omx_video_enc_drain (GstOMXVideoEnc * self);
static GstFlowReturn gst_omx_video_enc_handle_output_frame (GstOMXVideoEnc *
self, GstOMXPort * port, GstOMXBuffer * buf, GstVideoCodecFrame * frame);
@ -882,7 +881,6 @@ gst_omx_video_enc_start (GstVideoEncoder * encoder)
self = GST_OMX_VIDEO_ENC (encoder);
self->last_upstream_ts = 0;
self->eos = FALSE;
self->downstream_flow_ret = GST_FLOW_OK;
return TRUE;
@ -907,7 +905,6 @@ gst_omx_video_enc_stop (GstVideoEncoder * encoder)
self->downstream_flow_ret = GST_FLOW_FLUSHING;
self->started = FALSE;
self->eos = FALSE;
if (self->input_state)
gst_video_codec_state_unref (self->input_state);
@ -951,7 +948,7 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
*/
if (needs_disable) {
GST_DEBUG_OBJECT (self, "Need to disable and drain encoder");
gst_omx_video_enc_drain (self, FALSE);
gst_omx_video_enc_drain (self);
gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, TRUE);
/* Wait until the srcpad loop is finished,
@ -1206,7 +1203,6 @@ gst_omx_video_enc_flush (GstVideoEncoder * encoder)
/* Start the srcpad loop again */
self->last_upstream_ts = 0;
self->eos = FALSE;
self->downstream_flow_ret = GST_FLOW_OK;
gst_pad_start_task (GST_VIDEO_ENCODER_SRC_PAD (self),
(GstTaskFunction) gst_omx_video_enc_loop, encoder, NULL);
@ -1394,12 +1390,6 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder,
GST_DEBUG_OBJECT (self, "Handling frame");
if (self->eos) {
GST_WARNING_OBJECT (self, "Got frame after EOS");
gst_video_codec_frame_unref (frame);
return GST_FLOW_EOS;
}
if (self->downstream_flow_ret != GST_FLOW_OK) {
gst_video_codec_frame_unref (frame);
return self->downstream_flow_ret;
@ -1606,11 +1596,11 @@ gst_omx_video_enc_finish (GstVideoEncoder * encoder)
self = GST_OMX_VIDEO_ENC (encoder);
return gst_omx_video_enc_drain (self, TRUE);
return gst_omx_video_enc_drain (self);
}
static GstFlowReturn
gst_omx_video_enc_drain (GstOMXVideoEnc * self, gboolean at_eos)
gst_omx_video_enc_drain (GstOMXVideoEnc * self)
{
GstOMXVideoEncClass *klass;
GstOMXBuffer *buf;
@ -1627,14 +1617,6 @@ gst_omx_video_enc_drain (GstOMXVideoEnc * self, gboolean at_eos)
}
self->started = FALSE;
/* Don't send EOS buffer twice, this doesn't work */
if (self->eos) {
GST_DEBUG_OBJECT (self, "Component is EOS already");
return GST_FLOW_OK;
}
if (at_eos)
self->eos = TRUE;
if ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)) {
GST_WARNING_OBJECT (self, "Component does not support empty EOS buffers");
return GST_FLOW_OK;

View file

@ -67,9 +67,6 @@ struct _GstOMXVideoEnc
/* TRUE if EOS buffers shouldn't be forwarded */
gboolean draining;
/* TRUE if upstream is EOS */
gboolean eos;
/* properties */
guint32 control_rate;
guint32 target_bitrate;