From 9121131f3121466910eee5a735b2dab18cb8a7a5 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 4 Nov 2016 16:41:05 +0000 Subject: [PATCH] opusdec: fix 120 ms buffers being wrongly emitted Using the max 120 ms buffer size to ensure we have enough space for decoded data meant that Opus could actually return 120 ms' worth of data. https://bugzilla.gnome.org/show_bug.cgi?id=771723 --- ext/opus/gstopusdec.c | 59 ++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/ext/opus/gstopusdec.c b/ext/opus/gstopusdec.c index 304e6bf8a2..46d6663000 100644 --- a/ext/opus/gstopusdec.c +++ b/ext/opus/gstopusdec.c @@ -590,11 +590,11 @@ opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buffer) " num frame samples: %d new leftover: %" GST_TIME_FORMAT, GST_TIME_ARGS (aligned_missing_duration), samples, GST_TIME_ARGS (dec->leftover_plc_duration)); + } else { + /* use maximum size (120 ms) as the number of returned samples is + not constant over the stream. */ + samples = 120 * dec->sample_rate / 1000; } - - /* use maximum size (120 ms) as the number of returned samples is - not constant over the stream. */ - samples = 120 * dec->sample_rate / 1000; packet_size = samples * dec->n_channels * 2; outbuf = @@ -610,23 +610,44 @@ opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buffer) gst_buffer_map (outbuf, &omap, GST_MAP_WRITE); out_data = (gint16 *) omap.data; - if (dec->use_inband_fec) { - if (gst_buffer_get_size (dec->last_buffer) > 0) { - /* normal delayed decode */ - GST_LOG_OBJECT (dec, "FEC enabled, decoding last delayed buffer"); - n = opus_multistream_decode (dec->state, data, size, out_data, samples, - 0); + do { + if (dec->use_inband_fec) { + if (gst_buffer_get_size (dec->last_buffer) > 0) { + /* normal delayed decode */ + GST_LOG_OBJECT (dec, "FEC enabled, decoding last delayed buffer"); + n = opus_multistream_decode (dec->state, data, size, out_data, samples, + 0); + } else { + /* FEC reconstruction decode */ + GST_LOG_OBJECT (dec, "FEC enabled, reconstructing last buffer"); + n = opus_multistream_decode (dec->state, data, size, out_data, samples, + 1); + } } else { - /* FEC reconstruction decode */ - GST_LOG_OBJECT (dec, "FEC enabled, reconstructing last buffer"); + /* normal decode */ + GST_LOG_OBJECT (dec, "FEC disabled, decoding buffer"); n = opus_multistream_decode (dec->state, data, size, out_data, samples, - 1); + 0); } - } else { - /* normal decode */ - GST_LOG_OBJECT (dec, "FEC disabled, decoding buffer"); - n = opus_multistream_decode (dec->state, data, size, out_data, samples, 0); - } + if (n == OPUS_BUFFER_TOO_SMALL) { + /* if too small, add 2.5 milliseconds and try again, up to the + * Opus max size of 120 milliseconds */ + if (samples >= 120 * dec->sample_rate / 1000) + break; + samples += 25 * dec->sample_rate / 10000; + packet_size = samples * dec->n_channels * 2; + gst_buffer_unmap (outbuf, &omap); + gst_buffer_unref (outbuf); + outbuf = + gst_audio_decoder_allocate_output_buffer (GST_AUDIO_DECODER (dec), + packet_size); + if (!outbuf) { + goto buffer_failed; + } + gst_buffer_map (outbuf, &omap, GST_MAP_WRITE); + out_data = (gint16 *) omap.data; + } + } while (n == OPUS_BUFFER_TOO_SMALL); gst_buffer_unmap (outbuf, &omap); if (data != NULL) gst_buffer_unmap (buf, &map); @@ -641,6 +662,8 @@ opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buffer) } GST_DEBUG_OBJECT (dec, "decoded %d samples", n); gst_buffer_set_size (outbuf, n * 2 * dec->n_channels); + GST_BUFFER_DURATION (outbuf) = samples * GST_SECOND / dec->sample_rate; + samples = n; cmeta = gst_buffer_get_audio_clipping_meta (buf); -- 2.34.1