shaka-player 4.7.4 → 4.7.6
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/dist/locales.js +31 -31
- package/dist/shaka-player.compiled.d.ts +7 -0
- package/dist/shaka-player.compiled.debug.d.ts +7 -0
- package/dist/shaka-player.compiled.debug.externs.js +4 -0
- package/dist/shaka-player.compiled.debug.js +117 -114
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.externs.js +4 -0
- package/dist/shaka-player.compiled.js +1032 -1030
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.ui.d.ts +7 -0
- package/dist/shaka-player.ui.debug.d.ts +7 -0
- package/dist/shaka-player.ui.debug.externs.js +4 -0
- package/dist/shaka-player.ui.debug.js +140 -138
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.externs.js +4 -0
- package/dist/shaka-player.ui.js +1202 -1200
- package/dist/shaka-player.ui.map +3 -3
- package/externs/shaka/abr_manager.js +9 -0
- package/lib/abr/simple_abr_manager.js +11 -0
- package/lib/cast/cast_proxy.js +18 -0
- package/lib/hls/hls_utils.js +5 -5
- package/lib/media/media_source_engine.js +1 -1
- package/lib/media/play_rate_controller.js +1 -0
- package/lib/media/segment_prefetch.js +4 -0
- package/lib/media/streaming_engine.js +6 -8
- package/lib/net/networking_engine.js +1 -1
- package/lib/player.js +48 -5
- package/lib/text/ttml_text_parser.js +5 -0
- package/lib/util/language_utils.js +7 -8
- package/lib/util/periods.js +7 -1
- package/lib/util/platform.js +18 -0
- package/lib/util/stream_utils.js +14 -0
- package/package.json +1 -1
- package/ui/controls.js +3 -0
- package/ui/pip_button.js +5 -21
- package/ui/playback_rate_selection.js +4 -0
|
@@ -96,6 +96,15 @@ shaka.extern.AbrManager = class {
|
|
|
96
96
|
*/
|
|
97
97
|
segmentDownloaded(deltaTimeMs, numBytes, allowSwitch) {}
|
|
98
98
|
|
|
99
|
+
/**
|
|
100
|
+
* Notifies the ABR that it is a time to suggest new streams. This is used by
|
|
101
|
+
* the Player when it finishes adding the last partial segment of a fast
|
|
102
|
+
* switching stream.
|
|
103
|
+
*
|
|
104
|
+
* @exportDoc
|
|
105
|
+
*/
|
|
106
|
+
trySuggestStreams() {}
|
|
107
|
+
|
|
99
108
|
/**
|
|
100
109
|
* Gets an estimate of the current bandwidth in bit/sec. This is used by the
|
|
101
110
|
* Player to generate stats.
|
|
@@ -320,6 +320,17 @@ shaka.abr.SimpleAbrManager = class {
|
|
|
320
320
|
}
|
|
321
321
|
|
|
322
322
|
|
|
323
|
+
/**
|
|
324
|
+
* @override
|
|
325
|
+
* @export
|
|
326
|
+
*/
|
|
327
|
+
trySuggestStreams() {
|
|
328
|
+
if ((this.lastTimeChosenMs_ != null) && this.enabled_) {
|
|
329
|
+
this.suggestStreams_();
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
|
|
323
334
|
/**
|
|
324
335
|
* @override
|
|
325
336
|
* @export
|
package/lib/cast/cast_proxy.js
CHANGED
|
@@ -496,6 +496,16 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
|
|
496
496
|
startTime = this.sender_.get('video', 'currentTime');
|
|
497
497
|
}
|
|
498
498
|
|
|
499
|
+
let activeTextTrack;
|
|
500
|
+
const textTracks = this.sender_.get('player', 'getTextTracks')();
|
|
501
|
+
|
|
502
|
+
if (textTracks && textTracks.length) {
|
|
503
|
+
activeTextTrack = textTracks.find((t) => t.active);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
const isTextTrackVisible =
|
|
507
|
+
this.sender_.get('player', 'isTextTrackVisible')();
|
|
508
|
+
|
|
499
509
|
// Now load the manifest, if present.
|
|
500
510
|
if (assetUri) {
|
|
501
511
|
// Don't autoplay the content until we finish setting up initial state.
|
|
@@ -527,6 +537,14 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
|
|
527
537
|
/** @type {Object} */(this.localPlayer_)[setter](value);
|
|
528
538
|
}
|
|
529
539
|
|
|
540
|
+
this.localPlayer_.setTextTrackVisibility(isTextTrackVisible);
|
|
541
|
+
if (activeTextTrack) {
|
|
542
|
+
this.localPlayer_.selectTextLanguage(
|
|
543
|
+
activeTextTrack.language,
|
|
544
|
+
activeTextTrack.roles,
|
|
545
|
+
activeTextTrack.forced);
|
|
546
|
+
}
|
|
547
|
+
|
|
530
548
|
// Restore the original autoplay setting.
|
|
531
549
|
this.localVideo_.autoplay = autoplay;
|
|
532
550
|
if (assetUri) {
|
package/lib/hls/hls_utils.js
CHANGED
|
@@ -47,12 +47,12 @@ shaka.hls.Utils = class {
|
|
|
47
47
|
* @return {?shaka.hls.Tag}
|
|
48
48
|
*/
|
|
49
49
|
static getFirstTagWithName(tags, name) {
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
for (const tag of tags) {
|
|
51
|
+
if (tag.name === name) {
|
|
52
|
+
return tag;
|
|
53
|
+
}
|
|
53
54
|
}
|
|
54
|
-
|
|
55
|
-
return tagsWithName[0];
|
|
55
|
+
return null;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
/**
|
|
@@ -1805,7 +1805,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1805
1805
|
|
|
1806
1806
|
this.destroyer_.ensureNotDestroyed();
|
|
1807
1807
|
|
|
1808
|
-
this.eventManager_.listenOnce(this.video_, '
|
|
1808
|
+
this.eventManager_.listenOnce(this.video_, 'canplaythrough', () => {
|
|
1809
1809
|
this.destroyer_.ensureNotDestroyed();
|
|
1810
1810
|
|
|
1811
1811
|
this.video_.autoplay = previousAutoPlayState;
|
|
@@ -97,6 +97,10 @@ shaka.media.SegmentPrefetch = class {
|
|
|
97
97
|
this.segmentPrefetchMap_.set(reference, segmentPrefetchOperation);
|
|
98
98
|
}
|
|
99
99
|
this.prefetchPosTime_ = reference.startTime;
|
|
100
|
+
if (this.stream_.fastSwitching && reference.isPartial() &&
|
|
101
|
+
reference.isLastPartial()) {
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
100
104
|
reference = iterator.next().value;
|
|
101
105
|
}
|
|
102
106
|
}
|
|
@@ -121,7 +121,7 @@ shaka.media.StreamingEngine = class {
|
|
|
121
121
|
this.destroyer_ = new shaka.util.Destroyer(() => this.doDestroy_());
|
|
122
122
|
|
|
123
123
|
/** @private {number} */
|
|
124
|
-
this.lastMediaSourceReset_ =
|
|
124
|
+
this.lastMediaSourceReset_ = Date.now() / 1000;
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
/** @override */
|
|
@@ -1488,8 +1488,7 @@ shaka.media.StreamingEngine = class {
|
|
|
1488
1488
|
JSON.stringify(buffered));
|
|
1489
1489
|
|
|
1490
1490
|
if (!mediaState.waitingToClearBuffer) {
|
|
1491
|
-
this.playerInterface_.onSegmentAppended(
|
|
1492
|
-
reference.startTime, reference.endTime, mediaState.type);
|
|
1491
|
+
this.playerInterface_.onSegmentAppended(reference, mediaState.stream);
|
|
1493
1492
|
}
|
|
1494
1493
|
|
|
1495
1494
|
// Update right away.
|
|
@@ -2526,8 +2525,8 @@ shaka.media.StreamingEngine = class {
|
|
|
2526
2525
|
* onError: function(!shaka.util.Error),
|
|
2527
2526
|
* onEvent: function(!Event),
|
|
2528
2527
|
* onManifestUpdate: function(),
|
|
2529
|
-
* onSegmentAppended: function(
|
|
2530
|
-
* !shaka.
|
|
2528
|
+
* onSegmentAppended: function(!shaka.media.SegmentReference,
|
|
2529
|
+
* !shaka.extern.Stream),
|
|
2531
2530
|
* onInitSegmentAppended: function(!number,!shaka.media.InitSegmentReference),
|
|
2532
2531
|
* beforeAppendSegment: function(
|
|
2533
2532
|
* shaka.util.ManifestParserUtils.ContentType,!BufferSource):Promise,
|
|
@@ -2552,10 +2551,9 @@ shaka.media.StreamingEngine = class {
|
|
|
2552
2551
|
* Called when an event occurs that should be sent to the app.
|
|
2553
2552
|
* @property {function()} onManifestUpdate
|
|
2554
2553
|
* Called when an embedded 'emsg' box should trigger a manifest update.
|
|
2555
|
-
* @property {function(
|
|
2556
|
-
*
|
|
2554
|
+
* @property {function(!shaka.media.SegmentReference,
|
|
2555
|
+
* !shaka.extern.Stream)} onSegmentAppended
|
|
2557
2556
|
* Called after a segment is successfully appended to a MediaSource.
|
|
2558
|
-
* The parameters are the start and end time.
|
|
2559
2557
|
* @property
|
|
2560
2558
|
* {function(!number, !shaka.media.InitSegmentReference)} onInitSegmentAppended
|
|
2561
2559
|
* Called when an init segment is appended to a MediaSource.
|
|
@@ -700,7 +700,7 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
|
|
|
700
700
|
const segment = context.segment;
|
|
701
701
|
const stream = context.stream;
|
|
702
702
|
if (segment && stream && stream.fastSwitching) {
|
|
703
|
-
if (segment.isPartial()
|
|
703
|
+
if (segment.isPartial()) {
|
|
704
704
|
return false;
|
|
705
705
|
}
|
|
706
706
|
}
|
package/lib/player.js
CHANGED
|
@@ -550,6 +550,12 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
550
550
|
*/
|
|
551
551
|
this.loadEventManager_ = new shaka.util.EventManager();
|
|
552
552
|
|
|
553
|
+
/**
|
|
554
|
+
* For listeners scoped to the lifetime of the loaded content.
|
|
555
|
+
* @private {shaka.util.EventManager}
|
|
556
|
+
*/
|
|
557
|
+
this.trickPlayEventManager_ = new shaka.util.EventManager();
|
|
558
|
+
|
|
553
559
|
/** @private {shaka.net.NetworkingEngine} */
|
|
554
560
|
this.networkingEngine_ = null;
|
|
555
561
|
|
|
@@ -848,6 +854,10 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
848
854
|
this.loadEventManager_.release();
|
|
849
855
|
this.loadEventManager_ = null;
|
|
850
856
|
}
|
|
857
|
+
if (this.trickPlayEventManager_) {
|
|
858
|
+
this.trickPlayEventManager_.release();
|
|
859
|
+
this.trickPlayEventManager_ = null;
|
|
860
|
+
}
|
|
851
861
|
|
|
852
862
|
this.abrManagerFactory_ = null;
|
|
853
863
|
this.config_ = null;
|
|
@@ -1166,6 +1176,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
1166
1176
|
// element.
|
|
1167
1177
|
if (this.video_) {
|
|
1168
1178
|
this.loadEventManager_.removeAll();
|
|
1179
|
+
this.trickPlayEventManager_.removeAll();
|
|
1169
1180
|
}
|
|
1170
1181
|
|
|
1171
1182
|
// Stop the variant checker timer
|
|
@@ -1847,6 +1858,12 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
1847
1858
|
'Please use an AbrManager with setCmsdManager function.');
|
|
1848
1859
|
this.abrManager_.setCmsdManager = () => {};
|
|
1849
1860
|
}
|
|
1861
|
+
if (typeof this.abrManager_.trySuggestStreams != 'function') {
|
|
1862
|
+
shaka.Deprecate.deprecateFeature(5,
|
|
1863
|
+
'AbrManager',
|
|
1864
|
+
'Please use an AbrManager with trySuggestStreams function.');
|
|
1865
|
+
this.abrManager_.trySuggestStreams = () => {};
|
|
1866
|
+
}
|
|
1850
1867
|
this.abrManager_.configure(this.config_.abr);
|
|
1851
1868
|
}
|
|
1852
1869
|
|
|
@@ -2904,8 +2921,13 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2904
2921
|
onError: (error) => this.onError_(error),
|
|
2905
2922
|
onEvent: (event) => this.dispatchEvent(event),
|
|
2906
2923
|
onManifestUpdate: () => this.onManifestUpdate_(),
|
|
2907
|
-
onSegmentAppended: (
|
|
2908
|
-
this.onSegmentAppended_(
|
|
2924
|
+
onSegmentAppended: (reference, stream) => {
|
|
2925
|
+
this.onSegmentAppended_(
|
|
2926
|
+
reference.startTime, reference.endTime, stream.type);
|
|
2927
|
+
if (this.abrManager_ && stream.fastSwitching &&
|
|
2928
|
+
reference.isPartial() && reference.isLastPartial()) {
|
|
2929
|
+
this.abrManager_.trySuggestStreams();
|
|
2930
|
+
}
|
|
2909
2931
|
},
|
|
2910
2932
|
onInitSegmentAppended: (position, initSegment) => {
|
|
2911
2933
|
const mediaQuality = initSegment.getMediaQuality();
|
|
@@ -3569,6 +3591,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3569
3591
|
shaka.log.alwaysWarn('A trick play rate of 0 is unsupported!');
|
|
3570
3592
|
return;
|
|
3571
3593
|
}
|
|
3594
|
+
this.trickPlayEventManager_.removeAll();
|
|
3572
3595
|
|
|
3573
3596
|
if (this.video_.paused) {
|
|
3574
3597
|
// Our fast forward is implemented with playbackRate and needs the video
|
|
@@ -3582,6 +3605,22 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3582
3605
|
this.abrManager_.playbackRateChanged(rate);
|
|
3583
3606
|
this.streamingEngine_.setTrickPlay(Math.abs(rate) > 1);
|
|
3584
3607
|
}
|
|
3608
|
+
if (this.isLive()) {
|
|
3609
|
+
this.trickPlayEventManager_.listen(this.video_, 'timeupdate', () => {
|
|
3610
|
+
const currentTime = this.video_.currentTime;
|
|
3611
|
+
const seekRange = this.seekRange();
|
|
3612
|
+
const safeSeekOffset = this.config_.streaming.safeSeekOffset;
|
|
3613
|
+
if (rate > 0) {
|
|
3614
|
+
if (currentTime >= seekRange.end) {
|
|
3615
|
+
this.cancelTrickPlay();
|
|
3616
|
+
}
|
|
3617
|
+
} else {
|
|
3618
|
+
if (currentTime <= (seekRange.start + safeSeekOffset)) {
|
|
3619
|
+
this.cancelTrickPlay();
|
|
3620
|
+
}
|
|
3621
|
+
}
|
|
3622
|
+
});
|
|
3623
|
+
}
|
|
3585
3624
|
}
|
|
3586
3625
|
|
|
3587
3626
|
/**
|
|
@@ -3601,6 +3640,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3601
3640
|
this.abrManager_.playbackRateChanged(defaultPlaybackRate);
|
|
3602
3641
|
this.streamingEngine_.setTrickPlay(false);
|
|
3603
3642
|
}
|
|
3643
|
+
this.trickPlayEventManager_.removeAll();
|
|
3604
3644
|
}
|
|
3605
3645
|
|
|
3606
3646
|
/**
|
|
@@ -4576,13 +4616,16 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
4576
4616
|
// variant yet because we set the load mode before we select the first
|
|
4577
4617
|
// variant to stream.
|
|
4578
4618
|
const variant = this.streamingEngine_.getCurrentVariant();
|
|
4619
|
+
const textStream = this.streamingEngine_.getCurrentTextStream();
|
|
4579
4620
|
|
|
4580
4621
|
if (variant) {
|
|
4581
4622
|
const rate = this.playRateController_ ?
|
|
4582
4623
|
this.playRateController_.getRealRate() : 1;
|
|
4583
4624
|
const variantBandwidth = rate * variant.bandwidth;
|
|
4584
|
-
|
|
4585
|
-
|
|
4625
|
+
let currentStreamBandwidth = variantBandwidth;
|
|
4626
|
+
if (textStream && textStream.bandwidth) {
|
|
4627
|
+
currentStreamBandwidth += (rate * textStream.bandwidth);
|
|
4628
|
+
}
|
|
4586
4629
|
this.stats_.setCurrentStreamBandwidth(currentStreamBandwidth);
|
|
4587
4630
|
}
|
|
4588
4631
|
|
|
@@ -6871,7 +6914,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
6871
6914
|
* @export
|
|
6872
6915
|
*/
|
|
6873
6916
|
// eslint-disable-next-line no-useless-concat
|
|
6874
|
-
shaka.Player.version = 'v4.7.
|
|
6917
|
+
shaka.Player.version = 'v4.7.6' + '-uncompiled'; // x-release-please-version
|
|
6875
6918
|
|
|
6876
6919
|
// Initialize the deprecation system using the version string we just set
|
|
6877
6920
|
// on the player.
|
|
@@ -491,6 +491,11 @@ shaka.text.TtmlTextParser = class {
|
|
|
491
491
|
region.viewportAnchorX = region.viewportAnchorX * 100 /
|
|
492
492
|
globalWidth;
|
|
493
493
|
}
|
|
494
|
+
} else if (!extent) {
|
|
495
|
+
region.width = 100 - region.viewportAnchorX;
|
|
496
|
+
region.widthUnits = shaka.text.CueRegion.units.PERCENTAGE;
|
|
497
|
+
region.height = 100 - region.viewportAnchorY;
|
|
498
|
+
region.heightUnits = shaka.text.CueRegion.units.PERCENTAGE;
|
|
494
499
|
}
|
|
495
500
|
|
|
496
501
|
region.viewportAnchorUnits = percentage || globalWidth != null ?
|
|
@@ -192,25 +192,24 @@ shaka.util.LanguageUtils = class {
|
|
|
192
192
|
const LanguageUtils = shaka.util.LanguageUtils;
|
|
193
193
|
|
|
194
194
|
const privateusePrefix = 'x-';
|
|
195
|
-
const
|
|
196
|
-
|
|
195
|
+
const [languageRegion = '', privateuseSuffix = ''] =
|
|
196
|
+
locale.split(`-${privateusePrefix}`);
|
|
197
|
+
const [languageCode = '', regionCode = ''] = languageRegion.split('-');
|
|
197
198
|
|
|
198
199
|
// We are only going to use the language, the region and the "privateuse" part (as per https://datatracker.ietf.org/doc/html/rfc5646).
|
|
199
200
|
// Anything else is thrown away.
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
const privateuse = components[1] ?
|
|
203
|
-
`${privateusePrefix}${components[1]}` : '';
|
|
201
|
+
const privateuse = privateuseSuffix ?
|
|
202
|
+
`${privateusePrefix}${privateuseSuffix}` : '';
|
|
204
203
|
|
|
205
204
|
// Convert the language to lower case. It is standard for the language code
|
|
206
205
|
// to be in lower case, but it will also make the map look-up easier.
|
|
207
|
-
language =
|
|
206
|
+
let language = languageCode.toLowerCase();
|
|
208
207
|
language = LanguageUtils.isoMap_.get(language) || language;
|
|
209
208
|
|
|
210
209
|
// Convert the region to upper case. It is standard for the region to be in
|
|
211
210
|
// upper case. If there is no upper code, then it will be an empty string
|
|
212
211
|
// and this will be a no-op.
|
|
213
|
-
region =
|
|
212
|
+
const region = regionCode.toUpperCase();
|
|
214
213
|
|
|
215
214
|
return `${region ? `${language}-${region}` : language}${
|
|
216
215
|
privateuse ? `-${privateuse}` : ''}`;
|
package/lib/util/periods.js
CHANGED
|
@@ -724,7 +724,9 @@ shaka.util.PeriodCombiner = class {
|
|
|
724
724
|
// Add the codec of this stream to the output stream's codecs.
|
|
725
725
|
const codecs = new Set(outputStream.codecs.split(','));
|
|
726
726
|
for (const codec of match.codecs.split(',')) {
|
|
727
|
-
|
|
727
|
+
if (codec) {
|
|
728
|
+
codecs.add(codec);
|
|
729
|
+
}
|
|
728
730
|
}
|
|
729
731
|
const PeriodCombiner = shaka.util.PeriodCombiner;
|
|
730
732
|
outputStream.codecs = PeriodCombiner.filterDuplicateCodecs_(
|
|
@@ -1029,6 +1031,10 @@ shaka.util.PeriodCombiner = class {
|
|
|
1029
1031
|
continue;
|
|
1030
1032
|
}
|
|
1031
1033
|
|
|
1034
|
+
if (outputStream.fastSwitching != stream.fastSwitching) {
|
|
1035
|
+
continue;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1032
1038
|
if (!best || isBetterMatch(outputStream, best, stream)) {
|
|
1033
1039
|
best = stream;
|
|
1034
1040
|
}
|
package/lib/util/platform.js
CHANGED
|
@@ -220,6 +220,15 @@ shaka.util.Platform = class {
|
|
|
220
220
|
!shaka.util.Platform.isLegacyEdge();
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
+
/**
|
|
224
|
+
* Check if the current platform is Firefox.
|
|
225
|
+
*
|
|
226
|
+
* @return {boolean}
|
|
227
|
+
*/
|
|
228
|
+
static isFirefox() {
|
|
229
|
+
return shaka.util.Platform.userAgentContains_('Firefox');
|
|
230
|
+
}
|
|
231
|
+
|
|
223
232
|
/**
|
|
224
233
|
* Check if the current platform is from Apple.
|
|
225
234
|
*
|
|
@@ -422,6 +431,15 @@ shaka.util.Platform = class {
|
|
|
422
431
|
return navigator.platform.toLowerCase().includes('windows');
|
|
423
432
|
}
|
|
424
433
|
|
|
434
|
+
/**
|
|
435
|
+
* Return true if the platform is a Android, regardless of the browser.
|
|
436
|
+
*
|
|
437
|
+
* @return {boolean}
|
|
438
|
+
*/
|
|
439
|
+
static isAndroid() {
|
|
440
|
+
return shaka.util.Platform.userAgentContains_('Android');
|
|
441
|
+
}
|
|
442
|
+
|
|
425
443
|
/**
|
|
426
444
|
* Check if the user agent contains a key. This is the best way we know of
|
|
427
445
|
* right now to detect platforms. If there is a better way, please send a
|
package/lib/util/stream_utils.js
CHANGED
|
@@ -371,6 +371,9 @@ shaka.util.StreamUtils = class {
|
|
|
371
371
|
const StreamUtils = shaka.util.StreamUtils;
|
|
372
372
|
const isXboxOne = shaka.util.Platform.isXboxOne();
|
|
373
373
|
|
|
374
|
+
const isFirefoxAndroid = shaka.util.Platform.isFirefox() &&
|
|
375
|
+
shaka.util.Platform.isAndroid();
|
|
376
|
+
|
|
374
377
|
manifest.variants = manifest.variants.filter((variant) => {
|
|
375
378
|
// See: https://github.com/shaka-project/shaka-player/issues/3860
|
|
376
379
|
const video = variant.video;
|
|
@@ -426,6 +429,17 @@ shaka.util.StreamUtils = class {
|
|
|
426
429
|
|
|
427
430
|
const audio = variant.audio;
|
|
428
431
|
|
|
432
|
+
// See: https://github.com/shaka-project/shaka-player/issues/6111
|
|
433
|
+
// It seems that Firefox Android reports that it supports
|
|
434
|
+
// Opus + Widevine, but it is not actually supported.
|
|
435
|
+
// It makes sense to drop early.
|
|
436
|
+
if (isFirefoxAndroid && audio && audio.encrypted &&
|
|
437
|
+
audio.codecs.toLowerCase().includes('opus')) {
|
|
438
|
+
shaka.log.debug('Dropping variant - not compatible with platform',
|
|
439
|
+
StreamUtils.getVariantSummaryString_(variant));
|
|
440
|
+
return false;
|
|
441
|
+
}
|
|
442
|
+
|
|
429
443
|
if (audio) {
|
|
430
444
|
const codecs = StreamUtils.getCorrectAudioCodecs_(audio.codecs);
|
|
431
445
|
const fullType = MimeUtils.getFullOrConvertedType(
|
package/package.json
CHANGED
package/ui/controls.js
CHANGED
|
@@ -650,6 +650,9 @@ shaka.ui.Controls = class extends shaka.util.FakeEventTarget {
|
|
|
650
650
|
* @export
|
|
651
651
|
*/
|
|
652
652
|
isPiPAllowed() {
|
|
653
|
+
if (this.castProxy_.isCasting()) {
|
|
654
|
+
return false;
|
|
655
|
+
}
|
|
653
656
|
if ('documentPictureInPicture' in window &&
|
|
654
657
|
this.config_.preferDocumentPictureInPicture) {
|
|
655
658
|
const video = /** @type {HTMLVideoElement} */(this.localVideo_);
|
package/ui/pip_button.js
CHANGED
|
@@ -98,8 +98,8 @@ shaka.ui.PipButton = class extends shaka.ui.Element {
|
|
|
98
98
|
this.onLeavePictureInPicture_();
|
|
99
99
|
});
|
|
100
100
|
|
|
101
|
-
this.eventManager.listen(this.controls, 'caststatuschanged', (
|
|
102
|
-
this.
|
|
101
|
+
this.eventManager.listen(this.controls, 'caststatuschanged', () => {
|
|
102
|
+
this.onTracksChanged_();
|
|
103
103
|
});
|
|
104
104
|
|
|
105
105
|
this.eventManager.listen(this.player, 'trackschanged', () => {
|
|
@@ -164,25 +164,6 @@ shaka.ui.PipButton = class extends shaka.ui.Element {
|
|
|
164
164
|
this.localization.resolve(currentPipState);
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
-
/**
|
|
168
|
-
* @param {Event} e
|
|
169
|
-
* @private
|
|
170
|
-
*/
|
|
171
|
-
onCastStatusChange_(e) {
|
|
172
|
-
const isCasting = e['newStatus'];
|
|
173
|
-
|
|
174
|
-
if (isCasting) {
|
|
175
|
-
// Picture-in-picture is not applicable if we're casting
|
|
176
|
-
if (this.controls.isPiPAllowed()) {
|
|
177
|
-
shaka.ui.Utils.setDisplay(this.pipButton_, false);
|
|
178
|
-
}
|
|
179
|
-
} else {
|
|
180
|
-
if (this.controls.isPiPAllowed()) {
|
|
181
|
-
shaka.ui.Utils.setDisplay(this.pipButton_, true);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
167
|
|
|
187
168
|
/**
|
|
188
169
|
* Display the picture-in-picture button only when the content contains video.
|
|
@@ -194,6 +175,9 @@ shaka.ui.PipButton = class extends shaka.ui.Element {
|
|
|
194
175
|
async onTracksChanged_() {
|
|
195
176
|
if (!this.controls.isPiPAllowed()) {
|
|
196
177
|
shaka.ui.Utils.setDisplay(this.pipButton_, false);
|
|
178
|
+
if (this.controls.isPiPEnabled()) {
|
|
179
|
+
await this.controls.togglePiP();
|
|
180
|
+
}
|
|
197
181
|
} else if (this.player && this.player.isAudioOnly()) {
|
|
198
182
|
shaka.ui.Utils.setDisplay(this.pipButton_, false);
|
|
199
183
|
if (this.controls.isPiPEnabled()) {
|
|
@@ -44,6 +44,10 @@ shaka.ui.PlaybackRateSelection = class extends shaka.ui.SettingsMenu {
|
|
|
44
44
|
this.updateLocalizedStrings_();
|
|
45
45
|
});
|
|
46
46
|
|
|
47
|
+
this.eventManager.listen(this.player, 'loaded', () => {
|
|
48
|
+
this.updatePlaybackRateSelection_(this.player.getPlaybackRate());
|
|
49
|
+
});
|
|
50
|
+
|
|
47
51
|
this.eventManager.listen(this.player, 'ratechange', () => {
|
|
48
52
|
this.updatePlaybackRateSelection_(this.player.getPlaybackRate());
|
|
49
53
|
});
|