shaka-player 4.9.29 → 4.9.30

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.
@@ -1285,11 +1285,13 @@ shaka.dash.DashParser = class {
1285
1285
  for (let i = 0; i < periodNodes.length; i++) {
1286
1286
  const elem = periodNodes[i];
1287
1287
  const next = periodNodes[i + 1];
1288
- const start = /** @type {number} */ (
1288
+ let start = /** @type {number} */ (
1289
1289
  TXml.parseAttr(elem, 'start', TXml.parseDuration, prevEnd));
1290
1290
  const periodId = elem.attributes['id'];
1291
1291
  const givenDuration =
1292
1292
  TXml.parseAttr(elem, 'duration', TXml.parseDuration);
1293
+ start = (i == 0 && start == 0 && this.isTransitionFromDynamicToStatic_) ?
1294
+ seekRangeStart : start;
1293
1295
 
1294
1296
  let periodDuration = null;
1295
1297
  if (next) {
@@ -1299,7 +1301,7 @@ shaka.dash.DashParser = class {
1299
1301
  const nextStart =
1300
1302
  TXml.parseAttr(next, 'start', TXml.parseDuration);
1301
1303
  if (nextStart != null) {
1302
- periodDuration = nextStart - start;
1304
+ periodDuration = nextStart - start + seekRangeStart;
1303
1305
  }
1304
1306
  } else if (presentationDuration != null) {
1305
1307
  // "The Period extends until the Period.start of the next Period, or
@@ -2575,25 +2577,51 @@ shaka.dash.DashParser = class {
2575
2577
  return intValue;
2576
2578
  }
2577
2579
 
2580
+ case 'tag:dolby.com,2015:dash:audio_channel_configuration:2015': {
2581
+ // ETSI TS 103 190-2 v1.2.1, Annex G.3
2582
+ // LSB-to-MSB order
2583
+ const channelCountMapping =
2584
+ [2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 2, 2];
2585
+ const hexValue = parseInt(value, 16);
2586
+ if (!hexValue) { // 0 or NaN
2587
+ shaka.log.warning('Channel parsing failure! ' +
2588
+ 'Ignoring scheme and value', scheme, value);
2589
+ continue;
2590
+ }
2591
+ let numBits = 0;
2592
+ for (let i = 0; i < channelCountMapping.length; i++) {
2593
+ if (hexValue & (1<<i)) {
2594
+ numBits += channelCountMapping[i];
2595
+ }
2596
+ }
2597
+ if (numBits) {
2598
+ return numBits;
2599
+ }
2600
+ continue;
2601
+ }
2602
+
2578
2603
  case 'tag:dolby.com,2014:dash:audio_channel_configuration:2011':
2579
2604
  case 'urn:dolby:dash:audio_channel_configuration:2011': {
2580
- // A hex-encoded 16-bit integer, in which each bit represents a
2581
- // channel.
2582
- let hexValue = parseInt(value, 16);
2605
+ // Defined by https://ott.dolby.com/OnDelKits/DDP/Dolby_Digital_Plus_Online_Delivery_Kit_v1.5/Documentation/Content_Creation/SDM/help_files/topics/ddp_mpeg_dash_c_mpd_auchlconfig.html
2606
+ // keep list in order of the spec; reverse for LSB-to-MSB order
2607
+ const channelCountMapping =
2608
+ [1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1, 2, 1, 1].reverse();
2609
+ const hexValue = parseInt(value, 16);
2583
2610
  if (!hexValue) { // 0 or NaN
2584
2611
  shaka.log.warning('Channel parsing failure! ' +
2585
2612
  'Ignoring scheme and value', scheme, value);
2586
2613
  continue;
2587
2614
  }
2588
- // Count the 1-bits in hexValue.
2589
2615
  let numBits = 0;
2590
- while (hexValue) {
2591
- if (hexValue & 1) {
2592
- ++numBits;
2616
+ for (let i = 0; i < channelCountMapping.length; i++) {
2617
+ if (hexValue & (1<<i)) {
2618
+ numBits += channelCountMapping[i];
2593
2619
  }
2594
- hexValue >>= 1;
2595
2620
  }
2596
- return numBits;
2621
+ if (numBits) {
2622
+ return numBits;
2623
+ }
2624
+ continue;
2597
2625
  }
2598
2626
 
2599
2627
  // Defined by https://dashif.org/identifiers/audio_source_metadata/ and clause 8.2, in ISO/IEC 23001-8.
@@ -778,7 +778,7 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
778
778
  if (currentTimeline.length) {
779
779
  const lastCurrentEntry = currentTimeline[currentTimeline.length - 1];
780
780
  newEntries = info.timeline.filter((entry) => {
781
- return entry.start >= lastCurrentEntry.end;
781
+ return entry.end > lastCurrentEntry.end;
782
782
  });
783
783
  } else {
784
784
  newEntries = info.timeline.slice();
@@ -743,6 +743,17 @@ shaka.media.DrmEngine = class {
743
743
  return;
744
744
  }
745
745
  }
746
+ let duplicate = false;
747
+ this.storedPersistentSessions_.forEach((metadata, sessionId) => {
748
+ if (!duplicate &&
749
+ shaka.util.BufferUtils.equal(initData, metadata.initData)) {
750
+ duplicate = true;
751
+ }
752
+ });
753
+ if (duplicate) {
754
+ shaka.log.debug('Ignoring duplicate init data.');
755
+ return;
756
+ }
746
757
  }
747
758
 
748
759
  // If there are pre-existing sessions that have all been loaded
@@ -116,7 +116,7 @@ shaka.media.MediaSourceEngine = class {
116
116
  /** @private {boolean} */
117
117
  this.playbackHasBegun_ = false;
118
118
 
119
- /** @private {(MediaSource|ManagedMediaSource)} */
119
+ /** @private {MediaSource} */
120
120
  this.mediaSource_ = this.createMediaSource(this.mediaSourceOpen_);
121
121
 
122
122
  /** @private {boolean} */
@@ -175,13 +175,16 @@ shaka.media.MediaSourceEngine = class {
175
175
  * Replaced by unit tests.
176
176
  *
177
177
  * @param {!shaka.util.PublicPromise} p
178
- * @return {!(MediaSource|ManagedMediaSource)}
178
+ * @return {!MediaSource}
179
179
  */
180
180
  createMediaSource(p) {
181
+ /** @type {!MediaSource} */
182
+ let mediaSource;
183
+
181
184
  if (window.ManagedMediaSource) {
182
185
  this.video_.disableRemotePlayback = true;
183
186
 
184
- const mediaSource = new ManagedMediaSource();
187
+ mediaSource = new ManagedMediaSource();
185
188
 
186
189
  this.eventManager_.listen(
187
190
  mediaSource, 'startstreaming', () => {
@@ -192,39 +195,25 @@ shaka.media.MediaSourceEngine = class {
192
195
  mediaSource, 'endstreaming', () => {
193
196
  this.streamingAllowed_ = false;
194
197
  });
195
-
196
- this.eventManager_.listenOnce(
197
- mediaSource, 'sourceopen', () => this.onSourceOpen_(p));
198
-
199
- // Correctly set when playback has begun.
200
- this.eventManager_.listenOnce(this.video_, 'playing', () => {
201
- this.playbackHasBegun_ = true;
202
- });
203
-
204
- this.url_ = shaka.media.MediaSourceEngine.createObjectURL(mediaSource);
205
-
206
- this.video_.src = this.url_;
207
-
208
- return mediaSource;
209
198
  } else {
210
- const mediaSource = new MediaSource();
199
+ mediaSource = new MediaSource();
200
+ }
211
201
 
212
- // Set up MediaSource on the video element.
213
- this.eventManager_.listenOnce(
214
- mediaSource, 'sourceopen', () => this.onSourceOpen_(p));
202
+ // Set up MediaSource on the video element.
203
+ this.eventManager_.listenOnce(
204
+ mediaSource, 'sourceopen', () => this.onSourceOpen_(p));
215
205
 
216
- // Correctly set when playback has begun.
217
- this.eventManager_.listenOnce(this.video_, 'playing', () => {
218
- this.playbackHasBegun_ = true;
219
- });
206
+ // Correctly set when playback has begun.
207
+ this.eventManager_.listenOnce(this.video_, 'playing', () => {
208
+ this.playbackHasBegun_ = true;
209
+ });
220
210
 
221
- // Store the object URL for releasing it later.
222
- this.url_ = shaka.media.MediaSourceEngine.createObjectURL(mediaSource);
211
+ // Store the object URL for releasing it later.
212
+ this.url_ = shaka.media.MediaSourceEngine.createObjectURL(mediaSource);
223
213
 
224
- this.video_.src = this.url_;
214
+ this.video_.src = this.url_;
225
215
 
226
- return mediaSource;
227
- }
216
+ return mediaSource;
228
217
  }
229
218
 
230
219
  /**
@@ -427,7 +427,9 @@ shaka.media.MediaSourcePlayhead = class {
427
427
  // infinite loop on systems where changing currentTime takes a
428
428
  // significant amount of time (e.g. Chromecast).
429
429
  const time = Date.now() / 1000;
430
- if (!this.lastCorrectiveSeek_ || this.lastCorrectiveSeek_ < time - 1) {
430
+ const seekDelay = shaka.util.Platform.isFuchsiaCastDevice() ? 3 : 1;
431
+ if (!this.lastCorrectiveSeek_ ||
432
+ this.lastCorrectiveSeek_ < time - seekDelay) {
431
433
  this.lastCorrectiveSeek_ = time;
432
434
  canCorrectiveSeek = true;
433
435
  }
package/lib/player.js CHANGED
@@ -2803,6 +2803,11 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
2803
2803
  }
2804
2804
  }
2805
2805
  mediaElement.src = playbackUri;
2806
+ // If ManagedMediaSource exists, we've disabled remote playback on our own.
2807
+ // Reenable it so AirPlay can be used via RemotePlayback API.
2808
+ if (this.mediaSourceEngine_ && window.ManagedMediaSource) {
2809
+ mediaElement.disableRemotePlayback = false;
2810
+ }
2806
2811
 
2807
2812
  // Tizen 3 / WebOS won't load anything unless you call load() explicitly,
2808
2813
  // no matter the value of the preload attribute. This is harmful on some
@@ -7530,7 +7535,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
7530
7535
  * @export
7531
7536
  */
7532
7537
  // eslint-disable-next-line no-useless-concat, max-len
7533
- shaka.Player.version = 'v4.9.29' + '-uncompiled'; // x-release-please-version
7538
+ shaka.Player.version = 'v4.9.30' + '-uncompiled'; // x-release-please-version
7534
7539
 
7535
7540
  // Initialize the deprecation system using the version string we just set
7536
7541
  // on the player.
@@ -629,7 +629,7 @@ shaka.util.Platform = class {
629
629
  *
630
630
  * Some devices are known not to support `MediaSource.changeType`
631
631
  * well. These devices should use the reload strategy. If a device
632
- * reports that it supports `changeType` but support it reliabley
632
+ * reports that it supports `changeType` but support it unreliably
633
633
  * it should be added to this list.
634
634
  *
635
635
  * @return {boolean}
@@ -638,7 +638,8 @@ shaka.util.Platform = class {
638
638
  const Platform = shaka.util.Platform;
639
639
  if (Platform.isTizen2() || Platform.isTizen3() || Platform.isTizen4() ||
640
640
  Platform.isTizen5() || Platform.isTizen6() || Platform.isWebOS3() ||
641
- Platform.isWebOS4() || Platform.isWebOS5()) {
641
+ Platform.isWebOS4() || Platform.isWebOS5() || Platform.isPS4() ||
642
+ Platform.isPS5()) {
642
643
  return false;
643
644
  }
644
645
  // Older chromecasts without GoogleTV seem to not support SMOOTH properly.
@@ -11,6 +11,7 @@ goog.require('shaka.abr.SimpleAbrManager');
11
11
  goog.require('shaka.config.AutoShowText');
12
12
  goog.require('shaka.config.CodecSwitchingStrategy');
13
13
  goog.require('shaka.log');
14
+ goog.require('shaka.media.Capabilities');
14
15
  goog.require('shaka.net.NetworkingEngine');
15
16
  goog.require('shaka.util.ConfigUtils');
16
17
  goog.require('shaka.util.FairPlayUtils');
@@ -103,7 +104,8 @@ shaka.util.PlayerConfiguration = class {
103
104
 
104
105
  let codecSwitchingStrategy = shaka.config.CodecSwitchingStrategy.RELOAD;
105
106
  let multiTypeVariantsAllowed = false;
106
- if (shaka.util.Platform.supportsSmoothCodecSwitching()) {
107
+ if (shaka.media.Capabilities.isChangeTypeSupported() &&
108
+ shaka.util.Platform.supportsSmoothCodecSwitching()) {
107
109
  codecSwitchingStrategy = shaka.config.CodecSwitchingStrategy.SMOOTH;
108
110
  multiTypeVariantsAllowed = true;
109
111
  }
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.9.29",
4
+ "version": "4.9.30",
5
5
  "homepage": "https://github.com/shaka-project/shaka-player",
6
6
  "author": "Google",
7
7
  "maintainers": [
package/ui/externs/ui.js CHANGED
@@ -226,7 +226,8 @@ shaka.extern.UIVolumeBarColors;
226
226
  * @property {boolean} seekOnTaps
227
227
  * Indicates whether or not a fast-forward and rewind tap button that seeks
228
228
  * video some seconds.
229
- * Defaults to true.
229
+ * Defaults to true if the browser <code>navigator.maxTouchPoints > 0</code>
230
+ * is true.
230
231
  * @property {number} tapSeekDistance
231
232
  * The time interval, in seconds, to seek when the user presses the left or
232
233
  * right part of the video. If less than or equal to 0,
@@ -72,7 +72,7 @@ shaka.ui.RemoteButton = class extends shaka.ui.Element {
72
72
 
73
73
  shaka.ui.Utils.setDisplay(this.remoteButton_, false);
74
74
 
75
- if (!this.video.remote || this.video.disableRemotePlayback) {
75
+ if (!this.video.remote) {
76
76
  this.remoteButton_.classList.add('shaka-hidden');
77
77
  } else {
78
78
  this.eventManager.listen(
@@ -138,10 +138,11 @@ shaka.ui.RemoteButton = class extends shaka.ui.Element {
138
138
  } else if (this.video.remote.state == 'disconnected') {
139
139
  const handleAvailabilityChange = (availability) => {
140
140
  if (this.player) {
141
+ const disableRemote = this.video.disableRemotePlayback;
141
142
  const loadMode = this.player.getLoadMode();
142
143
  const srcMode = loadMode == shaka.Player.LoadMode.SRC_EQUALS;
143
144
  shaka.ui.Utils.setDisplay(
144
- this.remoteButton_, srcMode && availability);
145
+ this.remoteButton_, srcMode && availability && !disableRemote);
145
146
  } else {
146
147
  shaka.ui.Utils.setDisplay(this.remoteButton_, false);
147
148
  }
package/ui/ui.js CHANGED
@@ -252,7 +252,7 @@ shaka.ui.Overlay = class {
252
252
  fullScreenElement: this.videoContainer_,
253
253
  preferDocumentPictureInPicture: true,
254
254
  showAudioChannelCountVariants: true,
255
- seekOnTaps: true,
255
+ seekOnTaps: navigator.maxTouchPoints > 0,
256
256
  tapSeekDistance: 10,
257
257
  refreshTickInSeconds: 0.125,
258
258
  displayInVrMode: false,
@@ -275,6 +275,9 @@ shaka.ui.Overlay = class {
275
275
  (name) => name != 'play_pause' && name != 'volume');
276
276
  }
277
277
 
278
+ // Set this button here to push it at the end.
279
+ config.overflowMenuButtons.push('save_video_frame');
280
+
278
281
  return config;
279
282
  }
280
283
 
@@ -476,6 +479,8 @@ shaka.ui.Overlay = class {
476
479
  video.removeAttribute('src');
477
480
  }
478
481
 
482
+ await player.attach(shaka.util.Dom.asHTMLMediaElement(video));
483
+
479
484
  for (const elem of video.querySelectorAll('source')) {
480
485
  try { // eslint-disable-next-line no-await-in-loop
481
486
  await ui.getControls().getPlayer().load(elem.getAttribute('src'));
@@ -484,8 +489,6 @@ shaka.ui.Overlay = class {
484
489
  shaka.log.error('Error auto-loading asset', e);
485
490
  }
486
491
  }
487
-
488
- await player.attach(shaka.util.Dom.asHTMLMediaElement(video));
489
492
  }
490
493
 
491
494