qtdemux: compensate wrong data offset for MSS fragments

A data offset with an offset smaller than the moof length is wrong
in smooth streaming streams.

The samples will not be located and eventually playback will
error out. So compensate assuming data is in mdat following moof.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3840>
This commit is contained in:
Hosang Lee 2020-06-16 15:18:37 +09:00 committed by GStreamer Marge Bot
parent f7c2602d41
commit 88f16ebd2a

View file

@ -3320,7 +3320,7 @@ qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
gboolean has_tfdt)
gboolean has_tfdt, guint trun_node_total)
{
GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
guint64 timestamp;
@ -3364,6 +3364,17 @@ qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
/* note this is really signed */
if (!gst_byte_reader_get_int32_be (trun, &data_offset))
goto fail;
if (qtdemux->variant == VARIANT_MSS_FRAGMENTED
&& data_offset <= moof_length
&& *base_offset == -1 && trun_node_total == 1) {
/* MSS spec states that, if only one TrunBox is specified, then the
* DataOffset field MUST be the sum of the lengths of the MoofBox and all
* the fields in the MdatBox field */
GST_WARNING_OBJECT (qtdemux,
"trun offset is less than the moof size, assuming offset is after moof");
data_offset = moof_length + 8;
}
GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
/* default base offset = first byte of moof */
if (*base_offset == -1) {
@ -4130,6 +4141,7 @@ qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
while (traf_node) {
guint64 decode_time = 0;
guint trun_node_total = 0;
/* Fragment Header node */
tfhd_node =
@ -4249,6 +4261,20 @@ qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
stream->duration_last_moof = stream->duration_moof;
stream->duration_moof = 0;
/* Count the number of trun nodes */
if (qtdemux->variant == VARIANT_MSS_FRAGMENTED) {
trun_node =
qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
&trun_data);
while (trun_node) {
trun_node_total++;
trun_node =
qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
&trun_data);
}
GST_LOG_OBJECT (qtdemux, "%u trun node(s) available", trun_node_total);
}
/* Track Run node */
trun_node =
qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
@ -4256,7 +4282,7 @@ qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
while (trun_node) {
qtdemux_parse_trun (qtdemux, &trun_data, stream,
ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
&running_offset, decode_time, (tfdt_node != NULL));
&running_offset, decode_time, (tfdt_node != NULL), trun_node_total);
/* iterate all siblings */
trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
&trun_data);