omxaudioenc: Add hack for encoder components that don't allow empty EOS buffers

This commit is contained in:
Jonas Larsson 2011-12-14 10:09:34 +01:00 committed by Sebastian Dröge
parent 2cab5b5db5
commit 887d43c290

View file

@ -463,88 +463,107 @@ gst_omx_audio_enc_loop (GstOMXAudioEnc * self)
return;
}
g_assert (acq_return == GST_OMX_ACQUIRE_BUFFER_OK && buf != NULL);
g_assert (acq_return == GST_OMX_ACQUIRE_BUFFER_OK);
GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %lu", buf->omx_buf->nFlags,
buf->omx_buf->nTimeStamp);
if (buf) {
GST_AUDIO_ENCODER_STREAM_LOCK (self);
is_eos = ! !(buf->omx_buf->nFlags & OMX_BUFFERFLAG_EOS);
GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %lu", buf->omx_buf->nFlags,
buf->omx_buf->nTimeStamp);
if ((buf->omx_buf->nFlags & OMX_BUFFERFLAG_CODECCONFIG)
&& buf->omx_buf->nFilledLen > 0) {
GstCaps *caps;
GstBuffer *codec_data;
caps = gst_caps_copy (GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (self)));
codec_data = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen);
memcpy (GST_BUFFER_DATA (codec_data),
buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
buf->omx_buf->nFilledLen);
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->out_port, buf);
GST_AUDIO_ENCODER_STREAM_UNLOCK (self);
goto caps_failed;
/* 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->out_port)) {
GST_DEBUG_OBJECT (self, "Flushing");
gst_omx_port_release_buffer (self->out_port, buf);
goto flushing;
}
gst_caps_unref (caps);
flow_ret = GST_FLOW_OK;
} else if (buf->omx_buf->nFilledLen > 0) {
GstBuffer *outbuf;
guint n_samples;
n_samples =
klass->get_num_samples (self, self->out_port,
gst_audio_encoder_get_audio_info (GST_AUDIO_ENCODER (self)), buf);
GST_AUDIO_ENCODER_STREAM_LOCK (self);
is_eos = ! !(buf->omx_buf->nFlags & OMX_BUFFERFLAG_EOS);
if (buf->omx_buf->nFilledLen > 0) {
outbuf = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen);
if ((buf->omx_buf->nFlags & OMX_BUFFERFLAG_CODECCONFIG)
&& buf->omx_buf->nFilledLen > 0) {
GstCaps *caps;
GstBuffer *codec_data;
memcpy (GST_BUFFER_DATA (outbuf),
caps = gst_caps_copy (GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (self)));
codec_data = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen);
memcpy (GST_BUFFER_DATA (codec_data),
buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
buf->omx_buf->nFilledLen);
} else {
outbuf = gst_buffer_new ();
}
gst_buffer_set_caps (outbuf,
GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (self)));
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->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_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,
n_samples =
klass->get_num_samples (self, self->out_port,
gst_audio_encoder_get_audio_info (GST_AUDIO_ENCODER (self)), buf);
if (buf->omx_buf->nFilledLen > 0) {
outbuf = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen);
memcpy (GST_BUFFER_DATA (outbuf),
buf->omx_buf->pBuffer + buf->omx_buf->nOffset,
buf->omx_buf->nFilledLen);
} else {
outbuf = gst_buffer_new ();
}
gst_buffer_set_caps (outbuf,
GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (self)));
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 (is_eos || flow_ret == GST_FLOW_UNEXPECTED) {
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_UNEXPECTED;
flow_ret =
gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER (self),
outbuf, n_samples);
}
g_mutex_unlock (self->drain_lock);
if (is_eos || flow_ret == GST_FLOW_UNEXPECTED) {
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_UNEXPECTED;
}
g_mutex_unlock (self->drain_lock);
} else {
GST_DEBUG_OBJECT (self, "Finished frame: %s",
gst_flow_get_name (flow_ret));
}
gst_omx_port_release_buffer (port, buf);
self->downstream_flow_ret = flow_ret;
} else {
GST_DEBUG_OBJECT (self, "Finished frame: %s", gst_flow_get_name (flow_ret));
g_assert ((klass->hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER));
GST_AUDIO_ENCODER_STREAM_LOCK (self);
flow_ret = GST_FLOW_UNEXPECTED;
}
gst_omx_port_release_buffer (port, buf);
self->downstream_flow_ret = flow_ret;
if (flow_ret != GST_FLOW_OK)
goto flow_error;
@ -993,8 +1012,10 @@ static gboolean
gst_omx_audio_enc_event (GstAudioEncoder * encoder, GstEvent * event)
{
GstOMXAudioEnc *self;
GstOMXAudioEncClass *klass;
self = GST_OMX_AUDIO_ENC (encoder);
klass = GST_OMX_AUDIO_ENC_GET_CLASS (self);
if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
GstOMXBuffer *buf;
@ -1009,6 +1030,17 @@ gst_omx_audio_enc_event (GstAudioEncoder * encoder, GstEvent * event)
}
self->eos = TRUE;
if ((klass->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->out_port->port_lock);
g_queue_push_tail (self->out_port->pending_buffers, NULL);
g_cond_broadcast (self->out_port->port_cond);
g_mutex_unlock (self->out_port->port_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 */
@ -1042,11 +1074,14 @@ gst_omx_audio_enc_event (GstAudioEncoder * encoder, GstEvent * event)
static GstFlowReturn
gst_omx_audio_enc_drain (GstOMXAudioEnc * self)
{
GstOMXAudioEncClass *klass;
GstOMXBuffer *buf;
GstOMXAcquireBufferReturn acq_ret;
GST_DEBUG_OBJECT (self, "Draining component");
klass = GST_OMX_AUDIO_ENC_GET_CLASS (self);
if (!self->started) {
GST_DEBUG_OBJECT (self, "Component not started yet");
return GST_FLOW_OK;
@ -1059,6 +1094,11 @@ gst_omx_audio_enc_drain (GstOMXAudioEnc * self)
return GST_FLOW_OK;
}
if ((klass->hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)) {
GST_WARNING_OBJECT (self, "Component does not support empty EOS buffers");
return GST_FLOW_OK;
}
/* 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 */