From 762a281b0c2735064b4d7525fa5379c4031cd944 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 11 Sep 2024 13:23:35 +0300 Subject: [PATCH] matroskamux: Include end padding in the block duration for Opus streams It has to be included in the block duration but in GStreamer we're not including it in the buffer duration, so it has to be added again here. Not including it in the block duration can lead to fatal errors when playing back with Firefox if there are more padding samples than actual samples, e.g. > D/MediaDemuxer WebMDemuxer[7f6a0808b900] ::GetNextPacket: Padding frames larger > than packet size, flagging the packet for error (padding: {13500000,1000000000}, > duration: {6000,1000000}, already processed: false) Part-of: --- .../gst/matroska/matroska-mux.c | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/subprojects/gst-plugins-good/gst/matroska/matroska-mux.c b/subprojects/gst-plugins-good/gst/matroska/matroska-mux.c index f6f49a44ba..8f1435983b 100644 --- a/subprojects/gst-plugins-good/gst/matroska/matroska-mux.c +++ b/subprojects/gst-plugins-good/gst/matroska/matroska-mux.c @@ -4203,6 +4203,15 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad, } } + if (!strcmp (collect_pad->track->codec_id, GST_MATROSKA_CODEC_ID_AUDIO_OPUS)) { + cmeta = gst_buffer_get_audio_clipping_meta (buf); + g_assert (!cmeta || cmeta->format == GST_FORMAT_DEFAULT); + + /* Start clipping is done via header and CodecDelay */ + if (cmeta && !cmeta->end) + cmeta = NULL; + } + /* Check if the duration differs from the default duration. */ write_duration = FALSE; block_duration = 0; @@ -4210,6 +4219,15 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad, block_duration = GST_BUFFER_DURATION (buf) + duration_diff; block_duration = gst_util_uint64_scale (block_duration, 1, mux->time_scale); + /* Padding should be considered in the block duration and is clipped off + * again during playback. Specifically, firefox considers it a fatal error + * if there is more padding than the block duration */ + if (cmeta) { + guint64 end = gst_util_uint64_scale_round (cmeta->end, GST_SECOND, 48000); + end = gst_util_uint64_scale (end, 1, mux->time_scale); + block_duration += end; + } + /* small difference should be ok. */ if (block_duration > collect_pad->default_duration_scaled + 1 || block_duration < collect_pad->default_duration_scaled - 1) { @@ -4237,15 +4255,6 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad, if (is_video_invisible) flags |= 0x08; - if (!strcmp (collect_pad->track->codec_id, GST_MATROSKA_CODEC_ID_AUDIO_OPUS)) { - cmeta = gst_buffer_get_audio_clipping_meta (buf); - g_assert (!cmeta || cmeta->format == GST_FORMAT_DEFAULT); - - /* Start clipping is done via header and CodecDelay */ - if (cmeta && !cmeta->end) - cmeta = NULL; - } - if (mux->doctype_version > 1 && !write_duration && !cmeta) { if (is_video_keyframe) flags |= 0x80;