shaka-player 3.3.12 → 3.3.14

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 (60) hide show
  1. package/AUTHORS +1 -0
  2. package/CHANGELOG.md +33 -0
  3. package/CONTRIBUTORS +1 -0
  4. package/dist/deps.js +3 -3
  5. package/dist/locales.js +31 -31
  6. package/dist/shaka-player.compiled.d.ts +1 -1
  7. package/dist/shaka-player.compiled.debug.d.ts +1 -1
  8. package/dist/shaka-player.compiled.debug.externs.js +2 -1
  9. package/dist/shaka-player.compiled.debug.js +135 -126
  10. package/dist/shaka-player.compiled.debug.map +3 -3
  11. package/dist/shaka-player.compiled.externs.js +2 -1
  12. package/dist/shaka-player.compiled.js +744 -739
  13. package/dist/shaka-player.compiled.map +3 -3
  14. package/dist/shaka-player.ui.d.ts +1 -1
  15. package/dist/shaka-player.ui.debug.d.ts +1 -1
  16. package/dist/shaka-player.ui.debug.externs.js +2 -1
  17. package/dist/shaka-player.ui.debug.js +228 -219
  18. package/dist/shaka-player.ui.debug.map +3 -3
  19. package/dist/shaka-player.ui.externs.js +2 -1
  20. package/dist/shaka-player.ui.js +849 -845
  21. package/dist/shaka-player.ui.map +3 -3
  22. package/docs/tutorials/welcome.md +2 -2
  23. package/externs/shaka/player.js +2 -1
  24. package/lib/cast/cast_proxy.js +2 -1
  25. package/lib/cast/cast_receiver.js +19 -5
  26. package/lib/cast/cast_sender.js +2 -1
  27. package/lib/cast/cast_utils.js +16 -6
  28. package/lib/cea/cea708_window.js +2 -2
  29. package/lib/dash/segment_template.js +1 -1
  30. package/lib/hls/hls_parser.js +17 -3
  31. package/lib/media/content_workarounds.js +12 -0
  32. package/lib/media/playhead.js +23 -1
  33. package/lib/media/streaming_engine.js +3 -12
  34. package/lib/player.js +24 -11
  35. package/lib/polyfill/media_capabilities.js +59 -9
  36. package/lib/text/ttml_text_parser.js +32 -7
  37. package/lib/text/ui_text_displayer.js +22 -5
  38. package/lib/util/manifest_parser_utils.js +4 -0
  39. package/lib/util/platform.js +21 -2
  40. package/lib/util/stream_utils.js +30 -10
  41. package/package.json +1 -1
  42. package/test/cast/cast_receiver_integration.js +97 -16
  43. package/test/cast/cast_receiver_unit.js +17 -12
  44. package/test/cast/cast_utils_unit.js +1 -0
  45. package/test/dash/dash_parser_manifest_unit.js +1 -0
  46. package/test/hls/hls_parser_unit.js +1 -0
  47. package/test/media/playhead_unit.js +41 -0
  48. package/test/media/streaming_engine_integration.js +13 -0
  49. package/test/media/streaming_engine_unit.js +23 -8
  50. package/test/player_unit.js +87 -0
  51. package/test/polyfill/media_capabilities_unit.js +261 -0
  52. package/test/test/util/simple_fakes.js +3 -0
  53. package/test/text/mp4_ttml_parser_unit.js +4 -4
  54. package/test/text/ttml_text_parser_unit.js +119 -86
  55. package/test/text/ui_text_displayer_unit.js +76 -0
  56. package/test/ui/text_displayer_layout_unit.js +14 -0
  57. package/test/util/stream_utils_unit.js +18 -0
  58. package/test/util/xml_utils_unit.js +6 -1
  59. package/ui/controls.js +5 -2
  60. package/ui/settings_menu.js +11 -2
@@ -461,4 +461,80 @@ describe('UITextDisplayer', () => {
461
461
  expect(Object.keys(cueCssObj)).not.toContain('left');
462
462
  }
463
463
  });
464
+
465
+ it('does not lose second item in a region', () => {
466
+ const cueRegion = new shaka.text.CueRegion();
467
+ cueRegion.id = 'regionId';
468
+ cueRegion.height = 80;
469
+ cueRegion.heightUnits = shaka.text.CueRegion.units.PERCENTAGE;
470
+ cueRegion.width = 80;
471
+ cueRegion.widthUnits = shaka.text.CueRegion.units.PERCENTAGE;
472
+ cueRegion.viewportAnchorX = 10;
473
+ cueRegion.viewportAnchorY = 10;
474
+ cueRegion.viewportAnchorUnits = shaka.text.CueRegion.units.PERCENTAGE;
475
+
476
+ // These have identical nested.
477
+ const cue1 = new shaka.text.Cue(168, 181.84, '');
478
+ cue1.nestedCues = [
479
+ new shaka.text.Cue(168, 181.84, ''),
480
+ ];
481
+ cue1.region = cueRegion;
482
+
483
+ const nested1 = new shaka.text.Cue(168, 170.92, '');
484
+ nested1.nestedCues = [new shaka.text.Cue(0, 170.92,
485
+ 'Emo look. I mean listen.')];
486
+
487
+ const nested2 = new shaka.text.Cue(172, 174.84, '');
488
+ nested2.nestedCues = [new shaka.text.Cue(172, 174.84,
489
+ 'You have to learn to listen.')];
490
+
491
+ const nested3 = new shaka.text.Cue(175.84, 177.64, '');
492
+ nested3.nestedCues = [new shaka.text.Cue(175.84, 177.64,
493
+ 'This is not some game.')];
494
+
495
+ const nested4 = new shaka.text.Cue(177.68, 181.84, '');
496
+ nested4.nestedCues = [new shaka.text.Cue(177.68, 181.84,
497
+ 'You - I mean we - we could easily die out here.')];
498
+
499
+ cue1.nestedCues[0].nestedCues = [nested1, nested2, nested3, nested4];
500
+
501
+ video.currentTime = 170;
502
+ textDisplayer.setTextVisibility(true);
503
+ textDisplayer.append([cue1]);
504
+ updateCaptions();
505
+
506
+ /** @type {Element} */
507
+ const textContainer = videoContainer.querySelector('.shaka-text-container');
508
+ let captions = textContainer.querySelectorAll('div');
509
+ expect(captions.length).toBe(1);
510
+ let allRegionElements = textContainer.querySelectorAll(
511
+ '.shaka-text-region');
512
+ // Verify that the nested cues are all attached to a single region element.
513
+ expect(allRegionElements.length).toBe(1);
514
+
515
+ // Advance time to where there is none to show
516
+ video.currentTime = 171;
517
+ updateCaptions();
518
+
519
+ allRegionElements = textContainer.querySelectorAll(
520
+ '.shaka-text-region');
521
+ expect(allRegionElements.length).toBe(1);
522
+
523
+ // Advance time to where there is something to show
524
+ video.currentTime = 173;
525
+ updateCaptions();
526
+
527
+ allRegionElements = textContainer.querySelectorAll(
528
+ '.shaka-text-region');
529
+ expect(allRegionElements.length).toBe(1);
530
+
531
+ captions = textContainer.querySelectorAll('div');
532
+
533
+ expect(captions.length).toBe(1);
534
+ expect(captions[0].textContent).toBe('You have to learn to listen.');
535
+
536
+ allRegionElements = textContainer.querySelectorAll(
537
+ '.shaka-text-region');
538
+ expect(allRegionElements.length).toBe(1);
539
+ });
464
540
  });
@@ -444,6 +444,20 @@ filterDescribe('TextDisplayer layout', supportsScreenshots, () => {
444
444
 
445
445
  await checkScreenshot(prefix, 'deeply-nested-cues');
446
446
  });
447
+
448
+ // Regression test for #4567, in which "end" line alignment for VTT was
449
+ // inverted.
450
+ it('line alignment', async () => {
451
+ const cue = new shaka.text.Cue(0, 1, 'Captain\'s log, stardate 41636.9');
452
+
453
+ cue.line = 70;
454
+ cue.lineInterpretation = shaka.text.Cue.lineInterpretation.PERCENTAGE;
455
+ cue.lineAlign = shaka.text.Cue.lineAlign.END;
456
+
457
+ textDisplayer.append([cue]);
458
+
459
+ await checkScreenshot(prefix, 'line-alignment');
460
+ });
447
461
  }
448
462
 
449
463
  /** @param {!HTMLElement} element */
@@ -701,6 +701,24 @@ describe('StreamUtils', () => {
701
701
 
702
702
  expect(manifest.variants.length).toBe(1);
703
703
  });
704
+
705
+ it('supports legacy AVC1 codec', async () => {
706
+ if (!MediaSource.isTypeSupported('video/mp4; codecs="avc1.42001e"')) {
707
+ pending('Codec avc1.42001e is not supported by the platform.');
708
+ }
709
+ manifest = shaka.test.ManifestGenerator.generate((manifest) => {
710
+ manifest.addVariant(0, (variant) => {
711
+ variant.addVideo(1, (stream) => {
712
+ stream.mime('video/mp4', 'avc1.66.30');
713
+ });
714
+ });
715
+ });
716
+
717
+ await shaka.util.StreamUtils.filterManifest(
718
+ fakeDrmEngine, /* currentVariant= */ null, manifest);
719
+
720
+ expect(manifest.variants.length).toBe(1);
721
+ });
704
722
  });
705
723
 
706
724
  describe('chooseCodecsAndFilterManifest', () => {
@@ -425,10 +425,15 @@ describe('XmlUtils', () => {
425
425
  });
426
426
 
427
427
  it('returns null on XML that embeds SVG', () => {
428
+ // Some platforms, such as Xbox One, don't recognize elements as SVG
429
+ // based on namespace alone. So the SVG element below needs to be a real
430
+ // SVG element.
428
431
  const xmlString = [
429
432
  '<?xml version="1.0"?>',
430
433
  '<Root>',
431
- ' <Child xmlns="http://www.w3.org/2000/svg"></Child>',
434
+ ' <svg viewBox="0 0 100 100">',
435
+ ' <rect x="0" y="0" width="100" height"100" />',
436
+ ' </svg>',
432
437
  '</Root>',
433
438
  ].join('\n');
434
439
  const doc = XmlUtils.parseXmlString(xmlString, 'Root');
package/ui/controls.js CHANGED
@@ -1004,7 +1004,10 @@ shaka.ui.Controls = class extends shaka.util.FakeEventTarget {
1004
1004
  if (!this.video_ ||
1005
1005
  this.video_.readyState == 0 ||
1006
1006
  this.castProxy_.isCasting() ||
1007
- !this.config_.enableFullscreenOnRotation) { return; }
1007
+ !this.config_.enableFullscreenOnRotation ||
1008
+ !document.fullscreenEnabled) {
1009
+ return;
1010
+ }
1008
1011
 
1009
1012
  if (screen.orientation.type.includes('landscape') &&
1010
1013
  !document.fullscreenElement) {
@@ -1169,7 +1172,7 @@ shaka.ui.Controls = class extends shaka.util.FakeEventTarget {
1169
1172
  // The controls are hidden, so show them.
1170
1173
  this.onMouseMove_(event);
1171
1174
  // Stop this event from becoming a click event.
1172
- event.preventDefault();
1175
+ event.cancelable && event.preventDefault();
1173
1176
  }
1174
1177
  }
1175
1178
 
@@ -12,6 +12,7 @@ goog.require('shaka.ui.Enums');
12
12
  goog.require('shaka.ui.Utils');
13
13
  goog.require('shaka.util.Dom');
14
14
  goog.require('shaka.util.FakeEvent');
15
+ goog.require('shaka.util.Iterables');
15
16
  goog.requireType('shaka.ui.Controls');
16
17
 
17
18
 
@@ -116,8 +117,16 @@ shaka.ui.SettingsMenu = class extends shaka.ui.Element {
116
117
  this.eventManager.listen(this.backButton, 'click', () => {
117
118
  shaka.ui.Utils.setDisplay(this.parent, true);
118
119
 
119
- /** @type {!HTMLElement} */
120
- (this.parent.childNodes[0]).focus();
120
+ const isDisplayed =
121
+ (element) => element.classList.contains('shaka-hidden') == false;
122
+
123
+ const Iterables = shaka.util.Iterables;
124
+ if (Iterables.some(this.parent.childNodes, isDisplayed)) {
125
+ // Focus on the first visible child of the overflow menu
126
+ const visibleElements =
127
+ Iterables.filter(this.parent.childNodes, isDisplayed);
128
+ /** @type {!HTMLElement} */ (visibleElements[0]).focus();
129
+ }
121
130
 
122
131
  // Make sure controls are displayed
123
132
  this.controls.computeOpacity();