-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Parse <SegmentList> and <SegmentBase> #18
Changes from 1 commit
fb9b91a
e31b500
8629106
9e06c2c
6b89e5a
0fa09fc
2a9f36a
1d5b64f
e7469b6
2e4b4ec
4539d9c
9b1aad7
8bb1413
b9f69ad
06cd527
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -51,24 +51,41 @@ export const buildBaseUrls = (referenceUrls, baseUrlElements) => { | |
export const getSegmentInformation = (adaptationSet) => { | ||
const segmentTemplate = findChildren(adaptationSet, 'SegmentTemplate')[0]; | ||
const segmentList = findChildren(adaptationSet, 'SegmentList')[0]; | ||
const segmentUrls = segmentList && findChildren(segmentList, 'SegmentURL'); | ||
const segmentUrls = segmentList && findChildren(segmentList, 'SegmentURL') | ||
.map(s => shallowMerge({ tag: 'SegmentURL' }, getAttributes(s))); | ||
const segmentBase = findChildren(adaptationSet, 'SegmentBase')[0]; | ||
const segmentTimelineNode = segmentList ? segmentList : segmentTemplate; | ||
const segmentTimelineNode = segmentList || segmentTemplate; | ||
const segmentTimeline = | ||
segmentTimelineNode && findChildren(segmentTimelineNode, 'SegmentTimeline')[0]; | ||
const segmentInitializationNode = segmentList || segmentBase || segmentTemplate; | ||
const segmentInitialization = segmentInitializationNode && | ||
findChildren(segmentInitializationNode, 'Initialization')[0]; | ||
|
||
// SegmentTemplate is handled slightly differently, since it can have both @initialization | ||
// and an <Initialization> node. @initialization can be templated, while the node can have a | ||
// url and range specified. If the <SegmentTemplate> has both @initialization and | ||
// an <Initialization> subelement we opt to override with the node, | ||
// as this interaction is not defined in the spec. | ||
const template = segmentTemplate && getAttributes(segmentTemplate); | ||
|
||
if (template && segmentInitialization) { | ||
template.initialization = getAttributes(segmentInitialization); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be good if we can account for the
This way in |
||
} | ||
|
||
return { | ||
template: segmentTemplate && getAttributes(segmentTemplate), | ||
template, | ||
timeline: segmentTimeline && | ||
findChildren(segmentTimeline, 'S').map(s => getAttributes(s)), | ||
list: segmentList && | ||
shallowMerge(getAttributes(segmentList), | ||
{ | ||
segmentUrls: segmentUrls && | ||
segmentUrls.map(s => | ||
shallowMerge({ tag: 'SegmentURL' }, getAttributes(s))) | ||
}), | ||
base: segmentBase && getAttributes(segmentBase) | ||
findChildren(segmentTimeline, 'S').map(s => getAttributes(s)), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know that this line was added by me, including the indentation, but do you mind fixing the indentation here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wonder why the linter didn't catch this one, I think it gave me a warning or error for the indentation under There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ya I'm surprised I added it myself, and didn't catch it myself or with the linter. Its not even lined up with anything ha |
||
list: segmentList && shallowMerge( | ||
getAttributes(segmentList), | ||
{ | ||
segmentUrls, | ||
initialization: getAttributes(segmentInitialization) | ||
}), | ||
base: segmentBase && shallowMerge( | ||
getAttributes(segmentBase), { | ||
initialization: getAttributes(segmentInitialization) | ||
}) | ||
}; | ||
}; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
import resolveUrl from '../utils/resolveUrl'; | ||
import urlTypeToSegment from './urlType'; | ||
import { parseByDuration, parseByTimeline } from './timeParser'; | ||
|
||
const identifierPattern = /\$([A-z]*)(?:(%0)([0-9]+)d)?\$/g; | ||
|
@@ -151,7 +152,26 @@ export const segmentsFromTemplate = (attributes, segmentTimeline) => { | |
RepresentationID: attributes.id, | ||
Bandwidth: parseInt(attributes.bandwidth || 0, 10) | ||
}; | ||
const mapUri = constructTemplateUrl(attributes.initialization || '', templateValues); | ||
|
||
let mapSegment = { uri: '', resolvedUri: resolveUrl(attributes.baseUrl || '', '') }; | ||
|
||
if (attributes.initialization && typeof attributes.initialization === 'string') { | ||
const mapUri = constructTemplateUrl(attributes.initialization || '', templateValues); | ||
|
||
mapSegment = { | ||
uri: mapUri, | ||
resolvedUri: resolveUrl(attributes.baseUrl || '', mapUri) | ||
}; | ||
} | ||
|
||
if (attributes.initialization && typeof attributes.initialization === 'object') { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Based on what I picked up off the spec, |
||
mapSegment = urlTypeToSegment({ | ||
baseUrl: attributes.baseUrl, | ||
source: attributes.initialization.sourceURL, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With the changes proposed in my other comment to handle the string to object conversion in
In the case that the |
||
range: attributes.initialization.range | ||
}); | ||
} | ||
|
||
const segments = parseTemplateInfo(attributes, segmentTimeline); | ||
|
||
return segments.map(segment => { | ||
|
@@ -165,10 +185,7 @@ export const segmentsFromTemplate = (attributes, segmentTimeline) => { | |
timeline: segment.timeline, | ||
duration: segment.duration, | ||
resolvedUri: resolveUrl(attributes.baseUrl || '', uri), | ||
map: { | ||
uri: mapUri, | ||
resolvedUri: resolveUrl(attributes.baseUrl || '', mapUri) | ||
} | ||
map: mapSegment | ||
}; | ||
}); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import resolveUrl from '../utils/resolveUrl'; | ||
|
||
/** | ||
* @typedef {Object} SingleUri | ||
* @property {string} uri - relative location of segment | ||
* @property {string} resolvedUri - resolved location of segment | ||
* @property {Object} byterange - Object containing information on how to make byte range | ||
* requests following byte-range-spec per RFC2616. | ||
* @property {String} byterange.length - length of range request | ||
* @property {String} byterange.offset - byte offset of range request | ||
* | ||
* @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.1 | ||
*/ | ||
|
||
/** | ||
* Converts a URLType node (5.3.9.2.3 Table 13) to a segment object | ||
* that conforms to how m3u8-parser is structured | ||
* | ||
* @see https://github.com/videojs/m3u8-parser | ||
* | ||
* @param {string} baseUrl - baseUrl provided by <BaseUrl> nodes | ||
* @param {string} source - source url for segment | ||
* @param {string} range - optional range used for range calls, follows | ||
* @return {SingleUri} full segment information transformed into a format similar | ||
* to m3u8-parser | ||
*/ | ||
export const urlTypeToSegment = ({ baseUrl = '', source = '', range = '' }) => { | ||
const init = { | ||
uri: source, | ||
resolvedUri: resolveUrl(baseUrl || '', source) | ||
}; | ||
|
||
if (source && range) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think
The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch. I made an assumption that both were required but the existence of baseUrl makes that a poor assumption. |
||
const ranges = range.split('-'); | ||
const startRange = parseInt(ranges[0], 10); | ||
const endRange = parseInt(ranges[1], 10); | ||
|
||
init.byterange = { | ||
length: endRange - startRange, | ||
offset: startRange | ||
}; | ||
} | ||
|
||
return init; | ||
}; | ||
|
||
export default urlTypeToSegment; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These variable names are a bit misleading.
segmentTimelineNode
andsegmentInitializationNode
are actually the parent nodes of those nodes