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/dash/mpd_utils.js
CHANGED
|
@@ -29,22 +29,24 @@ shaka.dash.MpdUtils = class {
|
|
|
29
29
|
* @param {string} uriTemplate
|
|
30
30
|
* @param {?string} representationId
|
|
31
31
|
* @param {?number} number
|
|
32
|
+
* @param {?number} subNumber
|
|
32
33
|
* @param {?number} bandwidth
|
|
33
34
|
* @param {?(number|bigint)} time
|
|
34
35
|
* @return {string} A URI string.
|
|
35
36
|
* @see ISO/IEC 23009-1:2014 section 5.3.9.4.4
|
|
36
37
|
*/
|
|
37
38
|
static fillUriTemplate(
|
|
38
|
-
uriTemplate, representationId, number, bandwidth, time) {
|
|
39
|
+
uriTemplate, representationId, number, subNumber, bandwidth, time) {
|
|
39
40
|
/** @type {!Object.<string, ?number|?string>} */
|
|
40
41
|
const valueTable = {
|
|
41
42
|
'RepresentationID': representationId,
|
|
42
43
|
'Number': number,
|
|
44
|
+
'SubNumber': subNumber,
|
|
43
45
|
'Bandwidth': bandwidth,
|
|
44
46
|
'Time': time,
|
|
45
47
|
};
|
|
46
48
|
|
|
47
|
-
const re = /\$(RepresentationID|Number|Bandwidth|Time)?(?:%0([0-9]+)([diouxX]))?\$/g; // eslint-disable-line max-len
|
|
49
|
+
const re = /\$(RepresentationID|Number|SubNumber|Bandwidth|Time)?(?:%0([0-9]+)([diouxX]))?\$/g; // eslint-disable-line max-len
|
|
48
50
|
const uri = uriTemplate.replace(re, (match, name, widthStr, format) => {
|
|
49
51
|
if (match == '$$') {
|
|
50
52
|
return '$';
|
|
@@ -126,11 +128,12 @@ shaka.dash.MpdUtils = class {
|
|
|
126
128
|
* @param {number} unscaledPresentationTimeOffset
|
|
127
129
|
* @param {number} periodDuration The Period's duration in seconds.
|
|
128
130
|
* Infinity indicates that the Period continues indefinitely.
|
|
131
|
+
* @param {number} startNumber
|
|
129
132
|
* @return {!Array.<shaka.media.PresentationTimeline.TimeRange>}
|
|
130
133
|
*/
|
|
131
134
|
static createTimeline(
|
|
132
135
|
segmentTimeline, timescale, unscaledPresentationTimeOffset,
|
|
133
|
-
periodDuration) {
|
|
136
|
+
periodDuration, startNumber) {
|
|
134
137
|
goog.asserts.assert(
|
|
135
138
|
timescale > 0 && timescale < Infinity,
|
|
136
139
|
'timescale must be a positive, finite integer');
|
|
@@ -154,6 +157,10 @@ shaka.dash.MpdUtils = class {
|
|
|
154
157
|
XmlUtils.parseAttr(timePoint, 'd', XmlUtils.parseNonNegativeInt);
|
|
155
158
|
const r = XmlUtils.parseAttr(timePoint, 'r', XmlUtils.parseInt);
|
|
156
159
|
|
|
160
|
+
const k = XmlUtils.parseAttr(timePoint, 'k', XmlUtils.parseInt);
|
|
161
|
+
|
|
162
|
+
const partialSegments = k || 0;
|
|
163
|
+
|
|
157
164
|
// Adjust the start time to account for the presentation time offset.
|
|
158
165
|
if (t != null) {
|
|
159
166
|
t -= unscaledPresentationTimeOffset;
|
|
@@ -236,6 +243,8 @@ shaka.dash.MpdUtils = class {
|
|
|
236
243
|
start: startTime / timescale,
|
|
237
244
|
end: endTime / timescale,
|
|
238
245
|
unscaledStart: startTime,
|
|
246
|
+
partialSegments: partialSegments,
|
|
247
|
+
segmentPosition: timeline.length + startNumber,
|
|
239
248
|
};
|
|
240
249
|
timeline.push(item);
|
|
241
250
|
|
|
@@ -299,7 +308,7 @@ shaka.dash.MpdUtils = class {
|
|
|
299
308
|
if (timelineNode) {
|
|
300
309
|
timeline = MpdUtils.createTimeline(
|
|
301
310
|
timelineNode, timescale, unscaledPresentationTimeOffset,
|
|
302
|
-
context.periodInfo.duration || Infinity);
|
|
311
|
+
context.periodInfo.duration || Infinity, startNumber);
|
|
303
312
|
}
|
|
304
313
|
|
|
305
314
|
const scaledPresentationTimeOffset =
|
|
@@ -315,30 +324,46 @@ shaka.dash.MpdUtils = class {
|
|
|
315
324
|
}
|
|
316
325
|
|
|
317
326
|
/**
|
|
318
|
-
*
|
|
319
|
-
*
|
|
327
|
+
* Parses common attributes for Representation, AdaptationSet, and Period.
|
|
320
328
|
* @param {shaka.dash.DashParser.Context} context
|
|
321
329
|
* @param {function(?shaka.dash.DashParser.InheritanceFrame):Element} callback
|
|
322
|
-
*
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
*/
|
|
326
|
-
static inheritAttribute(context, callback, attribute) {
|
|
330
|
+
* @return {!Array.<!Element>}
|
|
331
|
+
*/
|
|
332
|
+
static getNodes(context, callback) {
|
|
327
333
|
const Functional = shaka.util.Functional;
|
|
328
334
|
goog.asserts.assert(
|
|
329
335
|
callback(context.representation),
|
|
330
|
-
'There must be at least one element of the given type'
|
|
336
|
+
'There must be at least one element of the given type',
|
|
337
|
+
);
|
|
331
338
|
|
|
332
|
-
|
|
333
|
-
const nodes = [
|
|
339
|
+
return [
|
|
334
340
|
callback(context.representation),
|
|
335
341
|
callback(context.adaptationSet),
|
|
336
342
|
callback(context.period),
|
|
337
343
|
].filter(Functional.isNotNull);
|
|
344
|
+
}
|
|
338
345
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
346
|
+
/**
|
|
347
|
+
* Searches the inheritance for a Segment* with the given attribute.
|
|
348
|
+
*
|
|
349
|
+
* @param {shaka.dash.DashParser.Context} context
|
|
350
|
+
* @param {function(?shaka.dash.DashParser.InheritanceFrame):Element} callback
|
|
351
|
+
* Gets the Element that contains the attribute to inherit.
|
|
352
|
+
* @param {string} attribute
|
|
353
|
+
* @return {?string}
|
|
354
|
+
*/
|
|
355
|
+
static inheritAttribute(context, callback, attribute) {
|
|
356
|
+
const MpdUtils = shaka.dash.MpdUtils;
|
|
357
|
+
const nodes = MpdUtils.getNodes(context, callback);
|
|
358
|
+
|
|
359
|
+
let result = null;
|
|
360
|
+
for (const node of nodes) {
|
|
361
|
+
result = node.getAttribute(attribute);
|
|
362
|
+
if (result) {
|
|
363
|
+
break;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return result;
|
|
342
367
|
}
|
|
343
368
|
|
|
344
369
|
/**
|
|
@@ -351,22 +376,18 @@ shaka.dash.MpdUtils = class {
|
|
|
351
376
|
* @return {Element}
|
|
352
377
|
*/
|
|
353
378
|
static inheritChild(context, callback, child) {
|
|
354
|
-
const
|
|
355
|
-
|
|
356
|
-
callback(context.representation),
|
|
357
|
-
'There must be at least one element of the given type');
|
|
358
|
-
|
|
359
|
-
/** @type {!Array.<!Element>} */
|
|
360
|
-
const nodes = [
|
|
361
|
-
callback(context.representation),
|
|
362
|
-
callback(context.adaptationSet),
|
|
363
|
-
callback(context.period),
|
|
364
|
-
].filter(Functional.isNotNull);
|
|
379
|
+
const MpdUtils = shaka.dash.MpdUtils;
|
|
380
|
+
const nodes = MpdUtils.getNodes(context, callback);
|
|
365
381
|
|
|
366
382
|
const XmlUtils = shaka.util.XmlUtils;
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
383
|
+
let result = null;
|
|
384
|
+
for (const node of nodes) {
|
|
385
|
+
result = XmlUtils.findChild(node, child);
|
|
386
|
+
if (result) {
|
|
387
|
+
break;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
return result;
|
|
370
391
|
}
|
|
371
392
|
|
|
372
393
|
/**
|
package/lib/dash/segment_base.js
CHANGED
|
@@ -45,11 +45,10 @@ shaka.dash.SegmentBase = class {
|
|
|
45
45
|
return null;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
let resolvedUris = context.representation.
|
|
48
|
+
let resolvedUris = context.representation.getBaseUris();
|
|
49
49
|
const uri = initialization.getAttribute('sourceURL');
|
|
50
50
|
if (uri) {
|
|
51
|
-
resolvedUris = ManifestParserUtils.resolveUris(
|
|
52
|
-
context.representation.baseUris, [uri]);
|
|
51
|
+
resolvedUris = ManifestParserUtils.resolveUris(resolvedUris, [uri]);
|
|
53
52
|
}
|
|
54
53
|
|
|
55
54
|
let startByte = 0;
|
|
@@ -249,12 +248,12 @@ shaka.dash.SegmentBase = class {
|
|
|
249
248
|
const representationIndex = MpdUtils.inheritChild(
|
|
250
249
|
context, SegmentBase.fromInheritance_, 'RepresentationIndex');
|
|
251
250
|
|
|
252
|
-
let indexUris = context.representation.
|
|
251
|
+
let indexUris = context.representation.getBaseUris();
|
|
253
252
|
if (representationIndex) {
|
|
254
253
|
const representationUri = representationIndex.getAttribute('sourceURL');
|
|
255
254
|
if (representationUri) {
|
|
256
255
|
indexUris = ManifestParserUtils.resolveUris(
|
|
257
|
-
|
|
256
|
+
indexUris, [representationUri]);
|
|
258
257
|
}
|
|
259
258
|
}
|
|
260
259
|
|
package/lib/dash/segment_list.js
CHANGED
|
@@ -59,7 +59,7 @@ shaka.dash.SegmentList = class {
|
|
|
59
59
|
|
|
60
60
|
const references = SegmentList.createSegmentReferences_(
|
|
61
61
|
context.periodInfo.start, context.periodInfo.duration,
|
|
62
|
-
info.startNumber, context.representation.
|
|
62
|
+
info.startNumber, context.representation.getBaseUris, info,
|
|
63
63
|
initSegmentReference, aes128Key);
|
|
64
64
|
|
|
65
65
|
const isNew = !segmentIndex;
|
|
@@ -195,7 +195,7 @@ shaka.dash.SegmentList = class {
|
|
|
195
195
|
* @param {number} periodStart in seconds.
|
|
196
196
|
* @param {?number} periodDuration in seconds.
|
|
197
197
|
* @param {number} startNumber
|
|
198
|
-
* @param {
|
|
198
|
+
* @param {function():!Array.<string>} getBaseUris
|
|
199
199
|
* @param {shaka.dash.SegmentList.SegmentListInfo} info
|
|
200
200
|
* @param {shaka.media.InitSegmentReference} initSegmentReference
|
|
201
201
|
* @param {shaka.extern.aes128Key|undefined} aes128Key
|
|
@@ -203,7 +203,7 @@ shaka.dash.SegmentList = class {
|
|
|
203
203
|
* @private
|
|
204
204
|
*/
|
|
205
205
|
static createSegmentReferences_(
|
|
206
|
-
periodStart, periodDuration, startNumber,
|
|
206
|
+
periodStart, periodDuration, startNumber, getBaseUris, info,
|
|
207
207
|
initSegmentReference, aes128Key) {
|
|
208
208
|
const ManifestParserUtils = shaka.util.ManifestParserUtils;
|
|
209
209
|
|
|
@@ -246,7 +246,8 @@ shaka.dash.SegmentList = class {
|
|
|
246
246
|
let uris = null;
|
|
247
247
|
const getUris = () => {
|
|
248
248
|
if (uris == null) {
|
|
249
|
-
uris = ManifestParserUtils.resolveUris(
|
|
249
|
+
uris = ManifestParserUtils.resolveUris(
|
|
250
|
+
getBaseUris(), [segment.mediaUri]);
|
|
250
251
|
}
|
|
251
252
|
return uris;
|
|
252
253
|
};
|
|
@@ -131,16 +131,18 @@ shaka.dash.SegmentTemplate = class {
|
|
|
131
131
|
info,
|
|
132
132
|
context.representation.id,
|
|
133
133
|
context.bandwidth,
|
|
134
|
-
context.representation.
|
|
134
|
+
context.representation.getBaseUris,
|
|
135
135
|
periodStart,
|
|
136
136
|
periodEnd,
|
|
137
137
|
initSegmentReference,
|
|
138
138
|
shouldFit,
|
|
139
139
|
aes128Key,
|
|
140
|
+
context.representation.segmentSequenceCadence,
|
|
140
141
|
);
|
|
141
142
|
} else {
|
|
142
143
|
const tsi = /** @type {!TimelineSegmentIndex} */(segmentIndex);
|
|
143
|
-
tsi.appendTemplateInfo(
|
|
144
|
+
tsi.appendTemplateInfo(
|
|
145
|
+
info, periodStart, periodEnd, shouldFit, initSegmentReference);
|
|
144
146
|
|
|
145
147
|
const availabilityStart =
|
|
146
148
|
context.presentationTimeline.getSegmentAvailabilityStart();
|
|
@@ -166,7 +168,7 @@ shaka.dash.SegmentTemplate = class {
|
|
|
166
168
|
if (segmentIndex instanceof shaka.dash.TimelineSegmentIndex &&
|
|
167
169
|
segmentIndex.isEmpty()) {
|
|
168
170
|
segmentIndex.appendTemplateInfo(info, periodStart,
|
|
169
|
-
periodEnd, shouldFit);
|
|
171
|
+
periodEnd, shouldFit, initSegmentReference);
|
|
170
172
|
}
|
|
171
173
|
return Promise.resolve(segmentIndex);
|
|
172
174
|
},
|
|
@@ -284,10 +286,10 @@ shaka.dash.SegmentTemplate = class {
|
|
|
284
286
|
goog.asserts.assert(info.indexTemplate, 'must be using index template');
|
|
285
287
|
const filledTemplate = MpdUtils.fillUriTemplate(
|
|
286
288
|
info.indexTemplate, context.representation.id,
|
|
287
|
-
null, context.bandwidth || null, null);
|
|
289
|
+
null, null, context.bandwidth || null, null);
|
|
288
290
|
|
|
289
291
|
const resolvedUris = ManifestParserUtils.resolveUris(
|
|
290
|
-
context.representation.
|
|
292
|
+
context.representation.getBaseUris(), [filledTemplate]);
|
|
291
293
|
|
|
292
294
|
return shaka.dash.SegmentBase.generateSegmentIndexFromUris(
|
|
293
295
|
context, requestSegment, init, resolvedUris, 0, null,
|
|
@@ -345,7 +347,7 @@ shaka.dash.SegmentTemplate = class {
|
|
|
345
347
|
const template = info.mediaTemplate;
|
|
346
348
|
const bandwidth = context.bandwidth || null;
|
|
347
349
|
const id = context.representation.id;
|
|
348
|
-
const
|
|
350
|
+
const getBaseUris = context.representation.getBaseUris;
|
|
349
351
|
|
|
350
352
|
const timestampOffset = periodStart - info.scaledPresentationTimeOffset;
|
|
351
353
|
|
|
@@ -429,8 +431,8 @@ shaka.dash.SegmentTemplate = class {
|
|
|
429
431
|
time = BigInt(segmentMediaTime) * BigInt(timescale);
|
|
430
432
|
}
|
|
431
433
|
const mediaUri = MpdUtils.fillUriTemplate(
|
|
432
|
-
template, id, position, bandwidth, time);
|
|
433
|
-
return ManifestParserUtils.resolveUris(
|
|
434
|
+
template, id, position, /* subNumber= */ null, bandwidth, time);
|
|
435
|
+
return ManifestParserUtils.resolveUris(getBaseUris(), [mediaUri]);
|
|
434
436
|
};
|
|
435
437
|
|
|
436
438
|
// Relative to the presentation.
|
|
@@ -540,13 +542,13 @@ shaka.dash.SegmentTemplate = class {
|
|
|
540
542
|
|
|
541
543
|
const repId = context.representation.id;
|
|
542
544
|
const bandwidth = context.bandwidth || null;
|
|
543
|
-
const
|
|
545
|
+
const getBaseUris = context.representation.getBaseUris;
|
|
544
546
|
const getUris = () => {
|
|
545
547
|
goog.asserts.assert(initialization, 'Should have returned earler');
|
|
546
548
|
const filledTemplate = MpdUtils.fillUriTemplate(
|
|
547
|
-
initialization, repId, null, bandwidth, null);
|
|
549
|
+
initialization, repId, null, null, bandwidth, null);
|
|
548
550
|
const resolvedUris = ManifestParserUtils.resolveUris(
|
|
549
|
-
|
|
551
|
+
getBaseUris(), [filledTemplate]);
|
|
550
552
|
return resolvedUris;
|
|
551
553
|
};
|
|
552
554
|
const qualityInfo = shaka.dash.SegmentBase.createQualityInfo(context);
|
|
@@ -579,16 +581,17 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
579
581
|
* @param {!shaka.dash.SegmentTemplate.SegmentTemplateInfo} templateInfo
|
|
580
582
|
* @param {?string} representationId
|
|
581
583
|
* @param {number} bandwidth
|
|
582
|
-
* @param {Array.<string>}
|
|
584
|
+
* @param {function():Array.<string>} getBaseUris
|
|
583
585
|
* @param {number} periodStart
|
|
584
586
|
* @param {number} periodEnd
|
|
585
587
|
* @param {shaka.media.InitSegmentReference} initSegmentReference
|
|
586
588
|
* @param {boolean} shouldFit
|
|
587
589
|
* @param {shaka.extern.aes128Key|undefined} aes128Key
|
|
590
|
+
* @param {number} segmentSequenceCadence
|
|
588
591
|
*/
|
|
589
|
-
constructor(templateInfo, representationId, bandwidth,
|
|
592
|
+
constructor(templateInfo, representationId, bandwidth, getBaseUris,
|
|
590
593
|
periodStart, periodEnd, initSegmentReference, shouldFit,
|
|
591
|
-
aes128Key) {
|
|
594
|
+
aes128Key, segmentSequenceCadence) {
|
|
592
595
|
super([]);
|
|
593
596
|
|
|
594
597
|
/** @private {?shaka.dash.SegmentTemplate.SegmentTemplateInfo} */
|
|
@@ -597,8 +600,8 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
597
600
|
this.representationId_ = representationId;
|
|
598
601
|
/** @private {number} */
|
|
599
602
|
this.bandwidth_ = bandwidth;
|
|
600
|
-
/** @private {Array.<string>} */
|
|
601
|
-
this.
|
|
603
|
+
/** @private {function():Array.<string>} */
|
|
604
|
+
this.getBaseUris_ = getBaseUris;
|
|
602
605
|
/** @private {number} */
|
|
603
606
|
this.periodStart_ = periodStart;
|
|
604
607
|
/** @private {number} */
|
|
@@ -607,6 +610,8 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
607
610
|
this.initSegmentReference_ = initSegmentReference;
|
|
608
611
|
/** @private {shaka.extern.aes128Key|undefined} */
|
|
609
612
|
this.aes128Key_ = aes128Key;
|
|
613
|
+
/** @private {number} */
|
|
614
|
+
this.segmentSequenceCadence_ = segmentSequenceCadence;
|
|
610
615
|
|
|
611
616
|
|
|
612
617
|
if (shouldFit) {
|
|
@@ -680,8 +685,11 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
680
685
|
* @param {number} periodStart
|
|
681
686
|
* @param {number} periodEnd
|
|
682
687
|
* @param {boolean} shouldFit
|
|
688
|
+
* @param {shaka.media.InitSegmentReference} initSegmentReference
|
|
683
689
|
*/
|
|
684
|
-
appendTemplateInfo(info, periodStart, periodEnd, shouldFit
|
|
690
|
+
appendTemplateInfo(info, periodStart, periodEnd, shouldFit,
|
|
691
|
+
initSegmentReference) {
|
|
692
|
+
this.initSegmentReference_ = initSegmentReference;
|
|
685
693
|
if (!this.templateInfo_) {
|
|
686
694
|
this.templateInfo_ = info;
|
|
687
695
|
this.periodStart_ = periodStart;
|
|
@@ -689,6 +697,8 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
689
697
|
} else {
|
|
690
698
|
const currentTimeline = this.templateInfo_.timeline;
|
|
691
699
|
|
|
700
|
+
this.templateInfo_.mediaTemplate = info.mediaTemplate;
|
|
701
|
+
|
|
692
702
|
// Append timeline
|
|
693
703
|
const lastCurrentEntry = currentTimeline[currentTimeline.length - 1];
|
|
694
704
|
const newEntries = info.timeline.filter((entry) => {
|
|
@@ -814,29 +824,81 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
814
824
|
let ref = this.references[correctedPosition];
|
|
815
825
|
|
|
816
826
|
if (!ref) {
|
|
827
|
+
const mediaTemplate = this.templateInfo_.mediaTemplate;
|
|
817
828
|
const range = this.templateInfo_.timeline[correctedPosition];
|
|
818
|
-
const segmentReplacement =
|
|
829
|
+
const segmentReplacement = range.segmentPosition;
|
|
819
830
|
const timeReplacement = this.templateInfo_
|
|
820
831
|
.unscaledPresentationTimeOffset + range.unscaledStart;
|
|
832
|
+
const timestampOffset = this.periodStart_ -
|
|
833
|
+
this.templateInfo_.scaledPresentationTimeOffset;
|
|
834
|
+
|
|
835
|
+
const partialSegmentRefs = [];
|
|
836
|
+
|
|
837
|
+
const partialDuration = (range.end - range.start) / range.partialSegments;
|
|
838
|
+
|
|
839
|
+
for (let i = 0; i < range.partialSegments; i++) {
|
|
840
|
+
const start = range.start + partialDuration * i;
|
|
841
|
+
const end = start + partialDuration;
|
|
842
|
+
const subNumber = i + 1;
|
|
843
|
+
let uris = null;
|
|
844
|
+
const getPartialUris = () => {
|
|
845
|
+
if (!this.templateInfo_) {
|
|
846
|
+
return [];
|
|
847
|
+
}
|
|
848
|
+
if (uris == null) {
|
|
849
|
+
uris = shaka.dash.TimelineSegmentIndex.createUris_(
|
|
850
|
+
this.templateInfo_.mediaTemplate,
|
|
851
|
+
this.representationId_,
|
|
852
|
+
segmentReplacement,
|
|
853
|
+
this.bandwidth_,
|
|
854
|
+
timeReplacement,
|
|
855
|
+
subNumber,
|
|
856
|
+
this.getBaseUris_);
|
|
857
|
+
}
|
|
858
|
+
return uris;
|
|
859
|
+
};
|
|
860
|
+
const partial = new shaka.media.SegmentReference(
|
|
861
|
+
this.periodStart_ + start,
|
|
862
|
+
this.periodStart_ + end,
|
|
863
|
+
getPartialUris,
|
|
864
|
+
/* startByte= */ 0,
|
|
865
|
+
/* endByte= */ null,
|
|
866
|
+
this.initSegmentReference_,
|
|
867
|
+
timestampOffset,
|
|
868
|
+
this.periodStart_,
|
|
869
|
+
this.periodEnd_,
|
|
870
|
+
/* partialReferences= */ [],
|
|
871
|
+
/* tilesLayout= */ '',
|
|
872
|
+
/* tileDuration= */ null,
|
|
873
|
+
/* syncTime= */ null,
|
|
874
|
+
shaka.media.SegmentReference.Status.AVAILABLE,
|
|
875
|
+
this.aes128Key_);
|
|
876
|
+
if (this.segmentSequenceCadence_ == 0) {
|
|
877
|
+
if (i > 0) {
|
|
878
|
+
partial.markAsNonIndependent();
|
|
879
|
+
}
|
|
880
|
+
} else if ((i % this.segmentSequenceCadence_) != 0) {
|
|
881
|
+
partial.markAsNonIndependent();
|
|
882
|
+
}
|
|
883
|
+
partialSegmentRefs.push(partial);
|
|
884
|
+
}
|
|
821
885
|
|
|
822
886
|
const createUrisCb = () => {
|
|
823
|
-
if (
|
|
887
|
+
if (range.partialSegments > 0) {
|
|
824
888
|
return [];
|
|
825
889
|
}
|
|
826
890
|
return shaka.dash.TimelineSegmentIndex
|
|
827
891
|
.createUris_(
|
|
828
|
-
|
|
892
|
+
mediaTemplate,
|
|
829
893
|
this.representationId_,
|
|
830
894
|
segmentReplacement,
|
|
831
895
|
this.bandwidth_,
|
|
832
896
|
timeReplacement,
|
|
833
|
-
|
|
897
|
+
/* subNumber= */ null,
|
|
898
|
+
this.getBaseUris_,
|
|
834
899
|
);
|
|
835
900
|
};
|
|
836
901
|
|
|
837
|
-
const timestampOffset = this.periodStart_ -
|
|
838
|
-
this.templateInfo_.scaledPresentationTimeOffset;
|
|
839
|
-
|
|
840
902
|
ref = new shaka.media.SegmentReference(
|
|
841
903
|
this.periodStart_ + range.start,
|
|
842
904
|
this.periodStart_ + range.end,
|
|
@@ -847,12 +909,13 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
847
909
|
timestampOffset,
|
|
848
910
|
this.periodStart_,
|
|
849
911
|
this.periodEnd_,
|
|
850
|
-
|
|
912
|
+
partialSegmentRefs,
|
|
851
913
|
/* tilesLayout= */ '',
|
|
852
914
|
/* tileDuration= */ null,
|
|
853
915
|
/* syncTime= */ null,
|
|
854
916
|
shaka.media.SegmentReference.Status.AVAILABLE,
|
|
855
|
-
this.aes128Key_
|
|
917
|
+
this.aes128Key_,
|
|
918
|
+
/* allPartialSegments= */ range.partialSegments > 0);
|
|
856
919
|
this.references[correctedPosition] = ref;
|
|
857
920
|
}
|
|
858
921
|
|
|
@@ -866,12 +929,12 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
866
929
|
* @private
|
|
867
930
|
*/
|
|
868
931
|
static createUris_(mediaTemplate, repId, segmentReplacement,
|
|
869
|
-
bandwidth, timeReplacement,
|
|
932
|
+
bandwidth, timeReplacement, subNumber, getBaseUris) {
|
|
870
933
|
const mediaUri = shaka.dash.MpdUtils.fillUriTemplate(
|
|
871
934
|
mediaTemplate, repId,
|
|
872
|
-
segmentReplacement, bandwidth || null, timeReplacement);
|
|
935
|
+
segmentReplacement, subNumber, bandwidth || null, timeReplacement);
|
|
873
936
|
return shaka.util.ManifestParserUtils
|
|
874
|
-
.resolveUris(
|
|
937
|
+
.resolveUris(getBaseUris(), [mediaUri])
|
|
875
938
|
.map((g) => {
|
|
876
939
|
return g.toString();
|
|
877
940
|
});
|
package/lib/hls/hls_classes.js
CHANGED
|
@@ -11,7 +11,6 @@ goog.provide('shaka.hls.Segment');
|
|
|
11
11
|
goog.provide('shaka.hls.Tag');
|
|
12
12
|
|
|
13
13
|
goog.require('goog.asserts');
|
|
14
|
-
goog.require('shaka.hls.Utils');
|
|
15
14
|
goog.require('shaka.util.Error');
|
|
16
15
|
|
|
17
16
|
|
|
@@ -20,19 +19,11 @@ goog.require('shaka.util.Error');
|
|
|
20
19
|
*/
|
|
21
20
|
shaka.hls.Playlist = class {
|
|
22
21
|
/**
|
|
23
|
-
* @param {string} absoluteUri An absolute, final URI after redirects.
|
|
24
22
|
* @param {!shaka.hls.PlaylistType} type
|
|
25
23
|
* @param {!Array.<shaka.hls.Tag>} tags
|
|
26
24
|
* @param {!Array.<shaka.hls.Segment>=} segments
|
|
27
25
|
*/
|
|
28
|
-
constructor(
|
|
29
|
-
/**
|
|
30
|
-
* An absolute, final URI after redirects.
|
|
31
|
-
*
|
|
32
|
-
* @const {string}
|
|
33
|
-
*/
|
|
34
|
-
this.absoluteUri = absoluteUri;
|
|
35
|
-
|
|
26
|
+
constructor(type, tags, segments) {
|
|
36
27
|
/** @const {shaka.hls.PlaylistType} */
|
|
37
28
|
this.type = type;
|
|
38
29
|
|
|
@@ -87,10 +78,11 @@ shaka.hls.Tag = class {
|
|
|
87
78
|
* As in some cases (like in tests) the tag never existed in string form, it
|
|
88
79
|
* is far easier to recreate the tag from the parsed form.
|
|
89
80
|
*
|
|
81
|
+
* @param {?Set.<string>=} attributesToSkip
|
|
90
82
|
* @return {string}
|
|
91
83
|
* @override
|
|
92
84
|
*/
|
|
93
|
-
toString() {
|
|
85
|
+
toString(attributesToSkip) {
|
|
94
86
|
/**
|
|
95
87
|
* @param {shaka.hls.Attribute} attr
|
|
96
88
|
* @return {string}
|
|
@@ -107,7 +99,12 @@ shaka.hls.Tag = class {
|
|
|
107
99
|
// 4) <NAME>:<VALUE>,<ATTRIBUTE_LIST>
|
|
108
100
|
|
|
109
101
|
let tagStr = '#' + this.name;
|
|
110
|
-
const appendages = this.attributes ? this.attributes.
|
|
102
|
+
const appendages = this.attributes ? this.attributes.filter((attr) => {
|
|
103
|
+
if (!attributesToSkip) {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
return !attributesToSkip.has(attr.name);
|
|
107
|
+
}).map(attrToStr) : [];
|
|
111
108
|
|
|
112
109
|
if (this.value) {
|
|
113
110
|
appendages.unshift(this.value);
|
|
@@ -120,6 +117,22 @@ shaka.hls.Tag = class {
|
|
|
120
117
|
return tagStr;
|
|
121
118
|
}
|
|
122
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Create the string key of the tag.
|
|
122
|
+
*
|
|
123
|
+
* @return {string}
|
|
124
|
+
*/
|
|
125
|
+
getTagKey() {
|
|
126
|
+
const attributesToSkip = new Set()
|
|
127
|
+
.add('AUDIO')
|
|
128
|
+
.add('VIDEO')
|
|
129
|
+
.add('SUBTITLES')
|
|
130
|
+
.add('PATHWAY-ID')
|
|
131
|
+
.add('GROUP-ID')
|
|
132
|
+
.add('URI');
|
|
133
|
+
return this.toString(attributesToSkip);
|
|
134
|
+
}
|
|
135
|
+
|
|
123
136
|
/**
|
|
124
137
|
* Adds an attribute to an HLS Tag.
|
|
125
138
|
*
|
|
@@ -203,48 +216,20 @@ shaka.hls.Segment = class {
|
|
|
203
216
|
/**
|
|
204
217
|
* Creates an HLS segment object.
|
|
205
218
|
*
|
|
206
|
-
* @param {string} absoluteMediaPlaylistUri An absolute Media Playlist URI.
|
|
207
219
|
* @param {string} verbatimSegmentUri verbatim segment URI.
|
|
208
220
|
* @param {!Array.<shaka.hls.Tag>} tags
|
|
209
221
|
* @param {!Array.<shaka.hls.Tag>=} partialSegments
|
|
210
222
|
*/
|
|
211
|
-
constructor(
|
|
212
|
-
partialSegments=[]) {
|
|
223
|
+
constructor(verbatimSegmentUri, tags, partialSegments=[]) {
|
|
213
224
|
/** @const {!Array.<shaka.hls.Tag>} */
|
|
214
225
|
this.tags = tags;
|
|
215
226
|
|
|
216
|
-
/** @
|
|
217
|
-
this.
|
|
218
|
-
|
|
219
|
-
/** @type {?string} */
|
|
220
|
-
this.absoluteMediaPlaylistUri_ = absoluteMediaPlaylistUri;
|
|
221
|
-
|
|
222
|
-
/** @type {?string} */
|
|
223
|
-
this.verbatimSegmentUri_ = verbatimSegmentUri;
|
|
227
|
+
/** @const {?string} */
|
|
228
|
+
this.verbatimSegmentUri = verbatimSegmentUri;
|
|
224
229
|
|
|
225
230
|
/** @type {!Array.<shaka.hls.Tag>} */
|
|
226
231
|
this.partialSegments = partialSegments;
|
|
227
232
|
}
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Returns an absolute URI.
|
|
231
|
-
*
|
|
232
|
-
* @return {string}
|
|
233
|
-
*/
|
|
234
|
-
get absoluteUri() {
|
|
235
|
-
if (!this.absoluteUri_ &&
|
|
236
|
-
this.absoluteMediaPlaylistUri_ && this.verbatimSegmentUri_) {
|
|
237
|
-
goog.asserts.assert(this.absoluteMediaPlaylistUri_,
|
|
238
|
-
'An absolute Media Playlist URI should be defined!');
|
|
239
|
-
goog.asserts.assert(this.verbatimSegmentUri_,
|
|
240
|
-
'An verbatim segment URI should be defined!');
|
|
241
|
-
this.absoluteUri_ = shaka.hls.Utils.constructAbsoluteUri(
|
|
242
|
-
this.absoluteMediaPlaylistUri_, this.verbatimSegmentUri_);
|
|
243
|
-
this.absoluteMediaPlaylistUri_ = null;
|
|
244
|
-
this.verbatimSegmentUri_ = null;
|
|
245
|
-
}
|
|
246
|
-
return this.absoluteUri_ || '';
|
|
247
|
-
}
|
|
248
233
|
};
|
|
249
234
|
|
|
250
235
|
|