mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 04:26:14 +00:00
omx: Handle the OMX_EventBufferFlag to detect EOS too
This commit is contained in:
parent
acf15e84a9
commit
22dce51dd4
5 changed files with 327 additions and 261 deletions
56
omx/gstomx.c
56
omx/gstomx.c
|
@ -321,6 +321,23 @@ gst_omx_component_handle_messages (GstOMXComponent * comp)
|
||||||
|
|
||||||
break;
|
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:{
|
case GST_OMX_MESSAGE_BUFFER_DONE:{
|
||||||
GstOMXBuffer *buf = msg->content.buffer_done.buffer->pAppPrivate;
|
GstOMXBuffer *buf = msg->content.buffer_done.buffer->pAppPrivate;
|
||||||
GstOMXPort *port;
|
GstOMXPort *port;
|
||||||
|
@ -356,6 +373,10 @@ gst_omx_component_handle_messages (GstOMXComponent * comp)
|
||||||
* the port was flushed */
|
* the port was flushed */
|
||||||
GST_DEBUG_OBJECT (comp->parent, "Port %u filled buffer %p (%p)",
|
GST_DEBUG_OBJECT (comp->parent, "Port %u filled buffer %p (%p)",
|
||||||
port->index, buf, buf->omx_buf->pBuffer);
|
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;
|
buf->used = FALSE;
|
||||||
|
@ -491,8 +512,21 @@ EventHandler (OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_EVENTTYPE eEvent,
|
||||||
gst_omx_component_send_message (comp, msg);
|
gst_omx_component_send_message (comp, msg);
|
||||||
break;
|
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_EventPortFormatDetected:
|
||||||
case OMX_EventBufferFlag:
|
|
||||||
default:
|
default:
|
||||||
GST_DEBUG_OBJECT (comp->parent, "Unknown event 0x%08x", eEvent);
|
GST_DEBUG_OBJECT (comp->parent, "Unknown event 0x%08x", eEvent);
|
||||||
break;
|
break;
|
||||||
|
@ -879,6 +913,7 @@ gst_omx_component_add_port (GstOMXComponent * comp, guint32 index)
|
||||||
port->flushed = FALSE;
|
port->flushed = FALSE;
|
||||||
port->enabled_pending = FALSE;
|
port->enabled_pending = FALSE;
|
||||||
port->disabled_pending = FALSE;
|
port->disabled_pending = FALSE;
|
||||||
|
port->eos = FALSE;
|
||||||
|
|
||||||
if (port->port_def.eDir == OMX_DirInput)
|
if (port->port_def.eDir == OMX_DirInput)
|
||||||
comp->n_in_ports++;
|
comp->n_in_ports++;
|
||||||
|
@ -1237,8 +1272,22 @@ retry:
|
||||||
goto done;
|
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.
|
* and a properly configured port.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -1478,6 +1527,9 @@ gst_omx_port_set_flushing (GstOMXPort * port, GstClockTime timeout,
|
||||||
err = OMX_ErrorTimeout;
|
err = OMX_ErrorTimeout;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reset EOS flag */
|
||||||
|
port->eos = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
|
@ -118,6 +118,8 @@ typedef enum {
|
||||||
GST_OMX_ACQUIRE_BUFFER_FLUSHING,
|
GST_OMX_ACQUIRE_BUFFER_FLUSHING,
|
||||||
/* The port must be reconfigured */
|
/* The port must be reconfigured */
|
||||||
GST_OMX_ACQUIRE_BUFFER_RECONFIGURE,
|
GST_OMX_ACQUIRE_BUFFER_RECONFIGURE,
|
||||||
|
/* The port is EOS */
|
||||||
|
GST_OMX_ACQUIRE_BUFFER_EOS,
|
||||||
/* A fatal error happened */
|
/* A fatal error happened */
|
||||||
GST_OMX_ACQUIRE_BUFFER_ERROR
|
GST_OMX_ACQUIRE_BUFFER_ERROR
|
||||||
} GstOMXAcquireBufferReturn;
|
} GstOMXAcquireBufferReturn;
|
||||||
|
@ -146,6 +148,7 @@ typedef enum {
|
||||||
GST_OMX_MESSAGE_ERROR,
|
GST_OMX_MESSAGE_ERROR,
|
||||||
GST_OMX_MESSAGE_PORT_ENABLE,
|
GST_OMX_MESSAGE_PORT_ENABLE,
|
||||||
GST_OMX_MESSAGE_PORT_SETTINGS_CHANGED,
|
GST_OMX_MESSAGE_PORT_SETTINGS_CHANGED,
|
||||||
|
GST_OMX_MESSAGE_BUFFER_FLAG,
|
||||||
GST_OMX_MESSAGE_BUFFER_DONE,
|
GST_OMX_MESSAGE_BUFFER_DONE,
|
||||||
} GstOMXMessageType;
|
} GstOMXMessageType;
|
||||||
|
|
||||||
|
@ -169,6 +172,10 @@ struct _GstOMXMessage {
|
||||||
struct {
|
struct {
|
||||||
OMX_U32 port;
|
OMX_U32 port;
|
||||||
} port_settings_changed;
|
} port_settings_changed;
|
||||||
|
struct {
|
||||||
|
OMX_U32 port;
|
||||||
|
OMX_U32 flags;
|
||||||
|
} buffer_flag;
|
||||||
struct {
|
struct {
|
||||||
OMX_HANDLETYPE component;
|
OMX_HANDLETYPE component;
|
||||||
OMX_PTR app_data;
|
OMX_PTR app_data;
|
||||||
|
@ -191,6 +198,7 @@ struct _GstOMXPort {
|
||||||
gboolean flushed; /* TRUE after OMX_CommandFlush was done */
|
gboolean flushed; /* TRUE after OMX_CommandFlush was done */
|
||||||
gboolean enabled_pending; /* TRUE after OMX_Command{En,Dis}able */
|
gboolean enabled_pending; /* TRUE after OMX_Command{En,Dis}able */
|
||||||
gboolean disabled_pending; /* was done until it took effect */
|
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.
|
/* Increased whenever the settings of these port change.
|
||||||
* If settings_cookie != configured_settings_cookie
|
* If settings_cookie != configured_settings_cookie
|
||||||
|
|
|
@ -282,7 +282,6 @@ gst_omx_audio_enc_loop (GstOMXAudioEnc * self)
|
||||||
GstOMXBuffer *buf = NULL;
|
GstOMXBuffer *buf = NULL;
|
||||||
GstFlowReturn flow_ret = GST_FLOW_OK;
|
GstFlowReturn flow_ret = GST_FLOW_OK;
|
||||||
GstOMXAcquireBufferReturn acq_return;
|
GstOMXAcquireBufferReturn acq_return;
|
||||||
gboolean is_eos;
|
|
||||||
OMX_ERRORTYPE err;
|
OMX_ERRORTYPE err;
|
||||||
|
|
||||||
klass = GST_OMX_AUDIO_ENC_GET_CLASS (self);
|
klass = GST_OMX_AUDIO_ENC_GET_CLASS (self);
|
||||||
|
@ -292,6 +291,8 @@ gst_omx_audio_enc_loop (GstOMXAudioEnc * self)
|
||||||
goto component_error;
|
goto component_error;
|
||||||
} else if (acq_return == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
|
} else if (acq_return == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
|
||||||
goto 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))
|
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);
|
g_assert (acq_return == GST_OMX_ACQUIRE_BUFFER_OK);
|
||||||
|
if (!buf) {
|
||||||
if (buf) {
|
g_assert ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER));
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_AUDIO_ENCODER_STREAM_LOCK (self);
|
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)
|
GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %lu", buf->omx_buf->nFlags,
|
||||||
&& buf->omx_buf->nFilledLen > 0) {
|
buf->omx_buf->nTimeStamp);
|
||||||
GstCaps *caps;
|
|
||||||
GstBuffer *codec_data;
|
/* 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_AUDIO_ENCODER_STREAM_LOCK (self);
|
||||||
|
|
||||||
|
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 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);
|
||||||
|
|
||||||
|
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_DEBUG_OBJECT (self, "Handling output data");
|
||||||
|
|
||||||
|
n_samples =
|
||||||
|
klass->get_num_samples (self, self->enc_out_port,
|
||||||
|
gst_audio_encoder_get_audio_info (GST_AUDIO_ENCODER (self)), buf);
|
||||||
|
|
||||||
|
if (buf->omx_buf->nFilledLen > 0) {
|
||||||
GstMapInfo map = GST_MAP_INFO_INIT;
|
GstMapInfo map = GST_MAP_INFO_INIT;
|
||||||
|
outbuf = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (self, "Handling codec data");
|
gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
|
||||||
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);
|
|
||||||
|
|
||||||
gst_buffer_map (codec_data, &map, GST_MAP_WRITE);
|
|
||||||
memcpy (map.data,
|
memcpy (map.data,
|
||||||
buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
|
buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
|
||||||
buf->omx_buf->nFilledLen);
|
buf->omx_buf->nFilledLen);
|
||||||
gst_buffer_unmap (codec_data, &map);
|
gst_buffer_unmap (outbuf, &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_DEBUG_OBJECT (self, "Handling output data");
|
|
||||||
|
|
||||||
n_samples =
|
|
||||||
klass->get_num_samples (self, self->enc_out_port,
|
|
||||||
gst_audio_encoder_get_audio_info (GST_AUDIO_ENCODER (self)), buf);
|
|
||||||
|
|
||||||
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 (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);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
outbuf = gst_buffer_new ();
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (self, "Handled output data");
|
|
||||||
|
|
||||||
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 {
|
} else {
|
||||||
GST_DEBUG_OBJECT (self, "Finished frame: %s",
|
outbuf = gst_buffer_new ();
|
||||||
gst_flow_get_name (flow_ret));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = gst_omx_port_release_buffer (port, buf);
|
GST_BUFFER_TIMESTAMP (outbuf) =
|
||||||
if (err != OMX_ErrorNone)
|
gst_util_uint64_scale (buf->omx_buf->nTimeStamp, GST_SECOND,
|
||||||
goto release_error;
|
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;
|
flow_ret =
|
||||||
} else {
|
gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER (self),
|
||||||
g_assert ((klass->cdata.hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER));
|
outbuf, n_samples);
|
||||||
GST_AUDIO_ENCODER_STREAM_LOCK (self);
|
|
||||||
flow_ret = GST_FLOW_EOS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
if (flow_ret != GST_FLOW_OK)
|
||||||
goto flow_error;
|
goto flow_error;
|
||||||
|
|
||||||
|
@ -513,6 +497,29 @@ flushing:
|
||||||
gst_pad_pause_task (GST_AUDIO_ENCODER_SRC_PAD (self));
|
gst_pad_pause_task (GST_AUDIO_ENCODER_SRC_PAD (self));
|
||||||
self->downstream_flow_ret = GST_FLOW_FLUSHING;
|
self->downstream_flow_ret = GST_FLOW_FLUSHING;
|
||||||
self->started = FALSE;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
flow_error:
|
flow_error:
|
||||||
|
|
|
@ -1361,23 +1361,21 @@ gst_omx_video_dec_deallocate_output_buffers (GstOMXVideoDec * self)
|
||||||
static void
|
static void
|
||||||
gst_omx_video_dec_loop (GstOMXVideoDec * self)
|
gst_omx_video_dec_loop (GstOMXVideoDec * self)
|
||||||
{
|
{
|
||||||
GstOMXVideoDecClass *klass;
|
|
||||||
GstOMXPort *port = self->dec_out_port;
|
GstOMXPort *port = self->dec_out_port;
|
||||||
GstOMXBuffer *buf = NULL;
|
GstOMXBuffer *buf = NULL;
|
||||||
GstVideoCodecFrame *frame;
|
GstVideoCodecFrame *frame;
|
||||||
GstFlowReturn flow_ret = GST_FLOW_OK;
|
GstFlowReturn flow_ret = GST_FLOW_OK;
|
||||||
GstOMXAcquireBufferReturn acq_return;
|
GstOMXAcquireBufferReturn acq_return;
|
||||||
GstClockTimeDiff deadline;
|
GstClockTimeDiff deadline;
|
||||||
gboolean is_eos;
|
|
||||||
OMX_ERRORTYPE err;
|
OMX_ERRORTYPE err;
|
||||||
|
|
||||||
klass = GST_OMX_VIDEO_DEC_GET_CLASS (self);
|
|
||||||
|
|
||||||
acq_return = gst_omx_port_acquire_buffer (port, &buf);
|
acq_return = gst_omx_port_acquire_buffer (port, &buf);
|
||||||
if (acq_return == GST_OMX_ACQUIRE_BUFFER_ERROR) {
|
if (acq_return == GST_OMX_ACQUIRE_BUFFER_ERROR) {
|
||||||
goto component_error;
|
goto component_error;
|
||||||
} else if (acq_return == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
|
} else if (acq_return == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
|
||||||
goto 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)) ||
|
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;
|
goto flushing;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf) {
|
GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %lu",
|
||||||
GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %lu",
|
buf->omx_buf->nFlags, buf->omx_buf->nTimeStamp);
|
||||||
buf->omx_buf->nFlags, buf->omx_buf->nTimeStamp);
|
|
||||||
|
|
||||||
GST_VIDEO_DECODER_STREAM_LOCK (self);
|
GST_VIDEO_DECODER_STREAM_LOCK (self);
|
||||||
frame = _find_nearest_frame (self, buf);
|
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;
|
||||||
|
|
||||||
if (frame
|
/* This sometimes happens at EOS or if the input is not properly framed,
|
||||||
&& (deadline = gst_video_decoder_get_max_decode_time
|
* let's handle it gracefully by allocating a new buffer for the current
|
||||||
(GST_VIDEO_DECODER (self), frame)) < 0) {
|
* caps and filling it
|
||||||
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,
|
GST_ERROR_OBJECT (self, "No corresponding frame found");
|
||||||
* 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");
|
if (self->out_port_pool) {
|
||||||
|
gint i, n;
|
||||||
|
GstBufferPoolAcquireParams params = { 0, };
|
||||||
|
|
||||||
if (self->out_port_pool) {
|
n = port->buffers->len;
|
||||||
gint i, n;
|
for (i = 0; i < n; i++) {
|
||||||
GstBufferPoolAcquireParams params = { 0, };
|
GstOMXBuffer *tmp = g_ptr_array_index (port->buffers, i);
|
||||||
|
|
||||||
n = port->buffers->len;
|
if (tmp == buf)
|
||||||
for (i = 0; i < n; i++) {
|
break;
|
||||||
GstOMXBuffer *tmp = g_ptr_array_index (port->buffers, i);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
g_assert (i != n);
|
||||||
|
|
||||||
flow_ret = gst_pad_push (GST_VIDEO_DECODER_SRC_PAD (self), outbuf);
|
GST_OMX_BUFFER_POOL (self->out_port_pool)->current_buffer_index = i;
|
||||||
} else if (buf->omx_buf->nFilledLen > 0) {
|
flow_ret =
|
||||||
if (self->out_port_pool) {
|
gst_buffer_pool_acquire_buffer (self->out_port_pool, &outbuf,
|
||||||
gint i, n;
|
¶ms);
|
||||||
GstBufferPoolAcquireParams params = { 0, };
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
n = port->buffers->len;
|
flow_ret = gst_pad_push (GST_VIDEO_DECODER_SRC_PAD (self), outbuf);
|
||||||
for (i = 0; i < n; i++) {
|
} else if (buf->omx_buf->nFilledLen > 0) {
|
||||||
GstOMXBuffer *tmp = g_ptr_array_index (port->buffers, i);
|
if (self->out_port_pool) {
|
||||||
|
gint i, n;
|
||||||
|
GstBufferPoolAcquireParams params = { 0, };
|
||||||
|
|
||||||
if (tmp == buf)
|
n = port->buffers->len;
|
||||||
break;
|
for (i = 0; i < n; i++) {
|
||||||
}
|
GstOMXBuffer *tmp = g_ptr_array_index (port->buffers, i);
|
||||||
g_assert (i != n);
|
|
||||||
|
|
||||||
GST_OMX_BUFFER_POOL (self->out_port_pool)->current_buffer_index = i;
|
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,
|
||||||
|
&frame->output_buffer, ¶ms);
|
||||||
|
if (flow_ret != GST_FLOW_OK) {
|
||||||
flow_ret =
|
flow_ret =
|
||||||
gst_buffer_pool_acquire_buffer (self->out_port_pool,
|
gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
|
||||||
&frame->output_buffer, ¶ms);
|
frame = NULL;
|
||||||
if (flow_ret != GST_FLOW_OK) {
|
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 =
|
flow_ret =
|
||||||
gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
|
gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
|
||||||
frame = NULL;
|
frame = NULL;
|
||||||
|
@ -1578,64 +1593,25 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
|
||||||
flow_ret =
|
flow_ret =
|
||||||
gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
|
gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
|
||||||
frame = NULL;
|
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) {
|
||||||
GST_DEBUG_OBJECT (self, "Read frame from component");
|
flow_ret = gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
|
||||||
|
frame = NULL;
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf) {
|
|
||||||
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_DECODER_STREAM_LOCK (self);
|
|
||||||
flow_ret = GST_FLOW_EOS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (self, "Read frame from component");
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (self, "Finished frame: %s", gst_flow_get_name (flow_ret));
|
||||||
|
|
||||||
|
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)
|
if (flow_ret != GST_FLOW_OK)
|
||||||
goto flow_error;
|
goto flow_error;
|
||||||
|
|
||||||
|
@ -1665,6 +1641,29 @@ flushing:
|
||||||
return;
|
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:
|
flow_error:
|
||||||
{
|
{
|
||||||
if (flow_ret == GST_FLOW_EOS) {
|
if (flow_ret == GST_FLOW_EOS) {
|
||||||
|
|
|
@ -740,7 +740,6 @@ gst_omx_video_enc_loop (GstOMXVideoEnc * self)
|
||||||
GstVideoCodecFrame *frame;
|
GstVideoCodecFrame *frame;
|
||||||
GstFlowReturn flow_ret = GST_FLOW_OK;
|
GstFlowReturn flow_ret = GST_FLOW_OK;
|
||||||
GstOMXAcquireBufferReturn acq_return;
|
GstOMXAcquireBufferReturn acq_return;
|
||||||
gboolean is_eos;
|
|
||||||
OMX_ERRORTYPE err;
|
OMX_ERRORTYPE err;
|
||||||
|
|
||||||
klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
|
klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
|
||||||
|
@ -750,6 +749,8 @@ gst_omx_video_enc_loop (GstOMXVideoEnc * self)
|
||||||
goto component_error;
|
goto component_error;
|
||||||
} else if (acq_return == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
|
} else if (acq_return == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
|
||||||
goto 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))
|
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;
|
goto flushing;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf) {
|
GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %lu", buf->omx_buf->nFlags,
|
||||||
GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %lu", buf->omx_buf->nFlags,
|
buf->omx_buf->nTimeStamp);
|
||||||
buf->omx_buf->nTimeStamp);
|
|
||||||
|
|
||||||
GST_VIDEO_ENCODER_STREAM_LOCK (self);
|
GST_VIDEO_ENCODER_STREAM_LOCK (self);
|
||||||
frame = _find_nearest_frame (self, buf);
|
frame = _find_nearest_frame (self, buf);
|
||||||
|
|
||||||
is_eos = ! !(buf->omx_buf->nFlags & OMX_BUFFERFLAG_EOS);
|
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);
|
GST_DEBUG_OBJECT (self, "Finished frame: %s", gst_flow_get_name (flow_ret));
|
||||||
flow_ret =
|
|
||||||
klass->handle_output_frame (self, self->enc_out_port, buf, frame);
|
|
||||||
|
|
||||||
if (is_eos || flow_ret == GST_FLOW_EOS) {
|
err = gst_omx_port_release_buffer (port, buf);
|
||||||
g_mutex_lock (&self->drain_lock);
|
if (err != OMX_ErrorNone)
|
||||||
if (self->draining) {
|
goto release_error;
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
err = gst_omx_port_release_buffer (port, buf);
|
self->downstream_flow_ret = flow_ret;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (self, "Read frame from component");
|
GST_DEBUG_OBJECT (self, "Read frame from component");
|
||||||
|
|
||||||
|
@ -914,6 +892,28 @@ flushing:
|
||||||
self->started = FALSE;
|
self->started = FALSE;
|
||||||
return;
|
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:
|
flow_error:
|
||||||
{
|
{
|
||||||
if (flow_ret == GST_FLOW_EOS) {
|
if (flow_ret == GST_FLOW_EOS) {
|
||||||
|
|
Loading…
Reference in a new issue