Skip to content

Commit

Permalink
feat: Add isLowLatency to shaka.extern.Manifest (#6842)
Browse files Browse the repository at this point in the history
  • Loading branch information
avelad authored Jun 18, 2024
1 parent 5f06a32 commit e020814
Show file tree
Hide file tree
Showing 13 changed files with 38 additions and 19 deletions.
5 changes: 4 additions & 1 deletion externs/shaka/manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
* serviceDescription: ?shaka.extern.ServiceDescription,
* nextUrl: ?string,
* periodCount: number,
* gapCount: number
* gapCount: number,
* isLowLatency: boolean
* }}
*
* @description
Expand Down Expand Up @@ -108,6 +109,8 @@
* discontinuities found between periods. For HLS, it is a number of EXT-X-GAP
* and GAP=YES occurrences. For MSS, it is always set to 0.
* If in src= mode or nothing is loaded, NaN.
* @property {bolean} isLowLatency
* If true, the manifest is Low Latency.
*
* @exportDoc
*/
Expand Down
16 changes: 7 additions & 9 deletions lib/dash/dash_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ shaka.dash.DashParser = class {

/** @private {number} */
this.gapCount_ = 0;

/** @private {boolean} */
this.isLowLatency_ = false;
}

/**
Expand Down Expand Up @@ -709,7 +712,7 @@ shaka.dash.DashParser = class {
// lowLatencyMode, but if it has been configured to activate the
// lowLatencyMode if a stream of this type is detected, we automatically
// activate the lowLatencyMode.
if (this.minTotalAvailabilityTimeOffset_ && !this.lowLatencyMode_) {
if (this.isLowLatency_ && !this.lowLatencyMode_) {
const autoLowLatencyMode = this.playerInterface_.isAutoLowLatencyMode();
if (autoLowLatencyMode) {
this.playerInterface_.enableLowLatencyMode();
Expand All @@ -720,14 +723,6 @@ shaka.dash.DashParser = class {
if (this.lowLatencyMode_) {
presentationTimeline.setAvailabilityTimeOffset(
this.minTotalAvailabilityTimeOffset_);
} else if (this.minTotalAvailabilityTimeOffset_) {
// If the playlist contains AvailabilityTimeOffset value, the
// streaming.lowLatencyMode value should be set to true to stream with low
// latency mode.
shaka.log.alwaysWarn('Low-latency DASH live stream detected, but ' +
'low-latency streaming mode is not enabled in Shaka Player. ' +
'Set streaming.lowLatencyMode configuration to true, and see ' +
'https://bit.ly/3clctcj for details.');
}

// Use @maxSegmentDuration to override smaller, derived values.
Expand Down Expand Up @@ -765,6 +760,7 @@ shaka.dash.DashParser = class {
nextUrl: this.parseMpdChaining_(mpd),
periodCount: periods.length,
gapCount: this.gapCount_,
isLowLatency: this.isLowLatency_,
};

// We only need to do clock sync when we're using presentation start
Expand Down Expand Up @@ -1918,6 +1914,8 @@ shaka.dash.DashParser = class {
Math.min(this.minTotalAvailabilityTimeOffset_,
context.representation.availabilityTimeOffset);

this.isLowLatency_ = this.minTotalAvailabilityTimeOffset_ > 0;

if (!this.verifyRepresentation_(context.representation)) {
shaka.log.warning('Skipping Representation', context.representation);
return null;
Expand Down
8 changes: 3 additions & 5 deletions lib/hls/hls_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,7 @@ shaka.hls.HlsParser = class {
nextUrl: null,
periodCount: 1,
gapCount: 0,
isLowLatency: false,
};

// If there is no 'CODECS' attribute in the manifest and codec guessing is
Expand Down Expand Up @@ -3353,11 +3354,8 @@ shaka.hls.HlsParser = class {
let startByte = 0;
let endByte = null;

if (hlsSegment.partialSegments.length && !this.lowLatencyMode_) {
shaka.log.alwaysWarn('Low-latency HLS live stream detected, but ' +
'low-latency streaming mode is not enabled in Shaka ' +
'Player. Set streaming.lowLatencyMode configuration to ' +
'true, and see https://bit.ly/3clctcj for details.');
if (hlsSegment.partialSegments.length) {
this.manifest_.isLowLatency = true;
}

let syncTime = null;
Expand Down
6 changes: 4 additions & 2 deletions lib/media/streaming_engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -1529,9 +1529,11 @@ shaka.media.StreamingEngine = class {
const isMP4 = stream.mimeType == 'video/mp4' ||
stream.mimeType == 'audio/mp4';
const isReadableStreamSupported = window.ReadableStream;
const lowLatencyMode = this.config_.lowLatencyMode &&
this.manifest_.isLowLatency;
// Enable MP4 low latency streaming with ReadableStream chunked data.
// And only for DASH and HLS with byterange optimization.
if (this.config_.lowLatencyMode && isReadableStreamSupported && isMP4 &&
if (lowLatencyMode && isReadableStreamSupported && isMP4 &&
(this.manifest_.type != shaka.media.ManifestParser.HLS ||
reference.hasByterangeOptimization())) {
let remaining = new Uint8Array(0);
Expand Down Expand Up @@ -1622,7 +1624,7 @@ shaka.media.StreamingEngine = class {
reference.startTime, /* skipFirst= */ true);
}
} else {
if (this.config_.lowLatencyMode && !isReadableStreamSupported) {
if (lowLatencyMode && !isReadableStreamSupported) {
shaka.log.warning('Low latency streaming mode is enabled, but ' +
'ReadableStream is not supported by the browser.');
}
Expand Down
1 change: 1 addition & 0 deletions lib/mss/mss_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ shaka.mss.MssParser = class {
nextUrl: null,
periodCount: 1,
gapCount: 0,
isLowLatency: false,
};

// This is the first point where we have a meaningful presentation start
Expand Down
1 change: 1 addition & 0 deletions lib/offline/manifest_converter.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ shaka.offline.ManifestConverter = class {
nextUrl: null,
periodCount: 1,
gapCount: 0,
isLowLatency: false,
};
}

Expand Down
7 changes: 7 additions & 0 deletions lib/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -2446,6 +2446,13 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
this.parser_.onInitialVariantChosen(toLazyLoad);
}

if (this.manifest_.isLowLatency && !this.config_.streaming.lowLatencyMode) {
shaka.log.alwaysWarn('Low-latency live stream detected, but ' +
'low-latency streaming mode is not enabled in Shaka Player. ' +
'Set streaming.lowLatencyMode configuration to true, and see ' +
'https://bit.ly/3clctcj for details.');
}

shaka.Player.applyPlayRange_(this.manifest_.presentationTimeline,
this.config_.playRangeStart,
this.config_.playRangeEnd);
Expand Down
7 changes: 5 additions & 2 deletions test/hls/hls_parser_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -2923,8 +2923,10 @@ describe('HlsParser', () => {
* @param {!Array.<number>} startTimes
* @param {number} syncTimeOffset
* @param {(function(!shaka.media.SegmentReference))=} modifyFn
* @param {boolean=} isLowLatency
*/
async function test(media, startTimes, syncTimeOffset, modifyFn) {
async function test(media, startTimes, syncTimeOffset, modifyFn,
isLowLatency = false) {
const master = [
'#EXTM3U\n',
'#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1.4d401f,vtt",',
Expand Down Expand Up @@ -2953,6 +2955,7 @@ describe('HlsParser', () => {
});
manifest.sequenceMode = sequenceMode;
manifest.type = shaka.media.ManifestParser.HLS;
manifest.isLowLatency = !!isLowLatency;
});

fakeNetEngine
Expand Down Expand Up @@ -3073,7 +3076,7 @@ describe('HlsParser', () => {
reference.partialReferences = [partialRef, partialRef2];
reference.allPartialSegments = true;
}
});
}, /* isLowLatency= */ true);
});
});

Expand Down
1 change: 1 addition & 0 deletions test/media/playhead_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ describe('Playhead', () => {
nextUrl: null,
periodCount: 1,
gapCount: 0,
isLowLatency: false,
};

config = shaka.util.PlayerConfiguration.createDefault().streaming;
Expand Down
1 change: 1 addition & 0 deletions test/media/streaming_engine_integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,7 @@ describe('StreamingEngine', () => {
nextUrl: null,
periodCount: 1,
gapCount: 0,
isLowLatency: false,
variants: [{
id: 1,
video: {
Expand Down
1 change: 1 addition & 0 deletions test/media/streaming_engine_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,7 @@ describe('StreamingEngine', () => {
// Use the VOD manifests to test the streamDataCallback function in the low
// latency mode.
setupVod();
manifest.isLowLatency = true;

const config = shaka.util.PlayerConfiguration.createDefault().streaming;
config.lowLatencyMode = true;
Expand Down
2 changes: 2 additions & 0 deletions test/test/util/manifest_generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ shaka.test.ManifestGenerator.Manifest = class {
this.periodCount = 1;
/** @type {number} */
this.gapCount = 0;
/** @type {boolean} */
this.isLowLatency = false;


/** @type {shaka.extern.Manifest} */
Expand Down
1 change: 1 addition & 0 deletions test/test/util/streaming_engine_util.js
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ shaka.test.StreamingEngineUtil = class {
nextUrl: null,
periodCount: 1,
gapCount: 0,
isLowLatency: false,
};

/** @type {shaka.extern.Variant} */
Expand Down

0 comments on commit e020814

Please sign in to comment.