shaka-player 3.3.4 → 3.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/build-and-test.yaml +0 -1
- package/.github/workflows/release-please.yaml +1 -1
- package/.github/workflows/selenium-lab-tests.yaml +0 -1
- package/CHANGELOG.md +18 -0
- package/build/README.md +2 -2
- package/build/checkversion.py +1 -1
- package/build/generateTsDefs.py +0 -2
- package/build/test.py +7 -1
- package/build/types/core +0 -1
- package/dist/controls.css +1 -1
- package/dist/deps.js +1 -2
- package/dist/locales.js +30 -30
- package/dist/shaka-player.compiled.d.ts +238 -239
- package/dist/shaka-player.compiled.debug.d.ts +238 -239
- package/dist/shaka-player.compiled.debug.externs.js +1 -0
- package/dist/shaka-player.compiled.debug.js +149 -147
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +1 -0
- package/dist/shaka-player.compiled.js +844 -842
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +282 -283
- package/dist/shaka-player.ui.debug.d.ts +282 -283
- package/dist/shaka-player.ui.debug.externs.js +1 -0
- package/dist/shaka-player.ui.debug.js +222 -220
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +1 -0
- package/dist/shaka-player.ui.js +956 -954
- package/dist/shaka-player.ui.map +4 -4
- package/karma.conf.js +4 -0
- package/lib/dash/dash_parser.js +2 -3
- package/lib/hls/hls_parser.js +23 -11
- package/lib/media/media_source_engine.js +7 -1
- package/lib/offline/indexeddb/storage_mechanism.js +4 -2
- package/lib/offline/storage.js +92 -91
- package/lib/player.js +165 -107
- package/lib/util/config_utils.js +25 -0
- package/lib/util/error.js +7 -0
- package/lib/util/manifest_parser_utils.js +1 -1
- package/lib/util/mime_utils.js +48 -1
- package/lib/util/periods.js +5 -4
- package/lib/util/player_configuration.js +9 -14
- package/lib/util/stream_utils.js +4 -2
- package/package.json +1 -1
- package/test/cast/cast_utils_unit.js +1 -0
- package/test/dash/dash_parser_manifest_unit.js +0 -24
- package/test/hls/hls_live_unit.js +26 -0
- package/test/hls/manifest_text_parser_unit.js +19 -0
- package/test/media/media_source_engine_integration.js +1 -0
- package/test/media/media_source_engine_unit.js +4 -4
- package/test/media/streaming_engine_integration.js +2 -0
- package/test/offline/indexeddb_storage_unit.js +1 -1
- package/test/offline/storage_compatibility_unit.js +1 -1
- package/test/player_external.js +7 -1
- package/test/player_integration.js +6 -10
- package/test/player_src_equals_integration.js +81 -83
- package/test/player_unit.js +98 -1
- package/test/test/boot.js +9 -0
- package/test/test/externs/filters.js +4 -0
- package/test/test/util/simple_fakes.js +31 -2
- package/test/util/mime_utils_unit.js +54 -0
- package/test/util/periods_unit.js +79 -0
- package/docs/tutorials/gsoc-ideas-list.md +0 -3
- package/lib/util/mutex.js +0 -52
package/karma.conf.js
CHANGED
|
@@ -363,6 +363,8 @@ module.exports = (config) => {
|
|
|
363
363
|
// If testing custom assets, we don't serve other unit or integration tests.
|
|
364
364
|
// External asset tests are the basis for custom asset testing, so this file
|
|
365
365
|
// is automatically included.
|
|
366
|
+
clientArgs.testFiles.push('demo/common/asset.js');
|
|
367
|
+
clientArgs.testFiles.push('demo/common/assets.js');
|
|
366
368
|
clientArgs.testFiles.push('test/player_external.js');
|
|
367
369
|
} else {
|
|
368
370
|
// In a normal test run, we serve unit tests.
|
|
@@ -374,6 +376,8 @@ module.exports = (config) => {
|
|
|
374
376
|
}
|
|
375
377
|
if (settings.external) {
|
|
376
378
|
// If --external is present, we serve external asset tests.
|
|
379
|
+
clientArgs.testFiles.push('demo/common/asset.js');
|
|
380
|
+
clientArgs.testFiles.push('demo/common/assets.js');
|
|
377
381
|
clientArgs.testFiles.push('test/**/*_external.js');
|
|
378
382
|
}
|
|
379
383
|
}
|
package/lib/dash/dash_parser.js
CHANGED
|
@@ -764,8 +764,8 @@ shaka.dash.DashParser = class {
|
|
|
764
764
|
// currently support that. Just choose one.
|
|
765
765
|
// TODO: https://github.com/shaka-project/shaka-player/issues/1528
|
|
766
766
|
stream.trickModeVideo = trickModeSet.streams.find((trickStream) =>
|
|
767
|
-
shaka.util.MimeUtils.
|
|
768
|
-
shaka.util.MimeUtils.
|
|
767
|
+
shaka.util.MimeUtils.getNormalizedCodec(stream.codecs) ==
|
|
768
|
+
shaka.util.MimeUtils.getNormalizedCodec(trickStream.codecs));
|
|
769
769
|
}
|
|
770
770
|
}
|
|
771
771
|
}
|
|
@@ -1228,7 +1228,6 @@ shaka.dash.DashParser = class {
|
|
|
1228
1228
|
});
|
|
1229
1229
|
let spatialAudio = false;
|
|
1230
1230
|
if (hasJoc) {
|
|
1231
|
-
context.representation.mimeType = 'audio/eac3-joc';
|
|
1232
1231
|
spatialAudio = true;
|
|
1233
1232
|
}
|
|
1234
1233
|
|
package/lib/hls/hls_parser.js
CHANGED
|
@@ -1739,8 +1739,8 @@ shaka.hls.HlsParser = class {
|
|
|
1739
1739
|
* @param {number} timestampOffset
|
|
1740
1740
|
* @param {!Map.<string, string>} variables
|
|
1741
1741
|
* @param {string} absoluteMediaPlaylistUri
|
|
1742
|
-
* @return {!shaka.media.SegmentReference}
|
|
1743
1742
|
* @param {string} type
|
|
1743
|
+
* @return {shaka.media.SegmentReference}
|
|
1744
1744
|
* @private
|
|
1745
1745
|
*/
|
|
1746
1746
|
createSegmentReference_(
|
|
@@ -1756,9 +1756,23 @@ shaka.hls.HlsParser = class {
|
|
|
1756
1756
|
let startByte = 0;
|
|
1757
1757
|
let endByte = null;
|
|
1758
1758
|
|
|
1759
|
+
if (!extinfTag) {
|
|
1760
|
+
if (hlsSegment.partialSegments.length == 0) {
|
|
1761
|
+
// EXTINF tag must be available if the segment has no partial segments.
|
|
1762
|
+
throw new shaka.util.Error(
|
|
1763
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
1764
|
+
shaka.util.Error.Category.MANIFEST,
|
|
1765
|
+
shaka.util.Error.Code.HLS_REQUIRED_TAG_MISSING, 'EXTINF');
|
|
1766
|
+
} else if (!this.lowLatencyMode_) {
|
|
1767
|
+
// Without EXTINF and without low-latency mode, partial segments get
|
|
1768
|
+
// ignored.
|
|
1769
|
+
return null;
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1759
1773
|
// Create SegmentReferences for the partial segments.
|
|
1760
1774
|
const partialSegmentRefs = [];
|
|
1761
|
-
if (this.lowLatencyMode_
|
|
1775
|
+
if (this.lowLatencyMode_) {
|
|
1762
1776
|
for (let i = 0; i < hlsSegment.partialSegments.length; i++) {
|
|
1763
1777
|
const item = hlsSegment.partialSegments[i];
|
|
1764
1778
|
const pPreviousReference = i == 0 ?
|
|
@@ -1799,14 +1813,6 @@ shaka.hls.HlsParser = class {
|
|
|
1799
1813
|
/* appendWindowEnd= */ Infinity);
|
|
1800
1814
|
partialSegmentRefs.push(partial);
|
|
1801
1815
|
} // for-loop of hlsSegment.partialSegments
|
|
1802
|
-
} else {
|
|
1803
|
-
// EXTINF tag must be available if the segment has no partial segments.
|
|
1804
|
-
if (!extinfTag) {
|
|
1805
|
-
throw new shaka.util.Error(
|
|
1806
|
-
shaka.util.Error.Severity.CRITICAL,
|
|
1807
|
-
shaka.util.Error.Category.MANIFEST,
|
|
1808
|
-
shaka.util.Error.Code.HLS_REQUIRED_TAG_MISSING, 'EXTINF');
|
|
1809
|
-
}
|
|
1810
1816
|
}
|
|
1811
1817
|
|
|
1812
1818
|
// If the segment has EXTINF tag, set the segment's end time, start byte
|
|
@@ -1825,6 +1831,7 @@ shaka.hls.HlsParser = class {
|
|
|
1825
1831
|
} else {
|
|
1826
1832
|
endTime = partialSegmentRefs[partialSegmentRefs.length - 1].endTime;
|
|
1827
1833
|
}
|
|
1834
|
+
|
|
1828
1835
|
// If the segment has EXT-X-BYTERANGE tag, set the start byte and end byte
|
|
1829
1836
|
// base on the byterange information. If segment has no EXT-X-BYTERANGE tag
|
|
1830
1837
|
// and has partial segments, set the start byte and end byte base on the
|
|
@@ -2054,7 +2061,9 @@ shaka.hls.HlsParser = class {
|
|
|
2054
2061
|
playlist.absoluteUri,
|
|
2055
2062
|
type);
|
|
2056
2063
|
|
|
2057
|
-
|
|
2064
|
+
if (reference) {
|
|
2065
|
+
references.push(reference);
|
|
2066
|
+
}
|
|
2058
2067
|
} else if (!this.lowLatencyMode_) {
|
|
2059
2068
|
// If a segment has no extinfTag, it must contain partial segments.
|
|
2060
2069
|
shaka.log.alwaysWarn('Low-latency HLS live stream detected, but ' +
|
|
@@ -2233,6 +2242,9 @@ shaka.hls.HlsParser = class {
|
|
|
2233
2242
|
variables,
|
|
2234
2243
|
/* absoluteMediaPlaylistUri= */ '',
|
|
2235
2244
|
type);
|
|
2245
|
+
goog.asserts.assert(
|
|
2246
|
+
segmentRef != null, 'Segment reference should not be null!');
|
|
2247
|
+
|
|
2236
2248
|
// If we are updating the manifest, we can usually skip fetching the segment
|
|
2237
2249
|
// by examining the references we already have. This won't be possible if
|
|
2238
2250
|
// there was some kind of lag or delay updating the manifest on the server,
|
|
@@ -63,6 +63,11 @@ shaka.media.MediaSourceEngine = class {
|
|
|
63
63
|
string>} */
|
|
64
64
|
this.sourceBufferTypes_ = {};
|
|
65
65
|
|
|
66
|
+
|
|
67
|
+
/** @private {!Object.<shaka.util.ManifestParserUtils.ContentType,
|
|
68
|
+
boolean>} */
|
|
69
|
+
this.expectedEncryption_ = {};
|
|
70
|
+
|
|
66
71
|
/** @private {shaka.text.TextEngine} */
|
|
67
72
|
this.textEngine_ = null;
|
|
68
73
|
|
|
@@ -345,6 +350,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
345
350
|
this.sourceBuffers_[contentType] = sourceBuffer;
|
|
346
351
|
this.sourceBufferTypes_[contentType] = mimeType;
|
|
347
352
|
this.queues_[contentType] = [];
|
|
353
|
+
this.expectedEncryption_[contentType] = !!stream.drmInfos.length;
|
|
348
354
|
}
|
|
349
355
|
}
|
|
350
356
|
}
|
|
@@ -1091,7 +1097,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1091
1097
|
*/
|
|
1092
1098
|
workAroundBrokenPlatforms_(segment, startTime, contentType) {
|
|
1093
1099
|
const isInitSegment = startTime == null;
|
|
1094
|
-
const encryptionExpected = this.
|
|
1100
|
+
const encryptionExpected = this.expectedEncryption_[contentType];
|
|
1095
1101
|
|
|
1096
1102
|
// If:
|
|
1097
1103
|
// 1. this is an init segment,
|
|
@@ -368,8 +368,10 @@ shaka.offline.indexeddb.StorageMechanism.SESSION_ID_STORE = 'session-ids';
|
|
|
368
368
|
shaka.offline.StorageMuxer.register(
|
|
369
369
|
'idb',
|
|
370
370
|
() => {
|
|
371
|
-
// Offline storage is not supported on the Chromecast
|
|
372
|
-
|
|
371
|
+
// Offline storage is not supported on the Chromecast or Xbox One
|
|
372
|
+
// platforms.
|
|
373
|
+
if (shaka.util.Platform.isChromecast() ||
|
|
374
|
+
shaka.util.Platform.isXboxOne()) {
|
|
373
375
|
return null;
|
|
374
376
|
}
|
|
375
377
|
// Offline storage requires the IndexedDB API.
|
package/lib/offline/storage.js
CHANGED
|
@@ -29,7 +29,6 @@ goog.require('shaka.util.Functional');
|
|
|
29
29
|
goog.require('shaka.util.IDestroyable');
|
|
30
30
|
goog.require('shaka.util.Iterables');
|
|
31
31
|
goog.require('shaka.util.MimeUtils');
|
|
32
|
-
goog.require('shaka.util.Mutex');
|
|
33
32
|
goog.require('shaka.util.Platform');
|
|
34
33
|
goog.require('shaka.util.PlayerConfiguration');
|
|
35
34
|
goog.require('shaka.util.StreamUtils');
|
|
@@ -210,7 +209,7 @@ shaka.offline.Storage = class {
|
|
|
210
209
|
}
|
|
211
210
|
|
|
212
211
|
goog.asserts.assert(
|
|
213
|
-
this.config_, 'Cannot reconfigure
|
|
212
|
+
this.config_, 'Cannot reconfigure storage after calling destroy.');
|
|
214
213
|
return shaka.util.PlayerConfiguration.mergeConfigObjects(
|
|
215
214
|
/* destination= */ this.config_, /* updates= */ config );
|
|
216
215
|
}
|
|
@@ -479,36 +478,34 @@ shaka.offline.Storage = class {
|
|
|
479
478
|
async downloadSegments_(
|
|
480
479
|
toDownload, manifestId, manifestDB, downloader, config, storage,
|
|
481
480
|
manifest, drmEngine) {
|
|
481
|
+
let pendingManifestUpdates = {};
|
|
482
|
+
let pendingDataSize = 0;
|
|
483
|
+
|
|
482
484
|
/**
|
|
483
485
|
* @param {!Array.<!shaka.offline.DownloadInfo>} toDownload
|
|
484
486
|
* @param {boolean} updateDRM
|
|
485
487
|
*/
|
|
486
488
|
const download = async (toDownload, updateDRM) => {
|
|
487
|
-
const throwIfAbortedFn = () => {
|
|
488
|
-
this.ensureNotDestroyed_();
|
|
489
|
-
};
|
|
490
489
|
for (const download of toDownload) {
|
|
491
|
-
/** @param {?BufferSource} data */
|
|
492
|
-
let data;
|
|
493
490
|
const request = download.makeSegmentRequest(config);
|
|
494
491
|
const estimateId = download.estimateId;
|
|
495
492
|
const isInitSegment = download.isInitSegment;
|
|
496
|
-
const onDownloaded = (d) => {
|
|
497
|
-
data = d;
|
|
498
|
-
return Promise.resolve();
|
|
499
|
-
};
|
|
500
|
-
downloader.queue(download.groupId,
|
|
501
|
-
request, estimateId, isInitSegment, onDownloaded);
|
|
502
|
-
downloader.queueWork(download.groupId, async () => {
|
|
503
|
-
goog.asserts.assert(data, 'We should have loaded data by now');
|
|
504
|
-
goog.asserts.assert(data instanceof ArrayBuffer,
|
|
505
|
-
'The data should be an ArrayBuffer');
|
|
506
493
|
|
|
494
|
+
const onDownloaded = async (data) => {
|
|
495
|
+
// Store the data.
|
|
496
|
+
const dataKeys = await storage.addSegments([{data}]);
|
|
497
|
+
this.ensureNotDestroyed_();
|
|
498
|
+
|
|
499
|
+
// Store the necessary update to the manifest, to be processed later.
|
|
507
500
|
const ref = /** @type {!shaka.media.SegmentReference} */ (
|
|
508
501
|
download.ref);
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
502
|
+
const id = shaka.offline.DownloadInfo.idForSegmentRef(ref);
|
|
503
|
+
pendingManifestUpdates[id] = dataKeys[0];
|
|
504
|
+
pendingDataSize += data.byteLength;
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
downloader.queue(download.groupId,
|
|
508
|
+
request, estimateId, isInitSegment, onDownloaded);
|
|
512
509
|
}
|
|
513
510
|
await downloader.waitToFinish();
|
|
514
511
|
|
|
@@ -516,8 +513,8 @@ shaka.offline.Storage = class {
|
|
|
516
513
|
// Re-store the manifest, to attach session IDs.
|
|
517
514
|
// These were (maybe) discovered inside the downloader; we can only add
|
|
518
515
|
// them now, at the end, since the manifestDB is in flux during the
|
|
519
|
-
// process of downloading and storing, and
|
|
520
|
-
// not know about the DRM engine.
|
|
516
|
+
// process of downloading and storing, and assignSegmentsToManifest
|
|
517
|
+
// does not know about the DRM engine.
|
|
521
518
|
this.ensureNotDestroyed_();
|
|
522
519
|
this.setManifestDrmFields_(manifest, manifestDB, drmEngine, config);
|
|
523
520
|
await storage.updateManifest(manifestId, manifestDB);
|
|
@@ -526,24 +523,54 @@ shaka.offline.Storage = class {
|
|
|
526
523
|
|
|
527
524
|
const usingBgFetch = false; // TODO: Get.
|
|
528
525
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
526
|
+
try {
|
|
527
|
+
if (this.getManifestIsEncrypted_(manifest) && usingBgFetch &&
|
|
528
|
+
!this.getManifestIncludesInitData_(manifest)) {
|
|
529
|
+
// Background fetch can't make DRM sessions, so if we have to get the
|
|
530
|
+
// init data from the init segments, download those first before
|
|
531
|
+
// anything else.
|
|
532
|
+
await download(toDownload.filter((info) => info.isInitSegment), true);
|
|
533
|
+
this.ensureNotDestroyed_();
|
|
534
|
+
toDownload = toDownload.filter((info) => !info.isInitSegment);
|
|
538
535
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
536
|
+
// Copy these and reset them now, before calling await.
|
|
537
|
+
const manifestUpdates = pendingManifestUpdates;
|
|
538
|
+
const dataSize = pendingDataSize;
|
|
539
|
+
pendingManifestUpdates = {};
|
|
540
|
+
pendingDataSize = 0;
|
|
542
541
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
542
|
+
await shaka.offline.Storage.assignSegmentsToManifest(
|
|
543
|
+
storage, manifestId, manifestDB, manifestUpdates, dataSize,
|
|
544
|
+
() => this.ensureNotDestroyed_());
|
|
545
|
+
this.ensureNotDestroyed_();
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
if (!usingBgFetch) {
|
|
549
|
+
await download(toDownload, false);
|
|
550
|
+
this.ensureNotDestroyed_();
|
|
551
|
+
|
|
552
|
+
// Copy these and reset them now, before calling await.
|
|
553
|
+
const manifestUpdates = pendingManifestUpdates;
|
|
554
|
+
const dataSize = pendingDataSize;
|
|
555
|
+
pendingManifestUpdates = {};
|
|
556
|
+
pendingDataSize = 0;
|
|
557
|
+
|
|
558
|
+
await shaka.offline.Storage.assignSegmentsToManifest(
|
|
559
|
+
storage, manifestId, manifestDB, manifestUpdates, dataSize,
|
|
560
|
+
() => this.ensureNotDestroyed_());
|
|
561
|
+
this.ensureNotDestroyed_();
|
|
562
|
+
|
|
563
|
+
goog.asserts.assert(
|
|
564
|
+
!manifestDB.isIncomplete, 'The manifest should be complete by now');
|
|
565
|
+
} else {
|
|
566
|
+
// TODO: Send the request to the service worker. Don't await the result.
|
|
567
|
+
}
|
|
568
|
+
} catch (error) {
|
|
569
|
+
const dataKeys = Object.values(pendingManifestUpdates);
|
|
570
|
+
// Remove these pending segments that are not yet linked to the manifest.
|
|
571
|
+
await storage.removeSegments(dataKeys, (key) => {});
|
|
572
|
+
|
|
573
|
+
throw error;
|
|
547
574
|
}
|
|
548
575
|
}
|
|
549
576
|
|
|
@@ -567,70 +594,50 @@ shaka.offline.Storage = class {
|
|
|
567
594
|
}
|
|
568
595
|
|
|
569
596
|
/**
|
|
570
|
-
*
|
|
571
|
-
*
|
|
572
|
-
* The parts of this function that modify the manifest are protected by a
|
|
573
|
-
* mutex, to prevent race conditions; specifically, it prevents two parallel
|
|
574
|
-
* instances of this method from both loading the manifest into memory at the
|
|
575
|
-
* same time, which would result in the slower/later call overwriting the
|
|
576
|
-
* changes of the other.
|
|
597
|
+
* Updates the given manifest, assigns database keys to segments, then stores
|
|
598
|
+
* the updated manifest.
|
|
577
599
|
*
|
|
600
|
+
* It is up to the caller to ensure that this method is not called
|
|
601
|
+
* concurrently on the same manifest.
|
|
602
|
+
*
|
|
603
|
+
* @param {shaka.extern.StorageCell} storage
|
|
578
604
|
* @param {number} manifestId
|
|
579
|
-
* @param {!shaka.
|
|
580
|
-
* @param {
|
|
605
|
+
* @param {!shaka.extern.ManifestDB} manifestDB
|
|
606
|
+
* @param {!Object.<string, number>} manifestUpdates
|
|
607
|
+
* @param {number} dataSizeUpdate
|
|
581
608
|
* @param {function()} throwIfAbortedFn A function that should throw if the
|
|
582
609
|
* download has been aborted.
|
|
583
|
-
* @return {!Promise
|
|
610
|
+
* @return {!Promise}
|
|
584
611
|
*/
|
|
585
|
-
static async
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
const idForRef = shaka.offline.DownloadInfo.idForSegmentRef(ref);
|
|
612
|
+
static async assignSegmentsToManifest(
|
|
613
|
+
storage, manifestId, manifestDB, manifestUpdates, dataSizeUpdate,
|
|
614
|
+
throwIfAbortedFn) {
|
|
590
615
|
let manifestUpdated = false;
|
|
591
|
-
let dataKey;
|
|
592
|
-
let activeHandle;
|
|
593
|
-
/** @type {!shaka.extern.ManifestDB} */
|
|
594
|
-
let manifestDB;
|
|
595
|
-
|
|
596
|
-
let mutexId = 0;
|
|
597
616
|
|
|
598
617
|
try {
|
|
599
|
-
await muxer.init();
|
|
600
|
-
activeHandle = await muxer.getActive();
|
|
601
|
-
|
|
602
|
-
// Store the data.
|
|
603
|
-
const dataKeys = await activeHandle.cell.addSegments([data]);
|
|
604
|
-
dataKey = dataKeys[0];
|
|
605
|
-
throwIfAbortedFn();
|
|
606
|
-
|
|
607
|
-
// Acquire the mutex before accessing the manifest, since there could be
|
|
608
|
-
// multiple instances of this method running at once.
|
|
609
|
-
mutexId = await shaka.offline.Storage.mutex_.acquire();
|
|
610
|
-
throwIfAbortedFn();
|
|
611
|
-
|
|
612
|
-
// Load the manifest.
|
|
613
|
-
const manifests = await activeHandle.cell.getManifests([manifestId]);
|
|
614
|
-
throwIfAbortedFn();
|
|
615
|
-
manifestDB = manifests[0];
|
|
616
|
-
|
|
617
618
|
// Assign the stored data to the manifest.
|
|
618
619
|
let complete = true;
|
|
619
620
|
for (const stream of manifestDB.streams) {
|
|
620
621
|
for (const segment of stream.segments) {
|
|
621
|
-
|
|
622
|
+
let dataKey = segment.pendingSegmentRefId ?
|
|
623
|
+
manifestUpdates[segment.pendingSegmentRefId] : null;
|
|
624
|
+
if (dataKey != null) {
|
|
622
625
|
segment.dataKey = dataKey;
|
|
623
626
|
// Now that the segment has been associated with the appropriate
|
|
624
627
|
// dataKey, the pendingSegmentRefId is no longer necessary.
|
|
625
628
|
segment.pendingSegmentRefId = undefined;
|
|
626
629
|
}
|
|
627
|
-
|
|
630
|
+
|
|
631
|
+
dataKey = segment.pendingInitSegmentRefId ?
|
|
632
|
+
manifestUpdates[segment.pendingInitSegmentRefId] : null;
|
|
633
|
+
if (dataKey != null) {
|
|
628
634
|
segment.initSegmentKey = dataKey;
|
|
629
635
|
// Now that the init segment has been associated with the
|
|
630
636
|
// appropriate initSegmentKey, the pendingInitSegmentRefId is no
|
|
631
637
|
// longer necessary.
|
|
632
638
|
segment.pendingInitSegmentRefId = undefined;
|
|
633
639
|
}
|
|
640
|
+
|
|
634
641
|
if (segment.pendingSegmentRefId) {
|
|
635
642
|
complete = false;
|
|
636
643
|
}
|
|
@@ -641,33 +648,30 @@ shaka.offline.Storage = class {
|
|
|
641
648
|
}
|
|
642
649
|
|
|
643
650
|
// Update the size of the manifest.
|
|
644
|
-
manifestDB.size +=
|
|
651
|
+
manifestDB.size += dataSizeUpdate;
|
|
645
652
|
|
|
646
653
|
// Mark the manifest as complete, if all segments are downloaded.
|
|
647
654
|
if (complete) {
|
|
648
655
|
manifestDB.isIncomplete = false;
|
|
649
656
|
}
|
|
650
657
|
|
|
651
|
-
//
|
|
652
|
-
await
|
|
658
|
+
// Update the manifest.
|
|
659
|
+
await storage.updateManifest(manifestId, manifestDB);
|
|
653
660
|
manifestUpdated = true;
|
|
654
661
|
throwIfAbortedFn();
|
|
655
662
|
} catch (e) {
|
|
656
663
|
await shaka.offline.Storage.cleanStoredManifest(manifestId);
|
|
657
664
|
|
|
658
|
-
if (
|
|
665
|
+
if (!manifestUpdated) {
|
|
666
|
+
const dataKeys = Object.values(manifestUpdates);
|
|
659
667
|
// The cleanStoredManifest method will not "see" any segments that have
|
|
660
668
|
// been downloaded but not assigned to the manifest yet. So un-store
|
|
661
669
|
// them separately.
|
|
662
|
-
await
|
|
670
|
+
await storage.removeSegments(dataKeys, (key) => {});
|
|
663
671
|
}
|
|
664
672
|
|
|
665
673
|
throw e;
|
|
666
|
-
} finally {
|
|
667
|
-
await muxer.destroy();
|
|
668
|
-
shaka.offline.Storage.mutex_.release(mutexId);
|
|
669
674
|
}
|
|
670
|
-
return manifestDB;
|
|
671
675
|
}
|
|
672
676
|
|
|
673
677
|
/**
|
|
@@ -1662,9 +1666,6 @@ shaka.offline.Storage = class {
|
|
|
1662
1666
|
}
|
|
1663
1667
|
};
|
|
1664
1668
|
|
|
1665
|
-
/** @private {!shaka.util.Mutex} */
|
|
1666
|
-
shaka.offline.Storage.mutex_ = new shaka.util.Mutex();
|
|
1667
|
-
|
|
1668
1669
|
shaka.offline.Storage.defaultSystemIds_ = new Map()
|
|
1669
1670
|
.set('org.w3.clearkey', '1077efecc0b24d02ace33c1e52e2fb4b')
|
|
1670
1671
|
.set('com.widevine.alpha', 'edef8ba979d64acea3c827dcd51d21ed')
|