shaka-player 4.4.3 → 4.6.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/ISSUE_TEMPLATE/bug_report.md +1 -1
- package/.github/workflows/release-please.yaml +2 -27
- package/AUTHORS +2 -0
- package/CHANGELOG.md +156 -39
- package/CODE_OF_CONDUCT.md +1 -1
- package/CONTRIBUTORS +2 -0
- package/README.md +54 -42
- package/demo/asset_card.js +18 -21
- package/demo/cast_receiver/index.html +0 -1
- package/demo/close_button.js +0 -3
- package/demo/common/asset.js +33 -22
- package/demo/common/assets.js +249 -60
- package/demo/config.js +219 -253
- package/demo/custom.js +88 -133
- package/demo/front.js +7 -10
- package/demo/index.html +19 -22
- package/demo/input.js +6 -11
- package/demo/input_container.js +8 -9
- package/demo/main.js +62 -126
- package/demo/search.js +29 -34
- package/demo/service_worker.js +0 -3
- package/demo/tooltip.js +3 -5
- package/demo/visualizer.js +3 -5
- package/demo/visualizer_button.js +1 -20
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +211 -228
- package/dist/demo.compiled.debug.map +4 -4
- package/dist/demo.compiled.js +211 -228
- package/dist/demo.compiled.map +4 -4
- package/dist/deps.js +42 -37
- package/dist/locales.js +34 -30
- package/dist/receiver.compiled.debug.js +64 -77
- package/dist/receiver.compiled.debug.map +4 -4
- package/dist/receiver.compiled.js +64 -77
- package/dist/receiver.compiled.map +4 -4
- package/dist/shaka-player.compiled.d.ts +343 -151
- package/dist/shaka-player.compiled.debug.d.ts +343 -151
- package/dist/shaka-player.compiled.debug.externs.js +356 -117
- package/dist/shaka-player.compiled.debug.js +952 -811
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +356 -117
- package/dist/shaka-player.compiled.js +1165 -1078
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +359 -153
- package/dist/shaka-player.ui.debug.d.ts +359 -153
- package/dist/shaka-player.ui.debug.externs.js +382 -117
- package/dist/shaka-player.ui.debug.js +1084 -918
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +382 -117
- package/dist/shaka-player.ui.js +1377 -1274
- package/dist/shaka-player.ui.map +4 -4
- package/docs/design/lcevc-integration.md +14 -14
- package/docs/tutorials/ad_monetization.md +54 -0
- package/docs/tutorials/basic-usage.md +2 -1
- package/docs/tutorials/errors.md +2 -1
- package/docs/tutorials/faq.md +27 -55
- package/docs/tutorials/index.json +2 -1
- package/docs/tutorials/lcevc.md +118 -0
- package/docs/tutorials/offline.md +10 -8
- package/docs/tutorials/plugins.md +5 -0
- package/docs/tutorials/ui-customization.md +17 -0
- package/docs/tutorials/ui.md +2 -1
- package/docs/tutorials/upgrade.md +3 -0
- package/externs/css_style_declaration.js +19 -0
- package/externs/lcevc.js +37 -13
- package/externs/managedmediasource.js +24 -0
- package/externs/media_remote.js +68 -0
- package/externs/mediatailor.js +193 -0
- package/externs/pictureinpicture.js +11 -0
- package/externs/shaka/abr_manager.js +6 -2
- package/externs/shaka/ads.js +27 -0
- package/externs/shaka/cea.js +7 -0
- package/externs/shaka/codecs.js +5 -3
- package/externs/shaka/manifest.js +31 -10
- package/externs/shaka/manifest_parser.js +24 -1
- package/externs/shaka/net.js +2 -2
- package/externs/shaka/offline.js +13 -2
- package/externs/shaka/player.js +65 -8
- package/externs/shaka/text.js +3 -1
- package/externs/shaka/transmuxer.js +1 -1
- package/karma.conf.js +7 -3
- package/lib/abr/simple_abr_manager.js +66 -9
- package/lib/ads/ad_manager.js +104 -50
- package/lib/ads/media_tailor_ad.js +297 -0
- package/lib/ads/media_tailor_ad_manager.js +839 -0
- package/lib/cast/cast_receiver.js +1 -1
- package/lib/cea/cea_decoder.js +28 -0
- package/lib/cea/dummy_caption_decoder.js +5 -0
- package/lib/cea/ts_cea_parser.js +15 -2
- package/lib/config/codec_switching_strategy.js +24 -0
- package/lib/dash/content_protection.js +120 -2
- package/lib/dash/dash_parser.js +322 -93
- package/lib/dash/mpd_utils.js +62 -37
- package/lib/dash/segment_base.js +17 -10
- package/lib/dash/segment_list.js +18 -9
- package/lib/dash/segment_template.js +122 -107
- package/lib/dependencies/all.js +8 -7
- package/lib/hls/hls_classes.js +28 -43
- package/lib/hls/hls_parser.js +798 -658
- package/lib/hls/hls_utils.js +64 -5
- package/lib/hls/manifest_text_parser.js +7 -11
- package/lib/lcevc/lcevc_dec.js +220 -0
- package/lib/media/adaptation_set.js +32 -14
- package/lib/media/adaptation_set_criteria.js +86 -16
- package/lib/media/closed_caption_parser.js +13 -0
- package/lib/media/content_workarounds.js +6 -0
- package/lib/media/drm_engine.js +8 -13
- package/lib/media/manifest_parser.js +8 -113
- package/lib/media/media_source_capabilities.js +10 -3
- package/lib/media/media_source_engine.js +286 -44
- package/lib/media/play_rate_controller.js +8 -38
- package/lib/media/presentation_timeline.js +7 -1
- package/lib/media/quality_observer.js +1 -1
- package/lib/media/segment_index.js +6 -6
- package/lib/media/segment_prefetch.js +92 -24
- package/lib/media/segment_reference.js +73 -7
- package/lib/media/segment_utils.js +343 -0
- package/lib/media/stall_detector.js +0 -3
- package/lib/media/streaming_engine.js +73 -38
- package/lib/mss/mss_parser.js +19 -2
- package/lib/net/networking_engine.js +67 -12
- package/lib/net/networking_utils.js +95 -0
- package/lib/offline/indexeddb/v1_storage_cell.js +3 -0
- package/lib/offline/indexeddb/v2_storage_cell.js +3 -0
- package/lib/offline/manifest_converter.js +3 -0
- package/lib/offline/offline_manifest_parser.js +10 -0
- package/lib/offline/storage.js +14 -7
- package/lib/player.js +1098 -1537
- package/lib/polyfill/mediasource.js +22 -1
- package/lib/text/cue.js +15 -0
- package/lib/text/mp4_ttml_parser.js +2 -2
- package/lib/text/srt_text_parser.js +2 -2
- package/lib/text/stub_text_displayer.js +51 -0
- package/lib/text/text_engine.js +3 -2
- package/lib/text/ttml_text_parser.js +45 -5
- package/lib/text/ui_text_displayer.js +8 -0
- package/lib/text/vtt_text_parser.js +40 -22
- package/lib/transmuxer/aac_transmuxer.js +1 -1
- package/lib/transmuxer/ac3_transmuxer.js +1 -1
- package/lib/transmuxer/ec3_transmuxer.js +1 -1
- package/lib/transmuxer/h264.js +5 -4
- package/lib/transmuxer/h265.js +863 -0
- package/lib/transmuxer/mp3_transmuxer.js +1 -1
- package/lib/transmuxer/mpeg_ts_transmuxer.js +4 -3
- package/lib/transmuxer/mss_transmuxer.js +1 -1
- package/lib/transmuxer/ts_transmuxer.js +187 -22
- package/lib/util/buffer_utils.js +26 -4
- package/lib/util/content_steering_manager.js +358 -0
- package/lib/util/error.js +30 -15
- package/lib/util/exp_golomb.js +30 -2
- package/lib/util/fairplay_utils.js +1 -1
- package/lib/util/fake_event.js +8 -1
- package/lib/util/id3_utils.js +50 -1
- package/lib/util/manifest_parser_utils.js +12 -8
- package/lib/util/mp4_generator.js +6 -8
- package/lib/util/mutex.js +59 -0
- package/lib/util/object_utils.js +1 -1
- package/lib/util/periods.js +156 -179
- package/lib/util/platform.js +44 -3
- package/lib/util/player_configuration.js +43 -6
- package/lib/util/state_history.js +6 -2
- package/lib/util/stream_utils.js +206 -283
- package/lib/util/ts_parser.js +335 -98
- package/lib/util/uint8array_utils.js +5 -1
- package/lib/util/xml_utils.js +5 -0
- package/maintained-branches.md +3 -2
- package/package.json +4 -6
- package/roadmap.md +25 -5
- package/shaka-player.uncompiled.js +2 -2
- package/support.html +0 -1
- package/test/abr/simple_abr_manager_unit.js +33 -33
- package/test/ads/ad_manager_unit.js +3 -2
- package/test/cast/cast_receiver_integration.js +50 -4
- package/test/cast/cast_utils_unit.js +2 -0
- package/test/cea/cea_decoder_unit.js +7 -0
- package/test/codec_switching/codec_switching_integration.js +182 -0
- package/test/dash/dash_parser_content_protection_unit.js +2 -0
- package/test/dash/dash_parser_integration.js +74 -0
- package/test/dash/dash_parser_live_unit.js +2 -19
- package/test/dash/dash_parser_manifest_unit.js +536 -2
- package/test/dash/dash_parser_segment_base_unit.js +2 -0
- package/test/dash/dash_parser_segment_list_unit.js +2 -0
- package/test/dash/dash_parser_segment_template_unit.js +2 -0
- package/test/dash/mpd_utils_unit.js +61 -30
- package/test/demo/demo_unit.js +0 -16
- package/test/hls/hls_live_unit.js +14 -3
- package/test/hls/hls_parser_unit.js +385 -33
- package/test/hls/manifest_text_parser_unit.js +32 -99
- package/test/media/adaptation_set_criteria_unit.js +284 -15
- package/test/media/adaptation_set_unit.js +2 -0
- package/test/media/content_workarounds_unit.js +1 -1
- package/test/media/drm_engine_unit.js +3 -3
- package/test/media/media_source_engine_unit.js +166 -2
- package/test/media/play_rate_controller_unit.js +0 -48
- package/test/media/segment_index_unit.js +5 -4
- package/test/media/segment_prefetch_unit.js +1 -1
- package/test/media/streaming_engine_unit.js +17 -17
- package/test/mss/mss_parser_unit.js +2 -0
- package/test/mss/mss_player_integration.js +3 -2
- package/test/net/networking_engine_unit.js +3 -3
- package/test/{media/manifest_parser_unit.js → net/networking_utils_unit.js} +2 -2
- package/test/offline/manifest_convert_unit.js +14 -0
- package/test/offline/offline_integration.js +2 -1
- package/test/offline/storage_integration.js +22 -13
- package/test/player_external.js +4 -2
- package/test/player_integration.js +15 -4
- package/test/player_load_graph_integration.js +47 -151
- package/test/player_src_equals_external.js +1 -0
- package/test/player_src_equals_integration.js +71 -4
- package/test/player_unit.js +182 -158
- package/test/test/assets/dash-aes-128/Fragments(video=0,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=20000000,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=40000000,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=60000000,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=i,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/dash.mpd +18 -0
- package/test/test/assets/dash-aes-128/license +1 -0
- package/test/test/assets/dash-multi-codec/audio_en_2c_128k_aac.mp4 +0 -0
- package/test/test/assets/dash-multi-codec/audio_es_2c_64k_opus.webm +0 -0
- package/test/test/assets/dash-multi-codec/dash.mpd +32 -0
- package/test/test/assets/dash-multi-codec/video_144p_108k_h264.mp4 +0 -0
- package/test/test/assets/hls-ts-h265/0.ts +0 -0
- package/test/test/assets/hls-ts-h265/hevc.m3u8 +6 -0
- package/test/test/assets/hls-ts-h265/index.m3u8 +7 -0
- package/test/test/assets/hls-ts-muxed-aac-h265/0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h265/1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h265/media.m3u8 +9 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/media.m3u8 +24 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00000.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00001.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00002.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00003.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00004.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00005.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0000.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0001.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0002.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0003.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/prog_index.m3u8 +14 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/index.m3u8 +23 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-1-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-2-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-3-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-4-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-5-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-6-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-7-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-8-v1-a1.ts +0 -0
- package/test/test/util/dash_parser_util.js +4 -0
- package/test/test/util/fake_ad_manager.js +20 -0
- package/test/test/util/fake_media_source_engine.js +13 -2
- package/test/test/util/fake_networking_engine.js +9 -1
- package/test/test/util/fake_segment_prefetch.js +3 -0
- package/test/test/util/manifest_generator.js +11 -3
- package/test/test/util/manifest_parser_util.js +14 -2
- package/test/test/util/mss_parser_util.js +4 -0
- package/test/test/util/offline_utils.js +2 -0
- package/test/test/util/simple_fakes.js +2 -2
- package/test/test/util/streaming_engine_util.js +10 -4
- package/test/test/util/test_scheme.js +6 -0
- package/test/test/util/ui_utils.js +4 -3
- package/test/text/mp4_ttml_parser_unit.js +4 -4
- package/test/text/srt_text_parser_unit.js +1 -1
- package/test/text/text_displayer_layout_unit.js +1 -1
- package/test/text/text_engine_unit.js +6 -0
- package/test/text/ttml_text_parser_unit.js +85 -2
- package/test/text/vtt_text_parser_unit.js +103 -31
- package/test/transmuxer/transmuxer_engine_integration.js +9 -0
- package/test/transmuxer/transmuxer_integration.js +150 -3
- package/test/ui/ad_ui_unit.js +2 -2
- package/test/ui/ui_customization_unit.js +17 -16
- package/test/ui/ui_integration.js +30 -20
- package/test/ui/ui_unit.js +28 -29
- package/test/util/buffer_utils_unit.js +1 -1
- package/test/util/content_steering_manager_unit.js +427 -0
- package/test/util/id3_utils_unit.js +52 -0
- package/test/util/stream_utils_unit.js +207 -169
- package/test/util/ts_parser_unit.js +3 -3
- package/third_party/closure-uri/uri.js +13 -1
- package/ui/audio_language_selection.js +9 -2
- package/ui/controls.js +125 -0
- package/ui/externs/ui.js +24 -2
- package/ui/language_utils.js +43 -8
- package/ui/less/range_elements.less +33 -0
- package/ui/locales/en.json +1 -0
- package/ui/locales/es-419.json +1 -0
- package/ui/locales/es.json +1 -0
- package/ui/locales/source.json +4 -0
- package/ui/localization.js +10 -0
- package/ui/pip_button.js +22 -120
- package/ui/remote_button.js +203 -0
- package/ui/resolution_selection.js +47 -10
- package/ui/seek_bar.js +296 -3
- package/ui/text_selection.js +2 -1
- package/ui/ui.js +11 -4
- package/demo/common/message_ids.js +0 -309
- package/demo/locales/en.json +0 -288
- package/demo/locales/source.json +0 -1146
- package/externs/mux.js +0 -69
- package/lib/lcevc/lcevc_dil.js +0 -152
- package/lib/routing/node.js +0 -23
- package/lib/routing/payload.js +0 -43
- package/lib/routing/walker.js +0 -587
- package/lib/transmuxer/muxjs_transmuxer.js +0 -242
- package/test/routing/walker_unit.js +0 -504
- package/test/transmuxer/muxjs_transmuxer_integration.js +0 -177
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/*! @license
|
|
2
|
+
* Shaka Player
|
|
3
|
+
* Copyright 2016 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
goog.provide('shaka.util.Mutex');
|
|
8
|
+
|
|
9
|
+
goog.require('shaka.log');
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @summary A simple mutex.
|
|
14
|
+
*/
|
|
15
|
+
shaka.util.Mutex = class {
|
|
16
|
+
/** Constructs the mutex. */
|
|
17
|
+
constructor() {
|
|
18
|
+
/** @private {?string} */
|
|
19
|
+
this.acquiredIdentifier = null;
|
|
20
|
+
|
|
21
|
+
/** @private {!Array.<function()>} */
|
|
22
|
+
this.unlockQueue = [];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Acquires the mutex, as soon as possible.
|
|
27
|
+
* @param {string} identifier
|
|
28
|
+
* @return {!Promise}
|
|
29
|
+
*/
|
|
30
|
+
async acquire(identifier) {
|
|
31
|
+
shaka.log.v2(identifier + ' has requested mutex');
|
|
32
|
+
if (this.acquiredIdentifier) {
|
|
33
|
+
await new Promise((resolve) => this.unlockQueue.push(resolve));
|
|
34
|
+
}
|
|
35
|
+
this.acquiredIdentifier = identifier;
|
|
36
|
+
shaka.log.v2(identifier + ' has acquired mutex');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Releases your hold on the mutex.
|
|
41
|
+
*/
|
|
42
|
+
release() {
|
|
43
|
+
shaka.log.v2(this.acquiredIdentifier + ' has released mutex');
|
|
44
|
+
if (this.unlockQueue.length > 0) {
|
|
45
|
+
this.unlockQueue.shift()();
|
|
46
|
+
} else {
|
|
47
|
+
this.acquiredIdentifier = null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Completely releases the mutex. Meant for use by the tests.
|
|
53
|
+
*/
|
|
54
|
+
releaseAll() {
|
|
55
|
+
while (this.acquiredIdentifier) {
|
|
56
|
+
this.release();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
package/lib/util/object_utils.js
CHANGED
|
@@ -19,7 +19,7 @@ shaka.util.ObjectUtils = class {
|
|
|
19
19
|
* @return {T}
|
|
20
20
|
*/
|
|
21
21
|
static cloneObject(arg) {
|
|
22
|
-
const seenObjects = new
|
|
22
|
+
const seenObjects = new WeakSet();
|
|
23
23
|
// This recursively clones the value |val|, using the captured variable
|
|
24
24
|
// |seenObjects| to track the objects we have already cloned.
|
|
25
25
|
/** @suppress {strictMissingProperties} */
|
package/lib/util/periods.js
CHANGED
|
@@ -103,6 +103,37 @@ shaka.util.PeriodCombiner = class {
|
|
|
103
103
|
return this.imageStreams_;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Returns an object that contains arrays of streams by type
|
|
108
|
+
* @param {!Array.<shaka.extern.Period>} periods
|
|
109
|
+
* @return {{
|
|
110
|
+
* audioStreamsPerPeriod: !Array.<!Array.<shaka.extern.Stream>>,
|
|
111
|
+
* videoStreamsPerPeriod: !Array.<!Array.<shaka.extern.Stream>>,
|
|
112
|
+
* textStreamsPerPeriod: !Array.<!Array.<shaka.extern.Stream>>,
|
|
113
|
+
* imageStreamsPerPeriod: !Array.<!Array.<shaka.extern.Stream>>
|
|
114
|
+
* }}
|
|
115
|
+
* @private
|
|
116
|
+
*/
|
|
117
|
+
getStreamsPerPeriod_(periods) {
|
|
118
|
+
const audioStreamsPerPeriod = [];
|
|
119
|
+
const videoStreamsPerPeriod = [];
|
|
120
|
+
const textStreamsPerPeriod = [];
|
|
121
|
+
const imageStreamsPerPeriod = [];
|
|
122
|
+
|
|
123
|
+
for (const period of periods) {
|
|
124
|
+
audioStreamsPerPeriod.push(period.audioStreams);
|
|
125
|
+
videoStreamsPerPeriod.push(period.videoStreams);
|
|
126
|
+
textStreamsPerPeriod.push(period.textStreams);
|
|
127
|
+
imageStreamsPerPeriod.push(period.imageStreams);
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
audioStreamsPerPeriod,
|
|
131
|
+
videoStreamsPerPeriod,
|
|
132
|
+
textStreamsPerPeriod,
|
|
133
|
+
imageStreamsPerPeriod,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
106
137
|
/**
|
|
107
138
|
* @param {!Array.<shaka.extern.Period>} periods
|
|
108
139
|
* @param {boolean} isDynamic
|
|
@@ -113,10 +144,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
113
144
|
async combinePeriods(periods, isDynamic) {
|
|
114
145
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
115
146
|
|
|
116
|
-
shaka.util.PeriodCombiner.
|
|
117
|
-
shaka.util.PeriodCombiner.filterOutVideoStreamDuplicates_(periods);
|
|
118
|
-
shaka.util.PeriodCombiner.filterOutTextStreamDuplicates_(periods);
|
|
119
|
-
shaka.util.PeriodCombiner.filterOutImageStreamDuplicates_(periods);
|
|
147
|
+
shaka.util.PeriodCombiner.filterOutDuplicates_(periods);
|
|
120
148
|
|
|
121
149
|
// Optimization: for single-period VOD, do nothing. This makes sure
|
|
122
150
|
// single-period DASH content will be 100% accurately represented in the
|
|
@@ -151,14 +179,12 @@ shaka.util.PeriodCombiner = class {
|
|
|
151
179
|
return;
|
|
152
180
|
}
|
|
153
181
|
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
const imageStreamsPerPeriod = periods.map(
|
|
161
|
-
(period) => period.imageStreams);
|
|
182
|
+
const {
|
|
183
|
+
audioStreamsPerPeriod,
|
|
184
|
+
videoStreamsPerPeriod,
|
|
185
|
+
textStreamsPerPeriod,
|
|
186
|
+
imageStreamsPerPeriod,
|
|
187
|
+
} = this.getStreamsPerPeriod_(periods);
|
|
162
188
|
|
|
163
189
|
// It's okay to have a period with no text or images, but our algorithm
|
|
164
190
|
// fails on any period without matching streams. So we add dummy streams
|
|
@@ -174,33 +200,32 @@ shaka.util.PeriodCombiner = class {
|
|
|
174
200
|
ContentType.IMAGE));
|
|
175
201
|
}
|
|
176
202
|
|
|
177
|
-
await
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
shaka.util.PeriodCombiner.concatenateStreams_);
|
|
203
|
+
await Promise.all([
|
|
204
|
+
shaka.util.PeriodCombiner.combine_(
|
|
205
|
+
this.audioStreams_,
|
|
206
|
+
audioStreamsPerPeriod,
|
|
207
|
+
firstNewPeriodIndex,
|
|
208
|
+
shaka.util.PeriodCombiner.cloneStream_,
|
|
209
|
+
shaka.util.PeriodCombiner.concatenateStreams_),
|
|
210
|
+
shaka.util.PeriodCombiner.combine_(
|
|
211
|
+
this.videoStreams_,
|
|
212
|
+
videoStreamsPerPeriod,
|
|
213
|
+
firstNewPeriodIndex,
|
|
214
|
+
shaka.util.PeriodCombiner.cloneStream_,
|
|
215
|
+
shaka.util.PeriodCombiner.concatenateStreams_),
|
|
216
|
+
shaka.util.PeriodCombiner.combine_(
|
|
217
|
+
this.textStreams_,
|
|
218
|
+
textStreamsPerPeriod,
|
|
219
|
+
firstNewPeriodIndex,
|
|
220
|
+
shaka.util.PeriodCombiner.cloneStream_,
|
|
221
|
+
shaka.util.PeriodCombiner.concatenateStreams_),
|
|
222
|
+
shaka.util.PeriodCombiner.combine_(
|
|
223
|
+
this.imageStreams_,
|
|
224
|
+
imageStreamsPerPeriod,
|
|
225
|
+
firstNewPeriodIndex,
|
|
226
|
+
shaka.util.PeriodCombiner.cloneStream_,
|
|
227
|
+
shaka.util.PeriodCombiner.concatenateStreams_),
|
|
228
|
+
]);
|
|
204
229
|
}
|
|
205
230
|
|
|
206
231
|
// Create variants for all audio/video combinations.
|
|
@@ -209,7 +234,8 @@ shaka.util.PeriodCombiner = class {
|
|
|
209
234
|
if (!this.videoStreams_.length || !this.audioStreams_.length) {
|
|
210
235
|
// For audio-only or video-only content, just give each stream its own
|
|
211
236
|
// variant.
|
|
212
|
-
const streams = this.videoStreams_.
|
|
237
|
+
const streams = this.videoStreams_.length ? this.videoStreams_ :
|
|
238
|
+
this.audioStreams_;
|
|
213
239
|
for (const stream of streams) {
|
|
214
240
|
const id = nextVariantId++;
|
|
215
241
|
variants.push({
|
|
@@ -262,141 +288,90 @@ shaka.util.PeriodCombiner = class {
|
|
|
262
288
|
}
|
|
263
289
|
|
|
264
290
|
/**
|
|
265
|
-
* @param {!Array
|
|
291
|
+
* @param {!Array<shaka.extern.Period>} periods
|
|
266
292
|
* @private
|
|
267
293
|
*/
|
|
268
|
-
static
|
|
269
|
-
const
|
|
270
|
-
// Two audio streams are considered to be duplicates of
|
|
271
|
-
// one another if their ids are different, but all the other
|
|
272
|
-
// information is the same.
|
|
273
|
-
for (const period of periods) {
|
|
274
|
-
const filteredAudios = [];
|
|
275
|
-
for (const a1 of period.audioStreams) {
|
|
276
|
-
let duplicate = false;
|
|
277
|
-
for (const a2 of filteredAudios) {
|
|
278
|
-
if (a1.id != a2.id &&
|
|
279
|
-
a1.channelsCount == a2.channelsCount &&
|
|
280
|
-
a1.language == a2.language &&
|
|
281
|
-
a1.bandwidth == a2.bandwidth &&
|
|
282
|
-
a1.label == a2.label &&
|
|
283
|
-
a1.codecs == a2.codecs &&
|
|
284
|
-
a1.mimeType == a2.mimeType &&
|
|
285
|
-
ArrayUtils.hasSameElements(a1.roles, a2.roles) &&
|
|
286
|
-
a1.audioSamplingRate == a2.audioSamplingRate &&
|
|
287
|
-
a1.primary == a2.primary) {
|
|
288
|
-
duplicate = true;
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
if (!duplicate) {
|
|
293
|
-
filteredAudios.push(a1);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
period.audioStreams = filteredAudios;
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* @param {!Array.<shaka.extern.Period>} periods
|
|
303
|
-
* @private
|
|
304
|
-
*/
|
|
305
|
-
static filterOutTextStreamDuplicates_(periods) {
|
|
306
|
-
const ArrayUtils = shaka.util.ArrayUtils;
|
|
307
|
-
// Two text streams are considered to be duplicates of
|
|
308
|
-
// one another if their ids are different, but all the other
|
|
309
|
-
// information is the same.
|
|
310
|
-
for (const period of periods) {
|
|
311
|
-
const filteredTexts = [];
|
|
312
|
-
for (const t1 of period.textStreams) {
|
|
313
|
-
let duplicate = false;
|
|
314
|
-
for (const t2 of filteredTexts) {
|
|
315
|
-
if (t1.id != t2.id &&
|
|
316
|
-
t1.language == t2.language &&
|
|
317
|
-
t1.label == t2.label &&
|
|
318
|
-
t1.codecs == t2.codecs &&
|
|
319
|
-
t1.mimeType == t2.mimeType &&
|
|
320
|
-
t1.bandwidth == t2.bandwidth &&
|
|
321
|
-
ArrayUtils.hasSameElements(t1.roles, t2.roles)) {
|
|
322
|
-
duplicate = true;
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
if (!duplicate) {
|
|
327
|
-
filteredTexts.push(t1);
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
period.textStreams = filteredTexts;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/**
|
|
336
|
-
* @param {!Array.<shaka.extern.Period>} periods
|
|
337
|
-
* @private
|
|
338
|
-
*/
|
|
339
|
-
static filterOutVideoStreamDuplicates_(periods) {
|
|
294
|
+
static filterOutDuplicates_(periods) {
|
|
295
|
+
const PeriodCombiner = shaka.util.PeriodCombiner;
|
|
340
296
|
const ArrayUtils = shaka.util.ArrayUtils;
|
|
341
297
|
const MapUtils = shaka.util.MapUtils;
|
|
342
|
-
|
|
343
|
-
// one another if their ids are different, but all the other
|
|
344
|
-
// information is the same.
|
|
298
|
+
|
|
345
299
|
for (const period of periods) {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
v1.
|
|
353
|
-
v1.
|
|
354
|
-
v1.
|
|
355
|
-
v1.
|
|
300
|
+
// Two video streams are considered to be duplicates of
|
|
301
|
+
// one another if their ids are different, but all the other
|
|
302
|
+
// information is the same.
|
|
303
|
+
period.videoStreams = PeriodCombiner.filterOutStreamDuplicates_(
|
|
304
|
+
period.videoStreams, (v1, v2) => {
|
|
305
|
+
return v1.id !== v2.id &&
|
|
306
|
+
v1.fastSwitching == v2.fastSwitching &&
|
|
307
|
+
v1.width === v2.width &&
|
|
308
|
+
v1.frameRate === v2.frameRate &&
|
|
309
|
+
v1.codecs === v2.codecs &&
|
|
310
|
+
v1.mimeType === v2.mimeType &&
|
|
311
|
+
v1.label === v2.label &&
|
|
356
312
|
ArrayUtils.hasSameElements(v1.roles, v2.roles) &&
|
|
357
313
|
MapUtils.hasSameElements(v1.closedCaptions, v2.closedCaptions) &&
|
|
358
|
-
v1.bandwidth
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
314
|
+
v1.bandwidth === v2.bandwidth;
|
|
315
|
+
});
|
|
316
|
+
// Two audio streams are considered to be duplicates of
|
|
317
|
+
// one another if their ids are different, but all the other
|
|
318
|
+
// information is the same.
|
|
319
|
+
period.audioStreams = PeriodCombiner.filterOutStreamDuplicates_(
|
|
320
|
+
period.audioStreams, (a1, a2) => {
|
|
321
|
+
return a1.id !== a2.id &&
|
|
322
|
+
a1.fastSwitching == a2.fastSwitching &&
|
|
323
|
+
a1.channelsCount === a2.channelsCount &&
|
|
324
|
+
a1.language === a2.language &&
|
|
325
|
+
a1.bandwidth === a2.bandwidth &&
|
|
326
|
+
a1.label === a2.label &&
|
|
327
|
+
a1.codecs === a2.codecs &&
|
|
328
|
+
a1.mimeType === a2.mimeType &&
|
|
329
|
+
ArrayUtils.hasSameElements(a1.roles, a2.roles) &&
|
|
330
|
+
a1.audioSamplingRate === a2.audioSamplingRate &&
|
|
331
|
+
a1.primary === a2.primary;
|
|
332
|
+
});
|
|
333
|
+
// Two text streams are considered to be duplicates of
|
|
334
|
+
// one another if their ids are different, but all the other
|
|
335
|
+
// information is the same.
|
|
336
|
+
period.textStreams = PeriodCombiner.filterOutStreamDuplicates_(
|
|
337
|
+
period.textStreams, (t1, t2) => {
|
|
338
|
+
return t1.id !== t2.id &&
|
|
339
|
+
t1.language === t2.language &&
|
|
340
|
+
t1.label === t2.label &&
|
|
341
|
+
t1.codecs === t2.codecs &&
|
|
342
|
+
t1.mimeType === t2.mimeType &&
|
|
343
|
+
t1.bandwidth === t2.bandwidth &&
|
|
344
|
+
ArrayUtils.hasSameElements(t1.roles, t2.roles);
|
|
345
|
+
});
|
|
346
|
+
// Two image streams are considered to be duplicates of
|
|
347
|
+
// one another if their ids are different, but all the other
|
|
348
|
+
// information is the same.
|
|
349
|
+
period.imageStreams = PeriodCombiner.filterOutStreamDuplicates_(
|
|
350
|
+
period.imageStreams, (i1, i2) => {
|
|
351
|
+
return i1.id !== i2.id &&
|
|
352
|
+
i1.width === i2.width &&
|
|
353
|
+
i1.codecs === i2.codecs &&
|
|
354
|
+
i1.mimeType === i2.mimeType;
|
|
355
|
+
});
|
|
369
356
|
}
|
|
370
357
|
}
|
|
371
358
|
|
|
372
359
|
/**
|
|
373
|
-
* @param {!Array
|
|
360
|
+
* @param {!Array<shaka.extern.Stream>} streams
|
|
361
|
+
* @param {function(
|
|
362
|
+
* shaka.extern.Stream, shaka.extern.Stream): boolean} isDuplicate
|
|
363
|
+
* @return {!Array<shaka.extern.Stream>}
|
|
374
364
|
* @private
|
|
375
365
|
*/
|
|
376
|
-
static
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
for (const i1 of period.imageStreams) {
|
|
383
|
-
let duplicate = false;
|
|
384
|
-
for (const i2 of filteredImages) {
|
|
385
|
-
if (i1.id != i2.id &&
|
|
386
|
-
i1.width == i2.width &&
|
|
387
|
-
i1.codecs == i2.codecs &&
|
|
388
|
-
i1.mimeType == i2.mimeType) {
|
|
389
|
-
duplicate = true;
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
if (!duplicate) {
|
|
394
|
-
filteredImages.push(i1);
|
|
395
|
-
}
|
|
366
|
+
static filterOutStreamDuplicates_(streams, isDuplicate) {
|
|
367
|
+
const filteredStreams = [];
|
|
368
|
+
for (const s1 of streams) {
|
|
369
|
+
const duplicate = filteredStreams.some((s2) => isDuplicate(s1, s2));
|
|
370
|
+
if (!duplicate) {
|
|
371
|
+
filteredStreams.push(s1);
|
|
396
372
|
}
|
|
397
|
-
|
|
398
|
-
period.imageStreams = filteredImages;
|
|
399
373
|
}
|
|
374
|
+
return filteredStreams;
|
|
400
375
|
}
|
|
401
376
|
|
|
402
377
|
/**
|
|
@@ -784,27 +759,25 @@ shaka.util.PeriodCombiner = class {
|
|
|
784
759
|
|
|
785
760
|
// Concatenate the new matches onto the stream, starting at the first new
|
|
786
761
|
// period.
|
|
787
|
-
for (let i =
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
used = false;
|
|
802
|
-
}
|
|
762
|
+
for (let i = firstNewPeriodIndex; i < matches.length; i++) {
|
|
763
|
+
const match = matches[i];
|
|
764
|
+
concat(outputStream, match);
|
|
765
|
+
|
|
766
|
+
// We only consider an audio stream "used" if its language is related to
|
|
767
|
+
// the output language. There are scenarios where we want to generate
|
|
768
|
+
// separate tracks for each language, even when we are forced to connect
|
|
769
|
+
// unrelated languages across periods.
|
|
770
|
+
let used = true;
|
|
771
|
+
if (outputStream.type == ContentType.AUDIO) {
|
|
772
|
+
const relatedness = LanguageUtils.relatedness(
|
|
773
|
+
outputStream.language, match.language);
|
|
774
|
+
if (relatedness == 0) {
|
|
775
|
+
used = false;
|
|
803
776
|
}
|
|
777
|
+
}
|
|
804
778
|
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
}
|
|
779
|
+
if (used) {
|
|
780
|
+
unusedStreamsPerPeriod[i].delete(match);
|
|
808
781
|
}
|
|
809
782
|
}
|
|
810
783
|
}
|
|
@@ -1495,6 +1468,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
1495
1468
|
return {
|
|
1496
1469
|
id: 0,
|
|
1497
1470
|
originalId: '',
|
|
1471
|
+
groupId: null,
|
|
1498
1472
|
primary: false,
|
|
1499
1473
|
type,
|
|
1500
1474
|
mimeType: '',
|
|
@@ -1515,6 +1489,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
1515
1489
|
spatialAudio: false,
|
|
1516
1490
|
closedCaptions: null,
|
|
1517
1491
|
external: false,
|
|
1492
|
+
fastSwitching: false,
|
|
1518
1493
|
};
|
|
1519
1494
|
}
|
|
1520
1495
|
|
|
@@ -1532,6 +1507,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
1532
1507
|
return {
|
|
1533
1508
|
id: 0,
|
|
1534
1509
|
originalId: '',
|
|
1510
|
+
groupId: null,
|
|
1535
1511
|
createSegmentIndex: () => Promise.resolve(),
|
|
1536
1512
|
segmentIndex: new shaka.media.SegmentIndex([]),
|
|
1537
1513
|
mimeType: '',
|
|
@@ -1554,6 +1530,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
1554
1530
|
closedCaptions: null,
|
|
1555
1531
|
accessibilityPurpose: null,
|
|
1556
1532
|
external: false,
|
|
1533
|
+
fastSwitching: false,
|
|
1557
1534
|
};
|
|
1558
1535
|
}
|
|
1559
1536
|
|
package/lib/util/platform.js
CHANGED
|
@@ -23,15 +23,16 @@ shaka.util.Platform = class {
|
|
|
23
23
|
* @return {boolean}
|
|
24
24
|
*/
|
|
25
25
|
static supportsMediaSource() {
|
|
26
|
+
const mediaSource = window.ManagedMediaSource || window.MediaSource;
|
|
26
27
|
// Browsers that lack a media source implementation will have no reference
|
|
27
28
|
// to |window.MediaSource|. Platforms that we see having problematic media
|
|
28
29
|
// source implementations will have this reference removed via a polyfill.
|
|
29
|
-
if (!
|
|
30
|
+
if (!mediaSource) {
|
|
30
31
|
return false;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
// Some very old MediaSource implementations didn't have isTypeSupported.
|
|
34
|
-
if (!
|
|
35
|
+
if (!mediaSource.isTypeSupported) {
|
|
35
36
|
return false;
|
|
36
37
|
}
|
|
37
38
|
|
|
@@ -154,6 +155,26 @@ shaka.util.Platform = class {
|
|
|
154
155
|
'Chrome/38.0.2125.122 Safari/537.36');
|
|
155
156
|
}
|
|
156
157
|
|
|
158
|
+
/**
|
|
159
|
+
* Check if the current platform is a WebOS 4.
|
|
160
|
+
*
|
|
161
|
+
* @return {boolean}
|
|
162
|
+
*/
|
|
163
|
+
static isWebOS4() {
|
|
164
|
+
// See: http://webostv.developer.lge.com/discover/specifications/web-engine/
|
|
165
|
+
return !!navigator.userAgent.match(/webOS\/4/i);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Check if the current platform is a WebOS 4.
|
|
170
|
+
*
|
|
171
|
+
* @return {boolean}
|
|
172
|
+
*/
|
|
173
|
+
static isWebOS5() {
|
|
174
|
+
// See: http://webostv.developer.lge.com/discover/specifications/web-engine/
|
|
175
|
+
return !!navigator.userAgent.match(/webOS\/5/i);
|
|
176
|
+
}
|
|
177
|
+
|
|
157
178
|
/**
|
|
158
179
|
* Check if the current platform is a Google Chromecast.
|
|
159
180
|
*
|
|
@@ -443,7 +464,7 @@ shaka.util.Platform = class {
|
|
|
443
464
|
*/
|
|
444
465
|
static requiresEncryptionInfoInAllInitSegments() {
|
|
445
466
|
const Platform = shaka.util.Platform;
|
|
446
|
-
return Platform.isTizen() || Platform.isXboxOne();
|
|
467
|
+
return Platform.isTizen() || Platform.isXboxOne() || Platform.isOrange();
|
|
447
468
|
}
|
|
448
469
|
|
|
449
470
|
/**
|
|
@@ -460,6 +481,26 @@ shaka.util.Platform = class {
|
|
|
460
481
|
return true;
|
|
461
482
|
}
|
|
462
483
|
|
|
484
|
+
/**
|
|
485
|
+
* Returns if codec switching SMOOTH is known reliable device support.
|
|
486
|
+
*
|
|
487
|
+
* Some devices are known not to support `MediaSource.changeType`
|
|
488
|
+
* well. These devices should use the reload strategy. If a device
|
|
489
|
+
* reports that it supports `changeType` but support it reliabley
|
|
490
|
+
* it should be added to this list.
|
|
491
|
+
*
|
|
492
|
+
* @return {boolean}
|
|
493
|
+
*/
|
|
494
|
+
static supportsSmoothCodecSwitching() {
|
|
495
|
+
const Platform = shaka.util.Platform;
|
|
496
|
+
if (Platform.isTizen2() || Platform.isTizen3() ||
|
|
497
|
+
Platform.isTizen4() || Platform.isWebOS3() ||
|
|
498
|
+
Platform.isWebOS4() || Platform.isWebOS5()) {
|
|
499
|
+
return false;
|
|
500
|
+
}
|
|
501
|
+
return true;
|
|
502
|
+
}
|
|
503
|
+
|
|
463
504
|
/**
|
|
464
505
|
* Returns true if MediaKeys is polyfilled
|
|
465
506
|
*
|