shaka-player 4.5.0 → 4.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
- package/AUTHORS +2 -0
- package/CHANGELOG.md +98 -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 +35 -31
- 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 +786 -736
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +162 -77
- package/dist/shaka-player.compiled.js +1154 -1121
- 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 +877 -811
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +167 -77
- package/dist/shaka-player.ui.js +1362 -1318
- 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 +249 -83
- 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 +83 -26
- package/lib/hls/hls_classes.js +28 -43
- package/lib/hls/hls_parser.js +761 -649
- 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 +41 -21
- 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 +993 -1502
- 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 +377 -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,12 +131,13 @@ 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);
|
|
@@ -284,10 +285,10 @@ shaka.dash.SegmentTemplate = class {
|
|
|
284
285
|
goog.asserts.assert(info.indexTemplate, 'must be using index template');
|
|
285
286
|
const filledTemplate = MpdUtils.fillUriTemplate(
|
|
286
287
|
info.indexTemplate, context.representation.id,
|
|
287
|
-
null, context.bandwidth || null, null);
|
|
288
|
+
null, null, context.bandwidth || null, null);
|
|
288
289
|
|
|
289
290
|
const resolvedUris = ManifestParserUtils.resolveUris(
|
|
290
|
-
context.representation.
|
|
291
|
+
context.representation.getBaseUris(), [filledTemplate]);
|
|
291
292
|
|
|
292
293
|
return shaka.dash.SegmentBase.generateSegmentIndexFromUris(
|
|
293
294
|
context, requestSegment, init, resolvedUris, 0, null,
|
|
@@ -345,7 +346,7 @@ shaka.dash.SegmentTemplate = class {
|
|
|
345
346
|
const template = info.mediaTemplate;
|
|
346
347
|
const bandwidth = context.bandwidth || null;
|
|
347
348
|
const id = context.representation.id;
|
|
348
|
-
const
|
|
349
|
+
const getBaseUris = context.representation.getBaseUris;
|
|
349
350
|
|
|
350
351
|
const timestampOffset = periodStart - info.scaledPresentationTimeOffset;
|
|
351
352
|
|
|
@@ -429,8 +430,8 @@ shaka.dash.SegmentTemplate = class {
|
|
|
429
430
|
time = BigInt(segmentMediaTime) * BigInt(timescale);
|
|
430
431
|
}
|
|
431
432
|
const mediaUri = MpdUtils.fillUriTemplate(
|
|
432
|
-
template, id, position, bandwidth, time);
|
|
433
|
-
return ManifestParserUtils.resolveUris(
|
|
433
|
+
template, id, position, /* subNumber= */ null, bandwidth, time);
|
|
434
|
+
return ManifestParserUtils.resolveUris(getBaseUris(), [mediaUri]);
|
|
434
435
|
};
|
|
435
436
|
|
|
436
437
|
// Relative to the presentation.
|
|
@@ -540,13 +541,13 @@ shaka.dash.SegmentTemplate = class {
|
|
|
540
541
|
|
|
541
542
|
const repId = context.representation.id;
|
|
542
543
|
const bandwidth = context.bandwidth || null;
|
|
543
|
-
const
|
|
544
|
+
const getBaseUris = context.representation.getBaseUris;
|
|
544
545
|
const getUris = () => {
|
|
545
546
|
goog.asserts.assert(initialization, 'Should have returned earler');
|
|
546
547
|
const filledTemplate = MpdUtils.fillUriTemplate(
|
|
547
|
-
initialization, repId, null, bandwidth, null);
|
|
548
|
+
initialization, repId, null, null, bandwidth, null);
|
|
548
549
|
const resolvedUris = ManifestParserUtils.resolveUris(
|
|
549
|
-
|
|
550
|
+
getBaseUris(), [filledTemplate]);
|
|
550
551
|
return resolvedUris;
|
|
551
552
|
};
|
|
552
553
|
const qualityInfo = shaka.dash.SegmentBase.createQualityInfo(context);
|
|
@@ -579,16 +580,17 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
579
580
|
* @param {!shaka.dash.SegmentTemplate.SegmentTemplateInfo} templateInfo
|
|
580
581
|
* @param {?string} representationId
|
|
581
582
|
* @param {number} bandwidth
|
|
582
|
-
* @param {Array.<string>}
|
|
583
|
+
* @param {function():Array.<string>} getBaseUris
|
|
583
584
|
* @param {number} periodStart
|
|
584
585
|
* @param {number} periodEnd
|
|
585
586
|
* @param {shaka.media.InitSegmentReference} initSegmentReference
|
|
586
587
|
* @param {boolean} shouldFit
|
|
587
588
|
* @param {shaka.extern.aes128Key|undefined} aes128Key
|
|
589
|
+
* @param {number} segmentSequenceCadence
|
|
588
590
|
*/
|
|
589
|
-
constructor(templateInfo, representationId, bandwidth,
|
|
591
|
+
constructor(templateInfo, representationId, bandwidth, getBaseUris,
|
|
590
592
|
periodStart, periodEnd, initSegmentReference, shouldFit,
|
|
591
|
-
aes128Key) {
|
|
593
|
+
aes128Key, segmentSequenceCadence) {
|
|
592
594
|
super([]);
|
|
593
595
|
|
|
594
596
|
/** @private {?shaka.dash.SegmentTemplate.SegmentTemplateInfo} */
|
|
@@ -597,8 +599,8 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
597
599
|
this.representationId_ = representationId;
|
|
598
600
|
/** @private {number} */
|
|
599
601
|
this.bandwidth_ = bandwidth;
|
|
600
|
-
/** @private {Array.<string>} */
|
|
601
|
-
this.
|
|
602
|
+
/** @private {function():Array.<string>} */
|
|
603
|
+
this.getBaseUris_ = getBaseUris;
|
|
602
604
|
/** @private {number} */
|
|
603
605
|
this.periodStart_ = periodStart;
|
|
604
606
|
/** @private {number} */
|
|
@@ -607,6 +609,8 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
607
609
|
this.initSegmentReference_ = initSegmentReference;
|
|
608
610
|
/** @private {shaka.extern.aes128Key|undefined} */
|
|
609
611
|
this.aes128Key_ = aes128Key;
|
|
612
|
+
/** @private {number} */
|
|
613
|
+
this.segmentSequenceCadence_ = segmentSequenceCadence;
|
|
610
614
|
|
|
611
615
|
|
|
612
616
|
if (shouldFit) {
|
|
@@ -814,29 +818,81 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
814
818
|
let ref = this.references[correctedPosition];
|
|
815
819
|
|
|
816
820
|
if (!ref) {
|
|
821
|
+
const mediaTemplate = this.templateInfo_.mediaTemplate;
|
|
817
822
|
const range = this.templateInfo_.timeline[correctedPosition];
|
|
818
|
-
const segmentReplacement =
|
|
823
|
+
const segmentReplacement = range.segmentPosition;
|
|
819
824
|
const timeReplacement = this.templateInfo_
|
|
820
825
|
.unscaledPresentationTimeOffset + range.unscaledStart;
|
|
826
|
+
const timestampOffset = this.periodStart_ -
|
|
827
|
+
this.templateInfo_.scaledPresentationTimeOffset;
|
|
828
|
+
|
|
829
|
+
const partialSegmentRefs = [];
|
|
830
|
+
|
|
831
|
+
const partialDuration = (range.end - range.start) / range.partialSegments;
|
|
832
|
+
|
|
833
|
+
for (let i = 0; i < range.partialSegments; i++) {
|
|
834
|
+
const start = range.start + partialDuration * i;
|
|
835
|
+
const end = start + partialDuration;
|
|
836
|
+
const subNumber = i + 1;
|
|
837
|
+
let uris = null;
|
|
838
|
+
const getPartialUris = () => {
|
|
839
|
+
if (!this.templateInfo_) {
|
|
840
|
+
return [];
|
|
841
|
+
}
|
|
842
|
+
if (uris == null) {
|
|
843
|
+
uris = shaka.dash.TimelineSegmentIndex.createUris_(
|
|
844
|
+
this.templateInfo_.mediaTemplate,
|
|
845
|
+
this.representationId_,
|
|
846
|
+
segmentReplacement,
|
|
847
|
+
this.bandwidth_,
|
|
848
|
+
timeReplacement,
|
|
849
|
+
subNumber,
|
|
850
|
+
this.getBaseUris_);
|
|
851
|
+
}
|
|
852
|
+
return uris;
|
|
853
|
+
};
|
|
854
|
+
const partial = new shaka.media.SegmentReference(
|
|
855
|
+
this.periodStart_ + start,
|
|
856
|
+
this.periodStart_ + end,
|
|
857
|
+
getPartialUris,
|
|
858
|
+
/* startByte= */ 0,
|
|
859
|
+
/* endByte= */ null,
|
|
860
|
+
this.initSegmentReference_,
|
|
861
|
+
timestampOffset,
|
|
862
|
+
this.periodStart_,
|
|
863
|
+
this.periodEnd_,
|
|
864
|
+
/* partialReferences= */ [],
|
|
865
|
+
/* tilesLayout= */ '',
|
|
866
|
+
/* tileDuration= */ null,
|
|
867
|
+
/* syncTime= */ null,
|
|
868
|
+
shaka.media.SegmentReference.Status.AVAILABLE,
|
|
869
|
+
this.aes128Key_);
|
|
870
|
+
if (this.segmentSequenceCadence_ == 0) {
|
|
871
|
+
if (i > 0) {
|
|
872
|
+
partial.markAsNonIndependent();
|
|
873
|
+
}
|
|
874
|
+
} else if ((i % this.segmentSequenceCadence_) != 0) {
|
|
875
|
+
partial.markAsNonIndependent();
|
|
876
|
+
}
|
|
877
|
+
partialSegmentRefs.push(partial);
|
|
878
|
+
}
|
|
821
879
|
|
|
822
880
|
const createUrisCb = () => {
|
|
823
|
-
if (
|
|
881
|
+
if (range.partialSegments > 0) {
|
|
824
882
|
return [];
|
|
825
883
|
}
|
|
826
884
|
return shaka.dash.TimelineSegmentIndex
|
|
827
885
|
.createUris_(
|
|
828
|
-
|
|
886
|
+
mediaTemplate,
|
|
829
887
|
this.representationId_,
|
|
830
888
|
segmentReplacement,
|
|
831
889
|
this.bandwidth_,
|
|
832
890
|
timeReplacement,
|
|
833
|
-
|
|
891
|
+
/* subNumber= */ null,
|
|
892
|
+
this.getBaseUris_,
|
|
834
893
|
);
|
|
835
894
|
};
|
|
836
895
|
|
|
837
|
-
const timestampOffset = this.periodStart_ -
|
|
838
|
-
this.templateInfo_.scaledPresentationTimeOffset;
|
|
839
|
-
|
|
840
896
|
ref = new shaka.media.SegmentReference(
|
|
841
897
|
this.periodStart_ + range.start,
|
|
842
898
|
this.periodStart_ + range.end,
|
|
@@ -847,12 +903,13 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
847
903
|
timestampOffset,
|
|
848
904
|
this.periodStart_,
|
|
849
905
|
this.periodEnd_,
|
|
850
|
-
|
|
906
|
+
partialSegmentRefs,
|
|
851
907
|
/* tilesLayout= */ '',
|
|
852
908
|
/* tileDuration= */ null,
|
|
853
909
|
/* syncTime= */ null,
|
|
854
910
|
shaka.media.SegmentReference.Status.AVAILABLE,
|
|
855
|
-
this.aes128Key_
|
|
911
|
+
this.aes128Key_,
|
|
912
|
+
/* allPartialSegments= */ range.partialSegments > 0);
|
|
856
913
|
this.references[correctedPosition] = ref;
|
|
857
914
|
}
|
|
858
915
|
|
|
@@ -866,12 +923,12 @@ shaka.dash.TimelineSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
866
923
|
* @private
|
|
867
924
|
*/
|
|
868
925
|
static createUris_(mediaTemplate, repId, segmentReplacement,
|
|
869
|
-
bandwidth, timeReplacement,
|
|
926
|
+
bandwidth, timeReplacement, subNumber, getBaseUris) {
|
|
870
927
|
const mediaUri = shaka.dash.MpdUtils.fillUriTemplate(
|
|
871
928
|
mediaTemplate, repId,
|
|
872
|
-
segmentReplacement, bandwidth || null, timeReplacement);
|
|
929
|
+
segmentReplacement, subNumber, bandwidth || null, timeReplacement);
|
|
873
930
|
return shaka.util.ManifestParserUtils
|
|
874
|
-
.resolveUris(
|
|
931
|
+
.resolveUris(getBaseUris(), [mediaUri])
|
|
875
932
|
.map((g) => {
|
|
876
933
|
return g.toString();
|
|
877
934
|
});
|
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
|
|