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
package/externs/mux.js DELETED
@@ -1,69 +0,0 @@
1
- /*! @license
2
- * Shaka Player
3
- * Copyright 2016 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- /**
8
- * @fileoverview Externs for mux.js library.
9
- * @externs
10
- */
11
-
12
-
13
- /**
14
- * @typedef {{
15
- * mp4: typeof muxjs.mp4
16
- * }}
17
- * @const
18
- */
19
- var muxjs = {};
20
-
21
-
22
- /** @const */
23
- muxjs.mp4 = {};
24
-
25
-
26
- muxjs.mp4.Transmuxer = class {
27
- /** @param {Object=} options */
28
- constructor(options) {}
29
-
30
- /** @param {number} time */
31
- setBaseMediaDecodeTime(time) {}
32
-
33
- /** @param {!Uint8Array} data */
34
- push(data) {}
35
-
36
- flush() {}
37
-
38
- /**
39
- * Add a handler for a specified event type.
40
- * @param {string} type Event name
41
- * @param {Function} listener The callback to be invoked
42
- */
43
- on(type, listener) {}
44
-
45
- /**
46
- * Remove a handler for a specified event type.
47
- * @param {string} type Event name
48
- * @param {Function} listener The callback to be removed
49
- */
50
- off(type, listener) {}
51
-
52
- /** Remove all handlers and clean up. */
53
- dispose() {}
54
- };
55
-
56
-
57
- /**
58
- * @typedef {{
59
- * initSegment: !Uint8Array,
60
- * data: !Uint8Array
61
- * }}
62
- *
63
- * @description Transmuxed data from mux.js.
64
- * @property {!Uint8Array} initSegment
65
- * @property {!Uint8Array} data
66
- * @exportDoc
67
- */
68
- muxjs.mp4.Transmuxer.Segment;
69
-
@@ -1,152 +0,0 @@
1
- /*! @license
2
- * Shaka Player
3
- * Copyright 2016 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- goog.provide('shaka.lcevc.Dil');
8
- goog.require('shaka.log');
9
- goog.require('shaka.util.IReleasable');
10
-
11
- /**
12
- * @summary
13
- * lcevcDil - (MPEG-5 Part 2 LCEVC - Decoder Integration Layer) provides
14
- * all the operations related to the enhancement and rendering
15
- * of LCEVC enabled streams and on to a canvas.
16
- * @implements {shaka.util.IReleasable}
17
- * @export
18
- */
19
- shaka.lcevc.Dil = class {
20
- /**
21
- * @param {HTMLVideoElement} media The video element that will be attached to
22
- * LCEVC Dil for input.
23
- * @param {HTMLCanvasElement} canvas The canvas element that will be attached
24
- * to LCEVC Dil to render the enhanced frames.
25
- * @param {shaka.extern.LcevcConfiguration} dilConfig The LCEVC DIL
26
- * config object to initialize the LCEVC DIL.
27
- */
28
- constructor(media, canvas, dilConfig) {
29
- /** @private {?LcevcDil.LcevcDIL} */
30
- this.dil_ = null;
31
-
32
- /** @private {number} */
33
- this.variantId_ = -1;
34
-
35
- /** @private {HTMLVideoElement} */
36
- this.media_ = media;
37
-
38
- /** @private {HTMLCanvasElement} */
39
- this.canvas_ = canvas;
40
-
41
- /** @private {shaka.extern.LcevcConfiguration} */
42
- this.dilConfig_ = dilConfig;
43
-
44
- this.create_();
45
- }
46
-
47
- /**
48
- * Append data to the LCEVC Dil.
49
- * @param {BufferSource} data
50
- */
51
- appendBuffer(data) {
52
- if (this.dil_) {
53
- this.dil_.appendBuffer(data, 'video', this.variantId_);
54
- }
55
- }
56
-
57
- /**
58
- * Hide the canvas specifically in the case of a DRM Content
59
- */
60
- hideCanvas() {
61
- if (this.dil_) {
62
- this.canvas_.classList.add('shaka-hidden');
63
- }
64
- }
65
-
66
- /**
67
- * Create LCEVC Dil.
68
- * @private
69
- */
70
- create_() {
71
- if (this.isSupported_() && !this.dil_) {
72
- if (LcevcDil.SupportObject.webGLSupport(this.canvas_)) {
73
- // Make sure the canvas is not hidden from a previous playback session.
74
- this.canvas_.classList.remove('shaka-hidden');
75
- this.dil_ = new LcevcDil.LcevcDil(
76
- this.media_,
77
- this.canvas_,
78
- this.dilConfig_);
79
- }
80
- }
81
- }
82
-
83
- /**
84
- * Close LCEVC Dil.
85
- * @override
86
- * @export
87
- */
88
- release() {
89
- if (this.dil_) {
90
- this.dil_.close();
91
- this.dil_ = null;
92
- }
93
- }
94
-
95
- /**
96
- * Check if the LCEVC Dil lib is present and is supported by the browser.
97
- * @return {boolean}
98
- * @private
99
- */
100
- isSupported_() {
101
- if (typeof libDPIModule === 'undefined') {
102
- shaka.log.alwaysWarn(
103
- 'Could not Find LCEVC Library dependencies on this page');
104
- }
105
-
106
- if (typeof LcevcDil === 'undefined') {
107
- shaka.log.alwaysWarn('Could not Find LCEVC Library on this page');
108
- } else {
109
- if (!LcevcDil.SupportObject.SupportStatus) {
110
- shaka.log.alwaysWarn(LcevcDil.SupportObject.SupportError);
111
- }
112
- }
113
-
114
- return typeof LcevcDil !== 'undefined' &&
115
- typeof libDPIModule !== 'undefined' &&
116
- this.canvas_ instanceof HTMLCanvasElement &&
117
- LcevcDil.SupportObject.SupportStatus;
118
- }
119
-
120
- /**
121
- * Update current active variant
122
- * @param {shaka.extern.Track} track
123
- */
124
- updateVariant(track) {
125
- let containerFormat = shaka.lcevc.Dil.ContainerFormat.MPEG2_TS;
126
- switch (track.mimeType) {
127
- case 'video/webm': {
128
- containerFormat = shaka.lcevc.Dil.ContainerFormat.WEBM;
129
- break;
130
- }
131
- case 'video/mp4': {
132
- containerFormat = shaka.lcevc.Dil.ContainerFormat.MP4;
133
- break;
134
- }
135
- }
136
- if (this.dil_) {
137
- this.variantId_ = track.id;
138
- this.dil_.setLevelSwitching(track.id, true);
139
- this.dil_.setContainerFormat(containerFormat);
140
- }
141
- }
142
- };
143
-
144
- /**
145
- * Container Formats.
146
- * @const @enum {number}
147
- */
148
- shaka.lcevc.Dil.ContainerFormat = {
149
- MPEG2_TS: 0,
150
- WEBM: 1,
151
- MP4: 2,
152
- };
@@ -1,242 +0,0 @@
1
- /*! @license
2
- * Shaka Player
3
- * Copyright 2016 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- goog.provide('shaka.transmuxer.MuxjsTransmuxer');
8
-
9
- goog.require('goog.asserts');
10
- goog.require('shaka.dependencies');
11
- goog.require('shaka.media.Capabilities');
12
- goog.require('shaka.transmuxer.TransmuxerEngine');
13
- goog.require('shaka.util.BufferUtils');
14
- goog.require('shaka.util.Error');
15
- goog.require('shaka.util.ManifestParserUtils');
16
- goog.require('shaka.util.PublicPromise');
17
- goog.require('shaka.util.Uint8ArrayUtils');
18
-
19
-
20
- /**
21
- * @implements {shaka.extern.Transmuxer}
22
- * @export
23
- */
24
- shaka.transmuxer.MuxjsTransmuxer = class {
25
- /**
26
- * @param {string} mimeType
27
- */
28
- constructor(mimeType) {
29
- /** @private {string} */
30
- this.originalMimeType_ = mimeType;
31
-
32
- /** @private {?muxjs} */
33
- this.muxjs_ = shaka.dependencies.muxjs();
34
-
35
- /** @private {muxjs.mp4.Transmuxer} */
36
- this.muxTransmuxer_ = null;
37
-
38
- /** @private {shaka.util.PublicPromise} */
39
- this.transmuxPromise_ = null;
40
-
41
- /** @private {!Array.<!Uint8Array>} */
42
- this.transmuxedData_ = [];
43
-
44
- /** @private {boolean} */
45
- this.isTransmuxing_ = false;
46
-
47
- if (this.muxjs_) {
48
- this.muxTransmuxer_ = new this.muxjs_.mp4.Transmuxer({
49
- 'keepOriginalTimestamps': true,
50
- });
51
- this.muxTransmuxer_.on('data', (segment) => this.onTransmuxed_(segment));
52
- this.muxTransmuxer_.on('done', () => this.onTransmuxDone_());
53
- }
54
- }
55
-
56
-
57
- /**
58
- * @override
59
- * @export
60
- */
61
- destroy() {
62
- if (this.muxTransmuxer_) {
63
- this.muxTransmuxer_.dispose();
64
- }
65
- this.muxTransmuxer_ = null;
66
- }
67
-
68
-
69
- /**
70
- * Check if the mime type and the content type is supported.
71
- * @param {string} mimeType
72
- * @param {string=} contentType
73
- * @return {boolean}
74
- * @override
75
- * @export
76
- */
77
- isSupported(mimeType, contentType) {
78
- const Capabilities = shaka.media.Capabilities;
79
-
80
- const isTs = this.isTsContainer_(mimeType);
81
-
82
- if (!this.muxjs_ || !isTs) {
83
- return false;
84
- }
85
-
86
- if (contentType) {
87
- return Capabilities.isTypeSupported(
88
- this.convertTsCodecs_(contentType, mimeType));
89
- }
90
-
91
- const ContentType = shaka.util.ManifestParserUtils.ContentType;
92
-
93
- const audioMime = this.convertTsCodecs_(ContentType.AUDIO, mimeType);
94
- const videoMime = this.convertTsCodecs_(ContentType.VIDEO, mimeType);
95
- return Capabilities.isTypeSupported(audioMime) ||
96
- Capabilities.isTypeSupported(videoMime);
97
- }
98
-
99
-
100
- /**
101
- * Check if the mimetype contains 'mp2t'.
102
- * @param {string} mimeType
103
- * @return {boolean}
104
- * @private
105
- */
106
- isTsContainer_(mimeType) {
107
- return mimeType.toLowerCase().split(';')[0].split('/')[1] == 'mp2t';
108
- }
109
-
110
-
111
- /**
112
- * @override
113
- * @export
114
- */
115
- convertCodecs(contentType, mimeType) {
116
- if (this.isTsContainer_(mimeType)) {
117
- return this.convertTsCodecs_(contentType, mimeType);
118
- }
119
- return mimeType;
120
- }
121
-
122
-
123
- /**
124
- * For transport stream, convert its codecs to MP4 codecs.
125
- * @param {string} contentType
126
- * @param {string} tsMimeType
127
- * @return {string}
128
- * @private
129
- */
130
- convertTsCodecs_(contentType, tsMimeType) {
131
- const ContentType = shaka.util.ManifestParserUtils.ContentType;
132
- let mp4MimeType = tsMimeType.replace(/mp2t/i, 'mp4');
133
- if (contentType == ContentType.AUDIO) {
134
- mp4MimeType = mp4MimeType.replace('video', 'audio');
135
- }
136
-
137
- // Handle legacy AVC1 codec strings (pre-RFC 6381).
138
- // Look for "avc1.<profile>.<level>", where profile is:
139
- // 66 (baseline => 0x42)
140
- // 77 (main => 0x4d)
141
- // 100 (high => 0x64)
142
- // Reference: https://bit.ly/2K9JI3x
143
- const match = /avc1\.(66|77|100)\.(\d+)/.exec(mp4MimeType);
144
- if (match) {
145
- let newCodecString = 'avc1.';
146
-
147
- const profile = match[1];
148
- if (profile == '66') {
149
- newCodecString += '4200';
150
- } else if (profile == '77') {
151
- newCodecString += '4d00';
152
- } else {
153
- goog.asserts.assert(profile == '100',
154
- 'Legacy avc1 parsing code out of sync with regex!');
155
- newCodecString += '6400';
156
- }
157
-
158
- // Convert the level to hex and append to the codec string.
159
- const level = Number(match[2]);
160
- goog.asserts.assert(level < 256,
161
- 'Invalid legacy avc1 level number!');
162
- newCodecString += (level >> 4).toString(16);
163
- newCodecString += (level & 0xf).toString(16);
164
-
165
- mp4MimeType = mp4MimeType.replace(match[0], newCodecString);
166
- }
167
-
168
- return mp4MimeType;
169
- }
170
-
171
-
172
- /**
173
- * @override
174
- * @export
175
- */
176
- getOrginalMimeType() {
177
- return this.originalMimeType_;
178
- }
179
-
180
-
181
- /**
182
- * @override
183
- * @export
184
- */
185
- transmux(data) {
186
- goog.asserts.assert(this.muxTransmuxer_,
187
- 'mux.js should be available.');
188
- goog.asserts.assert(!this.isTransmuxing_,
189
- 'No transmuxing should be in progress.');
190
- this.isTransmuxing_ = true;
191
- this.transmuxPromise_ = new shaka.util.PublicPromise();
192
- this.transmuxedData_ = [];
193
-
194
- const dataArray = shaka.util.BufferUtils.toUint8(data);
195
- this.muxTransmuxer_.push(dataArray);
196
- this.muxTransmuxer_.flush();
197
-
198
- // Workaround for https://bit.ly/Shaka1449 mux.js not
199
- // emitting 'data' and 'done' events.
200
- // mux.js code is synchronous, so if onTransmuxDone_ has
201
- // not been called by now, it's not going to be.
202
- // Treat it as a transmuxing failure and reject the promise.
203
- if (this.isTransmuxing_) {
204
- this.transmuxPromise_.reject(new shaka.util.Error(
205
- shaka.util.Error.Severity.CRITICAL,
206
- shaka.util.Error.Category.MEDIA,
207
- shaka.util.Error.Code.TRANSMUXING_FAILED));
208
- }
209
- return this.transmuxPromise_;
210
- }
211
-
212
- /**
213
- * Handles the 'data' event of the transmuxer.
214
- * Extracts the cues from the transmuxed segment, and adds them to an array.
215
- * Stores the transmuxed data in another array, to pass it back to
216
- * MediaSourceEngine, and append to the source buffer.
217
- *
218
- * @param {muxjs.mp4.Transmuxer.Segment} segment
219
- * @private
220
- */
221
- onTransmuxed_(segment) {
222
- this.transmuxedData_.push(
223
- shaka.util.Uint8ArrayUtils.concat(segment.initSegment, segment.data));
224
- }
225
-
226
-
227
- /**
228
- * Handles the 'done' event of the transmuxer.
229
- * Resolves the transmux Promise, and returns the transmuxed data.
230
- * @private
231
- */
232
- onTransmuxDone_() {
233
- const data = shaka.util.Uint8ArrayUtils.concat(...this.transmuxedData_);
234
- this.transmuxPromise_.resolve(data);
235
- this.isTransmuxing_ = false;
236
- }
237
- };
238
-
239
- shaka.transmuxer.TransmuxerEngine.registerTransmuxer(
240
- 'video/mp2t',
241
- () => new shaka.transmuxer.MuxjsTransmuxer('video/mp2t'),
242
- shaka.transmuxer.TransmuxerEngine.PluginPriority.FALLBACK);
@@ -1,177 +0,0 @@
1
- /*! @license
2
- * Shaka Player
3
- * Copyright 2016 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- describe('MuxjsTransmuxer', () => {
8
- const ContentType = shaka.util.ManifestParserUtils.ContentType;
9
-
10
- const videoSegmentUri = '/base/test/test/assets/video.ts';
11
- const audioSegmentUri = '/base/test/test/assets/audio.ts';
12
- const mp4MimeType = 'video/mp4; codecs="avc1.42E01E"';
13
- const transportStreamVideoMimeType = 'video/mp2t; codecs="avc1.42E01E"';
14
- const transportStreamAudioMimeType = 'video/mp2t; codecs="mp4a.40.2"';
15
-
16
- /** @type {!ArrayBuffer} */
17
- let videoSegment;
18
- /** @type {!ArrayBuffer} */
19
- let audioSegment;
20
- /** @type {!ArrayBuffer} */
21
- let emptySegment;
22
-
23
- /** @type {?shaka.transmuxer.MuxjsTransmuxer} */
24
- let transmuxer;
25
-
26
- function useTsTransmuxer() {
27
- transmuxer = new shaka.transmuxer.MuxjsTransmuxer('video/mp2t');
28
- }
29
-
30
- beforeAll(async () => {
31
- const responses = await Promise.all([
32
- shaka.test.Util.fetch(videoSegmentUri),
33
- shaka.test.Util.fetch(audioSegmentUri),
34
- ]);
35
- videoSegment = responses[0];
36
- audioSegment = responses[1];
37
- emptySegment = new ArrayBuffer(0);
38
- });
39
-
40
- beforeEach(() => {
41
- transmuxer = null;
42
- });
43
-
44
- afterEach(async () => {
45
- await transmuxer.destroy();
46
- });
47
-
48
- describe('isSupported', () => {
49
- it('returns whether the content type is supported', () => {
50
- useTsTransmuxer();
51
- expect(transmuxer.isSupported(
52
- mp4MimeType, ContentType.VIDEO)).toBe(false);
53
- expect(transmuxer.isSupported(
54
- transportStreamVideoMimeType, ContentType.VIDEO)).toBe(true);
55
- });
56
-
57
- // Issue #1991
58
- it('handles upper-case MIME types', () => {
59
- useTsTransmuxer();
60
- const mimeType = transportStreamVideoMimeType.replace('mp2t', 'MP2T');
61
- expect(transmuxer.isSupported(
62
- mimeType, ContentType.VIDEO)).toBe(true);
63
- });
64
- });
65
-
66
- describe('convertCodecs', () => {
67
- const convertCodecs =
68
- (type, codecs) => transmuxer.convertCodecs(type, codecs);
69
-
70
- it('returns converted codecs for TS', () => {
71
- useTsTransmuxer();
72
- const convertedVideoCodecs =
73
- convertCodecs(ContentType.VIDEO, transportStreamVideoMimeType);
74
- const convertedAudioCodecs =
75
- convertCodecs(ContentType.AUDIO, transportStreamAudioMimeType);
76
- const expectedVideoCodecs = 'video/mp4; codecs="avc1.42E01E"';
77
- const expectedAudioCodecs = 'audio/mp4; codecs="mp4a.40.2"';
78
- expect(convertedVideoCodecs).toBe(expectedVideoCodecs);
79
- expect(convertedAudioCodecs).toBe(expectedAudioCodecs);
80
- });
81
-
82
- it('converts legacy avc1 codec strings', () => {
83
- useTsTransmuxer();
84
- expect(
85
- convertCodecs(
86
- ContentType.VIDEO, 'video/mp2t; codecs="avc1.100.42"'))
87
- .toBe('video/mp4; codecs="avc1.64002a"');
88
- expect(
89
- convertCodecs(ContentType.VIDEO, 'video/mp2t; codecs="avc1.77.80"'))
90
- .toBe('video/mp4; codecs="avc1.4d0050"');
91
- expect(
92
- convertCodecs(ContentType.VIDEO, 'video/mp2t; codecs="avc1.66.1"'))
93
- .toBe('video/mp4; codecs="avc1.420001"');
94
- });
95
-
96
- // Issue #1991
97
- it('handles upper-case MIME types', () => {
98
- useTsTransmuxer();
99
- expect(convertCodecs(
100
- ContentType.VIDEO, 'video/MP2T; codecs="avc1.420001"'))
101
- .toBe('video/mp4; codecs="avc1.420001"');
102
- });
103
- });
104
-
105
- describe('transmuxing', () => {
106
- it('transmux video from TS to MP4', async () => {
107
- useTsTransmuxer();
108
- let sawMDAT = false;
109
-
110
- const transmuxedData = await transmuxer.transmux(videoSegment);
111
- expect(transmuxedData).toEqual(jasmine.any(Uint8Array));
112
- expect(transmuxedData.length).toBeGreaterThan(0);
113
- new shaka.util.Mp4Parser()
114
- .box('mdat', shaka.util.Mp4Parser.allData((data) => {
115
- sawMDAT = true;
116
- expect(data.byteLength).toBeGreaterThan(0);
117
- }))
118
- .parse(transmuxedData);
119
- expect(sawMDAT).toBeTruthy();
120
- });
121
-
122
- it('transmux audio from TS to MP4', async () => {
123
- useTsTransmuxer();
124
- let sawMDAT = false;
125
- const transmuxedData = await transmuxer.transmux(audioSegment);
126
- expect(transmuxedData).toEqual(jasmine.any(Uint8Array));
127
- expect(transmuxedData.length).toBeGreaterThan(0);
128
- new shaka.util.Mp4Parser()
129
- .box('mdat', shaka.util.Mp4Parser.allData((data) => {
130
- sawMDAT = true;
131
- expect(data.byteLength).toBeGreaterThan(0);
132
- }))
133
- .parse(transmuxedData);
134
- expect(sawMDAT).toBeTruthy();
135
- });
136
-
137
- it('transmux empty video from TS to MP4', async () => {
138
- useTsTransmuxer();
139
- let sawMDAT = false;
140
- const transmuxedData = await transmuxer.transmux(emptySegment);
141
- expect(transmuxedData).toEqual(jasmine.any(Uint8Array));
142
- new shaka.util.Mp4Parser()
143
- .box('mdat', shaka.util.Mp4Parser.allData((data) => {
144
- sawMDAT = true;
145
- }))
146
- .parse(transmuxedData);
147
- expect(sawMDAT).toBeFalsy();
148
- });
149
-
150
- it('passes through true timestamps', async () => {
151
- useTsTransmuxer();
152
- let parsed = false;
153
- const expectedMp4Timestamp = 5166000; // in timescale units
154
- let mp4Timestamp;
155
-
156
- const transmuxedData = await transmuxer.transmux(videoSegment);
157
- const Mp4Parser = shaka.util.Mp4Parser;
158
-
159
- new Mp4Parser()
160
- .box('moof', Mp4Parser.children)
161
- .box('traf', Mp4Parser.children)
162
- .fullBox('tfdt', (box) => {
163
- goog.asserts.assert(
164
- box.version == 0 || box.version == 1,
165
- 'TFDT version can only be 0 or 1');
166
- const parsedTFDTBox = shaka.util.Mp4BoxParsers.parseTFDT(
167
- box.reader, box.version);
168
- mp4Timestamp = parsedTFDTBox.baseMediaDecodeTime;
169
- parsed = true;
170
- })
171
- .parse(transmuxedData);
172
-
173
- expect(parsed).toBe(true);
174
- expect(mp4Timestamp).toBe(expectedMp4Timestamp);
175
- });
176
- });
177
- });