shaka-player 4.3.10 → 4.4.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.
- package/.github/workflows/release-please.yaml +7 -0
- package/AUTHORS +9 -0
- package/CHANGELOG.md +295 -200
- package/CONTRIBUTORS +8 -0
- package/LICENSE +32 -0
- package/README.md +63 -10
- package/demo/autoTemplate.txt +40 -5
- package/demo/close_button.js +11 -0
- package/demo/common/asset.js +13 -1
- package/demo/common/assets.js +53 -3
- package/demo/common/message_ids.js +25 -1
- package/demo/config.js +69 -10
- package/demo/customWarning.txt +2 -2
- package/demo/index.html +3 -1
- package/demo/locales/en.json +26 -2
- package/demo/locales/source.json +105 -9
- package/demo/main.js +52 -9
- package/demo/search.js +3 -1
- package/demo/service_worker.js +3 -0
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +124 -112
- package/dist/demo.compiled.debug.map +3 -3
- package/dist/demo.compiled.js +124 -112
- package/dist/demo.compiled.map +3 -3
- package/dist/deps.js +46 -28
- package/dist/locales.js +28 -28
- package/dist/receiver.compiled.debug.js +52 -46
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +52 -46
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.d.ts +676 -391
- package/dist/shaka-player.compiled.debug.d.ts +676 -391
- package/dist/shaka-player.compiled.debug.externs.js +1188 -616
- package/dist/shaka-player.compiled.debug.js +1045 -700
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +1188 -616
- package/dist/shaka-player.compiled.js +1094 -933
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +677 -392
- package/dist/shaka-player.ui.debug.d.ts +677 -392
- package/dist/shaka-player.ui.debug.externs.js +1023 -451
- package/dist/shaka-player.ui.debug.js +1100 -739
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +1023 -451
- package/dist/shaka-player.ui.js +1244 -1071
- package/dist/shaka-player.ui.map +4 -4
- package/docs/tutorials/ad_monetization.md +15 -1
- package/docs/tutorials/application-level-redirects.md +1 -1
- package/docs/tutorials/config.md +9 -5
- package/docs/tutorials/drm-config.md +61 -0
- package/docs/tutorials/fairplay.md +19 -4
- package/docs/tutorials/license-server-auth.md +4 -4
- package/docs/tutorials/license-wrapping.md +2 -2
- package/docs/tutorials/ui-customization.md +7 -3
- package/docs/tutorials/ui.md +7 -7
- package/docs/tutorials/upgrade.md +3 -0
- package/externs/ima.js +123 -2
- package/externs/isoboxer.js +217 -0
- package/externs/mediakeys.js +18 -0
- package/externs/mux.js +1 -105
- package/externs/pictureinpicture.js +48 -0
- package/externs/shaka/ads.js +61 -1
- package/externs/shaka/cea.js +110 -0
- package/externs/shaka/codecs.js +32 -0
- package/externs/shaka/manifest.js +101 -1
- package/externs/shaka/manifest_parser.js +0 -10
- package/externs/shaka/net.js +36 -7
- package/externs/shaka/offline.js +8 -1
- package/externs/shaka/player.js +220 -21
- package/externs/shaka/text.js +1 -382
- package/externs/shaka/transmuxer.js +59 -0
- package/karma.conf.js +13 -0
- package/lib/abr/simple_abr_manager.js +6 -3
- package/lib/ads/ad_manager.js +60 -2
- package/lib/ads/client_side_ad.js +86 -0
- package/lib/ads/client_side_ad_manager.js +79 -3
- package/lib/ads/server_side_ad.js +86 -0
- package/lib/ads/server_side_ad_manager.js +13 -0
- package/lib/cast/cast_utils.js +1 -0
- package/lib/cea/cea608_data_channel.js +24 -14
- package/lib/cea/cea608_memory.js +5 -2
- package/lib/cea/cea708_service.js +8 -9
- package/lib/cea/cea708_window.js +1 -2
- package/lib/cea/cea_decoder.js +23 -6
- package/lib/cea/cea_utils.js +25 -2
- package/lib/cea/dummy_caption_decoder.js +21 -0
- package/lib/cea/dummy_cea_parser.js +1 -3
- package/lib/cea/mp4_cea_parser.js +15 -10
- package/lib/cea/ts_cea_parser.js +69 -0
- package/lib/dash/content_protection.js +32 -2
- package/lib/dash/dash_parser.js +93 -31
- package/lib/dash/mpd_utils.js +6 -25
- package/lib/dash/segment_base.js +12 -14
- package/lib/dash/segment_list.js +10 -6
- package/lib/dash/segment_template.js +349 -32
- package/lib/dependencies/all.js +8 -0
- package/lib/hls/hls_classes.js +33 -8
- package/lib/hls/hls_parser.js +805 -191
- package/lib/hls/manifest_text_parser.js +4 -14
- package/lib/media/adaptation_set_criteria.js +43 -3
- package/lib/media/closed_caption_parser.js +74 -12
- package/lib/media/drm_engine.js +189 -49
- package/lib/media/gap_jumping_controller.js +1 -1
- package/lib/media/manifest_parser.js +34 -0
- package/lib/media/media_source_capabilities.js +10 -0
- package/lib/media/media_source_engine.js +475 -231
- package/lib/media/playhead.js +1 -1
- package/lib/media/presentation_timeline.js +62 -0
- package/lib/media/segment_index.js +50 -14
- package/lib/media/segment_prefetch.js +277 -0
- package/lib/media/segment_reference.js +70 -4
- package/lib/media/streaming_engine.js +258 -81
- package/lib/media/video_wrapper.js +15 -7
- package/lib/mss/content_protection.js +353 -0
- package/lib/mss/mss_parser.js +1081 -0
- package/lib/net/networking_engine.js +60 -10
- package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
- package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
- package/lib/offline/manifest_converter.js +6 -0
- package/lib/offline/storage.js +2 -4
- package/lib/player.js +309 -105
- package/lib/polyfill/media_capabilities.js +43 -3
- package/lib/polyfill/patchedmediakeys_apple.js +5 -0
- package/lib/polyfill/patchedmediakeys_nop.js +5 -0
- package/lib/polyfill/patchedmediakeys_webkit.js +5 -0
- package/lib/text/cue.js +208 -130
- package/lib/text/lrc_text_parser.js +2 -2
- package/lib/text/mp4_vtt_parser.js +2 -2
- package/lib/text/sbv_text_parser.js +1 -1
- package/lib/text/simple_text_displayer.js +2 -1
- package/lib/text/srt_text_parser.js +9 -1
- package/lib/text/ssa_text_parser.js +2 -2
- package/lib/text/text_engine.js +3 -21
- package/lib/text/text_utils.js +71 -20
- package/lib/text/ui_text_displayer.js +14 -14
- package/lib/text/vtt_text_parser.js +22 -14
- package/lib/transmuxer/aac_transmuxer.js +224 -0
- package/lib/transmuxer/ac3.js +142 -0
- package/lib/transmuxer/ac3_transmuxer.js +212 -0
- package/lib/transmuxer/adts.js +232 -0
- package/lib/transmuxer/ec3.js +103 -0
- package/lib/transmuxer/ec3_transmuxer.js +212 -0
- package/lib/transmuxer/h264.js +324 -0
- package/lib/transmuxer/mp3_transmuxer.js +204 -0
- package/lib/transmuxer/mpeg_audio.js +196 -0
- package/lib/transmuxer/mpeg_ts_transmuxer.js +182 -0
- package/lib/transmuxer/mss_transmuxer.js +389 -0
- package/lib/{media/transmuxer.js → transmuxer/muxjs_transmuxer.js} +34 -80
- package/lib/transmuxer/transmuxer_engine.js +161 -0
- package/lib/transmuxer/ts_transmuxer.js +738 -0
- package/lib/util/cmcd_manager.js +131 -71
- package/lib/util/error.js +62 -26
- package/lib/util/exp_golomb.js +220 -0
- package/lib/util/fairplay_utils.js +64 -13
- package/lib/util/id3_utils.js +56 -3
- package/lib/util/language_utils.js +11 -8
- package/lib/util/manifest_parser_utils.js +3 -0
- package/lib/util/mime_utils.js +44 -7
- package/lib/util/mp4_box_parsers.js +233 -5
- package/lib/util/mp4_generator.js +1381 -0
- package/lib/util/periods.js +40 -34
- package/lib/util/platform.js +17 -3
- package/lib/util/player_configuration.js +38 -1
- package/lib/util/stream_utils.js +138 -27
- package/lib/util/text_parser.js +1 -1
- package/lib/util/ts_parser.js +470 -47
- package/lib/util/xml_utils.js +16 -3
- package/maintained-branches.md +2 -2
- package/package.json +3 -1
- package/roadmap.md +21 -6
- package/shaka-player.uncompiled.js +18 -0
- package/test/abr/simple_abr_manager_unit.js +32 -4
- package/test/ads/ad_manager_unit.js +18 -2
- package/test/cast/cast_utils_unit.js +7 -2
- package/test/cea/cea608_memory_unit.js +24 -0
- package/test/cea/cea_decoder_unit.js +33 -0
- package/test/dash/dash_parser_content_protection_unit.js +93 -3
- package/test/dash/dash_parser_live_unit.js +56 -13
- package/test/dash/dash_parser_manifest_unit.js +70 -2
- package/test/dash/dash_parser_segment_base_unit.js +14 -9
- package/test/dash/dash_parser_segment_template_unit.js +286 -6
- package/test/demo/demo_unit.js +5 -1
- package/test/hls/hls_live_unit.js +188 -28
- package/test/hls/hls_parser_unit.js +250 -109
- package/test/hls/manifest_text_parser_unit.js +18 -13
- package/test/media/adaptation_set_criteria_unit.js +46 -14
- package/test/media/adaptation_set_unit.js +2 -0
- package/test/media/drm_engine_integration.js +11 -8
- package/test/media/drm_engine_unit.js +220 -7
- package/test/media/media_source_engine_integration.js +122 -38
- package/test/media/media_source_engine_unit.js +133 -153
- package/test/media/playhead_unit.js +3 -0
- package/test/media/presentation_timeline_unit.js +51 -0
- package/test/media/segment_index_unit.js +52 -0
- package/test/media/segment_prefetch_unit.js +243 -0
- package/test/media/streaming_engine_integration.js +9 -3
- package/test/media/streaming_engine_unit.js +440 -59
- package/test/mss/mss_parser_content_protection_unit.js +49 -0
- package/test/mss/mss_parser_unit.js +472 -0
- package/test/mss/mss_player_integration.js +123 -0
- package/test/offline/manifest_convert_unit.js +9 -0
- package/test/offline/storage_integration.js +6 -1
- package/test/player_unit.js +386 -133
- package/test/polyfill/media_capabilities_unit.js +18 -0
- package/test/test/assets/hls-raw-aac/fileSequence0.aac +0 -0
- package/test/test/assets/hls-raw-aac/fileSequence1.aac +0 -0
- package/test/test/assets/hls-raw-aac/fileSequence2.aac +0 -0
- package/test/test/assets/hls-raw-aac/fileSequence3.aac +0 -0
- package/test/test/assets/hls-raw-aac/manifest.m3u8 +4 -0
- package/test/test/assets/hls-raw-aac/stream.m4a.m3u8 +14 -0
- package/test/test/assets/hls-raw-ac3/fileSequence0.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/fileSequence1.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/fileSequence2.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/fileSequence3.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/fileSequence4.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/fileSequence5.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/fileSequence6.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/fileSequence7.ac3 +0 -0
- package/test/test/assets/hls-raw-ac3/prog_index.m3u8 +31 -0
- package/test/test/assets/hls-raw-ec3/fileSequence0.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/fileSequence1.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/fileSequence2.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/fileSequence3.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/fileSequence4.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/fileSequence5.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/fileSequence6.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/fileSequence7.ec3 +0 -0
- package/test/test/assets/hls-raw-ec3/prog_index.m3u8 +31 -0
- package/test/test/assets/hls-raw-mp3/chunklist_w905519204.m3u8 +13 -0
- package/test/test/assets/hls-raw-mp3/media_w905519204_0.mp3 +0 -0
- package/test/test/assets/hls-raw-mp3/media_w905519204_1.mp3 +0 -0
- package/test/test/assets/hls-raw-mp3/media_w905519204_2.mp3 +0 -0
- package/test/test/assets/hls-raw-mp3/media_w905519204_3.mp3 +0 -0
- package/test/test/assets/hls-raw-mp3/playlist.m3u8 +4 -0
- package/test/test/assets/hls-ts-aac/playlist.m3u8 +23 -0
- package/test/test/assets/hls-ts-aac/segment_0.ts +0 -0
- package/test/test/assets/hls-ts-aac/segment_1.ts +0 -0
- package/test/test/assets/hls-ts-aac/segment_2.ts +0 -0
- package/test/test/assets/hls-ts-aac/segment_3.ts +0 -0
- package/test/test/assets/hls-ts-aac/segment_4.ts +0 -0
- package/test/test/assets/hls-ts-aac/segment_5.ts +0 -0
- package/test/test/assets/hls-ts-aac/segment_6.ts +0 -0
- package/test/test/assets/hls-ts-aac/segment_7.ts +0 -0
- package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0000.ts +0 -0
- package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0001.ts +0 -0
- package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0002.ts +0 -0
- package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0003.ts +0 -0
- package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0004.ts +0 -0
- package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0005.ts +0 -0
- package/test/test/assets/hls-ts-ac3/prog_index.m3u8 +19 -0
- package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0000.ts +0 -0
- package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0001.ts +0 -0
- package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0002.ts +0 -0
- package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0003.ts +0 -0
- package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0004.ts +0 -0
- package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0005.ts +0 -0
- package/test/test/assets/hls-ts-ec3/prog_index.m3u8 +19 -0
- package/test/test/assets/hls-ts-h264/fileSequence0.ts +0 -0
- package/test/test/assets/hls-ts-h264/fileSequence1.ts +0 -0
- package/test/test/assets/hls-ts-h264/fileSequence2.ts +0 -0
- package/test/test/assets/hls-ts-h264/fileSequence3.ts +0 -0
- package/test/test/assets/hls-ts-h264/fileSequence4.ts +0 -0
- package/test/test/assets/hls-ts-h264/fileSequence5.ts +0 -0
- package/test/test/assets/hls-ts-h264/prog_index.m3u8 +25 -0
- package/test/test/assets/hls-ts-mp3/manifest.m3u8 +13 -0
- package/test/test/assets/hls-ts-mp3/media_w239891843_0.ts +0 -0
- package/test/test/assets/hls-ts-mp3/media_w239891843_1.ts +0 -0
- package/test/test/assets/hls-ts-mp3/media_w239891843_2.ts +0 -0
- package/test/test/assets/hls-ts-mp3/media_w239891843_3.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/chunk.m3u8 +17 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/n_0_0_0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/n_1_0_0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/n_2_0_0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/n_3_0_0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/n_4_0_0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/n_5_0_0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h264/playlist.m3u8 +4 -0
- package/test/test/boot.js +7 -2
- package/test/test/util/fake_ad.js +99 -0
- package/test/test/util/fake_ad_manager.js +7 -1
- package/test/test/util/fake_networking_engine.js +41 -14
- package/test/test/util/fake_segment_prefetch.js +81 -0
- package/test/test/util/manifest_generator.js +19 -5
- package/test/test/util/mss_parser_util.js +115 -0
- package/test/test/util/offline_utils.js +1 -0
- package/test/test/util/simple_fakes.js +12 -3
- package/test/test/util/streaming_engine_util.js +14 -4
- package/test/test/util/ttml_utils.js +2 -2
- package/test/text/cue_integration.js +1 -1
- package/test/text/srt_text_parser_unit.js +78 -0
- package/test/text/text_engine_unit.js +17 -8
- package/test/text/ui_text_displayer_unit.js +4 -4
- package/test/text/vtt_text_parser_unit.js +59 -40
- package/test/text/web_vtt_generator_unit.js +9 -3
- package/test/{media/transmuxer_integration.js → transmuxer/muxjs_transmuxer_integration.js} +30 -33
- package/test/transmuxer/transmuxer_engine_integration.js +60 -0
- package/test/transmuxer/transmuxer_integration.js +296 -0
- package/test/util/cmcd_manager_unit.js +162 -13
- package/test/util/language_utils_unit.js +9 -2
- package/test/util/mp4_box_parsers_unit.js +39 -4
- package/test/util/periods_unit.js +34 -26
- package/test/util/stream_utils_unit.js +60 -107
- package/ui/controls.js +19 -1
- package/ui/controls.less +1 -0
- package/ui/externs/ui.js +11 -1
- package/ui/language_utils.js +15 -0
- package/ui/less/thumbnails.less +26 -0
- package/ui/locales/oc.json +42 -0
- package/ui/pip_button.js +83 -2
- package/ui/range_element.js +15 -0
- package/ui/resolution_selection.js +9 -2
- package/ui/seek_bar.js +223 -0
- package/ui/ui.js +5 -0
- package/lib/cea/i_caption_decoder.js +0 -51
- package/lib/cea/i_cea_parser.js +0 -68
|
@@ -135,7 +135,7 @@ shaka.text.Mp4VttParser = class {
|
|
|
135
135
|
box.version == 0 || box.version == 1,
|
|
136
136
|
'TFDT version can only be 0 or 1');
|
|
137
137
|
|
|
138
|
-
const parsedTFDTBox = shaka.util.Mp4BoxParsers.
|
|
138
|
+
const parsedTFDTBox = shaka.util.Mp4BoxParsers.parseTFDTInaccurate(
|
|
139
139
|
box.reader, box.version);
|
|
140
140
|
baseTime = parsedTFDTBox.baseMediaDecodeTime;
|
|
141
141
|
})
|
|
@@ -250,7 +250,7 @@ shaka.text.Mp4VttParser = class {
|
|
|
250
250
|
'MDAT which contain VTT cues and non-VTT data are not currently ' +
|
|
251
251
|
'supported!');
|
|
252
252
|
|
|
253
|
-
return /** @type {!Array.<!shaka.
|
|
253
|
+
return /** @type {!Array.<!shaka.text.Cue>} */ (
|
|
254
254
|
cues.filter(shaka.util.Functional.isNotNull));
|
|
255
255
|
}
|
|
256
256
|
|
|
@@ -51,6 +51,7 @@ shaka.text.SimpleTextDisplayer = class {
|
|
|
51
51
|
// kinds which can be displayed in the app's UI.
|
|
52
52
|
this.textTrack_ = video.addTextTrack(
|
|
53
53
|
'subtitles', shaka.Player.TextTrackLabel);
|
|
54
|
+
console.log(this.textTrack_);
|
|
54
55
|
}
|
|
55
56
|
this.textTrack_.mode = 'hidden';
|
|
56
57
|
}
|
|
@@ -179,7 +180,7 @@ shaka.text.SimpleTextDisplayer = class {
|
|
|
179
180
|
}
|
|
180
181
|
|
|
181
182
|
/**
|
|
182
|
-
* @param {!shaka.
|
|
183
|
+
* @param {!shaka.text.Cue} shakaCue
|
|
183
184
|
* @return {TextTrackCue}
|
|
184
185
|
* @private
|
|
185
186
|
*/
|
|
@@ -110,7 +110,15 @@ shaka.text.SrtTextParser = class {
|
|
|
110
110
|
// convert time codes
|
|
111
111
|
lines[0] = lines[0].replace(/,/g, '.');
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
const webvttCue = lines.join('\n')
|
|
114
|
+
.replace(/{b}/g, '<b>')
|
|
115
|
+
.replace(/{\/b}/g, '</b>')
|
|
116
|
+
.replace(/{i}/g, '<i>')
|
|
117
|
+
.replace(/{\/i}/g, '</i>')
|
|
118
|
+
.replace(/{u}/g, '<u>')
|
|
119
|
+
.replace(/{\/u}/g, '</u>');
|
|
120
|
+
|
|
121
|
+
return webvttCue + '\n\n';
|
|
114
122
|
}
|
|
115
123
|
};
|
|
116
124
|
|
|
@@ -105,7 +105,7 @@ shaka.text.SsaTextParser = class {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
// Process cues
|
|
108
|
-
/** @type {!Array.<!shaka.
|
|
108
|
+
/** @type {!Array.<!shaka.text.Cue>} */
|
|
109
109
|
const cues = [];
|
|
110
110
|
|
|
111
111
|
// Used to be able to iterate over the event parameters.
|
|
@@ -160,7 +160,7 @@ shaka.text.SsaTextParser = class {
|
|
|
160
160
|
/**
|
|
161
161
|
* Adds applicable style properties to a cue.
|
|
162
162
|
*
|
|
163
|
-
* @param {shaka.
|
|
163
|
+
* @param {shaka.text.Cue} cue
|
|
164
164
|
* @param {Object} style
|
|
165
165
|
* @private
|
|
166
166
|
*/
|
package/lib/text/text_engine.js
CHANGED
|
@@ -8,11 +8,11 @@ goog.provide('shaka.text.TextEngine');
|
|
|
8
8
|
|
|
9
9
|
goog.require('goog.asserts');
|
|
10
10
|
goog.require('shaka.log');
|
|
11
|
+
goog.require('shaka.media.ClosedCaptionParser');
|
|
11
12
|
goog.require('shaka.text.Cue');
|
|
12
13
|
goog.require('shaka.util.BufferUtils');
|
|
13
14
|
goog.require('shaka.util.IDestroyable');
|
|
14
15
|
goog.require('shaka.util.MimeUtils');
|
|
15
|
-
goog.requireType('shaka.cea.ICaptionDecoder');
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
// TODO: revisit this when Closure Compiler supports partially-exported classes.
|
|
@@ -100,8 +100,7 @@ shaka.text.TextEngine = class {
|
|
|
100
100
|
}
|
|
101
101
|
if (mimeType == shaka.util.MimeUtils.CEA608_CLOSED_CAPTION_MIMETYPE ||
|
|
102
102
|
mimeType == shaka.util.MimeUtils.CEA708_CLOSED_CAPTION_MIMETYPE ) {
|
|
103
|
-
|
|
104
|
-
return true;
|
|
103
|
+
return !!shaka.media.ClosedCaptionParser.findDecoder();
|
|
105
104
|
}
|
|
106
105
|
return false;
|
|
107
106
|
}
|
|
@@ -345,23 +344,6 @@ shaka.text.TextEngine = class {
|
|
|
345
344
|
}
|
|
346
345
|
}
|
|
347
346
|
|
|
348
|
-
/**
|
|
349
|
-
* @param {!Array<muxjs.mp4.ClosedCaption>} closedCaptions
|
|
350
|
-
* @return {!Array<!shaka.cea.ICaptionDecoder.ClosedCaption>}
|
|
351
|
-
*/
|
|
352
|
-
convertMuxjsCaptionsToShakaCaptions(closedCaptions) {
|
|
353
|
-
const cues = [];
|
|
354
|
-
for (const caption of closedCaptions) {
|
|
355
|
-
const cue = new shaka.text.Cue(
|
|
356
|
-
caption.startTime, caption.endTime, caption.text);
|
|
357
|
-
cues.push({
|
|
358
|
-
stream: caption.stream,
|
|
359
|
-
cue,
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
return cues;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
347
|
/**
|
|
366
348
|
* @param {!shaka.text.Cue} cue the cue to apply the timestamp to recursively
|
|
367
349
|
* @param {number} videoTimestampOffset the timestamp offset of the video
|
|
@@ -379,7 +361,7 @@ shaka.text.TextEngine = class {
|
|
|
379
361
|
* Store the closed captions in the text engine, and append the cues to the
|
|
380
362
|
* text displayer. This is a side-channel used for embedded text only.
|
|
381
363
|
*
|
|
382
|
-
* @param {!Array
|
|
364
|
+
* @param {!Array<!shaka.extern.ICaptionDecoder.ClosedCaption>} closedCaptions
|
|
383
365
|
* @param {?number} startTime relative to the start of the presentation
|
|
384
366
|
* @param {?number} endTime relative to the start of the presentation
|
|
385
367
|
* @param {number} videoTimestampOffset the timestamp offset of the video
|
package/lib/text/text_utils.js
CHANGED
|
@@ -19,40 +19,91 @@ shaka.text.Utils = class {
|
|
|
19
19
|
* @private
|
|
20
20
|
*/
|
|
21
21
|
static flattenPayload_(cue) {
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
if (cue.lineBreak) {
|
|
23
|
+
// This is a vertical lineBreak, so insert a newline.
|
|
24
|
+
return '\n';
|
|
25
|
+
}
|
|
26
|
+
if (cue.nestedCues.length) {
|
|
27
|
+
return cue.nestedCues.map(shaka.text.Utils.flattenPayload_).join('');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Handle bold, italics and underline
|
|
24
31
|
const openStyleTags = [];
|
|
25
32
|
const bold = cue.fontWeight >= shaka.text.Cue.fontWeight.BOLD;
|
|
26
33
|
const italics = cue.fontStyle == shaka.text.Cue.fontStyle.ITALIC;
|
|
27
34
|
const underline = cue.textDecoration.includes(
|
|
28
35
|
shaka.text.Cue.textDecoration.UNDERLINE);
|
|
29
36
|
if (bold) {
|
|
30
|
-
openStyleTags.push('b');
|
|
37
|
+
openStyleTags.push(['b']);
|
|
31
38
|
}
|
|
32
39
|
if (italics) {
|
|
33
|
-
openStyleTags.push('i');
|
|
40
|
+
openStyleTags.push(['i']);
|
|
34
41
|
}
|
|
35
42
|
if (underline) {
|
|
36
|
-
openStyleTags.push('u');
|
|
43
|
+
openStyleTags.push(['u']);
|
|
44
|
+
}
|
|
45
|
+
// Handle color classes, if the value consists of letters
|
|
46
|
+
let classes = '';
|
|
47
|
+
const color = shaka.text.Utils.getColorName_(cue.color);
|
|
48
|
+
if (color) {
|
|
49
|
+
classes += `.${color}`;
|
|
50
|
+
}
|
|
51
|
+
const bgColor = shaka.text.Utils.getColorName_(cue.backgroundColor);
|
|
52
|
+
if (bgColor) {
|
|
53
|
+
classes += `.bg_${bgColor}`;
|
|
54
|
+
}
|
|
55
|
+
if (classes) {
|
|
56
|
+
openStyleTags.push(['c', classes]);
|
|
37
57
|
}
|
|
38
58
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const suffixStyleTags = openStyleTags.reduceRight((acc, tag) => {
|
|
44
|
-
return `${acc}</${tag}>`;
|
|
45
|
-
}, '');
|
|
59
|
+
return openStyleTags.reduceRight((acc, [tag, classes = '']) => {
|
|
60
|
+
return `<${tag}${classes}>${acc}</${tag}>`;
|
|
61
|
+
}, cue.payload);
|
|
62
|
+
}
|
|
46
63
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Gets the color name from a color string.
|
|
66
|
+
*
|
|
67
|
+
* @param {string} string
|
|
68
|
+
* @return {?string}
|
|
69
|
+
* @private
|
|
70
|
+
*/
|
|
71
|
+
static getColorName_(string) {
|
|
72
|
+
switch (string.toLowerCase()) {
|
|
73
|
+
case 'white':
|
|
74
|
+
case '#fff':
|
|
75
|
+
case '#ffffff':
|
|
76
|
+
return 'white';
|
|
77
|
+
case 'lime':
|
|
78
|
+
case '#0f0':
|
|
79
|
+
case '#00ff00':
|
|
80
|
+
return 'lime';
|
|
81
|
+
case 'cyan':
|
|
82
|
+
case '#0ff':
|
|
83
|
+
case '#00ffff':
|
|
84
|
+
return 'cyan';
|
|
85
|
+
case 'red':
|
|
86
|
+
case '#f00':
|
|
87
|
+
case '#ff0000':
|
|
88
|
+
return 'red';
|
|
89
|
+
case 'yellow':
|
|
90
|
+
case '#ff0':
|
|
91
|
+
case '#ffff00':
|
|
92
|
+
return 'yellow';
|
|
93
|
+
case 'magenta':
|
|
94
|
+
case '#f0f':
|
|
95
|
+
return 'magenta';
|
|
96
|
+
case 'blue':
|
|
97
|
+
case '#00f':
|
|
98
|
+
case '#0000ff':
|
|
99
|
+
return 'blue';
|
|
100
|
+
case 'black':
|
|
101
|
+
case '#000':
|
|
102
|
+
case '#000000':
|
|
103
|
+
return 'black';
|
|
55
104
|
}
|
|
105
|
+
// No color name
|
|
106
|
+
return null;
|
|
56
107
|
}
|
|
57
108
|
|
|
58
109
|
/**
|
|
@@ -75,7 +75,7 @@ shaka.text.UITextDisplayer = class {
|
|
|
75
75
|
/**
|
|
76
76
|
* Maps cues to cue elements. Specifically points out the wrapper element of
|
|
77
77
|
* the cue (e.g. the HTML element to put nested cues inside).
|
|
78
|
-
* @private {Map.<!shaka.
|
|
78
|
+
* @private {Map.<!shaka.text.Cue, !{
|
|
79
79
|
* cueElement: !HTMLElement,
|
|
80
80
|
* regionElement: HTMLElement,
|
|
81
81
|
* wrapper: !HTMLElement
|
|
@@ -213,10 +213,10 @@ shaka.text.UITextDisplayer = class {
|
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
/**
|
|
216
|
-
* @param {!Array.<!shaka.
|
|
216
|
+
* @param {!Array.<!shaka.text.Cue>} cues
|
|
217
217
|
* @param {!HTMLElement} container
|
|
218
218
|
* @param {number} currentTime
|
|
219
|
-
* @param {!Array.<!shaka.
|
|
219
|
+
* @param {!Array.<!shaka.text.Cue>} parents
|
|
220
220
|
* @private
|
|
221
221
|
*/
|
|
222
222
|
updateCuesRecursive_(cues, container, currentTime, parents) {
|
|
@@ -235,7 +235,7 @@ shaka.text.UITextDisplayer = class {
|
|
|
235
235
|
* The cues whose corresponding elements should be in the DOM.
|
|
236
236
|
* Some of these might be new, some might have been displayed beforehand.
|
|
237
237
|
* These will only be added if updateDOM is true.
|
|
238
|
-
* @type {!Array.<!shaka.
|
|
238
|
+
* @type {!Array.<!shaka.text.Cue>}
|
|
239
239
|
*/
|
|
240
240
|
const toPlant = [];
|
|
241
241
|
for (const cue of cues) {
|
|
@@ -375,7 +375,7 @@ shaka.text.UITextDisplayer = class {
|
|
|
375
375
|
* Compute a unique internal id:
|
|
376
376
|
* Regions can reuse the id but have different dimensions, we need to
|
|
377
377
|
* consider those differences
|
|
378
|
-
* @param {shaka.
|
|
378
|
+
* @param {shaka.text.CueRegion} region
|
|
379
379
|
* @private
|
|
380
380
|
*/
|
|
381
381
|
generateRegionId_(region) {
|
|
@@ -394,7 +394,7 @@ shaka.text.UITextDisplayer = class {
|
|
|
394
394
|
* Get or create a region element corresponding to the cue region. These are
|
|
395
395
|
* cached by ID.
|
|
396
396
|
*
|
|
397
|
-
* @param {!shaka.
|
|
397
|
+
* @param {!shaka.text.Cue} cue
|
|
398
398
|
* @return {!HTMLElement}
|
|
399
399
|
* @private
|
|
400
400
|
*/
|
|
@@ -442,8 +442,8 @@ shaka.text.UITextDisplayer = class {
|
|
|
442
442
|
/**
|
|
443
443
|
* Creates the object for a cue.
|
|
444
444
|
*
|
|
445
|
-
* @param {!shaka.
|
|
446
|
-
* @param {!Array.<!shaka.
|
|
445
|
+
* @param {!shaka.text.Cue} cue
|
|
446
|
+
* @param {!Array.<!shaka.text.Cue>} parents
|
|
447
447
|
* @private
|
|
448
448
|
*/
|
|
449
449
|
createCue_(cue, parents) {
|
|
@@ -483,8 +483,8 @@ shaka.text.UITextDisplayer = class {
|
|
|
483
483
|
|
|
484
484
|
/**
|
|
485
485
|
* @param {!HTMLElement} cueElement
|
|
486
|
-
* @param {!shaka.
|
|
487
|
-
* @param {!Array.<!shaka.
|
|
486
|
+
* @param {!shaka.text.Cue} cue
|
|
487
|
+
* @param {!Array.<!shaka.text.Cue>} parents
|
|
488
488
|
* @param {boolean} hasWrapper
|
|
489
489
|
* @private
|
|
490
490
|
*/
|
|
@@ -722,7 +722,7 @@ shaka.text.UITextDisplayer = class {
|
|
|
722
722
|
* absolute value in pixels based on Computed Cell Size
|
|
723
723
|
*
|
|
724
724
|
* @param {string} lengthValue
|
|
725
|
-
* @param {!shaka.
|
|
725
|
+
* @param {!shaka.text.Cue} cue
|
|
726
726
|
* @param {HTMLElement} videoContainer
|
|
727
727
|
* @return {string}
|
|
728
728
|
* @private
|
|
@@ -753,7 +753,7 @@ shaka.text.UITextDisplayer = class {
|
|
|
753
753
|
* Returns computed absolute length value in pixels based on cell
|
|
754
754
|
* and a video container size
|
|
755
755
|
* @param {number} value
|
|
756
|
-
* @param {!shaka.
|
|
756
|
+
* @param {!shaka.text.Cue} cue
|
|
757
757
|
* @param {HTMLElement} videoContainer
|
|
758
758
|
* @return {string}
|
|
759
759
|
*
|
|
@@ -770,8 +770,8 @@ shaka.text.UITextDisplayer = class {
|
|
|
770
770
|
* it is assumed to be inherited from the parent. This returns null if the
|
|
771
771
|
* value isn't found.
|
|
772
772
|
*
|
|
773
|
-
* @param {!Array.<!shaka.
|
|
774
|
-
* @param {function(!shaka.
|
|
773
|
+
* @param {!Array.<!shaka.text.Cue>} parents
|
|
774
|
+
* @param {function(!shaka.text.Cue):?T} cb
|
|
775
775
|
* @return {?T}
|
|
776
776
|
* @template T
|
|
777
777
|
* @private
|
|
@@ -116,7 +116,7 @@ shaka.text.VttTextParser = class {
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
// Parse VTT regions.
|
|
119
|
-
/* !Array.<!shaka.
|
|
119
|
+
/* !Array.<!shaka.text.CueRegion> */
|
|
120
120
|
const regions = [];
|
|
121
121
|
for (const line of blocks[0].split('\n')) {
|
|
122
122
|
if (/^Region:/.test(line)) {
|
|
@@ -169,7 +169,7 @@ shaka.text.VttTextParser = class {
|
|
|
169
169
|
* Parses a string into a Region object.
|
|
170
170
|
*
|
|
171
171
|
* @param {string} text
|
|
172
|
-
* @return {!shaka.
|
|
172
|
+
* @return {!shaka.text.CueRegion}
|
|
173
173
|
* @private
|
|
174
174
|
*/
|
|
175
175
|
static parseRegion_(text) {
|
|
@@ -344,7 +344,7 @@ shaka.text.VttTextParser = class {
|
|
|
344
344
|
*
|
|
345
345
|
* @param {!Array.<string>} text
|
|
346
346
|
* @param {number} timeOffset
|
|
347
|
-
* @param {!Array.<!shaka.
|
|
347
|
+
* @param {!Array.<!shaka.text.CueRegion>} regions
|
|
348
348
|
* @param {!Map.<string, shaka.text.Cue>} styles
|
|
349
349
|
* @return {shaka.text.Cue}
|
|
350
350
|
* @private
|
|
@@ -380,11 +380,9 @@ shaka.text.VttTextParser = class {
|
|
|
380
380
|
let end = VttTextParser.parseTime_(parser);
|
|
381
381
|
|
|
382
382
|
if (start == null || expect == null || end == null) {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
shaka.util.Error.Code.INVALID_TEXT_CUE,
|
|
387
|
-
'Could not parse cue time range in WebVTT');
|
|
383
|
+
shaka.log.alwaysWarn(
|
|
384
|
+
'Failed to parse VTT time code. Cue skipped:', id, text);
|
|
385
|
+
return null;
|
|
388
386
|
}
|
|
389
387
|
|
|
390
388
|
start += timeOffset;
|
|
@@ -442,7 +440,7 @@ shaka.text.VttTextParser = class {
|
|
|
442
440
|
const xmlPayload = '<span>' + payload + '</span>';
|
|
443
441
|
const element = shaka.util.XmlUtils.parseXmlString(xmlPayload, 'span');
|
|
444
442
|
if (element) {
|
|
445
|
-
/** @type {!Array.<!shaka.
|
|
443
|
+
/** @type {!Array.<!shaka.text.Cue>} */
|
|
446
444
|
const cues = [];
|
|
447
445
|
const childNodes = element.childNodes;
|
|
448
446
|
if (childNodes.length == 1) {
|
|
@@ -649,8 +647,8 @@ shaka.text.VttTextParser = class {
|
|
|
649
647
|
|
|
650
648
|
/**
|
|
651
649
|
* Merges values created in parseStyle_
|
|
652
|
-
* @param {!shaka.
|
|
653
|
-
* @param {shaka.
|
|
650
|
+
* @param {!shaka.text.Cue} cue
|
|
651
|
+
* @param {shaka.text.Cue} refCue
|
|
654
652
|
* @private
|
|
655
653
|
*/
|
|
656
654
|
static mergeStyle_(cue, refCue) {
|
|
@@ -681,7 +679,7 @@ shaka.text.VttTextParser = class {
|
|
|
681
679
|
/**
|
|
682
680
|
* @param {!Node} element
|
|
683
681
|
* @param {!shaka.text.Cue} rootCue
|
|
684
|
-
* @param {Array.<!shaka.
|
|
682
|
+
* @param {Array.<!shaka.text.Cue>} cues
|
|
685
683
|
* @param {!Map.<string, shaka.text.Cue>} styles
|
|
686
684
|
* @private
|
|
687
685
|
*/
|
|
@@ -724,6 +722,14 @@ shaka.text.VttTextParser = class {
|
|
|
724
722
|
case 'u':
|
|
725
723
|
nestedCue.textDecoration.push(underline);
|
|
726
724
|
break;
|
|
725
|
+
case 'font': {
|
|
726
|
+
const color =
|
|
727
|
+
/** @type {!Element} */(element).getAttribute('color');
|
|
728
|
+
if (color) {
|
|
729
|
+
nestedCue.color = color;
|
|
730
|
+
}
|
|
731
|
+
break;
|
|
732
|
+
}
|
|
727
733
|
case 'div': {
|
|
728
734
|
const time = /** @type {!Element} */(element).getAttribute('time');
|
|
729
735
|
if (!time) {
|
|
@@ -787,7 +793,7 @@ shaka.text.VttTextParser = class {
|
|
|
787
793
|
cue.size = Number(results[1]);
|
|
788
794
|
} else if ((results =
|
|
789
795
|
// eslint-disable-next-line max-len
|
|
790
|
-
/^position:([\d.]+)%(?:,(line-left|line-right|middle|center|start|end))?$/
|
|
796
|
+
/^position:([\d.]+)%(?:,(line-left|line-right|middle|center|start|end|auto))?$/
|
|
791
797
|
.exec(word))) {
|
|
792
798
|
cue.position = Number(results[1]);
|
|
793
799
|
if (results[2]) {
|
|
@@ -891,8 +897,10 @@ shaka.text.VttTextParser = class {
|
|
|
891
897
|
cue.positionAlign = Cue.positionAlign.LEFT;
|
|
892
898
|
} else if (align == 'line-right' || align == 'end') {
|
|
893
899
|
cue.positionAlign = Cue.positionAlign.RIGHT;
|
|
894
|
-
} else {
|
|
900
|
+
} else if (align == 'center' || align == 'middle') {
|
|
895
901
|
cue.positionAlign = Cue.positionAlign.CENTER;
|
|
902
|
+
} else {
|
|
903
|
+
cue.positionAlign = Cue.positionAlign.AUTO;
|
|
896
904
|
}
|
|
897
905
|
}
|
|
898
906
|
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/*! @license
|
|
2
|
+
* Shaka Player
|
|
3
|
+
* Copyright 2016 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
goog.provide('shaka.transmuxer.AacTransmuxer');
|
|
8
|
+
|
|
9
|
+
goog.require('shaka.media.Capabilities');
|
|
10
|
+
goog.require('shaka.transmuxer.ADTS');
|
|
11
|
+
goog.require('shaka.transmuxer.TransmuxerEngine');
|
|
12
|
+
goog.require('shaka.util.BufferUtils');
|
|
13
|
+
goog.require('shaka.util.Error');
|
|
14
|
+
goog.require('shaka.util.Id3Utils');
|
|
15
|
+
goog.require('shaka.util.ManifestParserUtils');
|
|
16
|
+
goog.require('shaka.util.MimeUtils');
|
|
17
|
+
goog.require('shaka.util.Mp4Generator');
|
|
18
|
+
goog.require('shaka.util.Uint8ArrayUtils');
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @implements {shaka.extern.Transmuxer}
|
|
23
|
+
* @export
|
|
24
|
+
*/
|
|
25
|
+
shaka.transmuxer.AacTransmuxer = class {
|
|
26
|
+
/**
|
|
27
|
+
* @param {string} mimeType
|
|
28
|
+
*/
|
|
29
|
+
constructor(mimeType) {
|
|
30
|
+
/** @private {string} */
|
|
31
|
+
this.originalMimeType_ = mimeType;
|
|
32
|
+
|
|
33
|
+
/** @private {number} */
|
|
34
|
+
this.frameIndex_ = 0;
|
|
35
|
+
|
|
36
|
+
/** @private {!Map.<number, !Uint8Array>} */
|
|
37
|
+
this.initSegments = new Map();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @override
|
|
43
|
+
* @export
|
|
44
|
+
*/
|
|
45
|
+
destroy() {
|
|
46
|
+
this.initSegments.clear();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Check if the mime type and the content type is supported.
|
|
52
|
+
* @param {string} mimeType
|
|
53
|
+
* @param {string=} contentType
|
|
54
|
+
* @return {boolean}
|
|
55
|
+
* @override
|
|
56
|
+
* @export
|
|
57
|
+
*/
|
|
58
|
+
isSupported(mimeType, contentType) {
|
|
59
|
+
const Capabilities = shaka.media.Capabilities;
|
|
60
|
+
|
|
61
|
+
if (!this.isAacContainer_(mimeType)) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
65
|
+
return Capabilities.isTypeSupported(
|
|
66
|
+
this.convertCodecs(ContentType.AUDIO, mimeType));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Check if the mimetype is 'audio/aac'.
|
|
72
|
+
* @param {string} mimeType
|
|
73
|
+
* @return {boolean}
|
|
74
|
+
* @private
|
|
75
|
+
*/
|
|
76
|
+
isAacContainer_(mimeType) {
|
|
77
|
+
return mimeType.toLowerCase().split(';')[0] == 'audio/aac';
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @override
|
|
83
|
+
* @export
|
|
84
|
+
*/
|
|
85
|
+
convertCodecs(contentType, mimeType) {
|
|
86
|
+
if (this.isAacContainer_(mimeType)) {
|
|
87
|
+
const codecs = shaka.util.MimeUtils.getCodecs(mimeType);
|
|
88
|
+
return `audio/mp4; codecs="${codecs || 'mp4a.40.2'}"`;
|
|
89
|
+
}
|
|
90
|
+
return mimeType;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @override
|
|
96
|
+
* @export
|
|
97
|
+
*/
|
|
98
|
+
getOrginalMimeType() {
|
|
99
|
+
return this.originalMimeType_;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* @override
|
|
105
|
+
* @export
|
|
106
|
+
*/
|
|
107
|
+
transmux(data, stream, reference, duration) {
|
|
108
|
+
const ADTS = shaka.transmuxer.ADTS;
|
|
109
|
+
const Uint8ArrayUtils = shaka.util.Uint8ArrayUtils;
|
|
110
|
+
|
|
111
|
+
const uint8ArrayData = shaka.util.BufferUtils.toUint8(data);
|
|
112
|
+
|
|
113
|
+
// Check for the ADTS sync word
|
|
114
|
+
// Look for ADTS header | 1111 1111 | 1111 X00X | where X can be
|
|
115
|
+
// either 0 or 1
|
|
116
|
+
// Layer bits (position 14 and 15) in header should be always 0 for ADTS
|
|
117
|
+
// More info https://wiki.multimedia.cx/index.php?title=ADTS
|
|
118
|
+
const id3Data = shaka.util.Id3Utils.getID3Data(uint8ArrayData);
|
|
119
|
+
let offset = id3Data.length;
|
|
120
|
+
for (; offset < uint8ArrayData.length; offset++) {
|
|
121
|
+
if (ADTS.probe(uint8ArrayData, offset)) {
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
let timestamp = reference.endTime * 1000;
|
|
127
|
+
|
|
128
|
+
const frames = shaka.util.Id3Utils.getID3Frames(id3Data);
|
|
129
|
+
if (frames.length && reference) {
|
|
130
|
+
const metadataTimestamp = frames.find((frame) => {
|
|
131
|
+
return frame.description ===
|
|
132
|
+
'com.apple.streaming.transportStreamTimestamp';
|
|
133
|
+
});
|
|
134
|
+
if (metadataTimestamp) {
|
|
135
|
+
timestamp = /** @type {!number} */(metadataTimestamp.data);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const info = ADTS.parseInfo(uint8ArrayData, offset);
|
|
140
|
+
if (!info) {
|
|
141
|
+
return Promise.reject(new shaka.util.Error(
|
|
142
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
143
|
+
shaka.util.Error.Category.MEDIA,
|
|
144
|
+
shaka.util.Error.Code.TRANSMUXING_FAILED));
|
|
145
|
+
}
|
|
146
|
+
stream.audioSamplingRate = info.sampleRate;
|
|
147
|
+
stream.channelsCount = info.channelCount;
|
|
148
|
+
stream.codecs = info.codec;
|
|
149
|
+
|
|
150
|
+
/** @type {!Array.<shaka.util.Mp4Generator.Mp4Sample>} */
|
|
151
|
+
const samples = [];
|
|
152
|
+
|
|
153
|
+
while (offset < uint8ArrayData.length) {
|
|
154
|
+
const header = ADTS.parseHeader(uint8ArrayData, offset);
|
|
155
|
+
if (!header) {
|
|
156
|
+
return Promise.reject(new shaka.util.Error(
|
|
157
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
158
|
+
shaka.util.Error.Category.MEDIA,
|
|
159
|
+
shaka.util.Error.Code.TRANSMUXING_FAILED));
|
|
160
|
+
}
|
|
161
|
+
const length = header.headerLength + header.frameLength;
|
|
162
|
+
if (offset + length <= uint8ArrayData.length) {
|
|
163
|
+
const data = uint8ArrayData.subarray(
|
|
164
|
+
offset + header.headerLength, offset + length);
|
|
165
|
+
samples.push({
|
|
166
|
+
data: data,
|
|
167
|
+
size: header.frameLength,
|
|
168
|
+
duration: ADTS.AAC_SAMPLES_PER_FRAME,
|
|
169
|
+
cts: 0,
|
|
170
|
+
flags: {
|
|
171
|
+
isLeading: 0,
|
|
172
|
+
isDependedOn: 0,
|
|
173
|
+
hasRedundancy: 0,
|
|
174
|
+
degradPrio: 0,
|
|
175
|
+
dependsOn: 2,
|
|
176
|
+
isNonSync: 0,
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
offset += length;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** @type {number} */
|
|
184
|
+
const sampleRate = info.sampleRate;
|
|
185
|
+
/** @type {number} */
|
|
186
|
+
const baseMediaDecodeTime = Math.floor(timestamp * sampleRate / 1000);
|
|
187
|
+
|
|
188
|
+
/** @type {shaka.util.Mp4Generator.StreamInfo} */
|
|
189
|
+
const streamInfo = {
|
|
190
|
+
id: stream.id,
|
|
191
|
+
type: shaka.util.ManifestParserUtils.ContentType.AUDIO,
|
|
192
|
+
encrypted: stream.encrypted && stream.drmInfos.length > 0,
|
|
193
|
+
timescale: sampleRate,
|
|
194
|
+
duration: duration,
|
|
195
|
+
videoNalus: [],
|
|
196
|
+
audioConfig: new Uint8Array([]),
|
|
197
|
+
videoConfig: new Uint8Array([]),
|
|
198
|
+
data: {
|
|
199
|
+
sequenceNumber: this.frameIndex_,
|
|
200
|
+
baseMediaDecodeTime: baseMediaDecodeTime,
|
|
201
|
+
samples: samples,
|
|
202
|
+
},
|
|
203
|
+
stream: stream,
|
|
204
|
+
};
|
|
205
|
+
const mp4Generator = new shaka.util.Mp4Generator([streamInfo]);
|
|
206
|
+
let initSegment;
|
|
207
|
+
if (!this.initSegments.has(stream.id)) {
|
|
208
|
+
initSegment = mp4Generator.initSegment();
|
|
209
|
+
this.initSegments.set(stream.id, initSegment);
|
|
210
|
+
} else {
|
|
211
|
+
initSegment = this.initSegments.get(stream.id);
|
|
212
|
+
}
|
|
213
|
+
const segmentData = mp4Generator.segmentData();
|
|
214
|
+
|
|
215
|
+
this.frameIndex_++;
|
|
216
|
+
const transmuxData = Uint8ArrayUtils.concat(initSegment, segmentData);
|
|
217
|
+
return Promise.resolve(transmuxData);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
shaka.transmuxer.TransmuxerEngine.registerTransmuxer(
|
|
222
|
+
'audio/aac',
|
|
223
|
+
() => new shaka.transmuxer.AacTransmuxer('audio/aac'),
|
|
224
|
+
shaka.transmuxer.TransmuxerEngine.PluginPriority.FALLBACK);
|