Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support Parallel Segment Fetching #4784

Merged
merged 12 commits into from
Jan 31, 2023
2 changes: 1 addition & 1 deletion demo/locales/source.json
Original file line number Diff line number Diff line change
Expand Up @@ -1044,7 +1044,7 @@
"message": "Filters for assets that have [JARGON:XLINK] tags in their manifests, so that they can be broken into multiple files."
},
"DEMO_SEGMENT_PREFETCH_LIMIT": {
"description": "Segment Prefetch Limit configuration used by StreamingEngine.",
"description": "Max number of segments to be prefetched ahead of current time position.",
"message": "Segment Prefetch Limit."
}
}
3 changes: 1 addition & 2 deletions externs/shaka/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -1076,8 +1076,7 @@ shaka.extern.ManifestConfiguration;
* @property {boolean} segmentPrefetchLimit
* The maximum number of segments for each active stream to be prefetched
* ahead of playhead in parallel.
* If <code>0</code>, the segments will be fetched
* sequentially.
* If <code>0</code>, the segments will be fetched sequentially.
* Defaults to <code>0</code>.
* @exportDoc
*/
Expand Down
43 changes: 24 additions & 19 deletions lib/media/segment_prefetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

goog.require('goog.asserts');
goog.require('shaka.net.NetworkingEngine');
goog.require('shaka.media.InitSegmentReference');
goog.require('shaka.media.SegmentReference');
Expand All @@ -20,15 +21,10 @@ shaka.media.SegmentPrefetch = class {
/**
* @param {number} prefetchLimit
* @param {shaka.extern.Stream} stream
* @param {function(
* !(shaka.media.InitSegmentReference|shaka.media.SegmentReference),
* shaka.extern.Stream
* ):!shaka.net.NetworkingEngine.PendingRequest} fetchDispatcher
* @param {shaka.media.SegmentPrefetch.fetchDispatcher} fetchDispatcher
tyrelltle marked this conversation as resolved.
Show resolved Hide resolved
*/
constructor(prefetchLimit, stream, fetchDispatcher) {
/**
* @private {number}
*/
/** @private {number} */
this.prefetchLimit_ = prefetchLimit;

/** @private {shaka.extern.Stream} */
Expand All @@ -37,15 +33,12 @@ shaka.media.SegmentPrefetch = class {
/** @private {number} */
this.prefetchPosTime_ = 0;

/** @private {function(
* !(shaka.media.InitSegmentReference|shaka.media.SegmentReference),
* shaka.extern.Stream
* ):!shaka.net.NetworkingEngine.PendingRequest} */
/** @private {shaka.media.SegmentPrefetch.fetchDispatcher} */
this.fetchDispatcher_ = fetchDispatcher;

/**
* @private {!Map.<shaka.media.SegmentReference,
!shaka.net.NetworkingEngine.PendingRequest>}
* !shaka.net.NetworkingEngine.PendingRequest>}
*/
this.segmentPrefetchMap_ = new Map();
}
Expand All @@ -57,9 +50,9 @@ shaka.media.SegmentPrefetch = class {
* @public
*/
prefetchSegments(startReference) {
if (!(this.prefetchLimit_ > 0)) {
return;
}
goog.asserts.assert(this.prefetchLimit_ > 0,
'SegmentPrefetch can not be used when prefetchLimit <= 0.');

const logPrefix = shaka.media.SegmentPrefetch.logPrefix_(
theodab marked this conversation as resolved.
Show resolved Hide resolved
this.stream_,
);
Expand Down Expand Up @@ -93,11 +86,11 @@ shaka.media.SegmentPrefetch = class {
* @public
*/
getPrefetchedSegment(reference) {
goog.asserts.assert(this.prefetchLimit_ > 0,
'SegmentPrefetch can not be used when prefetchLimit <= 0.');

let op = null;
if (
!(reference instanceof shaka.media.SegmentReference) ||
!(this.prefetchLimit_ > 0)
) {
if (!(reference instanceof shaka.media.SegmentReference)) {
return null;
}

Expand Down Expand Up @@ -171,3 +164,15 @@ shaka.media.SegmentPrefetch = class {
return 'SegmentPrefetch(' + stream.type + ':' + stream.id + ')';
}
};

/**
* @typedef {function(
* !(shaka.media.InitSegmentReference|shaka.media.SegmentReference),
* shaka.extern.Stream
* ):!shaka.net.NetworkingEngine.PendingRequest}
*
* @description
* A callback function that fetches a segment.
* @export
*/
shaka.media.SegmentPrefetch.fetchDispatcher;
11 changes: 4 additions & 7 deletions lib/media/streaming_engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -2100,7 +2100,7 @@ shaka.media.StreamingEngine = class {

shaka.log.v2('fetching: reference=', reference);
let duration = 0;
if ((reference instanceof shaka.media.SegmentReference)) {
if (reference instanceof shaka.media.SegmentReference) {
// start and endTime are not defined in InitSegmentReference
duration = reference.endTime - reference.startTime;
}
Expand Down Expand Up @@ -2164,10 +2164,6 @@ shaka.media.StreamingEngine = class {
}
}

if (mediaState.segmentPrefetch) {
mediaState.segmentPrefetch.clearAll();
}

this.destroyer_.ensureNotDestroyed();

shaka.log.debug(logPrefix, 'cleared buffer');
Expand Down Expand Up @@ -2414,8 +2410,9 @@ shaka.media.StreamingEngine.PlayerInterface;
* updating.
* @property {shaka.net.NetworkingEngine.PendingRequest} operation
* Operation with the number of bytes to be downloaded.
* @property {shaka.media.SegmentPrefetch} segmentPrefetch
* segmentPrefetch.
* @property {?shaka.media.SegmentPrefetch} segmentPrefetch
* A prefetch object for managing prefetching. Null if unneeded
* (if prefetching is disabled, etc).
*/
shaka.media.StreamingEngine.MediaState_;

Expand Down
6 changes: 3 additions & 3 deletions test/test/util/fake_segment_prefetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ shaka.test.FakeSegmentPrefetch = class {
/** @private {shaka.extern.Stream} */
this.streamObj_ = stream;

/** @private {
* !Object.<string, shaka.test.FakeMediaSourceEngine.SegmentData>
* } */
/**
* @private {!Object.<string, shaka.test.FakeMediaSourceEngine.SegmentData>}
tyrelltle marked this conversation as resolved.
Show resolved Hide resolved
*/
this.segmentData_ = segmentData;
}

Expand Down