summaryrefslogtreecommitdiff
path: root/omx/gstomxaudioenc.c
diff options
context:
space:
mode:
authorJonas Larsson <Jonas.Larsson@palm.com>2011-12-14 10:09:34 +0100
committerSebastian Dröge <sebastian.droege@collabora.co.uk>2011-12-14 10:09:34 +0100
commit887d43c2903e9bd34558c0ee6977c3e68d392667 (patch)
tree5c030678c1dd189ccedb5324f3f22438629f9038 /omx/gstomxaudioenc.c
parent2cab5b5db53ed27b4c7eb9b523aa4b7962fa4716 (diff)
omxaudioenc: Add hack for encoder components that don't allow empty EOS buffers
Diffstat (limited to 'omx/gstomxaudioenc.c')
-rw-r--r--omx/gstomxaudioenc.c172
1 files changed, 106 insertions, 66 deletions
diff --git a/omx/gstomxaudioenc.c b/omx/gstomxaudioenc.c
index 4fb7811..18beb26 100644
--- a/omx/gstomxaudioenc.c
+++ b/omx/gstomxaudioenc.c
@@ -463,87 +463,106 @@ 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);
-
- if ((buf->omx_buf->nFlags & OMX_BUFFERFLAG_CODECCONFIG)
- && buf->omx_buf->nFilledLen > 0) {
- GstCaps *caps;
- GstBuffer *codec_data;
+ GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %lu", buf->omx_buf->nFlags,
+ buf->omx_buf->nTimeStamp);
- 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_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,
+ 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;
+
+ 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);
+ }
- 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;
+ 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));
}
- 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);
+ gst_omx_port_release_buffer (port, buf);
- self->downstream_flow_ret = flow_ret;
+ self->downstream_flow_ret = flow_ret;
+ } else {
+ g_assert ((klass->hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER));
+ GST_AUDIO_ENCODER_STREAM_LOCK (self);
+ flow_ret = GST_FLOW_UNEXPECTED;
+ }
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 */