mirror of
https://github.com/shaka-project/shaka-player.git
synced 2026-06-14 15:56:38 +03:00
Change Download Manager To Take Requests
Changed download manager to take |shakaExtern.Request| as input instead of |shaka.media.SegmentReference| and |shaka.media.InitSegmentReference| as it really does not need to know about those types. Issue #1248 Change-Id: I797c437f4339cf670b5eddad14952b0526b72ea5
This commit is contained in:
@@ -25,26 +25,39 @@ goog.require('shaka.util.IDestroyable');
|
||||
goog.require('shaka.util.MapUtils');
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* request: shakaExtern.Request,
|
||||
* estimatedSize: number,
|
||||
* onStore: function(number)
|
||||
* }}
|
||||
*
|
||||
* @property {shakaExtern.Request}
|
||||
* The network request that will give us the bytes we want to download.
|
||||
* @property {number} estimatedSize
|
||||
* The size of the segment as estimated by the bandwidth and segment duration.
|
||||
* @property {function(number)} onStore
|
||||
* A callback for when a segment has been added to the storage.
|
||||
*/
|
||||
shaka.offline.DownloadRequest;
|
||||
|
||||
|
||||
/**
|
||||
* This manages downloading segments and notifying the app of progress.
|
||||
*
|
||||
* @param {shaka.offline.IStorageEngine} storageEngine
|
||||
* @param {!shaka.net.NetworkingEngine} netEngine
|
||||
* @param {shakaExtern.RetryParameters} retryParams
|
||||
*
|
||||
* @struct
|
||||
* @constructor
|
||||
* @implements {shaka.util.IDestroyable}
|
||||
*/
|
||||
shaka.offline.DownloadManager = function(
|
||||
storageEngine, netEngine, retryParams) {
|
||||
shaka.offline.DownloadManager = function(storageEngine, netEngine) {
|
||||
/**
|
||||
* We sill store download requests in groups. The groups will be downloaded in
|
||||
* parallel but the segments in each group will be done serially.
|
||||
*
|
||||
* @private {!Object.<
|
||||
* number, !Array.<shaka.offline.DownloadManager.Segment>>}
|
||||
* @private {!Object.<number, !Array.<shaka.offline.DownloadRequest>>}
|
||||
*/
|
||||
this.groups_ = {};
|
||||
|
||||
@@ -61,9 +74,6 @@ shaka.offline.DownloadManager = function(
|
||||
/** @private {shaka.net.NetworkingEngine} */
|
||||
this.netEngine_ = netEngine;
|
||||
|
||||
/** @private {?shakaExtern.RetryParameters} */
|
||||
this.retryParams_ = retryParams;
|
||||
|
||||
/** @private {?shakaExtern.ManifestDB} */
|
||||
this.manifest_ = null;
|
||||
|
||||
@@ -92,29 +102,6 @@ shaka.offline.DownloadManager.prototype.followProgress = function(callback) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* uris: !Array.<string>,
|
||||
* startByte: number,
|
||||
* endByte: ?number,
|
||||
* bandwidthSize: number,
|
||||
* onStore: function(number)
|
||||
* }}
|
||||
*
|
||||
* @property {!Array.<string>} uris
|
||||
* The URIs to download for the segment.
|
||||
* @property {number} startByte
|
||||
* The byte index the segment starts at.
|
||||
* @property {?number} endByte
|
||||
* The byte index the segment ends at, if present.
|
||||
* @property {number} bandwidthSize
|
||||
* The size of the segment as estimated by the bandwidth and segment duration.
|
||||
* @property {function(number)} onStore
|
||||
* A callback for when a segment has been added to the storage.
|
||||
*/
|
||||
shaka.offline.DownloadManager.Segment;
|
||||
|
||||
|
||||
/** @override */
|
||||
shaka.offline.DownloadManager.prototype.destroy = function() {
|
||||
let storage = this.storageEngine_;
|
||||
@@ -135,7 +122,6 @@ shaka.offline.DownloadManager.prototype.destroy = function() {
|
||||
this.storedSegmentIds_ = [];
|
||||
this.storageEngine_ = null;
|
||||
this.netEngine_ = null;
|
||||
this.retryParams_ = null;
|
||||
this.manifest_ = null;
|
||||
this.promise_ = Promise.resolve();
|
||||
|
||||
@@ -144,24 +130,22 @@ shaka.offline.DownloadManager.prototype.destroy = function() {
|
||||
|
||||
|
||||
/**
|
||||
* Adds a segment to the list to be downloaded.
|
||||
* Add a request to be downloaded as part of a group.
|
||||
*
|
||||
* @param {number} group The group to add this segment to. If the group does
|
||||
* not exists, a new group will be created.
|
||||
* @param {!shaka.media.SegmentReference|!shaka.media.InitSegmentReference} ref
|
||||
* @param {number} bandwidthSize
|
||||
* @param {shakaExtern.Request} request
|
||||
* @param {number} estimatedSize
|
||||
* @param {function(number)} onStore
|
||||
* A callback for when the segment has been saved to storage. The parameter
|
||||
* will be the id the segment was saved under.
|
||||
*/
|
||||
shaka.offline.DownloadManager.prototype.addSegment = function(
|
||||
group, ref, bandwidthSize, onStore) {
|
||||
shaka.offline.DownloadManager.prototype.queue = function(
|
||||
group, request, estimatedSize, onStore) {
|
||||
this.groups_[group] = this.groups_[group] || [];
|
||||
this.groups_[group].push({
|
||||
uris: ref.getUris(),
|
||||
startByte: ref.startByte,
|
||||
endByte: ref.endByte,
|
||||
bandwidthSize: bandwidthSize,
|
||||
request: request,
|
||||
estimatedSize: estimatedSize,
|
||||
onStore: onStore
|
||||
});
|
||||
};
|
||||
@@ -185,7 +169,7 @@ shaka.offline.DownloadManager.prototype.downloadAndStore = function(manifest) {
|
||||
this.groups_ = {}; // Clear the map to create a clean slate.
|
||||
|
||||
groups.forEach((segments) => {
|
||||
segments.forEach((segment) => this.markAsPending_(segment));
|
||||
segments.forEach((segment) => this.markAsPending_(segment.estimatedSize));
|
||||
});
|
||||
|
||||
/** @type {!Promise.<number>} */
|
||||
@@ -210,7 +194,7 @@ shaka.offline.DownloadManager.prototype.downloadAndStore = function(manifest) {
|
||||
|
||||
|
||||
/**
|
||||
* @param {!Array.<shaka.offline.DownloadManager.Segment>} group
|
||||
* @param {!Array.<shaka.offline.DownloadRequest>} group
|
||||
* @return {!Promise}
|
||||
* @private
|
||||
*/
|
||||
@@ -229,7 +213,7 @@ shaka.offline.DownloadManager.prototype.downloadGroup_ = function(group) {
|
||||
|
||||
|
||||
/**
|
||||
* @param {shaka.offline.DownloadManager.Segment} segment
|
||||
* @param {shaka.offline.DownloadRequest} segment
|
||||
* @return {!Promise}
|
||||
* @private
|
||||
*/
|
||||
@@ -238,14 +222,11 @@ shaka.offline.DownloadManager.prototype.downloadSegment_ = function(segment) {
|
||||
this.checkDestroyed_();
|
||||
|
||||
let type = shaka.net.NetworkingEngine.RequestType.SEGMENT;
|
||||
let request = this.createRequest_(segment);
|
||||
return this.netEngine_.request(type, request).promise;
|
||||
return this.netEngine_.request(type, segment.request).promise;
|
||||
}).then((response) => {
|
||||
this.checkDestroyed_();
|
||||
|
||||
// Update progress for the download (won't include the "store" part).
|
||||
this.manifest_.size += response.data.byteLength;
|
||||
this.markAsDone_(segment);
|
||||
this.markAsDone_(segment.estimatedSize, response.data.byteLength);
|
||||
this.updateProgress_();
|
||||
|
||||
return this.storageEngine_.addSegment({
|
||||
@@ -260,29 +241,6 @@ shaka.offline.DownloadManager.prototype.downloadSegment_ = function(segment) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {!shaka.offline.DownloadManager.Segment} segment
|
||||
* @return {shakaExtern.Request}
|
||||
* @private
|
||||
*/
|
||||
shaka.offline.DownloadManager.prototype.createRequest_ = function(segment) {
|
||||
goog.asserts.assert(
|
||||
this.retryParams_,
|
||||
'DownloadManager must not be destroyed');
|
||||
|
||||
let request = shaka.net.NetworkingEngine.makeRequest(
|
||||
segment.uris,
|
||||
this.retryParams_);
|
||||
|
||||
if (segment.startByte != 0 || segment.endByte != null) {
|
||||
let end = segment.endByte == null ? '' : segment.endByte;
|
||||
request.headers['Range'] = 'bytes=' + segment.startByte + '-' + end;
|
||||
}
|
||||
|
||||
return request;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Check if the download manager has been destroyed. If so, throw an error to
|
||||
* kill the promise chain.
|
||||
@@ -299,30 +257,23 @@ shaka.offline.DownloadManager.prototype.checkDestroyed_ = function() {
|
||||
|
||||
|
||||
/**
|
||||
* @param {!shaka.offline.DownloadManager.Segment} segment
|
||||
* @param {number} estimate
|
||||
* @private
|
||||
*/
|
||||
shaka.offline.DownloadManager.prototype.markAsPending_ = function(segment) {
|
||||
/** @type {number} */
|
||||
let estimatedSize = segment.endByte == null ?
|
||||
segment.bandwidthSize :
|
||||
(segment.endByte - segment.startByte + 1);
|
||||
|
||||
this.downloadExpected_ += estimatedSize;
|
||||
shaka.offline.DownloadManager.prototype.markAsPending_ = function(estimate) {
|
||||
this.downloadExpected_ += estimate;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {!shaka.offline.DownloadManager.Segment} segment
|
||||
* @param {number} estimate The estimated number of bytes we need to download.
|
||||
* @param {number} actual The actual number of bytes we downloaded.
|
||||
* @private
|
||||
*/
|
||||
shaka.offline.DownloadManager.prototype.markAsDone_ = function(segment) {
|
||||
/** @type {number} */
|
||||
let estimatedSize = segment.endByte == null ?
|
||||
segment.bandwidthSize :
|
||||
(segment.endByte - segment.startByte + 1);
|
||||
|
||||
this.downloadActual_ += estimatedSize;
|
||||
shaka.offline.DownloadManager.prototype.markAsDone_ = function(
|
||||
estimate, actual) {
|
||||
this.downloadActual_ += estimate;
|
||||
this.manifest_.size += actual;
|
||||
};
|
||||
|
||||
|
||||
|
||||
+34
-11
@@ -22,6 +22,7 @@ goog.require('shaka.Player');
|
||||
goog.require('shaka.log');
|
||||
goog.require('shaka.media.DrmEngine');
|
||||
goog.require('shaka.media.ManifestParser');
|
||||
goog.require('shaka.net.NetworkingEngine');
|
||||
goog.require('shaka.offline.DownloadManager');
|
||||
goog.require('shaka.offline.IStorageEngine');
|
||||
goog.require('shaka.offline.ManifestConverter');
|
||||
@@ -642,8 +643,6 @@ shaka.offline.Storage.prototype.initIfNeeded_ = function() {
|
||||
goog.asserts.assert(this.player_, 'Player must be initialized');
|
||||
/** @type {shaka.net.NetworkingEngine} */
|
||||
let netEngine = this.getNetEngine_();
|
||||
/** @type {shakaExtern.RetryParameters} */
|
||||
let retryParams = this.player_.getConfiguration().streaming.retryParameters;
|
||||
|
||||
return shaka.offline.StorageEngineFactory.createStorageEngine()
|
||||
.then(function(storageEngine) {
|
||||
@@ -655,8 +654,7 @@ shaka.offline.Storage.prototype.initIfNeeded_ = function() {
|
||||
|
||||
this.downloadManager_ = new shaka.offline.DownloadManager(
|
||||
storageEngine,
|
||||
netEngine,
|
||||
retryParams);
|
||||
netEngine);
|
||||
this.downloadManager_.followProgress(function(progress, size) {
|
||||
/** @type {?shakaExtern.StoredContent} */
|
||||
let content = this.pendingContent_;
|
||||
@@ -956,13 +954,17 @@ shaka.offline.Storage.prototype.createStream_ = function(
|
||||
let endTime = segment.endTime;
|
||||
/** @type {number} */
|
||||
let duration = endTime - startTime;
|
||||
/** @type {number} */
|
||||
let bandwidthSize = duration * estimatedStreamBandwidth / 8;
|
||||
|
||||
this.downloadManager_.addSegment(
|
||||
/** @type {number} */
|
||||
let estimatedSize = segment.endByte ?
|
||||
(segment.endByte - segment.startByte) :
|
||||
(duration * estimatedStreamBandwidth / 8);
|
||||
|
||||
let request = this.createRequest_(segment);
|
||||
this.downloadManager_.queue(
|
||||
downloadGroup,
|
||||
segment,
|
||||
bandwidthSize,
|
||||
request,
|
||||
estimatedSize,
|
||||
function(id) {
|
||||
/** @type {shakaExtern.SegmentDB} */
|
||||
let segmentDb = {
|
||||
@@ -978,10 +980,11 @@ shaka.offline.Storage.prototype.createStream_ = function(
|
||||
let initSegment = stream.initSegmentReference;
|
||||
if (initSegment) {
|
||||
const noBandwidth = 0;
|
||||
let request = this.createRequest_(initSegment);
|
||||
|
||||
this.downloadManager_.addSegment(
|
||||
this.downloadManager_.queue(
|
||||
downloadGroup,
|
||||
initSegment,
|
||||
request,
|
||||
noBandwidth,
|
||||
function(id) {
|
||||
streamDb.initSegmentKey = id;
|
||||
@@ -1036,6 +1039,26 @@ shaka.offline.Storage.prototype.getNetEngine_ = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {!shaka.media.SegmentReference|
|
||||
* !shaka.media.InitSegmentReference} segment
|
||||
* @return {shakaExtern.Request}
|
||||
* @private
|
||||
*/
|
||||
shaka.offline.Storage.prototype.createRequest_ = function(segment) {
|
||||
let retryParams = this.player_.getConfiguration().streaming.retryParameters;
|
||||
let request = shaka.net.NetworkingEngine.makeRequest(
|
||||
segment.getUris(), retryParams);
|
||||
|
||||
if (segment.startByte != 0 || segment.endByte != null) {
|
||||
let end = segment.endByte == null ? '' : segment.endByte;
|
||||
request.headers['Range'] = 'bytes=' + segment.startByte + '-' + end;
|
||||
}
|
||||
|
||||
return request;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {shakaExtern.ManifestDB} manifest
|
||||
* @return {!Array.<number>}
|
||||
|
||||
@@ -483,15 +483,15 @@ describe('Storage', function() {
|
||||
|
||||
switch (progress.calls.count()) {
|
||||
case 1:
|
||||
expect(percent).toBeCloseTo(54 / 101);
|
||||
expect(percent).toBeCloseTo(0.53);
|
||||
expect(storedContent.size).toBe(54);
|
||||
break;
|
||||
case 2:
|
||||
expect(percent).toBeCloseTo(64 / 101);
|
||||
expect(percent).toBeCloseTo(0.64);
|
||||
expect(storedContent.size).toBe(67);
|
||||
break;
|
||||
case 3:
|
||||
expect(percent).toBeCloseTo(84 / 101);
|
||||
expect(percent).toBeCloseTo(0.84);
|
||||
expect(storedContent.size).toBe(133);
|
||||
break;
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user