shaka-player 3.1.4 → 3.3.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/ISSUE_TEMPLATE/feature_request.md +1 -1
- package/.github/ISSUE_TEMPLATE/question.md +1 -1
- package/AUTHORS +6 -5
- package/CHANGELOG.md +363 -0
- package/CONTRIBUTORS +4 -2
- package/README.md +4 -4
- package/build/types/core +3 -0
- package/build/types/offline +1 -0
- package/build/types/polyfill +2 -0
- package/build/types/ui +2 -0
- package/demo/common/asset.js +9 -7
- package/demo/common/assets.js +28 -1
- package/demo/common/message_ids.js +15 -2
- package/demo/config.js +35 -2
- package/demo/index.html +1 -1
- package/demo/locales/en.json +14 -1
- package/demo/locales/source.json +56 -4
- package/demo/main.js +2 -1
- package/dist/controls.css +26 -2
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +24 -21
- package/dist/demo.compiled.debug.map +3 -3
- package/dist/demo.compiled.js +24 -21
- package/dist/demo.compiled.map +3 -3
- package/dist/deps.js +33 -25
- package/dist/locales.js +31 -29
- package/dist/receiver.compiled.debug.js +14 -12
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +14 -12
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.d.ts +258 -20
- package/dist/shaka-player.compiled.debug.d.ts +258 -20
- package/dist/shaka-player.compiled.debug.externs.js +1005 -695
- package/dist/shaka-player.compiled.debug.js +720 -640
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +1005 -695
- package/dist/shaka-player.compiled.js +850 -817
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +274 -21
- package/dist/shaka-player.ui.debug.d.ts +274 -21
- package/dist/shaka-player.ui.debug.externs.js +766 -429
- package/dist/shaka-player.ui.debug.js +863 -765
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +766 -429
- package/dist/shaka-player.ui.js +1042 -996
- package/dist/shaka-player.ui.map +4 -4
- package/docs/design/bg-fetch-after.gv +29 -0
- package/docs/design/bg-fetch-after.gv.png +0 -0
- package/docs/design/bg-fetch-before.gv +18 -0
- package/docs/design/bg-fetch-before.gv.png +0 -0
- package/docs/design/bg-fetch.md +134 -0
- package/docs/tutorials/blob-url.md +15 -0
- package/docs/tutorials/index.json +1 -0
- package/docs/tutorials/ui-customization.md +66 -0
- package/docs/tutorials/ui.md +5 -5
- package/externs/aria.js +6 -0
- package/externs/ima.js +3 -0
- package/externs/shaka/ads.js +29 -1
- package/externs/shaka/manifest.js +18 -2
- package/externs/shaka/manifest_parser.js +10 -1
- package/externs/shaka/net.js +20 -4
- package/externs/shaka/offline.js +36 -2
- package/externs/shaka/player.js +182 -13
- package/externs/shaka/text.js +24 -10
- package/externs/texttrack.js +3 -0
- package/externs/webcrypto.js +18 -0
- package/lib/abr/ewma.js +14 -0
- package/lib/abr/ewma_bandwidth_estimator.js +16 -2
- package/lib/abr/simple_abr_manager.js +6 -0
- package/lib/ads/ad_manager.js +16 -15
- package/lib/ads/client_side_ad.js +8 -0
- package/lib/ads/client_side_ad_manager.js +14 -6
- package/lib/ads/server_side_ad.js +7 -0
- package/lib/ads/server_side_ad_manager.js +19 -2
- package/lib/cast/cast_proxy.js +8 -0
- package/lib/cast/cast_utils.js +7 -1
- package/lib/cea/cea608_data_channel.js +56 -56
- package/lib/cea/cea608_memory.js +33 -33
- package/lib/cea/cea708_service.js +43 -43
- package/lib/cea/cea708_window.js +38 -38
- package/lib/cea/cea_decoder.js +13 -14
- package/lib/cea/cea_utils.js +23 -23
- package/lib/cea/dtvcc_packet_builder.js +7 -7
- package/lib/cea/i_caption_decoder.js +2 -3
- package/lib/cea/i_cea_parser.js +2 -2
- package/lib/cea/mp4_cea_parser.js +6 -6
- package/lib/dash/dash_parser.js +53 -14
- package/lib/dash/segment_base.js +25 -1
- package/lib/dash/segment_list.js +18 -9
- package/lib/dash/segment_template.js +23 -10
- package/lib/hls/hls_parser.js +210 -30
- package/lib/media/closed_caption_parser.js +1 -2
- package/lib/media/drm_engine.js +162 -192
- package/lib/media/quality_observer.js +291 -0
- package/lib/media/segment_index.js +9 -1
- package/lib/media/segment_reference.js +37 -5
- package/lib/media/streaming_engine.js +48 -10
- package/lib/net/http_fetch_plugin.js +31 -11
- package/lib/net/http_plugin_utils.js +1 -0
- package/lib/net/http_xhr_plugin.js +40 -14
- package/lib/net/networking_engine.js +82 -18
- package/lib/offline/download_info.js +68 -0
- package/lib/offline/download_manager.js +14 -7
- package/lib/offline/indexeddb/base_storage_cell.js +35 -0
- package/lib/offline/indexeddb/storage_mechanism.js +1 -1
- package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
- package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
- package/lib/offline/indexeddb/v5_storage_cell.js +5 -0
- package/lib/offline/manifest_converter.js +3 -1
- package/lib/offline/storage.js +404 -297
- package/lib/offline/stored_content_utils.js +2 -0
- package/lib/player.js +622 -153
- package/lib/polyfill/aria.js +82 -0
- package/lib/polyfill/random_uuid.js +52 -0
- package/lib/routing/walker.js +2 -3
- package/lib/text/cue.js +12 -0
- package/lib/text/srt_text_parser.js +4 -4
- package/lib/text/text_engine.js +2 -2
- package/lib/text/ttml_text_parser.js +25 -2
- package/lib/text/ui_text_displayer.js +2 -2
- package/lib/text/vtt_text_parser.js +2 -2
- package/lib/text/web_vtt_generator.js +55 -12
- package/lib/util/cmcd_manager.js +826 -0
- package/lib/util/error.js +12 -0
- package/lib/util/language_utils.js +12 -0
- package/lib/util/manifest_parser_utils.js +1 -0
- package/lib/util/mp4_box_parsers.js +20 -20
- package/lib/util/multi_map.js +8 -0
- package/lib/util/mutex.js +52 -0
- package/lib/util/periods.js +98 -64
- package/lib/util/player_configuration.js +31 -1
- package/lib/util/stream_utils.js +140 -85
- package/lib/util/xml_utils.js +31 -12
- package/package.json +1 -1
- package/roadmap.md +24 -22
- package/shaka-player.uncompiled.js +4 -0
- package/test/cast/cast_utils_unit.js +1 -0
- package/test/cea/cea608_memory_unit.js +1 -1
- package/test/cea/cea708_service_unit.js +8 -8
- package/test/cea/cea708_window_unit.js +6 -6
- package/test/cea/cea_decoder_unit.js +1 -1
- package/test/cea/dtvcc_packet_builder_unit.js +2 -2
- package/test/dash/dash_parser_content_protection_unit.js +2 -0
- package/test/dash/dash_parser_live_unit.js +101 -1
- package/test/dash/dash_parser_manifest_unit.js +78 -2
- package/test/dash/dash_parser_segment_base_unit.js +2 -0
- package/test/dash/dash_parser_segment_list_unit.js +2 -1
- package/test/dash/dash_parser_segment_template_unit.js +2 -1
- package/test/hls/hls_live_unit.js +2 -0
- package/test/hls/hls_parser_unit.js +252 -0
- package/test/media/drm_engine_integration.js +86 -12
- package/test/media/drm_engine_unit.js +310 -450
- package/test/media/quality_observer_unit.js +139 -0
- package/test/media/segment_reference_unit.js +16 -1
- package/test/media/streaming_engine_integration.js +2 -1
- package/test/media/streaming_engine_unit.js +2 -0
- package/test/net/http_plugin_unit.js +20 -15
- package/test/offline/manifest_convert_unit.js +2 -0
- package/test/offline/storage_integration.js +117 -23
- package/test/player_integration.js +151 -0
- package/test/player_src_equals_integration.js +52 -0
- package/test/player_unit.js +11 -33
- package/test/test/assets/chapters.srt +11 -0
- package/test/test/assets/chapters.vtt +10 -0
- package/test/test/util/cea_utils.js +12 -12
- package/test/test/util/dash_parser_util.js +4 -0
- package/test/test/util/fake_ad.js +7 -0
- package/test/test/util/fake_ad_manager.js +7 -0
- package/test/test/util/fake_drm_engine.js +9 -2
- package/test/test/util/manifest_generator.js +5 -2
- package/test/test/util/manifest_parser_util.js +3 -1
- package/test/test/util/test_scheme.js +14 -1
- package/test/text/ttml_text_parser_unit.js +47 -0
- package/test/text/web_vtt_generator_unit.js +81 -7
- package/test/ui/ui_unit.js +250 -0
- package/test/util/cmcd_manager_unit.js +277 -0
- package/test/util/stream_utils_unit.js +118 -10
- package/ui/airplay_button.js +2 -1
- package/ui/audio_language_selection.js +9 -5
- package/ui/cast_button.js +5 -6
- package/ui/constants.js +0 -3
- package/ui/context_menu.js +109 -0
- package/ui/controls.js +41 -7
- package/ui/controls.less +1 -0
- package/ui/enums.js +4 -0
- package/ui/externs/ui.js +28 -1
- package/ui/fast_forward_button.js +16 -8
- package/ui/fullscreen_button.js +2 -3
- package/ui/language_utils.js +1 -1
- package/ui/less/buttons.less +0 -4
- package/ui/less/containers.less +74 -0
- package/ui/less/overflow_menu.less +0 -10
- package/ui/less/tooltip.less +97 -0
- package/ui/locales/en.json +1 -0
- package/ui/locales/source.json +4 -0
- package/ui/loop_button.js +6 -3
- package/ui/mute_button.js +3 -4
- package/ui/overflow_menu.js +7 -28
- package/ui/pip_button.js +10 -7
- package/ui/play_button.js +2 -2
- package/ui/playback_rate_selection.js +11 -15
- package/ui/presentation_time.js +1 -3
- package/ui/resolution_selection.js +11 -7
- package/ui/rewind_button.js +17 -9
- package/ui/seek_bar.js +6 -6
- package/ui/settings_menu.js +36 -4
- package/ui/small_play_button.js +1 -0
- package/ui/spacer.js +1 -1
- package/ui/statistics_button.js +253 -0
- package/ui/text_selection.js +19 -15
- package/ui/ui.js +30 -0
- package/ui/ui_utils.js +1 -1
- package/ui/volume_bar.js +2 -4
package/lib/util/stream_utils.js
CHANGED
|
@@ -8,7 +8,6 @@ goog.provide('shaka.util.StreamUtils');
|
|
|
8
8
|
|
|
9
9
|
goog.require('goog.asserts');
|
|
10
10
|
goog.require('shaka.log');
|
|
11
|
-
goog.require('shaka.media.MediaSourceEngine');
|
|
12
11
|
goog.require('shaka.text.TextEngine');
|
|
13
12
|
goog.require('shaka.util.Functional');
|
|
14
13
|
goog.require('shaka.util.LanguageUtils');
|
|
@@ -28,30 +27,43 @@ shaka.util.StreamUtils = class {
|
|
|
28
27
|
* bandwidth and filter out the rest.
|
|
29
28
|
* Also filters out variants that have too many audio channels.
|
|
30
29
|
* @param {!shaka.extern.Manifest} manifest
|
|
30
|
+
* @param {!Array.<string>} preferredVideoCodecs
|
|
31
|
+
* @param {!Array.<string>} preferredAudioCodecs
|
|
31
32
|
* @param {number} preferredAudioChannelCount
|
|
33
|
+
* @param {!Array.<string>} preferredDecodingAttributes
|
|
32
34
|
*/
|
|
33
|
-
static chooseCodecsAndFilterManifest(manifest,
|
|
35
|
+
static chooseCodecsAndFilterManifest(manifest, preferredVideoCodecs,
|
|
36
|
+
preferredAudioCodecs, preferredAudioChannelCount,
|
|
37
|
+
preferredDecodingAttributes) {
|
|
34
38
|
const StreamUtils = shaka.util.StreamUtils;
|
|
35
39
|
|
|
36
|
-
|
|
40
|
+
let variants = manifest.variants;
|
|
41
|
+
// To start, choose the codecs based on configured preferences if available.
|
|
42
|
+
if (preferredVideoCodecs.length || preferredAudioCodecs.length) {
|
|
43
|
+
variants = StreamUtils.choosePreferredCodecs(variants,
|
|
44
|
+
preferredVideoCodecs, preferredAudioCodecs);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Consider a subset of variants based on audio channel
|
|
37
48
|
// preferences.
|
|
38
49
|
// For some content (#1013), surround-sound variants will use a different
|
|
39
50
|
// codec than stereo variants, so it is important to choose codecs **after**
|
|
40
51
|
// considering the audio channel config.
|
|
41
|
-
|
|
42
|
-
|
|
52
|
+
variants = StreamUtils.filterVariantsByAudioChannelCount(
|
|
53
|
+
variants, preferredAudioChannelCount);
|
|
43
54
|
|
|
44
55
|
// Now organize variants into buckets by codecs.
|
|
45
56
|
/** @type {!shaka.util.MultiMap.<shaka.extern.Variant>} */
|
|
46
57
|
let variantsByCodecs = StreamUtils.getVariantsByCodecs_(variants);
|
|
47
58
|
variantsByCodecs = StreamUtils.filterVariantsByDensity_(variantsByCodecs);
|
|
48
59
|
|
|
49
|
-
const bestCodecs = StreamUtils.
|
|
60
|
+
const bestCodecs = StreamUtils.chooseCodecsByDecodingAttributes_(
|
|
61
|
+
variantsByCodecs, preferredDecodingAttributes);
|
|
50
62
|
|
|
51
63
|
// Filter out any variants that don't match, forcing AbrManager to choose
|
|
52
|
-
// from
|
|
64
|
+
// from a single video codec and a single audio codec possible.
|
|
53
65
|
manifest.variants = manifest.variants.filter((variant) => {
|
|
54
|
-
const codecs = StreamUtils.
|
|
66
|
+
const codecs = StreamUtils.getVariantCodecs_(variant);
|
|
55
67
|
if (codecs == bestCodecs) {
|
|
56
68
|
return true;
|
|
57
69
|
}
|
|
@@ -71,8 +83,8 @@ shaka.util.StreamUtils = class {
|
|
|
71
83
|
static getVariantsByCodecs_(variants) {
|
|
72
84
|
const variantsByCodecs = new shaka.util.MultiMap();
|
|
73
85
|
for (const variant of variants) {
|
|
74
|
-
const
|
|
75
|
-
variantsByCodecs.push(
|
|
86
|
+
const variantCodecs = shaka.util.StreamUtils.getVariantCodecs_(variant);
|
|
87
|
+
variantsByCodecs.push(variantCodecs, variant);
|
|
76
88
|
}
|
|
77
89
|
|
|
78
90
|
return variantsByCodecs;
|
|
@@ -80,6 +92,8 @@ shaka.util.StreamUtils = class {
|
|
|
80
92
|
|
|
81
93
|
/**
|
|
82
94
|
* Filters variants by density.
|
|
95
|
+
* Get variants by codecs map with the max density where all codecs are
|
|
96
|
+
* present.
|
|
83
97
|
*
|
|
84
98
|
* @param {!shaka.util.MultiMap.<shaka.extern.Variant>} variantsByCodecs
|
|
85
99
|
* @return {!shaka.util.MultiMap.<shaka.extern.Variant>}
|
|
@@ -120,6 +134,107 @@ shaka.util.StreamUtils = class {
|
|
|
120
134
|
return maxDensity ? codecGroupsByDensity.get(maxDensity) : variantsByCodecs;
|
|
121
135
|
}
|
|
122
136
|
|
|
137
|
+
/**
|
|
138
|
+
* Choose the codecs by configured preferred audio and video codecs.
|
|
139
|
+
*
|
|
140
|
+
* @param {!Array<shaka.extern.Variant>} variants
|
|
141
|
+
* @param {!Array.<string>} preferredVideoCodecs
|
|
142
|
+
* @param {!Array.<string>} preferredAudioCodecs
|
|
143
|
+
* @return {!Array<shaka.extern.Variant>}
|
|
144
|
+
*/
|
|
145
|
+
static choosePreferredCodecs(variants, preferredVideoCodecs,
|
|
146
|
+
preferredAudioCodecs) {
|
|
147
|
+
let subset = variants;
|
|
148
|
+
for (const videoCodec of preferredVideoCodecs) {
|
|
149
|
+
const filtered = subset.filter((variant) => {
|
|
150
|
+
return variant.video && variant.video.codecs.startsWith(videoCodec);
|
|
151
|
+
});
|
|
152
|
+
if (filtered.length) {
|
|
153
|
+
subset = filtered;
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
for (const audioCodec of preferredAudioCodecs) {
|
|
159
|
+
const filtered = subset.filter((variant) => {
|
|
160
|
+
return variant.audio && variant.audio.codecs.startsWith(audioCodec);
|
|
161
|
+
});
|
|
162
|
+
if (filtered.length) {
|
|
163
|
+
subset = filtered;
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return subset;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Choose the codecs by configured preferred decoding attributes.
|
|
172
|
+
*
|
|
173
|
+
* @param {!shaka.util.MultiMap.<shaka.extern.Variant>} variantsByCodecs
|
|
174
|
+
* @param {!Array.<string>} attributes
|
|
175
|
+
* @return {string}
|
|
176
|
+
* @private
|
|
177
|
+
*/
|
|
178
|
+
static chooseCodecsByDecodingAttributes_(variantsByCodecs, attributes) {
|
|
179
|
+
const StreamUtils = shaka.util.StreamUtils;
|
|
180
|
+
|
|
181
|
+
for (const attribute of attributes) {
|
|
182
|
+
if (attribute == StreamUtils.DecodingAttributes.SMOOTH ||
|
|
183
|
+
attribute == StreamUtils.DecodingAttributes.POWER) {
|
|
184
|
+
variantsByCodecs = StreamUtils.chooseCodecsByMediaCapabilitiesInfo_(
|
|
185
|
+
variantsByCodecs, attribute);
|
|
186
|
+
// If we only have one smooth or powerEfficient codecs, choose it as the
|
|
187
|
+
// best codecs.
|
|
188
|
+
if (variantsByCodecs.size() == 1) {
|
|
189
|
+
return variantsByCodecs.keys()[0];
|
|
190
|
+
}
|
|
191
|
+
} else if (attribute == StreamUtils.DecodingAttributes.BANDWIDTH) {
|
|
192
|
+
return StreamUtils.findCodecsByLowestBandwidth_(variantsByCodecs);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// If there's no configured decoding preferences, or we have multiple codecs
|
|
196
|
+
// that meets the configured decoding preferences, choose the one with
|
|
197
|
+
// the lowest bandwidth.
|
|
198
|
+
return StreamUtils.findCodecsByLowestBandwidth_(variantsByCodecs);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Choose the best codecs by configured preferred MediaCapabilitiesInfo
|
|
203
|
+
* attributes.
|
|
204
|
+
*
|
|
205
|
+
* @param {!shaka.util.MultiMap.<shaka.extern.Variant>} variantsByCodecs
|
|
206
|
+
* @param {string} attribute
|
|
207
|
+
* @return {!shaka.util.MultiMap.<shaka.extern.Variant>}
|
|
208
|
+
* @private
|
|
209
|
+
*/
|
|
210
|
+
static chooseCodecsByMediaCapabilitiesInfo_(variantsByCodecs, attribute) {
|
|
211
|
+
let highestScore = 0;
|
|
212
|
+
const bestVariantsByCodecs = new shaka.util.MultiMap();
|
|
213
|
+
variantsByCodecs.forEach((codecs, variants) => {
|
|
214
|
+
let sum = 0;
|
|
215
|
+
let num = 0;
|
|
216
|
+
|
|
217
|
+
for (const variant of variants) {
|
|
218
|
+
if (variant.decodingInfos.length) {
|
|
219
|
+
sum += variant.decodingInfos[0][attribute] ? 1 : 0;
|
|
220
|
+
num++;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const averageScore = sum / num;
|
|
225
|
+
shaka.log.debug('codecs', codecs, 'avg', attribute, averageScore);
|
|
226
|
+
|
|
227
|
+
if (averageScore > highestScore) {
|
|
228
|
+
bestVariantsByCodecs.clear();
|
|
229
|
+
bestVariantsByCodecs.push(codecs, variants);
|
|
230
|
+
highestScore = averageScore;
|
|
231
|
+
} else if (averageScore == highestScore) {
|
|
232
|
+
bestVariantsByCodecs.push(codecs, variants);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
return bestVariantsByCodecs;
|
|
236
|
+
}
|
|
237
|
+
|
|
123
238
|
/**
|
|
124
239
|
* Find the lowest-bandwidth (best) codecs.
|
|
125
240
|
* Compute the average bandwidth for each group of variants.
|
|
@@ -128,7 +243,7 @@ shaka.util.StreamUtils = class {
|
|
|
128
243
|
* @return {string}
|
|
129
244
|
* @private
|
|
130
245
|
*/
|
|
131
|
-
static
|
|
246
|
+
static findCodecsByLowestBandwidth_(variantsByCodecs) {
|
|
132
247
|
let bestCodecs = '';
|
|
133
248
|
let lowestAverageBandwidth = Infinity;
|
|
134
249
|
|
|
@@ -163,7 +278,7 @@ shaka.util.StreamUtils = class {
|
|
|
163
278
|
* @return {string}
|
|
164
279
|
* @private
|
|
165
280
|
*/
|
|
166
|
-
static
|
|
281
|
+
static getVariantCodecs_(variant) {
|
|
167
282
|
// Only consider the base of the codec string. For example, these should
|
|
168
283
|
// both be considered the same codec: avc1.42c01e, avc1.4d401f
|
|
169
284
|
let baseVideoCodec = '';
|
|
@@ -183,7 +298,7 @@ shaka.util.StreamUtils = class {
|
|
|
183
298
|
* Filter the variants in |manifest| to only include the variants that meet
|
|
184
299
|
* the given restrictions.
|
|
185
300
|
*
|
|
186
|
-
* @param {shaka.extern.Manifest} manifest
|
|
301
|
+
* @param {!shaka.extern.Manifest} manifest
|
|
187
302
|
* @param {shaka.extern.Restrictions} restrictions
|
|
188
303
|
* @param {{width: number, height:number}} maxHwResolution
|
|
189
304
|
*/
|
|
@@ -283,17 +398,11 @@ shaka.util.StreamUtils = class {
|
|
|
283
398
|
* @param {shaka.media.DrmEngine} drmEngine
|
|
284
399
|
* @param {?shaka.extern.Variant} currentVariant
|
|
285
400
|
* @param {shaka.extern.Manifest} manifest
|
|
286
|
-
* @param {boolean=} useMediaCapabilities
|
|
287
401
|
*/
|
|
288
402
|
static async filterManifest(
|
|
289
|
-
drmEngine, currentVariant, manifest
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
manifest.offlineSessionIds.length > 0);
|
|
293
|
-
} else {
|
|
294
|
-
shaka.util.StreamUtils.filterManifestByDrm(manifest, drmEngine);
|
|
295
|
-
shaka.util.StreamUtils.filterManifestByMediaSource(manifest);
|
|
296
|
-
}
|
|
403
|
+
drmEngine, currentVariant, manifest) {
|
|
404
|
+
await shaka.util.StreamUtils.filterManifestByMediaCapabilities(manifest,
|
|
405
|
+
manifest.offlineSessionIds.length > 0);
|
|
297
406
|
shaka.util.StreamUtils.filterManifestByCurrentVariant(
|
|
298
407
|
currentVariant, manifest);
|
|
299
408
|
shaka.util.StreamUtils.filterTextStreams_(manifest);
|
|
@@ -301,29 +410,6 @@ shaka.util.StreamUtils = class {
|
|
|
301
410
|
}
|
|
302
411
|
|
|
303
412
|
|
|
304
|
-
/**
|
|
305
|
-
* Filter the variants in |manifest| to only include those that are supported
|
|
306
|
-
* by |drm|.
|
|
307
|
-
* @param {shaka.extern.Manifest} manifest
|
|
308
|
-
* @param {shaka.media.DrmEngine} drmEngine
|
|
309
|
-
*/
|
|
310
|
-
static filterManifestByDrm(manifest, drmEngine) {
|
|
311
|
-
manifest.variants = manifest.variants.filter((variant) => {
|
|
312
|
-
if (drmEngine && drmEngine.initialized()) {
|
|
313
|
-
if (!drmEngine.supportsVariant(variant)) {
|
|
314
|
-
shaka.log.debug('Dropping variant - not compatible with key system',
|
|
315
|
-
variant);
|
|
316
|
-
return false;
|
|
317
|
-
}
|
|
318
|
-
return true;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
shaka.log.debug('DrmEngine is not initialized yet.');
|
|
322
|
-
return true;
|
|
323
|
-
});
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
|
|
327
413
|
/**
|
|
328
414
|
* Alters the given Manifest to filter out any streams unsupported by the
|
|
329
415
|
* platform via MediaCapabilities.decodingInfo() API.
|
|
@@ -363,46 +449,6 @@ shaka.util.StreamUtils = class {
|
|
|
363
449
|
}
|
|
364
450
|
|
|
365
451
|
|
|
366
|
-
/**
|
|
367
|
-
* Filter the variants in the |manifest| to only include those that are
|
|
368
|
-
* supported by media source.
|
|
369
|
-
* TODO: remove once MediaCap implementations are done.
|
|
370
|
-
* @param {shaka.extern.Manifest} manifest
|
|
371
|
-
*/
|
|
372
|
-
static filterManifestByMediaSource(manifest) {
|
|
373
|
-
const StreamUtils = shaka.util.StreamUtils;
|
|
374
|
-
|
|
375
|
-
manifest.variants = manifest.variants.filter((variant) => {
|
|
376
|
-
const audio = variant.audio;
|
|
377
|
-
const video = variant.video;
|
|
378
|
-
|
|
379
|
-
if (audio && !shaka.media.MediaSourceEngine.isStreamSupported(audio)) {
|
|
380
|
-
shaka.log.debug('Dropping variant - audio not compatible with platform',
|
|
381
|
-
StreamUtils.getStreamSummaryString_(audio));
|
|
382
|
-
return false;
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
if (video && !shaka.media.MediaSourceEngine.isStreamSupported(video)) {
|
|
386
|
-
shaka.log.debug('Dropping variant - video not compatible with platform',
|
|
387
|
-
StreamUtils.getStreamSummaryString_(video));
|
|
388
|
-
return false;
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
// See: https://github.com/google/shaka-player/issues/3380
|
|
392
|
-
if (shaka.util.Platform.isXboxOne() && video &&
|
|
393
|
-
((video.width && video.width > 1920) ||
|
|
394
|
-
(video.height && video.height > 1080)) &&
|
|
395
|
-
video.codecs.includes('avc1.')) {
|
|
396
|
-
shaka.log.debug('Dropping variant - video not compatible with platform',
|
|
397
|
-
StreamUtils.getStreamSummaryString_(video));
|
|
398
|
-
return false;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
return true;
|
|
402
|
-
});
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
|
|
406
452
|
/**
|
|
407
453
|
* Get the decodingInfo results of the variants via MediaCapabilities.
|
|
408
454
|
* This should be called after the DrmEngine is created and configured, and
|
|
@@ -1371,3 +1417,12 @@ shaka.util.StreamUtils = class {
|
|
|
1371
1417
|
|
|
1372
1418
|
/** @private {number} */
|
|
1373
1419
|
shaka.util.StreamUtils.nextTrackId_ = 0;
|
|
1420
|
+
|
|
1421
|
+
/**
|
|
1422
|
+
* @enum {string}
|
|
1423
|
+
*/
|
|
1424
|
+
shaka.util.StreamUtils.DecodingAttributes = {
|
|
1425
|
+
SMOOTH: 'smooth',
|
|
1426
|
+
POWER: 'powerEfficient',
|
|
1427
|
+
BANDWIDTH: 'bandwidth',
|
|
1428
|
+
};
|
package/lib/util/xml_utils.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
goog.provide('shaka.util.XmlUtils');
|
|
8
8
|
|
|
9
|
+
goog.require('goog.asserts');
|
|
9
10
|
goog.require('shaka.log');
|
|
10
11
|
goog.require('shaka.util.StringUtils');
|
|
11
12
|
|
|
@@ -312,29 +313,46 @@ shaka.util.XmlUtils = class {
|
|
|
312
313
|
|
|
313
314
|
|
|
314
315
|
/**
|
|
315
|
-
* Parse a string and return the resulting root element if
|
|
316
|
-
*
|
|
316
|
+
* Parse a string and return the resulting root element if it was valid XML.
|
|
317
|
+
*
|
|
317
318
|
* @param {string} xmlString
|
|
318
319
|
* @param {string} expectedRootElemName
|
|
319
320
|
* @return {Element}
|
|
320
321
|
*/
|
|
321
322
|
static parseXmlString(xmlString, expectedRootElemName) {
|
|
322
323
|
const parser = new DOMParser();
|
|
323
|
-
let rootElem = null;
|
|
324
324
|
let xml = null;
|
|
325
325
|
try {
|
|
326
326
|
xml = parser.parseFromString(xmlString, 'text/xml');
|
|
327
|
-
} catch (exception) {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
327
|
+
} catch (exception) {
|
|
328
|
+
shaka.log.error('XML parsing exception:', exception);
|
|
329
|
+
return null;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// According to MDN, parseFromString never returns null.
|
|
333
|
+
goog.asserts.assert(xml, 'Parsed XML document cannot be null!');
|
|
334
|
+
|
|
335
|
+
// Check for empty documents.
|
|
336
|
+
const rootElem = xml.documentElement;
|
|
337
|
+
if (!rootElem) {
|
|
338
|
+
shaka.log.error('XML document was empty!');
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Check for parser errors.
|
|
343
|
+
const parserErrorElements = rootElem.getElementsByTagName('parsererror');
|
|
344
|
+
if (parserErrorElements.length) {
|
|
345
|
+
shaka.log.error('XML parser error found:', parserErrorElements[0]);
|
|
346
|
+
return null;
|
|
334
347
|
}
|
|
335
|
-
|
|
348
|
+
|
|
349
|
+
// The top-level element in the loaded XML should have the name we expect.
|
|
350
|
+
if (xml.documentElement.tagName != expectedRootElemName) {
|
|
351
|
+
shaka.log.error(
|
|
352
|
+
`XML tag name does not match expected "${expectedRootElemName}":`,
|
|
353
|
+
xml.documentElement.tagName);
|
|
336
354
|
return null;
|
|
337
|
-
}
|
|
355
|
+
}
|
|
338
356
|
|
|
339
357
|
return rootElem;
|
|
340
358
|
}
|
|
@@ -352,6 +370,7 @@ shaka.util.XmlUtils = class {
|
|
|
352
370
|
const string = shaka.util.StringUtils.fromUTF8(data);
|
|
353
371
|
return shaka.util.XmlUtils.parseXmlString(string, expectedRootElemName);
|
|
354
372
|
} catch (exception) {
|
|
373
|
+
shaka.log.error('parseXmlString threw!', exception);
|
|
355
374
|
return null;
|
|
356
375
|
}
|
|
357
376
|
}
|
package/package.json
CHANGED
package/roadmap.md
CHANGED
|
@@ -8,49 +8,51 @@ CHANGELOG.md.
|
|
|
8
8
|
The goals of future milestones are fluid until we begin that development cycle,
|
|
9
9
|
so the exact milestone for future features is not pre-determined.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
- HLS performance improvements
|
|
13
|
-
https://github.com/google/shaka-player/issues/3363
|
|
14
|
-
- HLS interstitial support
|
|
15
|
-
https://github.com/google/shaka-player/issues/3364
|
|
16
|
-
- Integration with Google Video ML/Cloud AI
|
|
11
|
+
Priority features up next:
|
|
17
12
|
- Support containerless formats
|
|
18
13
|
https://github.com/google/shaka-player/issues/2337
|
|
14
|
+
- Preload API
|
|
15
|
+
https://github.com/google/shaka-player/issues/880
|
|
16
|
+
- Codec-switching and order preference
|
|
17
|
+
https://github.com/google/shaka-player/issues/1528
|
|
18
|
+
https://github.com/google/shaka-player/issues/2179
|
|
19
|
+
|
|
20
|
+
Candidate features for future release cycles:
|
|
21
|
+
- HLS interstitial support
|
|
22
|
+
https://github.com/google/shaka-player/issues/3364
|
|
19
23
|
- Support ID3 tags in mp4
|
|
20
24
|
https://github.com/google/shaka-player/issues/3351
|
|
21
25
|
- MSE support for FairPlay
|
|
22
26
|
https://github.com/google/shaka-player/issues/3346
|
|
23
|
-
- Codec-switching and order preference
|
|
24
|
-
https://github.com/google/shaka-player/issues/1528
|
|
25
|
-
https://github.com/google/shaka-player/issues/2179
|
|
26
|
-
- Configurable key-system priority
|
|
27
|
-
https://github.com/google/shaka-player/issues/3002
|
|
28
|
-
- Preload API
|
|
29
|
-
https://github.com/google/shaka-player/issues/880
|
|
30
|
-
- Thumbnail tracks
|
|
31
|
-
DASH: https://github.com/google/shaka-player/issues/559
|
|
32
|
-
HLS: https://github.com/google/shaka-player/issues/2429
|
|
33
27
|
- Smaller, more modular binary
|
|
34
28
|
- Official TypeScript defs, generated from source
|
|
35
29
|
https://github.com/google/shaka-player/issues/1030
|
|
30
|
+
- Shaka Analytics Component and an integration with BigQuery Analytics
|
|
31
|
+
https://github.com/google/shaka-player/issues/3359
|
|
32
|
+
- Integration with Google Video ML/Cloud AI
|
|
36
33
|
|
|
37
|
-
v3.3 - 2021 Q3
|
|
34
|
+
v3.3 - 2021 Q3 or Q4
|
|
38
35
|
- Background fetch for offline storage
|
|
39
36
|
https://github.com/google/shaka-player/issues/879
|
|
40
|
-
-
|
|
41
|
-
https://github.com/google/shaka-player/issues/
|
|
37
|
+
- HLS performance improvements
|
|
38
|
+
https://github.com/google/shaka-player/issues/3363
|
|
42
39
|
|
|
43
|
-
|
|
40
|
+
=====
|
|
41
|
+
|
|
42
|
+
v3.2 - 2021 Q3
|
|
44
43
|
- MediaCapabilities to make performance-based decisions
|
|
45
44
|
https://github.com/google/shaka-player/issues/1391
|
|
45
|
+
- Configurable key-system priority
|
|
46
|
+
https://github.com/google/shaka-player/issues/3002
|
|
46
47
|
|
|
47
48
|
v3.1 - 2021 Q2
|
|
48
49
|
- Low-latency live (LL-HLS, LL-DASH)
|
|
49
50
|
https://github.com/google/shaka-player/issues/1525
|
|
50
51
|
- Own CEA parser, use mux.js only for TS
|
|
51
52
|
https://github.com/google/shaka-player/issues/2648
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
- Thumbnail tracks
|
|
54
|
+
DASH: https://github.com/google/shaka-player/issues/559
|
|
55
|
+
HLS: https://github.com/google/shaka-player/issues/2429
|
|
54
56
|
|
|
55
57
|
v3.0 - 2020 Q2
|
|
56
58
|
- Code health improvements
|
|
@@ -32,6 +32,7 @@ goog.require('shaka.offline.OfflineManifestParser');
|
|
|
32
32
|
goog.require('shaka.offline.OfflineScheme');
|
|
33
33
|
goog.require('shaka.offline.Storage');
|
|
34
34
|
goog.require('shaka.offline.indexeddb.StorageMechanism');
|
|
35
|
+
goog.require('shaka.polyfill.Aria');
|
|
35
36
|
goog.require('shaka.polyfill.EncryptionScheme');
|
|
36
37
|
goog.require('shaka.polyfill.Fullscreen');
|
|
37
38
|
goog.require('shaka.polyfill.MathRound');
|
|
@@ -43,6 +44,7 @@ goog.require('shaka.polyfill.PatchedMediaKeysMs');
|
|
|
43
44
|
goog.require('shaka.polyfill.PatchedMediaKeysNop');
|
|
44
45
|
goog.require('shaka.polyfill.PatchedMediaKeysWebkit');
|
|
45
46
|
goog.require('shaka.polyfill.PiPWebkit');
|
|
47
|
+
goog.require('shaka.polyfill.RandomUUID');
|
|
46
48
|
goog.require('shaka.polyfill.VTTCue');
|
|
47
49
|
goog.require('shaka.polyfill.VideoPlayPromise');
|
|
48
50
|
goog.require('shaka.polyfill.VideoPlaybackQuality');
|
|
@@ -69,6 +71,7 @@ goog.require('shaka.ui.AdPosition');
|
|
|
69
71
|
goog.require('shaka.ui.AirPlayButton');
|
|
70
72
|
goog.require('shaka.ui.BigPlayButton');
|
|
71
73
|
goog.require('shaka.ui.CastButton');
|
|
74
|
+
goog.require('shaka.ui.ContextMenu');
|
|
72
75
|
goog.require('shaka.ui.Element');
|
|
73
76
|
goog.require('shaka.ui.FastForwardButton');
|
|
74
77
|
goog.require('shaka.ui.FullscreenButton');
|
|
@@ -84,6 +87,7 @@ goog.require('shaka.ui.RewindButton');
|
|
|
84
87
|
goog.require('shaka.ui.SkipAdButton');
|
|
85
88
|
goog.require('shaka.ui.SmallPlayButton');
|
|
86
89
|
goog.require('shaka.ui.Spacer');
|
|
90
|
+
goog.require('shaka.ui.StatisticsButton');
|
|
87
91
|
goog.require('shaka.ui.TextSelection');
|
|
88
92
|
goog.require('shaka.ui.VolumeBar');
|
|
89
93
|
goog.require('shaka.util.Dom');
|
|
@@ -27,6 +27,7 @@ describe('CastUtils', () => {
|
|
|
27
27
|
'getAdManager', // Handled specially
|
|
28
28
|
'getSharedConfiguration', // Handled specially
|
|
29
29
|
'getNetworkingEngine', // Handled specially
|
|
30
|
+
'getDrmEngine', // Handled specially
|
|
30
31
|
'getMediaElement', // Handled specially
|
|
31
32
|
'setMaxHardwareResolution',
|
|
32
33
|
'destroy', // Should use CastProxy.destroy instead
|
|
@@ -19,39 +19,39 @@ describe('Cea708Service', () => {
|
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Hide window (2 bytes), with a bitmap provided to indicate all windows.
|
|
22
|
-
* @type {!Array
|
|
22
|
+
* @type {!Array<number>}
|
|
23
23
|
*/
|
|
24
24
|
const hideWindow = [0x8a, 0xff];
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* Define window (7 bytes), defines window #0 to be a visible window
|
|
28
28
|
* with 32 rows and 32 columns. (We specify 31 for each since decoder adds 1).
|
|
29
|
-
* @type {!Array
|
|
29
|
+
* @type {!Array<number>}
|
|
30
30
|
*/
|
|
31
31
|
const defineWindow = [
|
|
32
32
|
0x98, 0x38, 0x00, 0x00, 0x1f, 0x1f, 0x00,
|
|
33
33
|
];
|
|
34
34
|
|
|
35
|
-
/** @type {
|
|
35
|
+
/** @type {number} */
|
|
36
36
|
const startTime = 1;
|
|
37
37
|
|
|
38
|
-
/** @type {
|
|
38
|
+
/** @type {number} */
|
|
39
39
|
const endTime = 2;
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* We arbitrarily pick service 1 for all of these tests.
|
|
43
|
-
* @type {
|
|
43
|
+
* @type {number}
|
|
44
44
|
*/
|
|
45
45
|
const serviceNumber = 1;
|
|
46
46
|
|
|
47
|
-
/** @type {
|
|
47
|
+
/** @type {string} */
|
|
48
48
|
const stream = `svc${serviceNumber}`;
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
51
|
* Takes in a array of bytes and a presentation timestamp (in seconds),
|
|
52
52
|
* and converts it into a CEA-708 DTVCC Packet.
|
|
53
|
-
* @param {!Array
|
|
54
|
-
* @param {
|
|
53
|
+
* @param {!Array<number>} bytes
|
|
54
|
+
* @param {number} pts
|
|
55
55
|
*/
|
|
56
56
|
const createCea708PacketFromBytes = (bytes, pts) => {
|
|
57
57
|
const cea708Bytes = bytes.map((code, i) => {
|
|
@@ -15,22 +15,22 @@ describe('Cea708Window', () => {
|
|
|
15
15
|
/** @type {!shaka.cea.Cea708Window} */
|
|
16
16
|
let window;
|
|
17
17
|
|
|
18
|
-
/** @type {
|
|
18
|
+
/** @type {number} */
|
|
19
19
|
const serviceNumber = 1; // We will arbitrarily pick service 1 for all tests.
|
|
20
20
|
|
|
21
|
-
/** @type {
|
|
21
|
+
/** @type {string} */
|
|
22
22
|
const stream = `svc${serviceNumber}`;
|
|
23
23
|
|
|
24
|
-
/** @type {
|
|
24
|
+
/** @type {number} */
|
|
25
25
|
const rowCount = 10;
|
|
26
26
|
|
|
27
|
-
/** @type {
|
|
27
|
+
/** @type {number} */
|
|
28
28
|
const colCount = 32;
|
|
29
29
|
|
|
30
|
-
/** @type {
|
|
30
|
+
/** @type {number} */
|
|
31
31
|
const startTime = 1;
|
|
32
32
|
|
|
33
|
-
/** @type {
|
|
33
|
+
/** @type {number} */
|
|
34
34
|
const endTime = 2;
|
|
35
35
|
|
|
36
36
|
beforeEach(() => {
|
|
@@ -11,10 +11,10 @@ describe('DtvccPacketBuilder', () => {
|
|
|
11
11
|
/** @type {!shaka.cea.DtvccPacketBuilder} */
|
|
12
12
|
let dtvccPacketBuilder;
|
|
13
13
|
|
|
14
|
-
/** @type {
|
|
14
|
+
/** @type {number} */
|
|
15
15
|
const DTVCC_PACKET_START = shaka.cea.DtvccPacketBuilder.DTVCC_PACKET_START;
|
|
16
16
|
|
|
17
|
-
/** @type {
|
|
17
|
+
/** @type {number} */
|
|
18
18
|
const DTVCC_PACKET_DATA = shaka.cea.DtvccPacketBuilder.DTVCC_PACKET_DATA;
|
|
19
19
|
|
|
20
20
|
beforeEach(() => {
|
|
@@ -42,6 +42,8 @@ describe('DashParser ContentProtection', () => {
|
|
|
42
42
|
|
|
43
43
|
const playerInterface = {
|
|
44
44
|
networkingEngine: netEngine,
|
|
45
|
+
modifyManifestRequest: (request, manifestInfo) => {},
|
|
46
|
+
modifySegmentRequest: (request, segmentInfo) => {},
|
|
45
47
|
filter: (manifest) => Promise.resolve(),
|
|
46
48
|
makeTextStreamsForClosedCaptions: (manifest) => {},
|
|
47
49
|
onTimelineRegionAdded: fail, // Should not have any EventStream elements.
|