shaka-player 4.5.0 → 4.6.1
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/AUTHORS +2 -0
- package/CHANGELOG.md +109 -0
- package/CODE_OF_CONDUCT.md +1 -1
- package/CONTRIBUTORS +2 -0
- package/README.md +38 -32
- package/demo/common/asset.js +11 -17
- package/demo/common/assets.js +117 -11
- package/demo/config.js +28 -1
- package/demo/custom.js +52 -38
- package/demo/main.js +11 -3
- package/demo/search.js +7 -0
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +133 -124
- package/dist/demo.compiled.debug.map +3 -3
- package/dist/demo.compiled.js +133 -124
- package/dist/demo.compiled.map +3 -3
- package/dist/deps.js +20 -18
- package/dist/locales.js +34 -30
- package/dist/receiver.compiled.debug.js +58 -50
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +58 -50
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.d.ts +440 -390
- package/dist/shaka-player.compiled.debug.d.ts +440 -390
- package/dist/shaka-player.compiled.debug.externs.js +162 -77
- package/dist/shaka-player.compiled.debug.js +789 -738
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +162 -77
- package/dist/shaka-player.compiled.js +1147 -1113
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +491 -437
- package/dist/shaka-player.ui.debug.d.ts +491 -437
- package/dist/shaka-player.ui.debug.externs.js +167 -77
- package/dist/shaka-player.ui.debug.js +857 -791
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +167 -77
- package/dist/shaka-player.ui.js +1359 -1314
- package/dist/shaka-player.ui.map +4 -4
- package/docs/tutorials/ad_monetization.md +54 -0
- package/docs/tutorials/basic-usage.md +2 -1
- package/docs/tutorials/errors.md +2 -1
- package/docs/tutorials/offline.md +10 -8
- package/docs/tutorials/plugins.md +5 -0
- package/docs/tutorials/ui-customization.md +13 -0
- package/docs/tutorials/ui.md +2 -1
- package/docs/tutorials/upgrade.md +3 -0
- package/externs/managedmediasource.js +24 -0
- package/externs/shaka/abr_manager.js +6 -2
- package/externs/shaka/cea.js +7 -0
- package/externs/shaka/codecs.js +5 -3
- package/externs/shaka/manifest.js +21 -5
- package/externs/shaka/manifest_parser.js +17 -0
- package/externs/shaka/net.js +2 -2
- package/externs/shaka/offline.js +9 -2
- package/externs/shaka/player.js +53 -7
- package/externs/shaka/text.js +3 -1
- package/externs/shaka/transmuxer.js +1 -1
- package/lib/abr/simple_abr_manager.js +25 -8
- package/lib/ads/media_tailor_ad_manager.js +14 -3
- package/lib/cast/cast_receiver.js +1 -1
- package/lib/cea/cea_decoder.js +28 -0
- package/lib/cea/dummy_caption_decoder.js +5 -0
- package/lib/dash/dash_parser.js +251 -84
- package/lib/dash/mpd_utils.js +52 -31
- package/lib/dash/segment_base.js +4 -5
- package/lib/dash/segment_list.js +5 -4
- package/lib/dash/segment_template.js +92 -29
- package/lib/hls/hls_classes.js +28 -43
- package/lib/hls/hls_parser.js +770 -652
- package/lib/hls/hls_utils.js +64 -5
- package/lib/hls/manifest_text_parser.js +7 -11
- package/lib/media/adaptation_set.js +20 -13
- package/lib/media/adaptation_set_criteria.js +70 -18
- package/lib/media/closed_caption_parser.js +13 -0
- package/lib/media/content_workarounds.js +6 -0
- package/lib/media/drm_engine.js +8 -13
- package/lib/media/manifest_parser.js +8 -113
- package/lib/media/media_source_capabilities.js +10 -3
- package/lib/media/media_source_engine.js +75 -21
- package/lib/media/play_rate_controller.js +8 -38
- package/lib/media/presentation_timeline.js +7 -1
- package/lib/media/quality_observer.js +1 -1
- package/lib/media/segment_index.js +5 -5
- package/lib/media/segment_prefetch.js +92 -24
- package/lib/media/segment_reference.js +67 -1
- package/lib/media/segment_utils.js +343 -0
- package/lib/media/stall_detector.js +0 -3
- package/lib/media/streaming_engine.js +72 -44
- package/lib/mss/mss_parser.js +18 -2
- package/lib/net/networking_engine.js +66 -12
- package/lib/net/networking_utils.js +95 -0
- package/lib/offline/indexeddb/v1_storage_cell.js +2 -0
- package/lib/offline/indexeddb/v2_storage_cell.js +2 -0
- package/lib/offline/manifest_converter.js +2 -0
- package/lib/offline/offline_manifest_parser.js +10 -0
- package/lib/offline/storage.js +11 -7
- package/lib/player.js +998 -1503
- package/lib/polyfill/mediasource.js +22 -1
- package/lib/text/mp4_ttml_parser.js +2 -2
- package/lib/text/srt_text_parser.js +2 -2
- package/lib/text/stub_text_displayer.js +51 -0
- package/lib/text/text_engine.js +3 -2
- package/lib/text/ttml_text_parser.js +28 -5
- package/lib/text/ui_text_displayer.js +4 -0
- package/lib/text/vtt_text_parser.js +7 -2
- package/lib/transmuxer/aac_transmuxer.js +1 -1
- package/lib/transmuxer/ac3_transmuxer.js +1 -1
- package/lib/transmuxer/ec3_transmuxer.js +1 -1
- package/lib/transmuxer/h264.js +5 -4
- package/lib/transmuxer/h265.js +5 -4
- package/lib/transmuxer/mp3_transmuxer.js +1 -1
- package/lib/transmuxer/mpeg_ts_transmuxer.js +1 -1
- package/lib/transmuxer/mss_transmuxer.js +1 -1
- package/lib/transmuxer/ts_transmuxer.js +33 -13
- package/lib/util/buffer_utils.js +26 -4
- package/lib/util/content_steering_manager.js +358 -0
- package/lib/util/error.js +2 -6
- package/lib/util/fairplay_utils.js +1 -1
- package/lib/util/fake_event.js +5 -1
- package/lib/util/id3_utils.js +50 -1
- package/lib/util/manifest_parser_utils.js +12 -8
- package/lib/util/mp4_generator.js +2 -4
- package/lib/util/mutex.js +59 -0
- package/lib/util/object_utils.js +1 -1
- package/lib/util/periods.js +154 -179
- package/lib/util/platform.js +4 -3
- package/lib/util/player_configuration.js +35 -6
- package/lib/util/stream_utils.js +105 -98
- package/lib/util/ts_parser.js +124 -73
- package/lib/util/uint8array_utils.js +5 -1
- package/lib/util/xml_utils.js +5 -0
- package/maintained-branches.md +2 -2
- package/package.json +1 -1
- package/roadmap.md +15 -5
- package/shaka-player.uncompiled.js +0 -1
- package/test/abr/simple_abr_manager_unit.js +33 -33
- package/test/ads/ad_manager_unit.js +3 -2
- package/test/cast/cast_receiver_integration.js +3 -4
- package/test/cast/cast_utils_unit.js +2 -0
- package/test/cea/cea_decoder_unit.js +7 -0
- package/test/codec_switching/codec_switching_integration.js +2 -1
- package/test/dash/dash_parser_integration.js +2 -1
- package/test/dash/dash_parser_live_unit.js +0 -19
- package/test/dash/dash_parser_manifest_unit.js +494 -2
- package/test/dash/mpd_utils_unit.js +61 -30
- package/test/hls/hls_live_unit.js +12 -3
- package/test/hls/hls_parser_unit.js +417 -27
- package/test/hls/manifest_text_parser_unit.js +32 -99
- package/test/media/adaptation_set_criteria_unit.js +172 -21
- package/test/media/adaptation_set_unit.js +1 -0
- package/test/media/content_workarounds_unit.js +1 -1
- package/test/media/drm_engine_unit.js +3 -3
- package/test/media/media_source_engine_unit.js +1 -1
- package/test/media/play_rate_controller_unit.js +0 -48
- package/test/media/segment_index_unit.js +2 -1
- package/test/mss/mss_player_integration.js +3 -2
- package/test/net/networking_engine_unit.js +3 -3
- package/test/{media/manifest_parser_unit.js → net/networking_utils_unit.js} +2 -2
- package/test/offline/manifest_convert_unit.js +9 -0
- package/test/offline/offline_integration.js +2 -1
- package/test/offline/storage_integration.js +21 -9
- package/test/player_external.js +4 -2
- package/test/player_integration.js +15 -4
- package/test/player_load_graph_integration.js +47 -151
- package/test/player_src_equals_external.js +1 -0
- package/test/player_src_equals_integration.js +71 -4
- package/test/player_unit.js +80 -27
- package/test/test/util/fake_media_source_engine.js +5 -0
- package/test/test/util/fake_networking_engine.js +9 -1
- package/test/test/util/fake_segment_prefetch.js +3 -0
- package/test/test/util/manifest_generator.js +4 -0
- package/test/test/util/manifest_parser_util.js +14 -2
- package/test/test/util/offline_utils.js +1 -0
- package/test/test/util/simple_fakes.js +2 -2
- package/test/test/util/streaming_engine_util.js +3 -0
- package/test/test/util/test_scheme.js +6 -0
- package/test/test/util/ui_utils.js +4 -3
- package/test/text/mp4_ttml_parser_unit.js +4 -4
- package/test/text/srt_text_parser_unit.js +1 -1
- package/test/text/text_displayer_layout_unit.js +1 -1
- package/test/text/text_engine_unit.js +6 -0
- package/test/text/ttml_text_parser_unit.js +33 -2
- package/test/transmuxer/transmuxer_engine_integration.js +9 -0
- package/test/transmuxer/transmuxer_integration.js +33 -3
- package/test/ui/ad_ui_unit.js +2 -2
- package/test/ui/ui_customization_unit.js +17 -16
- package/test/ui/ui_integration.js +30 -20
- package/test/ui/ui_unit.js +25 -19
- package/test/util/buffer_utils_unit.js +1 -1
- package/test/util/content_steering_manager_unit.js +427 -0
- package/test/util/id3_utils_unit.js +52 -0
- package/test/util/stream_utils_unit.js +17 -113
- package/test/util/ts_parser_unit.js +3 -3
- package/third_party/closure-uri/uri.js +13 -1
- package/ui/audio_language_selection.js +9 -2
- package/ui/externs/ui.js +17 -2
- package/ui/language_utils.js +43 -8
- package/ui/less/range_elements.less +33 -0
- package/ui/locales/en.json +1 -0
- package/ui/locales/es-419.json +1 -0
- package/ui/locales/es.json +1 -0
- package/ui/locales/source.json +4 -0
- package/ui/localization.js +10 -0
- package/ui/remote_button.js +3 -1
- package/ui/resolution_selection.js +47 -10
- package/ui/seek_bar.js +296 -3
- package/ui/text_selection.js +2 -1
- package/ui/ui.js +6 -2
- package/lib/routing/node.js +0 -23
- package/lib/routing/payload.js +0 -47
- package/lib/routing/walker.js +0 -587
- package/test/routing/walker_unit.js +0 -505
package/lib/util/periods.js
CHANGED
|
@@ -103,6 +103,37 @@ shaka.util.PeriodCombiner = class {
|
|
|
103
103
|
return this.imageStreams_;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Returns an object that contains arrays of streams by type
|
|
108
|
+
* @param {!Array.<shaka.extern.Period>} periods
|
|
109
|
+
* @return {{
|
|
110
|
+
* audioStreamsPerPeriod: !Array.<!Array.<shaka.extern.Stream>>,
|
|
111
|
+
* videoStreamsPerPeriod: !Array.<!Array.<shaka.extern.Stream>>,
|
|
112
|
+
* textStreamsPerPeriod: !Array.<!Array.<shaka.extern.Stream>>,
|
|
113
|
+
* imageStreamsPerPeriod: !Array.<!Array.<shaka.extern.Stream>>
|
|
114
|
+
* }}
|
|
115
|
+
* @private
|
|
116
|
+
*/
|
|
117
|
+
getStreamsPerPeriod_(periods) {
|
|
118
|
+
const audioStreamsPerPeriod = [];
|
|
119
|
+
const videoStreamsPerPeriod = [];
|
|
120
|
+
const textStreamsPerPeriod = [];
|
|
121
|
+
const imageStreamsPerPeriod = [];
|
|
122
|
+
|
|
123
|
+
for (const period of periods) {
|
|
124
|
+
audioStreamsPerPeriod.push(period.audioStreams);
|
|
125
|
+
videoStreamsPerPeriod.push(period.videoStreams);
|
|
126
|
+
textStreamsPerPeriod.push(period.textStreams);
|
|
127
|
+
imageStreamsPerPeriod.push(period.imageStreams);
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
audioStreamsPerPeriod,
|
|
131
|
+
videoStreamsPerPeriod,
|
|
132
|
+
textStreamsPerPeriod,
|
|
133
|
+
imageStreamsPerPeriod,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
106
137
|
/**
|
|
107
138
|
* @param {!Array.<shaka.extern.Period>} periods
|
|
108
139
|
* @param {boolean} isDynamic
|
|
@@ -113,10 +144,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
113
144
|
async combinePeriods(periods, isDynamic) {
|
|
114
145
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
115
146
|
|
|
116
|
-
shaka.util.PeriodCombiner.
|
|
117
|
-
shaka.util.PeriodCombiner.filterOutVideoStreamDuplicates_(periods);
|
|
118
|
-
shaka.util.PeriodCombiner.filterOutTextStreamDuplicates_(periods);
|
|
119
|
-
shaka.util.PeriodCombiner.filterOutImageStreamDuplicates_(periods);
|
|
147
|
+
shaka.util.PeriodCombiner.filterOutDuplicates_(periods);
|
|
120
148
|
|
|
121
149
|
// Optimization: for single-period VOD, do nothing. This makes sure
|
|
122
150
|
// single-period DASH content will be 100% accurately represented in the
|
|
@@ -151,14 +179,12 @@ shaka.util.PeriodCombiner = class {
|
|
|
151
179
|
return;
|
|
152
180
|
}
|
|
153
181
|
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
const imageStreamsPerPeriod = periods.map(
|
|
161
|
-
(period) => period.imageStreams);
|
|
182
|
+
const {
|
|
183
|
+
audioStreamsPerPeriod,
|
|
184
|
+
videoStreamsPerPeriod,
|
|
185
|
+
textStreamsPerPeriod,
|
|
186
|
+
imageStreamsPerPeriod,
|
|
187
|
+
} = this.getStreamsPerPeriod_(periods);
|
|
162
188
|
|
|
163
189
|
// It's okay to have a period with no text or images, but our algorithm
|
|
164
190
|
// fails on any period without matching streams. So we add dummy streams
|
|
@@ -174,33 +200,32 @@ shaka.util.PeriodCombiner = class {
|
|
|
174
200
|
ContentType.IMAGE));
|
|
175
201
|
}
|
|
176
202
|
|
|
177
|
-
await
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
shaka.util.PeriodCombiner.concatenateStreams_);
|
|
203
|
+
await Promise.all([
|
|
204
|
+
shaka.util.PeriodCombiner.combine_(
|
|
205
|
+
this.audioStreams_,
|
|
206
|
+
audioStreamsPerPeriod,
|
|
207
|
+
firstNewPeriodIndex,
|
|
208
|
+
shaka.util.PeriodCombiner.cloneStream_,
|
|
209
|
+
shaka.util.PeriodCombiner.concatenateStreams_),
|
|
210
|
+
shaka.util.PeriodCombiner.combine_(
|
|
211
|
+
this.videoStreams_,
|
|
212
|
+
videoStreamsPerPeriod,
|
|
213
|
+
firstNewPeriodIndex,
|
|
214
|
+
shaka.util.PeriodCombiner.cloneStream_,
|
|
215
|
+
shaka.util.PeriodCombiner.concatenateStreams_),
|
|
216
|
+
shaka.util.PeriodCombiner.combine_(
|
|
217
|
+
this.textStreams_,
|
|
218
|
+
textStreamsPerPeriod,
|
|
219
|
+
firstNewPeriodIndex,
|
|
220
|
+
shaka.util.PeriodCombiner.cloneStream_,
|
|
221
|
+
shaka.util.PeriodCombiner.concatenateStreams_),
|
|
222
|
+
shaka.util.PeriodCombiner.combine_(
|
|
223
|
+
this.imageStreams_,
|
|
224
|
+
imageStreamsPerPeriod,
|
|
225
|
+
firstNewPeriodIndex,
|
|
226
|
+
shaka.util.PeriodCombiner.cloneStream_,
|
|
227
|
+
shaka.util.PeriodCombiner.concatenateStreams_),
|
|
228
|
+
]);
|
|
204
229
|
}
|
|
205
230
|
|
|
206
231
|
// Create variants for all audio/video combinations.
|
|
@@ -209,7 +234,8 @@ shaka.util.PeriodCombiner = class {
|
|
|
209
234
|
if (!this.videoStreams_.length || !this.audioStreams_.length) {
|
|
210
235
|
// For audio-only or video-only content, just give each stream its own
|
|
211
236
|
// variant.
|
|
212
|
-
const streams = this.videoStreams_.
|
|
237
|
+
const streams = this.videoStreams_.length ? this.videoStreams_ :
|
|
238
|
+
this.audioStreams_;
|
|
213
239
|
for (const stream of streams) {
|
|
214
240
|
const id = nextVariantId++;
|
|
215
241
|
variants.push({
|
|
@@ -262,141 +288,90 @@ shaka.util.PeriodCombiner = class {
|
|
|
262
288
|
}
|
|
263
289
|
|
|
264
290
|
/**
|
|
265
|
-
* @param {!Array
|
|
291
|
+
* @param {!Array<shaka.extern.Period>} periods
|
|
266
292
|
* @private
|
|
267
293
|
*/
|
|
268
|
-
static
|
|
269
|
-
const
|
|
270
|
-
// Two audio streams are considered to be duplicates of
|
|
271
|
-
// one another if their ids are different, but all the other
|
|
272
|
-
// information is the same.
|
|
273
|
-
for (const period of periods) {
|
|
274
|
-
const filteredAudios = [];
|
|
275
|
-
for (const a1 of period.audioStreams) {
|
|
276
|
-
let duplicate = false;
|
|
277
|
-
for (const a2 of filteredAudios) {
|
|
278
|
-
if (a1.id != a2.id &&
|
|
279
|
-
a1.channelsCount == a2.channelsCount &&
|
|
280
|
-
a1.language == a2.language &&
|
|
281
|
-
a1.bandwidth == a2.bandwidth &&
|
|
282
|
-
a1.label == a2.label &&
|
|
283
|
-
a1.codecs == a2.codecs &&
|
|
284
|
-
a1.mimeType == a2.mimeType &&
|
|
285
|
-
ArrayUtils.hasSameElements(a1.roles, a2.roles) &&
|
|
286
|
-
a1.audioSamplingRate == a2.audioSamplingRate &&
|
|
287
|
-
a1.primary == a2.primary) {
|
|
288
|
-
duplicate = true;
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
if (!duplicate) {
|
|
293
|
-
filteredAudios.push(a1);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
period.audioStreams = filteredAudios;
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* @param {!Array.<shaka.extern.Period>} periods
|
|
303
|
-
* @private
|
|
304
|
-
*/
|
|
305
|
-
static filterOutTextStreamDuplicates_(periods) {
|
|
306
|
-
const ArrayUtils = shaka.util.ArrayUtils;
|
|
307
|
-
// Two text streams are considered to be duplicates of
|
|
308
|
-
// one another if their ids are different, but all the other
|
|
309
|
-
// information is the same.
|
|
310
|
-
for (const period of periods) {
|
|
311
|
-
const filteredTexts = [];
|
|
312
|
-
for (const t1 of period.textStreams) {
|
|
313
|
-
let duplicate = false;
|
|
314
|
-
for (const t2 of filteredTexts) {
|
|
315
|
-
if (t1.id != t2.id &&
|
|
316
|
-
t1.language == t2.language &&
|
|
317
|
-
t1.label == t2.label &&
|
|
318
|
-
t1.codecs == t2.codecs &&
|
|
319
|
-
t1.mimeType == t2.mimeType &&
|
|
320
|
-
t1.bandwidth == t2.bandwidth &&
|
|
321
|
-
ArrayUtils.hasSameElements(t1.roles, t2.roles)) {
|
|
322
|
-
duplicate = true;
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
if (!duplicate) {
|
|
327
|
-
filteredTexts.push(t1);
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
period.textStreams = filteredTexts;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/**
|
|
336
|
-
* @param {!Array.<shaka.extern.Period>} periods
|
|
337
|
-
* @private
|
|
338
|
-
*/
|
|
339
|
-
static filterOutVideoStreamDuplicates_(periods) {
|
|
294
|
+
static filterOutDuplicates_(periods) {
|
|
295
|
+
const PeriodCombiner = shaka.util.PeriodCombiner;
|
|
340
296
|
const ArrayUtils = shaka.util.ArrayUtils;
|
|
341
297
|
const MapUtils = shaka.util.MapUtils;
|
|
342
|
-
|
|
343
|
-
// one another if their ids are different, but all the other
|
|
344
|
-
// information is the same.
|
|
298
|
+
|
|
345
299
|
for (const period of periods) {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
v1.
|
|
353
|
-
v1.
|
|
354
|
-
v1.
|
|
355
|
-
v1.
|
|
300
|
+
// Two video streams are considered to be duplicates of
|
|
301
|
+
// one another if their ids are different, but all the other
|
|
302
|
+
// information is the same.
|
|
303
|
+
period.videoStreams = PeriodCombiner.filterOutStreamDuplicates_(
|
|
304
|
+
period.videoStreams, (v1, v2) => {
|
|
305
|
+
return v1.id !== v2.id &&
|
|
306
|
+
v1.fastSwitching == v2.fastSwitching &&
|
|
307
|
+
v1.width === v2.width &&
|
|
308
|
+
v1.frameRate === v2.frameRate &&
|
|
309
|
+
v1.codecs === v2.codecs &&
|
|
310
|
+
v1.mimeType === v2.mimeType &&
|
|
311
|
+
v1.label === v2.label &&
|
|
356
312
|
ArrayUtils.hasSameElements(v1.roles, v2.roles) &&
|
|
357
313
|
MapUtils.hasSameElements(v1.closedCaptions, v2.closedCaptions) &&
|
|
358
|
-
v1.bandwidth
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
314
|
+
v1.bandwidth === v2.bandwidth;
|
|
315
|
+
});
|
|
316
|
+
// Two audio streams are considered to be duplicates of
|
|
317
|
+
// one another if their ids are different, but all the other
|
|
318
|
+
// information is the same.
|
|
319
|
+
period.audioStreams = PeriodCombiner.filterOutStreamDuplicates_(
|
|
320
|
+
period.audioStreams, (a1, a2) => {
|
|
321
|
+
return a1.id !== a2.id &&
|
|
322
|
+
a1.fastSwitching == a2.fastSwitching &&
|
|
323
|
+
a1.channelsCount === a2.channelsCount &&
|
|
324
|
+
a1.language === a2.language &&
|
|
325
|
+
a1.bandwidth === a2.bandwidth &&
|
|
326
|
+
a1.label === a2.label &&
|
|
327
|
+
a1.codecs === a2.codecs &&
|
|
328
|
+
a1.mimeType === a2.mimeType &&
|
|
329
|
+
ArrayUtils.hasSameElements(a1.roles, a2.roles) &&
|
|
330
|
+
a1.audioSamplingRate === a2.audioSamplingRate &&
|
|
331
|
+
a1.primary === a2.primary;
|
|
332
|
+
});
|
|
333
|
+
// Two text streams are considered to be duplicates of
|
|
334
|
+
// one another if their ids are different, but all the other
|
|
335
|
+
// information is the same.
|
|
336
|
+
period.textStreams = PeriodCombiner.filterOutStreamDuplicates_(
|
|
337
|
+
period.textStreams, (t1, t2) => {
|
|
338
|
+
return t1.id !== t2.id &&
|
|
339
|
+
t1.language === t2.language &&
|
|
340
|
+
t1.label === t2.label &&
|
|
341
|
+
t1.codecs === t2.codecs &&
|
|
342
|
+
t1.mimeType === t2.mimeType &&
|
|
343
|
+
t1.bandwidth === t2.bandwidth &&
|
|
344
|
+
ArrayUtils.hasSameElements(t1.roles, t2.roles);
|
|
345
|
+
});
|
|
346
|
+
// Two image streams are considered to be duplicates of
|
|
347
|
+
// one another if their ids are different, but all the other
|
|
348
|
+
// information is the same.
|
|
349
|
+
period.imageStreams = PeriodCombiner.filterOutStreamDuplicates_(
|
|
350
|
+
period.imageStreams, (i1, i2) => {
|
|
351
|
+
return i1.id !== i2.id &&
|
|
352
|
+
i1.width === i2.width &&
|
|
353
|
+
i1.codecs === i2.codecs &&
|
|
354
|
+
i1.mimeType === i2.mimeType;
|
|
355
|
+
});
|
|
369
356
|
}
|
|
370
357
|
}
|
|
371
358
|
|
|
372
359
|
/**
|
|
373
|
-
* @param {!Array
|
|
360
|
+
* @param {!Array<shaka.extern.Stream>} streams
|
|
361
|
+
* @param {function(
|
|
362
|
+
* shaka.extern.Stream, shaka.extern.Stream): boolean} isDuplicate
|
|
363
|
+
* @return {!Array<shaka.extern.Stream>}
|
|
374
364
|
* @private
|
|
375
365
|
*/
|
|
376
|
-
static
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
for (const i1 of period.imageStreams) {
|
|
383
|
-
let duplicate = false;
|
|
384
|
-
for (const i2 of filteredImages) {
|
|
385
|
-
if (i1.id != i2.id &&
|
|
386
|
-
i1.width == i2.width &&
|
|
387
|
-
i1.codecs == i2.codecs &&
|
|
388
|
-
i1.mimeType == i2.mimeType) {
|
|
389
|
-
duplicate = true;
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
if (!duplicate) {
|
|
394
|
-
filteredImages.push(i1);
|
|
395
|
-
}
|
|
366
|
+
static filterOutStreamDuplicates_(streams, isDuplicate) {
|
|
367
|
+
const filteredStreams = [];
|
|
368
|
+
for (const s1 of streams) {
|
|
369
|
+
const duplicate = filteredStreams.some((s2) => isDuplicate(s1, s2));
|
|
370
|
+
if (!duplicate) {
|
|
371
|
+
filteredStreams.push(s1);
|
|
396
372
|
}
|
|
397
|
-
|
|
398
|
-
period.imageStreams = filteredImages;
|
|
399
373
|
}
|
|
374
|
+
return filteredStreams;
|
|
400
375
|
}
|
|
401
376
|
|
|
402
377
|
/**
|
|
@@ -784,27 +759,25 @@ shaka.util.PeriodCombiner = class {
|
|
|
784
759
|
|
|
785
760
|
// Concatenate the new matches onto the stream, starting at the first new
|
|
786
761
|
// period.
|
|
787
|
-
for (let i =
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
used = false;
|
|
802
|
-
}
|
|
762
|
+
for (let i = firstNewPeriodIndex; i < matches.length; i++) {
|
|
763
|
+
const match = matches[i];
|
|
764
|
+
concat(outputStream, match);
|
|
765
|
+
|
|
766
|
+
// We only consider an audio stream "used" if its language is related to
|
|
767
|
+
// the output language. There are scenarios where we want to generate
|
|
768
|
+
// separate tracks for each language, even when we are forced to connect
|
|
769
|
+
// unrelated languages across periods.
|
|
770
|
+
let used = true;
|
|
771
|
+
if (outputStream.type == ContentType.AUDIO) {
|
|
772
|
+
const relatedness = LanguageUtils.relatedness(
|
|
773
|
+
outputStream.language, match.language);
|
|
774
|
+
if (relatedness == 0) {
|
|
775
|
+
used = false;
|
|
803
776
|
}
|
|
777
|
+
}
|
|
804
778
|
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
}
|
|
779
|
+
if (used) {
|
|
780
|
+
unusedStreamsPerPeriod[i].delete(match);
|
|
808
781
|
}
|
|
809
782
|
}
|
|
810
783
|
}
|
|
@@ -1516,6 +1489,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
1516
1489
|
spatialAudio: false,
|
|
1517
1490
|
closedCaptions: null,
|
|
1518
1491
|
external: false,
|
|
1492
|
+
fastSwitching: false,
|
|
1519
1493
|
};
|
|
1520
1494
|
}
|
|
1521
1495
|
|
|
@@ -1556,6 +1530,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
1556
1530
|
closedCaptions: null,
|
|
1557
1531
|
accessibilityPurpose: null,
|
|
1558
1532
|
external: false,
|
|
1533
|
+
fastSwitching: false,
|
|
1559
1534
|
};
|
|
1560
1535
|
}
|
|
1561
1536
|
|
package/lib/util/platform.js
CHANGED
|
@@ -23,15 +23,16 @@ shaka.util.Platform = class {
|
|
|
23
23
|
* @return {boolean}
|
|
24
24
|
*/
|
|
25
25
|
static supportsMediaSource() {
|
|
26
|
+
const mediaSource = window.ManagedMediaSource || window.MediaSource;
|
|
26
27
|
// Browsers that lack a media source implementation will have no reference
|
|
27
28
|
// to |window.MediaSource|. Platforms that we see having problematic media
|
|
28
29
|
// source implementations will have this reference removed via a polyfill.
|
|
29
|
-
if (!
|
|
30
|
+
if (!mediaSource) {
|
|
30
31
|
return false;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
// Some very old MediaSource implementations didn't have isTypeSupported.
|
|
34
|
-
if (!
|
|
35
|
+
if (!mediaSource.isTypeSupported) {
|
|
35
36
|
return false;
|
|
36
37
|
}
|
|
37
38
|
|
|
@@ -463,7 +464,7 @@ shaka.util.Platform = class {
|
|
|
463
464
|
*/
|
|
464
465
|
static requiresEncryptionInfoInAllInitSegments() {
|
|
465
466
|
const Platform = shaka.util.Platform;
|
|
466
|
-
return Platform.isTizen() || Platform.isXboxOne();
|
|
467
|
+
return Platform.isTizen() || Platform.isXboxOne() || Platform.isOrange();
|
|
467
468
|
}
|
|
468
469
|
|
|
469
470
|
/**
|
|
@@ -91,6 +91,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
91
91
|
// segments to detect key changes.
|
|
92
92
|
parseInbandPsshEnabled: shaka.util.Platform.isXboxOne(),
|
|
93
93
|
minHdcpVersion: '',
|
|
94
|
+
ignoreDuplicateInitData: !shaka.util.Platform.isTizen2(),
|
|
94
95
|
};
|
|
95
96
|
|
|
96
97
|
const manifest = {
|
|
@@ -148,6 +149,8 @@ shaka.util.PlayerConfiguration = class {
|
|
|
148
149
|
liveSegmentsDelay: 3,
|
|
149
150
|
sequenceMode: shaka.util.Platform.supportsSequenceMode(),
|
|
150
151
|
ignoreManifestTimestampsInSegmentsMode: false,
|
|
152
|
+
disableCodecGuessing: false,
|
|
153
|
+
allowLowLatencyByteRangeOptimization: true,
|
|
151
154
|
},
|
|
152
155
|
mss: {
|
|
153
156
|
manifestPreprocessor: (element) => {
|
|
@@ -215,15 +218,19 @@ shaka.util.PlayerConfiguration = class {
|
|
|
215
218
|
liveSync: false,
|
|
216
219
|
liveSyncMaxLatency: 1,
|
|
217
220
|
liveSyncPlaybackRate: 1.1,
|
|
221
|
+
liveSyncMinLatency: 0,
|
|
222
|
+
liveSyncMinPlaybackRate: 1,
|
|
218
223
|
};
|
|
219
224
|
|
|
220
|
-
// WebOS, Tizen, and
|
|
221
|
-
// slowly to seeking.
|
|
225
|
+
// WebOS, Tizen, Chromecast and Hisense have long hardware pipelines
|
|
226
|
+
// that respond slowly to seeking.
|
|
227
|
+
// Therefore we should not seek when we detect a stall
|
|
222
228
|
// on one of these platforms. Instead, default stallSkip to 0 to force the
|
|
223
229
|
// stall detector to pause and play instead.
|
|
224
230
|
if (shaka.util.Platform.isWebOS() ||
|
|
225
231
|
shaka.util.Platform.isTizen() ||
|
|
226
|
-
shaka.util.Platform.isChromecast()
|
|
232
|
+
shaka.util.Platform.isChromecast() ||
|
|
233
|
+
shaka.util.Platform.isHisense()) {
|
|
227
234
|
streaming.stallSkip = 0;
|
|
228
235
|
}
|
|
229
236
|
|
|
@@ -344,6 +351,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
344
351
|
preferredTextRole: '',
|
|
345
352
|
preferredAudioChannelCount: 2,
|
|
346
353
|
preferredVideoHdrLevel: 'AUTO',
|
|
354
|
+
preferredVideoLayout: '',
|
|
347
355
|
preferredVideoCodecs: [],
|
|
348
356
|
preferredAudioCodecs: [],
|
|
349
357
|
preferForcedSubs: false,
|
|
@@ -374,7 +382,8 @@ shaka.util.PlayerConfiguration = class {
|
|
|
374
382
|
// eslint-disable-next-line require-await
|
|
375
383
|
offline.trackSelectionCallback = async (tracks) => {
|
|
376
384
|
return shaka.util.PlayerConfiguration.defaultTrackSelect(
|
|
377
|
-
tracks, config.preferredAudioLanguage
|
|
385
|
+
tracks, config.preferredAudioLanguage,
|
|
386
|
+
config.preferredVideoHdrLevel);
|
|
378
387
|
};
|
|
379
388
|
|
|
380
389
|
return config;
|
|
@@ -415,14 +424,34 @@ shaka.util.PlayerConfiguration = class {
|
|
|
415
424
|
/**
|
|
416
425
|
* @param {!Array.<shaka.extern.Track>} tracks
|
|
417
426
|
* @param {string} preferredAudioLanguage
|
|
427
|
+
* @param {string} preferredVideoHdrLevel
|
|
418
428
|
* @return {!Array.<shaka.extern.Track>}
|
|
419
429
|
*/
|
|
420
|
-
static defaultTrackSelect(
|
|
430
|
+
static defaultTrackSelect(
|
|
431
|
+
tracks, preferredAudioLanguage, preferredVideoHdrLevel) {
|
|
421
432
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
422
433
|
const LanguageUtils = shaka.util.LanguageUtils;
|
|
423
434
|
|
|
435
|
+
let hdrLevel = preferredVideoHdrLevel;
|
|
436
|
+
if (hdrLevel == 'AUTO') {
|
|
437
|
+
// Auto detect the ideal HDR level.
|
|
438
|
+
if (window.matchMedia('(color-gamut: p3)').matches) {
|
|
439
|
+
hdrLevel = 'PQ';
|
|
440
|
+
} else {
|
|
441
|
+
hdrLevel = 'SDR';
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
424
445
|
/** @type {!Array.<shaka.extern.Track>} */
|
|
425
|
-
const allVariants = tracks.filter((track) =>
|
|
446
|
+
const allVariants = tracks.filter((track) => {
|
|
447
|
+
if (track.type != 'variant') {
|
|
448
|
+
return false;
|
|
449
|
+
}
|
|
450
|
+
if (track.hdr && track.hdr != hdrLevel) {
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
453
|
+
return true;
|
|
454
|
+
});
|
|
426
455
|
|
|
427
456
|
/** @type {!Array.<shaka.extern.Track>} */
|
|
428
457
|
let selectedVariants = [];
|