shaka-player 4.8.0 → 4.8.2
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/AUTHORS +1 -0
- package/CONTRIBUTORS +1 -0
- package/dist/deps.js +3 -3
- package/dist/locales.js +33 -33
- package/dist/shaka-player.compiled.d.ts +3 -2
- package/dist/shaka-player.compiled.debug.d.ts +3 -2
- package/dist/shaka-player.compiled.debug.externs.js +8 -2
- package/dist/shaka-player.compiled.debug.js +208 -199
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.externs.js +8 -2
- package/dist/shaka-player.compiled.js +1017 -1016
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.ui.d.ts +3 -2
- package/dist/shaka-player.ui.debug.d.ts +3 -2
- package/dist/shaka-player.ui.debug.externs.js +8 -2
- package/dist/shaka-player.ui.debug.js +149 -140
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.externs.js +8 -2
- package/dist/shaka-player.ui.js +1282 -1281
- package/dist/shaka-player.ui.map +3 -3
- package/lib/dash/dash_parser.js +9 -3
- package/lib/dash/mpd_utils.js +0 -6
- package/lib/dash/segment_template.js +24 -1
- package/lib/media/playhead.js +3 -3
- package/lib/media/segment_index.js +54 -18
- package/lib/media/segment_prefetch.js +20 -4
- package/lib/media/segment_reference.js +12 -0
- package/lib/media/streaming_engine.js +41 -3
- package/lib/mss/mss_parser.js +7 -2
- package/lib/player.js +2 -1
- package/lib/text/ui_text_displayer.js +12 -1
- package/lib/util/cmcd_manager.js +3 -2
- package/lib/util/platform.js +21 -0
- package/lib/util/player_configuration.js +28 -20
- package/lib/util/stream_utils.js +6 -2
- package/lib/util/tXml.js +1 -1
- package/package.json +1 -1
- package/ui/resolution_selection.js +1 -0
package/lib/dash/dash_parser.js
CHANGED
|
@@ -30,6 +30,7 @@ goog.require('shaka.util.MimeUtils');
|
|
|
30
30
|
goog.require('shaka.util.Networking');
|
|
31
31
|
goog.require('shaka.util.OperationManager');
|
|
32
32
|
goog.require('shaka.util.PeriodCombiner');
|
|
33
|
+
goog.require('shaka.util.PlayerConfiguration');
|
|
33
34
|
goog.require('shaka.util.StringUtils');
|
|
34
35
|
goog.require('shaka.util.Timer');
|
|
35
36
|
goog.require('shaka.util.TXml');
|
|
@@ -338,7 +339,9 @@ shaka.dash.DashParser = class {
|
|
|
338
339
|
async parseManifest_(data, finalManifestUri) {
|
|
339
340
|
let manifestData = data;
|
|
340
341
|
const manifestPreprocessor = this.config_.dash.manifestPreprocessor;
|
|
341
|
-
|
|
342
|
+
const defaultManifestPreprocessor =
|
|
343
|
+
shaka.util.PlayerConfiguration.defaultManifestPreprocessor;
|
|
344
|
+
if (manifestPreprocessor != defaultManifestPreprocessor) {
|
|
342
345
|
shaka.Deprecate.deprecateFeature(5,
|
|
343
346
|
'manifest.dash.manifestPreprocessor configuration',
|
|
344
347
|
'Please Use manifest.dash.manifestPreprocessorTXml instead.');
|
|
@@ -364,7 +367,9 @@ shaka.dash.DashParser = class {
|
|
|
364
367
|
}
|
|
365
368
|
const manifestPreprocessorTXml =
|
|
366
369
|
this.config_.dash.manifestPreprocessorTXml;
|
|
367
|
-
|
|
370
|
+
const defaultManifestPreprocessorTXml =
|
|
371
|
+
shaka.util.PlayerConfiguration.defaultManifestPreprocessorTXml;
|
|
372
|
+
if (manifestPreprocessorTXml != defaultManifestPreprocessorTXml) {
|
|
368
373
|
manifestPreprocessorTXml(mpd);
|
|
369
374
|
}
|
|
370
375
|
|
|
@@ -2074,8 +2079,9 @@ shaka.dash.DashParser = class {
|
|
|
2074
2079
|
* @private
|
|
2075
2080
|
*/
|
|
2076
2081
|
async requestForTiming_(getBaseUris, uri, method) {
|
|
2082
|
+
const uris = [shaka.util.StringUtils.htmlUnescape(uri)];
|
|
2077
2083
|
const requestUris =
|
|
2078
|
-
shaka.util.ManifestParserUtils.resolveUris(getBaseUris(),
|
|
2084
|
+
shaka.util.ManifestParserUtils.resolveUris(getBaseUris(), uris);
|
|
2079
2085
|
const request = shaka.net.NetworkingEngine.makeRequest(
|
|
2080
2086
|
requestUris, this.config_.retryParameters);
|
|
2081
2087
|
request.method = method;
|
package/lib/dash/mpd_utils.js
CHANGED
|
@@ -282,12 +282,6 @@ shaka.dash.MpdUtils = class {
|
|
|
282
282
|
const durationStr =
|
|
283
283
|
MpdUtils.inheritAttribute(context, callback, 'duration');
|
|
284
284
|
let segmentDuration = TXml.parsePositiveInt(durationStr || '');
|
|
285
|
-
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
286
|
-
// TODO: The specification is not clear, check this once it is resolved:
|
|
287
|
-
// https://github.com/Dash-Industry-Forum/DASH-IF-IOP/issues/404
|
|
288
|
-
if (context.representation.contentType == ContentType.IMAGE) {
|
|
289
|
-
segmentDuration = TXml.parseFloat(durationStr || '');
|
|
290
|
-
}
|
|
291
285
|
if (segmentDuration) {
|
|
292
286
|
segmentDuration /= timescale;
|
|
293
287
|
}
|
|
@@ -398,6 +398,11 @@ shaka.dash.SegmentTemplate = class {
|
|
|
398
398
|
Math.ceil(availablePeriodTimes[1] / segmentDuration) - 1,
|
|
399
399
|
];
|
|
400
400
|
|
|
401
|
+
// For Low Latency we can request the partial current position.
|
|
402
|
+
if (context.representation.availabilityTimeOffset) {
|
|
403
|
+
availablePeriodPositions[1]++;
|
|
404
|
+
}
|
|
405
|
+
|
|
401
406
|
// In absolute positions.
|
|
402
407
|
const availablePresentationPositions =
|
|
403
408
|
availablePeriodPositions.map((x) => x + startNumber);
|
|
@@ -701,7 +706,7 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
701
706
|
*/
|
|
702
707
|
appendTemplateInfo(info, periodStart, periodEnd, shouldFit,
|
|
703
708
|
initSegmentReference) {
|
|
704
|
-
this.
|
|
709
|
+
this.updateInitSegmentReference(initSegmentReference);
|
|
705
710
|
if (!this.templateInfo_) {
|
|
706
711
|
this.templateInfo_ = info;
|
|
707
712
|
this.periodStart_ = periodStart;
|
|
@@ -732,6 +737,24 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
732
737
|
}
|
|
733
738
|
}
|
|
734
739
|
|
|
740
|
+
/**
|
|
741
|
+
* Updates the init segment reference and propagates the update to all
|
|
742
|
+
* references.
|
|
743
|
+
* @param {shaka.media.InitSegmentReference} initSegmentReference
|
|
744
|
+
*/
|
|
745
|
+
updateInitSegmentReference(initSegmentReference) {
|
|
746
|
+
if (this.initSegmentReference_ === initSegmentReference) {
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
this.initSegmentReference_ = initSegmentReference;
|
|
751
|
+
for (const reference of this.references) {
|
|
752
|
+
if (reference) {
|
|
753
|
+
reference.updateInitSegmentReference(initSegmentReference);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
|
|
735
758
|
/**
|
|
736
759
|
*
|
|
737
760
|
* @param {number} time
|
package/lib/media/playhead.js
CHANGED
|
@@ -382,10 +382,10 @@ shaka.media.MediaSourcePlayhead = class {
|
|
|
382
382
|
seekStart = seekEnd - this.minSeekRange_;
|
|
383
383
|
}
|
|
384
384
|
|
|
385
|
-
if (currentTime < seekStart
|
|
386
|
-
//
|
|
385
|
+
if (currentTime < seekStart) {
|
|
386
|
+
// The seek range has moved past the playhead. Move ahead to catch up.
|
|
387
387
|
const targetTime = this.reposition_(currentTime);
|
|
388
|
-
shaka.log.info('Jumping
|
|
388
|
+
shaka.log.info('Jumping forward ' + (targetTime - currentTime) +
|
|
389
389
|
' seconds to catch up with the seek range.');
|
|
390
390
|
this.mediaElement_.currentTime = targetTime;
|
|
391
391
|
}
|
|
@@ -436,10 +436,11 @@ shaka.media.SegmentIndex = class {
|
|
|
436
436
|
*
|
|
437
437
|
* @param {number} time
|
|
438
438
|
* @param {boolean=} allowNonIndepedent
|
|
439
|
+
* @param {boolean=} reverse
|
|
439
440
|
* @return {?shaka.media.SegmentIterator}
|
|
440
441
|
* @export
|
|
441
442
|
*/
|
|
442
|
-
getIteratorForTime(time, allowNonIndepedent = false) {
|
|
443
|
+
getIteratorForTime(time, allowNonIndepedent = false, reverse = false) {
|
|
443
444
|
let index = this.find(time);
|
|
444
445
|
if (index == null) {
|
|
445
446
|
return null;
|
|
@@ -476,7 +477,8 @@ shaka.media.SegmentIndex = class {
|
|
|
476
477
|
}
|
|
477
478
|
}
|
|
478
479
|
}
|
|
479
|
-
return new shaka.media.SegmentIterator(
|
|
480
|
+
return new shaka.media.SegmentIterator(
|
|
481
|
+
this, index, partialSegmentIndex, reverse);
|
|
480
482
|
}
|
|
481
483
|
|
|
482
484
|
/**
|
|
@@ -552,8 +554,9 @@ shaka.media.SegmentIterator = class {
|
|
|
552
554
|
* @param {shaka.media.SegmentIndex} segmentIndex
|
|
553
555
|
* @param {number} index
|
|
554
556
|
* @param {number} partialSegmentIndex
|
|
557
|
+
* @param {boolean} reverse
|
|
555
558
|
*/
|
|
556
|
-
constructor(segmentIndex, index, partialSegmentIndex) {
|
|
559
|
+
constructor(segmentIndex, index, partialSegmentIndex, reverse) {
|
|
557
560
|
/** @private {shaka.media.SegmentIndex} */
|
|
558
561
|
this.segmentIndex_ = segmentIndex;
|
|
559
562
|
|
|
@@ -562,6 +565,17 @@ shaka.media.SegmentIterator = class {
|
|
|
562
565
|
|
|
563
566
|
/** @private {number} */
|
|
564
567
|
this.currentPartialPosition_ = partialSegmentIndex;
|
|
568
|
+
|
|
569
|
+
/** @private {boolean} */
|
|
570
|
+
this.reverse = reverse;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* @param {boolean} reverse
|
|
575
|
+
* @export
|
|
576
|
+
*/
|
|
577
|
+
setReverse(reverse) {
|
|
578
|
+
this.reverse = reverse;
|
|
565
579
|
}
|
|
566
580
|
|
|
567
581
|
/**
|
|
@@ -606,25 +620,47 @@ shaka.media.SegmentIterator = class {
|
|
|
606
620
|
next() {
|
|
607
621
|
const ref = this.segmentIndex_.get(this.currentPosition_);
|
|
608
622
|
|
|
609
|
-
if (
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
623
|
+
if (!this.reverse) {
|
|
624
|
+
if (ref && ref.hasPartialSegments()) {
|
|
625
|
+
// If the regular segment contains partial segments, move to the next
|
|
626
|
+
// partial SegmentReference.
|
|
627
|
+
this.currentPartialPosition_++;
|
|
628
|
+
// If the current regular segment has been published completely, and
|
|
629
|
+
// we've reached the end of its partial segments list, move to the next
|
|
630
|
+
// regular segment.
|
|
631
|
+
// If the Partial Segments list is still on the fly, do not move to
|
|
632
|
+
// the next regular segment.
|
|
633
|
+
if (ref.hasAllPartialSegments() &&
|
|
634
|
+
this.currentPartialPosition_ == ref.partialReferences.length) {
|
|
635
|
+
this.currentPosition_++;
|
|
636
|
+
this.currentPartialPosition_ = 0;
|
|
637
|
+
}
|
|
638
|
+
} else {
|
|
639
|
+
// If the regular segment doesn't contain partial segments, move to the
|
|
640
|
+
// next regular segment.
|
|
620
641
|
this.currentPosition_++;
|
|
621
642
|
this.currentPartialPosition_ = 0;
|
|
622
643
|
}
|
|
623
644
|
} else {
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
645
|
+
if (ref && ref.hasPartialSegments()) {
|
|
646
|
+
// If the regular segment contains partial segments, move to the
|
|
647
|
+
// previous partial SegmentReference.
|
|
648
|
+
this.currentPartialPosition_--;
|
|
649
|
+
if (this.currentPartialPosition_ < 0) {
|
|
650
|
+
this.currentPosition_--;
|
|
651
|
+
const prevRef = this.segmentIndex_.get(this.currentPosition_);
|
|
652
|
+
if (prevRef && prevRef.hasPartialSegments()) {
|
|
653
|
+
this.currentPartialPosition_ = prevRef.partialReferences.length - 1;
|
|
654
|
+
} else {
|
|
655
|
+
this.currentPartialPosition_ = 0;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
} else {
|
|
659
|
+
// If the regular segment doesn't contain partial segments, move to the
|
|
660
|
+
// previous regular segment.
|
|
661
|
+
this.currentPosition_--;
|
|
662
|
+
this.currentPartialPosition_ = 0;
|
|
663
|
+
}
|
|
628
664
|
}
|
|
629
665
|
|
|
630
666
|
const res = this.current();
|
|
@@ -147,7 +147,12 @@ shaka.media.SegmentPrefetch = class {
|
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
// init segments are ignored from the prefetch limit
|
|
150
|
-
|
|
150
|
+
const initSegments = Array.from(this.initSegmentPrefetchMap_.keys());
|
|
151
|
+
const someReference = initSegments.some((reference) => {
|
|
152
|
+
return shaka.media.InitSegmentReference.equal(
|
|
153
|
+
reference, initSegmentReference);
|
|
154
|
+
});
|
|
155
|
+
if (!someReference) {
|
|
151
156
|
const segmentPrefetchOperation =
|
|
152
157
|
new shaka.media.SegmentPrefetchOperation(this.fetchDispatcher_);
|
|
153
158
|
segmentPrefetchOperation.dispatchFetch(
|
|
@@ -233,6 +238,15 @@ shaka.media.SegmentPrefetch = class {
|
|
|
233
238
|
this.prefetchPosTime_ = 0;
|
|
234
239
|
}
|
|
235
240
|
|
|
241
|
+
/**
|
|
242
|
+
* Remove a reference of prefetched segment if already exists.
|
|
243
|
+
* @param {!shaka.media.SegmentReference} reference
|
|
244
|
+
* @public
|
|
245
|
+
*/
|
|
246
|
+
removeReference(reference) {
|
|
247
|
+
this.abortPrefetchedSegment_(reference);
|
|
248
|
+
}
|
|
249
|
+
|
|
236
250
|
/**
|
|
237
251
|
* @param {number} time
|
|
238
252
|
* @param {boolean=} clearInitSegments
|
|
@@ -261,9 +275,11 @@ shaka.media.SegmentPrefetch = class {
|
|
|
261
275
|
const segmentReferences = Array.from(this.segmentPrefetchMap_.keys());
|
|
262
276
|
for (const initSegmentReference of this.initSegmentPrefetchMap_.keys()) {
|
|
263
277
|
// if no segment references this init segment, we should remove it.
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
segmentReference.initSegmentReference
|
|
278
|
+
const someReference = segmentReferences.some((segmentReference) => {
|
|
279
|
+
return shaka.media.InitSegmentReference.equal(
|
|
280
|
+
segmentReference.initSegmentReference, initSegmentReference);
|
|
281
|
+
});
|
|
282
|
+
if (!someReference) {
|
|
267
283
|
this.abortPrefetchedSegment_(initSegmentReference);
|
|
268
284
|
}
|
|
269
285
|
}
|
|
@@ -621,6 +621,18 @@ shaka.media.SegmentReference = class {
|
|
|
621
621
|
getSegmentData() {
|
|
622
622
|
return this.segmentData;
|
|
623
623
|
}
|
|
624
|
+
|
|
625
|
+
/**
|
|
626
|
+
* Updates the init segment reference and propagates the update to all partial
|
|
627
|
+
* references.
|
|
628
|
+
* @param {shaka.media.InitSegmentReference} initSegmentReference
|
|
629
|
+
*/
|
|
630
|
+
updateInitSegmentReference(initSegmentReference) {
|
|
631
|
+
this.initSegmentReference = initSegmentReference;
|
|
632
|
+
for (const partialReference of this.partialReferences) {
|
|
633
|
+
partialReference.updateInitSegmentReference(initSegmentReference);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
624
636
|
};
|
|
625
637
|
|
|
626
638
|
|
|
@@ -360,6 +360,8 @@ shaka.media.StreamingEngine = class {
|
|
|
360
360
|
setTrickPlay(on) {
|
|
361
361
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
362
362
|
|
|
363
|
+
this.updateSegmentIteratorReverse_();
|
|
364
|
+
|
|
363
365
|
const mediaState = this.mediaStates_.get(ContentType.VIDEO);
|
|
364
366
|
if (!mediaState) {
|
|
365
367
|
return;
|
|
@@ -1422,8 +1424,10 @@ shaka.media.StreamingEngine = class {
|
|
|
1422
1424
|
shaka.log.v1(
|
|
1423
1425
|
logPrefix, 'looking up segment from new stream endTime:', time);
|
|
1424
1426
|
|
|
1427
|
+
const reverse = this.playerInterface_.getPlaybackRate() < 0;
|
|
1425
1428
|
mediaState.segmentIterator =
|
|
1426
|
-
mediaState.stream.segmentIndex.getIteratorForTime(
|
|
1429
|
+
mediaState.stream.segmentIndex.getIteratorForTime(
|
|
1430
|
+
time, /* allowNonIndepedent= */ false, reverse);
|
|
1427
1431
|
const ref = mediaState.segmentIterator &&
|
|
1428
1432
|
mediaState.segmentIterator.next().value;
|
|
1429
1433
|
if (ref == null) {
|
|
@@ -1443,10 +1447,12 @@ shaka.media.StreamingEngine = class {
|
|
|
1443
1447
|
'lookupTime:', lookupTime,
|
|
1444
1448
|
'presentationTime:', presentationTime);
|
|
1445
1449
|
|
|
1450
|
+
const reverse = this.playerInterface_.getPlaybackRate() < 0;
|
|
1446
1451
|
let ref = null;
|
|
1447
1452
|
if (inaccurateTolerance) {
|
|
1448
1453
|
mediaState.segmentIterator =
|
|
1449
|
-
mediaState.stream.segmentIndex.getIteratorForTime(
|
|
1454
|
+
mediaState.stream.segmentIndex.getIteratorForTime(
|
|
1455
|
+
lookupTime, /* allowNonIndepedent= */ false, reverse);
|
|
1450
1456
|
ref = mediaState.segmentIterator &&
|
|
1451
1457
|
mediaState.segmentIterator.next().value;
|
|
1452
1458
|
}
|
|
@@ -1454,7 +1460,8 @@ shaka.media.StreamingEngine = class {
|
|
|
1454
1460
|
// If we can't find a valid segment with the drifted time, look for a
|
|
1455
1461
|
// segment with the presentation time.
|
|
1456
1462
|
mediaState.segmentIterator =
|
|
1457
|
-
mediaState.stream.segmentIndex.getIteratorForTime(
|
|
1463
|
+
mediaState.stream.segmentIndex.getIteratorForTime(
|
|
1464
|
+
presentationTime, /* allowNonIndepedent= */ false, reverse);
|
|
1458
1465
|
ref = mediaState.segmentIterator &&
|
|
1459
1466
|
mediaState.segmentIterator.next().value;
|
|
1460
1467
|
}
|
|
@@ -1695,6 +1702,11 @@ shaka.media.StreamingEngine = class {
|
|
|
1695
1702
|
error.code);
|
|
1696
1703
|
mediaState.hasError = true;
|
|
1697
1704
|
|
|
1705
|
+
if (error.category == shaka.util.Error.Category.NETWORK &&
|
|
1706
|
+
mediaState.segmentPrefetch) {
|
|
1707
|
+
mediaState.segmentPrefetch.removeReference(reference);
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1698
1710
|
error.severity = shaka.util.Error.Severity.CRITICAL;
|
|
1699
1711
|
await this.handleStreamingError_(mediaState, error);
|
|
1700
1712
|
}
|
|
@@ -2752,6 +2764,29 @@ shaka.media.StreamingEngine = class {
|
|
|
2752
2764
|
}
|
|
2753
2765
|
}
|
|
2754
2766
|
|
|
2767
|
+
/**
|
|
2768
|
+
* Update the segment iterator direction.
|
|
2769
|
+
*
|
|
2770
|
+
* @private
|
|
2771
|
+
*/
|
|
2772
|
+
updateSegmentIteratorReverse_() {
|
|
2773
|
+
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
2774
|
+
|
|
2775
|
+
const reverse = this.playerInterface_.getPlaybackRate() < 0;
|
|
2776
|
+
const videoState = this.mediaStates_.get(ContentType.VIDEO);
|
|
2777
|
+
if (videoState && videoState.segmentIterator) {
|
|
2778
|
+
videoState.segmentIterator.setReverse(reverse);
|
|
2779
|
+
}
|
|
2780
|
+
const audioState = this.mediaStates_.get(ContentType.AUDIO);
|
|
2781
|
+
if (audioState && audioState.segmentIterator) {
|
|
2782
|
+
audioState.segmentIterator.setReverse(reverse);
|
|
2783
|
+
}
|
|
2784
|
+
const textState = this.mediaStates_.get(ContentType.TEXT);
|
|
2785
|
+
if (textState && textState.segmentIterator) {
|
|
2786
|
+
textState.segmentIterator.setReverse(reverse);
|
|
2787
|
+
}
|
|
2788
|
+
}
|
|
2789
|
+
|
|
2755
2790
|
/**
|
|
2756
2791
|
* @param {shaka.media.StreamingEngine.MediaState_} mediaState
|
|
2757
2792
|
* @return {string} A log prefix of the form ($CONTENT_TYPE:$STREAM_ID), e.g.,
|
|
@@ -2768,6 +2803,7 @@ shaka.media.StreamingEngine = class {
|
|
|
2768
2803
|
* @typedef {{
|
|
2769
2804
|
* getPresentationTime: function():number,
|
|
2770
2805
|
* getBandwidthEstimate: function():number,
|
|
2806
|
+
* getPlaybackRate: function():number,
|
|
2771
2807
|
* mediaSourceEngine: !shaka.media.MediaSourceEngine,
|
|
2772
2808
|
* netEngine: shaka.net.NetworkingEngine,
|
|
2773
2809
|
* onError: function(!shaka.util.Error),
|
|
@@ -2787,6 +2823,8 @@ shaka.media.StreamingEngine = class {
|
|
|
2787
2823
|
* viewer is seeing on screen right now.
|
|
2788
2824
|
* @property {function():number} getBandwidthEstimate
|
|
2789
2825
|
* Get the estimated bandwidth in bits per second.
|
|
2826
|
+
* @property {function():number} getPlaybackRate
|
|
2827
|
+
* Get the playback rate
|
|
2790
2828
|
* @property {!shaka.media.MediaSourceEngine} mediaSourceEngine
|
|
2791
2829
|
* The MediaSourceEngine. The caller retains ownership.
|
|
2792
2830
|
* @property {shaka.net.NetworkingEngine} netEngine
|
package/lib/mss/mss_parser.js
CHANGED
|
@@ -23,6 +23,7 @@ goog.require('shaka.util.ManifestParserUtils');
|
|
|
23
23
|
goog.require('shaka.util.MimeUtils');
|
|
24
24
|
goog.require('shaka.util.Mp4Generator');
|
|
25
25
|
goog.require('shaka.util.OperationManager');
|
|
26
|
+
goog.require('shaka.util.PlayerConfiguration');
|
|
26
27
|
goog.require('shaka.util.Timer');
|
|
27
28
|
goog.require('shaka.util.TXml');
|
|
28
29
|
goog.require('shaka.util.XmlUtils');
|
|
@@ -282,7 +283,9 @@ shaka.mss.MssParser = class {
|
|
|
282
283
|
parseManifest_(data, finalManifestUri) {
|
|
283
284
|
let manifestData = data;
|
|
284
285
|
const manifestPreprocessor = this.config_.mss.manifestPreprocessor;
|
|
285
|
-
|
|
286
|
+
const defaultManifestPreprocessor =
|
|
287
|
+
shaka.util.PlayerConfiguration.defaultManifestPreprocessor;
|
|
288
|
+
if (manifestPreprocessor != defaultManifestPreprocessor) {
|
|
286
289
|
shaka.Deprecate.deprecateFeature(5,
|
|
287
290
|
'manifest.mss.manifestPreprocessor configuration',
|
|
288
291
|
'Please Use manifest.mss.manifestPreprocessorTXml instead.');
|
|
@@ -307,7 +310,9 @@ shaka.mss.MssParser = class {
|
|
|
307
310
|
finalManifestUri);
|
|
308
311
|
}
|
|
309
312
|
const manifestPreprocessorTXml = this.config_.mss.manifestPreprocessorTXml;
|
|
310
|
-
|
|
313
|
+
const defaultManifestPreprocessorTXml =
|
|
314
|
+
shaka.util.PlayerConfiguration.defaultManifestPreprocessorTXml;
|
|
315
|
+
if (manifestPreprocessorTXml != defaultManifestPreprocessorTXml) {
|
|
311
316
|
manifestPreprocessorTXml(mss);
|
|
312
317
|
}
|
|
313
318
|
this.processManifest_(mss, finalManifestUri);
|
package/lib/player.js
CHANGED
|
@@ -3246,6 +3246,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3246
3246
|
const playerInterface = {
|
|
3247
3247
|
getPresentationTime: () => this.playhead_ ? this.playhead_.getTime() : 0,
|
|
3248
3248
|
getBandwidthEstimate: () => this.abrManager_.getBandwidthEstimate(),
|
|
3249
|
+
getPlaybackRate: () => this.getPlaybackRate(),
|
|
3249
3250
|
mediaSourceEngine: this.mediaSourceEngine_,
|
|
3250
3251
|
netEngine: this.networkingEngine_,
|
|
3251
3252
|
onError: (error) => this.onError_(error),
|
|
@@ -7181,7 +7182,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
7181
7182
|
* @export
|
|
7182
7183
|
*/
|
|
7183
7184
|
// eslint-disable-next-line no-useless-concat
|
|
7184
|
-
shaka.Player.version = 'v4.8.
|
|
7185
|
+
shaka.Player.version = 'v4.8.2' + '-uncompiled'; // x-release-please-version
|
|
7185
7186
|
|
|
7186
7187
|
// Initialize the deprecation system using the version string we just set
|
|
7187
7188
|
// on the player.
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
goog.provide('shaka.text.UITextDisplayer');
|
|
9
9
|
|
|
10
10
|
goog.require('goog.asserts');
|
|
11
|
+
goog.require('shaka.Deprecate');
|
|
11
12
|
goog.require('shaka.text.Cue');
|
|
12
13
|
goog.require('shaka.text.CueRegion');
|
|
13
14
|
goog.require('shaka.util.Dom');
|
|
@@ -65,12 +66,22 @@ shaka.text.UITextDisplayer = class {
|
|
|
65
66
|
|
|
66
67
|
this.videoContainer_.appendChild(this.textContainer_);
|
|
67
68
|
|
|
69
|
+
if (!config || !config.captionsUpdatePeriod) {
|
|
70
|
+
shaka.Deprecate.deprecateFeature(5,
|
|
71
|
+
'UITextDisplayer w/ config',
|
|
72
|
+
'Please migrate to initializing UITextDisplayer with a config.');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** @private {number} */
|
|
76
|
+
const updatePeriod = (config && config.captionsUpdatePeriod) ?
|
|
77
|
+
config.captionsUpdatePeriod : 0.25;
|
|
78
|
+
|
|
68
79
|
/** @private {shaka.util.Timer} */
|
|
69
80
|
this.captionsTimer_ = new shaka.util.Timer(() => {
|
|
70
81
|
if (!this.video_.paused) {
|
|
71
82
|
this.updateCaptions_();
|
|
72
83
|
}
|
|
73
|
-
}).tickEvery(
|
|
84
|
+
}).tickEvery(updatePeriod);
|
|
74
85
|
|
|
75
86
|
/**
|
|
76
87
|
* Maps cues to cue elements. Specifically points out the wrapper element of
|
package/lib/util/cmcd_manager.js
CHANGED
|
@@ -187,12 +187,12 @@ shaka.util.CmcdManager = class {
|
|
|
187
187
|
|
|
188
188
|
const stream = context.stream;
|
|
189
189
|
if (stream) {
|
|
190
|
+
const playbackRate = this.playerInterface_.getPlaybackRate();
|
|
190
191
|
if (isMedia) {
|
|
191
192
|
data.bl = this.getBufferLength_(stream.type);
|
|
192
193
|
if (data.ot !== ObjectType.TIMED_TEXT) {
|
|
193
194
|
const remainingBufferLength =
|
|
194
195
|
this.getRemainingBufferLength_(stream.type);
|
|
195
|
-
const playbackRate = this.playerInterface_.getPlaybackRate();
|
|
196
196
|
if (playbackRate) {
|
|
197
197
|
data.dl = remainingBufferLength / Math.abs(playbackRate);
|
|
198
198
|
} else {
|
|
@@ -206,8 +206,9 @@ shaka.util.CmcdManager = class {
|
|
|
206
206
|
}
|
|
207
207
|
|
|
208
208
|
if (stream.segmentIndex && segment) {
|
|
209
|
+
const reverse = playbackRate < 0;
|
|
209
210
|
const iterator = stream.segmentIndex.getIteratorForTime(
|
|
210
|
-
segment.endTime, /* allowNonIndepedent= */ true);
|
|
211
|
+
segment.endTime, /* allowNonIndepedent= */ true, reverse);
|
|
211
212
|
if (iterator) {
|
|
212
213
|
const nextSegment = iterator.next().value;
|
|
213
214
|
if (nextSegment && nextSegment != segment) {
|
package/lib/util/platform.js
CHANGED
|
@@ -186,6 +186,17 @@ shaka.util.Platform = class {
|
|
|
186
186
|
return shaka.util.Platform.userAgentContains_('CrKey');
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
+
/**
|
|
190
|
+
* Check if the current platform is a Google Chromecast with Android
|
|
191
|
+
* (i.e. Chromecast with GoogleTV).
|
|
192
|
+
*
|
|
193
|
+
* @return {boolean}
|
|
194
|
+
*/
|
|
195
|
+
static isAndroidCastDevice() {
|
|
196
|
+
const Platform = shaka.util.Platform;
|
|
197
|
+
return Platform.isChromecast() && Platform.isAndroid();
|
|
198
|
+
}
|
|
199
|
+
|
|
189
200
|
/**
|
|
190
201
|
* Returns a major version number for Chrome, or Chromium-based browsers.
|
|
191
202
|
*
|
|
@@ -416,6 +427,9 @@ shaka.util.Platform = class {
|
|
|
416
427
|
return navigator.userAgentData.platform.toLowerCase() == 'macos';
|
|
417
428
|
}
|
|
418
429
|
// Fall back to the old API, with less strict matching.
|
|
430
|
+
if (!navigator.platform) {
|
|
431
|
+
return false;
|
|
432
|
+
}
|
|
419
433
|
return navigator.platform.toLowerCase().includes('mac');
|
|
420
434
|
}
|
|
421
435
|
|
|
@@ -430,6 +444,9 @@ shaka.util.Platform = class {
|
|
|
430
444
|
return navigator.userAgentData.platform.toLowerCase() == 'windows';
|
|
431
445
|
}
|
|
432
446
|
// Fall back to the old API, with less strict matching.
|
|
447
|
+
if (!navigator.platform) {
|
|
448
|
+
return false;
|
|
449
|
+
}
|
|
433
450
|
return navigator.platform.toLowerCase().includes('windows');
|
|
434
451
|
}
|
|
435
452
|
|
|
@@ -556,6 +573,10 @@ shaka.util.Platform = class {
|
|
|
556
573
|
Platform.isWebOS4() || Platform.isWebOS5()) {
|
|
557
574
|
return false;
|
|
558
575
|
}
|
|
576
|
+
// Older chromecasts without GoogleTV seem to not support SMOOTH properly.
|
|
577
|
+
if (Platform.isChromecast() && !Platform.isAndroidCastDevice()) {
|
|
578
|
+
return false;
|
|
579
|
+
}
|
|
559
580
|
// See: https://chromium-review.googlesource.com/c/chromium/src/+/4577759
|
|
560
581
|
if (Platform.isWindows() && Platform.isEdge()) {
|
|
561
582
|
return false;
|
|
@@ -141,16 +141,10 @@ shaka.util.PlayerConfiguration = class {
|
|
|
141
141
|
'urn:uuid:79f0049a-4098-8642-ab92-e65be0885f95':
|
|
142
142
|
'com.microsoft.playready',
|
|
143
143
|
},
|
|
144
|
-
manifestPreprocessor:
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
},
|
|
149
|
-
manifestPreprocessorTXml: (element) => {
|
|
150
|
-
return shaka.util.ConfigUtils.referenceParametersAndReturn(
|
|
151
|
-
[element],
|
|
152
|
-
element);
|
|
153
|
-
},
|
|
144
|
+
manifestPreprocessor:
|
|
145
|
+
shaka.util.PlayerConfiguration.defaultManifestPreprocessor,
|
|
146
|
+
manifestPreprocessorTXml:
|
|
147
|
+
shaka.util.PlayerConfiguration.defaultManifestPreprocessorTXml,
|
|
154
148
|
sequenceMode: false,
|
|
155
149
|
enableAudioGroups: false,
|
|
156
150
|
multiTypeVariantsAllowed,
|
|
@@ -174,16 +168,10 @@ shaka.util.PlayerConfiguration = class {
|
|
|
174
168
|
allowLowLatencyByteRangeOptimization: true,
|
|
175
169
|
},
|
|
176
170
|
mss: {
|
|
177
|
-
manifestPreprocessor:
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
},
|
|
182
|
-
manifestPreprocessorTXml: (element) => {
|
|
183
|
-
return shaka.util.ConfigUtils.referenceParametersAndReturn(
|
|
184
|
-
[element],
|
|
185
|
-
element);
|
|
186
|
-
},
|
|
171
|
+
manifestPreprocessor:
|
|
172
|
+
shaka.util.PlayerConfiguration.defaultManifestPreprocessor,
|
|
173
|
+
manifestPreprocessorTXml:
|
|
174
|
+
shaka.util.PlayerConfiguration.defaultManifestPreprocessorTXml,
|
|
187
175
|
sequenceMode: false,
|
|
188
176
|
keySystemsBySystemId: {
|
|
189
177
|
'9a04f079-9840-4286-ab92-e65be0885f95':
|
|
@@ -615,4 +603,24 @@ shaka.util.PlayerConfiguration = class {
|
|
|
615
603
|
|
|
616
604
|
return selectedTracks;
|
|
617
605
|
}
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* @param {!Element} element
|
|
609
|
+
* @return {!Element}
|
|
610
|
+
*/
|
|
611
|
+
static defaultManifestPreprocessor(element) {
|
|
612
|
+
return shaka.util.ConfigUtils.referenceParametersAndReturn(
|
|
613
|
+
[element],
|
|
614
|
+
element);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* @param {!shaka.extern.xml.Node} element
|
|
619
|
+
* @return {!shaka.extern.xml.Node}
|
|
620
|
+
*/
|
|
621
|
+
static defaultManifestPreprocessorTXml(element) {
|
|
622
|
+
return shaka.util.ConfigUtils.referenceParametersAndReturn(
|
|
623
|
+
[element],
|
|
624
|
+
element);
|
|
625
|
+
}
|
|
618
626
|
};
|
package/lib/util/stream_utils.js
CHANGED
|
@@ -983,8 +983,12 @@ shaka.util.StreamUtils = class {
|
|
|
983
983
|
// currently don't support 'fLaC', while 'flac' is supported by most
|
|
984
984
|
// major browsers.
|
|
985
985
|
// See https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
|
|
986
|
-
if (codecs
|
|
987
|
-
|
|
986
|
+
if (codecs.toLowerCase() == 'flac') {
|
|
987
|
+
if (!shaka.util.Platform.isSafari()) {
|
|
988
|
+
return 'flac';
|
|
989
|
+
} else {
|
|
990
|
+
return 'fLaC';
|
|
991
|
+
}
|
|
988
992
|
}
|
|
989
993
|
|
|
990
994
|
// The same is true for 'Opus'.
|
package/lib/util/tXml.js
CHANGED
|
@@ -779,7 +779,7 @@ shaka.util.TXml = class {
|
|
|
779
779
|
element.setAttribute(k, v);
|
|
780
780
|
}
|
|
781
781
|
|
|
782
|
-
if (doParents && node.parent) {
|
|
782
|
+
if (doParents && node.parent && node.parent.tagName != '?xml') {
|
|
783
783
|
const parentElement = TXml.txmlNodeToDomElement(
|
|
784
784
|
node.parent, /* doParents= */ true, /* doChildren= */ false);
|
|
785
785
|
parentElement.appendChild(element);
|
package/package.json
CHANGED
|
@@ -116,6 +116,7 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.SettingsMenu {
|
|
|
116
116
|
} else {
|
|
117
117
|
otherIdx = tracks.findIndex((t) => {
|
|
118
118
|
return t.height == track.height &&
|
|
119
|
+
t.videoBandwidth == track.videoBandwidth &&
|
|
119
120
|
t.frameRate == track.frameRate &&
|
|
120
121
|
t.hdr == track.hdr &&
|
|
121
122
|
t.videoLayout == track.videoLayout;
|