From 22dce51dd46f6901ca8615cbbb9538d612a97545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 14 Mar 2013 12:49:42 +0100 Subject: omx: Handle the OMX_EventBufferFlag to detect EOS too --- omx/gstomx.c | 56 +++++++++++- omx/gstomx.h | 8 ++ omx/gstomxaudioenc.c | 199 +++++++++++++++++++++-------------------- omx/gstomxvideodec.c | 243 +++++++++++++++++++++++++-------------------------- omx/gstomxvideoenc.c | 70 +++++++-------- 5 files changed, 321 insertions(+), 255 deletions(-) diff --git a/omx/gstomx.c b/omx/gstomx.c index 84bac15..5545de8 100644 --- a/omx/gstomx.c +++ b/omx/gstomx.c @@ -321,6 +321,23 @@ gst_omx_component_handle_messages (GstOMXComponent * comp) break; } + case GST_OMX_MESSAGE_BUFFER_FLAG:{ + GstOMXPort *port = NULL; + OMX_U32 index = msg->content.buffer_flag.port; + OMX_U32 flags = msg->content.buffer_flag.flags; + + port = gst_omx_component_get_port (comp, index); + if (!port) + break; + + GST_DEBUG_OBJECT (comp->parent, "Port %u got buffer flags 0x%08x", + port->index, flags); + if ((flags & OMX_BUFFERFLAG_EOS) + && port->port_def.eDir == OMX_DirOutput) + port->eos = TRUE; + + break; + } case GST_OMX_MESSAGE_BUFFER_DONE:{ GstOMXBuffer *buf = msg->content.buffer_done.buffer->pAppPrivate; GstOMXPort *port; @@ -356,6 +373,10 @@ gst_omx_component_handle_messages (GstOMXComponent * comp) * the port was flushed */ GST_DEBUG_OBJECT (comp->parent, "Port %u filled buffer %p (%p)", port->index, buf, buf->omx_buf->pBuffer); + + if ((buf->omx_buf->nFlags & OMX_BUFFERFLAG_EOS) + && port->port_def.eDir == OMX_DirOutput) + port->eos = TRUE; } buf->used = FALSE; @@ -491,8 +512,21 @@ EventHandler (OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_EVENTTYPE eEvent, gst_omx_component_send_message (comp, msg); break; } + case OMX_EventBufferFlag:{ + GstOMXMessage *msg; + + msg = g_slice_new (GstOMXMessage); + + msg->type = GST_OMX_MESSAGE_BUFFER_FLAG; + msg->content.buffer_flag.port = nData1; + msg->content.buffer_flag.flags = nData2; + GST_DEBUG_OBJECT (comp->parent, "Port %u got buffer flags 0x%08x", + msg->content.buffer_flag.port, msg->content.buffer_flag.flags); + + gst_omx_component_send_message (comp, msg); + break; + } case OMX_EventPortFormatDetected: - case OMX_EventBufferFlag: default: GST_DEBUG_OBJECT (comp->parent, "Unknown event 0x%08x", eEvent); break; @@ -879,6 +913,7 @@ gst_omx_component_add_port (GstOMXComponent * comp, guint32 index) port->flushed = FALSE; port->enabled_pending = FALSE; port->disabled_pending = FALSE; + port->eos = FALSE; if (port->port_def.eDir == OMX_DirInput) comp->n_in_ports++; @@ -1237,8 +1272,22 @@ retry: goto done; } + if (port->port_def.eDir == OMX_DirOutput && port->eos) { + if (!g_queue_is_empty (&port->pending_buffers)) { + GST_DEBUG_OBJECT (comp->parent, + "Output port %u is EOS but has buffers pending", port->index); + _buf = g_queue_pop_head (&port->pending_buffers); + + ret = GST_OMX_ACQUIRE_BUFFER_OK; + goto done; + } + + ret = GST_OMX_ACQUIRE_BUFFER_EOS; + goto done; + } + /* - * At this point we have no error or flushing port + * At this point we have no error or flushing/eos port * and a properly configured port. * */ @@ -1478,6 +1527,9 @@ gst_omx_port_set_flushing (GstOMXPort * port, GstClockTime timeout, err = OMX_ErrorTimeout; goto done; } + + /* Reset EOS flag */ + port->eos = FALSE; } done: diff --git a/omx/gstomx.h b/omx/gstomx.h index eedb9ef..92580a6 100644 --- a/omx/gstomx.h +++ b/omx/gstomx.h @@ -118,6 +118,8 @@ typedef enum { GST_OMX_ACQUIRE_BUFFER_FLUSHING, /* The port must be reconfigured */ GST_OMX_ACQUIRE_BUFFER_RECONFIGURE, + /* The port is EOS */ + GST_OMX_ACQUIRE_BUFFER_EOS, /* A fatal error happened */ GST_OMX_ACQUIRE_BUFFER_ERROR } GstOMXAcquireBufferReturn; @@ -146,6 +148,7 @@ typedef enum { GST_OMX_MESSAGE_ERROR, GST_OMX_MESSAGE_PORT_ENABLE, GST_OMX_MESSAGE_PORT_SETTINGS_CHANGED, + GST_OMX_MESSAGE_BUFFER_FLAG, GST_OMX_MESSAGE_BUFFER_DONE, } GstOMXMessageType; @@ -169,6 +172,10 @@ struct _GstOMXMessage { struct { OMX_U32 port; } port_settings_changed; + struct { + OMX_U32 port; + OMX_U32 flags; + } buffer_flag; struct { OMX_HANDLETYPE component; OMX_PTR app_data; @@ -191,6 +198,7 @@ struct _GstOMXPort { gboolean flushed; /* TRUE after OMX_CommandFlush was done */ gboolean enabled_pending; /* TRUE after OMX_Command{En,Dis}able */ gboolean disabled_pending; /* was done until it took effect */ + gboolean eos; /* TRUE after a buffer with EOS flag was received */ /* Increased whenever the settings of these port change. * If settings_cookie != configured_settings_cookie diff --git a/omx/gstomxaudioenc.c b/omx/gstomxaudioenc.c index 496c539..1a2344b 100644 --- a/omx/gstomxaudioenc.c +++ b/omx/gstomxaudioenc.c @@ -282,7 +282,6 @@ gst_omx_audio_enc_loop (GstOMXAudioEnc * self) GstOMXBuffer *buf = NULL; GstFlowReturn flow_ret = GST_FLOW_OK; GstOMXAcquireBufferReturn acq_return; - gboolean is_eos; OMX_ERRORTYPE err; klass = GST_OMX_AUDIO_ENC_GET_CLASS (self); @@ -292,6 +291,8 @@ gst_omx_audio_enc_loop (GstOMXAudioEnc * self) goto component_error; } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_FLUSHING) { goto flushing; + } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_EOS) { + goto eos; } if (!gst_pad_has_current_caps (GST_AUDIO_ENCODER_SRC_PAD (self)) @@ -374,120 +375,103 @@ gst_omx_audio_enc_loop (GstOMXAudioEnc * self) } g_assert (acq_return == GST_OMX_ACQUIRE_BUFFER_OK); - - if (buf) { - GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %lu", buf->omx_buf->nFlags, - buf->omx_buf->nTimeStamp); - - /* This prevents a deadlock between the srcpad stream - * lock and the videocodec stream lock, if ::reset() - * is called at the wrong time - */ - if (gst_omx_port_is_flushing (self->enc_out_port)) { - GST_DEBUG_OBJECT (self, "Flushing"); - gst_omx_port_release_buffer (self->enc_out_port, buf); - goto flushing; - } - + if (!buf) { + g_assert ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)); GST_AUDIO_ENCODER_STREAM_LOCK (self); - is_eos = ! !(buf->omx_buf->nFlags & OMX_BUFFERFLAG_EOS); + goto eos; + } - if ((buf->omx_buf->nFlags & OMX_BUFFERFLAG_CODECCONFIG) - && buf->omx_buf->nFilledLen > 0) { - GstCaps *caps; - GstBuffer *codec_data; - GstMapInfo map = GST_MAP_INFO_INIT; + GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %lu", buf->omx_buf->nFlags, + buf->omx_buf->nTimeStamp); - GST_DEBUG_OBJECT (self, "Handling codec data"); - caps = - gst_caps_copy (gst_pad_get_current_caps (GST_AUDIO_ENCODER_SRC_PAD - (self))); - codec_data = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen); + /* This prevents a deadlock between the srcpad stream + * lock and the videocodec stream lock, if ::reset() + * is called at the wrong time + */ + if (gst_omx_port_is_flushing (self->enc_out_port)) { + GST_DEBUG_OBJECT (self, "Flushing"); + gst_omx_port_release_buffer (self->enc_out_port, buf); + goto flushing; + } - gst_buffer_map (codec_data, &map, GST_MAP_WRITE); - memcpy (map.data, - buf->omx_buf->pBuffer + buf->omx_buf->nOffset, - buf->omx_buf->nFilledLen); - gst_buffer_unmap (codec_data, &map); - - gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, codec_data, - NULL); - if (!gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (self), caps)) { - gst_caps_unref (caps); - if (buf) - gst_omx_port_release_buffer (self->enc_out_port, buf); - GST_AUDIO_ENCODER_STREAM_UNLOCK (self); - goto caps_failed; - } - gst_caps_unref (caps); - flow_ret = GST_FLOW_OK; - } else if (buf->omx_buf->nFilledLen > 0) { - GstBuffer *outbuf; - guint n_samples; + GST_AUDIO_ENCODER_STREAM_LOCK (self); - GST_DEBUG_OBJECT (self, "Handling output data"); + if ((buf->omx_buf->nFlags & OMX_BUFFERFLAG_CODECCONFIG) + && buf->omx_buf->nFilledLen > 0) { + GstCaps *caps; + GstBuffer *codec_data; + GstMapInfo map = GST_MAP_INFO_INIT; - n_samples = - klass->get_num_samples (self, self->enc_out_port, - gst_audio_encoder_get_audio_info (GST_AUDIO_ENCODER (self)), buf); + GST_DEBUG_OBJECT (self, "Handling codec data"); + caps = + gst_caps_copy (gst_pad_get_current_caps (GST_AUDIO_ENCODER_SRC_PAD + (self))); + codec_data = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen); - if (buf->omx_buf->nFilledLen > 0) { - GstMapInfo map = GST_MAP_INFO_INIT; - outbuf = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen); + gst_buffer_map (codec_data, &map, GST_MAP_WRITE); + memcpy (map.data, + buf->omx_buf->pBuffer + buf->omx_buf->nOffset, + buf->omx_buf->nFilledLen); + gst_buffer_unmap (codec_data, &map); - gst_buffer_map (outbuf, &map, GST_MAP_WRITE); + gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, codec_data, NULL); + if (!gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (self), caps)) { + gst_caps_unref (caps); + if (buf) + gst_omx_port_release_buffer (self->enc_out_port, buf); + GST_AUDIO_ENCODER_STREAM_UNLOCK (self); + goto caps_failed; + } + gst_caps_unref (caps); + flow_ret = GST_FLOW_OK; + } else if (buf->omx_buf->nFilledLen > 0) { + GstBuffer *outbuf; + guint n_samples; - memcpy (map.data, - buf->omx_buf->pBuffer + buf->omx_buf->nOffset, - buf->omx_buf->nFilledLen); - gst_buffer_unmap (outbuf, &map); + GST_DEBUG_OBJECT (self, "Handling output data"); - } else { - outbuf = gst_buffer_new (); - } + n_samples = + klass->get_num_samples (self, self->enc_out_port, + gst_audio_encoder_get_audio_info (GST_AUDIO_ENCODER (self)), buf); - GST_BUFFER_TIMESTAMP (outbuf) = - gst_util_uint64_scale (buf->omx_buf->nTimeStamp, GST_SECOND, - OMX_TICKS_PER_SECOND); - if (buf->omx_buf->nTickCount != 0) - GST_BUFFER_DURATION (outbuf) = - gst_util_uint64_scale (buf->omx_buf->nTickCount, GST_SECOND, - OMX_TICKS_PER_SECOND); - - flow_ret = - gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER (self), - outbuf, n_samples); - } + if (buf->omx_buf->nFilledLen > 0) { + GstMapInfo map = GST_MAP_INFO_INIT; + outbuf = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen); - GST_DEBUG_OBJECT (self, "Handled output data"); + gst_buffer_map (outbuf, &map, GST_MAP_WRITE); + + memcpy (map.data, + buf->omx_buf->pBuffer + buf->omx_buf->nOffset, + buf->omx_buf->nFilledLen); + gst_buffer_unmap (outbuf, &map); - if (is_eos || flow_ret == GST_FLOW_EOS) { - g_mutex_lock (&self->drain_lock); - if (self->draining) { - GST_DEBUG_OBJECT (self, "Drained"); - self->draining = FALSE; - g_cond_broadcast (&self->drain_cond); - } else if (flow_ret == GST_FLOW_OK) { - GST_DEBUG_OBJECT (self, "Component signalled EOS"); - flow_ret = GST_FLOW_EOS; - } - g_mutex_unlock (&self->drain_lock); } else { - GST_DEBUG_OBJECT (self, "Finished frame: %s", - gst_flow_get_name (flow_ret)); + outbuf = gst_buffer_new (); } - err = gst_omx_port_release_buffer (port, buf); - if (err != OMX_ErrorNone) - goto release_error; + GST_BUFFER_TIMESTAMP (outbuf) = + gst_util_uint64_scale (buf->omx_buf->nTimeStamp, GST_SECOND, + OMX_TICKS_PER_SECOND); + if (buf->omx_buf->nTickCount != 0) + GST_BUFFER_DURATION (outbuf) = + gst_util_uint64_scale (buf->omx_buf->nTickCount, GST_SECOND, + OMX_TICKS_PER_SECOND); - self->downstream_flow_ret = flow_ret; - } else { - g_assert ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)); - GST_AUDIO_ENCODER_STREAM_LOCK (self); - flow_ret = GST_FLOW_EOS; + flow_ret = + gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER (self), + outbuf, n_samples); } + GST_DEBUG_OBJECT (self, "Handled output data"); + + GST_DEBUG_OBJECT (self, "Finished frame: %s", gst_flow_get_name (flow_ret)); + + err = gst_omx_port_release_buffer (port, buf); + if (err != OMX_ErrorNone) + goto release_error; + + self->downstream_flow_ret = flow_ret; + if (flow_ret != GST_FLOW_OK) goto flow_error; @@ -513,6 +497,29 @@ flushing: gst_pad_pause_task (GST_AUDIO_ENCODER_SRC_PAD (self)); self->downstream_flow_ret = GST_FLOW_FLUSHING; self->started = FALSE; + return; + } +eos: + { + g_mutex_lock (&self->drain_lock); + if (self->draining) { + GST_DEBUG_OBJECT (self, "Drained"); + self->draining = FALSE; + g_cond_broadcast (&self->drain_cond); + flow_ret = GST_FLOW_OK; + } else { + GST_DEBUG_OBJECT (self, "Component signalled EOS"); + flow_ret = GST_FLOW_EOS; + } + g_mutex_unlock (&self->drain_lock); + + self->downstream_flow_ret = flow_ret; + + if (flow_ret != GST_FLOW_OK) + goto flow_error; + + GST_AUDIO_ENCODER_STREAM_UNLOCK (self); + return; } flow_error: diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c index b190dbb..cd8e9bb 100644 --- a/omx/gstomxvideodec.c +++ b/omx/gstomxvideodec.c @@ -1361,23 +1361,21 @@ gst_omx_video_dec_deallocate_output_buffers (GstOMXVideoDec * self) static void gst_omx_video_dec_loop (GstOMXVideoDec * self) { - GstOMXVideoDecClass *klass; GstOMXPort *port = self->dec_out_port; GstOMXBuffer *buf = NULL; GstVideoCodecFrame *frame; GstFlowReturn flow_ret = GST_FLOW_OK; GstOMXAcquireBufferReturn acq_return; GstClockTimeDiff deadline; - gboolean is_eos; OMX_ERRORTYPE err; - klass = GST_OMX_VIDEO_DEC_GET_CLASS (self); - acq_return = gst_omx_port_acquire_buffer (port, &buf); if (acq_return == GST_OMX_ACQUIRE_BUFFER_ERROR) { goto component_error; } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_FLUSHING) { goto flushing; + } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_EOS) { + goto eos; } if (!gst_pad_has_current_caps (GST_VIDEO_DECODER_SRC_PAD (self)) || @@ -1490,85 +1488,102 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self) goto flushing; } - if (buf) { - GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %lu", - buf->omx_buf->nFlags, buf->omx_buf->nTimeStamp); - - GST_VIDEO_DECODER_STREAM_LOCK (self); - frame = _find_nearest_frame (self, buf); - - is_eos = ! !(buf->omx_buf->nFlags & OMX_BUFFERFLAG_EOS); - - if (frame - && (deadline = gst_video_decoder_get_max_decode_time - (GST_VIDEO_DECODER (self), frame)) < 0) { - GST_WARNING_OBJECT (self, - "Frame is too late, dropping (deadline %" GST_TIME_FORMAT ")", - GST_TIME_ARGS (-deadline)); - flow_ret = gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame); - frame = NULL; - } else if (!frame && buf->omx_buf->nFilledLen > 0) { - GstBuffer *outbuf; + GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %lu", + buf->omx_buf->nFlags, buf->omx_buf->nTimeStamp); - /* This sometimes happens at EOS or if the input is not properly framed, - * let's handle it gracefully by allocating a new buffer for the current - * caps and filling it - */ + GST_VIDEO_DECODER_STREAM_LOCK (self); + frame = _find_nearest_frame (self, buf); + + if (frame + && (deadline = gst_video_decoder_get_max_decode_time + (GST_VIDEO_DECODER (self), frame)) < 0) { + GST_WARNING_OBJECT (self, + "Frame is too late, dropping (deadline %" GST_TIME_FORMAT ")", + GST_TIME_ARGS (-deadline)); + flow_ret = gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame); + frame = NULL; + } else if (!frame && buf->omx_buf->nFilledLen > 0) { + GstBuffer *outbuf; + + /* This sometimes happens at EOS or if the input is not properly framed, + * let's handle it gracefully by allocating a new buffer for the current + * caps and filling it + */ - GST_ERROR_OBJECT (self, "No corresponding frame found"); + GST_ERROR_OBJECT (self, "No corresponding frame found"); - if (self->out_port_pool) { - gint i, n; - GstBufferPoolAcquireParams params = { 0, }; + if (self->out_port_pool) { + gint i, n; + GstBufferPoolAcquireParams params = { 0, }; - n = port->buffers->len; - for (i = 0; i < n; i++) { - GstOMXBuffer *tmp = g_ptr_array_index (port->buffers, i); + n = port->buffers->len; + for (i = 0; i < n; i++) { + GstOMXBuffer *tmp = g_ptr_array_index (port->buffers, i); - if (tmp == buf) - break; - } - g_assert (i != n); + if (tmp == buf) + break; + } + g_assert (i != n); - GST_OMX_BUFFER_POOL (self->out_port_pool)->current_buffer_index = i; - flow_ret = - gst_buffer_pool_acquire_buffer (self->out_port_pool, &outbuf, - ¶ms); - if (flow_ret != GST_FLOW_OK) { - gst_omx_port_release_buffer (port, buf); - goto invalid_buffer; - } - buf = NULL; - } else { - outbuf = - gst_video_decoder_allocate_output_buffer (GST_VIDEO_DECODER (self)); - if (!gst_omx_video_dec_fill_buffer (self, buf, outbuf)) { - gst_buffer_unref (outbuf); - gst_omx_port_release_buffer (port, buf); - goto invalid_buffer; - } + GST_OMX_BUFFER_POOL (self->out_port_pool)->current_buffer_index = i; + flow_ret = + gst_buffer_pool_acquire_buffer (self->out_port_pool, &outbuf, + ¶ms); + if (flow_ret != GST_FLOW_OK) { + gst_omx_port_release_buffer (port, buf); + goto invalid_buffer; } + buf = NULL; + } else { + outbuf = + gst_video_decoder_allocate_output_buffer (GST_VIDEO_DECODER (self)); + if (!gst_omx_video_dec_fill_buffer (self, buf, outbuf)) { + gst_buffer_unref (outbuf); + gst_omx_port_release_buffer (port, buf); + goto invalid_buffer; + } + } - flow_ret = gst_pad_push (GST_VIDEO_DECODER_SRC_PAD (self), outbuf); - } else if (buf->omx_buf->nFilledLen > 0) { - if (self->out_port_pool) { - gint i, n; - GstBufferPoolAcquireParams params = { 0, }; + flow_ret = gst_pad_push (GST_VIDEO_DECODER_SRC_PAD (self), outbuf); + } else if (buf->omx_buf->nFilledLen > 0) { + if (self->out_port_pool) { + gint i, n; + GstBufferPoolAcquireParams params = { 0, }; - n = port->buffers->len; - for (i = 0; i < n; i++) { - GstOMXBuffer *tmp = g_ptr_array_index (port->buffers, i); + n = port->buffers->len; + for (i = 0; i < n; i++) { + GstOMXBuffer *tmp = g_ptr_array_index (port->buffers, i); - if (tmp == buf) - break; - } - g_assert (i != n); + if (tmp == buf) + break; + } + g_assert (i != n); - GST_OMX_BUFFER_POOL (self->out_port_pool)->current_buffer_index = i; + GST_OMX_BUFFER_POOL (self->out_port_pool)->current_buffer_index = i; + flow_ret = + gst_buffer_pool_acquire_buffer (self->out_port_pool, + &frame->output_buffer, ¶ms); + if (flow_ret != GST_FLOW_OK) { flow_ret = - gst_buffer_pool_acquire_buffer (self->out_port_pool, - &frame->output_buffer, ¶ms); - if (flow_ret != GST_FLOW_OK) { + gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame); + frame = NULL; + gst_omx_port_release_buffer (port, buf); + goto invalid_buffer; + } + flow_ret = + gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame); + frame = NULL; + buf = NULL; + } else { + if ((flow_ret = + gst_video_decoder_allocate_output_frame (GST_VIDEO_DECODER + (self), frame)) == GST_FLOW_OK) { + /* FIXME: This currently happens because of a race condition too. + * We first need to reconfigure the output port and then the input + * port if both need reconfiguration. + */ + if (!gst_omx_video_dec_fill_buffer (self, buf, frame->output_buffer)) { + gst_buffer_replace (&frame->output_buffer, NULL); flow_ret = gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame); frame = NULL; @@ -1578,64 +1593,25 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self) flow_ret = gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame); frame = NULL; - buf = NULL; - } else { - if ((flow_ret = - gst_video_decoder_allocate_output_frame (GST_VIDEO_DECODER - (self), frame)) == GST_FLOW_OK) { - /* FIXME: This currently happens because of a race condition too. - * We first need to reconfigure the output port and then the input - * port if both need reconfiguration. - */ - if (!gst_omx_video_dec_fill_buffer (self, buf, frame->output_buffer)) { - gst_buffer_replace (&frame->output_buffer, NULL); - flow_ret = - gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame); - frame = NULL; - gst_omx_port_release_buffer (port, buf); - goto invalid_buffer; - } - flow_ret = - gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame); - frame = NULL; - } } - } else if (frame != NULL) { - flow_ret = gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame); - frame = NULL; } + } else if (frame != NULL) { + flow_ret = gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame); + frame = NULL; + } - GST_DEBUG_OBJECT (self, "Read frame from component"); - - if (is_eos || flow_ret == GST_FLOW_EOS) { - g_mutex_lock (&self->drain_lock); - if (self->draining) { - GST_DEBUG_OBJECT (self, "Drained"); - self->draining = FALSE; - g_cond_broadcast (&self->drain_cond); - } else if (flow_ret == GST_FLOW_OK) { - GST_DEBUG_OBJECT (self, "Component signalled EOS"); - flow_ret = GST_FLOW_EOS; - } - g_mutex_unlock (&self->drain_lock); - } else { - GST_DEBUG_OBJECT (self, "Finished frame: %s", - gst_flow_get_name (flow_ret)); - } + GST_DEBUG_OBJECT (self, "Read frame from component"); - if (buf) { - err = gst_omx_port_release_buffer (port, buf); - if (err != OMX_ErrorNone) - goto release_error; - } + GST_DEBUG_OBJECT (self, "Finished frame: %s", gst_flow_get_name (flow_ret)); - self->downstream_flow_ret = flow_ret; - } else { - g_assert ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)); - GST_VIDEO_DECODER_STREAM_LOCK (self); - flow_ret = GST_FLOW_EOS; + if (buf) { + err = gst_omx_port_release_buffer (port, buf); + if (err != OMX_ErrorNone) + goto release_error; } + self->downstream_flow_ret = flow_ret; + if (flow_ret != GST_FLOW_OK) goto flow_error; @@ -1665,6 +1641,29 @@ flushing: return; } +eos: + { + g_mutex_lock (&self->drain_lock); + if (self->draining) { + GST_DEBUG_OBJECT (self, "Drained"); + self->draining = FALSE; + g_cond_broadcast (&self->drain_cond); + flow_ret = GST_FLOW_OK; + } else { + GST_DEBUG_OBJECT (self, "Component signalled EOS"); + flow_ret = GST_FLOW_EOS; + } + g_mutex_unlock (&self->drain_lock); + self->downstream_flow_ret = flow_ret; + + if (flow_ret != GST_FLOW_OK) + goto flow_error; + + GST_VIDEO_DECODER_STREAM_UNLOCK (self); + + return; + } + flow_error: { if (flow_ret == GST_FLOW_EOS) { diff --git a/omx/gstomxvideoenc.c b/omx/gstomxvideoenc.c index edc957f..22efecd 100644 --- a/omx/gstomxvideoenc.c +++ b/omx/gstomxvideoenc.c @@ -740,7 +740,6 @@ gst_omx_video_enc_loop (GstOMXVideoEnc * self) GstVideoCodecFrame *frame; GstFlowReturn flow_ret = GST_FLOW_OK; GstOMXAcquireBufferReturn acq_return; - gboolean is_eos; OMX_ERRORTYPE err; klass = GST_OMX_VIDEO_ENC_GET_CLASS (self); @@ -750,6 +749,8 @@ gst_omx_video_enc_loop (GstOMXVideoEnc * self) goto component_error; } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_FLUSHING) { goto flushing; + } else if (acq_return == GST_OMX_ACQUIRE_BUFFER_EOS) { + goto eos; } if (!gst_pad_has_current_caps (GST_VIDEO_ENCODER_SRC_PAD (self)) @@ -845,45 +846,22 @@ gst_omx_video_enc_loop (GstOMXVideoEnc * self) goto flushing; } - if (buf) { - GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %lu", buf->omx_buf->nFlags, - buf->omx_buf->nTimeStamp); + GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %lu", buf->omx_buf->nFlags, + buf->omx_buf->nTimeStamp); - GST_VIDEO_ENCODER_STREAM_LOCK (self); - frame = _find_nearest_frame (self, buf); - - is_eos = ! !(buf->omx_buf->nFlags & OMX_BUFFERFLAG_EOS); + GST_VIDEO_ENCODER_STREAM_LOCK (self); + frame = _find_nearest_frame (self, buf); - g_assert (klass->handle_output_frame); - flow_ret = - klass->handle_output_frame (self, self->enc_out_port, buf, frame); + g_assert (klass->handle_output_frame); + flow_ret = klass->handle_output_frame (self, self->enc_out_port, buf, frame); - if (is_eos || flow_ret == GST_FLOW_EOS) { - g_mutex_lock (&self->drain_lock); - if (self->draining) { - GST_DEBUG_OBJECT (self, "Drained"); - self->draining = FALSE; - g_cond_broadcast (&self->drain_cond); - } else if (flow_ret == GST_FLOW_OK) { - GST_DEBUG_OBJECT (self, "Component signalled EOS"); - flow_ret = GST_FLOW_EOS; - } - g_mutex_unlock (&self->drain_lock); - } else { - GST_DEBUG_OBJECT (self, "Finished frame: %s", - gst_flow_get_name (flow_ret)); - } + GST_DEBUG_OBJECT (self, "Finished frame: %s", gst_flow_get_name (flow_ret)); - err = gst_omx_port_release_buffer (port, buf); - if (err != OMX_ErrorNone) - goto release_error; + err = gst_omx_port_release_buffer (port, buf); + if (err != OMX_ErrorNone) + goto release_error; - self->downstream_flow_ret = flow_ret; - } else { - g_assert ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)); - GST_VIDEO_ENCODER_STREAM_LOCK (self); - flow_ret = GST_FLOW_EOS; - } + self->downstream_flow_ret = flow_ret; GST_DEBUG_OBJECT (self, "Read frame from component"); @@ -914,6 +892,28 @@ flushing: self->started = FALSE; return; } + +eos: + { + g_mutex_lock (&self->drain_lock); + if (self->draining) { + GST_DEBUG_OBJECT (self, "Drained"); + self->draining = FALSE; + g_cond_broadcast (&self->drain_cond); + flow_ret = GST_FLOW_OK; + } else { + GST_DEBUG_OBJECT (self, "Component signalled EOS"); + flow_ret = GST_FLOW_EOS; + } + g_mutex_unlock (&self->drain_lock); + + if (flow_ret != GST_FLOW_OK) + goto flow_error; + + GST_VIDEO_ENCODER_STREAM_UNLOCK (self); + + return; + } flow_error: { if (flow_ret == GST_FLOW_EOS) { -- cgit v1.2.1