shaka-player 4.7.12 → 4.8.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/AUTHORS +1 -0
- package/CONTRIBUTORS +1 -0
- package/LICENSE +54 -0
- package/README.md +22 -1
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/deps.js +36 -25
- package/dist/locales.js +40 -30
- package/dist/shaka-player.compiled.d.ts +196 -46
- package/dist/shaka-player.compiled.debug.d.ts +196 -46
- package/dist/shaka-player.compiled.debug.externs.js +474 -337
- package/dist/shaka-player.compiled.debug.js +992 -871
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +474 -337
- package/dist/shaka-player.compiled.js +1248 -1174
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +259 -49
- package/dist/shaka-player.ui.debug.d.ts +259 -49
- package/dist/shaka-player.ui.debug.externs.js +591 -376
- package/dist/shaka-player.ui.debug.js +1208 -1003
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +591 -376
- package/dist/shaka-player.ui.js +1533 -1408
- package/dist/shaka-player.ui.map +4 -4
- package/externs/device_sensor_event.js +18 -0
- package/externs/hisense.js +16 -0
- package/externs/playstation.js +31 -0
- package/externs/shaka/abr_manager.js +3 -1
- package/externs/shaka/ads.js +5 -0
- package/externs/shaka/codecs.js +13 -0
- package/externs/shaka/manifest.js +69 -7
- package/externs/shaka/net.js +13 -1
- package/externs/shaka/offline.js +7 -1
- package/externs/shaka/player.js +184 -13
- package/externs/shaka/text.js +19 -0
- package/externs/tizen.js +41 -0
- package/externs/webos.js +19 -0
- package/externs/xbox.js +43 -0
- package/lib/abr/simple_abr_manager.js +9 -1
- package/lib/ads/ad_manager.js +19 -2
- package/lib/ads/client_side_ad_manager.js +5 -3
- package/lib/ads/media_tailor_ad_manager.js +9 -0
- package/lib/cast/cast_receiver.js +0 -14
- package/lib/cast/cast_utils.js +1 -0
- package/lib/cea/mp4_cea_parser.js +6 -1
- package/lib/dash/content_protection.js +97 -53
- package/lib/dash/dash_parser.js +240 -179
- package/lib/dash/mpd_utils.js +72 -65
- package/lib/dash/segment_base.js +35 -22
- package/lib/dash/segment_list.js +39 -31
- package/lib/dash/segment_template.js +47 -23
- package/lib/hls/hls_parser.js +376 -165
- package/lib/media/buffering_observer.js +25 -1
- package/lib/media/drm_engine.js +91 -71
- package/lib/media/manifest_filterer.js +220 -0
- package/lib/media/media_source_engine.js +108 -29
- package/lib/media/playhead.js +3 -3
- package/lib/media/preload_manager.js +827 -0
- package/lib/media/presentation_timeline.js +11 -0
- package/lib/media/segment_index.js +60 -49
- package/lib/media/segment_prefetch.js +140 -43
- package/lib/media/segment_reference.js +31 -8
- package/lib/media/segment_utils.js +208 -25
- package/lib/media/streaming_engine.js +321 -77
- package/lib/mss/content_protection.js +31 -25
- package/lib/mss/mss_parser.js +78 -55
- package/lib/net/networking_engine.js +49 -4
- 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 +10 -3
- package/lib/offline/storage.js +5 -3
- package/lib/player.js +896 -674
- package/lib/polyfill/media_capabilities.js +16 -1
- package/lib/text/simple_text_displayer.js +9 -0
- package/lib/text/stub_text_displayer.js +7 -0
- package/lib/text/text_engine.js +16 -3
- package/lib/text/ttml_text_parser.js +116 -114
- package/lib/text/ui_text_displayer.js +28 -11
- package/lib/text/vtt_text_parser.js +54 -115
- package/lib/transmuxer/opus.js +91 -0
- package/lib/transmuxer/ts_transmuxer.js +115 -0
- package/lib/util/cmcd_manager.js +152 -3
- package/lib/util/dom_utils.js +11 -0
- package/lib/util/error.js +5 -0
- package/lib/util/fake_event.js +2 -0
- package/lib/util/manifest_parser_utils.js +97 -3
- package/lib/util/mime_utils.js +10 -5
- package/lib/util/mp4_box_parsers.js +346 -17
- package/lib/util/mp4_generator.js +23 -0
- package/lib/util/periods.js +24 -37
- package/lib/util/platform.js +161 -9
- package/lib/util/player_configuration.js +61 -3
- package/lib/util/stats.js +16 -0
- package/lib/util/stream_utils.js +350 -277
- package/lib/util/string_utils.js +36 -0
- package/lib/util/tXml.js +814 -0
- package/lib/util/ts_parser.js +50 -0
- package/lib/util/xml_utils.js +10 -338
- package/package.json +2 -2
- package/shaka-player.uncompiled.js +8 -0
- package/ui/controls.js +187 -5
- package/ui/enums.js +2 -0
- package/ui/externs/ui.js +30 -3
- package/ui/gl_matrix/matrix_4x4.js +568 -0
- package/ui/gl_matrix/matrix_quaternion.js +45 -0
- package/ui/less/containers.less +11 -0
- package/ui/locales/en-GB.json +2 -0
- package/ui/locales/en.json +2 -0
- package/ui/locales/es-419.json +2 -0
- package/ui/locales/es.json +2 -0
- package/ui/locales/source.json +8 -0
- package/ui/recenter_vr.js +126 -0
- package/ui/resolution_selection.js +25 -5
- package/ui/statistics_button.js +12 -0
- package/ui/text_selection.js +1 -1
- package/ui/toggle_stereoscopic.js +127 -0
- package/ui/ui.js +74 -38
- package/ui/vr_manager.js +557 -0
- package/ui/vr_utils.js +232 -0
- package/ui/vr_webgl.js +697 -0
package/lib/dash/mpd_utils.js
CHANGED
|
@@ -13,7 +13,7 @@ goog.require('shaka.util.AbortableOperation');
|
|
|
13
13
|
goog.require('shaka.util.Error');
|
|
14
14
|
goog.require('shaka.util.Functional');
|
|
15
15
|
goog.require('shaka.util.ManifestParserUtils');
|
|
16
|
-
goog.require('shaka.util.
|
|
16
|
+
goog.require('shaka.util.TXml');
|
|
17
17
|
goog.requireType('shaka.dash.DashParser');
|
|
18
18
|
goog.requireType('shaka.media.PresentationTimeline');
|
|
19
19
|
|
|
@@ -123,7 +123,7 @@ shaka.dash.MpdUtils = class {
|
|
|
123
123
|
* Expands a SegmentTimeline into an array-based timeline. The results are in
|
|
124
124
|
* seconds.
|
|
125
125
|
*
|
|
126
|
-
* @param {!
|
|
126
|
+
* @param {!shaka.extern.xml.Node} segmentTimeline
|
|
127
127
|
* @param {number} timescale
|
|
128
128
|
* @param {number} unscaledPresentationTimeOffset
|
|
129
129
|
* @param {number} periodDuration The Period's duration in seconds.
|
|
@@ -141,9 +141,9 @@ shaka.dash.MpdUtils = class {
|
|
|
141
141
|
periodDuration > 0, 'period duration must be a positive integer');
|
|
142
142
|
|
|
143
143
|
// Alias.
|
|
144
|
-
const
|
|
144
|
+
const TXml = shaka.util.TXml;
|
|
145
145
|
|
|
146
|
-
const timePoints =
|
|
146
|
+
const timePoints = TXml.findChildren(segmentTimeline, 'S');
|
|
147
147
|
|
|
148
148
|
/** @type {!Array.<shaka.media.PresentationTimeline.TimeRange>} */
|
|
149
149
|
const timeline = [];
|
|
@@ -152,12 +152,12 @@ shaka.dash.MpdUtils = class {
|
|
|
152
152
|
for (let i = 0; i < timePoints.length; ++i) {
|
|
153
153
|
const timePoint = timePoints[i];
|
|
154
154
|
const next = timePoints[i + 1];
|
|
155
|
-
let t =
|
|
155
|
+
let t = TXml.parseAttr(timePoint, 't', TXml.parseNonNegativeInt);
|
|
156
156
|
const d =
|
|
157
|
-
|
|
158
|
-
const r =
|
|
157
|
+
TXml.parseAttr(timePoint, 'd', TXml.parseNonNegativeInt);
|
|
158
|
+
const r = TXml.parseAttr(timePoint, 'r', TXml.parseInt);
|
|
159
159
|
|
|
160
|
-
const k =
|
|
160
|
+
const k = TXml.parseAttr(timePoint, 'k', TXml.parseInt);
|
|
161
161
|
|
|
162
162
|
const partialSegments = k || 0;
|
|
163
163
|
|
|
@@ -179,7 +179,7 @@ shaka.dash.MpdUtils = class {
|
|
|
179
179
|
if (repeat < 0) {
|
|
180
180
|
if (next) {
|
|
181
181
|
const nextStartTime =
|
|
182
|
-
|
|
182
|
+
TXml.parseAttr(next, 't', TXml.parseNonNegativeInt);
|
|
183
183
|
if (nextStartTime == null) {
|
|
184
184
|
shaka.log.warning(
|
|
185
185
|
'An "S" element cannot have a negative repeat',
|
|
@@ -260,7 +260,8 @@ shaka.dash.MpdUtils = class {
|
|
|
260
260
|
* Parses common segment info for SegmentList and SegmentTemplate.
|
|
261
261
|
*
|
|
262
262
|
* @param {shaka.dash.DashParser.Context} context
|
|
263
|
-
* @param {function(?shaka.dash.DashParser.InheritanceFrame):
|
|
263
|
+
* @param {function(?shaka.dash.DashParser.InheritanceFrame):
|
|
264
|
+
* ?shaka.extern.xml.Node} callback
|
|
264
265
|
* Gets the element that contains the segment info.
|
|
265
266
|
* @return {shaka.dash.MpdUtils.SegmentInfo}
|
|
266
267
|
*/
|
|
@@ -269,23 +270,23 @@ shaka.dash.MpdUtils = class {
|
|
|
269
270
|
callback(context.representation),
|
|
270
271
|
'There must be at least one element of the given type.');
|
|
271
272
|
const MpdUtils = shaka.dash.MpdUtils;
|
|
272
|
-
const
|
|
273
|
+
const TXml = shaka.util.TXml;
|
|
273
274
|
|
|
274
275
|
const timescaleStr =
|
|
275
276
|
MpdUtils.inheritAttribute(context, callback, 'timescale');
|
|
276
277
|
let timescale = 1;
|
|
277
278
|
if (timescaleStr) {
|
|
278
|
-
timescale =
|
|
279
|
+
timescale = TXml.parsePositiveInt(timescaleStr) || 1;
|
|
279
280
|
}
|
|
280
281
|
|
|
281
282
|
const durationStr =
|
|
282
283
|
MpdUtils.inheritAttribute(context, callback, 'duration');
|
|
283
|
-
let segmentDuration =
|
|
284
|
+
let segmentDuration = TXml.parsePositiveInt(durationStr || '');
|
|
284
285
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
285
286
|
// TODO: The specification is not clear, check this once it is resolved:
|
|
286
287
|
// https://github.com/Dash-Industry-Forum/DASH-IF-IOP/issues/404
|
|
287
288
|
if (context.representation.contentType == ContentType.IMAGE) {
|
|
288
|
-
segmentDuration =
|
|
289
|
+
segmentDuration = TXml.parseFloat(durationStr || '');
|
|
289
290
|
}
|
|
290
291
|
if (segmentDuration) {
|
|
291
292
|
segmentDuration /= timescale;
|
|
@@ -296,7 +297,7 @@ shaka.dash.MpdUtils = class {
|
|
|
296
297
|
const unscaledPresentationTimeOffset =
|
|
297
298
|
Number(MpdUtils.inheritAttribute(context, callback,
|
|
298
299
|
'presentationTimeOffset')) || 0;
|
|
299
|
-
let startNumber =
|
|
300
|
+
let startNumber = TXml.parseNonNegativeInt(startNumberStr || '');
|
|
300
301
|
if (startNumberStr == null || startNumber == null) {
|
|
301
302
|
startNumber = 1;
|
|
302
303
|
}
|
|
@@ -326,8 +327,9 @@ shaka.dash.MpdUtils = class {
|
|
|
326
327
|
/**
|
|
327
328
|
* Parses common attributes for Representation, AdaptationSet, and Period.
|
|
328
329
|
* @param {shaka.dash.DashParser.Context} context
|
|
329
|
-
* @param {function(?shaka.dash.DashParser.InheritanceFrame):
|
|
330
|
-
*
|
|
330
|
+
* @param {function(?shaka.dash.DashParser.InheritanceFrame):
|
|
331
|
+
* ?shaka.extern.xml.Node} callback
|
|
332
|
+
* @return {!Array.<!shaka.extern.xml.Node>}
|
|
331
333
|
*/
|
|
332
334
|
static getNodes(context, callback) {
|
|
333
335
|
const Functional = shaka.util.Functional;
|
|
@@ -347,7 +349,8 @@ shaka.dash.MpdUtils = class {
|
|
|
347
349
|
* Searches the inheritance for a Segment* with the given attribute.
|
|
348
350
|
*
|
|
349
351
|
* @param {shaka.dash.DashParser.Context} context
|
|
350
|
-
* @param {function(?shaka.dash.DashParser.InheritanceFrame):
|
|
352
|
+
* @param {function(?shaka.dash.DashParser.InheritanceFrame):
|
|
353
|
+
* ?shaka.extern.xml.Node} callback
|
|
351
354
|
* Gets the Element that contains the attribute to inherit.
|
|
352
355
|
* @param {string} attribute
|
|
353
356
|
* @return {?string}
|
|
@@ -358,7 +361,7 @@ shaka.dash.MpdUtils = class {
|
|
|
358
361
|
|
|
359
362
|
let result = null;
|
|
360
363
|
for (const node of nodes) {
|
|
361
|
-
result = node.
|
|
364
|
+
result = node.attributes[attribute];
|
|
362
365
|
if (result) {
|
|
363
366
|
break;
|
|
364
367
|
}
|
|
@@ -370,19 +373,20 @@ shaka.dash.MpdUtils = class {
|
|
|
370
373
|
* Searches the inheritance for a Segment* with the given child.
|
|
371
374
|
*
|
|
372
375
|
* @param {shaka.dash.DashParser.Context} context
|
|
373
|
-
* @param {function(?shaka.dash.DashParser.InheritanceFrame):
|
|
376
|
+
* @param {function(?shaka.dash.DashParser.InheritanceFrame):
|
|
377
|
+
* ?shaka.extern.xml.Node} callback
|
|
374
378
|
* Gets the Element that contains the child to inherit.
|
|
375
379
|
* @param {string} child
|
|
376
|
-
* @return {
|
|
380
|
+
* @return {?shaka.extern.xml.Node}
|
|
377
381
|
*/
|
|
378
382
|
static inheritChild(context, callback, child) {
|
|
379
383
|
const MpdUtils = shaka.dash.MpdUtils;
|
|
380
384
|
const nodes = MpdUtils.getNodes(context, callback);
|
|
381
385
|
|
|
382
|
-
const
|
|
386
|
+
const TXml = shaka.util.TXml;
|
|
383
387
|
let result = null;
|
|
384
388
|
for (const node of nodes) {
|
|
385
|
-
result =
|
|
389
|
+
result = TXml.findChild(node, child);
|
|
386
390
|
if (result) {
|
|
387
391
|
break;
|
|
388
392
|
}
|
|
@@ -395,33 +399,35 @@ shaka.dash.MpdUtils = class {
|
|
|
395
399
|
* It also strips the xlink properties off of the element,
|
|
396
400
|
* even if the process fails.
|
|
397
401
|
*
|
|
398
|
-
* @param {!
|
|
402
|
+
* @param {!shaka.extern.xml.Node} element
|
|
399
403
|
* @param {!shaka.extern.RetryParameters} retryParameters
|
|
400
404
|
* @param {boolean} failGracefully
|
|
401
405
|
* @param {string} baseUri
|
|
402
406
|
* @param {!shaka.net.NetworkingEngine} networkingEngine
|
|
403
407
|
* @param {number} linkDepth
|
|
404
|
-
* @return {!shaka.util.AbortableOperation.<!
|
|
408
|
+
* @return {!shaka.util.AbortableOperation.<!shaka.extern.xml.Node>}
|
|
405
409
|
* @private
|
|
406
410
|
*/
|
|
407
411
|
static handleXlinkInElement_(
|
|
408
412
|
element, retryParameters, failGracefully, baseUri, networkingEngine,
|
|
409
413
|
linkDepth) {
|
|
410
414
|
const MpdUtils = shaka.dash.MpdUtils;
|
|
411
|
-
const
|
|
415
|
+
const TXml = shaka.util.TXml;
|
|
412
416
|
const Error = shaka.util.Error;
|
|
413
417
|
const ManifestParserUtils = shaka.util.ManifestParserUtils;
|
|
414
418
|
const NS = MpdUtils.XlinkNamespaceUri_;
|
|
415
419
|
|
|
416
|
-
const xlinkHref =
|
|
420
|
+
const xlinkHref = TXml.getAttributeNS(element, NS, 'href');
|
|
417
421
|
const xlinkActuate =
|
|
418
|
-
|
|
422
|
+
TXml.getAttributeNS(element, NS, 'actuate') || 'onRequest';
|
|
419
423
|
|
|
420
424
|
// Remove the xlink properties, so it won't download again
|
|
421
425
|
// when re-processed.
|
|
422
|
-
for (const
|
|
423
|
-
|
|
424
|
-
|
|
426
|
+
for (const key of Object.keys(element.attributes)) {
|
|
427
|
+
const segs = key.split(':');
|
|
428
|
+
const namespace = shaka.util.TXml.getKnownNameSpace(NS);
|
|
429
|
+
if (segs[0] == namespace) {
|
|
430
|
+
delete element.attributes[key];
|
|
425
431
|
}
|
|
426
432
|
}
|
|
427
433
|
|
|
@@ -465,7 +471,7 @@ shaka.dash.MpdUtils = class {
|
|
|
465
471
|
// top-level element. If there are multiple roots, it will be
|
|
466
472
|
// rejected.
|
|
467
473
|
const rootElem =
|
|
468
|
-
|
|
474
|
+
TXml.parseXml(response.data, element.tagName);
|
|
469
475
|
if (!rootElem) {
|
|
470
476
|
// It was not valid XML.
|
|
471
477
|
return shaka.util.AbortableOperation.failed(new Error(
|
|
@@ -477,20 +483,20 @@ shaka.dash.MpdUtils = class {
|
|
|
477
483
|
// the element can be changed further.
|
|
478
484
|
|
|
479
485
|
// Remove the current contents of the node.
|
|
480
|
-
|
|
481
|
-
element.removeChild(element.childNodes[0]);
|
|
482
|
-
}
|
|
486
|
+
element.children = [];
|
|
483
487
|
|
|
484
488
|
// Move the children of the loaded xml into the current element.
|
|
485
|
-
while (rootElem.
|
|
486
|
-
const child = rootElem.
|
|
487
|
-
|
|
488
|
-
|
|
489
|
+
while (rootElem.children.length) {
|
|
490
|
+
const child = rootElem.children.shift();
|
|
491
|
+
if (TXml.isNode(child)) {
|
|
492
|
+
child.parent = element;
|
|
493
|
+
}
|
|
494
|
+
element.children.push(child);
|
|
489
495
|
}
|
|
490
496
|
|
|
491
497
|
// Move the attributes of the loaded xml into the current element.
|
|
492
|
-
for (const
|
|
493
|
-
element.
|
|
498
|
+
for (const key of Object.keys(rootElem.attributes)) {
|
|
499
|
+
element.attributes[key] = rootElem.attributes[key];
|
|
494
500
|
}
|
|
495
501
|
|
|
496
502
|
return shaka.dash.MpdUtils.processXlinks(
|
|
@@ -503,25 +509,26 @@ shaka.dash.MpdUtils = class {
|
|
|
503
509
|
* Filter the contents of a node recursively, replacing xlink links
|
|
504
510
|
* with their associated online data.
|
|
505
511
|
*
|
|
506
|
-
* @param {!
|
|
512
|
+
* @param {!shaka.extern.xml.Node} element
|
|
507
513
|
* @param {!shaka.extern.RetryParameters} retryParameters
|
|
508
514
|
* @param {boolean} failGracefully
|
|
509
515
|
* @param {string} baseUri
|
|
510
516
|
* @param {!shaka.net.NetworkingEngine} networkingEngine
|
|
511
517
|
* @param {number=} linkDepth, default set to 0
|
|
512
|
-
* @return {!shaka.util.AbortableOperation.<!
|
|
518
|
+
* @return {!shaka.util.AbortableOperation.<!shaka.extern.xml.Node>}
|
|
513
519
|
*/
|
|
514
520
|
static processXlinks(
|
|
515
|
-
element, retryParameters,
|
|
521
|
+
element, retryParameters,
|
|
522
|
+
failGracefully, baseUri, networkingEngine,
|
|
516
523
|
linkDepth = 0) {
|
|
517
524
|
const MpdUtils = shaka.dash.MpdUtils;
|
|
518
|
-
const
|
|
525
|
+
const TXml = shaka.util.TXml;
|
|
519
526
|
const NS = MpdUtils.XlinkNamespaceUri_;
|
|
520
527
|
|
|
521
|
-
if (
|
|
528
|
+
if (TXml.getAttributeNS(element, NS, 'href')) {
|
|
522
529
|
let handled = MpdUtils.handleXlinkInElement_(
|
|
523
|
-
element, retryParameters, failGracefully,
|
|
524
|
-
linkDepth);
|
|
530
|
+
element, retryParameters, failGracefully,
|
|
531
|
+
baseUri, networkingEngine, linkDepth);
|
|
525
532
|
if (failGracefully) {
|
|
526
533
|
// Catch any error and go on.
|
|
527
534
|
handled = handled.chain(undefined, (error) => {
|
|
@@ -537,23 +544,23 @@ shaka.dash.MpdUtils = class {
|
|
|
537
544
|
}
|
|
538
545
|
|
|
539
546
|
const childOperations = [];
|
|
540
|
-
for (const child of
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
547
|
+
for (const child of shaka.util.TXml.getChildNodes(element)) {
|
|
548
|
+
const resolveToZeroString = 'urn:mpeg:dash:resolve-to-zero:2013';
|
|
549
|
+
if (TXml.getAttributeNS(child, NS, 'href') == resolveToZeroString) {
|
|
550
|
+
// This is a 'resolve to zero' code; it means the element should
|
|
551
|
+
// be removed, as specified by the mpeg-dash rules for xlink.
|
|
552
|
+
element.children = element.children.filter(
|
|
553
|
+
(elem) => elem !== child);
|
|
554
|
+
} else if (child.tagName != 'SegmentTimeline') {
|
|
555
|
+
// Don't recurse into a SegmentTimeline since xlink attributes
|
|
556
|
+
// aren't valid in there and looking at each segment can take a long
|
|
557
|
+
// time with larger manifests.
|
|
558
|
+
|
|
559
|
+
// Replace the child with its processed form.
|
|
560
|
+
childOperations.push(shaka.dash.MpdUtils.processXlinks(
|
|
561
|
+
/** @type {!shaka.extern.xml.Node} */ (child),
|
|
562
|
+
retryParameters, failGracefully,
|
|
563
|
+
baseUri, networkingEngine, linkDepth));
|
|
557
564
|
}
|
|
558
565
|
}
|
|
559
566
|
|
package/lib/dash/segment_base.js
CHANGED
|
@@ -16,7 +16,8 @@ goog.require('shaka.media.WebmSegmentIndexParser');
|
|
|
16
16
|
goog.require('shaka.util.Error');
|
|
17
17
|
goog.require('shaka.util.ManifestParserUtils');
|
|
18
18
|
goog.require('shaka.util.ObjectUtils');
|
|
19
|
-
goog.require('shaka.util.
|
|
19
|
+
goog.require('shaka.util.StringUtils');
|
|
20
|
+
goog.require('shaka.util.TXml');
|
|
20
21
|
goog.requireType('shaka.dash.DashParser');
|
|
21
22
|
goog.requireType('shaka.media.PresentationTimeline');
|
|
22
23
|
goog.requireType('shaka.media.SegmentReference');
|
|
@@ -30,14 +31,16 @@ shaka.dash.SegmentBase = class {
|
|
|
30
31
|
* Creates an init segment reference from a Context object.
|
|
31
32
|
*
|
|
32
33
|
* @param {shaka.dash.DashParser.Context} context
|
|
33
|
-
* @param {function(?shaka.dash.DashParser.InheritanceFrame):
|
|
34
|
-
*
|
|
34
|
+
* @param {function(?shaka.dash.DashParser.InheritanceFrame):
|
|
35
|
+
* ?shaka.extern.xml.Node} callback
|
|
36
|
+
* @param {shaka.extern.aesKey|undefined} aesKey
|
|
35
37
|
* @return {shaka.media.InitSegmentReference}
|
|
36
38
|
*/
|
|
37
|
-
static createInitSegment(context, callback,
|
|
39
|
+
static createInitSegment(context, callback, aesKey) {
|
|
38
40
|
const MpdUtils = shaka.dash.MpdUtils;
|
|
39
|
-
const
|
|
41
|
+
const TXml = shaka.util.TXml;
|
|
40
42
|
const ManifestParserUtils = shaka.util.ManifestParserUtils;
|
|
43
|
+
const StringUtils = shaka.util.StringUtils;
|
|
41
44
|
|
|
42
45
|
const initialization =
|
|
43
46
|
MpdUtils.inheritChild(context, callback, 'Initialization');
|
|
@@ -46,15 +49,16 @@ shaka.dash.SegmentBase = class {
|
|
|
46
49
|
}
|
|
47
50
|
|
|
48
51
|
let resolvedUris = context.representation.getBaseUris();
|
|
49
|
-
const uri = initialization.
|
|
52
|
+
const uri = initialization.attributes['sourceURL'];
|
|
50
53
|
if (uri) {
|
|
51
|
-
resolvedUris = ManifestParserUtils.resolveUris(resolvedUris, [
|
|
54
|
+
resolvedUris = ManifestParserUtils.resolveUris(resolvedUris, [
|
|
55
|
+
StringUtils.htmlUnescape(uri),
|
|
56
|
+
]);
|
|
52
57
|
}
|
|
53
58
|
|
|
54
59
|
let startByte = 0;
|
|
55
60
|
let endByte = null;
|
|
56
|
-
const range =
|
|
57
|
-
XmlUtils.parseAttr(initialization, 'range', XmlUtils.parseRange);
|
|
61
|
+
const range = TXml.parseAttr(initialization, 'range', TXml.parseRange);
|
|
58
62
|
if (range) {
|
|
59
63
|
startByte = range.start;
|
|
60
64
|
endByte = range.end;
|
|
@@ -62,14 +66,17 @@ shaka.dash.SegmentBase = class {
|
|
|
62
66
|
|
|
63
67
|
const getUris = () => resolvedUris;
|
|
64
68
|
const qualityInfo = shaka.dash.SegmentBase.createQualityInfo(context);
|
|
65
|
-
|
|
69
|
+
const ref = new shaka.media.InitSegmentReference(
|
|
66
70
|
getUris,
|
|
67
71
|
startByte,
|
|
68
72
|
endByte,
|
|
69
73
|
qualityInfo,
|
|
70
74
|
/* timescale= */ null,
|
|
71
75
|
/* segmentData= */ null,
|
|
72
|
-
|
|
76
|
+
aesKey);
|
|
77
|
+
ref.codecs = context.representation.codecs;
|
|
78
|
+
ref.mimeType = context.representation.mimeType;
|
|
79
|
+
return ref;
|
|
73
80
|
}
|
|
74
81
|
|
|
75
82
|
/**
|
|
@@ -77,17 +84,17 @@ shaka.dash.SegmentBase = class {
|
|
|
77
84
|
*
|
|
78
85
|
* @param {shaka.dash.DashParser.Context} context
|
|
79
86
|
* @param {shaka.dash.DashParser.RequestSegmentCallback} requestSegment
|
|
80
|
-
* @param {shaka.extern.
|
|
87
|
+
* @param {shaka.extern.aesKey|undefined} aesKey
|
|
81
88
|
* @return {shaka.dash.DashParser.StreamInfo}
|
|
82
89
|
*/
|
|
83
|
-
static createStreamInfo(context, requestSegment,
|
|
90
|
+
static createStreamInfo(context, requestSegment, aesKey) {
|
|
84
91
|
goog.asserts.assert(context.representation.segmentBase,
|
|
85
92
|
'Should only be called with SegmentBase');
|
|
86
93
|
// Since SegmentBase does not need updates, simply treat any call as
|
|
87
94
|
// the initial parse.
|
|
88
95
|
const MpdUtils = shaka.dash.MpdUtils;
|
|
89
96
|
const SegmentBase = shaka.dash.SegmentBase;
|
|
90
|
-
const
|
|
97
|
+
const TXml = shaka.util.TXml;
|
|
91
98
|
|
|
92
99
|
const unscaledPresentationTimeOffset = Number(MpdUtils.inheritAttribute(
|
|
93
100
|
context, SegmentBase.fromInheritance_, 'presentationTimeOffset')) || 0;
|
|
@@ -96,14 +103,14 @@ shaka.dash.SegmentBase = class {
|
|
|
96
103
|
context, SegmentBase.fromInheritance_, 'timescale');
|
|
97
104
|
let timescale = 1;
|
|
98
105
|
if (timescaleStr) {
|
|
99
|
-
timescale =
|
|
106
|
+
timescale = TXml.parsePositiveInt(timescaleStr) || 1;
|
|
100
107
|
}
|
|
101
108
|
|
|
102
109
|
const scaledPresentationTimeOffset =
|
|
103
110
|
(unscaledPresentationTimeOffset / timescale) || 0;
|
|
104
111
|
|
|
105
112
|
const initSegmentReference = SegmentBase.createInitSegment(
|
|
106
|
-
context, SegmentBase.fromInheritance_,
|
|
113
|
+
context, SegmentBase.fromInheritance_, aesKey);
|
|
107
114
|
|
|
108
115
|
// Throws an immediate error if the format is unsupported.
|
|
109
116
|
SegmentBase.checkSegmentIndexRangeSupport_(context, initSegmentReference);
|
|
@@ -184,6 +191,10 @@ shaka.dash.SegmentBase = class {
|
|
|
184
191
|
indexData, initData, uris, initSegmentReference, timestampOffset,
|
|
185
192
|
appendWindowStart, appendWindowEnd);
|
|
186
193
|
}
|
|
194
|
+
for (const ref of references) {
|
|
195
|
+
ref.codecs = context.representation.codecs;
|
|
196
|
+
ref.mimeType = context.representation.mimeType;
|
|
197
|
+
}
|
|
187
198
|
|
|
188
199
|
presentationTimeline.notifySegments(references);
|
|
189
200
|
|
|
@@ -201,7 +212,7 @@ shaka.dash.SegmentBase = class {
|
|
|
201
212
|
|
|
202
213
|
/**
|
|
203
214
|
* @param {?shaka.dash.DashParser.InheritanceFrame} frame
|
|
204
|
-
* @return {
|
|
215
|
+
* @return {?shaka.extern.xml.Node}
|
|
205
216
|
* @private
|
|
206
217
|
*/
|
|
207
218
|
static fromInheritance_(frame) {
|
|
@@ -218,17 +229,17 @@ shaka.dash.SegmentBase = class {
|
|
|
218
229
|
static computeIndexRange_(context) {
|
|
219
230
|
const MpdUtils = shaka.dash.MpdUtils;
|
|
220
231
|
const SegmentBase = shaka.dash.SegmentBase;
|
|
221
|
-
const
|
|
232
|
+
const TXml = shaka.util.TXml;
|
|
222
233
|
|
|
223
234
|
const representationIndex = MpdUtils.inheritChild(
|
|
224
235
|
context, SegmentBase.fromInheritance_, 'RepresentationIndex');
|
|
225
236
|
const indexRangeElem = MpdUtils.inheritAttribute(
|
|
226
237
|
context, SegmentBase.fromInheritance_, 'indexRange');
|
|
227
238
|
|
|
228
|
-
let indexRange =
|
|
239
|
+
let indexRange = TXml.parseRange(indexRangeElem || '');
|
|
229
240
|
if (representationIndex) {
|
|
230
|
-
indexRange =
|
|
231
|
-
representationIndex, 'range',
|
|
241
|
+
indexRange = TXml.parseAttr(
|
|
242
|
+
representationIndex, 'range', TXml.parseRange, indexRange);
|
|
232
243
|
}
|
|
233
244
|
return indexRange;
|
|
234
245
|
}
|
|
@@ -244,13 +255,15 @@ shaka.dash.SegmentBase = class {
|
|
|
244
255
|
const ManifestParserUtils = shaka.util.ManifestParserUtils;
|
|
245
256
|
const MpdUtils = shaka.dash.MpdUtils;
|
|
246
257
|
const SegmentBase = shaka.dash.SegmentBase;
|
|
258
|
+
const StringUtils = shaka.util.StringUtils;
|
|
247
259
|
|
|
248
260
|
const representationIndex = MpdUtils.inheritChild(
|
|
249
261
|
context, SegmentBase.fromInheritance_, 'RepresentationIndex');
|
|
250
262
|
|
|
251
263
|
let indexUris = context.representation.getBaseUris();
|
|
252
264
|
if (representationIndex) {
|
|
253
|
-
const representationUri =
|
|
265
|
+
const representationUri =
|
|
266
|
+
StringUtils.htmlUnescape(representationIndex.attributes['sourceURL']);
|
|
254
267
|
if (representationUri) {
|
|
255
268
|
indexUris = ManifestParserUtils.resolveUris(
|
|
256
269
|
indexUris, [representationUri]);
|
package/lib/dash/segment_list.js
CHANGED
|
@@ -16,7 +16,8 @@ goog.require('shaka.media.SegmentReference');
|
|
|
16
16
|
goog.require('shaka.util.Error');
|
|
17
17
|
goog.require('shaka.util.Functional');
|
|
18
18
|
goog.require('shaka.util.ManifestParserUtils');
|
|
19
|
-
goog.require('shaka.util.
|
|
19
|
+
goog.require('shaka.util.StringUtils');
|
|
20
|
+
goog.require('shaka.util.TXml');
|
|
20
21
|
goog.requireType('shaka.dash.DashParser');
|
|
21
22
|
goog.requireType('shaka.media.PresentationTimeline');
|
|
22
23
|
|
|
@@ -31,16 +32,16 @@ shaka.dash.SegmentList = class {
|
|
|
31
32
|
*
|
|
32
33
|
* @param {shaka.dash.DashParser.Context} context
|
|
33
34
|
* @param {!Object.<string, !shaka.extern.Stream>} streamMap
|
|
34
|
-
* @param {shaka.extern.
|
|
35
|
+
* @param {shaka.extern.aesKey|undefined} aesKey
|
|
35
36
|
* @return {shaka.dash.DashParser.StreamInfo}
|
|
36
37
|
*/
|
|
37
|
-
static createStreamInfo(context, streamMap,
|
|
38
|
+
static createStreamInfo(context, streamMap, aesKey) {
|
|
38
39
|
goog.asserts.assert(context.representation.segmentList,
|
|
39
40
|
'Should only be called with SegmentList');
|
|
40
41
|
const SegmentList = shaka.dash.SegmentList;
|
|
41
42
|
|
|
42
43
|
const initSegmentReference = shaka.dash.SegmentBase.createInitSegment(
|
|
43
|
-
context, SegmentList.fromInheritance_,
|
|
44
|
+
context, SegmentList.fromInheritance_, aesKey);
|
|
44
45
|
const info = SegmentList.parseSegmentListInfo_(context);
|
|
45
46
|
|
|
46
47
|
SegmentList.checkSegmentListInfo_(context, info);
|
|
@@ -60,7 +61,8 @@ shaka.dash.SegmentList = class {
|
|
|
60
61
|
const references = SegmentList.createSegmentReferences_(
|
|
61
62
|
context.periodInfo.start, context.periodInfo.duration,
|
|
62
63
|
info.startNumber, context.representation.getBaseUris, info,
|
|
63
|
-
initSegmentReference,
|
|
64
|
+
initSegmentReference, aesKey, context.representation.mimeType,
|
|
65
|
+
context.representation.codecs);
|
|
64
66
|
|
|
65
67
|
const isNew = !segmentIndex;
|
|
66
68
|
if (segmentIndex) {
|
|
@@ -94,7 +96,7 @@ shaka.dash.SegmentList = class {
|
|
|
94
96
|
|
|
95
97
|
/**
|
|
96
98
|
* @param {?shaka.dash.DashParser.InheritanceFrame} frame
|
|
97
|
-
* @return {
|
|
99
|
+
* @return {?shaka.extern.xml.Node}
|
|
98
100
|
* @private
|
|
99
101
|
*/
|
|
100
102
|
static fromInheritance_(frame) {
|
|
@@ -198,13 +200,15 @@ shaka.dash.SegmentList = class {
|
|
|
198
200
|
* @param {function():!Array.<string>} getBaseUris
|
|
199
201
|
* @param {shaka.dash.SegmentList.SegmentListInfo} info
|
|
200
202
|
* @param {shaka.media.InitSegmentReference} initSegmentReference
|
|
201
|
-
* @param {shaka.extern.
|
|
203
|
+
* @param {shaka.extern.aesKey|undefined} aesKey
|
|
204
|
+
* @param {string} mimeType
|
|
205
|
+
* @param {string} codecs
|
|
202
206
|
* @return {!Array.<!shaka.media.SegmentReference>}
|
|
203
207
|
* @private
|
|
204
208
|
*/
|
|
205
209
|
static createSegmentReferences_(
|
|
206
210
|
periodStart, periodDuration, startNumber, getBaseUris, info,
|
|
207
|
-
initSegmentReference,
|
|
211
|
+
initSegmentReference, aesKey, mimeType, codecs) {
|
|
208
212
|
const ManifestParserUtils = shaka.util.ManifestParserUtils;
|
|
209
213
|
|
|
210
214
|
let max = info.mediaSegments.length;
|
|
@@ -251,22 +255,25 @@ shaka.dash.SegmentList = class {
|
|
|
251
255
|
}
|
|
252
256
|
return uris;
|
|
253
257
|
};
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
258
|
+
|
|
259
|
+
const ref = new shaka.media.SegmentReference(
|
|
260
|
+
periodStart + startTime,
|
|
261
|
+
periodStart + endTime,
|
|
262
|
+
getUris,
|
|
263
|
+
segment.start,
|
|
264
|
+
segment.end,
|
|
265
|
+
initSegmentReference,
|
|
266
|
+
timestampOffset,
|
|
267
|
+
appendWindowStart, appendWindowEnd,
|
|
268
|
+
/* partialReferences= */ [],
|
|
269
|
+
/* tilesLayout= */ '',
|
|
270
|
+
/* tileDuration= */ null,
|
|
271
|
+
/* syncTime= */ null,
|
|
272
|
+
shaka.media.SegmentReference.Status.AVAILABLE,
|
|
273
|
+
aesKey);
|
|
274
|
+
ref.codecs = codecs;
|
|
275
|
+
ref.mimeType = mimeType;
|
|
276
|
+
references.push(ref);
|
|
270
277
|
prevEndTime = endTime;
|
|
271
278
|
}
|
|
272
279
|
|
|
@@ -282,21 +289,22 @@ shaka.dash.SegmentList = class {
|
|
|
282
289
|
*/
|
|
283
290
|
static parseMediaSegments_(context) {
|
|
284
291
|
const Functional = shaka.util.Functional;
|
|
285
|
-
/** @type {!Array.<!
|
|
292
|
+
/** @type {!Array.<!shaka.extern.xml.Node>} */
|
|
286
293
|
const segmentLists = [
|
|
287
294
|
context.representation.segmentList,
|
|
288
295
|
context.adaptationSet.segmentList,
|
|
289
296
|
context.period.segmentList,
|
|
290
297
|
].filter(Functional.isNotNull);
|
|
291
298
|
|
|
292
|
-
const
|
|
299
|
+
const TXml = shaka.util.TXml;
|
|
300
|
+
const StringUtils = shaka.util.StringUtils;
|
|
293
301
|
// Search each SegmentList for one with at least one SegmentURL element,
|
|
294
302
|
// select the first one, and convert each SegmentURL element to a tuple.
|
|
295
303
|
return segmentLists
|
|
296
|
-
.map((node) => { return
|
|
304
|
+
.map((node) => { return TXml.findChildren(node, 'SegmentURL'); })
|
|
297
305
|
.reduce((all, part) => { return all.length > 0 ? all : part; })
|
|
298
306
|
.map((urlNode) => {
|
|
299
|
-
if (urlNode.
|
|
307
|
+
if (urlNode.attributes['indexRange'] &&
|
|
300
308
|
!context.indexRangeWarningGiven) {
|
|
301
309
|
context.indexRangeWarningGiven = true;
|
|
302
310
|
shaka.log.warning(
|
|
@@ -305,9 +313,9 @@ shaka.dash.SegmentList = class {
|
|
|
305
313
|
'attribute or SegmentTimeline, which must be accurate.');
|
|
306
314
|
}
|
|
307
315
|
|
|
308
|
-
const uri = urlNode.
|
|
309
|
-
const range =
|
|
310
|
-
urlNode, 'mediaRange',
|
|
316
|
+
const uri = StringUtils.htmlUnescape(urlNode.attributes['media']);
|
|
317
|
+
const range = TXml.parseAttr(
|
|
318
|
+
urlNode, 'mediaRange', TXml.parseRange,
|
|
311
319
|
{start: 0, end: null});
|
|
312
320
|
return {mediaUri: uri, start: range.start, end: range.end};
|
|
313
321
|
});
|