summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Penquerc'h <vincent.penquerch@collabora.co.uk>2016-11-04 16:41:05 +0000
committerSebastian Dröge <sebastian@centricular.com>2016-12-05 11:03:46 +0200
commitfaac1d7089a58e56abff44242feba3edff42ff2e (patch)
tree296a081f0c59769eb493f7753297b95d62ddba80
parentbe96016d5f7aec7b6791c6d44e16f37383d6bc31 (diff)
downloadgstreamer-plugins-base-faac1d7089a58e56abff44242feba3edff42ff2e.tar.gz
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
-rw-r--r--ext/opus/gstopusdec.c59
1 files changed, 41 insertions, 18 deletions
diff --git a/ext/opus/gstopusdec.c b/ext/opus/gstopusdec.c
index 304e6bf8a..46d666300 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);