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:
Aaron Vaage
2018-04-06 17:15:21 -07:00
parent 612d248d4c
commit 4a4050d223
3 changed files with 76 additions and 102 deletions
+39 -88
View File
@@ -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
View File
@@ -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>}
+3 -3
View File
@@ -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: