From 88f16ebd2a0c63d83f1870a266ad93e53af9ee06 Mon Sep 17 00:00:00 2001 From: Hosang Lee Date: Tue, 16 Jun 2020 15:18:37 +0900 Subject: [PATCH] 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: --- .../gst-plugins-good/gst/isomp4/qtdemux.c | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/subprojects/gst-plugins-good/gst/isomp4/qtdemux.c b/subprojects/gst-plugins-good/gst/isomp4/qtdemux.c index e6ab452d5f..c13addee22 100644 --- a/subprojects/gst-plugins-good/gst/isomp4/qtdemux.c +++ b/subprojects/gst-plugins-good/gst/isomp4/qtdemux.c @@ -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);