shaka-player 4.8.10 → 4.9.1

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.
Files changed (66) hide show
  1. package/README.md +5 -0
  2. package/dist/controls.css +1 -1
  3. package/dist/controls.css.map +1 -1
  4. package/dist/deps.js +5 -5
  5. package/dist/locales.js +34 -34
  6. package/dist/shaka-player.compiled.d.ts +39 -18
  7. package/dist/shaka-player.compiled.debug.d.ts +39 -18
  8. package/dist/shaka-player.compiled.debug.externs.js +32 -12
  9. package/dist/shaka-player.compiled.debug.js +638 -579
  10. package/dist/shaka-player.compiled.debug.map +4 -4
  11. package/dist/shaka-player.compiled.externs.js +32 -12
  12. package/dist/shaka-player.compiled.js +1272 -1237
  13. package/dist/shaka-player.compiled.map +4 -4
  14. package/dist/shaka-player.ui.d.ts +39 -18
  15. package/dist/shaka-player.ui.debug.d.ts +39 -18
  16. package/dist/shaka-player.ui.debug.externs.js +43 -23
  17. package/dist/shaka-player.ui.debug.js +668 -609
  18. package/dist/shaka-player.ui.debug.map +4 -4
  19. package/dist/shaka-player.ui.externs.js +43 -23
  20. package/dist/shaka-player.ui.js +1487 -1451
  21. package/dist/shaka-player.ui.map +4 -4
  22. package/externs/shaka/manifest.js +11 -1
  23. package/externs/shaka/offline.js +3 -0
  24. package/externs/shaka/player.js +105 -12
  25. package/externs/tizen.js +1 -1
  26. package/lib/abr/simple_abr_manager.js +5 -0
  27. package/lib/ads/media_tailor_ad.js +11 -0
  28. package/lib/ads/media_tailor_ad_manager.js +37 -3
  29. package/lib/dash/dash_parser.js +655 -46
  30. package/lib/dash/mpd_utils.js +7 -8
  31. package/lib/dash/segment_template.js +65 -10
  32. package/lib/hls/hls_parser.js +92 -34
  33. package/lib/media/content_workarounds.js +4 -2
  34. package/lib/media/drm_engine.js +274 -40
  35. package/lib/media/manifest_filterer.js +2 -2
  36. package/lib/media/media_source_engine.js +66 -31
  37. package/lib/media/segment_utils.js +14 -3
  38. package/lib/mss/mss_parser.js +2 -0
  39. package/lib/net/http_plugin_utils.js +2 -1
  40. package/lib/net/networking_engine.js +14 -0
  41. package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
  42. package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
  43. package/lib/offline/manifest_converter.js +2 -0
  44. package/lib/offline/storage.js +1 -0
  45. package/lib/player.js +220 -14
  46. package/lib/polyfill/media_capabilities.js +10 -35
  47. package/lib/transmuxer/aac_transmuxer.js +4 -2
  48. package/lib/transmuxer/ac3_transmuxer.js +2 -1
  49. package/lib/transmuxer/ec3_transmuxer.js +2 -1
  50. package/lib/transmuxer/mp3_transmuxer.js +4 -2
  51. package/lib/transmuxer/mpeg_ts_transmuxer.js +2 -1
  52. package/lib/transmuxer/mss_transmuxer.js +4 -2
  53. package/lib/transmuxer/ts_transmuxer.js +44 -24
  54. package/lib/util/config_utils.js +74 -6
  55. package/lib/util/error.js +17 -8
  56. package/lib/util/mp4_box_parsers.js +23 -2
  57. package/lib/util/periods.js +51 -28
  58. package/lib/util/platform.js +3 -1
  59. package/lib/util/player_configuration.js +20 -8
  60. package/lib/util/stream_utils.js +62 -30
  61. package/lib/util/tXml.js +74 -6
  62. package/package.json +2 -2
  63. package/support.html +1 -0
  64. package/ui/controls.js +4 -0
  65. package/ui/less/ad_controls.less +2 -1
  66. package/ui/resolution_selection.js +12 -3
@@ -41,6 +41,7 @@ shaka.media.SegmentUtils = class {
41
41
  sampleRate: null,
42
42
  closedCaptions: new Map(),
43
43
  videoRange: null,
44
+ colorGamut: null,
44
45
  };
45
46
  }
46
47
 
@@ -125,6 +126,7 @@ shaka.media.SegmentUtils = class {
125
126
  sampleRate: null,
126
127
  closedCaptions: closedCaptions,
127
128
  videoRange: null,
129
+ colorGamut: null,
128
130
  };
129
131
  }
130
132
 
@@ -199,6 +201,8 @@ shaka.media.SegmentUtils = class {
199
201
  let sampleRate = null;
200
202
  /** @type {?string} */
201
203
  let realVideoRange = null;
204
+ /** @type {?string} */
205
+ let realColorGamut = null;
202
206
 
203
207
  /** @type {?string} */
204
208
  let baseBox;
@@ -371,8 +375,10 @@ shaka.media.SegmentUtils = class {
371
375
  })
372
376
 
373
377
  .box('colr', (box) => {
374
- const {videoRange} = shaka.util.Mp4BoxParsers.parseCOLR(box.reader);
378
+ const {videoRange, colorGamut} =
379
+ shaka.util.Mp4BoxParsers.parseCOLR(box.reader);
375
380
  realVideoRange = videoRange;
381
+ realColorGamut = colorGamut;
376
382
  })
377
383
 
378
384
  .parse(initData || data, /* partialOkay= */ true);
@@ -404,6 +410,7 @@ shaka.media.SegmentUtils = class {
404
410
  sampleRate: sampleRate,
405
411
  closedCaptions: closedCaptions,
406
412
  videoRange: realVideoRange,
413
+ colorGamut: realColorGamut,
407
414
  };
408
415
  }
409
416
 
@@ -465,7 +472,9 @@ shaka.media.SegmentUtils = class {
465
472
  return codecs;
466
473
  }
467
474
  const dolbyVision = codecs.find((codec) => {
468
- return codec.startsWith('dvh1.') || codec.startsWith('dvhe.');
475
+ return codec.startsWith('dvh1.') ||
476
+ codec.startsWith('dvhe.') ||
477
+ codec.startsWith('dav1.');
469
478
  });
470
479
  if (!dolbyVision) {
471
480
  return codecs;
@@ -518,7 +527,8 @@ shaka.media.SegmentUtils = class {
518
527
  * channelCount: ?number,
519
528
  * sampleRate: ?number,
520
529
  * closedCaptions: Map.<string, string>,
521
- * videoRange: ?string
530
+ * videoRange: ?string,
531
+ * colorGamut: ?string
522
532
  * }}
523
533
  *
524
534
  * @property {string} type
@@ -531,5 +541,6 @@ shaka.media.SegmentUtils = class {
531
541
  * @property {?number} sampleRate
532
542
  * @property {Map.<string, string>} closedCaptions
533
543
  * @property {?string} videoRange
544
+ * @property {?string} colorGamut
534
545
  */
535
546
  shaka.media.SegmentUtils.BasicInfo;
@@ -419,6 +419,7 @@ shaka.mss.MssParser = class {
419
419
  ignoreManifestTimestampsInSegmentsMode: false,
420
420
  type: shaka.media.ManifestParser.MSS,
421
421
  serviceDescription: null,
422
+ nextUrl: null,
422
423
  };
423
424
 
424
425
  // This is the first point where we have a meaningful presentation start
@@ -570,6 +571,7 @@ shaka.mss.MssParser = class {
570
571
  spatialAudio: false,
571
572
  closedCaptions: null,
572
573
  hdr: undefined,
574
+ colorGamut: undefined,
573
575
  videoLayout: undefined,
574
576
  tilesLayout: undefined,
575
577
  matchedStreams: [],
@@ -58,7 +58,8 @@ shaka.net.HttpPluginUtils = class {
58
58
  status,
59
59
  responseText,
60
60
  headers,
61
- requestType);
61
+ requestType,
62
+ responseURL || uri);
62
63
  }
63
64
  }
64
65
  };
@@ -96,10 +96,21 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
96
96
  /** @private {?shaka.net.NetworkingEngine.OnResponse} */
97
97
  this.onResponse_ = onResponse || null;
98
98
 
99
+ /** @private {boolean} */
100
+ this.forceHTTP_ = false;
101
+
99
102
  /** @private {boolean} */
100
103
  this.forceHTTPS_ = false;
101
104
  }
102
105
 
106
+ /**
107
+ * @param {boolean} forceHTTP
108
+ * @export
109
+ */
110
+ setForceHTTP(forceHTTP) {
111
+ this.forceHTTP_ = forceHTTP;
112
+ }
113
+
103
114
  /**
104
115
  * @param {boolean} forceHTTPS
105
116
  * @export
@@ -463,6 +474,9 @@ shaka.net.NetworkingEngine = class extends shaka.util.FakeEventTarget {
463
474
  */
464
475
  send_(type, request, context, backoff, index, lastError,
465
476
  numBytesRemainingObj) {
477
+ if (this.forceHTTP_) {
478
+ request.uris[index] = request.uris[index].replace('https://', 'http://');
479
+ }
466
480
  if (this.forceHTTPS_) {
467
481
  request.uris[index] = request.uris[index].replace('http://', 'https://');
468
482
  }
@@ -158,6 +158,7 @@ shaka.offline.indexeddb.V1StorageCell = class
158
158
  frameRate: old.frameRate,
159
159
  pixelAspectRatio: undefined,
160
160
  hdr: undefined,
161
+ colorGamut: undefined,
161
162
  videoLayout: undefined,
162
163
  kind: old.kind,
163
164
  language: old.language,
@@ -107,6 +107,7 @@ shaka.offline.indexeddb.V2StorageCell = class
107
107
  frameRate: old.frameRate,
108
108
  pixelAspectRatio: old.pixelAspectRatio,
109
109
  hdr: undefined,
110
+ colorGamut: undefined,
110
111
  videoLayout: undefined,
111
112
  kind: old.kind,
112
113
  language: old.language,
@@ -93,6 +93,7 @@ shaka.offline.ManifestConverter = class {
93
93
  ignoreManifestTimestampsInSegmentsMode: false,
94
94
  type: manifestDB.type || shaka.media.ManifestParser.UNKNOWN,
95
95
  serviceDescription: null,
96
+ nextUrl: null,
96
97
  };
97
98
  }
98
99
 
@@ -191,6 +192,7 @@ shaka.offline.ManifestConverter = class {
191
192
  frameRate: streamDB.frameRate,
192
193
  pixelAspectRatio: streamDB.pixelAspectRatio,
193
194
  hdr: streamDB.hdr,
195
+ colorGamut: streamDB.colorGamut,
194
196
  videoLayout: streamDB.videoLayout,
195
197
  kind: streamDB.kind,
196
198
  encrypted: streamDB.encrypted,
@@ -1316,6 +1316,7 @@ shaka.offline.Storage = class {
1316
1316
  frameRate: stream.frameRate,
1317
1317
  pixelAspectRatio: stream.pixelAspectRatio,
1318
1318
  hdr: stream.hdr,
1319
+ colorGamut: stream.colorGamut,
1319
1320
  videoLayout: stream.videoLayout,
1320
1321
  kind: stream.kind,
1321
1322
  language: stream.language,
package/lib/player.js CHANGED
@@ -582,6 +582,12 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
582
582
  */
583
583
  this.trickPlayEventManager_ = new shaka.util.EventManager();
584
584
 
585
+ /**
586
+ * For listeners scoped to the lifetime of the ad manager.
587
+ * @private {shaka.util.EventManager}
588
+ */
589
+ this.adManagerEventManager_ = new shaka.util.EventManager();
590
+
585
591
  /** @private {shaka.net.NetworkingEngine} */
586
592
  this.networkingEngine_ = null;
587
593
 
@@ -708,7 +714,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
708
714
  */
709
715
  this.lastTextFactory_;
710
716
 
711
- /** @private {{width: number, height: number}} */
717
+ /** @private {shaka.extern.Resolution} */
712
718
  this.maxHwRes_ = {width: Infinity, height: Infinity};
713
719
 
714
720
  /** @private {!shaka.media.ManifestFilterer} */
@@ -758,14 +764,78 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
758
764
  this.cmsdManager_ = this.createCmsd_();
759
765
 
760
766
  this.networkingEngine_ = this.createNetworkingEngine();
767
+ this.networkingEngine_.setForceHTTP(this.config_.streaming.forceHTTP);
761
768
  this.networkingEngine_.setForceHTTPS(this.config_.streaming.forceHTTPS);
762
769
 
763
770
  /** @private {shaka.extern.IAdManager} */
764
771
  this.adManager_ = null;
765
772
 
773
+ /** @private {?shaka.media.PreloadManager} */
774
+ this.preloadDueAdManager_ = null;
775
+
776
+ /** @private {HTMLMediaElement} */
777
+ this.preloadDueAdManagerVideo_ = null;
778
+
779
+ /** @private {shaka.util.Timer} */
780
+ this.preloadDueAdManagerTimer_ = new shaka.util.Timer(async () => {
781
+ if (this.preloadDueAdManager_) {
782
+ goog.asserts.assert(this.preloadDueAdManagerVideo_, 'Must have video');
783
+ await this.attach(
784
+ this.preloadDueAdManagerVideo_, /* initializeMediaSource= */ true);
785
+ await this.load(this.preloadDueAdManager_);
786
+ this.preloadDueAdManagerVideo_.play();
787
+ this.preloadDueAdManager_ = null;
788
+ }
789
+ });
790
+
766
791
  if (shaka.Player.adManagerFactory_) {
767
792
  this.adManager_ = shaka.Player.adManagerFactory_();
768
793
  this.adManager_.configure(this.config_.ads);
794
+
795
+ // Note: we don't use shaka.ads.AdManager.AD_STARTED to avoid add a
796
+ // optional module in the player.
797
+ this.adManagerEventManager_.listen(
798
+ this.adManager_, 'ad-started', async (e) => {
799
+ if (this.config_.ads.supportsMultipleMediaElements) {
800
+ return;
801
+ }
802
+ const event = /** @type {?google.ima.AdEvent} */
803
+ (e['originalEvent']);
804
+ if (!event) {
805
+ return;
806
+ }
807
+ const contentPauseRequested =
808
+ google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED;
809
+ if (event.type != contentPauseRequested) {
810
+ return;
811
+ }
812
+ this.preloadDueAdManagerTimer_.stop();
813
+ if (!this.preloadDueAdManager_) {
814
+ this.preloadDueAdManagerVideo_ = this.video_;
815
+ this.preloadDueAdManager_ =
816
+ await this.detachAndSavePreload(true);
817
+ }
818
+ });
819
+
820
+ // Note: we don't use shaka.ads.AdManager.AD_STOPPED to avoid add a
821
+ // optional module in the player.
822
+ this.adManagerEventManager_.listen(
823
+ this.adManager_, 'ad-stopped', (e) => {
824
+ if (this.config_.ads.supportsMultipleMediaElements) {
825
+ return;
826
+ }
827
+ const event = /** @type {?google.ima.AdEvent} */
828
+ (e['originalEvent']);
829
+ if (!event) {
830
+ return;
831
+ }
832
+ const contentResumeRequested =
833
+ google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED;
834
+ if (event.type != contentResumeRequested) {
835
+ return;
836
+ }
837
+ this.preloadDueAdManagerTimer_.tickAfter(0.1);
838
+ });
769
839
  }
770
840
 
771
841
  // If the browser comes back online after being offline, then try to play
@@ -779,6 +849,9 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
779
849
  this.checkVariantsTimer_ =
780
850
  new shaka.util.Timer(() => this.checkVariants_());
781
851
 
852
+ /** @private {?shaka.media.PreloadManager} */
853
+ this.preloadNextUrl_ = null;
854
+
782
855
  // Even though |attach| will start in later interpreter cycles, it should be
783
856
  // the LAST thing we do in the constructor because conceptually it relies on
784
857
  // player having been initialized.
@@ -913,6 +986,10 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
913
986
  this.trickPlayEventManager_.release();
914
987
  this.trickPlayEventManager_ = null;
915
988
  }
989
+ if (this.adManagerEventManager_) {
990
+ this.adManagerEventManager_.release();
991
+ this.adManagerEventManager_ = null;
992
+ }
916
993
 
917
994
  this.abrManagerFactory_ = null;
918
995
  this.config_ = null;
@@ -1030,10 +1107,15 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
1030
1107
  }
1031
1108
  const manifest = shaka.media.ManifestParser.probeSupport();
1032
1109
  const media = shaka.media.MediaSourceEngine.probeSupport();
1110
+ const hardwareResolution =
1111
+ await shaka.util.Platform.detectMaxHardwareResolution();
1112
+
1113
+ /** @type {shaka.extern.SupportType} */
1033
1114
  const ret = {
1034
- manifest: manifest,
1035
- media: media,
1036
- drm: drm,
1115
+ manifest,
1116
+ media,
1117
+ drm,
1118
+ hardwareResolution,
1037
1119
  };
1038
1120
 
1039
1121
  const plugins = shaka.Player.supportPlugins_;
@@ -1301,6 +1383,15 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
1301
1383
  this.adManager_.onAssetUnload();
1302
1384
  }
1303
1385
 
1386
+ if (this.preloadDueAdManager_ && !keepAdManager) {
1387
+ this.preloadDueAdManager_.destroy();
1388
+ this.preloadDueAdManager_ = null;
1389
+ }
1390
+
1391
+ if (!keepAdManager) {
1392
+ this.preloadDueAdManagerTimer_.stop();
1393
+ }
1394
+
1304
1395
  if (this.cmsdManager_) {
1305
1396
  this.cmsdManager_.reset();
1306
1397
  }
@@ -1332,6 +1423,14 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
1332
1423
  this.drmEngine_ = null;
1333
1424
  }
1334
1425
 
1426
+ if (this.preloadNextUrl_ &&
1427
+ this.assetUri_ != this.preloadNextUrl_.getAssetUri()) {
1428
+ if (!this.preloadNextUrl_.isDestroyed()) {
1429
+ this.preloadNextUrl_.destroy();
1430
+ }
1431
+ this.preloadNextUrl_ = null;
1432
+ }
1433
+
1335
1434
  this.assetUri_ = null;
1336
1435
  this.mimeType_ = null;
1337
1436
  this.bufferObserver_ = null;
@@ -1351,6 +1450,15 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
1351
1450
  }
1352
1451
  }
1353
1452
 
1453
+ // On some devices, cached MediaKeySystemAccess objects may corrupt
1454
+ // after several playbacks, and they are not able anymore to properly
1455
+ // create MediaKeys objects. To prevent it, clear the cache after
1456
+ // each playback.
1457
+ if (this.config_.streaming.clearDecodingCache) {
1458
+ shaka.util.StreamUtils.clearDecodingConfigCache();
1459
+ shaka.media.DrmEngine.clearMediaKeySystemAccessMap();
1460
+ }
1461
+
1354
1462
  this.manifest_ = null;
1355
1463
  this.stats_ = new shaka.util.Stats(); // Replace with a clean object.
1356
1464
  this.lastTextFactory_ = null;
@@ -1426,6 +1534,9 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
1426
1534
  }
1427
1535
 
1428
1536
  if (this.assetUri_) {
1537
+ // Note: This is used to avoid the destruction of the nextUrl
1538
+ // preloadManager that can be the current one.
1539
+ this.assetUri_ = assetUri;
1429
1540
  await this.unload(/* initializeMediaSource= */ false);
1430
1541
  }
1431
1542
 
@@ -1627,6 +1738,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
1627
1738
  // properly destroyed or released.
1628
1739
  await preloadManager.destroy();
1629
1740
  }
1741
+ this.preloadNextUrl_ = null;
1630
1742
  }
1631
1743
  }
1632
1744
 
@@ -1664,6 +1776,34 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
1664
1776
  */
1665
1777
  async unloadAndSavePreload(
1666
1778
  initializeMediaSource = true, keepAdManager = false) {
1779
+ const preloadManager = await this.savePreload_();
1780
+ await this.unload(initializeMediaSource, keepAdManager);
1781
+ return preloadManager;
1782
+ }
1783
+
1784
+ /**
1785
+ * Detach the player from the current media element, if any, and returns a
1786
+ * PreloadManager that contains the loaded manifest of that asset, if any.
1787
+ * Allows for the asset to be re-loaded by this player faster, in the future.
1788
+ * When in src= mode, this detach but does not make a PreloadManager.
1789
+ * Leaves the player in a state where it cannot play media, until it has been
1790
+ * attached to something else.
1791
+ *
1792
+ * @param {boolean=} keepAdManager
1793
+ * @return {!Promise.<?shaka.media.PreloadManager>}
1794
+ * @export
1795
+ */
1796
+ async detachAndSavePreload(keepAdManager = false) {
1797
+ const preloadManager = await this.savePreload_();
1798
+ await this.detach(keepAdManager);
1799
+ return preloadManager;
1800
+ }
1801
+
1802
+ /**
1803
+ * @return {!Promise.<?shaka.media.PreloadManager>}
1804
+ * @private
1805
+ */
1806
+ async savePreload_() {
1667
1807
  let preloadManager = null;
1668
1808
  if (this.manifest_ && this.parser_ && this.parserFactory_ &&
1669
1809
  this.assetUri_) {
@@ -1698,7 +1838,6 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
1698
1838
  this.abrManager_ = null;
1699
1839
  this.abrManagerFactory_ = null;
1700
1840
  }
1701
- await this.unload(initializeMediaSource, keepAdManager);
1702
1841
  return preloadManager;
1703
1842
  }
1704
1843
 
@@ -2376,6 +2515,28 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
2376
2515
  this.loadEventManager_.listen(
2377
2516
  mediaElement, 'timeupdate', onVideoProgress);
2378
2517
  this.onVideoProgress_();
2518
+ if (this.manifest_.nextUrl) {
2519
+ if (this.config_.streaming.preloadNextUrlWindow > 0) {
2520
+ const onTimeUpdate = async () => {
2521
+ const timeToEnd = this.video_.duration - this.video_.currentTime;
2522
+ if (!isNaN(timeToEnd)) {
2523
+ if (timeToEnd <= this.config_.streaming.preloadNextUrlWindow) {
2524
+ this.loadEventManager_.unlisten(
2525
+ mediaElement, 'timeupdate', onTimeUpdate);
2526
+ goog.asserts.assert(this.manifest_.nextUrl,
2527
+ 'this.manifest_.nextUrl should be valid.');
2528
+ this.preloadNextUrl_ =
2529
+ await this.preload(this.manifest_.nextUrl);
2530
+ }
2531
+ }
2532
+ };
2533
+ this.loadEventManager_.listen(
2534
+ mediaElement, 'timeupdate', onTimeUpdate);
2535
+ }
2536
+ this.loadEventManager_.listen(mediaElement, 'ended', () => {
2537
+ this.load(this.preloadNextUrl_ || this.manifest_.nextUrl);
2538
+ });
2539
+ }
2379
2540
  }
2380
2541
 
2381
2542
  if (this.adManager_) {
@@ -3413,10 +3574,12 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
3413
3574
  }
3414
3575
 
3415
3576
  // If lowLatencyMode is enabled, and inaccurateManifestTolerance and
3416
- // rebufferingGoal and segmentPrefetchLimit and baseDelay are not
3417
- // specified, set inaccurateManifestTolerance to 0 and rebufferingGoal
3418
- // to 0.01 and segmentPrefetchLimit to 2 and updateIntervalSeconds to
3419
- // 0.1 and baseDelay to 100 by default for low latency streaming.
3577
+ // rebufferingGoal and segmentPrefetchLimit and baseDelay and
3578
+ // autoCorrectDrift and maxDisabledTime are not specified, set
3579
+ // inaccurateManifestTolerance to 0 and rebufferingGoal to 0.01 and
3580
+ // segmentPrefetchLimit to 2 and updateIntervalSeconds to 0.1 and and
3581
+ // baseDelay to 100 and autoCorrectDrift to false and maxDisabledTime
3582
+ // to 1 by default for low latency streaming.
3420
3583
  if (config['streaming'] && config['streaming']['lowLatencyMode']) {
3421
3584
  if (config['streaming']['inaccurateManifestTolerance'] == undefined) {
3422
3585
  config['streaming']['inaccurateManifestTolerance'] = 0;
@@ -3430,6 +3593,9 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
3430
3593
  if (config['streaming']['updateIntervalSeconds'] == undefined) {
3431
3594
  config['streaming']['updateIntervalSeconds'] = 0.1;
3432
3595
  }
3596
+ if (config['streaming']['maxDisabledTime'] == undefined) {
3597
+ config['streaming']['maxDisabledTime'] = 1;
3598
+ }
3433
3599
  if (config['streaming']['retryParameters'] == undefined) {
3434
3600
  config['streaming']['retryParameters'] = {};
3435
3601
  }
@@ -3439,6 +3605,12 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
3439
3605
  if (config['manifest'] == undefined) {
3440
3606
  config['manifest'] = {};
3441
3607
  }
3608
+ if (config['manifest']['dash'] == undefined) {
3609
+ config['manifest']['dash'] = {};
3610
+ }
3611
+ if (config['manifest']['dash']['autoCorrectDrift'] == undefined) {
3612
+ config['manifest']['dash']['autoCorrectDrift'] = false;
3613
+ }
3442
3614
  if (config['manifest']['retryParameters'] == undefined) {
3443
3615
  config['manifest']['retryParameters'] = {};
3444
3616
  }
@@ -3513,6 +3685,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
3513
3685
  }
3514
3686
  }
3515
3687
  if (this.networkingEngine_) {
3688
+ this.networkingEngine_.setForceHTTP(this.config_.streaming.forceHTTP);
3516
3689
  this.networkingEngine_.setForceHTTPS(this.config_.streaming.forceHTTPS);
3517
3690
  }
3518
3691
 
@@ -3600,6 +3773,24 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
3600
3773
  return ret;
3601
3774
  }
3602
3775
 
3776
+ /**
3777
+ * Return a copy of the current non default configuration. Modifications of
3778
+ * the returned value will not affect the Player's active configuration.
3779
+ * You must call <code>player.configure()</code> to make changes.
3780
+ *
3781
+ * @return {!Object}
3782
+ * @export
3783
+ */
3784
+ getNonDefaultConfiguration() {
3785
+ goog.asserts.assert(this.config_, 'Config must not be null!');
3786
+
3787
+ const ret = this.defaultConfig_();
3788
+ shaka.util.PlayerConfiguration.mergeConfigObjects(
3789
+ ret, this.config_, this.defaultConfig_());
3790
+ return shaka.util.ConfigUtils.getDifferenceFromConfigObjects(
3791
+ this.config_, this.defaultConfig_());
3792
+ }
3793
+
3603
3794
  /**
3604
3795
  * Return a reference to the current configuration. Modifications to the
3605
3796
  * returned value will affect the Player's active configuration. This method
@@ -5734,6 +5925,9 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
5734
5925
  error.code == shaka.util.Error.Code.HTTP_ERROR) {
5735
5926
  // These errors can be near-instant, so delay a bit before retrying.
5736
5927
  retryDelaySeconds = 1;
5928
+ if (this.config_.streaming.lowLatencyMode) {
5929
+ retryDelaySeconds = 0.1;
5930
+ }
5737
5931
  } else if (error.code == shaka.util.Error.Code.TIMEOUT) {
5738
5932
  // We already waited for a timeout, so retry quickly.
5739
5933
  retryDelaySeconds = 0.1;
@@ -6027,8 +6221,14 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
6027
6221
  // serviceDescription must override if it is defined in the MPD and
6028
6222
  // liveSync configuration is not set.
6029
6223
  if (this.manifest_ && this.manifest_.serviceDescription) {
6030
- liveSyncMaxLatency = this.manifest_.serviceDescription.maxLatency ||
6031
- this.config_.streaming.liveSyncMaxLatency;
6224
+ liveSyncMaxLatency = this.config_.streaming.liveSyncMaxLatency;
6225
+ if (this.manifest_.serviceDescription.targetLatency != null) {
6226
+ liveSyncMaxLatency =
6227
+ this.manifest_.serviceDescription.targetLatency +
6228
+ this.config_.streaming.liveSyncTargetLatencyTolerance;
6229
+ } else if (this.manifest_.serviceDescription.maxLatency != null) {
6230
+ liveSyncMaxLatency = this.manifest_.serviceDescription.maxLatency;
6231
+ }
6032
6232
  liveSyncPlaybackRate =
6033
6233
  this.manifest_.serviceDescription.maxPlaybackRate ||
6034
6234
  this.config_.streaming.liveSyncPlaybackRate;
@@ -6044,8 +6244,14 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
6044
6244
  // serviceDescription must override if it is defined in the MPD and
6045
6245
  // liveSync configuration is not set.
6046
6246
  if (this.manifest_ && this.manifest_.serviceDescription) {
6047
- liveSyncMinLatency = this.manifest_.serviceDescription.minLatency ||
6048
- this.config_.streaming.liveSyncMinLatency;
6247
+ liveSyncMinLatency = this.config_.streaming.liveSyncMinLatency;
6248
+ if (this.manifest_.serviceDescription.targetLatency != null) {
6249
+ liveSyncMinLatency =
6250
+ this.manifest_.serviceDescription.targetLatency -
6251
+ this.config_.streaming.liveSyncTargetLatencyTolerance;
6252
+ } else if (this.manifest_.serviceDescription.minLatency != null) {
6253
+ liveSyncMinLatency = this.manifest_.serviceDescription.minLatency;
6254
+ }
6049
6255
  liveSyncMinPlaybackRate =
6050
6256
  this.manifest_.serviceDescription.minPlaybackRate ||
6051
6257
  this.config_.streaming.liveSyncMinPlaybackRate;
@@ -7240,7 +7446,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
7240
7446
  * @export
7241
7447
  */
7242
7448
  // eslint-disable-next-line no-useless-concat
7243
- shaka.Player.version = 'v4.8.10' + '-uncompiled'; // x-release-please-version
7449
+ shaka.Player.version = 'v4.9.1' + '-uncompiled'; // x-release-please-version
7244
7450
 
7245
7451
  // Initialize the deprecation system using the version string we just set
7246
7452
  // on the player.
@@ -8,6 +8,7 @@ goog.provide('shaka.polyfill.MediaCapabilities');
8
8
 
9
9
  goog.require('shaka.log');
10
10
  goog.require('shaka.media.Capabilities');
11
+ goog.require('shaka.media.DrmEngine');
11
12
  goog.require('shaka.polyfill');
12
13
  goog.require('shaka.util.Platform');
13
14
 
@@ -276,25 +277,22 @@ shaka.polyfill.MediaCapabilities = class {
276
277
  mediaKeySystemConfig.videoCapabilities = videoCapabilities;
277
278
  }
278
279
 
279
- const cacheKey = shaka.polyfill.MediaCapabilities
280
- .generateKeySystemCacheKey_(
281
- videoConfig ? videoConfig.contentType : '',
282
- audioConfig ? audioConfig.contentType : '',
283
- mcapKeySystemConfig.keySystem);
280
+ const videoCodec = videoConfig ? videoConfig.contentType : '';
281
+ const audioCodec = audioConfig ? audioConfig.contentType : '';
282
+ const keySystem = mcapKeySystemConfig.keySystem;
284
283
 
285
284
  /** @type {MediaKeySystemAccess} */
286
285
  let keySystemAccess = null;
287
286
  try {
288
- if (cacheKey in shaka.polyfill.MediaCapabilities
289
- .memoizedMediaKeySystemAccessRequests_) {
290
- keySystemAccess = shaka.polyfill.MediaCapabilities
291
- .memoizedMediaKeySystemAccessRequests_[cacheKey];
287
+ if (shaka.media.DrmEngine.hasMediaKeySystemAccess(
288
+ videoCodec, audioCodec, keySystem)) {
289
+ keySystemAccess = shaka.media.DrmEngine.getMediaKeySystemAccess(
290
+ videoCodec, audioCodec, keySystem);
292
291
  } else {
293
292
  keySystemAccess = await navigator.requestMediaKeySystemAccess(
294
293
  mcapKeySystemConfig.keySystem, [mediaKeySystemConfig]);
295
- shaka.polyfill.MediaCapabilities
296
- .memoizedMediaKeySystemAccessRequests_[cacheKey] =
297
- keySystemAccess;
294
+ shaka.media.DrmEngine.setMediaKeySystemAccess(
295
+ videoCodec, audioCodec, keySystem, keySystemAccess);
298
296
  }
299
297
  } catch (e) {
300
298
  shaka.log.info('navigator.requestMediaKeySystemAccess failed.');
@@ -346,19 +344,6 @@ shaka.polyfill.MediaCapabilities = class {
346
344
  }
347
345
  return result;
348
346
  }
349
-
350
- /**
351
- * A method for generating a key for the MediaKeySystemAccessRequests cache.
352
- *
353
- * @param {!string} videoCodec
354
- * @param {!string} audioCodec
355
- * @param {!string} keySystem
356
- * @return {!string}
357
- * @private
358
- */
359
- static generateKeySystemCacheKey_(videoCodec, audioCodec, keySystem) {
360
- return `${videoCodec}#${audioCodec}#${keySystem}`;
361
- }
362
347
  };
363
348
 
364
349
  /**
@@ -371,16 +356,6 @@ shaka.polyfill.MediaCapabilities = class {
371
356
  */
372
357
  shaka.polyfill.MediaCapabilities.originalMcap = null;
373
358
 
374
- /**
375
- * A cache that stores the MediaKeySystemAccess result of calling
376
- * `navigator.requestMediaKeySystemAccess` by a key combination of
377
- * video/audio codec and key system string.
378
- *
379
- * @type {(Object<(!string), (!MediaKeySystemAccess)>)}
380
- * @export
381
- */
382
- shaka.polyfill.MediaCapabilities.memoizedMediaKeySystemAccessRequests_ = {};
383
-
384
359
  /**
385
360
  * A cache that stores the canDisplayType result of calling
386
361
  * `cast.__platform__.canDisplayType`.
@@ -141,7 +141,8 @@ shaka.transmuxer.AacTransmuxer = class {
141
141
  return Promise.reject(new shaka.util.Error(
142
142
  shaka.util.Error.Severity.CRITICAL,
143
143
  shaka.util.Error.Category.MEDIA,
144
- shaka.util.Error.Code.TRANSMUXING_FAILED));
144
+ shaka.util.Error.Code.TRANSMUXING_FAILED,
145
+ reference ? reference.getUris()[0] : null));
145
146
  }
146
147
  stream.audioSamplingRate = info.sampleRate;
147
148
  stream.channelsCount = info.channelCount;
@@ -155,7 +156,8 @@ shaka.transmuxer.AacTransmuxer = class {
155
156
  return Promise.reject(new shaka.util.Error(
156
157
  shaka.util.Error.Severity.CRITICAL,
157
158
  shaka.util.Error.Category.MEDIA,
158
- shaka.util.Error.Code.TRANSMUXING_FAILED));
159
+ shaka.util.Error.Code.TRANSMUXING_FAILED,
160
+ reference ? reference.getUris()[0] : null));
159
161
  }
160
162
  const length = header.headerLength + header.frameLength;
161
163
  if (offset + length <= uint8ArrayData.length) {
@@ -144,7 +144,8 @@ shaka.transmuxer.Ac3Transmuxer = class {
144
144
  return Promise.reject(new shaka.util.Error(
145
145
  shaka.util.Error.Severity.CRITICAL,
146
146
  shaka.util.Error.Category.MEDIA,
147
- shaka.util.Error.Code.TRANSMUXING_FAILED));
147
+ shaka.util.Error.Code.TRANSMUXING_FAILED,
148
+ reference ? reference.getUris()[0] : null));
148
149
  }
149
150
  stream.audioSamplingRate = frame.sampleRate;
150
151
  stream.channelsCount = frame.channelCount;