shaka-player 4.4.3 → 4.5.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 (198) hide show
  1. package/.github/workflows/release-please.yaml +2 -27
  2. package/CHANGELOG.md +64 -45
  3. package/README.md +16 -10
  4. package/demo/asset_card.js +18 -21
  5. package/demo/cast_receiver/index.html +0 -1
  6. package/demo/close_button.js +0 -3
  7. package/demo/common/asset.js +22 -5
  8. package/demo/common/assets.js +132 -49
  9. package/demo/config.js +192 -253
  10. package/demo/custom.js +39 -98
  11. package/demo/front.js +7 -10
  12. package/demo/index.html +19 -22
  13. package/demo/input.js +6 -11
  14. package/demo/input_container.js +8 -9
  15. package/demo/main.js +51 -123
  16. package/demo/search.js +22 -34
  17. package/demo/service_worker.js +0 -3
  18. package/demo/tooltip.js +3 -5
  19. package/demo/visualizer.js +3 -5
  20. package/demo/visualizer_button.js +1 -20
  21. package/dist/demo.compiled.debug.js +152 -178
  22. package/dist/demo.compiled.debug.map +4 -4
  23. package/dist/demo.compiled.js +152 -178
  24. package/dist/demo.compiled.map +4 -4
  25. package/dist/deps.js +27 -24
  26. package/dist/locales.js +31 -31
  27. package/dist/receiver.compiled.debug.js +22 -43
  28. package/dist/receiver.compiled.debug.map +4 -4
  29. package/dist/receiver.compiled.js +22 -43
  30. package/dist/receiver.compiled.map +4 -4
  31. package/dist/shaka-player.compiled.d.ts +507 -365
  32. package/dist/shaka-player.compiled.debug.d.ts +507 -365
  33. package/dist/shaka-player.compiled.debug.externs.js +205 -51
  34. package/dist/shaka-player.compiled.debug.js +541 -450
  35. package/dist/shaka-player.compiled.debug.map +4 -4
  36. package/dist/shaka-player.compiled.externs.js +205 -51
  37. package/dist/shaka-player.compiled.js +1120 -1066
  38. package/dist/shaka-player.compiled.map +4 -4
  39. package/dist/shaka-player.ui.d.ts +562 -410
  40. package/dist/shaka-player.ui.debug.d.ts +562 -410
  41. package/dist/shaka-player.ui.debug.externs.js +226 -51
  42. package/dist/shaka-player.ui.debug.js +606 -506
  43. package/dist/shaka-player.ui.debug.map +4 -4
  44. package/dist/shaka-player.ui.externs.js +226 -51
  45. package/dist/shaka-player.ui.js +1266 -1207
  46. package/dist/shaka-player.ui.map +4 -4
  47. package/docs/design/lcevc-integration.md +14 -14
  48. package/docs/tutorials/faq.md +27 -55
  49. package/docs/tutorials/index.json +2 -1
  50. package/docs/tutorials/lcevc.md +118 -0
  51. package/docs/tutorials/ui-customization.md +4 -0
  52. package/externs/css_style_declaration.js +19 -0
  53. package/externs/lcevc.js +37 -13
  54. package/externs/media_remote.js +68 -0
  55. package/externs/mediatailor.js +193 -0
  56. package/externs/pictureinpicture.js +11 -0
  57. package/externs/shaka/ads.js +27 -0
  58. package/externs/shaka/manifest.js +10 -5
  59. package/externs/shaka/manifest_parser.js +7 -1
  60. package/externs/shaka/offline.js +4 -0
  61. package/externs/shaka/player.js +12 -1
  62. package/karma.conf.js +7 -3
  63. package/lib/abr/simple_abr_manager.js +43 -3
  64. package/lib/ads/ad_manager.js +104 -50
  65. package/lib/ads/media_tailor_ad.js +297 -0
  66. package/lib/ads/media_tailor_ad_manager.js +828 -0
  67. package/lib/cea/ts_cea_parser.js +15 -2
  68. package/lib/config/codec_switching_strategy.js +24 -0
  69. package/lib/dash/content_protection.js +120 -2
  70. package/lib/dash/dash_parser.js +75 -12
  71. package/lib/dash/mpd_utils.js +10 -6
  72. package/lib/dash/segment_base.js +13 -5
  73. package/lib/dash/segment_list.js +13 -5
  74. package/lib/dash/segment_template.js +43 -85
  75. package/lib/dependencies/all.js +8 -7
  76. package/lib/hls/hls_parser.js +44 -16
  77. package/lib/lcevc/lcevc_dec.js +220 -0
  78. package/lib/media/adaptation_set.js +22 -11
  79. package/lib/media/adaptation_set_criteria.js +25 -7
  80. package/lib/media/media_source_engine.js +215 -27
  81. package/lib/media/segment_index.js +1 -1
  82. package/lib/media/segment_reference.js +7 -7
  83. package/lib/media/streaming_engine.js +33 -18
  84. package/lib/mss/mss_parser.js +1 -0
  85. package/lib/net/networking_engine.js +1 -0
  86. package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
  87. package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
  88. package/lib/offline/manifest_converter.js +1 -0
  89. package/lib/offline/storage.js +3 -0
  90. package/lib/player.js +142 -72
  91. package/lib/routing/payload.js +5 -1
  92. package/lib/text/cue.js +15 -0
  93. package/lib/text/ttml_text_parser.js +17 -0
  94. package/lib/text/ui_text_displayer.js +4 -0
  95. package/lib/text/vtt_text_parser.js +33 -20
  96. package/lib/transmuxer/h265.js +862 -0
  97. package/lib/transmuxer/mpeg_ts_transmuxer.js +3 -2
  98. package/lib/transmuxer/ts_transmuxer.js +160 -15
  99. package/lib/util/error.js +28 -9
  100. package/lib/util/exp_golomb.js +30 -2
  101. package/lib/util/fake_event.js +3 -0
  102. package/lib/util/mp4_generator.js +4 -4
  103. package/lib/util/periods.js +2 -0
  104. package/lib/util/platform.js +40 -0
  105. package/lib/util/player_configuration.js +8 -0
  106. package/lib/util/state_history.js +6 -2
  107. package/lib/util/stream_utils.js +133 -217
  108. package/lib/util/ts_parser.js +226 -40
  109. package/maintained-branches.md +3 -2
  110. package/package.json +4 -6
  111. package/roadmap.md +15 -5
  112. package/shaka-player.uncompiled.js +2 -1
  113. package/support.html +0 -1
  114. package/test/cast/cast_receiver_integration.js +47 -0
  115. package/test/codec_switching/codec_switching_integration.js +181 -0
  116. package/test/dash/dash_parser_content_protection_unit.js +2 -0
  117. package/test/dash/dash_parser_integration.js +73 -0
  118. package/test/dash/dash_parser_live_unit.js +2 -0
  119. package/test/dash/dash_parser_manifest_unit.js +42 -0
  120. package/test/dash/dash_parser_segment_base_unit.js +2 -0
  121. package/test/dash/dash_parser_segment_list_unit.js +2 -0
  122. package/test/dash/dash_parser_segment_template_unit.js +2 -0
  123. package/test/demo/demo_unit.js +0 -16
  124. package/test/hls/hls_live_unit.js +2 -0
  125. package/test/hls/hls_parser_unit.js +8 -6
  126. package/test/media/adaptation_set_criteria_unit.js +118 -0
  127. package/test/media/adaptation_set_unit.js +1 -0
  128. package/test/media/media_source_engine_unit.js +165 -1
  129. package/test/media/segment_index_unit.js +4 -4
  130. package/test/media/segment_prefetch_unit.js +1 -1
  131. package/test/media/streaming_engine_unit.js +17 -17
  132. package/test/mss/mss_parser_unit.js +2 -0
  133. package/test/offline/manifest_convert_unit.js +5 -0
  134. package/test/offline/storage_integration.js +1 -4
  135. package/test/player_unit.js +102 -131
  136. package/test/routing/walker_unit.js +1 -0
  137. package/test/test/assets/dash-aes-128/Fragments(video=0,format=mpd-time-csf) +0 -0
  138. package/test/test/assets/dash-aes-128/Fragments(video=20000000,format=mpd-time-csf) +0 -0
  139. package/test/test/assets/dash-aes-128/Fragments(video=40000000,format=mpd-time-csf) +0 -0
  140. package/test/test/assets/dash-aes-128/Fragments(video=60000000,format=mpd-time-csf) +0 -0
  141. package/test/test/assets/dash-aes-128/Fragments(video=i,format=mpd-time-csf) +0 -0
  142. package/test/test/assets/dash-aes-128/dash.mpd +18 -0
  143. package/test/test/assets/dash-aes-128/license +1 -0
  144. package/test/test/assets/dash-multi-codec/audio_en_2c_128k_aac.mp4 +0 -0
  145. package/test/test/assets/dash-multi-codec/audio_es_2c_64k_opus.webm +0 -0
  146. package/test/test/assets/dash-multi-codec/dash.mpd +32 -0
  147. package/test/test/assets/dash-multi-codec/video_144p_108k_h264.mp4 +0 -0
  148. package/test/test/assets/hls-ts-h265/0.ts +0 -0
  149. package/test/test/assets/hls-ts-h265/hevc.m3u8 +6 -0
  150. package/test/test/assets/hls-ts-h265/index.m3u8 +7 -0
  151. package/test/test/assets/hls-ts-muxed-aac-h265/0.ts +0 -0
  152. package/test/test/assets/hls-ts-muxed-aac-h265/1.ts +0 -0
  153. package/test/test/assets/hls-ts-muxed-aac-h265/media.m3u8 +9 -0
  154. package/test/test/assets/hls-ts-muxed-ac3-h264/media.m3u8 +24 -0
  155. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00000.ts +0 -0
  156. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00001.ts +0 -0
  157. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00002.ts +0 -0
  158. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00003.ts +0 -0
  159. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00004.ts +0 -0
  160. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00005.ts +0 -0
  161. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0000.ts +0 -0
  162. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0001.ts +0 -0
  163. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0002.ts +0 -0
  164. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0003.ts +0 -0
  165. package/test/test/assets/hls-ts-muxed-ec3-h264/prog_index.m3u8 +14 -0
  166. package/test/test/assets/hls-ts-muxed-mp3-h264/index.m3u8 +23 -0
  167. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-1-v1-a1.ts +0 -0
  168. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-2-v1-a1.ts +0 -0
  169. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-3-v1-a1.ts +0 -0
  170. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-4-v1-a1.ts +0 -0
  171. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-5-v1-a1.ts +0 -0
  172. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-6-v1-a1.ts +0 -0
  173. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-7-v1-a1.ts +0 -0
  174. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-8-v1-a1.ts +0 -0
  175. package/test/test/util/dash_parser_util.js +4 -0
  176. package/test/test/util/fake_ad_manager.js +20 -0
  177. package/test/test/util/fake_media_source_engine.js +8 -2
  178. package/test/test/util/manifest_generator.js +7 -3
  179. package/test/test/util/mss_parser_util.js +4 -0
  180. package/test/test/util/offline_utils.js +1 -0
  181. package/test/test/util/streaming_engine_util.js +7 -4
  182. package/test/text/ttml_text_parser_unit.js +52 -0
  183. package/test/text/vtt_text_parser_unit.js +103 -31
  184. package/test/transmuxer/transmuxer_integration.js +117 -0
  185. package/test/ui/ui_unit.js +3 -10
  186. package/test/util/stream_utils_unit.js +208 -74
  187. package/ui/controls.js +125 -0
  188. package/ui/externs/ui.js +8 -1
  189. package/ui/pip_button.js +22 -120
  190. package/ui/remote_button.js +201 -0
  191. package/ui/ui.js +5 -2
  192. package/demo/common/message_ids.js +0 -309
  193. package/demo/locales/en.json +0 -288
  194. package/demo/locales/source.json +0 -1146
  195. package/externs/mux.js +0 -69
  196. package/lib/lcevc/lcevc_dil.js +0 -152
  197. package/lib/transmuxer/muxjs_transmuxer.js +0 -242
  198. package/test/transmuxer/muxjs_transmuxer_integration.js +0 -177
@@ -427,10 +427,34 @@ shaka.util.TsParser = class {
427
427
  * @export
428
428
  */
429
429
  parseAvcNalus(pes, nextPes) {
430
+ shaka.Deprecate.deprecateFeature(5,
431
+ 'TsParser',
432
+ 'Please use parseNalus function instead.');
433
+ return this.parseNalus(pes, nextPes);
434
+ }
435
+
436
+ /**
437
+ * Parse AVC and HVC Nalus
438
+ *
439
+ * The code is based on hls.js
440
+ * Credit to https://github.com/video-dev/hls.js/blob/master/src/demux/tsdemuxer.ts
441
+ *
442
+ * @param {shaka.extern.MPEG_PES} pes
443
+ * @param {?shaka.extern.MPEG_PES=} nextPes
444
+ * @param {?shaka.extern.VideoNalu=} lastNalu
445
+ * @return {!Array.<shaka.extern.VideoNalu>}
446
+ * @export
447
+ */
448
+ parseNalus(pes, nextPes, lastNalu) {
430
449
  const timescale = shaka.util.TsParser.Timescale;
431
450
  const time = pes.pts ? pes.pts / timescale : null;
432
- let data = pes.data;
433
- let len = data.byteLength;
451
+ const data = pes.data;
452
+ const len = data.byteLength;
453
+
454
+ let naluHeaderSize = 1;
455
+ if (this.videoCodec_ == 'hvc') {
456
+ naluHeaderSize = 2;
457
+ }
434
458
 
435
459
  // A NALU does not contain is its size.
436
460
  // The Annex B specification solves this by requiring ‘Start Codes’ to
@@ -448,8 +472,6 @@ shaka.util.TsParser = class {
448
472
  // Extracted from the first byte.
449
473
  let lastNaluType = 0;
450
474
 
451
- let tryToFinishLastNalu = false;
452
-
453
475
  /** @type {?shaka.extern.VideoNalu} */
454
476
  let infoOfLastNalu;
455
477
 
@@ -457,25 +479,25 @@ shaka.util.TsParser = class {
457
479
  const value = data[i];
458
480
  if (!value) {
459
481
  numZeros++;
460
- } else if (numZeros >= 2 && value == 1 && tryToFinishLastNalu) {
482
+ } else if (numZeros >= 2 && value == 1 && lastNalu) {
461
483
  // If we are scanning the next PES, we need append the data to the
462
484
  // previous Nalu and don't scan for more nalus.
463
485
  const startCodeSize = numZeros > 3 ? 3 : numZeros;
464
486
  const lastByteToKeep = i - startCodeSize;
465
487
  // Optimization
466
488
  if (lastByteToKeep == 0) {
467
- break;
489
+ return [];
468
490
  }
469
- infoOfLastNalu.data = shaka.util.Uint8ArrayUtils.concat(
470
- infoOfLastNalu.data, data.subarray(0, lastByteToKeep));
471
- infoOfLastNalu.fullData = shaka.util.Uint8ArrayUtils.concat(
472
- infoOfLastNalu.fullData, data.subarray(0, lastByteToKeep));
473
- break;
491
+ lastNalu.data = shaka.util.Uint8ArrayUtils.concat(
492
+ lastNalu.data, data.subarray(0, lastByteToKeep));
493
+ lastNalu.fullData = shaka.util.Uint8ArrayUtils.concat(
494
+ lastNalu.fullData, data.subarray(0, lastByteToKeep));
495
+ return [];
474
496
  } else if (numZeros >= 2 && value == 1) {
475
497
  // We just read a start code. Consume the NALU we passed, if any.
476
498
  if (lastNaluStart >= 0) {
477
- // Because the start position includes the type, skip the first byte.
478
- const firstByteToKeep = lastNaluStart + 1;
499
+ // Because the start position includes the header size.
500
+ const firstByteToKeep = lastNaluStart + naluHeaderSize;
479
501
 
480
502
  // Compute the last byte to keep. The start code is at most 3 zeros.
481
503
  // Any earlier zeros are not part of the start code.
@@ -491,11 +513,17 @@ shaka.util.TsParser = class {
491
513
  time: time,
492
514
  };
493
515
  nalus.push(nalu);
516
+ } else if (lastNalu) {
517
+ const overflow = i - numZeros;
518
+ if (overflow > 0) {
519
+ lastNalu.data = shaka.util.Uint8ArrayUtils.concat(
520
+ lastNalu.data, data.subarray(0, overflow));
521
+ }
494
522
  }
495
523
 
496
524
  // We just read a start code, so there should be another byte here, at
497
525
  // least, for the NALU type. Check just in case.
498
- if (i >= len - 1) {
526
+ if (i >= len - naluHeaderSize) {
499
527
  shaka.log.warning('Malformed TS, incomplete NALU, ignoring.');
500
528
  return nalus;
501
529
  }
@@ -503,7 +531,11 @@ shaka.util.TsParser = class {
503
531
  // Advance and read the type of the next NALU.
504
532
  i++;
505
533
  lastNaluStart = i;
506
- lastNaluType = data[i] & 0x1f;
534
+ if (this.videoCodec_ == 'hvc') {
535
+ lastNaluType = (data[i] >> 1) & 0x3f;
536
+ } else {
537
+ lastNaluType = data[i] & 0x1f;
538
+ }
507
539
  numZeros = 0;
508
540
  } else {
509
541
  numZeros = 0;
@@ -512,27 +544,17 @@ shaka.util.TsParser = class {
512
544
  // unfinished Nalu, we will try to use the next PES to complete the
513
545
  // unfinished Nalu.
514
546
  if (i >= (len - 1) && lastNaluStart >= 0 && numZeros >= 0) {
515
- if (tryToFinishLastNalu) {
516
- infoOfLastNalu.data = shaka.util.Uint8ArrayUtils.concat(
517
- infoOfLastNalu.data, data);
518
- infoOfLastNalu.fullData = shaka.util.Uint8ArrayUtils.concat(
519
- infoOfLastNalu.fullData, data);
520
- } else {
521
- tryToFinishLastNalu = true;
522
- // The rest of the buffer was a NALU.
523
- // Because the start position includes the type, skip the first byte.
524
- const firstByteToKeep = lastNaluStart + 1;
525
- infoOfLastNalu = {
526
- data: data.subarray(firstByteToKeep, len),
527
- fullData: data.subarray(lastNaluStart, len),
528
- type: lastNaluType,
529
- time: time,
530
- };
531
- if (nextPes && pes.packetLength == 0) {
532
- data = nextPes.data;
533
- len = data.byteLength;
534
- i = -1;
535
- }
547
+ // The rest of the buffer was a NALU.
548
+ // Because the start position includes the header size.
549
+ const firstByteToKeep = lastNaluStart + naluHeaderSize;
550
+ infoOfLastNalu = {
551
+ data: data.subarray(firstByteToKeep, len),
552
+ fullData: data.subarray(lastNaluStart, len),
553
+ type: lastNaluType,
554
+ time: time,
555
+ };
556
+ if (nextPes) {
557
+ this.parseNalus(nextPes, /* nextPes= */ null, infoOfLastNalu);
536
558
  }
537
559
  }
538
560
  }
@@ -540,6 +562,12 @@ shaka.util.TsParser = class {
540
562
  if (infoOfLastNalu) {
541
563
  nalus.push(infoOfLastNalu);
542
564
  }
565
+ if (!nalus.length && lastNalu) {
566
+ lastNalu.data = shaka.util.Uint8ArrayUtils.concat(
567
+ lastNalu.data, data);
568
+ lastNalu.fullData = shaka.util.Uint8ArrayUtils.concat(
569
+ lastNalu.fullData, data);
570
+ }
543
571
  return nalus;
544
572
  }
545
573
 
@@ -664,9 +692,6 @@ shaka.util.TsParser = class {
664
692
  */
665
693
  getVideoNalus() {
666
694
  const nalus = [];
667
- if (this.videoCodec_ != 'avc') {
668
- return nalus;
669
- }
670
695
  const videoData = this.getVideoData();
671
696
  for (let i = 0; i < videoData.length; i++) {
672
697
  const pes = videoData[i];
@@ -674,7 +699,7 @@ shaka.util.TsParser = class {
674
699
  if (i + 1 < videoData.length) {
675
700
  nextPes = videoData[i + 1];
676
701
  }
677
- nalus.push(...this.parseAvcNalus(pes, nextPes));
702
+ nalus.push(...this.parseNalus(pes, nextPes));
678
703
  }
679
704
  return nalus;
680
705
  }
@@ -703,6 +728,19 @@ shaka.util.TsParser = class {
703
728
  * @export
704
729
  */
705
730
  getVideoInfo() {
731
+ if (this.videoCodec_ == 'hvc') {
732
+ return this.getHvcInfo_();
733
+ }
734
+ return this.getAvcInfo_();
735
+ }
736
+
737
+ /**
738
+ * Return the video information for AVC
739
+ *
740
+ * @return {{height: ?string, width: ?string, codec: ?string}}
741
+ * @private
742
+ */
743
+ getAvcInfo_() {
706
744
  const TsParser = shaka.util.TsParser;
707
745
  const videoInfo = {
708
746
  height: null,
@@ -823,6 +861,146 @@ shaka.util.TsParser = class {
823
861
  return videoInfo;
824
862
  }
825
863
 
864
+ /**
865
+ * Return the video information for HVC
866
+ *
867
+ * @return {{height: ?string, width: ?string, codec: ?string}}
868
+ * @private
869
+ */
870
+ getHvcInfo_() {
871
+ const TsParser = shaka.util.TsParser;
872
+ const videoInfo = {
873
+ height: null,
874
+ width: null,
875
+ codec: null,
876
+ };
877
+ const videoNalus = this.getVideoNalus();
878
+ if (!videoNalus.length) {
879
+ return videoInfo;
880
+ }
881
+ const spsNalu = videoNalus.find((nalu) => {
882
+ return nalu.type == TsParser.H265_NALU_TYPE_SPS_;
883
+ });
884
+ if (!spsNalu) {
885
+ return videoInfo;
886
+ }
887
+
888
+ const gb = new shaka.util.ExpGolomb(
889
+ spsNalu.fullData, /* convertEbsp2rbsp= */ true);
890
+
891
+ // remove NALu Header
892
+ gb.readUnsignedByte();
893
+ gb.readUnsignedByte();
894
+
895
+ // SPS
896
+ gb.readBits(4); // video_paramter_set_id
897
+ const maxSubLayersMinus1 = gb.readBits(3);
898
+ gb.readBoolean(); // temporal_id_nesting_flag
899
+
900
+ // profile_tier_level begin
901
+ const generalProfileSpace = gb.readBits(2);
902
+ const generalTierFlag = gb.readBits(1);
903
+ const generalProfileIdc = gb.readBits(5);
904
+ const generalProfileCompatibilityFlags = gb.readBits(32);
905
+ const generalConstraintIndicatorFlags1 = gb.readUnsignedByte();
906
+ const generalConstraintIndicatorFlags2 = gb.readUnsignedByte();
907
+ const generalConstraintIndicatorFlags3 = gb.readUnsignedByte();
908
+ const generalConstraintIndicatorFlags4 = gb.readUnsignedByte();
909
+ const generalConstraintIndicatorFlags5 = gb.readUnsignedByte();
910
+ const generalConstraintIndicatorFlags6 = gb.readUnsignedByte();
911
+ const generalLevelIdc = gb.readUnsignedByte();
912
+ const subLayerProfilePresentFlag = [];
913
+ const subLayerLevelPresentFlag = [];
914
+ for (let i = 0; i < maxSubLayersMinus1; i++) {
915
+ subLayerProfilePresentFlag.push(gb.readBoolean());
916
+ subLayerLevelPresentFlag.push(gb.readBoolean());
917
+ }
918
+ if (maxSubLayersMinus1 > 0) {
919
+ for (let i = maxSubLayersMinus1; i < 8; i++) {
920
+ gb.readBits(2);
921
+ }
922
+ }
923
+ for (let i = 0; i < maxSubLayersMinus1; i++) {
924
+ if (subLayerProfilePresentFlag[i]) {
925
+ gb.readBits(88);
926
+ }
927
+ if (subLayerLevelPresentFlag[i]) {
928
+ gb.readUnsignedByte();
929
+ }
930
+ }
931
+ // profile_tier_level end
932
+
933
+ gb.readUnsignedExpGolomb(); // seq_parameter_set_id
934
+ const chromaFormatIdc = gb.readUnsignedExpGolomb();
935
+ if (chromaFormatIdc == 3) {
936
+ gb.readBits(1); // separate_colour_plane_flag
937
+ }
938
+ const picWidthInLumaSamples = gb.readUnsignedExpGolomb();
939
+ const picHeightInLumaSamples = gb.readUnsignedExpGolomb();
940
+ let leftOffset = 0;
941
+ let rightOffset = 0;
942
+ let topOffset = 0;
943
+ let bottomOffset = 0;
944
+ const conformanceWindowFlag = gb.readBoolean();
945
+ if (conformanceWindowFlag) {
946
+ leftOffset += gb.readUnsignedExpGolomb();
947
+ rightOffset += gb.readUnsignedExpGolomb();
948
+ topOffset += gb.readUnsignedExpGolomb();
949
+ bottomOffset += gb.readUnsignedExpGolomb();
950
+ }
951
+
952
+ const subWc = chromaFormatIdc === 1 || chromaFormatIdc === 2 ? 2 : 1;
953
+ const subHc = chromaFormatIdc === 1 ? 2 : 1;
954
+ videoInfo.width =
955
+ String(picWidthInLumaSamples - (leftOffset + rightOffset) * subWc);
956
+ videoInfo.height =
957
+ String(picHeightInLumaSamples - (topOffset + bottomOffset) * subHc);
958
+
959
+ const reverseBits = (integer) => {
960
+ let result = 0;
961
+ for (let i = 0; i < 32; i++) {
962
+ result |= ((integer >> i) & 1) << (31 - i);
963
+ }
964
+ return result >>> 0;
965
+ };
966
+
967
+ const profileSpace = ['', 'A', 'B', 'C'][generalProfileSpace];
968
+ const profileCompatibility = reverseBits(generalProfileCompatibilityFlags);
969
+ const tierFlag = generalTierFlag == 1 ? 'H' : 'L';
970
+
971
+ let codec = 'hvc1';
972
+ codec += '.' + profileSpace + generalProfileIdc;
973
+ codec += '.' + profileCompatibility.toString(16).toUpperCase();
974
+ codec += '.' + tierFlag + generalLevelIdc;
975
+ if (generalConstraintIndicatorFlags6) {
976
+ codec += '.' +
977
+ generalConstraintIndicatorFlags6.toString(16).toUpperCase();
978
+ }
979
+ if (generalConstraintIndicatorFlags5) {
980
+ codec += '.' +
981
+ generalConstraintIndicatorFlags5.toString(16).toUpperCase();
982
+ }
983
+ if (generalConstraintIndicatorFlags4) {
984
+ codec += '.' +
985
+ generalConstraintIndicatorFlags4.toString(16).toUpperCase();
986
+ }
987
+ if (generalConstraintIndicatorFlags3) {
988
+ codec += '.' +
989
+ generalConstraintIndicatorFlags3.toString(16).toUpperCase();
990
+ }
991
+ if (generalConstraintIndicatorFlags2) {
992
+ codec += '.' +
993
+ generalConstraintIndicatorFlags2.toString(16).toUpperCase();
994
+ }
995
+ if (generalConstraintIndicatorFlags1) {
996
+ codec += '.' +
997
+ generalConstraintIndicatorFlags1.toString(16).toUpperCase();
998
+ }
999
+ videoInfo.codec = codec;
1000
+
1001
+ return videoInfo;
1002
+ }
1003
+
826
1004
  /**
827
1005
  * Convert a byte to 2 digits of hex. (Only handles values 0-255.)
828
1006
  *
@@ -904,6 +1082,14 @@ shaka.util.TsParser.PacketLength_ = 188;
904
1082
  shaka.util.TsParser.H264_NALU_TYPE_SPS_ = 0x07;
905
1083
 
906
1084
 
1085
+ /**
1086
+ * NALU type for Sequence Parameter Set (SPS) for H.265.
1087
+ * @const {number}
1088
+ * @private
1089
+ */
1090
+ shaka.util.TsParser.H265_NALU_TYPE_SPS_ = 0x21;
1091
+
1092
+
907
1093
  /**
908
1094
  * Values of profile_idc that indicate additional fields are included in the
909
1095
  * SPS.
@@ -2,8 +2,9 @@
2
2
 
3
3
  We are currently maintaining the following branches of Shaka Player:
4
4
 
5
- - v4.4 (latest)
6
- - v4.3 (previous, also in use by the Cast Application Framework)
5
+ - v4.5 (latest)
6
+ - v4.4 (previous)
7
+ - v4.3 (in use by the Cast Application Framework)
7
8
  - No active LTS branches at this time
8
9
 
9
10
  Other branches are no longer receiving bug fixes, and we recommend you upgrade
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "shaka-player",
3
3
  "description": "DASH/EME video player library",
4
- "version": "4.4.3",
4
+ "version": "4.5.0",
5
5
  "homepage": "https://github.com/shaka-project/shaka-player",
6
6
  "author": "Google",
7
7
  "maintainers": [
@@ -48,11 +48,10 @@
48
48
  "karma-sourcemap-loader": "^0.3.8",
49
49
  "karma-spec-reporter": "^0.0.34",
50
50
  "karma-webdriver-launcher": "^1.0.8",
51
- "lcevc_dil.js": "^1.1.20",
51
+ "lcevc_dec.js": "^1.0.0",
52
52
  "less": "https://gitpkg.now.sh/joeyparrish/less.js/packages/less?28c63a43",
53
53
  "less-plugin-clean-css": "github:austingardner/less-plugin-clean-css#4e9e77bf",
54
54
  "material-design-lite": "^1.3.0",
55
- "mux.js": "^6.2.0",
56
55
  "open-sans-fonts": "^1.6.2",
57
56
  "postcss-less": "^6.0.0",
58
57
  "pwacompat": "^2.0.17",
@@ -75,12 +74,11 @@
75
74
  "eme-encryption-scheme-polyfill/index.js",
76
75
  "es6-promise-polyfill/promise.min.js",
77
76
  "google-closure-library/closure/goog/base.js",
78
- "lcevc_dil.js/dist/lcevc_dil.min.js",
79
- "lcevc_dil.js/dist/liblcevc_dpi.wasm",
77
+ "lcevc_dec.js/dist/lcevc_dec.min.js",
78
+ "lcevc_dec.js/dist/liblcevc_dpi.wasm",
80
79
  "less/dist/less.js",
81
80
  "material-design-lite/dist/material.indigo-blue.min.css",
82
81
  "material-design-lite/dist/material.min.js",
83
- "mux.js/dist/mux.min.js",
84
82
  "popper.js/dist/umd/popper.min.js",
85
83
  "pwacompat/pwacompat.min.js",
86
84
  "tippy.js/umd/index.min.js",
package/roadmap.md CHANGED
@@ -9,22 +9,32 @@ The goals of future milestones are fluid until we begin that development cycle,
9
9
  so the exact milestone for future features is not pre-determined.
10
10
 
11
11
  Candidate features for future release cycles:
12
- - Preload API
13
- https://github.com/shaka-project/shaka-player/issues/880
14
12
  - Official TypeScript defs, generated from source
15
13
  https://github.com/shaka-project/shaka-player/issues/1030
16
14
  - Background fetch for offline storage
17
15
  https://github.com/shaka-project/shaka-player/issues/879
18
16
  - Smaller, more modular binary
19
17
 
20
- v4.5 - 2023 Q4 or 2024 Q1
18
+ v4.6 - 2024 Q1
19
+ - Content Steering
20
+ https://github.com/shaka-project/shaka-player/issues/5704
21
+ - Preload API
22
+ https://github.com/shaka-project/shaka-player/issues/880
23
+ - New DASH protocol for Low Latency.
24
+ - ManagedMediaSource
25
+ https://github.com/shaka-project/shaka-player/issues/5271
26
+
27
+ =====
28
+
29
+ v4.5 - 2023 Q4
21
30
  - Built-in transmuxer support for muxed content streams (audio+video)
22
31
  - Built-in transmuxer support for H265 streams
23
32
  - Remove optional mux.js dependency
24
33
  - Codec switching
25
34
  https://github.com/shaka-project/shaka-player/issues/1528
26
-
27
- =====
35
+ - AES-128 in DASH.
36
+ https://github.com/shaka-project/shaka-player/issues/5622
37
+ - AWS Elemental MediaTailor
28
38
 
29
39
  v4.4 - 2023 Q3
30
40
  - Built-in transmuxer for common cases, no mux.js required:
@@ -72,12 +72,12 @@ goog.require('shaka.transmuxer.ADTS');
72
72
  goog.require('shaka.transmuxer.Ec3');
73
73
  goog.require('shaka.transmuxer.Ec3Transmuxer');
74
74
  goog.require('shaka.transmuxer.H264');
75
+ goog.require('shaka.transmuxer.H265');
75
76
  goog.require('shaka.transmuxer.Mp3Transmuxer');
76
77
  goog.require('shaka.transmuxer.MpegAudio');
77
78
  goog.require('shaka.transmuxer.MpegTsTransmuxer');
78
79
  goog.require('shaka.transmuxer.TransmuxerEngine');
79
80
  goog.require('shaka.transmuxer.MssTransmuxer');
80
- goog.require('shaka.transmuxer.MuxjsTransmuxer');
81
81
  goog.require('shaka.transmuxer.TsTransmuxer');
82
82
  goog.require('shaka.ui.Controls');
83
83
  goog.require('shaka.ui.PlayButton');
@@ -100,6 +100,7 @@ goog.require('shaka.ui.Overlay');
100
100
  goog.require('shaka.ui.PipButton');
101
101
  goog.require('shaka.ui.PlaybackRateSelection');
102
102
  goog.require('shaka.ui.PresentationTimeTracker');
103
+ goog.require('shaka.ui.RemoteButton');
103
104
  goog.require('shaka.ui.ResolutionSelection');
104
105
  goog.require('shaka.ui.RewindButton');
105
106
  goog.require('shaka.ui.SkipAdButton');
package/support.html CHANGED
@@ -38,7 +38,6 @@
38
38
  }
39
39
 
40
40
  </style>
41
- <script defer src="node_modules/mux.js/dist/mux.min.js"></script>
42
41
  <script src="dist/shaka-player.compiled.js"></script>
43
42
  <script>
44
43
  function whenLoaded(fn) {
@@ -139,6 +139,53 @@ filterDescribe('CastReceiver', castReceiverIntegrationSupport, () => {
139
139
  }
140
140
  });
141
141
 
142
+ describe('state changed event', () => {
143
+ it('does not trigger a stack overflow', async () => {
144
+ const p = waitForLoadedData();
145
+
146
+ // We had a regression in which polling attributes eventually triggered a
147
+ // stack overflow because of a state change event that fired every time
148
+ // we checked the state. The error itself got swallowed and hidden
149
+ // inside CastReceiver, but would cause tests to disconnect in some
150
+ // environments (consistently in GitHub Actions VMs, inconsistently
151
+ // elsewhere).
152
+ //
153
+ // Testing for this is subtle: if we try to catch the error, it will be
154
+ // caught at a point when the stack has already or is about to overflow.
155
+ // Then if we call "fail", Jasmine will grow the stack further,
156
+ // triggering *another* overflow inside of fail(), causing our test to
157
+ // *pass*. So we need to fail fast. The best way I have found is to
158
+ // catch the very first recursion of pollAttributes_, long before we
159
+ // overflow, fail, then return early to avoid the actual recursion.
160
+ const original = /** @type {?} */(receiver).pollAttributes_;
161
+ let numRecursions = 0;
162
+ // eslint-disable-next-line no-restricted-syntax
163
+ /** @type {?} */(receiver).pollAttributes_ = function() {
164
+ try {
165
+ if (numRecursions > 0) {
166
+ fail('Found recursion in pollAttributes_!');
167
+ return undefined;
168
+ }
169
+
170
+ numRecursions++;
171
+ return original.apply(receiver, arguments);
172
+ } finally {
173
+ numRecursions--;
174
+ }
175
+ };
176
+
177
+ // Start the process of loading by sending a fake init message.
178
+ fakeConnectedSenders(1);
179
+ fakeIncomingMessage({
180
+ type: 'init',
181
+ initState: fakeInitState,
182
+ appData: {},
183
+ }, mockShakaMessageBus);
184
+
185
+ await p;
186
+ });
187
+ });
188
+
142
189
  describe('without drm', () => {
143
190
  it('sends reasonably-sized updates', async () => {
144
191
  // Use an unencrypted asset.