amcaudiodec: 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
This commit is contained in:
Sebastian Dröge 2015-05-19 18:02:30 +03:00
parent 7ca9f52ccb
commit 8bacecfb08
2 changed files with 46 additions and 10 deletions

View file

@ -228,6 +228,7 @@ gst_amc_audio_dec_init (GstAmcAudioDec * self)
g_mutex_init (&self->drain_lock);
g_cond_init (&self->drain_cond);
self->output_adapter = gst_adapter_new ();
}
static gboolean
@ -283,6 +284,10 @@ gst_amc_audio_dec_finalize (GObject * object)
{
GstAmcAudioDec *self = GST_AMC_AUDIO_DEC (object);
if (self->output_adapter)
gst_object_unref (self->output_adapter);
self->output_adapter = NULL;
g_mutex_clear (&self->drain_lock);
g_cond_clear (&self->drain_cond);
@ -505,7 +510,6 @@ retry:
GstBuffer *outbuf;
GstAmcBuffer *buf;
GstMapInfo minfo;
gint nframes;
/* 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
@ -545,18 +549,39 @@ retry:
}
gst_buffer_unmap (outbuf, &minfo);
nframes = 1;
if (self->spf != -1) {
nframes = buffer_info.size / self->info.bpf;
if (nframes % self->spf != 0)
GST_WARNING_OBJECT (self, "Output buffer does not contain an integer "
"number of input frames (frames: %d, spf: %d)", nframes, self->spf);
nframes = (nframes + self->spf - 1) / self->spf;
gst_adapter_push (self->output_adapter, outbuf);
} else {
flow_ret =
gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (self), outbuf, 1);
}
}
flow_ret =
gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (self), outbuf,
nframes);
if (self->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.
* Otherwise we take a multiple of codec frames and push
* them downstream
*/
avail /= self->info.bpf;
if (!is_eos) {
nframes = avail / self->spf;
avail = nframes * self->spf;
} else {
nframes = (avail + self->spf - 1) / self->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);
}
}
if (!gst_amc_codec_release_output_buffer (self->codec, idx, &err)) {
@ -782,6 +807,9 @@ gst_amc_audio_dec_stop (GstAudioDecoder * decoder)
memset (self->positions, 0, sizeof (self->positions));
gst_adapter_flush (self->output_adapter,
gst_adapter_available (self->output_adapter));
g_list_foreach (self->codec_datas, (GFunc) g_free, NULL);
g_list_free (self->codec_datas);
self->codec_datas = NULL;
@ -1014,6 +1042,8 @@ gst_amc_audio_dec_flush (GstAudioDecoder * decoder, gboolean hard)
gst_amc_codec_flush (self->codec, &err);
if (err)
GST_ELEMENT_WARNING_FROM_ERROR (self, err);
gst_adapter_flush (self->output_adapter,
gst_adapter_available (self->output_adapter));
self->flushing = FALSE;
/* Start the srcpad loop again */
@ -1295,5 +1325,8 @@ gst_amc_audio_dec_drain (GstAmcAudioDec * self)
ret = GST_FLOW_ERROR;
}
gst_adapter_flush (self->output_adapter,
gst_adapter_available (self->output_adapter));
return ret;
}

View file

@ -59,6 +59,9 @@ struct _GstAmcAudioDec
gboolean input_caps_changed;
gint spf;
/* For collecting complete frames for the output */
GstAdapter *output_adapter;
/* Output format of the codec */
GstAudioInfo info;
/* AMC positions, might need reordering */