From 3f46a12aab6560ff87fb7d55c41bd9abda4f602d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 19 May 2015 18:21:40 +0300 Subject: [PATCH] omxaudiodec: Add an output adapter for chunking the output into codec frames Otherwise the base class will be confused. See https://bugzilla.gnome.org/show_bug.cgi?id=685730 --- omx/gstomxaudiodec.c | 84 +++++++++++++++++++++++++++++++++++++++------------- omx/gstomxaudiodec.h | 2 ++ 2 files changed, 65 insertions(+), 21 deletions(-) diff --git a/omx/gstomxaudiodec.c b/omx/gstomxaudiodec.c index 44fdf89..e095cf3 100644 --- a/omx/gstomxaudiodec.c +++ b/omx/gstomxaudiodec.c @@ -105,6 +105,8 @@ gst_omx_audio_dec_init (GstOMXAudioDec * self) g_mutex_init (&self->drain_lock); g_cond_init (&self->drain_cond); + + self->output_adapter = gst_adapter_new (); } static gboolean @@ -219,6 +221,10 @@ gst_omx_audio_dec_finalize (GObject * object) g_mutex_clear (&self->drain_lock); g_cond_clear (&self->drain_cond); + if (self->output_adapter) + gst_object_unref (self->output_adapter); + self->output_adapter = NULL; + G_OBJECT_CLASS (gst_omx_audio_dec_parent_class)->finalize (object); } @@ -286,11 +292,13 @@ gst_omx_audio_dec_change_state (GstElement * element, GstStateChange transition) static void gst_omx_audio_dec_loop (GstOMXAudioDec * self) { + GstOMXAudioDecClass *klass = GST_OMX_AUDIO_DEC_GET_CLASS (self); GstOMXPort *port = self->dec_out_port; GstOMXBuffer *buf = NULL; GstFlowReturn flow_ret = GST_FLOW_OK; GstOMXAcquireBufferReturn acq_return; OMX_ERRORTYPE err; + gint spf; acq_return = gst_omx_port_acquire_buffer (port, &buf); if (acq_return == GST_OMX_ACQUIRE_BUFFER_ERROR) { @@ -485,11 +493,11 @@ gst_omx_audio_dec_loop (GstOMXAudioDec * self) GST_AUDIO_DECODER_STREAM_LOCK (self); + spf = klass->get_samples_per_frame (self, self->dec_out_port); + if (buf->omx_buf->nFilledLen > 0) { GstBuffer *outbuf; - gint nframes, spf; GstMapInfo minfo; - GstOMXAudioDecClass *klass = GST_OMX_AUDIO_DEC_GET_CLASS (self); GST_DEBUG_OBJECT (self, "Handling output data"); @@ -524,31 +532,37 @@ gst_omx_audio_dec_loop (GstOMXAudioDec * self) } gst_buffer_unmap (outbuf, &minfo); - nframes = 1; - spf = klass->get_samples_per_frame (self, self->dec_out_port); if (spf != -1) { - nframes = buf->omx_buf->nFilledLen / self->info.bpf; - if (nframes % spf != 0) - GST_WARNING_OBJECT (self, "Output buffer does not contain an integer " - "number of input frames (frames: %d, spf: %d)", nframes, spf); - nframes = (nframes + spf - 1) / spf; + gst_adapter_push (self->output_adapter, outbuf); + } else { + flow_ret = + gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (self), outbuf, 1); } - - 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_decoder_finish_frame (GST_AUDIO_DECODER (self), outbuf, - nframes); } GST_DEBUG_OBJECT (self, "Read frame from component"); + if (spf != -1) { + GstBuffer *outbuf; + guint avail = gst_adapter_available (self->output_adapter); + guint nframes; + + /* We take a multiple of codec frames and push + * them downstream + */ + avail /= self->info.bpf; + nframes = avail / spf; + avail = nframes * spf; + avail *= self->info.bpf; + + if (avail > 0) { + outbuf = gst_adapter_take_buffer (self->output_adapter, avail); + flow_ret = + gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (self), outbuf, + nframes); + } + } + GST_DEBUG_OBJECT (self, "Finished frame: %s", gst_flow_get_name (flow_ret)); if (buf) { @@ -590,6 +604,27 @@ flushing: eos: { + spf = klass->get_samples_per_frame (self, self->dec_out_port); + if (spf != -1) { + GstBuffer *outbuf; + guint avail = gst_adapter_available (self->output_adapter); + guint nframes; + + /* On EOS we take the complete adapter content, no matter + * if it is a multiple of the codec frame size or not. + */ + avail /= self->info.bpf; + nframes = (avail + spf - 1) / spf; + avail *= self->info.bpf; + + if (avail > 0) { + outbuf = gst_adapter_take_buffer (self->output_adapter, avail); + flow_ret = + gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (self), outbuf, + nframes); + } + } + g_mutex_lock (&self->drain_lock); if (self->draining) { GST_DEBUG_OBJECT (self, "Drained"); @@ -727,6 +762,9 @@ gst_omx_audio_dec_stop (GstAudioDecoder * decoder) g_cond_broadcast (&self->drain_cond); g_mutex_unlock (&self->drain_lock); + gst_adapter_flush (self->output_adapter, + gst_adapter_available (self->output_adapter)); + gst_omx_component_get_state (self->dec, 5 * GST_SECOND); gst_buffer_replace (&self->codec_data, NULL); @@ -965,6 +1003,8 @@ gst_omx_audio_dec_flush (GstAudioDecoder * decoder, gboolean hard) } /* Reset our state */ + gst_adapter_flush (self->output_adapter, + gst_adapter_available (self->output_adapter)); self->last_upstream_ts = 0; self->downstream_flow_ret = GST_FLOW_OK; self->started = FALSE; @@ -1328,6 +1368,8 @@ gst_omx_audio_dec_drain (GstOMXAudioDec * self) g_mutex_unlock (&self->drain_lock); GST_AUDIO_DECODER_STREAM_LOCK (self); + gst_adapter_flush (self->output_adapter, + gst_adapter_available (self->output_adapter)); self->started = FALSE; return GST_FLOW_OK; diff --git a/omx/gstomxaudiodec.h b/omx/gstomxaudiodec.h index 5cefd88..0f4adc6 100644 --- a/omx/gstomxaudiodec.h +++ b/omx/gstomxaudiodec.h @@ -76,6 +76,8 @@ struct _GstOMXAudioDec /* TRUE if EOS buffers shouldn't be forwarded */ gboolean draining; + GstAdapter *output_adapter; + GstFlowReturn downstream_flow_ret; }; -- 2.7.4