From 0ce20cef4fcc5e5e5723479bf8e980d92ece09f5 Mon Sep 17 00:00:00 2001 From: George Kiagiadakis Date: Wed, 14 Feb 2018 13:55:06 +0200 Subject: [PATCH] gstaudiodecoder: take into account GstAudioMeta::samples on the output buffers This is useful if the output buffers are planar and have extra padding on each plane, in which case size/bpf does not represent the number of valid samples. https://bugzilla.gnome.org/show_bug.cgi?id=705977 --- gst-libs/gst/audio/gstaudiodecoder.c | 37 +++++++++++++++++++++------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/gst-libs/gst/audio/gstaudiodecoder.c b/gst-libs/gst/audio/gstaudiodecoder.c index 2b629e9f08..00dd092dc6 100644 --- a/gst-libs/gst/audio/gstaudiodecoder.c +++ b/gst-libs/gst/audio/gstaudiodecoder.c @@ -1213,9 +1213,9 @@ gst_audio_decoder_finish_frame (GstAudioDecoder * dec, GstBuffer * buf, GstAudioDecoderPrivate *priv; GstAudioDecoderContext *ctx; GstAudioDecoderClass *klass = GST_AUDIO_DECODER_GET_CLASS (dec); - gint samples = 0; + GstAudioMeta *meta; GstClockTime ts, next_ts; - gsize size; + gsize size, samples = 0; GstFlowReturn ret = GST_FLOW_OK; GQueue inbufs = G_QUEUE_INIT; @@ -1227,7 +1227,9 @@ gst_audio_decoder_finish_frame (GstAudioDecoder * dec, GstBuffer * buf, priv = dec->priv; ctx = &dec->priv->ctx; + meta = buf ? gst_buffer_get_audio_meta (buf) : NULL; size = buf ? gst_buffer_get_size (buf) : 0; + samples = buf ? (meta ? meta->samples : size / ctx->info.bpf) : 0; /* must know the output format by now */ g_return_val_if_fail (buf == NULL || GST_AUDIO_INFO_IS_VALID (&ctx->info), @@ -1235,8 +1237,7 @@ gst_audio_decoder_finish_frame (GstAudioDecoder * dec, GstBuffer * buf, GST_LOG_OBJECT (dec, "accepting %" G_GSIZE_FORMAT " bytes == %" G_GSIZE_FORMAT - " samples for %d frames", buf ? size : -1, - buf ? size / ctx->info.bpf : -1, frames); + " samples for %d frames", buf ? size : 0, samples, frames); GST_AUDIO_DECODER_STREAM_LOCK (dec); @@ -1251,12 +1252,20 @@ gst_audio_decoder_finish_frame (GstAudioDecoder * dec, GstBuffer * buf, send_pending_events (dec); } - /* output shoud be whole number of sample frames */ + /* sanity checking */ if (G_LIKELY (buf && ctx->info.bpf)) { - if (size % ctx->info.bpf) - goto wrong_buffer; - /* per channel least */ - samples = size / ctx->info.bpf; + if (!meta || meta->info.layout == GST_AUDIO_LAYOUT_INTERLEAVED) { + /* output shoud be whole number of sample frames */ + if (size % ctx->info.bpf) + goto wrong_buffer; + /* output should have no additional padding */ + if (samples != size / ctx->info.bpf) + goto wrong_samples; + } else { + /* can't have more samples than what the buffer fits */ + if (samples > size / ctx->info.bpf) + goto wrong_samples; + } } /* frame and ts book-keeping */ @@ -1408,6 +1417,16 @@ wrong_buffer: ret = GST_FLOW_ERROR; goto exit; } +wrong_samples: + { + GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), + ("GstAudioMeta samples (%" G_GSIZE_FORMAT ") are inconsistent with " + "the buffer size and layout (size/bpf = %" G_GSIZE_FORMAT ")", + meta->samples, size / ctx->info.bpf)); + gst_buffer_unref (buf); + ret = GST_FLOW_ERROR; + goto exit; + } } static GstFlowReturn