Files
Vulture/VApp/node_modules/mpd-parser/src/segment/segmentList.js

100 lines
3.3 KiB
JavaScript

import { parseByTimeline } from './timelineTimeParser';
import { parseByDuration } from './durationTimeParser';
import urlTypeConverter from './urlType';
import errors from '../errors';
/**
* Converts a <SegmentUrl> (of type URLType from the DASH spec 5.3.9.2 Table 14)
* to an object that matches the output of a segment in videojs/mpd-parser
*
* @param {Object} attributes
* Object containing all inherited attributes from parent elements with attribute
* names as keys
* @param {Object} segmentUrl
* <SegmentURL> node to translate into a segment object
* @return {Object} translated segment object
*/
const SegmentURLToSegmentObject = (attributes, segmentUrl) => {
const { baseUrl, initialization = {} } = attributes;
const initSegment = urlTypeConverter({
baseUrl,
source: initialization.sourceURL,
range: initialization.range
});
const segment = urlTypeConverter({
baseUrl,
source: segmentUrl.media,
range: segmentUrl.mediaRange
});
segment.map = initSegment;
return segment;
};
/**
* Generates a list of segments using information provided by the SegmentList element
* SegmentList (DASH SPEC Section 5.3.9.3.2) contains a set of <SegmentURL> nodes. Each
* node should be translated into segment.
*
* @param {Object} attributes
* Object containing all inherited attributes from parent elements with attribute
* names as keys
* @param {Object[]|undefined} segmentTimeline
* List of objects representing the attributes of each S element contained within
* the SegmentTimeline element
* @return {Object.<Array>} list of segments
*/
export const segmentsFromList = (attributes, segmentTimeline) => {
const {
duration,
segmentUrls = [],
periodStart
} = attributes;
// Per spec (5.3.9.2.1) no way to determine segment duration OR
// if both SegmentTimeline and @duration are defined, it is outside of spec.
if ((!duration && !segmentTimeline) ||
(duration && segmentTimeline)) {
throw new Error(errors.SEGMENT_TIME_UNSPECIFIED);
}
const segmentUrlMap = segmentUrls.map(segmentUrlObject =>
SegmentURLToSegmentObject(attributes, segmentUrlObject));
let segmentTimeInfo;
if (duration) {
segmentTimeInfo = parseByDuration(attributes);
}
if (segmentTimeline) {
segmentTimeInfo = parseByTimeline(attributes, segmentTimeline);
}
const segments = segmentTimeInfo.map((segmentTime, index) => {
if (segmentUrlMap[index]) {
const segment = segmentUrlMap[index];
// See DASH spec section 5.3.9.2.2
// - if timescale isn't present on any level, default to 1.
const timescale = attributes.timescale || 1;
// - if presentationTimeOffset isn't present on any level, default to 0
const presentationTimeOffset = attributes.presentationTimeOffset || 0;
segment.timeline = segmentTime.timeline;
segment.duration = segmentTime.duration;
segment.number = segmentTime.number;
segment.presentationTime =
periodStart + ((segmentTime.time - presentationTimeOffset) / timescale);
return segment;
}
// Since we're mapping we should get rid of any blank segments (in case
// the given SegmentTimeline is handling for more elements than we have
// SegmentURLs for).
}).filter(segment => segment);
return segments;
};