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
@@ -128,8 +128,9 @@ shaka.transmuxer.MpegTsTransmuxer = class {
128
128
  * @override
129
129
  * @export
130
130
  */
131
- transmux(data) {
131
+ transmux(data, stream, reference, duration, contentType) {
132
132
  const MpegAudio = shaka.transmuxer.MpegAudio;
133
+ const ContentType = shaka.util.ManifestParserUtils.ContentType;
133
134
  const Uint8ArrayUtils = shaka.util.Uint8ArrayUtils;
134
135
 
135
136
  if (!this.tsParser_) {
@@ -142,7 +143,7 @@ shaka.transmuxer.MpegTsTransmuxer = class {
142
143
 
143
144
  const tsParser = this.tsParser_.parse(uint8ArrayData);
144
145
  const codecs = tsParser.getCodecs();
145
- if (codecs.audio != 'mp3' || codecs.video) {
146
+ if (codecs.audio != 'mp3' || contentType != ContentType.AUDIO) {
146
147
  return Promise.reject(new shaka.util.Error(
147
148
  shaka.util.Error.Severity.CRITICAL,
148
149
  shaka.util.Error.Category.MEDIA,
@@ -11,6 +11,7 @@ goog.require('shaka.transmuxer.Ac3');
11
11
  goog.require('shaka.transmuxer.ADTS');
12
12
  goog.require('shaka.transmuxer.Ec3');
13
13
  goog.require('shaka.transmuxer.H264');
14
+ goog.require('shaka.transmuxer.H265');
14
15
  goog.require('shaka.transmuxer.MpegAudio');
15
16
  goog.require('shaka.transmuxer.TransmuxerEngine');
16
17
  goog.require('shaka.util.BufferUtils');
@@ -21,6 +22,8 @@ goog.require('shaka.util.Mp4Generator');
21
22
  goog.require('shaka.util.TsParser');
22
23
  goog.require('shaka.util.Uint8ArrayUtils');
23
24
 
25
+ goog.requireType('shaka.media.SegmentReference');
26
+
24
27
 
25
28
  /**
26
29
  * @implements {shaka.extern.Transmuxer}
@@ -80,11 +83,6 @@ shaka.transmuxer.TsTransmuxer = class {
80
83
  const videoCodec = shaka.util.ManifestParserUtils.guessCodecsSafe(
81
84
  ContentType.VIDEO, allCodecs);
82
85
 
83
- // We don't support muxed content yet.
84
- if (audioCodec && videoCodec) {
85
- return false;
86
- }
87
-
88
86
  const TsTransmuxer = shaka.transmuxer.TsTransmuxer;
89
87
 
90
88
  if (audioCodec) {
@@ -179,7 +177,11 @@ shaka.transmuxer.TsTransmuxer = class {
179
177
  switch (codecs.video) {
180
178
  case 'avc':
181
179
  streamInfo =
182
- this.getAvcStreamInfo_(tsParser, stream, duration);
180
+ this.getAvcStreamInfo_(tsParser, stream, duration, reference);
181
+ break;
182
+ case 'hvc':
183
+ streamInfo =
184
+ this.getHvcStreamInfo_(tsParser, stream, duration, reference);
183
185
  break;
184
186
  }
185
187
  if (streamInfo) {
@@ -191,7 +193,7 @@ shaka.transmuxer.TsTransmuxer = class {
191
193
  switch (codecs.audio) {
192
194
  case 'aac':
193
195
  streamInfo =
194
- this.getAacStreamInfo_(tsParser, stream, duration);
196
+ this.getAacStreamInfo_(tsParser, stream, duration, reference);
195
197
  break;
196
198
  case 'ac3':
197
199
  streamInfo =
@@ -242,10 +244,11 @@ shaka.transmuxer.TsTransmuxer = class {
242
244
  * @param {shaka.util.TsParser} tsParser
243
245
  * @param {shaka.extern.Stream} stream
244
246
  * @param {number} duration
247
+ * @param {?shaka.media.SegmentReference} reference
245
248
  * @return {shaka.util.Mp4Generator.StreamInfo}
246
249
  * @private
247
250
  */
248
- getAacStreamInfo_(tsParser, stream, duration) {
251
+ getAacStreamInfo_(tsParser, stream, duration, reference) {
249
252
  const ADTS = shaka.transmuxer.ADTS;
250
253
  const timescale = shaka.util.TsParser.Timescale;
251
254
 
@@ -306,10 +309,58 @@ shaka.transmuxer.TsTransmuxer = class {
306
309
  }
307
310
 
308
311
  if (!info || firstPts == null) {
309
- throw new shaka.util.Error(
310
- shaka.util.Error.Severity.CRITICAL,
311
- shaka.util.Error.Category.MEDIA,
312
- shaka.util.Error.Code.TRANSMUXING_FAILED);
312
+ if (!tsParser.getVideoData().length) {
313
+ throw new shaka.util.Error(
314
+ shaka.util.Error.Severity.CRITICAL,
315
+ shaka.util.Error.Category.MEDIA,
316
+ shaka.util.Error.Code.TRANSMUXING_FAILED);
317
+ }
318
+
319
+ firstPts = reference.startTime * timescale;
320
+
321
+ const allCodecs = shaka.util.MimeUtils.splitCodecs(stream.codecs);
322
+ const audioCodec = shaka.util.ManifestParserUtils.guessCodecsSafe(
323
+ shaka.util.ManifestParserUtils.ContentType.AUDIO, allCodecs);
324
+ if (!audioCodec || !stream.channelsCount || !stream.audioSamplingRate) {
325
+ throw new shaka.util.Error(
326
+ shaka.util.Error.Severity.CRITICAL,
327
+ shaka.util.Error.Category.MEDIA,
328
+ shaka.util.Error.Code.TRANSMUXING_FAILED);
329
+ }
330
+ info = {
331
+ sampleRate: stream.audioSamplingRate,
332
+ channelCount: stream.channelsCount,
333
+ codec: audioCodec,
334
+ };
335
+ const silenceFrame =
336
+ ADTS.getSilentFrame(audioCodec, stream.channelsCount);
337
+ if (!silenceFrame) {
338
+ throw new shaka.util.Error(
339
+ shaka.util.Error.Severity.CRITICAL,
340
+ shaka.util.Error.Category.MEDIA,
341
+ shaka.util.Error.Code.TRANSMUXING_FAILED);
342
+ }
343
+ const segmentDuration =
344
+ (reference.endTime - reference.startTime) * timescale;
345
+ const finalPTs = firstPts + segmentDuration;
346
+ let currentPts = firstPts;
347
+ while (currentPts < finalPTs) {
348
+ samples.push({
349
+ data: silenceFrame,
350
+ size: silenceFrame.byteLength,
351
+ duration: ADTS.AAC_SAMPLES_PER_FRAME,
352
+ cts: 0,
353
+ flags: {
354
+ isLeading: 0,
355
+ isDependedOn: 0,
356
+ hasRedundancy: 0,
357
+ degradPrio: 0,
358
+ dependsOn: 2,
359
+ isNonSync: 0,
360
+ },
361
+ });
362
+ currentPts += ADTS.AAC_SAMPLES_PER_FRAME / info.sampleRate * timescale;
363
+ }
313
364
  }
314
365
 
315
366
  /** @type {number} */
@@ -609,10 +660,11 @@ shaka.transmuxer.TsTransmuxer = class {
609
660
  * @param {shaka.util.TsParser} tsParser
610
661
  * @param {shaka.extern.Stream} stream
611
662
  * @param {number} duration
663
+ * @param {?shaka.media.SegmentReference} reference
612
664
  * @return {shaka.util.Mp4Generator.StreamInfo}
613
665
  * @private
614
666
  */
615
- getAvcStreamInfo_(tsParser, stream, duration) {
667
+ getAvcStreamInfo_(tsParser, stream, duration, reference) {
616
668
  const H264 = shaka.transmuxer.H264;
617
669
  const timescale = shaka.util.TsParser.Timescale;
618
670
 
@@ -630,7 +682,7 @@ shaka.transmuxer.TsTransmuxer = class {
630
682
  if (i + 1 < videoData.length) {
631
683
  nextPes = videoData[i + 1];
632
684
  }
633
- const dataNalus = tsParser.parseAvcNalus(pes, nextPes);
685
+ const dataNalus = tsParser.parseNalus(pes, nextPes);
634
686
  nalus = nalus.concat(dataNalus);
635
687
  const frame = H264.parseFrame(dataNalus);
636
688
  if (!frame) {
@@ -642,8 +694,10 @@ shaka.transmuxer.TsTransmuxer = class {
642
694
  let duration;
643
695
  if (i + 1 < videoData.length) {
644
696
  duration = (videoData[i + 1].dts || 0) - (pes.dts || 0);
645
- } else {
697
+ } else if (videoData.length > 1) {
646
698
  duration = (pes.dts || 0) - (videoData[i - 1].dts || 0);
699
+ } else {
700
+ duration = (reference.endTime - reference.startTime) * timescale;
647
701
  }
648
702
  samples.push({
649
703
  data: frame.data,
@@ -690,6 +744,96 @@ shaka.transmuxer.TsTransmuxer = class {
690
744
  stream: stream,
691
745
  };
692
746
  }
747
+
748
+
749
+ /**
750
+ * @param {shaka.util.TsParser} tsParser
751
+ * @param {shaka.extern.Stream} stream
752
+ * @param {number} duration
753
+ * @param {?shaka.media.SegmentReference} reference
754
+ * @return {shaka.util.Mp4Generator.StreamInfo}
755
+ * @private
756
+ */
757
+ getHvcStreamInfo_(tsParser, stream, duration, reference) {
758
+ const H265 = shaka.transmuxer.H265;
759
+ const timescale = shaka.util.TsParser.Timescale;
760
+
761
+ /** @type {!Array.<shaka.util.Mp4Generator.Mp4Sample>} */
762
+ const samples = [];
763
+
764
+ /** @type {?number} */
765
+ let baseMediaDecodeTime = null;
766
+
767
+ let nalus = [];
768
+ const videoData = tsParser.getVideoData();
769
+ for (let i = 0; i < videoData.length; i++) {
770
+ const pes = videoData[i];
771
+ let nextPes;
772
+ if (i + 1 < videoData.length) {
773
+ nextPes = videoData[i + 1];
774
+ }
775
+ const dataNalus = tsParser.parseNalus(pes, nextPes);
776
+ nalus = nalus.concat(dataNalus);
777
+ const frame = H265.parseFrame(dataNalus);
778
+ if (!frame) {
779
+ continue;
780
+ }
781
+ if (baseMediaDecodeTime == null && pes.dts != null) {
782
+ baseMediaDecodeTime = pes.dts;
783
+ }
784
+ let duration;
785
+ if (i + 1 < videoData.length) {
786
+ duration = (videoData[i + 1].dts || 0) - (pes.dts || 0);
787
+ } else if (videoData.length > 1) {
788
+ duration = (pes.dts || 0) - (videoData[i - 1].dts || 0);
789
+ } else {
790
+ duration = (reference.endTime - reference.startTime) * timescale;
791
+ }
792
+ samples.push({
793
+ data: frame.data,
794
+ size: frame.data.byteLength,
795
+ duration: duration,
796
+ cts: Math.round((pes.pts || 0) - (pes.dts || 0)),
797
+ flags: {
798
+ isLeading: 0,
799
+ isDependedOn: 0,
800
+ hasRedundancy: 0,
801
+ degradPrio: 0,
802
+ dependsOn: frame.isKeyframe ? 2 : 1,
803
+ isNonSync: frame.isKeyframe ? 0 : 1,
804
+ },
805
+ });
806
+ }
807
+
808
+ const info = H265.parseInfo(nalus);
809
+
810
+ if (!info || baseMediaDecodeTime == null) {
811
+ throw new shaka.util.Error(
812
+ shaka.util.Error.Severity.CRITICAL,
813
+ shaka.util.Error.Category.MEDIA,
814
+ shaka.util.Error.Code.TRANSMUXING_FAILED);
815
+ }
816
+ stream.height = info.height;
817
+ stream.width = info.width;
818
+
819
+ return {
820
+ id: stream.id,
821
+ type: shaka.util.ManifestParserUtils.ContentType.VIDEO,
822
+ codecs: 'hvc1',
823
+ encrypted: stream.encrypted && stream.drmInfos.length > 0,
824
+ timescale: timescale,
825
+ duration: duration,
826
+ videoNalus: [],
827
+ audioConfig: new Uint8Array([]),
828
+ videoConfig: info.videoConfig,
829
+ data: {
830
+ sequenceNumber: this.frameIndex_,
831
+ baseMediaDecodeTime: baseMediaDecodeTime,
832
+ samples: samples,
833
+ },
834
+ stream: stream,
835
+ };
836
+ }
693
837
  };
694
838
 
695
839
  /**
@@ -713,6 +857,7 @@ shaka.transmuxer.TsTransmuxer.SUPPORTED_AUDIO_CODECS_ = [
713
857
  */
714
858
  shaka.transmuxer.TsTransmuxer.SUPPORTED_VIDEO_CODECS_ = [
715
859
  'avc',
860
+ 'hevc',
716
861
  ];
717
862
 
718
863
 
package/lib/util/error.js CHANGED
@@ -728,15 +728,8 @@ shaka.util.Error.Code = {
728
728
  */
729
729
  'NO_WEB_CRYPTO_API': 4042,
730
730
 
731
- /**
732
- * AES-128 iv length should be 16 bytes.
733
- */
734
- 'HLS_AES_128_INVALID_IV_LENGTH': 4043,
735
-
736
- /**
737
- * AES-128 encryption key length should be 16 bytes.
738
- */
739
- 'HLS_AES_128_INVALID_KEY_LENGTH': 4044,
731
+ // RETIRED: 'HLS_AES_128_INVALID_IV_LENGTH': 4043,
732
+ // RETIRED: 'HLS_AES_128_INVALID_KEY_LENGTH': 4044,
740
733
 
741
734
  /**
742
735
  * External thumbnails tracks cannot be added to live streams.
@@ -754,6 +747,26 @@ shaka.util.Error.Code = {
754
747
  */
755
748
  'MSS_LIVE_CONTENT_NOT_SUPPORTED': 4047,
756
749
 
750
+ /**
751
+ * AES-128 iv length should be 16 bytes.
752
+ */
753
+ 'AES_128_INVALID_IV_LENGTH': 4048,
754
+
755
+ /**
756
+ * AES-128 encryption key length should be 16 bytes.
757
+ */
758
+ 'AES_128_INVALID_KEY_LENGTH': 4049,
759
+
760
+ /**
761
+ * The DASH Manifest specifies conflicting AES-128 keys.
762
+ */
763
+ 'DASH_CONFLICTING_AES_128': 4050,
764
+
765
+ /**
766
+ * The DASH Manifest specifies a unsupported AES-128 encryption.
767
+ */
768
+ 'DASH_UNSUPPORTED_AES_128': 4051,
769
+
757
770
 
758
771
  // RETIRED: 'INCONSISTENT_BUFFER_STATE': 5000,
759
772
  // RETIRED: 'INVALID_SEGMENT_INDEX': 5001,
@@ -1107,4 +1120,10 @@ shaka.util.Error.Code = {
1107
1120
  * for the previous request to complete before initiating a new one.
1108
1121
  */
1109
1122
  'CURRENT_DAI_REQUEST_NOT_FINISHED': 10004,
1123
+
1124
+ /**
1125
+ * MediaTailor Ad Manager needs to be initialized to enable MediaTailor
1126
+ * Ad Insertion. Call adManager.initMediaTailor() to do it.
1127
+ */
1128
+ 'MT_AD_MANAGER_NOT_INITIALIZED': 10005,
1110
1129
  };
@@ -17,6 +17,7 @@
17
17
 
18
18
  goog.provide('shaka.util.ExpGolomb');
19
19
 
20
+ goog.require('shaka.util.BufferUtils');
20
21
  goog.require('shaka.util.DataViewReader');
21
22
 
22
23
 
@@ -31,13 +32,17 @@ goog.require('shaka.util.DataViewReader');
31
32
  shaka.util.ExpGolomb = class {
32
33
  /**
33
34
  * @param {!Uint8Array} data
35
+ * @param {boolean=} convertEbsp2rbsp
34
36
  */
35
- constructor(data) {
37
+ constructor(data, convertEbsp2rbsp = false) {
36
38
  /** @private {!Uint8Array} */
37
39
  this.data_ = data;
40
+ if (convertEbsp2rbsp) {
41
+ this.data_ = this.ebsp2rbsp_(data);
42
+ }
38
43
 
39
44
  /** @private {number} */
40
- this.workingBytesAvailable_ = data.byteLength;
45
+ this.workingBytesAvailable_ = this.data_.byteLength;
41
46
 
42
47
  // the current word being examined
43
48
  /** @private {number} */
@@ -48,6 +53,29 @@ shaka.util.ExpGolomb = class {
48
53
  this.workingBitsAvailable_ = 0;
49
54
  }
50
55
 
56
+ /**
57
+ * @param {!Uint8Array} data
58
+ * @return {!Uint8Array}
59
+ * @private
60
+ */
61
+ ebsp2rbsp_(data) {
62
+ const ret = new Uint8Array(data.byteLength);
63
+ let retIndex = 0;
64
+
65
+ for (let i = 0; i < data.byteLength; i++) {
66
+ if (i >= 2) {
67
+ // Unescape: Skip 0x03 after 00 00
68
+ if (data[i] == 0x03 && data[i - 1] == 0x00 && data[i - 2] == 0x00) {
69
+ continue;
70
+ }
71
+ }
72
+ ret[retIndex] = data[i];
73
+ retIndex++;
74
+ }
75
+
76
+ return shaka.util.BufferUtils.toUint8(ret, 0, retIndex);
77
+ }
78
+
51
79
  /**
52
80
  * Load the next word
53
81
  *
@@ -164,9 +164,11 @@ shaka.util.FakeEvent.EventName = {
164
164
  Error: 'error',
165
165
  ExpirationUpdated: 'expirationupdated',
166
166
  GapJumped: 'gapjumped',
167
+ KeyStatusChanged: 'keystatuschanged',
167
168
  Loaded: 'loaded',
168
169
  Loading: 'loading',
169
170
  ManifestParsed: 'manifestparsed',
171
+ ManifestUpdated: 'manifestupdated',
170
172
  MediaQualityChanged: 'mediaqualitychanged',
171
173
  Metadata: 'metadata',
172
174
  OnStateChange: 'onstatechange',
@@ -175,6 +177,7 @@ shaka.util.FakeEvent.EventName = {
175
177
  SegmentAppended: 'segmentappended',
176
178
  SessionDataEvent: 'sessiondata',
177
179
  StallDetected: 'stalldetected',
180
+ StateChanged: 'statechanged',
178
181
  Streaming: 'streaming',
179
182
  TextChanged: 'textchanged',
180
183
  TextTrackVisibility: 'texttrackvisibility',
@@ -624,7 +624,6 @@ shaka.util.Mp4Generator = class {
624
624
  const ContentType = shaka.util.ManifestParserUtils.ContentType;
625
625
 
626
626
  const id = streamInfo.id + 1;
627
- const bandwidth = streamInfo.stream.bandwidth || 0;
628
627
  const channelsCount = streamInfo.stream.channelsCount || 2;
629
628
  const audioSamplingRate = streamInfo.stream.audioSamplingRate || 44100;
630
629
 
@@ -670,9 +669,10 @@ shaka.util.Mp4Generator = class {
670
669
  0x11, // length
671
670
  0x40, // object type
672
671
  0x15, // streamType
673
- 0x00, 0x06, 0x00, // bufferSizeDB
674
- ...this.breakNumberIntoBytes_(bandwidth, 4), // maxBitrate
675
- ...this.breakNumberIntoBytes_(bandwidth, 4), // avgBitrate
672
+ 0x00, 0x00, 0x00, // bufferSizeDB
673
+ 0x00, 0x00, 0x00, 0x00, // maxBitrate
674
+ 0x00, 0x00, 0x00, 0x00, // avgBitrate
675
+
676
676
  // DecoderSpecificInfo
677
677
  0x05, // tag, DecoderSpecificInfoTag
678
678
  0x02, // length
@@ -1495,6 +1495,7 @@ shaka.util.PeriodCombiner = class {
1495
1495
  return {
1496
1496
  id: 0,
1497
1497
  originalId: '',
1498
+ groupId: null,
1498
1499
  primary: false,
1499
1500
  type,
1500
1501
  mimeType: '',
@@ -1532,6 +1533,7 @@ shaka.util.PeriodCombiner = class {
1532
1533
  return {
1533
1534
  id: 0,
1534
1535
  originalId: '',
1536
+ groupId: null,
1535
1537
  createSegmentIndex: () => Promise.resolve(),
1536
1538
  segmentIndex: new shaka.media.SegmentIndex([]),
1537
1539
  mimeType: '',
@@ -154,6 +154,26 @@ shaka.util.Platform = class {
154
154
  'Chrome/38.0.2125.122 Safari/537.36');
155
155
  }
156
156
 
157
+ /**
158
+ * Check if the current platform is a WebOS 4.
159
+ *
160
+ * @return {boolean}
161
+ */
162
+ static isWebOS4() {
163
+ // See: http://webostv.developer.lge.com/discover/specifications/web-engine/
164
+ return !!navigator.userAgent.match(/webOS\/4/i);
165
+ }
166
+
167
+ /**
168
+ * Check if the current platform is a WebOS 4.
169
+ *
170
+ * @return {boolean}
171
+ */
172
+ static isWebOS5() {
173
+ // See: http://webostv.developer.lge.com/discover/specifications/web-engine/
174
+ return !!navigator.userAgent.match(/webOS\/5/i);
175
+ }
176
+
157
177
  /**
158
178
  * Check if the current platform is a Google Chromecast.
159
179
  *
@@ -460,6 +480,26 @@ shaka.util.Platform = class {
460
480
  return true;
461
481
  }
462
482
 
483
+ /**
484
+ * Returns if codec switching SMOOTH is known reliable device support.
485
+ *
486
+ * Some devices are known not to support `MediaSource.changeType`
487
+ * well. These devices should use the reload strategy. If a device
488
+ * reports that it supports `changeType` but support it reliabley
489
+ * it should be added to this list.
490
+ *
491
+ * @return {boolean}
492
+ */
493
+ static supportsSmoothCodecSwitching() {
494
+ const Platform = shaka.util.Platform;
495
+ if (Platform.isTizen2() || Platform.isTizen3() ||
496
+ Platform.isTizen4() || Platform.isWebOS3() ||
497
+ Platform.isWebOS4() || Platform.isWebOS5()) {
498
+ return false;
499
+ }
500
+ return true;
501
+ }
502
+
463
503
  /**
464
504
  * Returns true if MediaKeys is polyfilled
465
505
  *
@@ -9,6 +9,7 @@ goog.provide('shaka.util.PlayerConfiguration');
9
9
  goog.require('goog.asserts');
10
10
  goog.require('shaka.abr.SimpleAbrManager');
11
11
  goog.require('shaka.config.AutoShowText');
12
+ goog.require('shaka.config.CodecSwitchingStrategy');
12
13
  goog.require('shaka.log');
13
14
  goog.require('shaka.net.NetworkingEngine');
14
15
  goog.require('shaka.util.ConfigUtils');
@@ -133,6 +134,7 @@ shaka.util.PlayerConfiguration = class {
133
134
  element);
134
135
  },
135
136
  sequenceMode: false,
137
+ enableAudioGroups: false,
136
138
  },
137
139
  hls: {
138
140
  ignoreTextStreamFailures: false,
@@ -307,7 +309,13 @@ shaka.util.PlayerConfiguration = class {
307
309
  drawLogo: false,
308
310
  };
309
311
 
312
+ let codecSwitchingStrategy = shaka.config.CodecSwitchingStrategy.RELOAD;
313
+ if (shaka.util.Platform.supportsSmoothCodecSwitching()) {
314
+ codecSwitchingStrategy = shaka.config.CodecSwitchingStrategy.SMOOTH;
315
+ }
316
+
310
317
  const mediaSource = {
318
+ codecSwitchingStrategy: codecSwitchingStrategy,
311
319
  sourceBufferExtraFeatures: '',
312
320
  forceTransmux: false,
313
321
  insertFakeEncryptionInInit: true,
@@ -40,13 +40,15 @@ shaka.util.StateHistory = class {
40
40
 
41
41
  /**
42
42
  * @param {string} state
43
+ * @return {boolean} True if this changed the state
43
44
  */
44
45
  update(state) {
45
46
  // |open_| will only be |null| when we first call |update|.
46
47
  if (this.open_ == null) {
47
48
  this.start_(state);
49
+ return true;
48
50
  } else {
49
- this.update_(state);
51
+ return this.update_(state);
50
52
  }
51
53
  }
52
54
 
@@ -116,6 +118,7 @@ shaka.util.StateHistory = class {
116
118
 
117
119
  /**
118
120
  * @param {string} state
121
+ * @return {boolean} True if this changed the state
119
122
  * @private
120
123
  */
121
124
  update_(state) {
@@ -131,7 +134,7 @@ shaka.util.StateHistory = class {
131
134
 
132
135
  // If the state has not changed, there is no need to add a new entry.
133
136
  if (this.open_.state == state) {
134
- return;
137
+ return false;
135
138
  }
136
139
 
137
140
  // We have changed states, so "close" the open state.
@@ -142,6 +145,7 @@ shaka.util.StateHistory = class {
142
145
  state: state,
143
146
  duration: 0,
144
147
  };
148
+ return true;
145
149
  }
146
150
 
147
151
  /**