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: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7502>
This commit is contained in:
Sebastian Dröge 2024-09-11 13:23:35 +03:00 committed by GStreamer Marge Bot
parent 396ef0cbcf
commit 762a281b0c

View file

@ -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. */ /* Check if the duration differs from the default duration. */
write_duration = FALSE; write_duration = FALSE;
block_duration = 0; 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_BUFFER_DURATION (buf) + duration_diff;
block_duration = gst_util_uint64_scale (block_duration, 1, mux->time_scale); 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. */ /* small difference should be ok. */
if (block_duration > collect_pad->default_duration_scaled + 1 || if (block_duration > collect_pad->default_duration_scaled + 1 ||
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) if (is_video_invisible)
flags |= 0x08; 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 (mux->doctype_version > 1 && !write_duration && !cmeta) {
if (is_video_keyframe) if (is_video_keyframe)
flags |= 0x80; flags |= 0x80;