shaka-player 4.4.3 → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/release-please.yaml +2 -27
- package/CHANGELOG.md +64 -45
- package/README.md +16 -10
- 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 +22 -5
- package/demo/common/assets.js +132 -49
- package/demo/config.js +192 -253
- package/demo/custom.js +39 -98
- 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 +51 -123
- package/demo/search.js +22 -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/demo.compiled.debug.js +152 -178
- package/dist/demo.compiled.debug.map +4 -4
- package/dist/demo.compiled.js +152 -178
- package/dist/demo.compiled.map +4 -4
- package/dist/deps.js +27 -24
- package/dist/locales.js +31 -31
- package/dist/receiver.compiled.debug.js +22 -43
- package/dist/receiver.compiled.debug.map +4 -4
- package/dist/receiver.compiled.js +22 -43
- package/dist/receiver.compiled.map +4 -4
- package/dist/shaka-player.compiled.d.ts +507 -365
- package/dist/shaka-player.compiled.debug.d.ts +507 -365
- package/dist/shaka-player.compiled.debug.externs.js +205 -51
- package/dist/shaka-player.compiled.debug.js +541 -450
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +205 -51
- package/dist/shaka-player.compiled.js +1120 -1066
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +562 -410
- package/dist/shaka-player.ui.debug.d.ts +562 -410
- package/dist/shaka-player.ui.debug.externs.js +226 -51
- package/dist/shaka-player.ui.debug.js +606 -506
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +226 -51
- package/dist/shaka-player.ui.js +1266 -1207
- package/dist/shaka-player.ui.map +4 -4
- package/docs/design/lcevc-integration.md +14 -14
- package/docs/tutorials/faq.md +27 -55
- package/docs/tutorials/index.json +2 -1
- package/docs/tutorials/lcevc.md +118 -0
- package/docs/tutorials/ui-customization.md +4 -0
- package/externs/css_style_declaration.js +19 -0
- package/externs/lcevc.js +37 -13
- package/externs/media_remote.js +68 -0
- package/externs/mediatailor.js +193 -0
- package/externs/pictureinpicture.js +11 -0
- package/externs/shaka/ads.js +27 -0
- package/externs/shaka/manifest.js +10 -5
- package/externs/shaka/manifest_parser.js +7 -1
- package/externs/shaka/offline.js +4 -0
- package/externs/shaka/player.js +12 -1
- package/karma.conf.js +7 -3
- package/lib/abr/simple_abr_manager.js +43 -3
- 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 +828 -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 +75 -12
- package/lib/dash/mpd_utils.js +10 -6
- package/lib/dash/segment_base.js +13 -5
- package/lib/dash/segment_list.js +13 -5
- package/lib/dash/segment_template.js +43 -85
- package/lib/dependencies/all.js +8 -7
- package/lib/hls/hls_parser.js +44 -16
- package/lib/lcevc/lcevc_dec.js +220 -0
- package/lib/media/adaptation_set.js +22 -11
- package/lib/media/adaptation_set_criteria.js +25 -7
- package/lib/media/media_source_engine.js +215 -27
- package/lib/media/segment_index.js +1 -1
- package/lib/media/segment_reference.js +7 -7
- package/lib/media/streaming_engine.js +33 -18
- package/lib/mss/mss_parser.js +1 -0
- package/lib/net/networking_engine.js +1 -0
- 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 +1 -0
- package/lib/offline/storage.js +3 -0
- package/lib/player.js +142 -72
- package/lib/routing/payload.js +5 -1
- package/lib/text/cue.js +15 -0
- package/lib/text/ttml_text_parser.js +17 -0
- package/lib/text/ui_text_displayer.js +4 -0
- package/lib/text/vtt_text_parser.js +33 -20
- package/lib/transmuxer/h265.js +862 -0
- package/lib/transmuxer/mpeg_ts_transmuxer.js +3 -2
- package/lib/transmuxer/ts_transmuxer.js +160 -15
- package/lib/util/error.js +28 -9
- package/lib/util/exp_golomb.js +30 -2
- package/lib/util/fake_event.js +3 -0
- package/lib/util/mp4_generator.js +4 -4
- package/lib/util/periods.js +2 -0
- package/lib/util/platform.js +40 -0
- package/lib/util/player_configuration.js +8 -0
- package/lib/util/state_history.js +6 -2
- package/lib/util/stream_utils.js +133 -217
- package/lib/util/ts_parser.js +226 -40
- package/maintained-branches.md +3 -2
- package/package.json +4 -6
- package/roadmap.md +15 -5
- package/shaka-player.uncompiled.js +2 -1
- package/support.html +0 -1
- package/test/cast/cast_receiver_integration.js +47 -0
- package/test/codec_switching/codec_switching_integration.js +181 -0
- package/test/dash/dash_parser_content_protection_unit.js +2 -0
- package/test/dash/dash_parser_integration.js +73 -0
- package/test/dash/dash_parser_live_unit.js +2 -0
- package/test/dash/dash_parser_manifest_unit.js +42 -0
- 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/demo/demo_unit.js +0 -16
- package/test/hls/hls_live_unit.js +2 -0
- package/test/hls/hls_parser_unit.js +8 -6
- package/test/media/adaptation_set_criteria_unit.js +118 -0
- package/test/media/adaptation_set_unit.js +1 -0
- package/test/media/media_source_engine_unit.js +165 -1
- package/test/media/segment_index_unit.js +4 -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/offline/manifest_convert_unit.js +5 -0
- package/test/offline/storage_integration.js +1 -4
- package/test/player_unit.js +102 -131
- package/test/routing/walker_unit.js +1 -0
- 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 +8 -2
- package/test/test/util/manifest_generator.js +7 -3
- package/test/test/util/mss_parser_util.js +4 -0
- package/test/test/util/offline_utils.js +1 -0
- package/test/test/util/streaming_engine_util.js +7 -4
- package/test/text/ttml_text_parser_unit.js +52 -0
- package/test/text/vtt_text_parser_unit.js +103 -31
- package/test/transmuxer/transmuxer_integration.js +117 -0
- package/test/ui/ui_unit.js +3 -10
- package/test/util/stream_utils_unit.js +208 -74
- package/ui/controls.js +125 -0
- package/ui/externs/ui.js +8 -1
- package/ui/pip_button.js +22 -120
- package/ui/remote_button.js +201 -0
- package/ui/ui.js +5 -2
- 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/transmuxer/muxjs_transmuxer.js +0 -242
- package/test/transmuxer/muxjs_transmuxer_integration.js +0 -177
package/lib/util/stream_utils.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
goog.provide('shaka.util.StreamUtils');
|
|
8
8
|
|
|
9
9
|
goog.require('goog.asserts');
|
|
10
|
+
goog.require('shaka.config.CodecSwitchingStrategy');
|
|
10
11
|
goog.require('shaka.log');
|
|
11
12
|
goog.require('shaka.media.Capabilities');
|
|
12
13
|
goog.require('shaka.text.TextEngine');
|
|
@@ -38,103 +39,148 @@ shaka.util.StreamUtils = class {
|
|
|
38
39
|
preferredAudioCodecs, preferredAudioChannelCount,
|
|
39
40
|
preferredDecodingAttributes) {
|
|
40
41
|
const StreamUtils = shaka.util.StreamUtils;
|
|
42
|
+
const MimeUtils = shaka.util.MimeUtils;
|
|
41
43
|
|
|
42
44
|
let variants = manifest.variants;
|
|
43
|
-
|
|
44
45
|
// To start, choose the codecs based on configured preferences if available.
|
|
45
46
|
if (preferredVideoCodecs.length || preferredAudioCodecs.length) {
|
|
46
47
|
variants = StreamUtils.choosePreferredCodecs(variants,
|
|
47
48
|
preferredVideoCodecs, preferredAudioCodecs);
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
51
|
+
if (preferredDecodingAttributes.length) {
|
|
52
|
+
// group variants by resolution and choose preferred variants only
|
|
53
|
+
/** @type {!shaka.util.MultiMap.<shaka.extern.Variant>} */
|
|
54
|
+
const variantsByResolutionMap = new shaka.util.MultiMap();
|
|
55
|
+
for (const variant of variants) {
|
|
56
|
+
variantsByResolutionMap
|
|
57
|
+
.push(String(variant.video.width || 0), variant);
|
|
58
|
+
}
|
|
59
|
+
const bestVariants = [];
|
|
60
|
+
variantsByResolutionMap.forEach((width, variantsByResolution) => {
|
|
61
|
+
let highestMatch = 0;
|
|
62
|
+
let matchingVariants = [];
|
|
63
|
+
for (const variant of variantsByResolution) {
|
|
64
|
+
const matchCount = preferredDecodingAttributes.filter(
|
|
65
|
+
(attribute) => variant.decodingInfos[0][attribute],
|
|
66
|
+
).length;
|
|
67
|
+
if (matchCount > highestMatch) {
|
|
68
|
+
highestMatch = matchCount;
|
|
69
|
+
matchingVariants = [variant];
|
|
70
|
+
} else if (matchCount == highestMatch) {
|
|
71
|
+
matchingVariants.push(variant);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
bestVariants.push(...matchingVariants);
|
|
75
|
+
});
|
|
76
|
+
variants = bestVariants;
|
|
77
|
+
}
|
|
62
78
|
|
|
63
|
-
|
|
64
|
-
|
|
79
|
+
if (preferredAudioChannelCount) {
|
|
80
|
+
variants = StreamUtils.filterVariantsByAudioChannelCount(
|
|
81
|
+
variants, preferredAudioChannelCount);
|
|
82
|
+
}
|
|
65
83
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
84
|
+
const audioStreamsSet = new Set();
|
|
85
|
+
const videoStreamsSet = new Set();
|
|
86
|
+
for (const variant of variants) {
|
|
87
|
+
if (variant.audio) {
|
|
88
|
+
audioStreamsSet.add(variant.audio);
|
|
89
|
+
}
|
|
90
|
+
if (variant.video) {
|
|
91
|
+
videoStreamsSet.add(variant.video);
|
|
72
92
|
}
|
|
93
|
+
}
|
|
73
94
|
|
|
74
|
-
|
|
75
|
-
return
|
|
95
|
+
const audioStreams = Array.from(audioStreamsSet).sort((v1, v2) => {
|
|
96
|
+
return v1.bandwidth - v2.bandwidth;
|
|
76
97
|
});
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
98
|
+
const audioStreamsMap = new Map();
|
|
99
|
+
const getAudioId = (stream) => {
|
|
100
|
+
return stream.language + (stream.channelsCount || 0) +
|
|
101
|
+
stream.roles.join(',') + stream.label;
|
|
102
|
+
};
|
|
103
|
+
for (const stream of audioStreams) {
|
|
104
|
+
const id = getAudioId(stream);
|
|
105
|
+
if (!audioStreamsMap.has(id)) {
|
|
106
|
+
audioStreamsMap.set(id, stream);
|
|
107
|
+
} else {
|
|
108
|
+
const includedStream = audioStreamsMap.get(id);
|
|
109
|
+
if (includedStream.bandwidth > stream.bandwidth) {
|
|
110
|
+
audioStreamsMap.set(id, stream);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
91
113
|
}
|
|
114
|
+
const validAudioStreams = [...audioStreamsMap.values()];
|
|
92
115
|
|
|
93
|
-
|
|
94
|
-
|
|
116
|
+
const videoStreams = Array.from(videoStreamsSet)
|
|
117
|
+
.sort((v1, v2) => {
|
|
118
|
+
if (!v1.bandwidth || !v2.bandwidth) {
|
|
119
|
+
return v1.width - v2.width;
|
|
120
|
+
}
|
|
121
|
+
return v1.bandwidth - v2.bandwidth;
|
|
122
|
+
});
|
|
95
123
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
* Get variants by codecs map with the max density where all codecs are
|
|
99
|
-
* present.
|
|
100
|
-
*
|
|
101
|
-
* @param {!shaka.util.MultiMap.<shaka.extern.Variant>} variantsByCodecs
|
|
102
|
-
* @return {!shaka.util.MultiMap.<shaka.extern.Variant>}
|
|
103
|
-
* @private
|
|
104
|
-
*/
|
|
105
|
-
static filterVariantsByDensity_(variantsByCodecs) {
|
|
106
|
-
let maxDensity = 0;
|
|
107
|
-
const codecGroupsByDensity = new Map();
|
|
108
|
-
const countCodecs = variantsByCodecs.size();
|
|
109
|
-
|
|
110
|
-
variantsByCodecs.forEach((codecs, variants) => {
|
|
111
|
-
for (const variant of variants) {
|
|
112
|
-
const video = variant.video;
|
|
113
|
-
if (!video || !video.width || !video.height) {
|
|
114
|
-
continue;
|
|
115
|
-
}
|
|
124
|
+
const isChangeTypeSupported =
|
|
125
|
+
shaka.media.Capabilities.isChangeTypeSupported();
|
|
116
126
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
127
|
+
const validVideoStreams = [];
|
|
128
|
+
for (const stream of videoStreams) {
|
|
129
|
+
if (!validVideoStreams.length) {
|
|
130
|
+
validVideoStreams.push(stream);
|
|
131
|
+
} else {
|
|
132
|
+
const previousStream = validVideoStreams[validVideoStreams.length - 1];
|
|
133
|
+
if (!isChangeTypeSupported) {
|
|
134
|
+
const previousCodec =
|
|
135
|
+
MimeUtils.getNormalizedCodec(previousStream.codecs);
|
|
136
|
+
const currentCodec =
|
|
137
|
+
MimeUtils.getNormalizedCodec(stream.codecs);
|
|
138
|
+
if (previousCodec !== currentCodec) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (stream.width > previousStream.width ||
|
|
143
|
+
stream.height > previousStream.height) {
|
|
144
|
+
validVideoStreams.push(stream);
|
|
145
|
+
} else if (stream.width == previousStream.width &&
|
|
146
|
+
stream.height == previousStream.height) {
|
|
147
|
+
const previousCodec =
|
|
148
|
+
MimeUtils.getNormalizedCodec(previousStream.codecs);
|
|
149
|
+
const currentCodec =
|
|
150
|
+
MimeUtils.getNormalizedCodec(stream.codecs);
|
|
151
|
+
if (previousCodec == currentCodec) {
|
|
152
|
+
if (stream.bandwidth < previousStream.bandwidth) {
|
|
153
|
+
validVideoStreams.push(stream);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
120
156
|
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
121
159
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
160
|
+
const validAudioIds =
|
|
161
|
+
validAudioStreams.map((audioStream) => audioStream.id);
|
|
162
|
+
const validVideoIds =
|
|
163
|
+
validVideoStreams.map((videoStream) => videoStream.id);
|
|
164
|
+
|
|
165
|
+
// Filter out any variants that don't match, forcing AbrManager to choose
|
|
166
|
+
// from a single video codec and a single audio codec possible.
|
|
167
|
+
manifest.variants = manifest.variants.filter((variant) => {
|
|
168
|
+
const audio = variant.audio;
|
|
169
|
+
const video = variant.video;
|
|
170
|
+
if (audio) {
|
|
171
|
+
if (!validAudioIds.includes(audio.id)) {
|
|
172
|
+
shaka.log.debug('Dropping Variant (better codec available)', variant);
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (video) {
|
|
177
|
+
if (!validVideoIds.includes(video.id)) {
|
|
178
|
+
shaka.log.debug('Dropping Variant (better codec available)', variant);
|
|
179
|
+
return false;
|
|
133
180
|
}
|
|
134
181
|
}
|
|
182
|
+
return true;
|
|
135
183
|
});
|
|
136
|
-
|
|
137
|
-
return maxDensity ? codecGroupsByDensity.get(maxDensity) : variantsByCodecs;
|
|
138
184
|
}
|
|
139
185
|
|
|
140
186
|
/**
|
|
@@ -170,135 +216,6 @@ shaka.util.StreamUtils = class {
|
|
|
170
216
|
return subset;
|
|
171
217
|
}
|
|
172
218
|
|
|
173
|
-
/**
|
|
174
|
-
* Choose the codecs by configured preferred decoding attributes.
|
|
175
|
-
*
|
|
176
|
-
* @param {!shaka.util.MultiMap.<shaka.extern.Variant>} variantsByCodecs
|
|
177
|
-
* @param {!Array.<string>} attributes
|
|
178
|
-
* @return {string}
|
|
179
|
-
* @private
|
|
180
|
-
*/
|
|
181
|
-
static chooseCodecsByDecodingAttributes_(variantsByCodecs, attributes) {
|
|
182
|
-
const StreamUtils = shaka.util.StreamUtils;
|
|
183
|
-
|
|
184
|
-
for (const attribute of attributes) {
|
|
185
|
-
if (attribute == StreamUtils.DecodingAttributes.SMOOTH ||
|
|
186
|
-
attribute == StreamUtils.DecodingAttributes.POWER) {
|
|
187
|
-
variantsByCodecs = StreamUtils.chooseCodecsByMediaCapabilitiesInfo_(
|
|
188
|
-
variantsByCodecs, attribute);
|
|
189
|
-
// If we only have one smooth or powerEfficient codecs, choose it as the
|
|
190
|
-
// best codecs.
|
|
191
|
-
if (variantsByCodecs.size() == 1) {
|
|
192
|
-
return variantsByCodecs.keys()[0];
|
|
193
|
-
}
|
|
194
|
-
} else if (attribute == StreamUtils.DecodingAttributes.BANDWIDTH) {
|
|
195
|
-
return StreamUtils.findCodecsByLowestBandwidth_(variantsByCodecs);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
// If there's no configured decoding preferences, or we have multiple codecs
|
|
199
|
-
// that meets the configured decoding preferences, choose the one with
|
|
200
|
-
// the lowest bandwidth.
|
|
201
|
-
return StreamUtils.findCodecsByLowestBandwidth_(variantsByCodecs);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Choose the best codecs by configured preferred MediaCapabilitiesInfo
|
|
206
|
-
* attributes.
|
|
207
|
-
*
|
|
208
|
-
* @param {!shaka.util.MultiMap.<shaka.extern.Variant>} variantsByCodecs
|
|
209
|
-
* @param {string} attribute
|
|
210
|
-
* @return {!shaka.util.MultiMap.<shaka.extern.Variant>}
|
|
211
|
-
* @private
|
|
212
|
-
*/
|
|
213
|
-
static chooseCodecsByMediaCapabilitiesInfo_(variantsByCodecs, attribute) {
|
|
214
|
-
let highestScore = 0;
|
|
215
|
-
const bestVariantsByCodecs = new shaka.util.MultiMap();
|
|
216
|
-
variantsByCodecs.forEach((codecs, variants) => {
|
|
217
|
-
let sum = 0;
|
|
218
|
-
let num = 0;
|
|
219
|
-
|
|
220
|
-
for (const variant of variants) {
|
|
221
|
-
if (variant.decodingInfos.length) {
|
|
222
|
-
sum += variant.decodingInfos[0][attribute] ? 1 : 0;
|
|
223
|
-
num++;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
const averageScore = sum / num;
|
|
228
|
-
shaka.log.debug('codecs', codecs, 'avg', attribute, averageScore);
|
|
229
|
-
|
|
230
|
-
if (averageScore > highestScore) {
|
|
231
|
-
bestVariantsByCodecs.clear();
|
|
232
|
-
bestVariantsByCodecs.push(codecs, variants);
|
|
233
|
-
highestScore = averageScore;
|
|
234
|
-
} else if (averageScore == highestScore) {
|
|
235
|
-
bestVariantsByCodecs.push(codecs, variants);
|
|
236
|
-
}
|
|
237
|
-
});
|
|
238
|
-
return bestVariantsByCodecs;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Find the lowest-bandwidth (best) codecs.
|
|
243
|
-
* Compute the average bandwidth for each group of variants.
|
|
244
|
-
*
|
|
245
|
-
* @param {!shaka.util.MultiMap.<shaka.extern.Variant>} variantsByCodecs
|
|
246
|
-
* @return {string}
|
|
247
|
-
* @private
|
|
248
|
-
*/
|
|
249
|
-
static findCodecsByLowestBandwidth_(variantsByCodecs) {
|
|
250
|
-
let bestCodecs = '';
|
|
251
|
-
let lowestAverageBandwidth = Infinity;
|
|
252
|
-
|
|
253
|
-
variantsByCodecs.forEach((codecs, variants) => {
|
|
254
|
-
let sum = 0;
|
|
255
|
-
let num = 0;
|
|
256
|
-
for (const variant of variants) {
|
|
257
|
-
sum += variant.bandwidth || 0;
|
|
258
|
-
++num;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
const averageBandwidth = sum / num;
|
|
262
|
-
shaka.log.debug('codecs', codecs, 'avg bandwidth', averageBandwidth);
|
|
263
|
-
|
|
264
|
-
if (averageBandwidth < lowestAverageBandwidth) {
|
|
265
|
-
bestCodecs = codecs;
|
|
266
|
-
lowestAverageBandwidth = averageBandwidth;
|
|
267
|
-
}
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
goog.asserts.assert(bestCodecs !== '', 'Should have chosen codecs!');
|
|
271
|
-
goog.asserts.assert(!isNaN(lowestAverageBandwidth),
|
|
272
|
-
'Bandwidth should be a number!');
|
|
273
|
-
|
|
274
|
-
return bestCodecs;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
/**
|
|
278
|
-
* Get a string representing all codecs used in a variant.
|
|
279
|
-
*
|
|
280
|
-
* @param {!shaka.extern.Variant} variant
|
|
281
|
-
* @return {string}
|
|
282
|
-
* @private
|
|
283
|
-
*/
|
|
284
|
-
static getVariantCodecs_(variant) {
|
|
285
|
-
// Only consider the base of the codec string. For example, these should
|
|
286
|
-
// both be considered the same codec: avc1.42c01e, avc1.4d401f
|
|
287
|
-
let baseVideoCodec = '';
|
|
288
|
-
if (variant.video) {
|
|
289
|
-
baseVideoCodec =
|
|
290
|
-
shaka.util.MimeUtils.getNormalizedCodec(variant.video.codecs);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
let baseAudioCodec = '';
|
|
294
|
-
if (variant.audio) {
|
|
295
|
-
baseAudioCodec =
|
|
296
|
-
shaka.util.MimeUtils.getNormalizedCodec(variant.audio.codecs);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
return baseVideoCodec + '-' + baseAudioCodec;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
219
|
/**
|
|
303
220
|
* Filter the variants in |manifest| to only include the variants that meet
|
|
304
221
|
* the given restrictions.
|
|
@@ -404,12 +321,12 @@ shaka.util.StreamUtils = class {
|
|
|
404
321
|
* @param {shaka.media.DrmEngine} drmEngine
|
|
405
322
|
* @param {?shaka.extern.Variant} currentVariant
|
|
406
323
|
* @param {shaka.extern.Manifest} manifest
|
|
324
|
+
* @param {shaka.config.CodecSwitchingStrategy=} codecSwitchingStrategy
|
|
407
325
|
*/
|
|
408
|
-
static async filterManifest(drmEngine, currentVariant, manifest
|
|
326
|
+
static async filterManifest(drmEngine, currentVariant, manifest,
|
|
327
|
+
codecSwitchingStrategy=shaka.config.CodecSwitchingStrategy.RELOAD) {
|
|
409
328
|
await shaka.util.StreamUtils.filterManifestByMediaCapabilities(manifest,
|
|
410
329
|
manifest.offlineSessionIds.length > 0);
|
|
411
|
-
shaka.util.StreamUtils.filterManifestByCurrentVariant(
|
|
412
|
-
currentVariant, manifest);
|
|
413
330
|
shaka.util.StreamUtils.filterTextStreams_(manifest);
|
|
414
331
|
await shaka.util.StreamUtils.filterImageStreams_(manifest);
|
|
415
332
|
}
|
|
@@ -1510,6 +1427,7 @@ shaka.util.StreamUtils = class {
|
|
|
1510
1427
|
|
|
1511
1428
|
/** @type {!Map.<number, !Array.<shaka.extern.Variant>>} */
|
|
1512
1429
|
const variantsByChannelCount = new Map();
|
|
1430
|
+
const capableVariants = [];
|
|
1513
1431
|
for (const variant of variantsWithChannelCounts) {
|
|
1514
1432
|
const count = variant.audio.channelsCount;
|
|
1515
1433
|
goog.asserts.assert(count != null, 'Must have count after filtering!');
|
|
@@ -1517,6 +1435,14 @@ shaka.util.StreamUtils = class {
|
|
|
1517
1435
|
variantsByChannelCount.set(count, []);
|
|
1518
1436
|
}
|
|
1519
1437
|
variantsByChannelCount.get(count).push(variant);
|
|
1438
|
+
if (count <= preferredAudioChannelCount) {
|
|
1439
|
+
capableVariants.push(variant);
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
// return all capable channelcounts
|
|
1444
|
+
if (capableVariants.length) {
|
|
1445
|
+
return capableVariants;
|
|
1520
1446
|
}
|
|
1521
1447
|
|
|
1522
1448
|
/** @type {!Array.<number>} */
|
|
@@ -1527,15 +1453,6 @@ shaka.util.StreamUtils = class {
|
|
|
1527
1453
|
return variants;
|
|
1528
1454
|
}
|
|
1529
1455
|
|
|
1530
|
-
// Choose the variants with the largest number of audio channels less than
|
|
1531
|
-
// or equal to the configured number of audio channels.
|
|
1532
|
-
const countLessThanOrEqualtoConfig =
|
|
1533
|
-
channelCounts.filter((count) => count <= preferredAudioChannelCount);
|
|
1534
|
-
if (countLessThanOrEqualtoConfig.length) {
|
|
1535
|
-
return variantsByChannelCount.get(
|
|
1536
|
-
Math.max(...countLessThanOrEqualtoConfig));
|
|
1537
|
-
}
|
|
1538
|
-
|
|
1539
1456
|
// If all variants have more audio channels than the config, choose the
|
|
1540
1457
|
// variants with the fewest audio channels.
|
|
1541
1458
|
return variantsByChannelCount.get(Math.min(...channelCounts));
|
|
@@ -1762,7 +1679,6 @@ shaka.util.StreamUtils.nextTrackId_ = 0;
|
|
|
1762
1679
|
shaka.util.StreamUtils.DecodingAttributes = {
|
|
1763
1680
|
SMOOTH: 'smooth',
|
|
1764
1681
|
POWER: 'powerEfficient',
|
|
1765
|
-
BANDWIDTH: 'bandwidth',
|
|
1766
1682
|
};
|
|
1767
1683
|
|
|
1768
1684
|
/**
|