From 4972ba2652ae07d24d4f4998fd49b94e2a1e2a74 Mon Sep 17 00:00:00 2001 From: Alvaro Velad Galvan Date: Mon, 19 Jun 2023 10:03:27 +0200 Subject: [PATCH] fix: Get the correct timescale when there are two trak boxes --- lib/media/streaming_engine.js | 40 +++++++++++++++++++++++------------ lib/util/mp4_box_parsers.js | 34 +++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 13 deletions(-) diff --git a/lib/media/streaming_engine.js b/lib/media/streaming_engine.js index 952631d5aef..7136ee31602 100644 --- a/lib/media/streaming_engine.js +++ b/lib/media/streaming_engine.js @@ -1759,16 +1759,42 @@ shaka.media.StreamingEngine = class { const initSegment = await fetchInit; this.destroyer_.ensureNotDestroyed(); + let lastTimescale = null; + const timescaleMap = new Map(); + const parser = new shaka.util.Mp4Parser(); const Mp4Parser = shaka.util.Mp4Parser; parser.box('moov', Mp4Parser.children) .box('trak', Mp4Parser.children) .box('mdia', Mp4Parser.children) .fullBox('mdhd', (box) => { - this.parseMDHD_(reference, box); + goog.asserts.assert( + box.version != null, + 'MDHD is a full box and should have a valid version.'); + const parsedMDHDBox = shaka.util.Mp4BoxParsers.parseMDHD( + box.reader, box.version); + lastTimescale = parsedMDHDBox.timescale; + }) + .box('hdlr', (box) => { + const parsedHDLR = shaka.util.Mp4BoxParsers.parseHDLR( + box.reader); + switch (parsedHDLR.handlerType) { + case 'soun': + timescaleMap.set(ContentType.AUDIO, lastTimescale); + break; + case 'vide': + timescaleMap.set(ContentType.VIDEO, lastTimescale); + break; + } + lastTimescale = null; }) .parse(initSegment); + if (timescaleMap.has(mediaState.type)) { + reference.initSegmentReference.timescale = + timescaleMap.get(mediaState.type); + } + shaka.log.v1(logPrefix, 'appending init segment'); const hasClosedCaptions = mediaState.stream.closedCaptions && mediaState.stream.closedCaptions.size > 0; @@ -1998,18 +2024,6 @@ shaka.media.StreamingEngine = class { } } - /** - * Parse MDHD box. - * @param {!shaka.media.SegmentReference} reference - * @param {!shaka.extern.ParsedBox} box - * @private - */ - parseMDHD_(reference, box) { - const parsedMDHDBox = shaka.util.Mp4BoxParsers.parseMDHD( - box.reader || 0, box.version || 0); - reference.initSegmentReference.timescale = parsedMDHDBox.timescale; - } - /** * Parse PRFT box. * @param {!shaka.media.SegmentReference} reference diff --git a/lib/util/mp4_box_parsers.js b/lib/util/mp4_box_parsers.js index 49b2d2e318c..dc215941716 100644 --- a/lib/util/mp4_box_parsers.js +++ b/lib/util/mp4_box_parsers.js @@ -251,6 +251,26 @@ shaka.util.Mp4BoxParsers = class { const codec = shaka.util.Mp4Parser.typeToString(fourcc); return {codec}; } + + /** + * Parses a HDLR box. + * @param {!shaka.util.DataViewReader} reader + * @return {!shaka.util.ParsedHDLRBox} + */ + static parseHDLR(reader) { + reader.skip(8); // Skip "pre_defined" + const parseType = (data) => { + let result = ''; + result += String.fromCharCode(data[0]); + result += String.fromCharCode(data[1]); + result += String.fromCharCode(data[2]); + result += String.fromCharCode(data[3]); + return result; + }; + const handlerType = parseType(reader.readBytes(4)); + + return {handlerType}; + } }; @@ -403,3 +423,17 @@ shaka.util.ParsedFRMABox; * @exportDoc */ shaka.util.ParsedMP4ABox; + +/** + * @typedef {{ + * handlerType: string + * }} + * + * @property {string} handlerType + * A four-character code that identifies the type of the media handler or + * data handler. For media handlers, this field defines the type of + * data—for example, 'vide' for video data, 'soun' for sound data. + * + * @exportDoc + */ +shaka.util.ParsedHDLRBox;