From 031dc5f637fe177e3c2b9fe74d13bec397322704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Obispo?= Date: Fri, 24 Nov 2023 13:22:24 +0100 Subject: [PATCH] added offset compensation for presentationTimeOffset --- lib/media/streaming_engine.js | 57 ++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/lib/media/streaming_engine.js b/lib/media/streaming_engine.js index e8ef7b56e0..4dae5359fb 100644 --- a/lib/media/streaming_engine.js +++ b/lib/media/streaming_engine.js @@ -1194,7 +1194,7 @@ shaka.media.StreamingEngine = class { mediaState.performingUpdate = true; try { - await this.initSourceBuffer_(mediaState, reference); + const timescale = await this.initSourceBuffer_(mediaState, reference); this.destroyer_.ensureNotDestroyed(); if (this.fatalError_) { return; @@ -1261,6 +1261,39 @@ shaka.media.StreamingEngine = class { this.scheduleUpdate_(mediaState, 0); return; } + if (timescale) { + new shaka.util.Mp4Parser() + .box('moof', shaka.util.Mp4Parser.children) + .box('traf', shaka.util.Mp4Parser.children) + .fullBox('tfdt', async (box) => { + goog.asserts.assert( + box.version != null, + 'TFDT is a full box and should have a valid version.'); + + const parsedTFDT = shaka.util.Mp4BoxParsers.parseTFDT( + box.reader, box.version); + + const baseMediaDecodeTime = parsedTFDT.baseMediaDecodeTime; + const scaledMediaDecodeTime = baseMediaDecodeTime / timescale; + + if (Math.abs(mediaState.lastTimestampOffset) > + scaledMediaDecodeTime) { + const lastAppendWindowEnd = 0 + + mediaState.lastAppendWindowEnd; + const lastAppendWindowStart = 0 + + mediaState.lastAppendWindowStart; + shaka.log.v1(logPrefix, + 'setting timestamp offset to ' + -scaledMediaDecodeTime); + await this.playerInterface_.mediaSourceEngine + .setStreamProperties( + mediaState.type, -scaledMediaDecodeTime, + lastAppendWindowStart, + lastAppendWindowEnd); + } + }) + .parse(result, /* partialOkay= */ false, + /* isChunkedData= */ true); + } await this.append_( mediaState, presentationTime, stream, reference, result); } @@ -1509,6 +1542,8 @@ shaka.media.StreamingEngine = class { operations.push(setProperties()); } + let timescale; + if (!shaka.media.InitSegmentReference.equal( reference.initSegmentReference, mediaState.lastInitSegmentReference)) { mediaState.lastInitSegmentReference = reference.initSegmentReference; @@ -1516,11 +1551,30 @@ shaka.media.StreamingEngine = class { if (reference.initSegmentReference) { shaka.log.v1(logPrefix, 'fetching init segment'); + const setTimeScale = (data) => { + new shaka.util.Mp4Parser() + .box('moov', shaka.util.Mp4Parser.children) + .box('mvhd', (box) => { + const version = box.reader.readUint8(); + if (version === 1) { + // skip according the standard + box.reader.skip(19); + } else { + box.reader.skip(11); + } + timescale = box.reader.readUint32(); + shaka.log.v2('mvhd', 'timescale', timescale); + }) + .parse(data, /* partialOkay= */ false, + /* isChunkedData= */ true); + }; + const fetchInit = this.fetch_(mediaState, reference.initSegmentReference); const append = async () => { try { const initSegment = await fetchInit; + mediaState.type === 'video' && setTimeScale(initSegment); this.destroyer_.ensureNotDestroyed(); shaka.log.v1(logPrefix, 'appending init segment'); const hasClosedCaptions = mediaState.stream.closedCaptions && @@ -1538,6 +1592,7 @@ shaka.media.StreamingEngine = class { } await Promise.all(operations); + return timescale; }