shaka-player 4.7.5 → 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.
@@ -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
@@ -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_ = 0;
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(number, number,
2530
- * !shaka.util.ManifestParserUtils.ContentType),
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(number, number,
2556
- * !shaka.util.ManifestParserUtils.ContentType)} onSegmentAppended
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() && !segment.isLastPartial()) {
703
+ if (segment.isPartial()) {
704
704
  return false;
705
705
  }
706
706
  }
package/lib/player.js CHANGED
@@ -1858,6 +1858,12 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
1858
1858
  'Please use an AbrManager with setCmsdManager function.');
1859
1859
  this.abrManager_.setCmsdManager = () => {};
1860
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
+ }
1861
1867
  this.abrManager_.configure(this.config_.abr);
1862
1868
  }
1863
1869
 
@@ -2915,8 +2921,13 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
2915
2921
  onError: (error) => this.onError_(error),
2916
2922
  onEvent: (event) => this.dispatchEvent(event),
2917
2923
  onManifestUpdate: () => this.onManifestUpdate_(),
2918
- onSegmentAppended: (start, end, contentType) => {
2919
- this.onSegmentAppended_(start, end, contentType);
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
+ }
2920
2931
  },
2921
2932
  onInitSegmentAppended: (position, initSegment) => {
2922
2933
  const mediaQuality = initSegment.getMediaQuality();
@@ -4605,13 +4616,16 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
4605
4616
  // variant yet because we set the load mode before we select the first
4606
4617
  // variant to stream.
4607
4618
  const variant = this.streamingEngine_.getCurrentVariant();
4619
+ const textStream = this.streamingEngine_.getCurrentTextStream();
4608
4620
 
4609
4621
  if (variant) {
4610
4622
  const rate = this.playRateController_ ?
4611
4623
  this.playRateController_.getRealRate() : 1;
4612
4624
  const variantBandwidth = rate * variant.bandwidth;
4613
- // TODO: Should include text bandwidth if it enabled.
4614
- const currentStreamBandwidth = variantBandwidth;
4625
+ let currentStreamBandwidth = variantBandwidth;
4626
+ if (textStream && textStream.bandwidth) {
4627
+ currentStreamBandwidth += (rate * textStream.bandwidth);
4628
+ }
4615
4629
  this.stats_.setCurrentStreamBandwidth(currentStreamBandwidth);
4616
4630
  }
4617
4631
 
@@ -6900,7 +6914,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
6900
6914
  * @export
6901
6915
  */
6902
6916
  // eslint-disable-next-line no-useless-concat
6903
- shaka.Player.version = 'v4.7.5' + '-uncompiled'; // x-release-please-version
6917
+ shaka.Player.version = 'v4.7.6' + '-uncompiled'; // x-release-please-version
6904
6918
 
6905
6919
  // Initialize the deprecation system using the version string we just set
6906
6920
  // on the player.
@@ -1031,6 +1031,10 @@ shaka.util.PeriodCombiner = class {
1031
1031
  continue;
1032
1032
  }
1033
1033
 
1034
+ if (outputStream.fastSwitching != stream.fastSwitching) {
1035
+ continue;
1036
+ }
1037
+
1034
1038
  if (!best || isBetterMatch(outputStream, best, stream)) {
1035
1039
  best = stream;
1036
1040
  }
@@ -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
@@ -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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "shaka-player",
3
3
  "description": "DASH/EME video player library",
4
- "version": "4.7.5",
4
+ "version": "4.7.6",
5
5
  "homepage": "https://github.com/shaka-project/shaka-player",
6
6
  "author": "Google",
7
7
  "maintainers": [
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', (e) => {
102
- this.onCastStatusChange_(e);
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()) {