Skip to content

Commit

Permalink
fix(Offline): Allow storage of MSS streams (#7799)
Browse files Browse the repository at this point in the history
Co-authored-by: theodab <[email protected]>
  • Loading branch information
avelad and theodab authored Dec 24, 2024
1 parent e40341c commit bc41643
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 3 deletions.
3 changes: 2 additions & 1 deletion demo/common/assets.js
Original file line number Diff line number Diff line change
Expand Up @@ -1406,7 +1406,8 @@ shakaAssets.testAssets = [
/* source= */ shakaAssets.Source.MICROSOFT)
.addFeature(shakaAssets.Feature.MSS)
.addFeature(shakaAssets.Feature.HIGH_DEFINITION)
.addFeature(shakaAssets.Feature.MP4),
.addFeature(shakaAssets.Feature.MP4)
.addFeature(shakaAssets.Feature.OFFLINE),
new ShakaDemoAssetInfo(
/* name= */ 'Super Speedway Trailer (MSS - PlayReady)',
/* iconUri= */ 'https://reference.dashif.org/dash.js/latest/samples/lib/img/mss-1.jpg',
Expand Down
4 changes: 4 additions & 0 deletions externs/shaka/offline.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ shaka.extern.ManifestDB;
* spatialAudio: boolean,
* closedCaptions: Map.<string, string>,
* tilesLayout: (string|undefined),
* mssPrivateData: (shaka.extern.MssPrivateData|undefined),
* external: boolean,
* fastSwitching: boolean,
* isAudioMuxedInVideo: boolean
Expand Down Expand Up @@ -214,6 +215,9 @@ shaka.extern.ManifestDB;
* The value is a grid-item-dimension consisting of two positive decimal
* integers in the format: column-x-row ('4x3'). It describes the arrangement
* of Images in a Grid. The minimum valid LAYOUT is '1x1'.
* @property {(shaka.extern.MssPrivateData|undefined)} mssPrivateData
* <i>Microsoft Smooth Streaming only.</i> <br>
* Private MSS data that is necessary to be able to do transmuxing.
* @property {boolean} external
* Indicate if the stream was added externally.
* Eg: external text tracks.
Expand Down
5 changes: 5 additions & 0 deletions lib/offline/download_info.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
goog.provide('shaka.offline.DownloadInfo');

goog.require('shaka.util.Networking');
goog.require('shaka.util.Uint8ArrayUtils');
goog.requireType('shaka.media.InitSegmentReference');
goog.requireType('shaka.media.SegmentReference');

Expand Down Expand Up @@ -43,6 +44,10 @@ shaka.offline.DownloadInfo = class {
* @return {string}
*/
static idForSegmentRef(ref) {
const segmentData = ref.getSegmentData();
if (segmentData) {
return shaka.util.Uint8ArrayUtils.toBase64(segmentData);
}
// Escape the URIs using encodeURI, to make sure that a weirdly formed URI
// cannot cause two unrelated refs to be considered equivalent.
const removeSprites = (uri) => {
Expand Down
54 changes: 54 additions & 0 deletions lib/offline/download_manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,60 @@ shaka.offline.DownloadManager = class {
return newPromise;
}

/**
* Add already-downloaded data to a group.
*
* @param {number} groupId
* The group to add this segment to. If the group does not exist, a new
* group will be created.
* @param {!BufferSource} queueData
* @param {number} estimateId
* @param {boolean} isInitSegment
* @param {function(BufferSource):!Promise} onDownloaded
* The callback for when this request has been downloaded. Downloading for
* |group| will pause until the promise returned by |onDownloaded| resolves.
* @return {!Promise} Resolved when this request is complete.
*/
queueData(groupId, queueData, estimateId, isInitSegment, onDownloaded) {
this.destroyer_.ensureNotDestroyed();

const group = this.groups_.get(groupId) || Promise.resolve();

// Add another download to the group.
const newPromise = group.then(() => {
// Make sure we stop downloading if we have been destroyed.
if (this.destroyer_.destroyed()) {
throw new shaka.util.Error(
shaka.util.Error.Severity.CRITICAL,
shaka.util.Error.Category.STORAGE,
shaka.util.Error.Code.OPERATION_ABORTED);
}

// Update initData
if (isInitSegment) {
const segmentBytes = shaka.util.BufferUtils.toUint8(queueData);
const pssh = new shaka.util.Pssh(segmentBytes);
for (const key in pssh.data) {
const index = Number(key);
const data = pssh.data[index];
const systemId = pssh.systemIds[index];
this.onInitData_(data, systemId);
}
}

// Update all our internal stats.
this.estimator_.close(estimateId, queueData.byteLength);
this.onProgress_(
this.estimator_.getEstimatedProgress(),
this.estimator_.getTotalDownloaded());

return onDownloaded(queueData);
});

this.groups_.set(groupId, newPromise);
return newPromise;
}

/**
* Add additional async work to the group work queue.
*
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 @@ -215,6 +215,7 @@ shaka.offline.ManifestConverter = class {
spatialAudio: streamDB.spatialAudio,
closedCaptions: streamDB.closedCaptions,
tilesLayout: streamDB.tilesLayout,
mssPrivateData: streamDB.mssPrivateData,
accessibilityPurpose: null,
external: streamDB.external,
fastSwitching: streamDB.fastSwitching,
Expand Down
13 changes: 11 additions & 2 deletions lib/offline/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -511,8 +511,16 @@ shaka.offline.Storage = class {
pendingDataSize += data.byteLength;
};

downloader.queue(download.groupId,
request, estimateId, isInitSegment, onDownloaded);
const ref = /** @type {!shaka.media.SegmentReference} */ (
download.ref);
const segmentData = ref.getSegmentData();
if (segmentData) {
downloader.queueData(download.groupId,
segmentData, estimateId, isInitSegment, onDownloaded);
} else {
downloader.queue(download.groupId,
request, estimateId, isInitSegment, onDownloaded);
}
}
await downloader.waitToFinish();

Expand Down Expand Up @@ -1606,6 +1614,7 @@ shaka.offline.Storage = class {
spatialAudio: stream.spatialAudio,
closedCaptions: stream.closedCaptions,
tilesLayout: stream.tilesLayout,
mssPrivateData: stream.mssPrivateData,
external: stream.external,
fastSwitching: stream.fastSwitching,
isAudioMuxedInVideo: stream.isAudioMuxedInVideo,
Expand Down
2 changes: 2 additions & 0 deletions test/offline/manifest_convert_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,7 @@ describe('ManifestConverter', () => {
spatialAudio: false,
closedCaptions: null,
tilesLayout: undefined,
mssPrivateData: undefined,
accessibilityPurpose: null,
external: false,
fastSwitching: false,
Expand Down Expand Up @@ -587,6 +588,7 @@ describe('ManifestConverter', () => {
spatialAudio: streamDb.spatialAudio,
closedCaptions: streamDb.closedCaptions,
tilesLayout: streamDb.tilesLayout,
mssPrivateData: streamDb.mssPrivateData,
accessibilityPurpose: null,
external: streamDb.external,
fastSwitching: streamDb.fastSwitching,
Expand Down

0 comments on commit bc41643

Please sign in to comment.