shaka-player 4.4.2 → 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 (202) hide show
  1. package/.github/workflows/release-please.yaml +2 -27
  2. package/CHANGELOG.md +67 -25
  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 +27 -5
  8. package/demo/common/assets.js +150 -52
  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 +52 -124
  16. package/demo/search.js +23 -35
  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 +187 -211
  22. package/dist/demo.compiled.debug.map +4 -4
  23. package/dist/demo.compiled.js +187 -211
  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 +42 -61
  28. package/dist/receiver.compiled.debug.map +4 -4
  29. package/dist/receiver.compiled.js +42 -61
  30. package/dist/receiver.compiled.map +4 -4
  31. package/dist/shaka-player.compiled.d.ts +728 -365
  32. package/dist/shaka-player.compiled.debug.d.ts +728 -365
  33. package/dist/shaka-player.compiled.debug.externs.js +475 -51
  34. package/dist/shaka-player.compiled.debug.js +576 -480
  35. package/dist/shaka-player.compiled.debug.map +4 -4
  36. package/dist/shaka-player.compiled.externs.js +475 -51
  37. package/dist/shaka-player.compiled.js +1117 -1056
  38. package/dist/shaka-player.compiled.map +4 -4
  39. package/dist/shaka-player.ui.d.ts +783 -410
  40. package/dist/shaka-player.ui.debug.d.ts +783 -410
  41. package/dist/shaka-player.ui.debug.externs.js +496 -51
  42. package/dist/shaka-player.ui.debug.js +647 -542
  43. package/dist/shaka-player.ui.debug.map +4 -4
  44. package/dist/shaka-player.ui.externs.js +496 -51
  45. package/dist/shaka-player.ui.js +1260 -1194
  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/offline.md +1 -1
  52. package/docs/tutorials/ui-customization.md +4 -0
  53. package/externs/css_style_declaration.js +19 -0
  54. package/externs/lcevc.js +37 -13
  55. package/externs/media_remote.js +68 -0
  56. package/externs/mediatailor.js +193 -0
  57. package/externs/pictureinpicture.js +11 -0
  58. package/externs/shaka/ads.js +27 -0
  59. package/externs/shaka/manifest.js +10 -5
  60. package/externs/shaka/manifest_parser.js +7 -1
  61. package/externs/shaka/offline.js +4 -0
  62. package/externs/shaka/player.js +12 -1
  63. package/karma.conf.js +7 -3
  64. package/lib/abr/simple_abr_manager.js +43 -3
  65. package/lib/ads/ad_manager.js +104 -50
  66. package/lib/ads/media_tailor_ad.js +297 -0
  67. package/lib/ads/media_tailor_ad_manager.js +828 -0
  68. package/lib/cea/ts_cea_parser.js +15 -2
  69. package/lib/config/codec_switching_strategy.js +24 -0
  70. package/lib/dash/content_protection.js +120 -2
  71. package/lib/dash/dash_parser.js +79 -13
  72. package/lib/dash/mpd_utils.js +10 -6
  73. package/lib/dash/segment_base.js +13 -5
  74. package/lib/dash/segment_list.js +13 -5
  75. package/lib/dash/segment_template.js +43 -85
  76. package/lib/dependencies/all.js +8 -7
  77. package/lib/hls/hls_parser.js +101 -37
  78. package/lib/lcevc/lcevc_dec.js +220 -0
  79. package/lib/media/adaptation_set.js +22 -11
  80. package/lib/media/adaptation_set_criteria.js +25 -7
  81. package/lib/media/media_source_engine.js +215 -27
  82. package/lib/media/segment_index.js +5 -5
  83. package/lib/media/segment_reference.js +10 -5
  84. package/lib/media/streaming_engine.js +44 -39
  85. package/lib/mss/mss_parser.js +1 -0
  86. package/lib/net/networking_engine.js +1 -0
  87. package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
  88. package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
  89. package/lib/offline/manifest_converter.js +1 -0
  90. package/lib/offline/storage.js +3 -0
  91. package/lib/player.js +142 -72
  92. package/lib/routing/payload.js +5 -1
  93. package/lib/text/cue.js +62 -47
  94. package/lib/text/ttml_text_parser.js +17 -0
  95. package/lib/text/ui_text_displayer.js +4 -0
  96. package/lib/text/vtt_text_parser.js +35 -22
  97. package/lib/transmuxer/h265.js +862 -0
  98. package/lib/transmuxer/mpeg_ts_transmuxer.js +3 -2
  99. package/lib/transmuxer/ts_transmuxer.js +160 -15
  100. package/lib/util/cmcd_manager.js +6 -1
  101. package/lib/util/error.js +28 -9
  102. package/lib/util/exp_golomb.js +30 -2
  103. package/lib/util/fake_event.js +3 -0
  104. package/lib/util/manifest_parser_utils.js +10 -4
  105. package/lib/util/mp4_generator.js +4 -4
  106. package/lib/util/periods.js +2 -0
  107. package/lib/util/platform.js +54 -0
  108. package/lib/util/player_configuration.js +8 -0
  109. package/lib/util/state_history.js +6 -2
  110. package/lib/util/stream_utils.js +133 -217
  111. package/lib/util/ts_parser.js +229 -43
  112. package/maintained-branches.md +3 -2
  113. package/package.json +4 -6
  114. package/roadmap.md +15 -5
  115. package/shaka-player.uncompiled.js +2 -1
  116. package/support.html +0 -1
  117. package/test/cast/cast_receiver_integration.js +47 -0
  118. package/test/codec_switching/codec_switching_integration.js +181 -0
  119. package/test/dash/dash_parser_content_protection_unit.js +2 -0
  120. package/test/dash/dash_parser_integration.js +73 -0
  121. package/test/dash/dash_parser_live_unit.js +2 -0
  122. package/test/dash/dash_parser_manifest_unit.js +47 -0
  123. package/test/dash/dash_parser_segment_base_unit.js +7 -0
  124. package/test/dash/dash_parser_segment_list_unit.js +23 -17
  125. package/test/dash/dash_parser_segment_template_unit.js +49 -0
  126. package/test/demo/demo_unit.js +0 -16
  127. package/test/hls/hls_live_unit.js +35 -0
  128. package/test/hls/hls_parser_unit.js +8 -61
  129. package/test/media/adaptation_set_criteria_unit.js +118 -0
  130. package/test/media/adaptation_set_unit.js +1 -0
  131. package/test/media/media_source_engine_unit.js +165 -1
  132. package/test/media/segment_index_unit.js +4 -4
  133. package/test/media/segment_prefetch_unit.js +1 -1
  134. package/test/media/streaming_engine_unit.js +17 -17
  135. package/test/mss/mss_parser_unit.js +2 -0
  136. package/test/offline/manifest_convert_unit.js +5 -0
  137. package/test/offline/storage_integration.js +1 -4
  138. package/test/player_unit.js +102 -131
  139. package/test/routing/walker_unit.js +1 -0
  140. package/test/test/assets/dash-aes-128/Fragments(video=0,format=mpd-time-csf) +0 -0
  141. package/test/test/assets/dash-aes-128/Fragments(video=20000000,format=mpd-time-csf) +0 -0
  142. package/test/test/assets/dash-aes-128/Fragments(video=40000000,format=mpd-time-csf) +0 -0
  143. package/test/test/assets/dash-aes-128/Fragments(video=60000000,format=mpd-time-csf) +0 -0
  144. package/test/test/assets/dash-aes-128/Fragments(video=i,format=mpd-time-csf) +0 -0
  145. package/test/test/assets/dash-aes-128/dash.mpd +18 -0
  146. package/test/test/assets/dash-aes-128/license +1 -0
  147. package/test/test/assets/dash-multi-codec/audio_en_2c_128k_aac.mp4 +0 -0
  148. package/test/test/assets/dash-multi-codec/audio_es_2c_64k_opus.webm +0 -0
  149. package/test/test/assets/dash-multi-codec/dash.mpd +32 -0
  150. package/test/test/assets/dash-multi-codec/video_144p_108k_h264.mp4 +0 -0
  151. package/test/test/assets/hls-ts-h265/0.ts +0 -0
  152. package/test/test/assets/hls-ts-h265/hevc.m3u8 +6 -0
  153. package/test/test/assets/hls-ts-h265/index.m3u8 +7 -0
  154. package/test/test/assets/hls-ts-muxed-aac-h265/0.ts +0 -0
  155. package/test/test/assets/hls-ts-muxed-aac-h265/1.ts +0 -0
  156. package/test/test/assets/hls-ts-muxed-aac-h265/media.m3u8 +9 -0
  157. package/test/test/assets/hls-ts-muxed-ac3-h264/media.m3u8 +24 -0
  158. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00000.ts +0 -0
  159. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00001.ts +0 -0
  160. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00002.ts +0 -0
  161. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00003.ts +0 -0
  162. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00004.ts +0 -0
  163. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00005.ts +0 -0
  164. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0000.ts +0 -0
  165. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0001.ts +0 -0
  166. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0002.ts +0 -0
  167. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0003.ts +0 -0
  168. package/test/test/assets/hls-ts-muxed-ec3-h264/prog_index.m3u8 +14 -0
  169. package/test/test/assets/hls-ts-muxed-mp3-h264/index.m3u8 +23 -0
  170. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-1-v1-a1.ts +0 -0
  171. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-2-v1-a1.ts +0 -0
  172. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-3-v1-a1.ts +0 -0
  173. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-4-v1-a1.ts +0 -0
  174. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-5-v1-a1.ts +0 -0
  175. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-6-v1-a1.ts +0 -0
  176. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-7-v1-a1.ts +0 -0
  177. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-8-v1-a1.ts +0 -0
  178. package/test/test/util/dash_parser_util.js +20 -7
  179. package/test/test/util/fake_ad_manager.js +20 -0
  180. package/test/test/util/fake_media_source_engine.js +8 -2
  181. package/test/test/util/manifest_generator.js +7 -3
  182. package/test/test/util/mss_parser_util.js +4 -0
  183. package/test/test/util/offline_utils.js +1 -0
  184. package/test/test/util/streaming_engine_util.js +7 -4
  185. package/test/text/ttml_text_parser_unit.js +52 -0
  186. package/test/text/vtt_text_parser_unit.js +105 -48
  187. package/test/transmuxer/transmuxer_integration.js +121 -4
  188. package/test/ui/ui_unit.js +3 -10
  189. package/test/util/stream_utils_unit.js +208 -74
  190. package/test/util/ts_parser_unit.js +1 -1
  191. package/ui/controls.js +125 -0
  192. package/ui/externs/ui.js +8 -1
  193. package/ui/pip_button.js +22 -120
  194. package/ui/remote_button.js +201 -0
  195. package/ui/ui.js +5 -2
  196. package/demo/common/message_ids.js +0 -309
  197. package/demo/locales/en.json +0 -287
  198. package/demo/locales/source.json +0 -1142
  199. package/externs/mux.js +0 -69
  200. package/lib/lcevc/lcevc_dil.js +0 -152
  201. package/lib/transmuxer/muxjs_transmuxer.js +0 -242
  202. package/test/transmuxer/muxjs_transmuxer_integration.js +0 -177
@@ -1409,15 +1409,11 @@ shaka.media.StreamingEngine = class {
1409
1409
  'ReadableStream is not supported by the browser.');
1410
1410
  }
1411
1411
  const fetchSegment = this.fetch_(mediaState, reference);
1412
- let result = await fetchSegment;
1412
+ const result = await fetchSegment;
1413
1413
  this.destroyer_.ensureNotDestroyed();
1414
1414
  if (this.fatalError_) {
1415
1415
  return;
1416
1416
  }
1417
- if (reference.hlsAes128Key) {
1418
- goog.asserts.assert(iter, 'mediaState.segmentIterator should exist');
1419
- result = await this.aes128Decrypt_(result, reference, iter);
1420
- }
1421
1417
  this.destroyer_.ensureNotDestroyed();
1422
1418
 
1423
1419
  // If the text stream gets switched between fetch_() and append_(), the
@@ -1502,13 +1498,13 @@ shaka.media.StreamingEngine = class {
1502
1498
 
1503
1499
  /**
1504
1500
  * @param {!BufferSource} rawResult
1505
- * @param {!shaka.media.SegmentReference} reference
1501
+ * @param {shaka.extern.aes128Key} aes128Key
1506
1502
  * @param {!shaka.media.SegmentIterator} iter
1507
1503
  * @return {!Promise.<!BufferSource>} finalResult
1508
1504
  * @private
1509
1505
  */
1510
- async aes128Decrypt_(rawResult, reference, iter) {
1511
- const key = reference.hlsAes128Key;
1506
+ async aes128Decrypt_(rawResult, aes128Key, iter) {
1507
+ const key = aes128Key;
1512
1508
  if (!key.cryptoKey) {
1513
1509
  goog.asserts.assert(key.fetchKey, 'If AES-128 cryptoKey was not ' +
1514
1510
  'preloaded, fetchKey function should be provided');
@@ -1688,22 +1684,21 @@ shaka.media.StreamingEngine = class {
1688
1684
  shaka.log.v1(logPrefix,
1689
1685
  'setting append window end to ' + appendWindowEnd);
1690
1686
 
1691
- if ((mediaState.lastCodecs && codecs != mediaState.lastCodecs) ||
1692
- (mediaState.lastMimeType && mimeType != mediaState.lastMimeType)) {
1687
+ const isResetMediaSourceNecessary =
1688
+ mediaState.lastCodecs && mediaState.lastMimeType &&
1689
+ this.playerInterface_.mediaSourceEngine.isResetMediaSourceNecessary(
1690
+ mediaState.type, mediaState.stream);
1691
+ if (isResetMediaSourceNecessary) {
1692
+ let otherState = null;
1693
1693
  if (mediaState.type === ContentType.VIDEO) {
1694
- /** @type {shaka.media.StreamingEngine.MediaState_} */
1695
- const audioState = this.mediaStates_.get(ContentType.AUDIO);
1696
- if (audioState) {
1697
- audioState.lastInitSegmentReference = null;
1698
- this.abortOperations_(audioState);
1699
- }
1694
+ otherState = this.mediaStates_.get(ContentType.AUDIO);
1700
1695
  } else if (mediaState.type === ContentType.AUDIO) {
1701
- /** @type {shaka.media.StreamingEngine.MediaState_} */
1702
- const videoState = this.mediaStates_.get(ContentType.VIDEO);
1703
- if (videoState) {
1704
- videoState.lastInitSegmentReference = null;
1705
- this.abortOperations_(videoState);
1706
- }
1696
+ otherState = this.mediaStates_.get(ContentType.VIDEO);
1697
+ }
1698
+ if (otherState) {
1699
+ otherState.lastInitSegmentReference = null;
1700
+ this.forceClearBuffer_(otherState);
1701
+ this.abortOperations_(otherState).catch(() => {});
1707
1702
  }
1708
1703
  }
1709
1704
 
@@ -1733,6 +1728,19 @@ shaka.media.StreamingEngine = class {
1733
1728
  mediaState.type, timestampOffset, appendWindowStart,
1734
1729
  appendWindowEnd, ignoreTimestampOffset,
1735
1730
  mediaState.stream, streamsByType);
1731
+ if (isResetMediaSourceNecessary) {
1732
+ let otherState = null;
1733
+ if (mediaState.type === ContentType.VIDEO) {
1734
+ otherState = this.mediaStates_.get(ContentType.AUDIO);
1735
+ } else if (mediaState.type === ContentType.AUDIO) {
1736
+ otherState = this.mediaStates_.get(ContentType.VIDEO);
1737
+ }
1738
+ if (otherState) {
1739
+ otherState.waitingToClearBuffer = false;
1740
+ otherState.performingUpdate = false;
1741
+ this.forceClearBuffer_(otherState);
1742
+ }
1743
+ }
1736
1744
  } catch (error) {
1737
1745
  mediaState.lastAppendWindowStart = null;
1738
1746
  mediaState.lastAppendWindowEnd = null;
@@ -1742,7 +1750,10 @@ shaka.media.StreamingEngine = class {
1742
1750
  throw error;
1743
1751
  }
1744
1752
  };
1745
- operations.push(setProperties());
1753
+ // Dispatching init asynchronously causes the sourceBuffers in
1754
+ // the MediaSourceEngine to become detached do to race conditions
1755
+ // with mediaSource and sourceBuffers being created simultaneously.
1756
+ await setProperties();
1746
1757
  }
1747
1758
 
1748
1759
  if (!shaka.media.InitSegmentReference.equal(
@@ -1818,10 +1829,10 @@ shaka.media.StreamingEngine = class {
1818
1829
  }
1819
1830
  }
1820
1831
 
1821
- const lastDiscontinuitySequence =
1822
- mediaState.lastSegmentReference ?
1823
- mediaState.lastSegmentReference.discontinuitySequence : null;
1824
1832
  if (this.manifest_.sequenceMode) {
1833
+ const lastDiscontinuitySequence =
1834
+ mediaState.lastSegmentReference ?
1835
+ mediaState.lastSegmentReference.discontinuitySequence : null;
1825
1836
  // Across discontinuity bounds, we should resync timestamps for
1826
1837
  // sequence mode playbacks. The next segment appended should
1827
1838
  // land at its theoretical timestamp from the segment index.
@@ -1831,18 +1842,6 @@ shaka.media.StreamingEngine = class {
1831
1842
  operations.push(this.playerInterface_.mediaSourceEngine.resync(
1832
1843
  mediaState.type, reference.startTime));
1833
1844
  }
1834
- } else if (this.manifest_.ignoreManifestTimestampsInSegmentsMode) {
1835
- // In segments mode, we need to resync to set the timestampOffset
1836
- // to the start of the current discontinuity sequence. This is
1837
- // because individual discontinuity sequences may have internal
1838
- // timestamps that overlap, so we adjust the timestampOffset to avoid
1839
- // having the SourceBuffer get overwritten.
1840
- if (reference.discontinuitySequence != lastDiscontinuitySequence) {
1841
- operations.push(
1842
- this.playerInterface_.mediaSourceEngine.resync(
1843
- mediaState.type,
1844
- reference.timestampOffset));
1845
- }
1846
1845
  }
1847
1846
 
1848
1847
  await Promise.all(operations);
@@ -2200,7 +2199,13 @@ shaka.media.StreamingEngine = class {
2200
2199
  mediaState.operation = op;
2201
2200
  const response = await op.promise;
2202
2201
  mediaState.operation = null;
2203
- return response.data;
2202
+ let result = response.data;
2203
+ if (reference.aes128Key) {
2204
+ const iter = mediaState.segmentIterator;
2205
+ goog.asserts.assert(iter, 'mediaState.segmentIterator should exist');
2206
+ result = await this.aes128Decrypt_(result, reference.aes128Key, iter);
2207
+ }
2208
+ return result;
2204
2209
  }
2205
2210
 
2206
2211
  /**
@@ -500,6 +500,7 @@ shaka.mss.MssParser = class {
500
500
  const stream = {
501
501
  id: id,
502
502
  originalId: streamIndex.getAttribute('Name') || String(id),
503
+ groupId: null,
503
504
  createSegmentIndex: () => Promise.resolve(),
504
505
  closeSegmentIndex: () => Promise.resolve(),
505
506
  segmentIndex: null,
@@ -769,6 +769,7 @@ shaka.net.NetworkingEngine.RequestType = {
769
769
  'TIMING': 4,
770
770
  'SERVER_CERTIFICATE': 5,
771
771
  'KEY': 6,
772
+ 'ADS': 7,
772
773
  };
773
774
 
774
775
  /**
@@ -150,6 +150,7 @@ shaka.offline.indexeddb.V1StorageCell = class
150
150
  return {
151
151
  id: old.id,
152
152
  originalId: null,
153
+ groupId: null,
153
154
  primary: old.primary,
154
155
  type: old.contentType,
155
156
  mimeType: old.mimeType,
@@ -99,6 +99,7 @@ shaka.offline.indexeddb.V2StorageCell = class
99
99
  return {
100
100
  id: old.id,
101
101
  originalId: old.originalId,
102
+ groupId: null,
102
103
  primary: old.primary,
103
104
  type: old.contentType,
104
105
  mimeType: old.mimeType,
@@ -180,6 +180,7 @@ shaka.offline.ManifestConverter = class {
180
180
  const stream = {
181
181
  id: streamDB.id,
182
182
  originalId: streamDB.originalId,
183
+ groupId: streamDB.groupId,
183
184
  createSegmentIndex: () => Promise.resolve(),
184
185
  segmentIndex,
185
186
  mimeType: streamDB.mimeType,
@@ -1168,6 +1168,8 @@ shaka.offline.Storage = class {
1168
1168
  enableLowLatencyMode: () => {},
1169
1169
  updateDuration: () => {},
1170
1170
  newDrmInfo: (stream) => {},
1171
+ onManifestUpdated: () => {},
1172
+ getBandwidthEstimate: () => config.abr.defaultBandwidthEstimate,
1171
1173
  };
1172
1174
 
1173
1175
  parser.configure(config.manifest);
@@ -1299,6 +1301,7 @@ shaka.offline.Storage = class {
1299
1301
  const streamDb = {
1300
1302
  id: stream.id,
1301
1303
  originalId: stream.originalId,
1304
+ groupId: stream.groupId,
1302
1305
  primary: stream.primary,
1303
1306
  type: stream.type,
1304
1307
  mimeType: stream.mimeType,