Skip to content

Commit

Permalink
fix: Get the correct timescale when there are two trak boxes (#5327)
Browse files Browse the repository at this point in the history
  • Loading branch information
avelad authored Jun 20, 2023
1 parent c1369de commit 022f6b9
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 16 deletions.
6 changes: 3 additions & 3 deletions lib/media/segment_reference.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ shaka.media.InitSegmentReference = class {
* segment extends to the end of the resource.
* @param {null|shaka.extern.MediaQualityInfo=} mediaQuality Information about
* the quality of the media associated with this init segment.
* @param {number=} timescale
* @param {(null|number)=} timescale
* @param {(null|BufferSource)=} segmentData
*/
constructor(uris, startByte, endByte, mediaQuality = null, timescale,
constructor(uris, startByte, endByte, mediaQuality = null, timescale = null,
segmentData = null) {
/** @type {function():!Array.<string>} */
this.getUris = uris;
Expand All @@ -47,7 +47,7 @@ shaka.media.InitSegmentReference = class {
/** @const {shaka.extern.MediaQualityInfo|null} */
this.mediaQuality = mediaQuality;

/** @type {number|undefined} */
/** @type {number|null} */
this.timescale = timescale;

/** @type {BufferSource|null} */
Expand Down
43 changes: 30 additions & 13 deletions lib/media/streaming_engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -1758,16 +1758,45 @@ 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);
} else if (lastTimescale != null) {
// Fallback for segments without HDLR box
reference.initSegmentReference.timescale = lastTimescale;
}

shaka.log.v1(logPrefix, 'appending init segment');
const hasClosedCaptions = mediaState.stream.closedCaptions &&
mediaState.stream.closedCaptions.size > 0;
Expand Down Expand Up @@ -1997,18 +2026,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
Expand Down
32 changes: 32 additions & 0 deletions lib/util/mp4_box_parsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,24 @@ 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 data = reader.readBytes(4);
let handlerType = '';
handlerType += String.fromCharCode(data[0]);
handlerType += String.fromCharCode(data[1]);
handlerType += String.fromCharCode(data[2]);
handlerType += String.fromCharCode(data[3]);

return {handlerType};
}
};


Expand Down Expand Up @@ -403,3 +421,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;

0 comments on commit 022f6b9

Please sign in to comment.