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
@@ -36,17 +36,19 @@ shaka.dash.SegmentTemplate = class {
36
36
  * @param {number} segmentLimit The maximum number of segments to generate for
37
37
  * a SegmentTemplate with fixed duration.
38
38
  * @param {!Object.<string, number>} periodDurationMap
39
+ * @param {shaka.extern.aes128Key|undefined} aes128Key
39
40
  * @return {shaka.dash.DashParser.StreamInfo}
40
41
  */
41
42
  static createStreamInfo(
42
43
  context, requestSegment, streamMap, isUpdate, segmentLimit,
43
- periodDurationMap) {
44
+ periodDurationMap, aes128Key) {
44
45
  goog.asserts.assert(context.representation.segmentTemplate,
45
46
  'Should only be called with SegmentTemplate');
46
47
  const SegmentTemplate = shaka.dash.SegmentTemplate;
47
48
  const TimelineSegmentIndex = shaka.dash.TimelineSegmentIndex;
48
49
 
49
- const initSegmentReference = SegmentTemplate.createInitSegment_(context);
50
+ const initSegmentReference =
51
+ SegmentTemplate.createInitSegment_(context, aes128Key);
50
52
 
51
53
  /** @type {shaka.dash.SegmentTemplate.SegmentTemplateInfo} */
52
54
  const info = SegmentTemplate.parseSegmentTemplateInfo_(context);
@@ -82,7 +84,7 @@ shaka.dash.SegmentTemplate = class {
82
84
  generateSegmentIndex: () => {
83
85
  return SegmentTemplate.generateSegmentIndexFromDuration_(
84
86
  shallowCopyOfContext, info, segmentLimit, initSegmentReference,
85
- periodDurationMap);
87
+ periodDurationMap, aes128Key);
86
88
  },
87
89
  };
88
90
  } else {
@@ -134,6 +136,7 @@ shaka.dash.SegmentTemplate = class {
134
136
  periodEnd,
135
137
  initSegmentReference,
136
138
  shouldFit,
139
+ aes128Key,
137
140
  );
138
141
  } else {
139
142
  const tsi = /** @type {!TimelineSegmentIndex} */(segmentIndex);
@@ -299,11 +302,13 @@ shaka.dash.SegmentTemplate = class {
299
302
  * @param {number} segmentLimit The maximum number of segments to generate.
300
303
  * @param {shaka.media.InitSegmentReference} initSegmentReference
301
304
  * @param {!Object.<string, number>} periodDurationMap
305
+ * @param {shaka.extern.aes128Key|undefined} aes128Key
302
306
  * @return {!Promise.<shaka.media.SegmentIndex>}
303
307
  * @private
304
308
  */
305
309
  static generateSegmentIndexFromDuration_(
306
- context, info, segmentLimit, initSegmentReference, periodDurationMap) {
310
+ context, info, segmentLimit, initSegmentReference, periodDurationMap,
311
+ aes128Key) {
307
312
  goog.asserts.assert(info.mediaTemplate,
308
313
  'There should be a media template with duration');
309
314
 
@@ -419,9 +424,12 @@ shaka.dash.SegmentTemplate = class {
419
424
  info.scaledPresentationTimeOffset;
420
425
 
421
426
  const getUris = () => {
427
+ let time = segmentMediaTime * timescale;
428
+ if ('BigInt' in window && time > Number.MAX_SAFE_INTEGER) {
429
+ time = BigInt(segmentMediaTime) * BigInt(timescale);
430
+ }
422
431
  const mediaUri = MpdUtils.fillUriTemplate(
423
- template, id, position, bandwidth,
424
- segmentMediaTime * timescale);
432
+ template, id, position, bandwidth, time);
425
433
  return ManifestParserUtils.resolveUris(baseUris, [mediaUri]);
426
434
  };
427
435
 
@@ -446,7 +454,13 @@ shaka.dash.SegmentTemplate = class {
446
454
  initSegmentReference,
447
455
  timestampOffset,
448
456
  /* appendWindowStart= */ periodStart,
449
- /* appendWindowEnd= */ getPeriodEnd());
457
+ /* appendWindowEnd= */ getPeriodEnd(),
458
+ /* partialReferences= */ [],
459
+ /* tilesLayout= */ '',
460
+ /* tileDuration= */ null,
461
+ /* syncTime= */ null,
462
+ shaka.media.SegmentReference.Status.AVAILABLE,
463
+ aes128Key);
450
464
  // This is necessary information for thumbnail streams:
451
465
  ref.trueEndTime = trueSegmentEnd;
452
466
  return ref;
@@ -505,87 +519,15 @@ shaka.dash.SegmentTemplate = class {
505
519
  return Promise.resolve(segmentIndex);
506
520
  }
507
521
 
508
- /**
509
- * Creates segment references from a timeline.
510
- *
511
- * @param {shaka.dash.DashParser.Context} context
512
- * @param {shaka.dash.SegmentTemplate.SegmentTemplateInfo} info
513
- * @param {shaka.media.InitSegmentReference} initSegmentReference
514
- * @return {!Array.<!shaka.media.SegmentReference>}
515
- * @private
516
- */
517
- static createFromTimeline_(context, info, initSegmentReference) {
518
- const MpdUtils = shaka.dash.MpdUtils;
519
- const ManifestParserUtils = shaka.util.ManifestParserUtils;
520
-
521
- const periodStart = context.periodInfo.start;
522
- const periodDuration = context.periodInfo.duration;
523
-
524
- const timestampOffset = periodStart - info.scaledPresentationTimeOffset;
525
- const appendWindowStart = periodStart;
526
- const appendWindowEnd = periodDuration ?
527
- periodStart + periodDuration : Infinity;
528
-
529
- /** @type {!Array.<!shaka.media.SegmentReference>} */
530
- const references = [];
531
- for (let i = 0; i < info.timeline.length; i++) {
532
- const {start, unscaledStart, end} = info.timeline[i];
533
-
534
- // Note: i = k - 1, where k indicates the k'th segment listed in the MPD.
535
- // (See section 5.3.9.5.3 of the DASH spec.)
536
- const segmentReplacement = i + info.startNumber;
537
-
538
- // Consider the presentation time offset in segment uri computation
539
- const timeReplacement = unscaledStart +
540
- info.unscaledPresentationTimeOffset;
541
- const repId = context.representation.id;
542
- const bandwidth = context.bandwidth || null;
543
- const mediaTemplate = info.mediaTemplate;
544
- const baseUris = context.representation.baseUris;
545
-
546
- // This callback must not capture any non-local
547
- // variables, such as info, context, etc. Make
548
- // sure any values you reference here have
549
- // been assigned to local variables within the
550
- // loop, or else we will end up with a leak.
551
- const createUris =
552
- () => {
553
- goog.asserts.assert(
554
- mediaTemplate,
555
- 'There should be a media template with a timeline');
556
- const mediaUri = MpdUtils.fillUriTemplate(
557
- mediaTemplate, repId,
558
- segmentReplacement, bandwidth || null, timeReplacement);
559
- return ManifestParserUtils
560
- .resolveUris(baseUris, [mediaUri])
561
- .map((g) => {
562
- return g.toString();
563
- });
564
- };
565
-
566
- references.push(new shaka.media.SegmentReference(
567
- periodStart + start,
568
- periodStart + end,
569
- createUris,
570
- /* startByte= */ 0,
571
- /* endByte= */ null,
572
- initSegmentReference,
573
- timestampOffset,
574
- appendWindowStart,
575
- appendWindowEnd));
576
- }
577
-
578
- return references;
579
- }
580
-
581
522
  /**
582
523
  * Creates an init segment reference from a context object.
583
524
  *
584
525
  * @param {shaka.dash.DashParser.Context} context
526
+ * @param {shaka.extern.aes128Key|undefined} aes128Key
585
527
  * @return {shaka.media.InitSegmentReference}
586
528
  * @private
587
529
  */
588
- static createInitSegment_(context) {
530
+ static createInitSegment_(context, aes128Key) {
589
531
  const MpdUtils = shaka.dash.MpdUtils;
590
532
  const ManifestParserUtils = shaka.util.ManifestParserUtils;
591
533
  const SegmentTemplate = shaka.dash.SegmentTemplate;
@@ -608,7 +550,14 @@ shaka.dash.SegmentTemplate = class {
608
550
  return resolvedUris;
609
551
  };
610
552
  const qualityInfo = shaka.dash.SegmentBase.createQualityInfo(context);
611
- return new shaka.media.InitSegmentReference(getUris, 0, null, qualityInfo);
553
+ return new shaka.media.InitSegmentReference(
554
+ getUris,
555
+ /* startByte= */ 0,
556
+ /* endByte= */ null,
557
+ qualityInfo,
558
+ /* timescale= */ null,
559
+ /* segmentData= */ null,
560
+ aes128Key);
612
561
  }
613
562
  };
614
563
 
@@ -635,10 +584,11 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
635
584
  * @param {number} periodEnd
636
585
  * @param {shaka.media.InitSegmentReference} initSegmentReference
637
586
  * @param {boolean} shouldFit
638
- *
587
+ * @param {shaka.extern.aes128Key|undefined} aes128Key
639
588
  */
640
589
  constructor(templateInfo, representationId, bandwidth, baseUris,
641
- periodStart, periodEnd, initSegmentReference, shouldFit) {
590
+ periodStart, periodEnd, initSegmentReference, shouldFit,
591
+ aes128Key) {
642
592
  super([]);
643
593
 
644
594
  /** @private {?shaka.dash.SegmentTemplate.SegmentTemplateInfo} */
@@ -655,6 +605,8 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
655
605
  this.periodEnd_ = periodEnd;
656
606
  /** @private {shaka.media.InitSegmentReference} */
657
607
  this.initSegmentReference_ = initSegmentReference;
608
+ /** @private {shaka.extern.aes128Key|undefined} */
609
+ this.aes128Key_ = aes128Key;
658
610
 
659
611
 
660
612
  if (shouldFit) {
@@ -894,7 +846,13 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
894
846
  this.initSegmentReference_,
895
847
  timestampOffset,
896
848
  this.periodStart_,
897
- this.periodEnd_);
849
+ this.periodEnd_,
850
+ /* partialReferences= */ [],
851
+ /* tilesLayout= */ '',
852
+ /* tileDuration= */ null,
853
+ /* syncTime= */ null,
854
+ shaka.media.SegmentReference.Status.AVAILABLE,
855
+ this.aes128Key_);
898
856
  this.references[correctedPosition] = ref;
899
857
  }
900
858
 
@@ -6,6 +6,8 @@
6
6
 
7
7
  goog.provide('shaka.dependencies');
8
8
 
9
+ goog.require('shaka.Deprecate');
10
+
9
11
  /**
10
12
  * @export
11
13
  */
@@ -22,6 +24,12 @@ shaka.dependencies = class {
22
24
  if (!shaka.dependencies.Allowed[key]) {
23
25
  throw new Error(`${key} is not supported`);
24
26
  }
27
+ if (key == shaka.dependencies.Allowed.muxjs) {
28
+ shaka.Deprecate.deprecateFeature(5,
29
+ 'mux.js',
30
+ 'mux.js is no longer used in Shaka Player.');
31
+ return;
32
+ }
25
33
  shaka.dependencies.dependencies_.set(key, () => dep);
26
34
  }
27
35
 
@@ -36,12 +44,6 @@ shaka.dependencies = class {
36
44
  return shaka.dependencies.dependencies_.has(key);
37
45
  }
38
46
 
39
- /** @return {?muxjs} */
40
- static muxjs() {
41
- return /** @type {?muxjs} */ (shaka.dependencies.dependencies_.get(
42
- shaka.dependencies.Allowed.muxjs)());
43
- }
44
-
45
47
  /** @return {?ISOBoxer} */
46
48
  static isoBoxer() {
47
49
  return /** @type {?ISOBoxer} */ (shaka.dependencies.dependencies_.get(
@@ -65,6 +67,5 @@ shaka.dependencies.Allowed = {
65
67
  * @private {!Map.<shaka.dependencies.Allowed, function():?>}
66
68
  */
67
69
  shaka.dependencies.dependencies_ = new Map([
68
- [shaka.dependencies.Allowed.muxjs, () => window.muxjs],
69
70
  [shaka.dependencies.Allowed.ISOBoxer, () => window.ISOBoxer],
70
71
  ]);
@@ -9,6 +9,7 @@ goog.provide('shaka.hls.HlsParser');
9
9
 
10
10
  goog.require('goog.Uri');
11
11
  goog.require('goog.asserts');
12
+ goog.require('shaka.abr.Ewma');
12
13
  goog.require('shaka.hls.ManifestTextParser');
13
14
  goog.require('shaka.hls.Playlist');
14
15
  goog.require('shaka.hls.PlaylistType');
@@ -215,6 +216,13 @@ shaka.hls.HlsParser = class {
215
216
 
216
217
  /** @private {boolean} */
217
218
  this.lowLatencyByterangeOptimization_ = false;
219
+
220
+ /**
221
+ * An ewma that tracks how long updates take.
222
+ * This is to mitigate issues caused by slow parsing on embedded devices.
223
+ * @private {!shaka.abr.Ewma}
224
+ */
225
+ this.averageUpdateDuration_ = new shaka.abr.Ewma(5);
218
226
  }
219
227
 
220
228
 
@@ -932,7 +940,11 @@ shaka.hls.HlsParser = class {
932
940
  hasVideo = true;
933
941
  break;
934
942
  case 'hvc':
935
- codecs.push('hvc1.1.6.L93.90');
943
+ if (videoInfo.codec) {
944
+ codecs.push(videoInfo.codec);
945
+ } else {
946
+ codecs.push('hvc1.1.6.L93.90');
947
+ }
936
948
  hasVideo = true;
937
949
  break;
938
950
  }
@@ -2493,6 +2505,7 @@ shaka.hls.HlsParser = class {
2493
2505
  return {
2494
2506
  id: this.globalId_++,
2495
2507
  originalId: name,
2508
+ groupId: null,
2496
2509
  createSegmentIndex: () => Promise.resolve(),
2497
2510
  segmentIndex: null,
2498
2511
  mimeType,
@@ -2595,7 +2608,7 @@ shaka.hls.HlsParser = class {
2595
2608
  /**
2596
2609
  * @param {!shaka.hls.Tag} drmTag
2597
2610
  * @param {!shaka.hls.Playlist} playlist
2598
- * @return {!shaka.extern.HlsAes128Key}
2611
+ * @return {!shaka.extern.aes128Key}
2599
2612
  * @private
2600
2613
  */
2601
2614
  parseAES128DrmTag_(drmTag, playlist) {
@@ -2629,7 +2642,7 @@ shaka.hls.HlsParser = class {
2629
2642
  throw new shaka.util.Error(
2630
2643
  shaka.util.Error.Severity.CRITICAL,
2631
2644
  shaka.util.Error.Category.MANIFEST,
2632
- shaka.util.Error.Code.HLS_AES_128_INVALID_IV_LENGTH);
2645
+ shaka.util.Error.Code.AES_128_INVALID_IV_LENGTH);
2633
2646
  }
2634
2647
  }
2635
2648
 
@@ -2652,7 +2665,7 @@ shaka.hls.HlsParser = class {
2652
2665
  throw new shaka.util.Error(
2653
2666
  shaka.util.Error.Severity.CRITICAL,
2654
2667
  shaka.util.Error.Category.MANIFEST,
2655
- shaka.util.Error.Code.HLS_AES_128_INVALID_KEY_LENGTH);
2668
+ shaka.util.Error.Code.AES_128_INVALID_KEY_LENGTH);
2656
2669
  }
2657
2670
 
2658
2671
  const algorithm = {
@@ -2844,7 +2857,7 @@ shaka.hls.HlsParser = class {
2844
2857
  mapTag.getAttributeValue('BYTERANGE', ''),
2845
2858
  ].join('-');
2846
2859
  if (!this.mapTagToInitSegmentRefMap_.has(mapTagKey)) {
2847
- /** @type {shaka.extern.HlsAes128Key|undefined} */
2860
+ /** @type {shaka.extern.aes128Key|undefined} */
2848
2861
  let aes128Key = undefined;
2849
2862
  for (const tag of tags) {
2850
2863
  if (tag.name == 'EXT-X-KEY') {
@@ -2866,7 +2879,7 @@ shaka.hls.HlsParser = class {
2866
2879
  * playlist.
2867
2880
  * @param {string} absoluteInitSegmentUri
2868
2881
  * @param {!shaka.hls.Tag} mapTag EXT-X-MAP
2869
- * @param {shaka.extern.HlsAes128Key=} aes128Key
2882
+ * @param {shaka.extern.aes128Key=} aes128Key
2870
2883
  * @return {!shaka.media.InitSegmentReference}
2871
2884
  * @private
2872
2885
  */
@@ -2915,13 +2928,13 @@ shaka.hls.HlsParser = class {
2915
2928
  * @param {string} absoluteMediaPlaylistUri
2916
2929
  * @param {string} type
2917
2930
  * @param {string} mimeType
2918
- * @param {shaka.extern.HlsAes128Key=} hlsAes128Key
2931
+ * @param {shaka.extern.aes128Key=} aes128Key
2919
2932
  * @return {shaka.media.SegmentReference}
2920
2933
  * @private
2921
2934
  */
2922
2935
  createSegmentReference_(
2923
2936
  initSegmentReference, previousReference, hlsSegment, startTime,
2924
- variables, absoluteMediaPlaylistUri, type, mimeType, hlsAes128Key) {
2937
+ variables, absoluteMediaPlaylistUri, type, mimeType, aes128Key) {
2925
2938
  const tags = hlsSegment.tags;
2926
2939
  const extinfTag =
2927
2940
  shaka.hls.Utils.getFirstTagWithName(tags, 'EXTINF');
@@ -3066,7 +3079,7 @@ shaka.hls.HlsParser = class {
3066
3079
  /* tileDuration= */ null,
3067
3080
  partialSyncTime,
3068
3081
  partialStatus,
3069
- hlsAes128Key);
3082
+ aes128Key);
3070
3083
  if (item.name == 'EXT-X-PRELOAD-HINT') {
3071
3084
  partial.markAsPreload();
3072
3085
  isPreloadSegment = true;
@@ -3178,7 +3191,7 @@ shaka.hls.HlsParser = class {
3178
3191
  tileDuration,
3179
3192
  syncTime,
3180
3193
  status,
3181
- hlsAes128Key,
3194
+ aes128Key,
3182
3195
  );
3183
3196
 
3184
3197
  if (segmentWithByteRangeOptimization) {
@@ -3245,8 +3258,8 @@ shaka.hls.HlsParser = class {
3245
3258
  /** @type {shaka.media.InitSegmentReference} */
3246
3259
  let initSegmentRef;
3247
3260
 
3248
- /** @type {shaka.extern.HlsAes128Key|undefined} */
3249
- let hlsAes128Key = undefined;
3261
+ /** @type {shaka.extern.aes128Key|undefined} */
3262
+ let aes128Key = undefined;
3250
3263
 
3251
3264
  let discontinuitySequence = shaka.hls.Utils.getFirstTagWithNameAsNumber(
3252
3265
  playlist.tags, 'EXT-X-DISCONTINUITY-SEQUENCE', 0);
@@ -3289,9 +3302,9 @@ shaka.hls.HlsParser = class {
3289
3302
  for (const drmTag of item.tags) {
3290
3303
  if (drmTag.name == 'EXT-X-KEY') {
3291
3304
  if (drmTag.getRequiredAttrValue('METHOD') == 'AES-128') {
3292
- hlsAes128Key = this.parseAES128DrmTag_(drmTag, playlist);
3305
+ aes128Key = this.parseAES128DrmTag_(drmTag, playlist);
3293
3306
  } else {
3294
- hlsAes128Key = undefined;
3307
+ aes128Key = undefined;
3295
3308
  }
3296
3309
  }
3297
3310
  }
@@ -3322,7 +3335,7 @@ shaka.hls.HlsParser = class {
3322
3335
  playlist.absoluteUri,
3323
3336
  type,
3324
3337
  mimeType,
3325
- hlsAes128Key);
3338
+ aes128Key);
3326
3339
 
3327
3340
  if (reference) {
3328
3341
  const bitrate = shaka.hls.Utils.getFirstTagWithNameAsNumber(
@@ -3690,12 +3703,20 @@ shaka.hls.HlsParser = class {
3690
3703
  }
3691
3704
 
3692
3705
  try {
3706
+ const startTime = Date.now();
3693
3707
  await this.update();
3694
3708
 
3709
+ // Keep track of how long the longest manifest update took.
3710
+ const endTime = Date.now();
3711
+
3695
3712
  // This may have converted to VOD, in which case we stop updating.
3696
3713
  if (this.isLive_()) {
3714
+ const updateDuration = (endTime - startTime) / 1000.0;
3715
+ this.averageUpdateDuration_.sample(1, updateDuration);
3697
3716
  const delay = this.getUpdatePlaylistDelay_();
3698
- this.updatePlaylistTimer_.tickAfter(/* seconds= */ delay);
3717
+ const finalDelay = Math.max(0,
3718
+ delay - this.averageUpdateDuration_.getEstimate());
3719
+ this.updatePlaylistTimer_.tickAfter(/* seconds= */ finalDelay);
3699
3720
  }
3700
3721
  } catch (error) {
3701
3722
  // Detect a call to stop() during this.update()
@@ -3718,6 +3739,13 @@ shaka.hls.HlsParser = class {
3718
3739
  // Try again very soon.
3719
3740
  this.updatePlaylistTimer_.tickAfter(/* seconds= */ 0.1);
3720
3741
  }
3742
+
3743
+ // Detect a call to stop()
3744
+ if (!this.playerInterface_) {
3745
+ return;
3746
+ }
3747
+
3748
+ this.playerInterface_.onManifestUpdated();
3721
3749
  }
3722
3750
 
3723
3751
 
@@ -0,0 +1,220 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ goog.provide('shaka.lcevc.Dec');
8
+ goog.require('shaka.log');
9
+ goog.require('shaka.Deprecate');
10
+ goog.require('shaka.util.IReleasable');
11
+
12
+ /**
13
+ * @summary
14
+ * lcevcDec - (MPEG-5 Part 2 LCEVC - Decoder) provides
15
+ * all the operations related to the enhancement and rendering
16
+ * of LCEVC enabled streams and on to a canvas.
17
+ * @implements {shaka.util.IReleasable}
18
+ * @export
19
+ */
20
+ shaka.lcevc.Dec = class {
21
+ /**
22
+ * @param {HTMLVideoElement} media The video element that will be attached to
23
+ * LCEVC Decoder for input.
24
+ * @param {HTMLCanvasElement} canvas The canvas element that will be attached
25
+ * to LCEVC Decoder to render the enhanced frames.
26
+ * @param {shaka.extern.LcevcConfiguration} lcevcConfig LCEVC configuration
27
+ * object to initialize the LCEVC Decoder.
28
+ */
29
+ constructor(media, canvas, lcevcConfig) {
30
+ /**
31
+ * LCEVC Decoder library based on availability, to check if either
32
+ * lcevc_dil or lcevc_dec is present.
33
+ * @private {LCEVCmodule}
34
+ */
35
+ this.lcevcLib_;
36
+
37
+ /** @private {?LCEVCdec.LCEVCdec} */
38
+ this.dec_ = null;
39
+
40
+ /** @private {number} */
41
+ this.variantId_ = -1;
42
+
43
+ /** @private {HTMLVideoElement} */
44
+ this.media_ = media;
45
+
46
+ /** @private {HTMLCanvasElement} */
47
+ this.canvas_ = canvas;
48
+
49
+ /** @private {shaka.extern.LcevcConfiguration} */
50
+ this.decConfig_ = lcevcConfig;
51
+
52
+ /** @private {boolean} */
53
+ this.toBeDeprecated_ = false;
54
+
55
+ this.create_();
56
+ }
57
+
58
+ /**
59
+ * Append data to the LCEVC Dec.
60
+ * @param {BufferSource} data
61
+ * @param {number} timestampOffset
62
+ */
63
+ appendBuffer(data, timestampOffset) {
64
+ if (this.dec_) {
65
+ // Timestamp offset describes how much offset should be applied to the
66
+ // LCEVC enhancement to match the decoded video frame, as such it needs
67
+ // to be negated.
68
+ this.dec_.appendBuffer(data, 'video', this.variantId_, -timestampOffset);
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Hide the canvas specifically in the case of a DRM Content
74
+ */
75
+ hideCanvas() {
76
+ if (this.dec_) {
77
+ this.canvas_.classList.add('shaka-hidden');
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Create LCEVC Decoder.
83
+ * @private
84
+ */
85
+ create_() {
86
+ if (this.isSupported_() && !this.dec_) {
87
+ if (this.lcevcLib_.SupportObject.webGLSupport(this.canvas_)) {
88
+ // Make sure the canvas is not hidden from a previous playback session.
89
+ this.canvas_.classList.remove('shaka-hidden');
90
+ // Initiate LCEVC Dec Library based on the type of module available.
91
+ if (this.toBeDeprecated_) {
92
+ this.dec_ = new this.lcevcLib_.LcevcDil(
93
+ this.media_,
94
+ this.canvas_,
95
+ this.decConfig_);
96
+ } else {
97
+ this.dec_ = new this.lcevcLib_.LCEVCdec(
98
+ this.media_,
99
+ this.canvas_,
100
+ this.decConfig_);
101
+ }
102
+ }
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Close LCEVC Decoder.
108
+ * @override
109
+ * @export
110
+ */
111
+ release() {
112
+ if (this.dec_) {
113
+ this.dec_.close();
114
+ this.dec_ = null;
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Check if the LCEVC Decoder lib is present and is supported by the browser.
120
+ * @return {boolean}
121
+ * @private
122
+ */
123
+ isSupported_() {
124
+ if (typeof libDPIModule === 'undefined') {
125
+ shaka.log.alwaysWarn(
126
+ 'Could not find LCEVC Library dependencies on this page');
127
+ }
128
+
129
+ // This is a check to make the LCEVC Dec Integration is backwards compatible
130
+ // with previous Integration. This logic checks for both implementations
131
+ // and uses the one available.
132
+ if (typeof LCEVCdec !== 'undefined') {
133
+ this.lcevcLib_ = LCEVCdec;
134
+ } else {
135
+ if (typeof LcevcDil !== 'undefined') {
136
+ this.lcevcLib_ = LcevcDil;
137
+ this.toBeDeprecated_ = true;
138
+ shaka.Deprecate.deprecateFeature(5,
139
+ 'LcevcDil',
140
+ 'lcevc_dil.js is deprecated, please use lcevc_dec.js instead');
141
+ } else {
142
+ shaka.log.alwaysWarn('Could not find LCEVC Library on this page');
143
+ return false;
144
+ }
145
+ }
146
+
147
+ // Making Sure if there is a valid LCEVC Dec Library exists.
148
+ if (typeof this.lcevcLib_.SupportObject === 'undefined') {
149
+ shaka.log.alwaysWarn('Could not find LCEVC Library on this page');
150
+ return false;
151
+ } else {
152
+ if (!this.lcevcLib_.SupportObject.SupportStatus) {
153
+ shaka.log.alwaysWarn(this.lcevcLib_.SupportObject.SupportError);
154
+ }
155
+ }
156
+
157
+ return typeof this.lcevcLib_ !== 'undefined' &&
158
+ typeof libDPIModule !== 'undefined' &&
159
+ this.canvas_ instanceof HTMLCanvasElement &&
160
+ this.lcevcLib_.SupportObject.SupportStatus;
161
+ }
162
+
163
+ /**
164
+ * Update current active variant
165
+ * @param {shaka.extern.Track} track
166
+ */
167
+ updateVariant(track, manifestType) {
168
+ let containerFormat = shaka.lcevc.Dec.ContainerFormat.MPEG2_TS;
169
+ let streamingFormat = shaka.lcevc.Dec.StreamingFormat.OTHER;
170
+ switch (track.mimeType) {
171
+ case 'video/webm': {
172
+ containerFormat = shaka.lcevc.Dec.ContainerFormat.WEBM;
173
+ break;
174
+ }
175
+ case 'video/mp4': {
176
+ containerFormat = shaka.lcevc.Dec.ContainerFormat.MP4;
177
+ break;
178
+ }
179
+ }
180
+ switch (manifestType) {
181
+ case 'DASH': {
182
+ streamingFormat = shaka.lcevc.Dec.StreamingFormat.DASH;
183
+ break;
184
+ }
185
+ case 'HLS': {
186
+ streamingFormat = shaka.lcevc.Dec.StreamingFormat.HLS;
187
+ break;
188
+ }
189
+ }
190
+ if (this.dec_) {
191
+ this.variantId_ = track.id;
192
+ this.dec_.setLevelSwitching(track.id, true);
193
+ this.dec_.setContainerFormat(containerFormat);
194
+ // This functionality is only available on the LCEVC Dec Library.
195
+ if (!this.toBeDeprecated_) {
196
+ this.dec_.setStreamingFormat(streamingFormat);
197
+ }
198
+ }
199
+ }
200
+ };
201
+
202
+ /**
203
+ * Container Formats.
204
+ * @const @enum {number}
205
+ */
206
+ shaka.lcevc.Dec.ContainerFormat = {
207
+ MPEG2_TS: 0,
208
+ WEBM: 1,
209
+ MP4: 2,
210
+ };
211
+
212
+ /**
213
+ * Streaming Formats.
214
+ * @const @enum {number}
215
+ */
216
+ shaka.lcevc.Dec.StreamingFormat = {
217
+ HLS: 0,
218
+ DASH: 1,
219
+ OTHER: -1,
220
+ };