shaka-player 3.1.5 → 3.2.3
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/CHANGELOG.md +129 -6
- package/README.md +4 -4
- package/build/types/polyfill +1 -0
- package/demo/common/asset.js +9 -7
- package/demo/common/assets.js +10 -1
- package/demo/common/message_ids.js +2 -1
- package/demo/config.js +5 -2
- package/demo/index.html +1 -1
- package/demo/locales/en.json +2 -1
- package/demo/locales/source.json +8 -4
- package/demo/main.js +2 -1
- package/dist/demo.compiled.debug.js +14 -14
- package/dist/demo.compiled.debug.map +2 -2
- package/dist/demo.compiled.js +14 -14
- package/dist/demo.compiled.map +2 -2
- package/dist/deps.js +21 -20
- package/dist/locales.js +30 -30
- package/dist/receiver.compiled.debug.js +8 -8
- package/dist/receiver.compiled.debug.map +2 -2
- package/dist/receiver.compiled.js +8 -8
- package/dist/receiver.compiled.map +2 -2
- package/dist/shaka-player.compiled.d.ts +63 -10
- package/dist/shaka-player.compiled.debug.d.ts +63 -10
- package/dist/shaka-player.compiled.debug.externs.js +786 -716
- package/dist/shaka-player.compiled.debug.js +563 -534
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +786 -716
- package/dist/shaka-player.compiled.js +820 -809
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +63 -10
- package/dist/shaka-player.ui.debug.d.ts +63 -10
- package/dist/shaka-player.ui.debug.externs.js +542 -472
- package/dist/shaka-player.ui.debug.js +594 -566
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +542 -472
- package/dist/shaka-player.ui.js +938 -927
- package/dist/shaka-player.ui.map +4 -4
- package/docs/tutorials/ui.md +5 -5
- package/externs/aria.js +6 -0
- package/externs/shaka/ads.js +24 -1
- package/externs/shaka/manifest.js +6 -1
- package/externs/shaka/offline.js +5 -0
- package/externs/shaka/player.js +61 -9
- package/externs/shaka/text.js +10 -10
- package/externs/texttrack.js +3 -0
- package/lib/ads/ad_manager.js +16 -15
- package/lib/ads/client_side_ad_manager.js +6 -2
- package/lib/ads/server_side_ad_manager.js +19 -2
- package/lib/cast/cast_proxy.js +8 -0
- package/lib/cast/cast_utils.js +6 -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 +5 -0
- package/lib/hls/hls_parser.js +159 -12
- package/lib/media/closed_caption_parser.js +1 -2
- package/lib/media/drm_engine.js +162 -192
- package/lib/media/segment_index.js +4 -1
- package/lib/media/segment_reference.js +37 -2
- package/lib/media/streaming_engine.js +6 -6
- package/lib/net/networking_engine.js +1 -0
- package/lib/offline/download_manager.js +1 -2
- 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 +3 -1
- package/lib/offline/storage.js +12 -14
- package/lib/player.js +426 -149
- package/lib/polyfill/aria.js +82 -0
- package/lib/routing/walker.js +2 -3
- package/lib/text/srt_text_parser.js +4 -4
- package/lib/text/text_engine.js +2 -2
- package/lib/text/vtt_text_parser.js +2 -2
- package/lib/text/web_vtt_generator.js +55 -12
- package/lib/util/error.js +6 -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/player_configuration.js +13 -1
- package/lib/util/stream_utils.js +168 -88
- package/lib/util/xml_utils.js +31 -12
- package/package.json +1 -1
- package/roadmap.md +24 -22
- package/shaka-player.uncompiled.js +1 -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_manifest_unit.js +43 -1
- package/test/hls/hls_parser_unit.js +250 -0
- package/test/media/drm_engine_integration.js +86 -12
- package/test/media/drm_engine_unit.js +310 -450
- package/test/offline/manifest_convert_unit.js +2 -0
- package/test/offline/storage_integration.js +9 -19
- package/test/player_integration.js +85 -0
- package/test/player_src_equals_integration.js +85 -0
- package/test/player_unit.js +25 -37
- package/test/test/assets/chapters.srt +11 -0
- package/test/test/assets/chapters.vtt +10 -0
- package/test/test/assets/chapters2.vtt +10 -0
- package/test/test/util/cea_utils.js +12 -12
- package/test/test/util/fake_ad_manager.js +7 -0
- package/test/test/util/manifest_generator.js +2 -0
- package/test/test/util/manifest_parser_util.js +3 -1
- package/test/text/web_vtt_generator_unit.js +81 -7
- package/test/util/stream_utils_unit.js +118 -10
- package/ui/airplay_button.js +1 -1
- package/ui/audio_language_selection.js +2 -5
- package/ui/cast_button.js +4 -6
- package/ui/constants.js +0 -3
- package/ui/fast_forward_button.js +2 -3
- package/ui/fullscreen_button.js +1 -3
- package/ui/language_utils.js +1 -1
- package/ui/loop_button.js +1 -3
- package/ui/mute_button.js +1 -3
- package/ui/overflow_menu.js +2 -3
- package/ui/pip_button.js +5 -7
- package/ui/playback_rate_selection.js +3 -6
- package/ui/presentation_time.js +1 -3
- package/ui/resolution_selection.js +4 -7
- package/ui/rewind_button.js +2 -3
- package/ui/seek_bar.js +2 -4
- package/ui/spacer.js +1 -1
- package/ui/text_selection.js +8 -11
- package/ui/ui_utils.js +1 -1
- package/ui/volume_bar.js +1 -3
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.
|
|
@@ -398,46 +484,6 @@ shaka.util.StreamUtils = class {
|
|
|
398
484
|
}
|
|
399
485
|
|
|
400
486
|
|
|
401
|
-
/**
|
|
402
|
-
* Filter the variants in the |manifest| to only include those that are
|
|
403
|
-
* supported by media source.
|
|
404
|
-
* TODO: remove once MediaCap implementations are done.
|
|
405
|
-
* @param {shaka.extern.Manifest} manifest
|
|
406
|
-
*/
|
|
407
|
-
static filterManifestByMediaSource(manifest) {
|
|
408
|
-
const StreamUtils = shaka.util.StreamUtils;
|
|
409
|
-
|
|
410
|
-
manifest.variants = manifest.variants.filter((variant) => {
|
|
411
|
-
const audio = variant.audio;
|
|
412
|
-
const video = variant.video;
|
|
413
|
-
|
|
414
|
-
if (audio && !shaka.media.MediaSourceEngine.isStreamSupported(audio)) {
|
|
415
|
-
shaka.log.debug('Dropping variant - audio not compatible with platform',
|
|
416
|
-
StreamUtils.getStreamSummaryString_(audio));
|
|
417
|
-
return false;
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
if (video && !shaka.media.MediaSourceEngine.isStreamSupported(video)) {
|
|
421
|
-
shaka.log.debug('Dropping variant - video not compatible with platform',
|
|
422
|
-
StreamUtils.getStreamSummaryString_(video));
|
|
423
|
-
return false;
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
// See: https://github.com/google/shaka-player/issues/3380
|
|
427
|
-
if (shaka.util.Platform.isXboxOne() && video &&
|
|
428
|
-
((video.width && video.width > 1920) ||
|
|
429
|
-
(video.height && video.height > 1080)) &&
|
|
430
|
-
video.codecs.includes('avc1.')) {
|
|
431
|
-
shaka.log.debug('Dropping variant - video not compatible with platform',
|
|
432
|
-
StreamUtils.getStreamSummaryString_(video));
|
|
433
|
-
return false;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
return true;
|
|
437
|
-
});
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
|
|
441
487
|
/**
|
|
442
488
|
* Get the decodingInfo results of the variants via MediaCapabilities.
|
|
443
489
|
* This should be called after the DrmEngine is created and configured, and
|
|
@@ -994,6 +1040,31 @@ shaka.util.StreamUtils = class {
|
|
|
994
1040
|
static imageStreamToTrack(stream) {
|
|
995
1041
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
996
1042
|
|
|
1043
|
+
let width = stream.width || null;
|
|
1044
|
+
let height = stream.height || null;
|
|
1045
|
+
|
|
1046
|
+
// The stream width and height represent the size of the entire thumbnail
|
|
1047
|
+
// sheet, so divide by the layout.
|
|
1048
|
+
let reference = null;
|
|
1049
|
+
// Note: segmentIndex is built by default for HLS, but not for DASH, but
|
|
1050
|
+
// in DASH this information comes at the stream level and not at the
|
|
1051
|
+
// segment level.
|
|
1052
|
+
if (stream.segmentIndex) {
|
|
1053
|
+
reference = stream.segmentIndex.get(0);
|
|
1054
|
+
}
|
|
1055
|
+
let layout = stream.tilesLayout;
|
|
1056
|
+
if (reference) {
|
|
1057
|
+
layout = reference.getTilesLayout() || layout;
|
|
1058
|
+
}
|
|
1059
|
+
if (layout && width != null) {
|
|
1060
|
+
width /= Number(layout.split('x')[0]);
|
|
1061
|
+
}
|
|
1062
|
+
if (layout && height != null) {
|
|
1063
|
+
height /= Number(layout.split('x')[1]);
|
|
1064
|
+
}
|
|
1065
|
+
// TODO: What happens if there are multiple grids, with different
|
|
1066
|
+
// layout sizes, inside this image stream?
|
|
1067
|
+
|
|
997
1068
|
/** @type {shaka.extern.Track} */
|
|
998
1069
|
const track = {
|
|
999
1070
|
id: stream.id,
|
|
@@ -1003,8 +1074,8 @@ shaka.util.StreamUtils = class {
|
|
|
1003
1074
|
language: '',
|
|
1004
1075
|
label: null,
|
|
1005
1076
|
kind: null,
|
|
1006
|
-
width
|
|
1007
|
-
height
|
|
1077
|
+
width,
|
|
1078
|
+
height,
|
|
1008
1079
|
frameRate: null,
|
|
1009
1080
|
pixelAspectRatio: null,
|
|
1010
1081
|
hdr: null,
|
|
@@ -1021,7 +1092,7 @@ shaka.util.StreamUtils = class {
|
|
|
1021
1092
|
channelsCount: null,
|
|
1022
1093
|
audioSamplingRate: null,
|
|
1023
1094
|
spatialAudio: false,
|
|
1024
|
-
tilesLayout:
|
|
1095
|
+
tilesLayout: layout || null,
|
|
1025
1096
|
audioBandwidth: null,
|
|
1026
1097
|
videoBandwidth: null,
|
|
1027
1098
|
originalVideoId: null,
|
|
@@ -1422,3 +1493,12 @@ shaka.util.StreamUtils = class {
|
|
|
1422
1493
|
|
|
1423
1494
|
/** @private {number} */
|
|
1424
1495
|
shaka.util.StreamUtils.nextTrackId_ = 0;
|
|
1496
|
+
|
|
1497
|
+
/**
|
|
1498
|
+
* @enum {string}
|
|
1499
|
+
*/
|
|
1500
|
+
shaka.util.StreamUtils.DecodingAttributes = {
|
|
1501
|
+
SMOOTH: 'smooth',
|
|
1502
|
+
POWER: 'powerEfficient',
|
|
1503
|
+
BANDWIDTH: 'bandwidth',
|
|
1504
|
+
};
|
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
|
|
|
@@ -331,29 +332,46 @@ shaka.util.XmlUtils = class {
|
|
|
331
332
|
|
|
332
333
|
|
|
333
334
|
/**
|
|
334
|
-
* Parse a string and return the resulting root element if
|
|
335
|
-
*
|
|
335
|
+
* Parse a string and return the resulting root element if it was valid XML.
|
|
336
|
+
*
|
|
336
337
|
* @param {string} xmlString
|
|
337
338
|
* @param {string} expectedRootElemName
|
|
338
339
|
* @return {Element}
|
|
339
340
|
*/
|
|
340
341
|
static parseXmlString(xmlString, expectedRootElemName) {
|
|
341
342
|
const parser = new DOMParser();
|
|
342
|
-
let rootElem = null;
|
|
343
343
|
let xml = null;
|
|
344
344
|
try {
|
|
345
345
|
xml = parser.parseFromString(xmlString, 'text/xml');
|
|
346
|
-
} catch (exception) {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
// same type as the element linking.
|
|
350
|
-
if (xml.documentElement.tagName == expectedRootElemName) {
|
|
351
|
-
rootElem = xml.documentElement;
|
|
352
|
-
}
|
|
346
|
+
} catch (exception) {
|
|
347
|
+
shaka.log.error('XML parsing exception:', exception);
|
|
348
|
+
return null;
|
|
353
349
|
}
|
|
354
|
-
|
|
350
|
+
|
|
351
|
+
// According to MDN, parseFromString never returns null.
|
|
352
|
+
goog.asserts.assert(xml, 'Parsed XML document cannot be null!');
|
|
353
|
+
|
|
354
|
+
// Check for empty documents.
|
|
355
|
+
const rootElem = xml.documentElement;
|
|
356
|
+
if (!rootElem) {
|
|
357
|
+
shaka.log.error('XML document was empty!');
|
|
355
358
|
return null;
|
|
356
|
-
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Check for parser errors.
|
|
362
|
+
const parserErrorElements = rootElem.getElementsByTagName('parsererror');
|
|
363
|
+
if (parserErrorElements.length) {
|
|
364
|
+
shaka.log.error('XML parser error found:', parserErrorElements[0]);
|
|
365
|
+
return null;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// The top-level element in the loaded XML should have the name we expect.
|
|
369
|
+
if (xml.documentElement.tagName != expectedRootElemName) {
|
|
370
|
+
shaka.log.error(
|
|
371
|
+
`XML tag name does not match expected "${expectedRootElemName}":`,
|
|
372
|
+
xml.documentElement.tagName);
|
|
373
|
+
return null;
|
|
374
|
+
}
|
|
357
375
|
|
|
358
376
|
return rootElem;
|
|
359
377
|
}
|
|
@@ -371,6 +389,7 @@ shaka.util.XmlUtils = class {
|
|
|
371
389
|
const string = shaka.util.StringUtils.fromUTF8(data);
|
|
372
390
|
return shaka.util.XmlUtils.parseXmlString(string, expectedRootElemName);
|
|
373
391
|
} catch (exception) {
|
|
392
|
+
shaka.log.error('parseXmlString threw!', exception);
|
|
374
393
|
return null;
|
|
375
394
|
}
|
|
376
395
|
}
|
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');
|
|
@@ -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(() => {
|