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.
Files changed (120) hide show
  1. package/AUTHORS +1 -0
  2. package/CONTRIBUTORS +1 -0
  3. package/LICENSE +54 -0
  4. package/README.md +22 -1
  5. package/dist/controls.css +1 -1
  6. package/dist/controls.css.map +1 -1
  7. package/dist/deps.js +36 -25
  8. package/dist/locales.js +40 -30
  9. package/dist/shaka-player.compiled.d.ts +196 -46
  10. package/dist/shaka-player.compiled.debug.d.ts +196 -46
  11. package/dist/shaka-player.compiled.debug.externs.js +474 -337
  12. package/dist/shaka-player.compiled.debug.js +992 -871
  13. package/dist/shaka-player.compiled.debug.map +4 -4
  14. package/dist/shaka-player.compiled.externs.js +474 -337
  15. package/dist/shaka-player.compiled.js +1248 -1174
  16. package/dist/shaka-player.compiled.map +4 -4
  17. package/dist/shaka-player.ui.d.ts +259 -49
  18. package/dist/shaka-player.ui.debug.d.ts +259 -49
  19. package/dist/shaka-player.ui.debug.externs.js +591 -376
  20. package/dist/shaka-player.ui.debug.js +1208 -1003
  21. package/dist/shaka-player.ui.debug.map +4 -4
  22. package/dist/shaka-player.ui.externs.js +591 -376
  23. package/dist/shaka-player.ui.js +1533 -1408
  24. package/dist/shaka-player.ui.map +4 -4
  25. package/externs/device_sensor_event.js +18 -0
  26. package/externs/hisense.js +16 -0
  27. package/externs/playstation.js +31 -0
  28. package/externs/shaka/abr_manager.js +3 -1
  29. package/externs/shaka/ads.js +5 -0
  30. package/externs/shaka/codecs.js +13 -0
  31. package/externs/shaka/manifest.js +69 -7
  32. package/externs/shaka/net.js +13 -1
  33. package/externs/shaka/offline.js +7 -1
  34. package/externs/shaka/player.js +184 -13
  35. package/externs/shaka/text.js +19 -0
  36. package/externs/tizen.js +41 -0
  37. package/externs/webos.js +19 -0
  38. package/externs/xbox.js +43 -0
  39. package/lib/abr/simple_abr_manager.js +9 -1
  40. package/lib/ads/ad_manager.js +19 -2
  41. package/lib/ads/client_side_ad_manager.js +5 -3
  42. package/lib/ads/media_tailor_ad_manager.js +9 -0
  43. package/lib/cast/cast_receiver.js +0 -14
  44. package/lib/cast/cast_utils.js +1 -0
  45. package/lib/cea/mp4_cea_parser.js +6 -1
  46. package/lib/dash/content_protection.js +97 -53
  47. package/lib/dash/dash_parser.js +240 -179
  48. package/lib/dash/mpd_utils.js +72 -65
  49. package/lib/dash/segment_base.js +35 -22
  50. package/lib/dash/segment_list.js +39 -31
  51. package/lib/dash/segment_template.js +47 -23
  52. package/lib/hls/hls_parser.js +376 -165
  53. package/lib/media/buffering_observer.js +25 -1
  54. package/lib/media/drm_engine.js +91 -71
  55. package/lib/media/manifest_filterer.js +220 -0
  56. package/lib/media/media_source_engine.js +108 -29
  57. package/lib/media/playhead.js +3 -3
  58. package/lib/media/preload_manager.js +827 -0
  59. package/lib/media/presentation_timeline.js +11 -0
  60. package/lib/media/segment_index.js +60 -49
  61. package/lib/media/segment_prefetch.js +140 -43
  62. package/lib/media/segment_reference.js +31 -8
  63. package/lib/media/segment_utils.js +208 -25
  64. package/lib/media/streaming_engine.js +321 -77
  65. package/lib/mss/content_protection.js +31 -25
  66. package/lib/mss/mss_parser.js +78 -55
  67. package/lib/net/networking_engine.js +49 -4
  68. package/lib/offline/indexeddb/v1_storage_cell.js +2 -0
  69. package/lib/offline/indexeddb/v2_storage_cell.js +2 -0
  70. package/lib/offline/manifest_converter.js +10 -3
  71. package/lib/offline/storage.js +5 -3
  72. package/lib/player.js +896 -674
  73. package/lib/polyfill/media_capabilities.js +16 -1
  74. package/lib/text/simple_text_displayer.js +9 -0
  75. package/lib/text/stub_text_displayer.js +7 -0
  76. package/lib/text/text_engine.js +16 -3
  77. package/lib/text/ttml_text_parser.js +116 -114
  78. package/lib/text/ui_text_displayer.js +28 -11
  79. package/lib/text/vtt_text_parser.js +54 -115
  80. package/lib/transmuxer/opus.js +91 -0
  81. package/lib/transmuxer/ts_transmuxer.js +115 -0
  82. package/lib/util/cmcd_manager.js +152 -3
  83. package/lib/util/dom_utils.js +11 -0
  84. package/lib/util/error.js +5 -0
  85. package/lib/util/fake_event.js +2 -0
  86. package/lib/util/manifest_parser_utils.js +97 -3
  87. package/lib/util/mime_utils.js +10 -5
  88. package/lib/util/mp4_box_parsers.js +346 -17
  89. package/lib/util/mp4_generator.js +23 -0
  90. package/lib/util/periods.js +24 -37
  91. package/lib/util/platform.js +161 -9
  92. package/lib/util/player_configuration.js +61 -3
  93. package/lib/util/stats.js +16 -0
  94. package/lib/util/stream_utils.js +350 -277
  95. package/lib/util/string_utils.js +36 -0
  96. package/lib/util/tXml.js +814 -0
  97. package/lib/util/ts_parser.js +50 -0
  98. package/lib/util/xml_utils.js +10 -338
  99. package/package.json +2 -2
  100. package/shaka-player.uncompiled.js +8 -0
  101. package/ui/controls.js +187 -5
  102. package/ui/enums.js +2 -0
  103. package/ui/externs/ui.js +30 -3
  104. package/ui/gl_matrix/matrix_4x4.js +568 -0
  105. package/ui/gl_matrix/matrix_quaternion.js +45 -0
  106. package/ui/less/containers.less +11 -0
  107. package/ui/locales/en-GB.json +2 -0
  108. package/ui/locales/en.json +2 -0
  109. package/ui/locales/es-419.json +2 -0
  110. package/ui/locales/es.json +2 -0
  111. package/ui/locales/source.json +8 -0
  112. package/ui/recenter_vr.js +126 -0
  113. package/ui/resolution_selection.js +25 -5
  114. package/ui/statistics_button.js +12 -0
  115. package/ui/text_selection.js +1 -1
  116. package/ui/toggle_stereoscopic.js +127 -0
  117. package/ui/ui.js +74 -38
  118. package/ui/vr_manager.js +557 -0
  119. package/ui/vr_utils.js +232 -0
  120. package/ui/vr_webgl.js +697 -0
@@ -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.XmlUtils');
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 {!Element} segmentTimeline
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 XmlUtils = shaka.util.XmlUtils;
144
+ const TXml = shaka.util.TXml;
145
145
 
146
- const timePoints = XmlUtils.findChildren(segmentTimeline, 'S');
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 = XmlUtils.parseAttr(timePoint, 't', XmlUtils.parseNonNegativeInt);
155
+ let t = TXml.parseAttr(timePoint, 't', TXml.parseNonNegativeInt);
156
156
  const d =
157
- XmlUtils.parseAttr(timePoint, 'd', XmlUtils.parseNonNegativeInt);
158
- const r = XmlUtils.parseAttr(timePoint, 'r', XmlUtils.parseInt);
157
+ TXml.parseAttr(timePoint, 'd', TXml.parseNonNegativeInt);
158
+ const r = TXml.parseAttr(timePoint, 'r', TXml.parseInt);
159
159
 
160
- const k = XmlUtils.parseAttr(timePoint, 'k', XmlUtils.parseInt);
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
- XmlUtils.parseAttr(next, 't', XmlUtils.parseNonNegativeInt);
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):Element} callback
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 XmlUtils = shaka.util.XmlUtils;
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 = XmlUtils.parsePositiveInt(timescaleStr) || 1;
279
+ timescale = TXml.parsePositiveInt(timescaleStr) || 1;
279
280
  }
280
281
 
281
282
  const durationStr =
282
283
  MpdUtils.inheritAttribute(context, callback, 'duration');
283
- let segmentDuration = XmlUtils.parsePositiveInt(durationStr || '');
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 = XmlUtils.parseFloat(durationStr || '');
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 = XmlUtils.parseNonNegativeInt(startNumberStr || '');
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):Element} callback
330
- * @return {!Array.<!Element>}
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):Element} callback
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.getAttribute(attribute);
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):Element} callback
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 {Element}
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 XmlUtils = shaka.util.XmlUtils;
386
+ const TXml = shaka.util.TXml;
383
387
  let result = null;
384
388
  for (const node of nodes) {
385
- result = XmlUtils.findChild(node, child);
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 {!Element} element
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.<!Element>}
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 XmlUtils = shaka.util.XmlUtils;
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 = XmlUtils.getAttributeNS(element, NS, 'href');
420
+ const xlinkHref = TXml.getAttributeNS(element, NS, 'href');
417
421
  const xlinkActuate =
418
- XmlUtils.getAttributeNS(element, NS, 'actuate') || 'onRequest';
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 attribute of Array.from(element.attributes)) {
423
- if (attribute.namespaceURI == NS) {
424
- element.removeAttributeNS(attribute.namespaceURI, attribute.localName);
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
- shaka.util.XmlUtils.parseXml(response.data, element.tagName);
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
- while (element.childNodes.length) {
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.childNodes.length) {
486
- const child = rootElem.childNodes[0];
487
- rootElem.removeChild(child);
488
- element.appendChild(child);
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 attribute of Array.from(rootElem.attributes)) {
493
- element.setAttributeNode(attribute.cloneNode(/* deep= */ false));
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 {!Element} element
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.<!Element>}
518
+ * @return {!shaka.util.AbortableOperation.<!shaka.extern.xml.Node>}
513
519
  */
514
520
  static processXlinks(
515
- element, retryParameters, failGracefully, baseUri, networkingEngine,
521
+ element, retryParameters,
522
+ failGracefully, baseUri, networkingEngine,
516
523
  linkDepth = 0) {
517
524
  const MpdUtils = shaka.dash.MpdUtils;
518
- const XmlUtils = shaka.util.XmlUtils;
525
+ const TXml = shaka.util.TXml;
519
526
  const NS = MpdUtils.XlinkNamespaceUri_;
520
527
 
521
- if (XmlUtils.getAttributeNS(element, NS, 'href')) {
528
+ if (TXml.getAttributeNS(element, NS, 'href')) {
522
529
  let handled = MpdUtils.handleXlinkInElement_(
523
- element, retryParameters, failGracefully, baseUri, networkingEngine,
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 Array.from(element.childNodes)) {
541
- if (child instanceof Element) {
542
- const resolveToZeroString = 'urn:mpeg:dash:resolve-to-zero:2013';
543
- if (XmlUtils.getAttributeNS(child, NS, 'href') == resolveToZeroString) {
544
- // This is a 'resolve to zero' code; it means the element should
545
- // be removed, as specified by the mpeg-dash rules for xlink.
546
- element.removeChild(child);
547
- } else if (child.tagName != 'SegmentTimeline') {
548
- // Don't recurse into a SegmentTimeline since xlink attributes
549
- // aren't valid in there and looking at each segment can take a long
550
- // time with larger manifests.
551
-
552
- // Replace the child with its processed form.
553
- childOperations.push(shaka.dash.MpdUtils.processXlinks(
554
- /** @type {!Element} */ (child), retryParameters, failGracefully,
555
- baseUri, networkingEngine, linkDepth));
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
 
@@ -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.XmlUtils');
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):Element} callback
34
- * @param {shaka.extern.aes128Key|undefined} aes128Key
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, aes128Key) {
39
+ static createInitSegment(context, callback, aesKey) {
38
40
  const MpdUtils = shaka.dash.MpdUtils;
39
- const XmlUtils = shaka.util.XmlUtils;
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.getAttribute('sourceURL');
52
+ const uri = initialization.attributes['sourceURL'];
50
53
  if (uri) {
51
- resolvedUris = ManifestParserUtils.resolveUris(resolvedUris, [uri]);
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
- return new shaka.media.InitSegmentReference(
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
- aes128Key);
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.aes128Key|undefined} aes128Key
87
+ * @param {shaka.extern.aesKey|undefined} aesKey
81
88
  * @return {shaka.dash.DashParser.StreamInfo}
82
89
  */
83
- static createStreamInfo(context, requestSegment, aes128Key) {
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 XmlUtils = shaka.util.XmlUtils;
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 = XmlUtils.parsePositiveInt(timescaleStr) || 1;
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_, aes128Key);
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 {Element}
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 XmlUtils = shaka.util.XmlUtils;
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 = XmlUtils.parseRange(indexRangeElem || '');
239
+ let indexRange = TXml.parseRange(indexRangeElem || '');
229
240
  if (representationIndex) {
230
- indexRange = XmlUtils.parseAttr(
231
- representationIndex, 'range', XmlUtils.parseRange, indexRange);
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 = representationIndex.getAttribute('sourceURL');
265
+ const representationUri =
266
+ StringUtils.htmlUnescape(representationIndex.attributes['sourceURL']);
254
267
  if (representationUri) {
255
268
  indexUris = ManifestParserUtils.resolveUris(
256
269
  indexUris, [representationUri]);
@@ -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.XmlUtils');
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.aes128Key|undefined} aes128Key
35
+ * @param {shaka.extern.aesKey|undefined} aesKey
35
36
  * @return {shaka.dash.DashParser.StreamInfo}
36
37
  */
37
- static createStreamInfo(context, streamMap, aes128Key) {
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_, aes128Key);
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, aes128Key);
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 {Element}
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.aes128Key|undefined} aes128Key
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, aes128Key) {
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
- references.push(
255
- new shaka.media.SegmentReference(
256
- periodStart + startTime,
257
- periodStart + endTime,
258
- getUris,
259
- segment.start,
260
- segment.end,
261
- initSegmentReference,
262
- timestampOffset,
263
- appendWindowStart, appendWindowEnd,
264
- /* partialReferences= */ [],
265
- /* tilesLayout= */ '',
266
- /* tileDuration= */ null,
267
- /* syncTime= */ null,
268
- shaka.media.SegmentReference.Status.AVAILABLE,
269
- aes128Key));
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.<!Element>} */
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 XmlUtils = shaka.util.XmlUtils;
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 XmlUtils.findChildren(node, 'SegmentURL'); })
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.getAttribute('indexRange') &&
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.getAttribute('media');
309
- const range = XmlUtils.parseAttr(
310
- urlNode, 'mediaRange', XmlUtils.parseRange,
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
  });