From 516430bde191bb0fd2fbb23a282af0511240ab78 Mon Sep 17 00:00:00 2001 From: KongQun Yang Date: Mon, 7 Dec 2020 00:02:02 -0800 Subject: [PATCH] [MP4] Truncate segment references in 'sidx' if necessary The reference count in 'sidx' box is a uint16 field, which allows at most 0xFFFF entries, i.e. at most 0xFFFF subsegments, which is roughly 18 hours for one second segments. Do not fail packaging when it happens. Instead, generate a warning and truncate the number of references to 0xFFFF instead. Note that the actual number of mp4 fragments in the mp4 file can still be more than 0xFFFF. The stream will not play to the end in DASH, but it will play successfully in HLS. Workarounds #862. Change-Id: Ib3930418d1528df1f9ea64cda0d0ebaa78d26abb --- packager/media/formats/mp4/box_definitions.cc | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/packager/media/formats/mp4/box_definitions.cc b/packager/media/formats/mp4/box_definitions.cc index e42df84e74..cdf942a47d 100644 --- a/packager/media/formats/mp4/box_definitions.cc +++ b/packager/media/formats/mp4/box_definitions.cc @@ -5,6 +5,7 @@ #include "packager/media/formats/mp4/box_definitions.h" #include +#include #include #include "packager/base/logging.h" @@ -2747,10 +2748,22 @@ bool SegmentIndex::ReadWriteInternal(BoxBuffer* buffer) { buffer->ReadWriteUInt64NBytes(&earliest_presentation_time, num_bytes) && buffer->ReadWriteUInt64NBytes(&first_offset, num_bytes)); - uint16_t reference_count = static_cast(references.size()); + uint16_t reference_count; + if (references.size() <= std::numeric_limits::max()) { + reference_count = static_cast(references.size()); + } else { + reference_count = std::numeric_limits::max(); + LOG(WARNING) << "Seeing " << references.size() + << " subsegment references, but at most " << reference_count + << " references can be stored in 'sidx' box." + << " The extra references are truncated."; + LOG(WARNING) << "The stream will not play to the end in DASH."; + LOG(WARNING) << "A possible workaround is to increase segment duration."; + } RCHECK(buffer->IgnoreBytes(2) && // reserved. buffer->ReadWriteUInt16(&reference_count)); - references.resize(reference_count); + if (buffer->Reading()) + references.resize(reference_count); uint32_t reference_type_size; uint32_t sap; @@ -2782,7 +2795,10 @@ size_t SegmentIndex::ComputeSizeInternal() { version = IsFitIn32Bits(earliest_presentation_time, first_offset) ? 0 : 1; return HeaderSize() + sizeof(reference_id) + sizeof(timescale) + sizeof(uint32_t) * (1 + version) * 2 + 2 * sizeof(uint16_t) + - 3 * sizeof(uint32_t) * references.size(); + 3 * sizeof(uint32_t) * + std::min( + references.size(), + static_cast(std::numeric_limits::max())); } MediaData::MediaData() = default;