shaka-player 3.3.5 → 4.0.2

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 (184) hide show
  1. package/.github/config.yml +1 -0
  2. package/.github/workflows/demo-version-index.yaml +8 -0
  3. package/.github/workflows/release-please.yaml +18 -2
  4. package/.github/workflows/sync-labels.yaml +33 -0
  5. package/.github/workflows/update-issues.yaml +29 -0
  6. package/.github/workflows/validate-pr-title.yaml +35 -0
  7. package/AUTHORS +1 -0
  8. package/CHANGELOG.md +215 -41
  9. package/CONTRIBUTORS +1 -0
  10. package/README.md +14 -11
  11. package/app-engine/demo-version-index/README.md +3 -3
  12. package/app-engine/demo-version-index/app.yaml +27 -1
  13. package/app-engine/demo-version-index/generate.py +164 -0
  14. package/app-engine/demo-version-index/main.py +4 -155
  15. package/app-engine/demo-version-index/requirements.txt +0 -1
  16. package/build/checkversion.py +1 -1
  17. package/build/compiler.py +1 -1
  18. package/build/misspellings.txt +1 -0
  19. package/build/shaka-lab.yaml +0 -2
  20. package/build/types/polyfill +0 -3
  21. package/demo/common/asset.js +17 -1
  22. package/demo/common/assets.js +29 -0
  23. package/demo/common/message_ids.js +6 -3
  24. package/demo/config.js +10 -11
  25. package/demo/custom.js +39 -0
  26. package/demo/demo.less +0 -1
  27. package/demo/demo_utils.js +0 -1
  28. package/demo/locales/en.json +6 -3
  29. package/demo/locales/source.json +22 -10
  30. package/demo/main.js +9 -6
  31. package/demo/search.js +2 -1
  32. package/dist/controls.css +3 -3
  33. package/dist/controls.css.map +1 -1
  34. package/dist/demo.compiled.debug.js +71 -64
  35. package/dist/demo.compiled.debug.map +3 -3
  36. package/dist/demo.compiled.js +71 -64
  37. package/dist/demo.compiled.map +3 -3
  38. package/dist/demo.css +1 -1
  39. package/dist/demo.css.map +1 -1
  40. package/dist/deps.js +17 -20
  41. package/dist/locales.js +33 -31
  42. package/dist/receiver.compiled.debug.js +32 -28
  43. package/dist/receiver.compiled.debug.map +3 -3
  44. package/dist/receiver.compiled.js +32 -28
  45. package/dist/receiver.compiled.map +3 -3
  46. package/dist/shaka-player.compiled.d.ts +311 -314
  47. package/dist/shaka-player.compiled.debug.d.ts +311 -314
  48. package/dist/shaka-player.compiled.debug.externs.js +126 -126
  49. package/dist/shaka-player.compiled.debug.js +430 -484
  50. package/dist/shaka-player.compiled.debug.map +4 -4
  51. package/dist/shaka-player.compiled.externs.js +126 -126
  52. package/dist/shaka-player.compiled.js +829 -845
  53. package/dist/shaka-player.compiled.map +4 -4
  54. package/dist/shaka-player.ui.d.ts +357 -358
  55. package/dist/shaka-player.ui.debug.d.ts +357 -358
  56. package/dist/shaka-player.ui.debug.externs.js +134 -126
  57. package/dist/shaka-player.ui.debug.js +489 -541
  58. package/dist/shaka-player.ui.debug.map +4 -4
  59. package/dist/shaka-player.ui.externs.js +134 -126
  60. package/dist/shaka-player.ui.js +988 -1000
  61. package/dist/shaka-player.ui.map +4 -4
  62. package/docs/tutorials/config.md +0 -2
  63. package/docs/tutorials/drm-config.md +5 -0
  64. package/docs/tutorials/fairplay.md +7 -22
  65. package/docs/tutorials/faq.md +0 -11
  66. package/docs/tutorials/index.json +2 -8
  67. package/docs/tutorials/plugins.md +1 -3
  68. package/docs/tutorials/upgrade.md +85 -11
  69. package/externs/polyfill.js +15 -0
  70. package/externs/shaka/manifest.js +5 -1
  71. package/externs/shaka/net.js +12 -0
  72. package/externs/shaka/offline.js +5 -1
  73. package/externs/shaka/player.js +39 -21
  74. package/externs/shaka/text.js +12 -12
  75. package/externs/sourcebuffer.js +15 -0
  76. package/lib/abr/simple_abr_manager.js +2 -1
  77. package/lib/ads/client_side_ad.js +13 -2
  78. package/lib/ads/client_side_ad_manager.js +22 -4
  79. package/lib/cast/cast_utils.js +0 -1
  80. package/lib/dash/content_protection.js +85 -5
  81. package/lib/dash/dash_parser.js +1 -0
  82. package/lib/hls/hls_parser.js +390 -747
  83. package/lib/hls/manifest_text_parser.js +2 -3
  84. package/lib/media/drm_engine.js +105 -37
  85. package/lib/media/gap_jumping_controller.js +10 -45
  86. package/lib/media/media_source_engine.js +150 -30
  87. package/lib/media/playhead.js +2 -5
  88. package/lib/media/presentation_timeline.js +1 -2
  89. package/lib/media/segment_index.js +13 -46
  90. package/lib/media/segment_reference.js +47 -1
  91. package/lib/media/streaming_engine.js +28 -11
  92. package/lib/media/time_ranges_utils.js +4 -9
  93. package/lib/net/networking_engine.js +3 -0
  94. package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
  95. package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
  96. package/lib/offline/manifest_converter.js +1 -0
  97. package/lib/offline/storage.js +8 -41
  98. package/lib/player.js +17 -201
  99. package/lib/polyfill/media_capabilities.js +12 -6
  100. package/lib/polyfill/mediasource.js +0 -28
  101. package/lib/polyfill/patchedmediakeys_nop.js +2 -0
  102. package/lib/polyfill/patchedmediakeys_webkit.js +2 -0
  103. package/lib/text/cue.js +0 -6
  104. package/lib/text/lrc_text_parser.js +8 -0
  105. package/lib/text/mp4_ttml_parser.js +8 -0
  106. package/lib/text/mp4_vtt_parser.js +8 -0
  107. package/lib/text/sbv_text_parser.js +8 -0
  108. package/lib/text/simple_text_displayer.js +1 -7
  109. package/lib/text/srt_text_parser.js +8 -0
  110. package/lib/text/ssa_text_parser.js +8 -0
  111. package/lib/text/text_engine.js +19 -3
  112. package/lib/text/ttml_text_parser.js +8 -0
  113. package/lib/text/ui_text_displayer.js +1 -7
  114. package/lib/text/vtt_text_parser.js +27 -5
  115. package/lib/text/web_vtt_generator.js +1 -7
  116. package/lib/util/error.js +9 -13
  117. package/lib/util/fairplay_utils.js +109 -0
  118. package/lib/util/functional.js +0 -42
  119. package/lib/util/mime_utils.js +16 -5
  120. package/lib/util/platform.js +45 -0
  121. package/lib/util/player_configuration.js +17 -6
  122. package/lib/util/pssh.js +23 -4
  123. package/lib/util/stream_utils.js +92 -22
  124. package/lib/util/uint8array_utils.js +0 -16
  125. package/lib/util/xml_utils.js +1 -1
  126. package/package.json +5 -2
  127. package/roadmap.md +19 -19
  128. package/shaka-player.uncompiled.js +0 -3
  129. package/test/dash/dash_parser_content_protection_unit.js +44 -0
  130. package/test/dash/dash_parser_segment_template_unit.js +3 -4
  131. package/test/demo/demo_unit.js +2 -1
  132. package/test/hls/hls_live_unit.js +155 -230
  133. package/test/hls/hls_parser_unit.js +515 -432
  134. package/test/media/drm_engine_unit.js +86 -120
  135. package/test/media/media_source_engine_integration.js +25 -3
  136. package/test/media/media_source_engine_unit.js +3 -2
  137. package/test/media/playhead_unit.js +27 -191
  138. package/test/media/segment_index_unit.js +15 -25
  139. package/test/media/streaming_engine_integration.js +2 -39
  140. package/test/media/streaming_engine_unit.js +3 -2
  141. package/test/media/time_ranges_utils_unit.js +0 -5
  142. package/test/offline/manifest_convert_unit.js +34 -4
  143. package/test/offline/offline_manifest_parser_unit.js +1 -0
  144. package/test/offline/storage_integration.js +5 -4
  145. package/test/player_external.js +0 -6
  146. package/test/player_integration.js +16 -0
  147. package/test/player_unit.js +26 -0
  148. package/test/test/util/fake_media_source_engine.js +11 -4
  149. package/test/test/util/manifest_generator.js +3 -1
  150. package/test/test/util/manifest_parser_util.js +4 -1
  151. package/test/test/util/offline_utils.js +1 -0
  152. package/test/test/util/streaming_engine_util.js +1 -0
  153. package/test/test/util/test_scheme.js +24 -1
  154. package/test/test/util/util.js +4 -4
  155. package/test/text/cue_integration.js +2 -2
  156. package/test/text/lrc_text_parser_unit.js +6 -7
  157. package/test/text/mp4_ttml_parser_unit.js +6 -4
  158. package/test/text/mp4_vtt_parser_unit.js +6 -5
  159. package/test/text/sbv_text_parser_unit.js +5 -6
  160. package/test/text/srt_text_parser_unit.js +5 -6
  161. package/test/text/ssa_text_parser_unit.js +17 -29
  162. package/test/text/text_engine_unit.js +45 -5
  163. package/test/text/ttml_text_parser_unit.js +77 -77
  164. package/test/text/vtt_text_parser_unit.js +116 -59
  165. package/test/ui/ui_integration.js +0 -16
  166. package/test/ui/ui_unit.js +27 -0
  167. package/test/util/cmcd_manager_unit.js +3 -0
  168. package/test/util/stream_utils_unit.js +23 -7
  169. package/ui/controls.js +65 -40
  170. package/ui/fullscreen_button.js +26 -6
  171. package/ui/less/containers.less +4 -4
  172. package/ui/less/general.less +1 -1
  173. package/ui/less/range_elements.less +1 -0
  174. package/ui/locales/en.json +1 -0
  175. package/ui/locales/source.json +5 -0
  176. package/ui/resolution_selection.js +31 -33
  177. package/ui/ui.js +0 -17
  178. package/.github/pull_request_template.md +0 -10
  179. package/docs/tutorials/upgrade-v2-5.md +0 -441
  180. package/docs/tutorials/upgrade-v3.md +0 -38
  181. package/lib/polyfill/mathround.js +0 -49
  182. package/lib/polyfill/patchedmediakeys_apple.js +0 -744
  183. package/lib/polyfill/patchedmediakeys_ms.js +0 -698
  184. package/test/util/functional_unit.js +0 -82
package/lib/player.js CHANGED
@@ -43,7 +43,6 @@ goog.require('shaka.util.Error');
43
43
  goog.require('shaka.util.EventManager');
44
44
  goog.require('shaka.util.FakeEvent');
45
45
  goog.require('shaka.util.FakeEventTarget');
46
- goog.require('shaka.util.Functional');
47
46
  goog.require('shaka.util.IDestroyable');
48
47
  goog.require('shaka.util.LanguageUtils');
49
48
  goog.require('shaka.util.ManifestParserUtils');
@@ -301,22 +300,6 @@ goog.requireType('shaka.routing.Payload');
301
300
  */
302
301
 
303
302
 
304
- /**
305
- * @event shaka.Player.LargeGapEvent
306
- * @description Fired when the playhead enters a large gap. If the
307
- * <code>streaming.jumpLargeGaps</code> configuration is set, the default
308
- * action of this event is to jump the gap; this can be prevented by calling
309
- * <code>preventDefault()</code> on the event object.
310
- * @property {string} type
311
- * 'largegap'
312
- * @property {number} currentTime
313
- * The current time of the playhead.
314
- * @property {number} gapSize
315
- * The size of the gap, in seconds.
316
- * @exportDoc
317
- */
318
-
319
-
320
303
  /**
321
304
  * @event shaka.Player.ManifestParsedEvent
322
305
  * @description Fired after the manifest has been parsed, but before anything
@@ -591,8 +574,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
591
574
  this.adManager_ = null;
592
575
 
593
576
  if (shaka.Player.adManagerFactory_) {
594
- this.adManager_ =
595
- shaka.util.Functional.callFactory(shaka.Player.adManagerFactory_);
577
+ this.adManager_ = shaka.Player.adManagerFactory_();
596
578
  }
597
579
 
598
580
  // If the browser comes back online after being offline, then try to play
@@ -870,10 +852,10 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
870
852
  return false;
871
853
  }
872
854
 
873
- // We do not support iOS 9, 10, or 11, nor those same versions of desktop
874
- // Safari.
855
+ // We do not support iOS 9, 10, 11 or 12, nor those same versions of
856
+ // desktop Safari.
875
857
  const safariVersion = shaka.util.Platform.safariVersion();
876
- if (safariVersion && safariVersion < 12) {
858
+ if (safariVersion && safariVersion < 13) {
877
859
  return false;
878
860
  }
879
861
 
@@ -1579,8 +1561,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
1579
1561
  // text displayer and streaming engine are always in sync, wait until they
1580
1562
  // are both initialized before setting the initial value.
1581
1563
  const textDisplayerFactory = this.config_.textDisplayFactory;
1582
- const textDisplayer =
1583
- shaka.util.Functional.callFactory(textDisplayerFactory);
1564
+ const textDisplayer = textDisplayerFactory();
1584
1565
  this.lastTextFactory_ = textDisplayerFactory;
1585
1566
 
1586
1567
  const mediaSourceEngine = this.createMediaSourceEngine(
@@ -1590,6 +1571,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
1590
1571
  (metadata, offset, endTime) => {
1591
1572
  this.processTimedMetadataMediaSrc_(metadata, offset, endTime);
1592
1573
  });
1574
+ const {segmentRelativeVttTiming} = this.config_.manifest;
1575
+ mediaSourceEngine.setSegmentRelativeVttTiming(segmentRelativeVttTiming);
1593
1576
 
1594
1577
  // Wait for media source engine to finish opening. This promise should
1595
1578
  // NEVER be rejected as per the media source engine implementation.
@@ -1651,7 +1634,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
1651
1634
  this.config_.manifest.retryParameters,
1652
1635
  has.mimeType);
1653
1636
  goog.asserts.assert(this.parserFactory_, 'Must have manifest parser');
1654
- this.parser_ = shaka.util.Functional.callFactory(this.parserFactory_);
1637
+ this.parser_ = this.parserFactory_();
1655
1638
 
1656
1639
  const manifestConfig =
1657
1640
  shaka.util.ObjectUtils.cloneObject(this.config_.manifest);
@@ -1937,13 +1920,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
1937
1920
  const abrFactory = this.config_.abrFactory;
1938
1921
  if (!this.abrManager_ || this.abrManagerFactory_ != abrFactory) {
1939
1922
  this.abrManagerFactory_ = abrFactory;
1940
- this.abrManager_ = shaka.util.Functional.callFactory(abrFactory);
1941
- if (typeof this.abrManager_.playbackRateChanged != 'function') {
1942
- shaka.Deprecate.deprecateFeature(4,
1943
- 'AbrManager',
1944
- 'Please use an AbrManager with playbackRateChanged function.');
1945
- this.abrManager_.playbackRateChanged = (rate) => {};
1946
- }
1923
+ this.abrManager_ = abrFactory();
1947
1924
  this.abrManager_.configure(this.config_.abr);
1948
1925
  }
1949
1926
 
@@ -2716,8 +2693,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
2716
2693
  this.manifest_,
2717
2694
  this.config_.streaming,
2718
2695
  startTime,
2719
- () => this.onSeek_(),
2720
- (event) => this.dispatchEvent(event));
2696
+ () => this.onSeek_());
2721
2697
  }
2722
2698
 
2723
2699
  /**
@@ -2976,17 +2952,6 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
2976
2952
 
2977
2953
  goog.asserts.assert(typeof(config) == 'object', 'Should be an object!');
2978
2954
 
2979
- // Deprecate 'manifest.dash.defaultPresentationDelay' configuration.
2980
- if (config['manifest'] && config['manifest']['dash'] &&
2981
- 'defaultPresentationDelay' in config['manifest']['dash']) {
2982
- shaka.Deprecate.deprecateFeature(4,
2983
- 'manifest.dash.defaultPresentationDelay configuration',
2984
- 'Please Use manifest.defaultPresentationDelay instead.');
2985
- config['manifest']['defaultPresentationDelay'] =
2986
- config['manifest']['dash']['defaultPresentationDelay'];
2987
- delete config['manifest']['dash']['defaultPresentationDelay'];
2988
- }
2989
-
2990
2955
  // If lowLatencyMode is enabled, and inaccurateManifestTolerance and
2991
2956
  // rebufferingGoal are not specified, set inaccurateManifestTolerance to 0
2992
2957
  // and rebufferingGoal to 0.01 by default for low latency streaming.
@@ -3053,10 +3018,13 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
3053
3018
  }
3054
3019
 
3055
3020
  if (this.mediaSourceEngine_) {
3021
+ const {segmentRelativeVttTiming} = this.config_.manifest;
3022
+ this.mediaSourceEngine_.setSegmentRelativeVttTiming(
3023
+ segmentRelativeVttTiming);
3024
+
3056
3025
  const textDisplayerFactory = this.config_.textDisplayFactory;
3057
3026
  if (this.lastTextFactory_ != textDisplayerFactory) {
3058
- const displayer =
3059
- shaka.util.Functional.callFactory(textDisplayerFactory);
3027
+ const displayer = textDisplayerFactory();
3060
3028
  this.mediaSourceEngine_.setTextDisplayer(displayer);
3061
3029
  this.lastTextFactory_ = textDisplayerFactory;
3062
3030
 
@@ -4441,158 +4409,6 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
4441
4409
  return this.stats_.getBlob();
4442
4410
  }
4443
4411
 
4444
- /**
4445
- * Adds the given text track to the loaded manifest. <code>load()</code> must
4446
- * resolve before calling. The presentation must have a duration.
4447
- *
4448
- * This returns the created track, which can immediately be selected by the
4449
- * application. The track will not be automatically selected.
4450
- *
4451
- * @param {string} uri
4452
- * @param {string} language
4453
- * @param {string} kind
4454
- * @param {string=} mimeType
4455
- * @param {string=} codec
4456
- * @param {string=} label
4457
- * @param {boolean=} forced
4458
- * @return {shaka.extern.Track}
4459
- * @export
4460
- */
4461
- addTextTrack(uri, language, kind, mimeType, codec, label, forced = false) {
4462
- shaka.Deprecate.deprecateFeature(4,
4463
- 'addTextTrack',
4464
- 'Please use an addTextTrackAsync.');
4465
- if (this.loadMode_ != shaka.Player.LoadMode.MEDIA_SOURCE &&
4466
- this.loadMode_ != shaka.Player.LoadMode.SRC_EQUALS) {
4467
- shaka.log.error(
4468
- 'Must call load() and wait for it to resolve before adding text ' +
4469
- 'tracks.');
4470
- throw new shaka.util.Error(
4471
- shaka.util.Error.Severity.RECOVERABLE,
4472
- shaka.util.Error.Category.PLAYER,
4473
- shaka.util.Error.Code.CONTENT_NOT_LOADED);
4474
- }
4475
-
4476
- if (!mimeType) {
4477
- // Try using the uri extension.
4478
- const extension = shaka.media.ManifestParser.getExtension(uri);
4479
- mimeType = shaka.Player.TEXT_EXTENSIONS_TO_MIME_TYPES_[extension];
4480
-
4481
- if (!mimeType) {
4482
- shaka.log.error(
4483
- 'The mimeType has not been provided and it could not be deduced ' +
4484
- 'from its extension.');
4485
- throw new shaka.util.Error(
4486
- shaka.util.Error.Severity.RECOVERABLE,
4487
- shaka.util.Error.Category.TEXT,
4488
- shaka.util.Error.Code.TEXT_COULD_NOT_GUESS_MIME_TYPE,
4489
- extension);
4490
- }
4491
- }
4492
-
4493
- if (this.loadMode_ == shaka.Player.LoadMode.SRC_EQUALS) {
4494
- if (mimeType != 'text/vtt') {
4495
- shaka.log.error('Only WebVTT is supported when using src=');
4496
- throw new shaka.util.Error(
4497
- shaka.util.Error.Severity.RECOVERABLE,
4498
- shaka.util.Error.Category.TEXT,
4499
- shaka.util.Error.Code.TEXT_ONLY_WEBVTT_SRC_EQUALS,
4500
- mimeType);
4501
- }
4502
- if (forced) {
4503
- // See: https://github.com/whatwg/html/issues/4472
4504
- kind = 'forced';
4505
- }
4506
- const trackElement =
4507
- /** @type {!HTMLTrackElement} */(document.createElement('track'));
4508
- trackElement.src = this.cmcdManager_.appendTextTrackData(uri);
4509
- trackElement.label = label || '';
4510
- trackElement.kind = kind;
4511
- trackElement.srclang = language;
4512
- // Because we're pulling in the text track file via Javascript, the
4513
- // same-origin policy applies. If you'd like to have a player served
4514
- // from one domain, but the text track served from another, you'll
4515
- // need to enable CORS in order to do so. In addition to enabling CORS
4516
- // on the server serving the text tracks, you will need to add the
4517
- // crossorigin attribute to the video element itself.
4518
- if (!this.video_.getAttribute('crossorigin')) {
4519
- this.video_.setAttribute('crossorigin', 'anonymous');
4520
- }
4521
- this.video_.appendChild(trackElement);
4522
- const textTracks = this.getTextTracks();
4523
- const srcTrack = textTracks.find((t) => {
4524
- return t.language == language &&
4525
- t.label == (label || '') &&
4526
- t.kind == kind;
4527
- });
4528
- if (srcTrack) {
4529
- this.onTracksChanged_();
4530
- return srcTrack;
4531
- }
4532
- // This should not happen, but there are browser implementations that may
4533
- // not support the Track element.
4534
- shaka.log.error('Cannot add this text when loaded with src=');
4535
- throw new shaka.util.Error(
4536
- shaka.util.Error.Severity.RECOVERABLE,
4537
- shaka.util.Error.Category.TEXT,
4538
- shaka.util.Error.Code.CANNOT_ADD_EXTERNAL_TEXT_TO_SRC_EQUALS);
4539
- }
4540
-
4541
- const ContentType = shaka.util.ManifestParserUtils.ContentType;
4542
-
4543
- const duration = this.manifest_.presentationTimeline.getDuration();
4544
- if (duration == Infinity) {
4545
- throw new shaka.util.Error(
4546
- shaka.util.Error.Severity.RECOVERABLE,
4547
- shaka.util.Error.Category.MANIFEST,
4548
- shaka.util.Error.Code.CANNOT_ADD_EXTERNAL_TEXT_TO_LIVE_STREAM);
4549
- }
4550
-
4551
- /** @type {shaka.extern.Stream} */
4552
- const stream = {
4553
- id: this.nextExternalStreamId_++,
4554
- originalId: null,
4555
- createSegmentIndex: () => Promise.resolve(),
4556
- segmentIndex: shaka.media.SegmentIndex.forSingleSegment(
4557
- /* startTime= */ 0,
4558
- /* duration= */ duration,
4559
- /* uris= */ [uri]),
4560
- mimeType: mimeType || '',
4561
- codecs: codec || '',
4562
- kind: kind,
4563
- encrypted: false,
4564
- drmInfos: [],
4565
- keyIds: new Set(),
4566
- language: language,
4567
- label: label || null,
4568
- type: ContentType.TEXT,
4569
- primary: false,
4570
- trickModeVideo: null,
4571
- emsgSchemeIdUris: null,
4572
- roles: [],
4573
- forced: !!forced,
4574
- channelsCount: null,
4575
- audioSamplingRate: null,
4576
- spatialAudio: false,
4577
- closedCaptions: null,
4578
- };
4579
-
4580
- const fullMimeType = shaka.util.MimeUtils.getFullType(
4581
- stream.mimeType, stream.codecs);
4582
- const supported = shaka.text.TextEngine.isTypeSupported(fullMimeType);
4583
- if (!supported) {
4584
- throw new shaka.util.Error(
4585
- shaka.util.Error.Severity.CRITICAL,
4586
- shaka.util.Error.Category.TEXT,
4587
- shaka.util.Error.Code.MISSING_TEXT_PLUGIN,
4588
- mimeType);
4589
- }
4590
-
4591
- this.manifest_.textStreams.push(stream);
4592
- this.onTracksChanged_();
4593
- return shaka.util.StreamUtils.textStreamToTrack(stream);
4594
- }
4595
-
4596
4412
  /**
4597
4413
  * Adds the given text track to the loaded manifest. <code>load()</code> must
4598
4414
  * resolve before calling. The presentation must have a duration.
@@ -4918,6 +4734,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
4918
4734
  periodStart: 0,
4919
4735
  segmentStart: 0,
4920
4736
  segmentEnd: this.video_.duration,
4737
+ vttOffset: 0,
4921
4738
  };
4922
4739
  const data = shaka.util.BufferUtils.toUint8(buffer);
4923
4740
  const cues = obj.parseMedia(data, time);
@@ -6574,7 +6391,6 @@ shaka.Player.EventName = {
6574
6391
  Emsg: 'emsg',
6575
6392
  Error: 'error',
6576
6393
  ExpirationUpdated: 'expirationupdated',
6577
- LargeGap: 'largegap',
6578
6394
  Loaded: 'loaded',
6579
6395
  Loading: 'loading',
6580
6396
  ManifestParsed: 'manifestparsed',
@@ -6634,7 +6450,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
6634
6450
  * @define {string} A version number taken from git at compile time.
6635
6451
  * @export
6636
6452
  */
6637
- shaka.Player.version = 'v3.3.5-uncompiled';
6453
+ shaka.Player.version = 'v4.0.2-uncompiled';
6638
6454
 
6639
6455
  // Initialize the deprecation system using the version string we just set
6640
6456
  // on the player.
@@ -24,8 +24,8 @@ shaka.polyfill.MediaCapabilities = class {
24
24
  * @export
25
25
  */
26
26
  static install() {
27
- // Since MediaCapabilities is not fully supported on Chromecast yet, we
28
- // should always install polyfill for Chromecast.
27
+ // Since MediaCapabilities is not fully supported on some Chromecast yet,
28
+ // we should always install polyfill for all Chromecast not Android-based.
29
29
  // TODO: re-evaluate MediaCapabilities in the future versions of Chromecast.
30
30
  // Since MediaCapabilities implementation is buggy in Apple browsers, we
31
31
  // should always install polyfill for Apple browsers.
@@ -37,10 +37,16 @@ shaka.polyfill.MediaCapabilities = class {
37
37
  // See: https://github.com/shaka-project/shaka-player/issues/3582
38
38
  // TODO: re-evaluate MediaCapabilities in the future versions of PS5
39
39
  // Browsers.
40
- if (!shaka.util.Platform.isChromecast() &&
41
- !shaka.util.Platform.isApple() &&
42
- !shaka.util.Platform.isPS5() &&
43
- navigator.mediaCapabilities) {
40
+ let canUseNativeMCap = true;
41
+ if (shaka.util.Platform.isApple() ||
42
+ shaka.util.Platform.isPS5() ||
43
+ shaka.util.Platform.isChromecast()) {
44
+ canUseNativeMCap = false;
45
+ }
46
+ if (shaka.util.Platform.isAndroidCastDevice()) {
47
+ canUseNativeMCap = true;
48
+ }
49
+ if (canUseNativeMCap && navigator.mediaCapabilities) {
44
50
  shaka.log.info(
45
51
  'MediaCapabilities: Native mediaCapabilities support found.');
46
52
  return;
@@ -38,11 +38,6 @@ shaka.polyfill.MediaSource = class {
38
38
  // Chromecast cannot make accurate determinations via isTypeSupported.
39
39
  shaka.polyfill.MediaSource.patchCastIsTypeSupported_();
40
40
  } else if (safariVersion) {
41
- // TS content is broken on Safari in general.
42
- // See https://github.com/shaka-project/shaka-player/issues/743
43
- // and https://bugs.webkit.org/show_bug.cgi?id=165342
44
- shaka.polyfill.MediaSource.rejectTsContent_();
45
-
46
41
  // NOTE: shaka.Player.isBrowserSupported() has its own restrictions on
47
42
  // Safari version.
48
43
  if (safariVersion <= 12) {
@@ -127,29 +122,6 @@ shaka.polyfill.MediaSource = class {
127
122
  };
128
123
  }
129
124
 
130
- /**
131
- * Patch isTypeSupported() to reject TS content. Used to avoid TS-related MSE
132
- * bugs on Safari.
133
- *
134
- * @private
135
- */
136
- static rejectTsContent_() {
137
- const originalIsTypeSupported = MediaSource.isTypeSupported;
138
-
139
- MediaSource.isTypeSupported = (mimeType) => {
140
- // Parse the basic MIME type from its parameters.
141
- const pieces = mimeType.split(/ *; */);
142
- const basicMimeType = pieces[0];
143
- const container = basicMimeType.split('/')[1];
144
-
145
- if (container.toLowerCase() == 'mp2t') {
146
- return false;
147
- }
148
-
149
- return originalIsTypeSupported(mimeType);
150
- };
151
- }
152
-
153
125
  /**
154
126
  * Patch |MediaSource.isTypeSupported| to always reject |codec|. This is used
155
127
  * when we know that we are on a platform that does not work well with a given
@@ -49,6 +49,8 @@ shaka.polyfill.PatchedMediaKeysNop = class {
49
49
  // These are not usable, but allow Player.isBrowserSupported to pass.
50
50
  window.MediaKeys = PatchedMediaKeysNop.MediaKeys;
51
51
  window.MediaKeySystemAccess = PatchedMediaKeysNop.MediaKeySystemAccess;
52
+
53
+ window.shakaMediaKeysPolyfill = true;
52
54
  }
53
55
 
54
56
  /**
@@ -72,6 +72,8 @@ shaka.polyfill.PatchedMediaKeysWebkit = class {
72
72
  PatchedMediaKeysWebkit.setMediaKeys;
73
73
  window.MediaKeys = PatchedMediaKeysWebkit.MediaKeys;
74
74
  window.MediaKeySystemAccess = PatchedMediaKeysWebkit.MediaKeySystemAccess;
75
+
76
+ window.shakaMediaKeysPolyfill = true;
75
77
  }
76
78
 
77
79
  /**
package/lib/text/cue.js CHANGED
@@ -234,12 +234,6 @@ shaka.text.Cue = class {
234
234
  */
235
235
  this.lineBreak = false;
236
236
 
237
- /**
238
- * @override
239
- * @exportInterface
240
- */
241
- this.spacer = false;
242
-
243
237
  /**
244
238
  * @override
245
239
  * @exportInterface
@@ -28,6 +28,14 @@ shaka.text.LrcTextParser = class {
28
28
  goog.asserts.assert(false, 'LRC does not have init segments');
29
29
  }
30
30
 
31
+ /**
32
+ * @override
33
+ * @export
34
+ */
35
+ setSequenceMode(sequenceMode) {
36
+ // Unused.
37
+ }
38
+
31
39
  /**
32
40
  * @override
33
41
  * @export
@@ -55,6 +55,14 @@ shaka.text.Mp4TtmlParser = class {
55
55
  }
56
56
  }
57
57
 
58
+ /**
59
+ * @override
60
+ * @export
61
+ */
62
+ setSequenceMode(sequenceMode) {
63
+ // Unused.
64
+ }
65
+
58
66
  /**
59
67
  * @override
60
68
  * @export
@@ -84,6 +84,14 @@ shaka.text.Mp4VttParser = class {
84
84
  }
85
85
  }
86
86
 
87
+ /**
88
+ * @override
89
+ * @export
90
+ */
91
+ setSequenceMode(sequenceMode) {
92
+ // Unused.
93
+ }
94
+
87
95
  /**
88
96
  * @override
89
97
  * @export
@@ -27,6 +27,14 @@ shaka.text.SbvTextParser = class {
27
27
  goog.asserts.assert(false, 'SubViewer does not have init segments');
28
28
  }
29
29
 
30
+ /**
31
+ * @override
32
+ * @export
33
+ */
34
+ setSequenceMode(sequenceMode) {
35
+ // Unused.
36
+ }
37
+
30
38
  /**
31
39
  * @override
32
40
  * @export
@@ -12,7 +12,6 @@
12
12
  goog.provide('shaka.text.SimpleTextDisplayer');
13
13
 
14
14
  goog.require('goog.asserts');
15
- goog.require('shaka.Deprecate');
16
15
  goog.require('shaka.log');
17
16
  goog.require('shaka.text.Cue');
18
17
 
@@ -108,12 +107,7 @@ shaka.text.SimpleTextDisplayer = class {
108
107
  return `${acc}</${tag}>`;
109
108
  }, '');
110
109
 
111
- if (cue.lineBreak || cue.spacer) {
112
- if (cue.spacer) {
113
- shaka.Deprecate.deprecateFeature(4,
114
- 'shaka.extern.Cue',
115
- 'Please use lineBreak instead of spacer.');
116
- }
110
+ if (cue.lineBreak) {
117
111
  // This is a vertical lineBreak, so insert a newline.
118
112
  return '\n';
119
113
  } else if (cue.nestedCues.length) {
@@ -35,6 +35,14 @@ shaka.text.SrtTextParser = class {
35
35
  goog.asserts.assert(false, 'SRT does not have init segments');
36
36
  }
37
37
 
38
+ /**
39
+ * @override
40
+ * @export
41
+ */
42
+ setSequenceMode(sequenceMode) {
43
+ // Unused.
44
+ }
45
+
38
46
  /**
39
47
  * @override
40
48
  * @export
@@ -28,6 +28,14 @@ shaka.text.SsaTextParser = class {
28
28
  goog.asserts.assert(false, 'SSA does not have init segments');
29
29
  }
30
30
 
31
+ /**
32
+ * @override
33
+ * @export
34
+ */
35
+ setSequenceMode(sequenceMode) {
36
+ // Unused.
37
+ }
38
+
31
39
  /**
32
40
  * @override
33
41
  * @export
@@ -7,9 +7,9 @@
7
7
  goog.provide('shaka.text.TextEngine');
8
8
 
9
9
  goog.require('goog.asserts');
10
+ goog.require('shaka.log');
10
11
  goog.require('shaka.text.Cue');
11
12
  goog.require('shaka.util.BufferUtils');
12
- goog.require('shaka.util.Functional');
13
13
  goog.require('shaka.util.IDestroyable');
14
14
  goog.require('shaka.util.MimeUtils');
15
15
  goog.requireType('shaka.cea.ICaptionDecoder');
@@ -30,6 +30,9 @@ shaka.text.TextEngine = class {
30
30
  /** @private {shaka.extern.TextDisplayer} */
31
31
  this.displayer_ = displayer;
32
32
 
33
+ /** @private {boolean} */
34
+ this.segmentRelativeVttTiming_ = false;
35
+
33
36
  /** @private {number} */
34
37
  this.timestampOffset_ = 0;
35
38
 
@@ -128,8 +131,10 @@ shaka.text.TextEngine = class {
128
131
  * called at least once before appendBuffer.
129
132
  *
130
133
  * @param {string} mimeType
134
+ * @param {boolean} sequenceMode
135
+ * @param {boolean} segmentRelativeVttTiming
131
136
  */
132
- initParser(mimeType) {
137
+ initParser(mimeType, sequenceMode, segmentRelativeVttTiming) {
133
138
  // No parser for CEA, which is extracted from video and side-loaded
134
139
  // into TextEngine and TextDisplayer.
135
140
  if (mimeType == shaka.util.MimeUtils.CEA608_CLOSED_CAPTION_MIMETYPE ||
@@ -140,7 +145,14 @@ shaka.text.TextEngine = class {
140
145
  const factory = shaka.text.TextEngine.parserMap_[mimeType];
141
146
  goog.asserts.assert(
142
147
  factory, 'Text type negotiation should have happened already');
143
- this.parser_ = shaka.util.Functional.callFactory(factory);
148
+ this.parser_ = factory();
149
+ if (this.parser_.setSequenceMode) {
150
+ this.parser_.setSequenceMode(sequenceMode);
151
+ } else {
152
+ shaka.log.alwaysWarn(
153
+ 'Text parsers should have a "setSequenceMode" method!');
154
+ }
155
+ this.segmentRelativeVttTiming_ = segmentRelativeVttTiming;
144
156
  }
145
157
 
146
158
  /**
@@ -166,11 +178,15 @@ shaka.text.TextEngine = class {
166
178
  return;
167
179
  }
168
180
 
181
+ const vttOffset = this.segmentRelativeVttTiming_ ?
182
+ startTime : this.timestampOffset_;
183
+
169
184
  /** @type {shaka.extern.TextParser.TimeContext} **/
170
185
  const time = {
171
186
  periodStart: this.timestampOffset_,
172
187
  segmentStart: startTime,
173
188
  segmentEnd: endTime,
189
+ vttOffset: vttOffset,
174
190
  };
175
191
 
176
192
  // Parse the buffer and add the new cues.
@@ -30,6 +30,14 @@ shaka.text.TtmlTextParser = class {
30
30
  goog.asserts.assert(false, 'TTML does not have init segments');
31
31
  }
32
32
 
33
+ /**
34
+ * @override
35
+ * @export
36
+ */
37
+ setSequenceMode(sequenceMode) {
38
+ // Unused.
39
+ }
40
+
33
41
  /**
34
42
  * @override
35
43
  * @export
@@ -8,7 +8,6 @@
8
8
  goog.provide('shaka.text.UITextDisplayer');
9
9
 
10
10
  goog.require('goog.asserts');
11
- goog.require('shaka.Deprecate');
12
11
  goog.require('shaka.text.Cue');
13
12
  goog.require('shaka.text.CueRegion');
14
13
  goog.require('shaka.util.Dom');
@@ -343,12 +342,7 @@ shaka.text.UITextDisplayer = class {
343
342
  createCue_(cue, parents) {
344
343
  const isNested = parents.length > 1;
345
344
  let type = isNested ? 'span' : 'div';
346
- if (cue.lineBreak || cue.spacer) {
347
- if (cue.spacer) {
348
- shaka.Deprecate.deprecateFeature(4,
349
- 'shaka.extern.Cue',
350
- 'Please use lineBreak instead of spacer.');
351
- }
345
+ if (cue.lineBreak) {
352
346
  type = 'br';
353
347
  }
354
348