shaka-player 4.8.8 → 4.9.0
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/README.md +5 -0
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/deps.js +5 -5
- package/dist/locales.js +33 -33
- package/dist/shaka-player.compiled.d.ts +39 -17
- package/dist/shaka-player.compiled.debug.d.ts +39 -17
- package/dist/shaka-player.compiled.debug.externs.js +32 -11
- package/dist/shaka-player.compiled.debug.js +574 -516
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +32 -11
- package/dist/shaka-player.compiled.js +1270 -1236
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +39 -17
- package/dist/shaka-player.ui.debug.d.ts +39 -17
- package/dist/shaka-player.ui.debug.externs.js +43 -22
- package/dist/shaka-player.ui.debug.js +601 -543
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +43 -22
- package/dist/shaka-player.ui.js +1483 -1448
- package/dist/shaka-player.ui.map +4 -4
- package/externs/shaka/manifest.js +11 -1
- package/externs/shaka/offline.js +3 -0
- package/externs/shaka/player.js +105 -12
- package/externs/tizen.js +1 -1
- package/lib/abr/simple_abr_manager.js +5 -0
- package/lib/ads/media_tailor_ad.js +11 -0
- package/lib/ads/media_tailor_ad_manager.js +37 -3
- package/lib/cea/cea608_data_channel.js +9 -0
- package/lib/cea/cea_decoder.js +6 -2
- package/lib/dash/dash_parser.js +655 -46
- package/lib/dash/mpd_utils.js +7 -8
- package/lib/dash/segment_template.js +65 -10
- package/lib/hls/hls_parser.js +92 -34
- package/lib/media/drm_engine.js +274 -40
- package/lib/media/manifest_filterer.js +10 -14
- package/lib/media/preload_manager.js +3 -10
- package/lib/media/segment_utils.js +14 -3
- package/lib/mss/mss_parser.js +2 -0
- package/lib/net/http_plugin_utils.js +2 -1
- package/lib/net/networking_engine.js +27 -0
- package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
- package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
- package/lib/offline/manifest_converter.js +2 -0
- package/lib/offline/storage.js +1 -0
- package/lib/player.js +221 -14
- package/lib/polyfill/media_capabilities.js +10 -35
- package/lib/util/config_utils.js +74 -6
- package/lib/util/error.js +7 -0
- package/lib/util/mp4_box_parsers.js +23 -2
- package/lib/util/periods.js +51 -28
- package/lib/util/platform.js +3 -1
- package/lib/util/player_configuration.js +20 -8
- package/lib/util/stream_utils.js +62 -30
- package/lib/util/tXml.js +74 -6
- package/package.json +2 -2
- package/support.html +1 -0
- package/ui/controls.js +4 -0
- package/ui/less/ad_controls.less +2 -1
- package/ui/resolution_selection.js +12 -3
package/lib/util/periods.js
CHANGED
|
@@ -166,11 +166,12 @@ shaka.util.PeriodCombiner = class {
|
|
|
166
166
|
/**
|
|
167
167
|
* @param {!Array.<shaka.extern.Period>} periods
|
|
168
168
|
* @param {boolean} isDynamic
|
|
169
|
+
* @param {boolean=} isPatchUpdate
|
|
169
170
|
* @return {!Promise}
|
|
170
171
|
*
|
|
171
172
|
* @export
|
|
172
173
|
*/
|
|
173
|
-
async combinePeriods(periods, isDynamic) {
|
|
174
|
+
async combinePeriods(periods, isDynamic, isPatchUpdate = false) {
|
|
174
175
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
175
176
|
|
|
176
177
|
// Optimization: for single-period VOD, do nothing. This makes sure
|
|
@@ -190,6 +191,8 @@ shaka.util.PeriodCombiner = class {
|
|
|
190
191
|
this.textStreams_ = Array.from(textStreamsPerPeriod[0].values());
|
|
191
192
|
this.imageStreams_ = Array.from(imageStreamsPerPeriod[0].values());
|
|
192
193
|
} else {
|
|
194
|
+
// How many periods we've seen before which are not included in this call.
|
|
195
|
+
const periodsMissing = isPatchUpdate ? this.usedPeriodIds_.size : 0;
|
|
193
196
|
// Find the first period we haven't seen before. Tag all the periods we
|
|
194
197
|
// see now as "used".
|
|
195
198
|
let firstNewPeriodIndex = -1;
|
|
@@ -226,25 +229,29 @@ shaka.util.PeriodCombiner = class {
|
|
|
226
229
|
audioStreamsPerPeriod,
|
|
227
230
|
firstNewPeriodIndex,
|
|
228
231
|
shaka.util.PeriodCombiner.cloneStream_,
|
|
229
|
-
shaka.util.PeriodCombiner.concatenateStreams_
|
|
232
|
+
shaka.util.PeriodCombiner.concatenateStreams_,
|
|
233
|
+
periodsMissing),
|
|
230
234
|
this.combine_(
|
|
231
235
|
this.videoStreams_,
|
|
232
236
|
videoStreamsPerPeriod,
|
|
233
237
|
firstNewPeriodIndex,
|
|
234
238
|
shaka.util.PeriodCombiner.cloneStream_,
|
|
235
|
-
shaka.util.PeriodCombiner.concatenateStreams_
|
|
239
|
+
shaka.util.PeriodCombiner.concatenateStreams_,
|
|
240
|
+
periodsMissing),
|
|
236
241
|
this.combine_(
|
|
237
242
|
this.textStreams_,
|
|
238
243
|
textStreamsPerPeriod,
|
|
239
244
|
firstNewPeriodIndex,
|
|
240
245
|
shaka.util.PeriodCombiner.cloneStream_,
|
|
241
|
-
shaka.util.PeriodCombiner.concatenateStreams_
|
|
246
|
+
shaka.util.PeriodCombiner.concatenateStreams_,
|
|
247
|
+
periodsMissing),
|
|
242
248
|
this.combine_(
|
|
243
249
|
this.imageStreams_,
|
|
244
250
|
imageStreamsPerPeriod,
|
|
245
251
|
firstNewPeriodIndex,
|
|
246
252
|
shaka.util.PeriodCombiner.cloneStream_,
|
|
247
|
-
shaka.util.PeriodCombiner.concatenateStreams_
|
|
253
|
+
shaka.util.PeriodCombiner.concatenateStreams_,
|
|
254
|
+
periodsMissing),
|
|
248
255
|
]);
|
|
249
256
|
}
|
|
250
257
|
|
|
@@ -367,28 +374,32 @@ shaka.util.PeriodCombiner = class {
|
|
|
367
374
|
audioStreamDbsPerPeriod,
|
|
368
375
|
/* firstNewPeriodIndex= */ 0,
|
|
369
376
|
shaka.util.PeriodCombiner.cloneStreamDB_,
|
|
370
|
-
shaka.util.PeriodCombiner.concatenateStreamDBs_
|
|
377
|
+
shaka.util.PeriodCombiner.concatenateStreamDBs_,
|
|
378
|
+
/* periodsMissing= */ 0);
|
|
371
379
|
|
|
372
380
|
const combinedVideoStreamDbs = await periodCombiner.combine_(
|
|
373
381
|
/* outputStreams= */ [],
|
|
374
382
|
videoStreamDbsPerPeriod,
|
|
375
383
|
/* firstNewPeriodIndex= */ 0,
|
|
376
384
|
shaka.util.PeriodCombiner.cloneStreamDB_,
|
|
377
|
-
shaka.util.PeriodCombiner.concatenateStreamDBs_
|
|
385
|
+
shaka.util.PeriodCombiner.concatenateStreamDBs_,
|
|
386
|
+
/* periodsMissing= */ 0);
|
|
378
387
|
|
|
379
388
|
const combinedTextStreamDbs = await periodCombiner.combine_(
|
|
380
389
|
/* outputStreams= */ [],
|
|
381
390
|
textStreamDbsPerPeriod,
|
|
382
391
|
/* firstNewPeriodIndex= */ 0,
|
|
383
392
|
shaka.util.PeriodCombiner.cloneStreamDB_,
|
|
384
|
-
shaka.util.PeriodCombiner.concatenateStreamDBs_
|
|
393
|
+
shaka.util.PeriodCombiner.concatenateStreamDBs_,
|
|
394
|
+
/* periodsMissing= */ 0);
|
|
385
395
|
|
|
386
396
|
const combinedImageStreamDbs = await periodCombiner.combine_(
|
|
387
397
|
/* outputStreams= */ [],
|
|
388
398
|
imageStreamDbsPerPeriod,
|
|
389
399
|
/* firstNewPeriodIndex= */ 0,
|
|
390
400
|
shaka.util.PeriodCombiner.cloneStreamDB_,
|
|
391
|
-
shaka.util.PeriodCombiner.concatenateStreamDBs_
|
|
401
|
+
shaka.util.PeriodCombiner.concatenateStreamDBs_,
|
|
402
|
+
/* periodsMissing= */ 0);
|
|
392
403
|
|
|
393
404
|
// Recreate variantIds from scratch in the output.
|
|
394
405
|
// HLS content is always single-period, so the early return at the top of
|
|
@@ -435,6 +446,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
435
446
|
* @param {function(T):T} clone Make a clone of an input stream.
|
|
436
447
|
* @param {function(T, T)} concat Concatenate the second stream onto the end
|
|
437
448
|
* of the first.
|
|
449
|
+
* @param {number} periodsMissing The number of periods missing
|
|
438
450
|
*
|
|
439
451
|
* @return {!Promise.<!Array.<T>>} The same array passed to outputStreams,
|
|
440
452
|
* modified to include any newly-created streams.
|
|
@@ -445,15 +457,18 @@ shaka.util.PeriodCombiner = class {
|
|
|
445
457
|
* @private
|
|
446
458
|
*/
|
|
447
459
|
async combine_(
|
|
448
|
-
outputStreams, streamsPerPeriod, firstNewPeriodIndex, clone, concat
|
|
460
|
+
outputStreams, streamsPerPeriod, firstNewPeriodIndex, clone, concat,
|
|
461
|
+
periodsMissing) {
|
|
449
462
|
const unusedStreamsPerPeriod = [];
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
463
|
+
|
|
464
|
+
for (let i = 0; i < streamsPerPeriod.length; i++) {
|
|
465
|
+
if (i >= firstNewPeriodIndex) {
|
|
466
|
+
// This periods streams are all new.
|
|
467
|
+
unusedStreamsPerPeriod.push(new Set(streamsPerPeriod[i].values()));
|
|
468
|
+
} else {
|
|
469
|
+
// This period's streams have all been used already.
|
|
470
|
+
unusedStreamsPerPeriod.push(new Set());
|
|
471
|
+
}
|
|
457
472
|
}
|
|
458
473
|
|
|
459
474
|
// First, extend all existing output Streams into the new periods.
|
|
@@ -461,7 +476,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
461
476
|
// eslint-disable-next-line no-await-in-loop
|
|
462
477
|
const ok = await this.extendExistingOutputStream_(
|
|
463
478
|
outputStream, streamsPerPeriod, firstNewPeriodIndex, concat,
|
|
464
|
-
unusedStreamsPerPeriod);
|
|
479
|
+
unusedStreamsPerPeriod, periodsMissing);
|
|
465
480
|
if (!ok) {
|
|
466
481
|
// This output Stream was not properly extended to include streams from
|
|
467
482
|
// the new period. This is likely a bug in our algorithm, so throw an
|
|
@@ -532,6 +547,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
532
547
|
* of the first.
|
|
533
548
|
* @param {!Array.<!Set.<T>>} unusedStreamsPerPeriod An array of sets of
|
|
534
549
|
* unused streams from each period.
|
|
550
|
+
* @param {number} periodsMissing How many periods are missing in this update.
|
|
535
551
|
*
|
|
536
552
|
* @return {!Promise.<boolean>}
|
|
537
553
|
*
|
|
@@ -543,8 +559,9 @@ shaka.util.PeriodCombiner = class {
|
|
|
543
559
|
*/
|
|
544
560
|
async extendExistingOutputStream_(
|
|
545
561
|
outputStream, streamsPerPeriod, firstNewPeriodIndex, concat,
|
|
546
|
-
unusedStreamsPerPeriod) {
|
|
547
|
-
this.findMatchesInAllPeriods_(streamsPerPeriod,
|
|
562
|
+
unusedStreamsPerPeriod, periodsMissing) {
|
|
563
|
+
this.findMatchesInAllPeriods_(streamsPerPeriod,
|
|
564
|
+
outputStream, periodsMissing > 0);
|
|
548
565
|
|
|
549
566
|
// This only exists where T == Stream, and this should only ever be called
|
|
550
567
|
// on Stream types. StreamDB should not have pre-existing output streams.
|
|
@@ -561,11 +578,11 @@ shaka.util.PeriodCombiner = class {
|
|
|
561
578
|
// the output's MetaSegmentIndex.
|
|
562
579
|
if (outputStream.segmentIndex) {
|
|
563
580
|
await shaka.util.PeriodCombiner.extendOutputSegmentIndex_(outputStream,
|
|
564
|
-
firstNewPeriodIndex);
|
|
581
|
+
firstNewPeriodIndex + periodsMissing);
|
|
565
582
|
}
|
|
566
583
|
|
|
567
584
|
shaka.util.PeriodCombiner.extendOutputStream_(outputStream,
|
|
568
|
-
firstNewPeriodIndex, concat, unusedStreamsPerPeriod);
|
|
585
|
+
firstNewPeriodIndex, concat, unusedStreamsPerPeriod, periodsMissing);
|
|
569
586
|
return true;
|
|
570
587
|
}
|
|
571
588
|
|
|
@@ -664,7 +681,8 @@ shaka.util.PeriodCombiner = class {
|
|
|
664
681
|
return null;
|
|
665
682
|
}
|
|
666
683
|
shaka.util.PeriodCombiner.extendOutputStream_(outputStream,
|
|
667
|
-
/* firstNewPeriodIndex= */ 0, concat, unusedStreamsPerPeriod
|
|
684
|
+
/* firstNewPeriodIndex= */ 0, concat, unusedStreamsPerPeriod,
|
|
685
|
+
/* periodsMissing= */ 0);
|
|
668
686
|
|
|
669
687
|
return outputStream;
|
|
670
688
|
}
|
|
@@ -678,6 +696,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
678
696
|
* of the first.
|
|
679
697
|
* @param {!Array.<!Set.<T>>} unusedStreamsPerPeriod An array of sets of
|
|
680
698
|
* unused streams from each period.
|
|
699
|
+
* @param {number} periodsMissing How many periods are missing in this update
|
|
681
700
|
*
|
|
682
701
|
* @template T
|
|
683
702
|
* Accepts either a StreamDB or Stream type.
|
|
@@ -685,7 +704,8 @@ shaka.util.PeriodCombiner = class {
|
|
|
685
704
|
* @private
|
|
686
705
|
*/
|
|
687
706
|
static extendOutputStream_(
|
|
688
|
-
outputStream, firstNewPeriodIndex, concat, unusedStreamsPerPeriod
|
|
707
|
+
outputStream, firstNewPeriodIndex, concat, unusedStreamsPerPeriod,
|
|
708
|
+
periodsMissing) {
|
|
689
709
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
690
710
|
const LanguageUtils = shaka.util.LanguageUtils;
|
|
691
711
|
const matches = outputStream.matchedStreams;
|
|
@@ -697,7 +717,8 @@ shaka.util.PeriodCombiner = class {
|
|
|
697
717
|
|
|
698
718
|
// Concatenate the new matches onto the stream, starting at the first new
|
|
699
719
|
// period.
|
|
700
|
-
|
|
720
|
+
const start = firstNewPeriodIndex + periodsMissing;
|
|
721
|
+
for (let i = start; i < matches.length; i++) {
|
|
701
722
|
const match = matches[i];
|
|
702
723
|
concat(outputStream, match);
|
|
703
724
|
|
|
@@ -715,7 +736,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
715
736
|
}
|
|
716
737
|
|
|
717
738
|
if (used) {
|
|
718
|
-
unusedStreamsPerPeriod[i].delete(match);
|
|
739
|
+
unusedStreamsPerPeriod[i - periodsMissing].delete(match);
|
|
719
740
|
// Add the full mimetypes to the stream.
|
|
720
741
|
if (match.fullMimeTypes) {
|
|
721
742
|
for (const fullMimeType of match.fullMimeTypes.values()) {
|
|
@@ -937,14 +958,16 @@ shaka.util.PeriodCombiner = class {
|
|
|
937
958
|
*
|
|
938
959
|
* @param {!Array<!Map<string, T>>} streamsPerPeriod
|
|
939
960
|
* @param {T} outputStream
|
|
961
|
+
* @param {boolean=} shouldAppend
|
|
940
962
|
*
|
|
941
963
|
* @template T
|
|
942
964
|
* Accepts either a StreamDB or Stream type.
|
|
943
965
|
*
|
|
944
966
|
* @private
|
|
945
967
|
*/
|
|
946
|
-
findMatchesInAllPeriods_(streamsPerPeriod, outputStream
|
|
947
|
-
|
|
968
|
+
findMatchesInAllPeriods_(streamsPerPeriod, outputStream,
|
|
969
|
+
shouldAppend = false) {
|
|
970
|
+
const matches = shouldAppend ? outputStream.matchedStreams : [];
|
|
948
971
|
for (const streams of streamsPerPeriod) {
|
|
949
972
|
const match = this.findBestMatchInPeriod_(streams, outputStream);
|
|
950
973
|
if (!match) {
|
package/lib/util/platform.js
CHANGED
|
@@ -648,10 +648,12 @@ shaka.util.Platform = class {
|
|
|
648
648
|
/**
|
|
649
649
|
* Detect the maximum resolution that the platform's hardware can handle.
|
|
650
650
|
*
|
|
651
|
-
* @return {!Promise.<
|
|
651
|
+
* @return {!Promise.<shaka.extern.Resolution>}
|
|
652
652
|
*/
|
|
653
653
|
static async detectMaxHardwareResolution() {
|
|
654
654
|
const Platform = shaka.util.Platform;
|
|
655
|
+
|
|
656
|
+
/** @type {shaka.extern.Resolution} */
|
|
655
657
|
const maxResolution = {
|
|
656
658
|
width: Infinity,
|
|
657
659
|
height: Infinity,
|
|
@@ -150,6 +150,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
150
150
|
multiTypeVariantsAllowed,
|
|
151
151
|
useStreamOnceInPeriodFlattening: false,
|
|
152
152
|
updatePeriod: -1,
|
|
153
|
+
enableFastSwitching: true,
|
|
153
154
|
},
|
|
154
155
|
hls: {
|
|
155
156
|
ignoreTextStreamFailures: false,
|
|
@@ -165,6 +166,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
165
166
|
sequenceMode: shaka.util.Platform.supportsSequenceMode(),
|
|
166
167
|
ignoreManifestTimestampsInSegmentsMode: false,
|
|
167
168
|
disableCodecGuessing: false,
|
|
169
|
+
disableClosedCaptionsDetection: false,
|
|
168
170
|
allowLowLatencyByteRangeOptimization: true,
|
|
169
171
|
},
|
|
170
172
|
mss: {
|
|
@@ -221,6 +223,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
221
223
|
inaccurateManifestTolerance: 2,
|
|
222
224
|
lowLatencyMode: false,
|
|
223
225
|
autoLowLatencyMode: false,
|
|
226
|
+
forceHTTP: false,
|
|
224
227
|
forceHTTPS: false,
|
|
225
228
|
preferNativeHls: false,
|
|
226
229
|
updateIntervalSeconds: 1,
|
|
@@ -236,6 +239,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
236
239
|
disableTextPrefetch: false,
|
|
237
240
|
disableVideoPrefetch: false,
|
|
238
241
|
liveSync: false,
|
|
242
|
+
liveSyncTargetLatencyTolerance: 0.5,
|
|
239
243
|
liveSyncMaxLatency: 1,
|
|
240
244
|
liveSyncPlaybackRate: 1.1,
|
|
241
245
|
liveSyncMinLatency: 0,
|
|
@@ -248,7 +252,10 @@ shaka.util.PlayerConfiguration = class {
|
|
|
248
252
|
vodDynamicPlaybackRateLowBufferRate: 0.95,
|
|
249
253
|
vodDynamicPlaybackRateBufferRatio: 0.5,
|
|
250
254
|
infiniteLiveStreamDuration: false,
|
|
255
|
+
preloadNextUrlWindow: 30,
|
|
251
256
|
loadTimeout: 30,
|
|
257
|
+
clearDecodingCache: shaka.util.Platform.isPS4() ||
|
|
258
|
+
shaka.util.Platform.isPS5(),
|
|
252
259
|
};
|
|
253
260
|
|
|
254
261
|
// WebOS, Tizen, Chromecast and Hisense have long hardware pipelines
|
|
@@ -317,6 +324,8 @@ shaka.util.PlayerConfiguration = class {
|
|
|
317
324
|
maxFrameRate: Infinity,
|
|
318
325
|
minBandwidth: 0,
|
|
319
326
|
maxBandwidth: Infinity,
|
|
327
|
+
minChannelsCount: 0,
|
|
328
|
+
maxChannelsCount: Infinity,
|
|
320
329
|
},
|
|
321
330
|
advanced: {
|
|
322
331
|
minTotalBytes: 128e3,
|
|
@@ -329,6 +338,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
329
338
|
ignoreDevicePixelRatio: false,
|
|
330
339
|
clearBufferSwitch: false,
|
|
331
340
|
safeMarginSwitch: 0,
|
|
341
|
+
cacheLoadThreshold: 20,
|
|
332
342
|
};
|
|
333
343
|
|
|
334
344
|
const cmcd = {
|
|
@@ -369,20 +379,19 @@ shaka.util.PlayerConfiguration = class {
|
|
|
369
379
|
},
|
|
370
380
|
};
|
|
371
381
|
|
|
382
|
+
let customPlayheadTracker = false;
|
|
372
383
|
let skipPlayDetection = false;
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
shaka.util.Platform.isHisense() ||
|
|
377
|
-
shaka.util.Platform.isPS5() ||
|
|
378
|
-
shaka.util.Platform.isPS4() ||
|
|
379
|
-
shaka.util.Platform.isXboxOne()) {
|
|
384
|
+
let supportsMultipleMediaElements = true;
|
|
385
|
+
if (shaka.util.Platform.isSmartTV()) {
|
|
386
|
+
customPlayheadTracker = true;
|
|
380
387
|
skipPlayDetection = true;
|
|
388
|
+
supportsMultipleMediaElements = false;
|
|
381
389
|
}
|
|
382
390
|
|
|
383
391
|
const ads = {
|
|
384
|
-
customPlayheadTracker
|
|
392
|
+
customPlayheadTracker,
|
|
385
393
|
skipPlayDetection,
|
|
394
|
+
supportsMultipleMediaElements,
|
|
386
395
|
};
|
|
387
396
|
|
|
388
397
|
const textDisplayer = {
|
|
@@ -426,6 +435,8 @@ shaka.util.PlayerConfiguration = class {
|
|
|
426
435
|
maxFrameRate: Infinity,
|
|
427
436
|
minBandwidth: 0,
|
|
428
437
|
maxBandwidth: Infinity,
|
|
438
|
+
minChannelsCount: 0,
|
|
439
|
+
maxChannelsCount: Infinity,
|
|
429
440
|
},
|
|
430
441
|
playRangeStart: 0,
|
|
431
442
|
playRangeEnd: Infinity,
|
|
@@ -474,6 +485,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
474
485
|
serverCertificate: new Uint8Array(0),
|
|
475
486
|
serverCertificateUri: '',
|
|
476
487
|
individualizationServer: '',
|
|
488
|
+
headers: {},
|
|
477
489
|
},
|
|
478
490
|
};
|
|
479
491
|
return shaka.util.ConfigUtils.mergeConfigObjects(
|
package/lib/util/stream_utils.js
CHANGED
|
@@ -232,7 +232,7 @@ shaka.util.StreamUtils = class {
|
|
|
232
232
|
*
|
|
233
233
|
* @param {!shaka.extern.Manifest} manifest
|
|
234
234
|
* @param {shaka.extern.Restrictions} restrictions
|
|
235
|
-
* @param {
|
|
235
|
+
* @param {shaka.extern.Resolution} maxHwResolution
|
|
236
236
|
*/
|
|
237
237
|
static filterByRestrictions(manifest, restrictions, maxHwResolution) {
|
|
238
238
|
manifest.variants = manifest.variants.filter((variant) => {
|
|
@@ -245,7 +245,7 @@ shaka.util.StreamUtils = class {
|
|
|
245
245
|
* @param {shaka.extern.Variant} variant
|
|
246
246
|
* @param {shaka.extern.Restrictions} restrictions
|
|
247
247
|
* Configured restrictions from the user.
|
|
248
|
-
* @param {
|
|
248
|
+
* @param {shaka.extern.Resolution} maxHwRes
|
|
249
249
|
* The maximum resolution the hardware can handle.
|
|
250
250
|
* This is applied separately from user restrictions because the setting
|
|
251
251
|
* should not be easily replaced by the user's configuration.
|
|
@@ -289,7 +289,7 @@ shaka.util.StreamUtils = class {
|
|
|
289
289
|
}
|
|
290
290
|
}
|
|
291
291
|
|
|
292
|
-
// |variant.frameRate| can be undefined, which breaks
|
|
292
|
+
// |variant.video.frameRate| can be undefined, which breaks
|
|
293
293
|
// the math, so make sure they are there first.
|
|
294
294
|
if (variant && variant.video && variant.video.frameRate) {
|
|
295
295
|
if (!inRange(variant.video.frameRate,
|
|
@@ -299,6 +299,16 @@ shaka.util.StreamUtils = class {
|
|
|
299
299
|
}
|
|
300
300
|
}
|
|
301
301
|
|
|
302
|
+
// |variant.audio.channelsCount| can be undefined, which breaks
|
|
303
|
+
// the math, so make sure they are there first.
|
|
304
|
+
if (variant && variant.audio && variant.audio.channelsCount) {
|
|
305
|
+
if (!inRange(variant.audio.channelsCount,
|
|
306
|
+
restrictions.minChannelsCount,
|
|
307
|
+
restrictions.maxChannelsCount)) {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
302
312
|
if (!inRange(variant.bandwidth,
|
|
303
313
|
restrictions.minBandwidth,
|
|
304
314
|
restrictions.maxBandwidth)) {
|
|
@@ -312,7 +322,7 @@ shaka.util.StreamUtils = class {
|
|
|
312
322
|
/**
|
|
313
323
|
* @param {!Array.<shaka.extern.Variant>} variants
|
|
314
324
|
* @param {shaka.extern.Restrictions} restrictions
|
|
315
|
-
* @param {
|
|
325
|
+
* @param {shaka.extern.Resolution} maxHwRes
|
|
316
326
|
* @return {boolean} Whether the tracks changed.
|
|
317
327
|
*/
|
|
318
328
|
static applyRestrictions(variants, restrictions, maxHwRes) {
|
|
@@ -813,6 +823,9 @@ shaka.util.StreamUtils = class {
|
|
|
813
823
|
break;
|
|
814
824
|
}
|
|
815
825
|
}
|
|
826
|
+
if (video.colorGamut) {
|
|
827
|
+
videoConfig.colorGamut = video.colorGamut;
|
|
828
|
+
}
|
|
816
829
|
videoConfigs.push(videoConfig);
|
|
817
830
|
}
|
|
818
831
|
}
|
|
@@ -931,38 +944,44 @@ shaka.util.StreamUtils = class {
|
|
|
931
944
|
}
|
|
932
945
|
|
|
933
946
|
if (audio) {
|
|
934
|
-
|
|
935
|
-
if (info.audioRobustness != '') {
|
|
936
|
-
if (!keySystemConfig.audio) {
|
|
937
|
-
// KeySystemTrackConfiguration
|
|
938
|
-
keySystemConfig.audio = {
|
|
939
|
-
robustness: info.audioRobustness,
|
|
940
|
-
};
|
|
941
|
-
} else {
|
|
942
|
-
keySystemConfig.audio.robustness =
|
|
943
|
-
keySystemConfig.audio.robustness || info.audioRobustness;
|
|
944
|
-
}
|
|
945
|
-
} else if (!keySystemConfig.audio) {
|
|
947
|
+
if (!keySystemConfig.audio) {
|
|
946
948
|
// KeySystemTrackConfiguration
|
|
947
|
-
keySystemConfig.audio = {
|
|
949
|
+
keySystemConfig.audio = {
|
|
950
|
+
encryptionScheme: info.encryptionScheme,
|
|
951
|
+
robustness: info.audioRobustness,
|
|
952
|
+
};
|
|
953
|
+
} else {
|
|
954
|
+
keySystemConfig.audio.encryptionScheme =
|
|
955
|
+
keySystemConfig.audio.encryptionScheme ||
|
|
956
|
+
info.encryptionScheme;
|
|
957
|
+
keySystemConfig.audio.robustness =
|
|
958
|
+
keySystemConfig.audio.robustness ||
|
|
959
|
+
info.audioRobustness;
|
|
960
|
+
}
|
|
961
|
+
// See: https://github.com/shaka-project/shaka-player/issues/4659
|
|
962
|
+
if (keySystemConfig.audio.robustness == '') {
|
|
963
|
+
delete keySystemConfig.audio.robustness;
|
|
948
964
|
}
|
|
949
965
|
}
|
|
950
966
|
|
|
951
967
|
if (video) {
|
|
952
|
-
|
|
953
|
-
if (info.videoRobustness != '') {
|
|
954
|
-
if (!keySystemConfig.video) {
|
|
955
|
-
// KeySystemTrackConfiguration
|
|
956
|
-
keySystemConfig.video = {
|
|
957
|
-
robustness: info.videoRobustness,
|
|
958
|
-
};
|
|
959
|
-
} else {
|
|
960
|
-
keySystemConfig.video.robustness =
|
|
961
|
-
keySystemConfig.video.robustness || info.videoRobustness;
|
|
962
|
-
}
|
|
963
|
-
} else if (!keySystemConfig.video) {
|
|
968
|
+
if (!keySystemConfig.video) {
|
|
964
969
|
// KeySystemTrackConfiguration
|
|
965
|
-
keySystemConfig.video = {
|
|
970
|
+
keySystemConfig.video = {
|
|
971
|
+
encryptionScheme: info.encryptionScheme,
|
|
972
|
+
robustness: info.videoRobustness,
|
|
973
|
+
};
|
|
974
|
+
} else {
|
|
975
|
+
keySystemConfig.video.encryptionScheme =
|
|
976
|
+
keySystemConfig.video.encryptionScheme ||
|
|
977
|
+
info.encryptionScheme;
|
|
978
|
+
keySystemConfig.video.robustness =
|
|
979
|
+
keySystemConfig.video.robustness ||
|
|
980
|
+
info.videoRobustness;
|
|
981
|
+
}
|
|
982
|
+
// See: https://github.com/shaka-project/shaka-player/issues/4659
|
|
983
|
+
if (keySystemConfig.video.robustness == '') {
|
|
984
|
+
delete keySystemConfig.video.robustness;
|
|
966
985
|
}
|
|
967
986
|
}
|
|
968
987
|
}
|
|
@@ -1277,6 +1296,7 @@ shaka.util.StreamUtils = class {
|
|
|
1277
1296
|
frameRate: null,
|
|
1278
1297
|
pixelAspectRatio: null,
|
|
1279
1298
|
hdr: null,
|
|
1299
|
+
colorGamut: null,
|
|
1280
1300
|
videoLayout: null,
|
|
1281
1301
|
mimeType: mimeType,
|
|
1282
1302
|
audioMimeType: audioMimeType,
|
|
@@ -1313,6 +1333,7 @@ shaka.util.StreamUtils = class {
|
|
|
1313
1333
|
track.pixelAspectRatio = video.pixelAspectRatio || null;
|
|
1314
1334
|
track.videoBandwidth = video.bandwidth || null;
|
|
1315
1335
|
track.hdr = video.hdr || null;
|
|
1336
|
+
track.colorGamut = video.colorGamut || null;
|
|
1316
1337
|
track.videoLayout = video.videoLayout || null;
|
|
1317
1338
|
}
|
|
1318
1339
|
|
|
@@ -1354,6 +1375,7 @@ shaka.util.StreamUtils = class {
|
|
|
1354
1375
|
frameRate: null,
|
|
1355
1376
|
pixelAspectRatio: null,
|
|
1356
1377
|
hdr: null,
|
|
1378
|
+
colorGamut: null,
|
|
1357
1379
|
videoLayout: null,
|
|
1358
1380
|
mimeType: stream.mimeType,
|
|
1359
1381
|
audioMimeType: null,
|
|
@@ -1431,6 +1453,7 @@ shaka.util.StreamUtils = class {
|
|
|
1431
1453
|
frameRate: null,
|
|
1432
1454
|
pixelAspectRatio: null,
|
|
1433
1455
|
hdr: null,
|
|
1456
|
+
colorGamut: null,
|
|
1434
1457
|
videoLayout: null,
|
|
1435
1458
|
mimeType: stream.mimeType,
|
|
1436
1459
|
audioMimeType: null,
|
|
@@ -1558,6 +1581,7 @@ shaka.util.StreamUtils = class {
|
|
|
1558
1581
|
frameRate: null,
|
|
1559
1582
|
pixelAspectRatio: null,
|
|
1560
1583
|
hdr: null,
|
|
1584
|
+
colorGamut: null,
|
|
1561
1585
|
videoLayout: null,
|
|
1562
1586
|
mimeType: null,
|
|
1563
1587
|
audioMimeType: null,
|
|
@@ -1829,6 +1853,14 @@ shaka.util.StreamUtils = class {
|
|
|
1829
1853
|
|
|
1830
1854
|
return 'unexpected stream type';
|
|
1831
1855
|
}
|
|
1856
|
+
|
|
1857
|
+
|
|
1858
|
+
/**
|
|
1859
|
+
* Clears underlying decoding config cache.
|
|
1860
|
+
*/
|
|
1861
|
+
static clearDecodingConfigCache() {
|
|
1862
|
+
shaka.util.StreamUtils.decodingConfigCache_ = {};
|
|
1863
|
+
}
|
|
1832
1864
|
};
|
|
1833
1865
|
|
|
1834
1866
|
|
package/lib/util/tXml.js
CHANGED
|
@@ -741,28 +741,94 @@ shaka.util.TXml = class {
|
|
|
741
741
|
* @return {!Array<!shaka.util.TXml.PathNode>}
|
|
742
742
|
*/
|
|
743
743
|
static parseXpath(exprString) {
|
|
744
|
+
const StringUtils = shaka.util.StringUtils;
|
|
744
745
|
const returnPaths = [];
|
|
745
746
|
// Split string by paths but ignore '/' in quotes
|
|
746
|
-
const paths = exprString
|
|
747
|
+
const paths = StringUtils.htmlUnescape(exprString)
|
|
747
748
|
.split(/\/+(?=(?:[^'"]*['"][^'"]*['"])*[^'"]*$)/);
|
|
748
749
|
for (const path of paths) {
|
|
749
|
-
const nodeName = path.match(
|
|
750
|
+
const nodeName = path.match(/^([\w]+)/);
|
|
750
751
|
|
|
751
|
-
// We only want the id attribute in which case
|
|
752
|
-
// /'(.*?)'/ will suffice to get it.
|
|
753
|
-
const idAttr = path.match(/(@id='(.*?)')/);
|
|
754
752
|
if (nodeName) {
|
|
753
|
+
// We only want the id attribute in which case
|
|
754
|
+
// /'(.*?)'/ will suffice to get it.
|
|
755
|
+
const idAttr = path.match(/(@id='(.*?)')/);
|
|
756
|
+
const position = path.match(/\[(\d+)\]/);
|
|
755
757
|
returnPaths.push({
|
|
756
758
|
name: nodeName[0],
|
|
757
759
|
id: idAttr ?
|
|
758
760
|
idAttr[0].match(/'(.*?)'/)[0].replace(/'/gm, '') : null,
|
|
761
|
+
// position is counted from 1, so make it readable for devs
|
|
762
|
+
position: position ? Number(position[1]) - 1 : null,
|
|
763
|
+
attribute: path.split('/@')[1] || null,
|
|
759
764
|
});
|
|
765
|
+
} else if (path.startsWith('@') && returnPaths.length) {
|
|
766
|
+
returnPaths[returnPaths.length - 1].attribute = path.slice(1);
|
|
760
767
|
}
|
|
761
768
|
}
|
|
762
769
|
return returnPaths;
|
|
763
770
|
}
|
|
764
771
|
|
|
765
772
|
|
|
773
|
+
/**
|
|
774
|
+
* Modifies nodes in specified array by adding or removing nodes
|
|
775
|
+
* and updating attributes.
|
|
776
|
+
* @param {!Array<shaka.extern.xml.Node>} nodes
|
|
777
|
+
* @param {!shaka.extern.xml.Node} patchNode
|
|
778
|
+
*/
|
|
779
|
+
static modifyNodes(nodes, patchNode) {
|
|
780
|
+
const TXml = shaka.util.TXml;
|
|
781
|
+
|
|
782
|
+
const paths = TXml.parseXpath(patchNode.attributes['sel'] || '');
|
|
783
|
+
if (!paths.length) {
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
const lastNode = paths[paths.length - 1];
|
|
787
|
+
const position = patchNode.attributes['pos'] || null;
|
|
788
|
+
|
|
789
|
+
let index = lastNode.position;
|
|
790
|
+
if (index === null) {
|
|
791
|
+
index = position === 'prepend' ? 0 : nodes.length;
|
|
792
|
+
} else if (position === 'prepend') {
|
|
793
|
+
--index;
|
|
794
|
+
} else if (position === 'after') {
|
|
795
|
+
++index;
|
|
796
|
+
}
|
|
797
|
+
const action = patchNode.tagName;
|
|
798
|
+
const attribute = lastNode.attribute;
|
|
799
|
+
|
|
800
|
+
// Modify attribute
|
|
801
|
+
if (attribute) {
|
|
802
|
+
TXml.modifyNodeAttribute(nodes[index], action, attribute,
|
|
803
|
+
TXml.getContents(patchNode) || '');
|
|
804
|
+
// Rearrange nodes
|
|
805
|
+
} else {
|
|
806
|
+
if (action === 'remove' || action === 'replace') {
|
|
807
|
+
nodes.splice(index, 1);
|
|
808
|
+
}
|
|
809
|
+
if (action === 'add' || action === 'replace') {
|
|
810
|
+
const newNodes = patchNode.children;
|
|
811
|
+
nodes.splice(index, 0, ...newNodes);
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
|
|
817
|
+
/**
|
|
818
|
+
* @param {!shaka.extern.xml.Node} node
|
|
819
|
+
* @param {string} action
|
|
820
|
+
* @param {string} attribute
|
|
821
|
+
* @param {string} value
|
|
822
|
+
*/
|
|
823
|
+
static modifyNodeAttribute(node, action, attribute, value) {
|
|
824
|
+
if (action === 'remove') {
|
|
825
|
+
delete node.attributes[attribute];
|
|
826
|
+
} else if (action === 'add' || action === 'replace') {
|
|
827
|
+
node.attributes[attribute] = value;
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
|
|
766
832
|
/**
|
|
767
833
|
* Converts a tXml node to DOM element.
|
|
768
834
|
* @param {shaka.extern.xml.Node} node
|
|
@@ -808,7 +874,9 @@ shaka.util.TXml.knownNameSpaces_ = new Map([]);
|
|
|
808
874
|
/**
|
|
809
875
|
* @typedef {{
|
|
810
876
|
* name: string,
|
|
811
|
-
* id: ?string
|
|
877
|
+
* id: ?string,
|
|
878
|
+
* position: ?number,
|
|
879
|
+
* attribute: ?string
|
|
812
880
|
* }}
|
|
813
881
|
*/
|
|
814
882
|
shaka.util.TXml.PathNode;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shaka-player",
|
|
3
3
|
"description": "DASH/EME video player library",
|
|
4
|
-
"version": "4.
|
|
4
|
+
"version": "4.9.0",
|
|
5
5
|
"homepage": "https://github.com/shaka-project/shaka-player",
|
|
6
6
|
"author": "Google",
|
|
7
7
|
"maintainers": [
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
"prepublishOnly": "python build/checkversion.py && python build/all.py --force"
|
|
106
106
|
},
|
|
107
107
|
"dependencies": {
|
|
108
|
-
"eme-encryption-scheme-polyfill": "^2.1.
|
|
108
|
+
"eme-encryption-scheme-polyfill": "^2.1.5"
|
|
109
109
|
},
|
|
110
110
|
"clean-package": {
|
|
111
111
|
"remove": [
|