shaka-player 4.7.12 → 4.8.0

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 (120) hide show
  1. package/AUTHORS +1 -0
  2. package/CONTRIBUTORS +1 -0
  3. package/LICENSE +54 -0
  4. package/README.md +22 -1
  5. package/dist/controls.css +1 -1
  6. package/dist/controls.css.map +1 -1
  7. package/dist/deps.js +36 -25
  8. package/dist/locales.js +40 -30
  9. package/dist/shaka-player.compiled.d.ts +196 -46
  10. package/dist/shaka-player.compiled.debug.d.ts +196 -46
  11. package/dist/shaka-player.compiled.debug.externs.js +474 -337
  12. package/dist/shaka-player.compiled.debug.js +992 -871
  13. package/dist/shaka-player.compiled.debug.map +4 -4
  14. package/dist/shaka-player.compiled.externs.js +474 -337
  15. package/dist/shaka-player.compiled.js +1248 -1174
  16. package/dist/shaka-player.compiled.map +4 -4
  17. package/dist/shaka-player.ui.d.ts +259 -49
  18. package/dist/shaka-player.ui.debug.d.ts +259 -49
  19. package/dist/shaka-player.ui.debug.externs.js +591 -376
  20. package/dist/shaka-player.ui.debug.js +1208 -1003
  21. package/dist/shaka-player.ui.debug.map +4 -4
  22. package/dist/shaka-player.ui.externs.js +591 -376
  23. package/dist/shaka-player.ui.js +1533 -1408
  24. package/dist/shaka-player.ui.map +4 -4
  25. package/externs/device_sensor_event.js +18 -0
  26. package/externs/hisense.js +16 -0
  27. package/externs/playstation.js +31 -0
  28. package/externs/shaka/abr_manager.js +3 -1
  29. package/externs/shaka/ads.js +5 -0
  30. package/externs/shaka/codecs.js +13 -0
  31. package/externs/shaka/manifest.js +69 -7
  32. package/externs/shaka/net.js +13 -1
  33. package/externs/shaka/offline.js +7 -1
  34. package/externs/shaka/player.js +184 -13
  35. package/externs/shaka/text.js +19 -0
  36. package/externs/tizen.js +41 -0
  37. package/externs/webos.js +19 -0
  38. package/externs/xbox.js +43 -0
  39. package/lib/abr/simple_abr_manager.js +9 -1
  40. package/lib/ads/ad_manager.js +19 -2
  41. package/lib/ads/client_side_ad_manager.js +5 -3
  42. package/lib/ads/media_tailor_ad_manager.js +9 -0
  43. package/lib/cast/cast_receiver.js +0 -14
  44. package/lib/cast/cast_utils.js +1 -0
  45. package/lib/cea/mp4_cea_parser.js +6 -1
  46. package/lib/dash/content_protection.js +97 -53
  47. package/lib/dash/dash_parser.js +240 -179
  48. package/lib/dash/mpd_utils.js +72 -65
  49. package/lib/dash/segment_base.js +35 -22
  50. package/lib/dash/segment_list.js +39 -31
  51. package/lib/dash/segment_template.js +47 -23
  52. package/lib/hls/hls_parser.js +376 -165
  53. package/lib/media/buffering_observer.js +25 -1
  54. package/lib/media/drm_engine.js +91 -71
  55. package/lib/media/manifest_filterer.js +220 -0
  56. package/lib/media/media_source_engine.js +108 -29
  57. package/lib/media/playhead.js +3 -3
  58. package/lib/media/preload_manager.js +827 -0
  59. package/lib/media/presentation_timeline.js +11 -0
  60. package/lib/media/segment_index.js +60 -49
  61. package/lib/media/segment_prefetch.js +140 -43
  62. package/lib/media/segment_reference.js +31 -8
  63. package/lib/media/segment_utils.js +208 -25
  64. package/lib/media/streaming_engine.js +321 -77
  65. package/lib/mss/content_protection.js +31 -25
  66. package/lib/mss/mss_parser.js +78 -55
  67. package/lib/net/networking_engine.js +49 -4
  68. package/lib/offline/indexeddb/v1_storage_cell.js +2 -0
  69. package/lib/offline/indexeddb/v2_storage_cell.js +2 -0
  70. package/lib/offline/manifest_converter.js +10 -3
  71. package/lib/offline/storage.js +5 -3
  72. package/lib/player.js +896 -674
  73. package/lib/polyfill/media_capabilities.js +16 -1
  74. package/lib/text/simple_text_displayer.js +9 -0
  75. package/lib/text/stub_text_displayer.js +7 -0
  76. package/lib/text/text_engine.js +16 -3
  77. package/lib/text/ttml_text_parser.js +116 -114
  78. package/lib/text/ui_text_displayer.js +28 -11
  79. package/lib/text/vtt_text_parser.js +54 -115
  80. package/lib/transmuxer/opus.js +91 -0
  81. package/lib/transmuxer/ts_transmuxer.js +115 -0
  82. package/lib/util/cmcd_manager.js +152 -3
  83. package/lib/util/dom_utils.js +11 -0
  84. package/lib/util/error.js +5 -0
  85. package/lib/util/fake_event.js +2 -0
  86. package/lib/util/manifest_parser_utils.js +97 -3
  87. package/lib/util/mime_utils.js +10 -5
  88. package/lib/util/mp4_box_parsers.js +346 -17
  89. package/lib/util/mp4_generator.js +23 -0
  90. package/lib/util/periods.js +24 -37
  91. package/lib/util/platform.js +161 -9
  92. package/lib/util/player_configuration.js +61 -3
  93. package/lib/util/stats.js +16 -0
  94. package/lib/util/stream_utils.js +350 -277
  95. package/lib/util/string_utils.js +36 -0
  96. package/lib/util/tXml.js +814 -0
  97. package/lib/util/ts_parser.js +50 -0
  98. package/lib/util/xml_utils.js +10 -338
  99. package/package.json +2 -2
  100. package/shaka-player.uncompiled.js +8 -0
  101. package/ui/controls.js +187 -5
  102. package/ui/enums.js +2 -0
  103. package/ui/externs/ui.js +30 -3
  104. package/ui/gl_matrix/matrix_4x4.js +568 -0
  105. package/ui/gl_matrix/matrix_quaternion.js +45 -0
  106. package/ui/less/containers.less +11 -0
  107. package/ui/locales/en-GB.json +2 -0
  108. package/ui/locales/en.json +2 -0
  109. package/ui/locales/es-419.json +2 -0
  110. package/ui/locales/es.json +2 -0
  111. package/ui/locales/source.json +8 -0
  112. package/ui/recenter_vr.js +126 -0
  113. package/ui/resolution_selection.js +25 -5
  114. package/ui/statistics_button.js +12 -0
  115. package/ui/text_selection.js +1 -1
  116. package/ui/toggle_stereoscopic.js +127 -0
  117. package/ui/ui.js +74 -38
  118. package/ui/vr_manager.js +557 -0
  119. package/ui/vr_utils.js +232 -0
  120. package/ui/vr_webgl.js +697 -0
@@ -31,6 +31,7 @@ goog.require('shaka.util.Mp4BoxParsers');
31
31
  goog.require('shaka.util.Mp4Parser');
32
32
  goog.require('shaka.util.Platform');
33
33
  goog.require('shaka.util.PublicPromise');
34
+ goog.require('shaka.util.StreamUtils');
34
35
  goog.require('shaka.util.TsParser');
35
36
  goog.require('shaka.lcevc.Dec');
36
37
 
@@ -237,18 +238,61 @@ shaka.media.MediaSourceEngine = class {
237
238
  * Checks if a certain type is supported.
238
239
  *
239
240
  * @param {shaka.extern.Stream} stream
240
- * @return {boolean}
241
+ * @param {shaka.util.ManifestParserUtils.ContentType} contentType
242
+ * @return {!Promise.<boolean>}
241
243
  */
242
- static isStreamSupported(stream) {
244
+ static async isStreamSupported(stream, contentType) {
245
+ if (stream.createSegmentIndex) {
246
+ await stream.createSegmentIndex();
247
+ }
248
+ if (!stream.segmentIndex) {
249
+ return false;
250
+ }
251
+ if (stream.segmentIndex.isEmpty()) {
252
+ return true;
253
+ }
243
254
  const MimeUtils = shaka.util.MimeUtils;
244
- const fullMimeType = MimeUtils.getFullType(stream.mimeType, stream.codecs);
245
- const extendedMimeType = MimeUtils.getExtendedType(stream);
246
- const fullMimeTypeWithAllCodecs = MimeUtils.getFullTypeWithAllCodecs(
247
- stream.mimeType, stream.codecs);
248
255
  const TransmuxerEngine = shaka.transmuxer.TransmuxerEngine;
249
- return shaka.text.TextEngine.isTypeSupported(fullMimeType) ||
250
- shaka.media.Capabilities.isTypeSupported(extendedMimeType) ||
251
- TransmuxerEngine.isSupported(fullMimeTypeWithAllCodecs, stream.type);
256
+ const ContentType = shaka.util.ManifestParserUtils.ContentType;
257
+ const StreamUtils = shaka.util.StreamUtils;
258
+ const seenCombos = new Set();
259
+ // Check each combination of mimeType and codecs within the segment index.
260
+ // Unfortunately we cannot use fullMimeTypes, as we ALSO need to check the
261
+ // getFullTypeWithAllCodecs (for the sake of the transmuxer) and we have no
262
+ // way of going from a full mimeType to a full mimeType with all codecs.
263
+ // As this function is only called in debug mode, a little inefficiency is
264
+ // acceptable.
265
+ for (const ref of stream.segmentIndex) {
266
+ const mimeType = ref.mimeType || stream.mimeType || '';
267
+ let codecs = ref.codecs || stream.codecs || '';
268
+ // Don't check the same combination of mimetype + codecs twice.
269
+ const combo = mimeType + ':' + codecs;
270
+ if (seenCombos.has(combo)) {
271
+ continue;
272
+ }
273
+ seenCombos.add(combo);
274
+ if (contentType == ContentType.TEXT) {
275
+ const fullMimeType = MimeUtils.getFullType(mimeType, codecs);
276
+ if (!shaka.text.TextEngine.isTypeSupported(fullMimeType)) {
277
+ return false;
278
+ }
279
+ } else {
280
+ if (contentType == ContentType.VIDEO) {
281
+ codecs = StreamUtils.getCorrectVideoCodecs(codecs);
282
+ } else if (contentType == ContentType.AUDIO) {
283
+ codecs = StreamUtils.getCorrectAudioCodecs(codecs);
284
+ }
285
+ const extendedMimeType = MimeUtils.getExtendedType(
286
+ stream, mimeType, codecs);
287
+ const fullMimeType = MimeUtils.getFullTypeWithAllCodecs(
288
+ mimeType, codecs);
289
+ if (!shaka.media.Capabilities.isTypeSupported(extendedMimeType) &&
290
+ !TransmuxerEngine.isSupported(fullMimeType, stream.type)) {
291
+ return false;
292
+ }
293
+ }
294
+ }
295
+ return true;
252
296
  }
253
297
 
254
298
  /**
@@ -451,7 +495,8 @@ shaka.media.MediaSourceEngine = class {
451
495
 
452
496
  for (const contentType of streamsByType.keys()) {
453
497
  const stream = streamsByType.get(contentType);
454
- this.initSourceBuffer_(contentType, stream, stream.codecs);
498
+ // eslint-disable-next-line no-await-in-loop
499
+ await this.initSourceBuffer_(contentType, stream, stream.codecs);
455
500
  if (this.needSplitMuxedContent_) {
456
501
  this.queues_[ContentType.AUDIO] = [];
457
502
  this.queues_[ContentType.VIDEO] = [];
@@ -467,13 +512,15 @@ shaka.media.MediaSourceEngine = class {
467
512
  * @param {shaka.util.ManifestParserUtils.ContentType} contentType
468
513
  * @param {shaka.extern.Stream} stream
469
514
  * @param {string} codecs
515
+ * @return {!Promise}
470
516
  * @private
471
517
  */
472
- initSourceBuffer_(contentType, stream, codecs) {
518
+ async initSourceBuffer_(contentType, stream, codecs) {
473
519
  const ContentType = shaka.util.ManifestParserUtils.ContentType;
474
520
 
475
521
  goog.asserts.assert(
476
- shaka.media.MediaSourceEngine.isStreamSupported(stream),
522
+ await shaka.media.MediaSourceEngine.isStreamSupported(
523
+ stream, contentType),
477
524
  'Type negotiation should happen before MediaSourceEngine.init!');
478
525
 
479
526
  let mimeType = shaka.util.MimeUtils.getFullType(
@@ -490,7 +537,6 @@ shaka.media.MediaSourceEngine = class {
490
537
  const mimeTypeWithAllCodecs =
491
538
  shaka.util.MimeUtils.getFullTypeWithAllCodecs(
492
539
  stream.mimeType, codecs);
493
- const TransmuxerEngine = shaka.transmuxer.TransmuxerEngine;
494
540
  if (needTransmux) {
495
541
  const audioCodec = shaka.util.ManifestParserUtils.guessCodecsSafe(
496
542
  ContentType.AUDIO, (codecs || '').split(','));
@@ -498,12 +544,12 @@ shaka.media.MediaSourceEngine = class {
498
544
  ContentType.VIDEO, (codecs || '').split(','));
499
545
  if (audioCodec && videoCodec) {
500
546
  this.needSplitMuxedContent_ = true;
501
- this.initSourceBuffer_(ContentType.AUDIO, stream, audioCodec);
502
- this.initSourceBuffer_(ContentType.VIDEO, stream, videoCodec);
547
+ await this.initSourceBuffer_(ContentType.AUDIO, stream, audioCodec);
548
+ await this.initSourceBuffer_(ContentType.VIDEO, stream, videoCodec);
503
549
  return;
504
550
  }
505
- const transmuxerPlugin =
506
- TransmuxerEngine.findTransmuxer(mimeTypeWithAllCodecs);
551
+ const transmuxerPlugin = shaka.transmuxer.TransmuxerEngine
552
+ .findTransmuxer(mimeTypeWithAllCodecs);
507
553
  if (transmuxerPlugin) {
508
554
  const transmuxer = transmuxerPlugin();
509
555
  this.transmuxers_[contentType] = transmuxer;
@@ -511,7 +557,7 @@ shaka.media.MediaSourceEngine = class {
511
557
  transmuxer.convertCodecs(contentType, mimeTypeWithAllCodecs);
512
558
  }
513
559
  }
514
- const type = mimeType + this.config_.sourceBufferExtraFeatures;
560
+ const type = this.addExtraFeaturesToMimeType_(mimeType);
515
561
 
516
562
  this.destroyer_.ensureNotDestroyed();
517
563
 
@@ -554,6 +600,9 @@ shaka.media.MediaSourceEngine = class {
554
600
  */
555
601
  configure(config) {
556
602
  this.config_ = config;
603
+ if (this.textEngine_) {
604
+ this.textEngine_.setModifyCueCallback(config.modifyCueCallback);
605
+ }
557
606
  }
558
607
 
559
608
  /**
@@ -575,6 +624,9 @@ shaka.media.MediaSourceEngine = class {
575
624
  reinitText(mimeType, sequenceMode, external) {
576
625
  if (!this.textEngine_) {
577
626
  this.textEngine_ = new shaka.text.TextEngine(this.textDisplayer_);
627
+ if (this.textEngine_) {
628
+ this.textEngine_.setModifyCueCallback(this.config_.modifyCueCallback);
629
+ }
578
630
  }
579
631
  this.textEngine_.initParser(mimeType, sequenceMode,
580
632
  external || this.segmentRelativeVttTiming_, this.manifestType_);
@@ -1689,7 +1741,7 @@ shaka.media.MediaSourceEngine = class {
1689
1741
  if (transmuxer) {
1690
1742
  this.transmuxers_[contentType] = transmuxer;
1691
1743
  }
1692
- const type = mimeType + this.config_.sourceBufferExtraFeatures;
1744
+ const type = this.addExtraFeaturesToMimeType_(mimeType);
1693
1745
  this.sourceBuffers_[contentType].changeType(type);
1694
1746
  this.sourceBufferTypes_[contentType] = mimeType;
1695
1747
  } else {
@@ -1793,16 +1845,22 @@ shaka.media.MediaSourceEngine = class {
1793
1845
 
1794
1846
  const totalOfBuffers = streamsByType.size;
1795
1847
  let numberOfSourceBufferAdded = 0;
1796
- this.eventManager_.listen(sourceBuffers, 'addsourcebuffer', (event) => {
1848
+ const onSourceBufferAdded = () => {
1797
1849
  numberOfSourceBufferAdded++;
1798
1850
  if (numberOfSourceBufferAdded === totalOfBuffers) {
1799
1851
  sourceBufferAdded.resolve();
1852
+ this.eventManager_.unlisten(sourceBuffers, 'addsourcebuffer',
1853
+ onSourceBufferAdded);
1800
1854
  }
1801
- });
1855
+ };
1856
+
1857
+ this.eventManager_.listen(sourceBuffers, 'addsourcebuffer',
1858
+ onSourceBufferAdded);
1802
1859
 
1803
1860
  for (const contentType of streamsByType.keys()) {
1804
1861
  const stream = streamsByType.get(contentType);
1805
- this.initSourceBuffer_(contentType, stream, stream.codecs);
1862
+ // eslint-disable-next-line no-await-in-loop
1863
+ await this.initSourceBuffer_(contentType, stream, stream.codecs);
1806
1864
  if (this.needSplitMuxedContent_) {
1807
1865
  this.queues_[ContentType.AUDIO] = [];
1808
1866
  this.queues_[ContentType.VIDEO] = [];
@@ -1821,7 +1879,12 @@ shaka.media.MediaSourceEngine = class {
1821
1879
  this.destroyer_.ensureNotDestroyed();
1822
1880
 
1823
1881
  this.eventManager_.listenOnce(this.video_, 'canplaythrough', () => {
1824
- this.destroyer_.ensureNotDestroyed();
1882
+ // Don't use ensureNotDestroyed() from this event listener, because
1883
+ // that results in an uncaught exception. Instead, just check the
1884
+ // flag.
1885
+ if (this.destroyer_.destroyed()) {
1886
+ return;
1887
+ }
1825
1888
 
1826
1889
  this.video_.autoplay = previousAutoPlayState;
1827
1890
  if (!previousPausedState) {
@@ -1935,10 +1998,12 @@ shaka.media.MediaSourceEngine = class {
1935
1998
  *
1936
1999
  * @param {shaka.util.ManifestParserUtils.ContentType} contentType
1937
2000
  * @param {shaka.extern.Stream} stream
2001
+ * @param {string} refMimeType
2002
+ * @param {string} refCodecs
1938
2003
  * @return {boolean}
1939
2004
  * @private
1940
2005
  */
1941
- isCodecSwitchNecessary_(contentType, stream) {
2006
+ isCodecSwitchNecessary_(contentType, stream, refMimeType, refCodecs) {
1942
2007
  if (contentType == shaka.util.ManifestParserUtils.ContentType.TEXT) {
1943
2008
  return false;
1944
2009
  }
@@ -1948,8 +2013,7 @@ shaka.media.MediaSourceEngine = class {
1948
2013
  const currentBasicType = MimeUtils.getBasicType(
1949
2014
  this.sourceBufferTypes_[contentType]);
1950
2015
 
1951
- let newMimeType = shaka.util.MimeUtils.getFullType(
1952
- stream.mimeType, stream.codecs);
2016
+ let newMimeType = shaka.util.MimeUtils.getFullType(refMimeType, refCodecs);
1953
2017
  let needTransmux = this.config_.forceTransmux;
1954
2018
  if (!shaka.media.Capabilities.isTypeSupported(newMimeType) ||
1955
2019
  (!this.sequenceMode_ &&
@@ -1958,7 +2022,7 @@ shaka.media.MediaSourceEngine = class {
1958
2022
  }
1959
2023
  const newMimeTypeWithAllCodecs =
1960
2024
  shaka.util.MimeUtils.getFullTypeWithAllCodecs(
1961
- stream.mimeType, stream.codecs);
2025
+ refMimeType, refCodecs);
1962
2026
  const TransmuxerEngine = shaka.transmuxer.TransmuxerEngine;
1963
2027
  if (needTransmux) {
1964
2028
  const transmuxerPlugin =
@@ -1984,10 +2048,12 @@ shaka.media.MediaSourceEngine = class {
1984
2048
  *
1985
2049
  * @param {shaka.util.ManifestParserUtils.ContentType} contentType
1986
2050
  * @param {shaka.extern.Stream} stream
2051
+ * @param {string} mimeType
2052
+ * @param {string} codecs
1987
2053
  * @return {boolean}
1988
2054
  */
1989
- isResetMediaSourceNecessary(contentType, stream) {
1990
- if (!this.isCodecSwitchNecessary_(contentType, stream)) {
2055
+ isResetMediaSourceNecessary(contentType, stream, mimeType, codecs) {
2056
+ if (!this.isCodecSwitchNecessary_(contentType, stream, mimeType, codecs)) {
1991
2057
  return false;
1992
2058
  }
1993
2059
 
@@ -2004,6 +2070,19 @@ shaka.media.MediaSourceEngine = class {
2004
2070
  updateLcevcDec(lcevcDec) {
2005
2071
  this.lcevcDec_ = lcevcDec;
2006
2072
  }
2073
+
2074
+ /**
2075
+ * @param {string} mimeType
2076
+ * @return {string}
2077
+ * @private
2078
+ */
2079
+ addExtraFeaturesToMimeType_(mimeType) {
2080
+ const extraFeatures = this.config_.addExtraFeaturesToSourceBuffer(mimeType);
2081
+ const extendedType = mimeType + extraFeatures;
2082
+ shaka.log.debug('Using full mime type', extendedType);
2083
+
2084
+ return extendedType;
2085
+ }
2007
2086
  };
2008
2087
 
2009
2088
 
@@ -382,10 +382,10 @@ shaka.media.MediaSourcePlayhead = class {
382
382
  seekStart = seekEnd - this.minSeekRange_;
383
383
  }
384
384
 
385
- if (currentTime < seekStart) {
386
- // The seek range has moved past the playhead. Move ahead to catch up.
385
+ if (currentTime < seekStart || currentTime > seekEnd) {
386
+ // playhead is outside of the seekrange. Move playhead to catch up.
387
387
  const targetTime = this.reposition_(currentTime);
388
- shaka.log.info('Jumping forward ' + (targetTime - currentTime) +
388
+ shaka.log.info('Jumping by ' + (targetTime - currentTime) +
389
389
  ' seconds to catch up with the seek range.');
390
390
  this.mediaElement_.currentTime = targetTime;
391
391
  }