@@ -16,21 +16,21 @@ const keySystemsMap = {
16
16
/**
17
17
* Builds a list of urls that is the product of the reference urls and BaseURL values
18
18
*
19
- * @param {string [] } referenceUrls
20
- * List of reference urls to resolve to
19
+ * @param {Object [] } references
20
+ * List of objects containing the reference URL as well as its attributes
21
21
* @param {Node[] } baseUrlElements
22
22
* List of BaseURL nodes from the mpd
23
- * @return {string [] }
24
- * List of resolved urls
23
+ * @return {Object [] }
24
+ * List of objects with resolved urls and attributes
25
25
*/
26
- export const buildBaseUrls = ( referenceUrls , baseUrlElements ) => {
26
+ export const buildBaseUrls = ( references , baseUrlElements ) => {
27
27
if ( ! baseUrlElements . length ) {
28
- return referenceUrls ;
28
+ return references ;
29
29
}
30
30
31
- return flatten ( referenceUrls . map ( function ( reference ) {
31
+ return flatten ( references . map ( function ( reference ) {
32
32
return baseUrlElements . map ( function ( baseUrlElement ) {
33
- return resolveUrl ( reference , getContent ( baseUrlElement ) ) ;
33
+ return merge ( parseAttributes ( baseUrlElement ) , { baseUrl : resolveUrl ( reference . baseUrl , getContent ( baseUrlElement ) ) } ) ;
34
34
} ) ;
35
35
} ) ) ;
36
36
} ;
@@ -140,8 +140,9 @@ export const getSegmentInformation = (adaptationSet) => {
140
140
*
141
141
* @param {Object } adaptationSetAttributes
142
142
* Contains attributes inherited by the AdaptationSet
143
- * @param {string[] } adaptationSetBaseUrls
144
- * Contains list of resolved base urls inherited by the AdaptationSet
143
+ * @param {Object[] } adaptationSetBaseUrls
144
+ * List of objects containing resolved base URLs and attributes
145
+ * inherited by the AdaptationSet
145
146
* @param {SegmentInformation } adaptationSetSegmentInfo
146
147
* Contains Segment information for the AdaptationSet
147
148
* @return {inheritBaseUrlsCallback }
@@ -158,7 +159,7 @@ export const inheritBaseUrls =
158
159
return repBaseUrls . map ( baseUrl => {
159
160
return {
160
161
segmentInfo : merge ( adaptationSetSegmentInfo , representationSegmentInfo ) ,
161
- attributes : merge ( attributes , { baseUrl } )
162
+ attributes : merge ( attributes , baseUrl )
162
163
} ;
163
164
} ) ;
164
165
} ;
@@ -340,8 +341,9 @@ export const toEventStream = (period) => {
340
341
*
341
342
* @param {Object } periodAttributes
342
343
* Contains attributes inherited by the Period
343
- * @param {string[] } periodBaseUrls
344
- * Contains list of resolved base urls inherited by the Period
344
+ * @param {Object[] } periodBaseUrls
345
+ * Contains list of objects with resolved base urls and attributes
346
+ * inherited by the Period
345
347
* @param {string[] } periodSegmentInfo
346
348
* Contains Segment Information at the period level
347
349
* @return {toRepresentationsCallback }
@@ -421,8 +423,9 @@ export const toRepresentations =
421
423
*
422
424
* @param {Object } mpdAttributes
423
425
* Contains attributes inherited by the mpd
424
- * @param {string[] } mpdBaseUrls
425
- * Contains list of resolved base urls inherited by the mpd
426
+ * @param {Object[] } mpdBaseUrls
427
+ * Contains list of objects with resolved base urls and attributes
428
+ * inherited by the mpd
426
429
* @return {toAdaptationSetsCallback }
427
430
* Callback map function
428
431
*/
@@ -441,6 +444,41 @@ export const toAdaptationSets = (mpdAttributes, mpdBaseUrls) => (period, index)
441
444
return flatten ( adaptationSets . map ( toRepresentations ( periodAttributes , periodBaseUrls , periodSegmentInfo ) ) ) ;
442
445
} ;
443
446
447
+ /**
448
+ * Tranforms an array of content steering nodes into an object
449
+ * containing CDN content steering information from the MPD manifest.
450
+ *
451
+ * For more information on the DASH spec for Content Steering parsing, see:
452
+ * https://dashif.org/docs/DASH-IF-CTS-00XX-Content-Steering-Community-Review.pdf
453
+ *
454
+ * @param {Node[] } contentSteeringNodes
455
+ * Content steering nodes
456
+ * @param {Function } eventHandler
457
+ * The event handler passed into the parser options to handle warnings
458
+ * @return {Object }
459
+ * Object containing content steering data
460
+ */
461
+ export const generateContentSteeringInformation = ( contentSteeringNodes , eventHandler ) => {
462
+ // If there are more than one ContentSteering tags, throw an error
463
+ if ( contentSteeringNodes . length > 1 ) {
464
+ eventHandler ( { type : 'warn' , message : 'The MPD manifest should contain no more than one ContentSteering tag' } ) ;
465
+ }
466
+
467
+ // Return a null value if there are no ContentSteering tags
468
+ if ( ! contentSteeringNodes . length ) {
469
+ return null ;
470
+ }
471
+
472
+ const infoFromContentSteeringTag =
473
+ merge ( { serverURL : getContent ( contentSteeringNodes [ 0 ] ) } , parseAttributes ( contentSteeringNodes [ 0 ] ) ) ;
474
+
475
+ // Converts `queryBeforeStart` to a boolean, as well as setting the default value
476
+ // to `false` if it doesn't exist
477
+ infoFromContentSteeringTag . queryBeforeStart = ( infoFromContentSteeringTag . queryBeforeStart === 'true' ) ;
478
+
479
+ return infoFromContentSteeringTag ;
480
+ } ;
481
+
444
482
/**
445
483
* Gets Period@start property for a given period.
446
484
*
@@ -518,7 +556,14 @@ export const inheritAttributes = (mpd, options = {}) => {
518
556
const {
519
557
manifestUri = '' ,
520
558
NOW = Date . now ( ) ,
521
- clientOffset = 0
559
+ clientOffset = 0 ,
560
+ // TODO: For now, we are expecting an eventHandler callback function
561
+ // to be passed into the mpd parser as an option.
562
+ // In the future, we should enable stream parsing by using the Stream class from vhs-utils.
563
+ // This will support new features including a standardized event handler.
564
+ // See the m3u8 parser for examples of how stream parsing is currently used for HLS parsing.
565
+ // https://github.com/videojs/vhs-utils/blob/88d6e10c631e57a5af02c5a62bc7376cd456b4f5/src/stream.js#L9
566
+ eventHandler = function ( ) { }
522
567
} = options ;
523
568
const periodNodes = findChildren ( mpd , 'Period' ) ;
524
569
@@ -530,6 +575,7 @@ export const inheritAttributes = (mpd, options = {}) => {
530
575
531
576
const mpdAttributes = parseAttributes ( mpd ) ;
532
577
const mpdBaseUrls = buildBaseUrls ( [ manifestUri ] , findChildren ( mpd , 'BaseURL' ) ) ;
578
+ const contentSteeringNodes = findChildren ( mpd , 'ContentSteering' ) ;
533
579
534
580
// See DASH spec section 5.3.1.2, Semantics of MPD element. Default type to 'static'.
535
581
mpdAttributes . type = mpdAttributes . type || 'static' ;
@@ -567,6 +613,14 @@ export const inheritAttributes = (mpd, options = {}) => {
567
613
568
614
return {
569
615
locations : mpdAttributes . locations ,
616
+ contentSteeringInfo : generateContentSteeringInformation ( contentSteeringNodes , eventHandler ) ,
617
+ // TODO: There are occurences where this `representationInfo` array contains undesired
618
+ // duplicates. This generally occurs when there are multiple BaseURL nodes that are
619
+ // direct children of the MPD node. When we attempt to resolve URLs from a combination of the
620
+ // parent BaseURL and a child BaseURL, and the value does not resolve,
621
+ // we end up returning the child BaseURL multiple times.
622
+ // We need to determine a way to remove these duplicates in a safe way.
623
+ // See: https://github.com/videojs/mpd-parser/pull/17#discussion_r162750527
570
624
representationInfo : flatten ( periods . map ( toAdaptationSets ( mpdAttributes , mpdBaseUrls ) ) ) ,
571
625
eventStream : flatten ( periods . map ( toEventStream ) )
572
626
} ;
0 commit comments