mpd-parser
Advanced tools
Comparing version 0.6.1 to 0.7.0
@@ -0,1 +1,18 @@ | ||
<a name="0.7.0"></a> | ||
# [0.7.0](https://github.com/videojs/mpd-parser/compare/v0.6.1...v0.7.0) (2018-10-24) | ||
### Features | ||
* limited multiperiod support ([#35](https://github.com/videojs/mpd-parser/issues/35)) ([aee87a0](https://github.com/videojs/mpd-parser/commit/aee87a0)) | ||
### Bug Fixes | ||
* fixed segment timeline parsing when duration is present ([#34](https://github.com/videojs/mpd-parser/issues/34)) ([90feb2d](https://github.com/videojs/mpd-parser/commit/90feb2d)) | ||
* Remove the postinstall script to prevent install issues ([#29](https://github.com/videojs/mpd-parser/issues/29)) ([ae458f4](https://github.com/videojs/mpd-parser/commit/ae458f4)) | ||
### Chores | ||
* Update to generator-videojs-plugin[@7](https://github.com/7).2.0 ([#28](https://github.com/videojs/mpd-parser/issues/28)) ([909cf08](https://github.com/videojs/mpd-parser/commit/909cf08)) | ||
* **package:** Update dependencies to enable Greenkeeper 🌴 ([#30](https://github.com/videojs/mpd-parser/issues/30)) ([0593c2c](https://github.com/videojs/mpd-parser/commit/0593c2c)) | ||
<a name="0.6.1"></a> | ||
@@ -2,0 +19,0 @@ ## [0.6.1](https://github.com/videojs/mpd-parser/compare/v0.6.0...v0.6.1) (2018-05-17) |
@@ -1,16 +0,110 @@ | ||
/** | ||
* mpd-parser | ||
* @version 0.6.1 | ||
* @copyright 2018 Brightcove, Inc | ||
* @license Apache-2.0 | ||
*/ | ||
/*! @name mpd-parser @version 0.7.0 @license Apache-2.0 */ | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } | ||
var URLToolkit = _interopDefault(require('url-toolkit')); | ||
var window = _interopDefault(require('global/window')); | ||
var window$1 = _interopDefault(require('global/window')); | ||
var version = "0.6.1"; | ||
var version = "0.7.0"; | ||
var isObject = function isObject(obj) { | ||
return !!obj && typeof obj === 'object'; | ||
}; | ||
var merge = function merge() { | ||
for (var _len = arguments.length, objects = new Array(_len), _key = 0; _key < _len; _key++) { | ||
objects[_key] = arguments[_key]; | ||
} | ||
return objects.reduce(function (result, source) { | ||
Object.keys(source).forEach(function (key) { | ||
if (Array.isArray(result[key]) && Array.isArray(source[key])) { | ||
result[key] = result[key].concat(source[key]); | ||
} else if (isObject(result[key]) && isObject(source[key])) { | ||
result[key] = merge(result[key], source[key]); | ||
} else { | ||
result[key] = source[key]; | ||
} | ||
}); | ||
return result; | ||
}, {}); | ||
}; | ||
var values = function values(o) { | ||
return Object.keys(o).map(function (k) { | ||
return o[k]; | ||
}); | ||
}; | ||
var range = function range(start, end) { | ||
var result = []; | ||
for (var i = start; i < end; i++) { | ||
result.push(i); | ||
} | ||
return result; | ||
}; | ||
var flatten = function flatten(lists) { | ||
return lists.reduce(function (x, y) { | ||
return x.concat(y); | ||
}, []); | ||
}; | ||
var from = function from(list) { | ||
if (!list.length) { | ||
return []; | ||
} | ||
var result = []; | ||
for (var i = 0; i < list.length; i++) { | ||
result.push(list[i]); | ||
} | ||
return result; | ||
}; | ||
var findIndexes = function findIndexes(l, key) { | ||
return l.reduce(function (a, e, i) { | ||
if (e[key]) { | ||
a.push(i); | ||
} | ||
return a; | ||
}, []); | ||
}; | ||
var mergeDiscontiguousPlaylists = function mergeDiscontiguousPlaylists(playlists) { | ||
var mergedPlaylists = values(playlists.reduce(function (acc, playlist) { | ||
// assuming playlist IDs are the same across periods | ||
// TODO: handle multiperiod where representation sets are not the same | ||
// across periods | ||
var name = playlist.attributes.id + (playlist.attributes.lang || ''); // Periods after first | ||
if (acc[name]) { | ||
var _acc$name$segments; | ||
// first segment of subsequent periods signal a discontinuity | ||
playlist.segments[0].discontinuity = true; | ||
(_acc$name$segments = acc[name].segments).push.apply(_acc$name$segments, playlist.segments); // bubble up contentProtection, this assumes all DRM content | ||
// has the same contentProtection | ||
if (playlist.attributes.contentProtection) { | ||
acc[name].attributes.contentProtection = playlist.attributes.contentProtection; | ||
} | ||
} else { | ||
// first Period | ||
acc[name] = playlist; | ||
} | ||
return acc; | ||
}, {})); | ||
return mergedPlaylists.map(function (playlist) { | ||
playlist.discontinuityStarts = findIndexes(playlist.segments, 'discontinuity'); | ||
return playlist; | ||
}); | ||
}; | ||
var formatAudioPlaylist = function formatAudioPlaylist(_ref) { | ||
@@ -21,3 +115,2 @@ var _attributes; | ||
segments = _ref.segments; | ||
var playlist = { | ||
@@ -44,3 +137,2 @@ attributes: (_attributes = { | ||
}; | ||
var formatVttPlaylist = function formatVttPlaylist(_ref2) { | ||
@@ -60,6 +152,7 @@ var _attributes2; | ||
number: 0 | ||
}]; | ||
// targetDuration should be the same duration as the only segment | ||
}]; // targetDuration should be the same duration as the only segment | ||
attributes.duration = attributes.sourceDuration; | ||
} | ||
return { | ||
@@ -79,3 +172,2 @@ attributes: (_attributes2 = { | ||
}; | ||
var organizeAudioPlaylists = function organizeAudioPlaylists(playlists) { | ||
@@ -85,10 +177,9 @@ return playlists.reduce(function (a, playlist) { | ||
var language = playlist.attributes.lang || ''; | ||
var label = 'main'; | ||
if (language) { | ||
label = playlist.attributes.lang + ' (' + role + ')'; | ||
} | ||
label = playlist.attributes.lang + " (" + role + ")"; | ||
} // skip if we already have the highest quality audio for a language | ||
// skip if we already have the highest quality audio for a language | ||
if (a[label] && a[label].playlists[0].attributes.BANDWIDTH > playlist.attributes.bandwidth) { | ||
@@ -101,16 +192,13 @@ return a; | ||
autoselect: true, | ||
'default': role === 'main', | ||
default: role === 'main', | ||
playlists: [formatAudioPlaylist(playlist)], | ||
uri: '' | ||
}; | ||
return a; | ||
}, {}); | ||
}; | ||
var organizeVttPlaylists = function organizeVttPlaylists(playlists) { | ||
return playlists.reduce(function (a, playlist) { | ||
var label = playlist.attributes.lang || 'text'; | ||
var label = playlist.attributes.lang || 'text'; // skip if we already have subtitles | ||
// skip if we already have subtitles | ||
if (a[label]) { | ||
@@ -122,3 +210,3 @@ return a; | ||
language: label, | ||
'default': false, | ||
default: false, | ||
autoselect: false, | ||
@@ -128,7 +216,5 @@ playlists: [formatVttPlaylist(playlist)], | ||
}; | ||
return a; | ||
}, {}); | ||
}; | ||
var formatVideoPlaylist = function formatVideoPlaylist(_ref3) { | ||
@@ -139,3 +225,2 @@ var _attributes3; | ||
segments = _ref3.segments; | ||
var playlist = { | ||
@@ -168,3 +253,2 @@ attributes: (_attributes3 = { | ||
}; | ||
var toM3u8 = function toM3u8(dashPlaylists) { | ||
@@ -175,11 +259,10 @@ var _mediaGroups; | ||
return {}; | ||
} | ||
} // grab all master attributes | ||
// grab all master attributes | ||
var _dashPlaylists$0$attr = dashPlaylists[0].attributes, | ||
duration = _dashPlaylists$0$attr.sourceDuration, | ||
_dashPlaylists$0$attr2 = _dashPlaylists$0$attr.minimumUpdatePeriod, | ||
minimumUpdatePeriod = _dashPlaylists$0$attr2 === undefined ? 0 : _dashPlaylists$0$attr2; | ||
minimumUpdatePeriod = _dashPlaylists$0$attr2 === void 0 ? 0 : _dashPlaylists$0$attr2; | ||
var videoOnly = function videoOnly(_ref4) { | ||
@@ -189,2 +272,3 @@ var attributes = _ref4.attributes; | ||
}; | ||
var audioOnly = function audioOnly(_ref5) { | ||
@@ -194,2 +278,3 @@ var attributes = _ref5.attributes; | ||
}; | ||
var vttOnly = function vttOnly(_ref6) { | ||
@@ -200,6 +285,5 @@ var attributes = _ref6.attributes; | ||
var videoPlaylists = dashPlaylists.filter(videoOnly).map(formatVideoPlaylist); | ||
var audioPlaylists = dashPlaylists.filter(audioOnly); | ||
var videoPlaylists = mergeDiscontiguousPlaylists(dashPlaylists.filter(videoOnly)).map(formatVideoPlaylist); | ||
var audioPlaylists = mergeDiscontiguousPlaylists(dashPlaylists.filter(audioOnly)); | ||
var vttPlaylists = dashPlaylists.filter(vttOnly); | ||
var master = { | ||
@@ -231,33 +315,167 @@ allowCache: true, | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { | ||
return typeof obj; | ||
} : function (obj) { | ||
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; | ||
}; | ||
var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; | ||
var isObject = function isObject(obj) { | ||
return !!obj && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object'; | ||
}; | ||
function createCommonjsModule(fn, module) { | ||
return module = { exports: {} }, fn(module, module.exports), module.exports; | ||
} | ||
var merge = function merge() { | ||
for (var _len = arguments.length, objects = Array(_len), _key = 0; _key < _len; _key++) { | ||
objects[_key] = arguments[_key]; | ||
} | ||
var urlToolkit = createCommonjsModule(function (module, exports) { | ||
// see https://tools.ietf.org/html/rfc1808 | ||
return objects.reduce(function (result, source) { | ||
/* jshint ignore:start */ | ||
(function(root) { | ||
/* jshint ignore:end */ | ||
Object.keys(source).forEach(function (key) { | ||
var URL_REGEX = /^((?:[a-zA-Z0-9+\-.]+:)?)(\/\/[^\/?#]*)?((?:[^\/\?#]*\/)*.*?)??(;.*?)?(\?.*?)?(#.*?)?$/; | ||
var FIRST_SEGMENT_REGEX = /^([^\/?#]*)(.*)$/; | ||
var SLASH_DOT_REGEX = /(?:\/|^)\.(?=\/)/g; | ||
var SLASH_DOT_DOT_REGEX = /(?:\/|^)\.\.\/(?!\.\.\/).*?(?=\/)/g; | ||
if (Array.isArray(result[key]) && Array.isArray(source[key])) { | ||
result[key] = result[key].concat(source[key]); | ||
} else if (isObject(result[key]) && isObject(source[key])) { | ||
result[key] = merge(result[key], source[key]); | ||
} else { | ||
result[key] = source[key]; | ||
var URLToolkit = { // jshint ignore:line | ||
// If opts.alwaysNormalize is true then the path will always be normalized even when it starts with / or // | ||
// E.g | ||
// With opts.alwaysNormalize = false (default, spec compliant) | ||
// http://a.com/b/cd + /e/f/../g => http://a.com/e/f/../g | ||
// With opts.alwaysNormalize = true (not spec compliant) | ||
// http://a.com/b/cd + /e/f/../g => http://a.com/e/g | ||
buildAbsoluteURL: function(baseURL, relativeURL, opts) { | ||
opts = opts || {}; | ||
// remove any remaining space and CRLF | ||
baseURL = baseURL.trim(); | ||
relativeURL = relativeURL.trim(); | ||
if (!relativeURL) { | ||
// 2a) If the embedded URL is entirely empty, it inherits the | ||
// entire base URL (i.e., is set equal to the base URL) | ||
// and we are done. | ||
if (!opts.alwaysNormalize) { | ||
return baseURL; | ||
} | ||
var basePartsForNormalise = URLToolkit.parseURL(baseURL); | ||
if (!basePartsForNormalise) { | ||
throw new Error('Error trying to parse base URL.'); | ||
} | ||
basePartsForNormalise.path = URLToolkit.normalizePath(basePartsForNormalise.path); | ||
return URLToolkit.buildURLFromParts(basePartsForNormalise); | ||
} | ||
}); | ||
return result; | ||
}, {}); | ||
}; | ||
var relativeParts = URLToolkit.parseURL(relativeURL); | ||
if (!relativeParts) { | ||
throw new Error('Error trying to parse relative URL.'); | ||
} | ||
if (relativeParts.scheme) { | ||
// 2b) If the embedded URL starts with a scheme name, it is | ||
// interpreted as an absolute URL and we are done. | ||
if (!opts.alwaysNormalize) { | ||
return relativeURL; | ||
} | ||
relativeParts.path = URLToolkit.normalizePath(relativeParts.path); | ||
return URLToolkit.buildURLFromParts(relativeParts); | ||
} | ||
var baseParts = URLToolkit.parseURL(baseURL); | ||
if (!baseParts) { | ||
throw new Error('Error trying to parse base URL.'); | ||
} | ||
if (!baseParts.netLoc && baseParts.path && baseParts.path[0] !== '/') { | ||
// If netLoc missing and path doesn't start with '/', assume everthing before the first '/' is the netLoc | ||
// This causes 'example.com/a' to be handled as '//example.com/a' instead of '/example.com/a' | ||
var pathParts = FIRST_SEGMENT_REGEX.exec(baseParts.path); | ||
baseParts.netLoc = pathParts[1]; | ||
baseParts.path = pathParts[2]; | ||
} | ||
if (baseParts.netLoc && !baseParts.path) { | ||
baseParts.path = '/'; | ||
} | ||
var builtParts = { | ||
// 2c) Otherwise, the embedded URL inherits the scheme of | ||
// the base URL. | ||
scheme: baseParts.scheme, | ||
netLoc: relativeParts.netLoc, | ||
path: null, | ||
params: relativeParts.params, | ||
query: relativeParts.query, | ||
fragment: relativeParts.fragment | ||
}; | ||
if (!relativeParts.netLoc) { | ||
// 3) If the embedded URL's <net_loc> is non-empty, we skip to | ||
// Step 7. Otherwise, the embedded URL inherits the <net_loc> | ||
// (if any) of the base URL. | ||
builtParts.netLoc = baseParts.netLoc; | ||
// 4) If the embedded URL path is preceded by a slash "/", the | ||
// path is not relative and we skip to Step 7. | ||
if (relativeParts.path[0] !== '/') { | ||
if (!relativeParts.path) { | ||
// 5) If the embedded URL path is empty (and not preceded by a | ||
// slash), then the embedded URL inherits the base URL path | ||
builtParts.path = baseParts.path; | ||
// 5a) if the embedded URL's <params> is non-empty, we skip to | ||
// step 7; otherwise, it inherits the <params> of the base | ||
// URL (if any) and | ||
if (!relativeParts.params) { | ||
builtParts.params = baseParts.params; | ||
// 5b) if the embedded URL's <query> is non-empty, we skip to | ||
// step 7; otherwise, it inherits the <query> of the base | ||
// URL (if any) and we skip to step 7. | ||
if (!relativeParts.query) { | ||
builtParts.query = baseParts.query; | ||
} | ||
} | ||
} else { | ||
// 6) The last segment of the base URL's path (anything | ||
// following the rightmost slash "/", or the entire path if no | ||
// slash is present) is removed and the embedded URL's path is | ||
// appended in its place. | ||
var baseURLPath = baseParts.path; | ||
var newPath = baseURLPath.substring(0, baseURLPath.lastIndexOf('/') + 1) + relativeParts.path; | ||
builtParts.path = URLToolkit.normalizePath(newPath); | ||
} | ||
} | ||
} | ||
if (builtParts.path === null) { | ||
builtParts.path = opts.alwaysNormalize ? URLToolkit.normalizePath(relativeParts.path) : relativeParts.path; | ||
} | ||
return URLToolkit.buildURLFromParts(builtParts); | ||
}, | ||
parseURL: function(url) { | ||
var parts = URL_REGEX.exec(url); | ||
if (!parts) { | ||
return null; | ||
} | ||
return { | ||
scheme: parts[1] || '', | ||
netLoc: parts[2] || '', | ||
path: parts[3] || '', | ||
params: parts[4] || '', | ||
query: parts[5] || '', | ||
fragment: parts[6] || '' | ||
}; | ||
}, | ||
normalizePath: function(path) { | ||
// The following operations are | ||
// then applied, in order, to the new path: | ||
// 6a) All occurrences of "./", where "." is a complete path | ||
// segment, are removed. | ||
// 6b) If the path ends with "." as a complete path segment, | ||
// that "." is removed. | ||
path = path.split('').reverse().join('').replace(SLASH_DOT_REGEX, ''); | ||
// 6c) All occurrences of "<segment>/../", where <segment> is a | ||
// complete path segment not equal to "..", are removed. | ||
// Removal of these path segments is performed iteratively, | ||
// removing the leftmost matching pattern on each iteration, | ||
// until no matching pattern remains. | ||
// 6d) If the path ends with "<segment>/..", where <segment> is a | ||
// complete path segment not equal to "..", that | ||
// "<segment>/.." is removed. | ||
while (path.length !== (path = path.replace(SLASH_DOT_DOT_REGEX, '')).length) {} // jshint ignore:line | ||
return path.split('').reverse().join(''); | ||
}, | ||
buildURLFromParts: function(parts) { | ||
return parts.scheme + parts.netLoc + parts.path + parts.params + parts.query + parts.fragment; | ||
} | ||
}; | ||
/* jshint ignore:start */ | ||
module.exports = URLToolkit; | ||
})(commonjsGlobal); | ||
/* jshint ignore:end */ | ||
}); | ||
var resolveUrl = function resolveUrl(baseUrl, relativeUrl) { | ||
@@ -267,10 +485,10 @@ // return early if we don't need to resolve | ||
return relativeUrl; | ||
} | ||
} // if the base URL is relative then combine with the current location | ||
// if the base URL is relative then combine with the current location | ||
if (!/\/\//i.test(baseUrl)) { | ||
baseUrl = URLToolkit.buildAbsoluteURL(window.location.href, baseUrl); | ||
baseUrl = urlToolkit.buildAbsoluteURL(window$1.location.href, baseUrl); | ||
} | ||
return URLToolkit.buildAbsoluteURL(baseUrl, relativeUrl); | ||
return urlToolkit.buildAbsoluteURL(baseUrl, relativeUrl); | ||
}; | ||
@@ -302,10 +520,10 @@ | ||
*/ | ||
var urlTypeToSegment = function urlTypeToSegment(_ref) { | ||
var _ref$baseUrl = _ref.baseUrl, | ||
baseUrl = _ref$baseUrl === undefined ? '' : _ref$baseUrl, | ||
baseUrl = _ref$baseUrl === void 0 ? '' : _ref$baseUrl, | ||
_ref$source = _ref.source, | ||
source = _ref$source === undefined ? '' : _ref$source, | ||
source = _ref$source === void 0 ? '' : _ref$source, | ||
_ref$range = _ref.range, | ||
range = _ref$range === undefined ? '' : _ref$range; | ||
range = _ref$range === void 0 ? '' : _ref$range; | ||
var init = { | ||
@@ -320,3 +538,2 @@ uri: source, | ||
var endRange = parseInt(ranges[1], 10); | ||
init.byterange = { | ||
@@ -351,8 +568,7 @@ length: endRange - startRange, | ||
_attributes$timescale = attributes.timescale, | ||
timescale = _attributes$timescale === undefined ? 1 : _attributes$timescale, | ||
timescale = _attributes$timescale === void 0 ? 1 : _attributes$timescale, | ||
_attributes$start = attributes.start, | ||
start = _attributes$start === undefined ? 0 : _attributes$start, | ||
start = _attributes$start === void 0 ? 0 : _attributes$start, | ||
_attributes$minimumUp = attributes.minimumUpdatePeriod, | ||
minimumUpdatePeriod = _attributes$minimumUp === undefined ? 0 : _attributes$minimumUp; | ||
minimumUpdatePeriod = _attributes$minimumUp === void 0 ? 0 : _attributes$minimumUp; | ||
var now = (NOW + clientOffset) / 1000; | ||
@@ -362,6 +578,4 @@ var periodStartWC = availabilityStartTime + start; | ||
var periodDuration = periodEndWC - periodStartWC; | ||
return Math.ceil((periodDuration * timescale - time) / duration); | ||
}; | ||
/** | ||
@@ -380,16 +594,17 @@ * Uses information provided by SegmentTemplate.SegmentTimeline to determine segment | ||
*/ | ||
var parseByTimeline = function parseByTimeline(attributes, segmentTimeline) { | ||
var _attributes$type = attributes.type, | ||
type = _attributes$type === undefined ? 'static' : _attributes$type, | ||
type = _attributes$type === void 0 ? 'static' : _attributes$type, | ||
_attributes$minimumUp2 = attributes.minimumUpdatePeriod, | ||
minimumUpdatePeriod = _attributes$minimumUp2 === undefined ? 0 : _attributes$minimumUp2, | ||
minimumUpdatePeriod = _attributes$minimumUp2 === void 0 ? 0 : _attributes$minimumUp2, | ||
_attributes$media = attributes.media, | ||
media = _attributes$media === undefined ? '' : _attributes$media, | ||
media = _attributes$media === void 0 ? '' : _attributes$media, | ||
sourceDuration = attributes.sourceDuration, | ||
_attributes$timescale2 = attributes.timescale, | ||
timescale = _attributes$timescale2 === undefined ? 1 : _attributes$timescale2, | ||
timescale = _attributes$timescale2 === void 0 ? 1 : _attributes$timescale2, | ||
_attributes$startNumb = attributes.startNumber, | ||
startNumber = _attributes$startNumb === undefined ? 1 : _attributes$startNumb, | ||
startNumber = _attributes$startNumb === void 0 ? 1 : _attributes$startNumb, | ||
timeline = attributes.periodIndex; | ||
var segments = []; | ||
@@ -411,3 +626,2 @@ var time = -1; | ||
// discontinuity | ||
// TODO: How to handle this type of discontinuity | ||
@@ -432,3 +646,2 @@ // timeline++ here would treat it like HLS discontuity and content would | ||
// with $Time$ values of [0, 1, 2, 5, 6, 7, 8, 9, 10, 11] ? | ||
time = segmentTime; | ||
@@ -461,3 +674,8 @@ } | ||
while (number < end) { | ||
segments.push({ number: number, duration: duration / timescale, time: time, timeline: timeline }); | ||
segments.push({ | ||
number: number, | ||
duration: duration / timescale, | ||
time: time, | ||
timeline: timeline | ||
}); | ||
time += duration; | ||
@@ -471,32 +689,2 @@ number++; | ||
var range = function range(start, end) { | ||
var result = []; | ||
for (var i = start; i < end; i++) { | ||
result.push(i); | ||
} | ||
return result; | ||
}; | ||
var flatten = function flatten(lists) { | ||
return lists.reduce(function (x, y) { | ||
return x.concat(y); | ||
}, []); | ||
}; | ||
var from = function from(list) { | ||
if (!list.length) { | ||
return []; | ||
} | ||
var result = []; | ||
for (var i = 0; i < list.length; i++) { | ||
result.push(list[i]); | ||
} | ||
return result; | ||
}; | ||
/** | ||
@@ -506,2 +694,3 @@ * Functions for calculating the range of available segments in static and dynamic | ||
*/ | ||
var segmentRange = { | ||
@@ -516,9 +705,7 @@ /** | ||
*/ | ||
'static': function _static(attributes) { | ||
static: function _static(attributes) { | ||
var duration = attributes.duration, | ||
_attributes$timescale = attributes.timescale, | ||
timescale = _attributes$timescale === undefined ? 1 : _attributes$timescale, | ||
timescale = _attributes$timescale === void 0 ? 1 : _attributes$timescale, | ||
sourceDuration = attributes.sourceDuration; | ||
return { | ||
@@ -530,3 +717,2 @@ start: 0, | ||
/** | ||
@@ -545,11 +731,10 @@ * Returns the current live window range of available segments for a dynamic MPD | ||
_attributes$timescale2 = attributes.timescale, | ||
timescale = _attributes$timescale2 === undefined ? 1 : _attributes$timescale2, | ||
timescale = _attributes$timescale2 === void 0 ? 1 : _attributes$timescale2, | ||
duration = attributes.duration, | ||
_attributes$start = attributes.start, | ||
start = _attributes$start === undefined ? 0 : _attributes$start, | ||
start = _attributes$start === void 0 ? 0 : _attributes$start, | ||
_attributes$minimumUp = attributes.minimumUpdatePeriod, | ||
minimumUpdatePeriod = _attributes$minimumUp === undefined ? 0 : _attributes$minimumUp, | ||
minimumUpdatePeriod = _attributes$minimumUp === void 0 ? 0 : _attributes$minimumUp, | ||
_attributes$timeShift = attributes.timeShiftBufferDepth, | ||
timeShiftBufferDepth = _attributes$timeShift === undefined ? Infinity : _attributes$timeShift; | ||
timeShiftBufferDepth = _attributes$timeShift === void 0 ? Infinity : _attributes$timeShift; | ||
var now = (NOW + clientOffset) / 1000; | ||
@@ -562,3 +747,2 @@ var periodStartWC = availabilityStartTime + start; | ||
var availableEnd = Math.floor((now - periodStartWC) * timescale / duration); | ||
return { | ||
@@ -570,3 +754,2 @@ start: Math.max(0, availableStart), | ||
}; | ||
/** | ||
@@ -595,2 +778,3 @@ * Maps a range of numbers to objects with information needed to build the corresponding | ||
*/ | ||
var toSegments = function toSegments(attributes) { | ||
@@ -600,8 +784,6 @@ return function (number, index) { | ||
_attributes$timescale3 = attributes.timescale, | ||
timescale = _attributes$timescale3 === undefined ? 1 : _attributes$timescale3, | ||
timescale = _attributes$timescale3 === void 0 ? 1 : _attributes$timescale3, | ||
periodIndex = attributes.periodIndex, | ||
_attributes$startNumb = attributes.startNumber, | ||
startNumber = _attributes$startNumb === undefined ? 1 : _attributes$startNumb; | ||
startNumber = _attributes$startNumb === void 0 ? 1 : _attributes$startNumb; | ||
return { | ||
@@ -615,3 +797,2 @@ number: startNumber + number, | ||
}; | ||
/** | ||
@@ -627,8 +808,9 @@ * Returns a list of objects containing segment timing and duration info used for | ||
*/ | ||
var parseByDuration = function parseByDuration(attributes) { | ||
var _attributes$type = attributes.type, | ||
type = _attributes$type === undefined ? 'static' : _attributes$type, | ||
type = _attributes$type === void 0 ? 'static' : _attributes$type, | ||
duration = attributes.duration, | ||
_attributes$timescale4 = attributes.timescale, | ||
timescale = _attributes$timescale4 === undefined ? 1 : _attributes$timescale4, | ||
timescale = _attributes$timescale4 === void 0 ? 1 : _attributes$timescale4, | ||
sourceDuration = attributes.sourceDuration; | ||
@@ -643,5 +825,4 @@ | ||
if (type === 'static') { | ||
var index = segments.length - 1; | ||
var index = segments.length - 1; // final segment may be less than full segment duration | ||
// final segment may be less than full segment duration | ||
segments[index].duration = sourceDuration - duration / timescale * index; | ||
@@ -654,3 +835,2 @@ } | ||
var identifierPattern = /\$([A-z]*)(?:(%0)([0-9]+)d)?\$/g; | ||
/** | ||
@@ -692,2 +872,3 @@ * Replaces template identifiers with corresponding values. To be used as the callback | ||
*/ | ||
var identifierReplacement = function identifierReplacement(values) { | ||
@@ -721,6 +902,5 @@ return function (match, identifier, format, width) { | ||
return '' + new Array(width - value.length + 1).join('0') + value; | ||
return "" + new Array(width - value.length + 1).join('0') + value; | ||
}; | ||
}; | ||
/** | ||
@@ -744,6 +924,6 @@ * Constructs a segment url from a template string | ||
*/ | ||
var constructTemplateUrl = function constructTemplateUrl(url, values) { | ||
return url.replace(identifierPattern, identifierReplacement(values)); | ||
}; | ||
/** | ||
@@ -762,2 +942,3 @@ * Generates a list of objects containing timing and duration information about each | ||
*/ | ||
var parseTemplateInfo = function parseTemplateInfo(attributes, segmentTimeline) { | ||
@@ -781,3 +962,2 @@ if (!attributes.duration && !segmentTimeline) { | ||
}; | ||
/** | ||
@@ -795,2 +975,3 @@ * Generates a list of segments using information provided by the SegmentTemplate element | ||
*/ | ||
var segmentsFromTemplate = function segmentsFromTemplate(attributes, segmentTimeline) { | ||
@@ -801,7 +982,7 @@ var templateValues = { | ||
}; | ||
var _attributes$initializ = attributes.initialization, | ||
initialization = _attributes$initializ === undefined ? { sourceURL: '', range: '' } : _attributes$initializ; | ||
initialization = _attributes$initializ === void 0 ? { | ||
sourceURL: '', | ||
range: '' | ||
} : _attributes$initializ; | ||
var mapSegment = urlTypeToSegment({ | ||
@@ -812,11 +993,7 @@ baseUrl: attributes.baseUrl, | ||
}); | ||
var segments = parseTemplateInfo(attributes, segmentTimeline); | ||
return segments.map(function (segment) { | ||
templateValues.Number = segment.number; | ||
templateValues.Time = segment.time; | ||
var uri = constructTemplateUrl(attributes.media || '', templateValues); | ||
return { | ||
@@ -854,8 +1031,7 @@ uri: uri, | ||
*/ | ||
var SegmentURLToSegmentObject = function SegmentURLToSegmentObject(attributes, segmentUrl) { | ||
var baseUrl = attributes.baseUrl, | ||
_attributes$initializ = attributes.initialization, | ||
initialization = _attributes$initializ === undefined ? {} : _attributes$initializ; | ||
initialization = _attributes$initializ === void 0 ? {} : _attributes$initializ; | ||
var initSegment = urlTypeToSegment({ | ||
@@ -866,3 +1042,2 @@ baseUrl: baseUrl, | ||
}); | ||
var segment = urlTypeToSegment({ | ||
@@ -873,8 +1048,5 @@ baseUrl: baseUrl, | ||
}); | ||
segment.map = initSegment; | ||
return segment; | ||
}; | ||
/** | ||
@@ -893,8 +1065,8 @@ * Generates a list of segments using information provided by the SegmentList element | ||
*/ | ||
var segmentsFromList = function segmentsFromList(attributes, segmentTimeline) { | ||
var duration = attributes.duration, | ||
_attributes$segmentUr = attributes.segmentUrls, | ||
segmentUrls = _attributes$segmentUr === undefined ? [] : _attributes$segmentUr; | ||
// Per spec (5.3.9.2.1) no way to determine segment duration OR | ||
segmentUrls = _attributes$segmentUr === void 0 ? [] : _attributes$segmentUr; // 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. | ||
@@ -909,3 +1081,3 @@ | ||
}); | ||
var segmentTimeInfo = void 0; | ||
var segmentTimeInfo; | ||
@@ -923,3 +1095,2 @@ if (duration) { | ||
var segment = segmentUrlMap[index]; | ||
segment.timeline = segmentTime.timeline; | ||
@@ -929,10 +1100,9 @@ segment.duration = segmentTime.duration; | ||
return segment; | ||
} | ||
// Since we're mapping we should get rid of any blank segments (in case | ||
} // 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(function (segment) { | ||
return segment; | ||
}); | ||
return segments; | ||
@@ -951,15 +1121,14 @@ }; | ||
*/ | ||
var segmentsFromBase = function segmentsFromBase(attributes) { | ||
var baseUrl = attributes.baseUrl, | ||
_attributes$initializ = attributes.initialization, | ||
initialization = _attributes$initializ === undefined ? {} : _attributes$initializ, | ||
initialization = _attributes$initializ === void 0 ? {} : _attributes$initializ, | ||
sourceDuration = attributes.sourceDuration, | ||
_attributes$timescale = attributes.timescale, | ||
timescale = _attributes$timescale === undefined ? 1 : _attributes$timescale, | ||
timescale = _attributes$timescale === void 0 ? 1 : _attributes$timescale, | ||
_attributes$indexRang = attributes.indexRange, | ||
indexRange = _attributes$indexRang === undefined ? '' : _attributes$indexRang, | ||
duration = attributes.duration; | ||
indexRange = _attributes$indexRang === void 0 ? '' : _attributes$indexRang, | ||
duration = attributes.duration; // base url is required for SegmentBase to work, per spec (Section 5.3.9.2.1) | ||
// base url is required for SegmentBase to work, per spec (Section 5.3.9.2.1) | ||
if (!baseUrl) { | ||
@@ -974,8 +1143,10 @@ throw new Error(errors.NO_BASE_URL); | ||
}); | ||
var segment = urlTypeToSegment({ baseUrl: baseUrl, source: baseUrl, range: indexRange }); | ||
var segment = urlTypeToSegment({ | ||
baseUrl: baseUrl, | ||
source: baseUrl, | ||
range: indexRange | ||
}); | ||
segment.map = initSegment; // If there is a duration, use it, otherwise use the given duration of the source | ||
// (since SegmentBase is only for one total segment) | ||
segment.map = initSegment; | ||
// If there is a duration, use it, otherwise use the given duration of the source | ||
// (since SegmentBase is only for one total segment) | ||
if (duration) { | ||
@@ -991,7 +1162,6 @@ var segmentTimeInfo = parseByDuration(attributes); | ||
segment.timeline = 0; | ||
} | ||
} // This is used for mediaSequence | ||
// This is used for mediaSequence | ||
segment.number = 0; | ||
return [segment]; | ||
@@ -1003,6 +1173,5 @@ }; | ||
segmentInfo = _ref.segmentInfo; | ||
var segmentAttributes; | ||
var segmentsFn; | ||
var segmentAttributes = void 0; | ||
var segmentsFn = void 0; | ||
if (segmentInfo.template) { | ||
@@ -1020,10 +1189,11 @@ segmentsFn = segmentsFromTemplate; | ||
if (!segmentsFn) { | ||
return { attributes: attributes }; | ||
return { | ||
attributes: attributes | ||
}; | ||
} | ||
var segments = segmentsFn(segmentAttributes, segmentInfo.timeline); | ||
// The @duration attribute will be used to determin the playlist's targetDuration which | ||
var segments = segmentsFn(segmentAttributes, segmentInfo.timeline); // The @duration attribute will be used to determin the playlist's targetDuration which | ||
// must be in seconds. Since we've generated the segment list, we no longer need | ||
// @duration to be in @timescale units, so we can convert it here. | ||
if (segmentAttributes.duration) { | ||
@@ -1033,5 +1203,3 @@ var _segmentAttributes = segmentAttributes, | ||
_segmentAttributes$ti = _segmentAttributes.timescale, | ||
timescale = _segmentAttributes$ti === undefined ? 1 : _segmentAttributes$ti; | ||
timescale = _segmentAttributes$ti === void 0 ? 1 : _segmentAttributes$ti; | ||
segmentAttributes.duration = duration / timescale; | ||
@@ -1053,3 +1221,2 @@ } else if (segments.length) { | ||
}; | ||
var toPlaylists = function toPlaylists(representations) { | ||
@@ -1065,3 +1232,2 @@ return representations.map(generateSegments); | ||
}; | ||
var getContent = function getContent(element) { | ||
@@ -1076,5 +1242,4 @@ return element.textContent.trim(); | ||
var SECONDS_IN_HOUR = 60 * 60; | ||
var SECONDS_IN_MIN = 60; | ||
var SECONDS_IN_MIN = 60; // P10Y10M10DT10H10M10.1S | ||
// P10Y10M10DT10H10M10.1S | ||
var durationRegex = /P(?:(\d*)Y)?(?:(\d*)M)?(?:(\d*)D)?(?:T(?:(\d*)H)?(?:(\d*)M)?(?:([\d.]*)S)?)?/; | ||
@@ -1097,10 +1262,8 @@ var match = durationRegex.exec(str); | ||
}; | ||
var parseDate = function parseDate(str) { | ||
// Date format without timezone according to ISO 8601 | ||
// YYY-MM-DDThh:mm:ss.ssssss | ||
var dateRegex = /^\d+-\d+-\d+T\d+:\d+:\d+(\.\d+)?$/; | ||
var dateRegex = /^\d+-\d+-\d+T\d+:\d+:\d+(\.\d+)?$/; // If the date string does not specifiy a timezone, we must specifiy UTC. This is | ||
// expressed by ending with 'Z' | ||
// If the date string does not specifiy a timezone, we must specifiy UTC. This is | ||
// expressed by ending with 'Z' | ||
if (dateRegex.test(str)) { | ||
@@ -1113,3 +1276,2 @@ str += 'Z'; | ||
// TODO: maybe order these in some way that makes it easy to find specific attributes | ||
var parsers = { | ||
@@ -1129,3 +1291,2 @@ /** | ||
/** | ||
@@ -1145,3 +1306,2 @@ * Specifies the Segment availability start time for all Segments referred to in this | ||
/** | ||
@@ -1160,3 +1320,2 @@ * Specifies the smallest period between potential changes to the MPD. Format is a | ||
/** | ||
@@ -1175,3 +1334,2 @@ * Specifies the duration of the smallest time shifting buffer for any Representation | ||
/** | ||
@@ -1190,3 +1348,2 @@ * Specifies the PeriodStart time of the Period relative to the availabilityStarttime. | ||
/** | ||
@@ -1204,3 +1361,2 @@ * Specifies the width of the visual presentation | ||
/** | ||
@@ -1218,3 +1374,2 @@ * Specifies the height of the visual presentation | ||
/** | ||
@@ -1232,3 +1387,2 @@ * Specifies the bitrate of the representation | ||
/** | ||
@@ -1246,3 +1400,2 @@ * Specifies the number of the first Media Segment in this Representation in the Period | ||
/** | ||
@@ -1260,3 +1413,2 @@ * Specifies the timescale in units per seconds | ||
/** | ||
@@ -1284,3 +1436,2 @@ * Specifies the constant approximate Segment duration | ||
/** | ||
@@ -1298,3 +1449,2 @@ * Specifies the Segment duration, in units of the value of the @timescale. | ||
/** | ||
@@ -1313,3 +1463,2 @@ * Specifies the MPD start time, in @timescale units, the first Segment in the series | ||
/** | ||
@@ -1328,3 +1477,2 @@ * Specifies the repeat count of the number of following contiguous Segments with the | ||
/** | ||
@@ -1343,3 +1491,2 @@ * Default parser for all other attributes. Acts as a no-op and just returns the value | ||
}; | ||
/** | ||
@@ -1354,2 +1501,3 @@ * Gets all the attributes and values of the provided node, parses attributes with known | ||
*/ | ||
var parseAttributes = function parseAttributes(el) { | ||
@@ -1362,5 +1510,3 @@ if (!(el && el.attributes)) { | ||
var parseFn = parsers[e.name] || parsers.DEFAULT; | ||
a[e.name] = parseFn(e.value); | ||
return a; | ||
@@ -1371,3 +1517,3 @@ }, {}); | ||
function decodeB64ToUint8Array(b64Text) { | ||
var decodedString = window.atob(b64Text); | ||
var decodedString = window$1.atob(b64Text); | ||
var array = new Uint8Array(decodedString.length); | ||
@@ -1378,2 +1524,3 @@ | ||
} | ||
return array; | ||
@@ -1388,3 +1535,2 @@ } | ||
}; | ||
/** | ||
@@ -1400,2 +1546,3 @@ * Builds a list of urls that is the product of the reference urls and BaseURL values | ||
*/ | ||
var buildBaseUrls = function buildBaseUrls(referenceUrls, baseUrlElements) { | ||
@@ -1412,3 +1559,2 @@ if (!baseUrlElements.length) { | ||
}; | ||
/** | ||
@@ -1436,2 +1582,3 @@ * Contains all Segment information for its containing AdaptationSet | ||
*/ | ||
var getSegmentInformation = function getSegmentInformation(adaptationSet) { | ||
@@ -1441,3 +1588,5 @@ var segmentTemplate = findChildren(adaptationSet, 'SegmentTemplate')[0]; | ||
var segmentUrls = segmentList && findChildren(segmentList, 'SegmentURL').map(function (s) { | ||
return merge({ tag: 'SegmentURL' }, parseAttributes(s)); | ||
return merge({ | ||
tag: 'SegmentURL' | ||
}, parseAttributes(s)); | ||
}); | ||
@@ -1448,5 +1597,3 @@ var segmentBase = findChildren(adaptationSet, 'SegmentBase')[0]; | ||
var segmentInitializationParentNode = segmentList || segmentBase || segmentTemplate; | ||
var segmentInitialization = segmentInitializationParentNode && findChildren(segmentInitializationParentNode, 'Initialization')[0]; | ||
// SegmentTemplate is handled slightly differently, since it can have both | ||
var segmentInitialization = segmentInitializationParentNode && findChildren(segmentInitializationParentNode, 'Initialization')[0]; // SegmentTemplate is handled slightly differently, since it can have both | ||
// @initialization and an <Initialization> node. @initialization can be templated, | ||
@@ -1456,2 +1603,3 @@ // while the node can have a url and range specified. If the <SegmentTemplate> has | ||
// the node, as this interaction is not defined in the spec. | ||
var template = segmentTemplate && parseAttributes(segmentTemplate); | ||
@@ -1465,3 +1613,5 @@ | ||
// for <SegmentTemplate> | ||
template.initialization = { sourceURL: template.initialization }; | ||
template.initialization = { | ||
sourceURL: template.initialization | ||
}; | ||
} | ||
@@ -1482,3 +1632,2 @@ | ||
}; | ||
Object.keys(segmentInfo).forEach(function (key) { | ||
@@ -1489,6 +1638,4 @@ if (!segmentInfo[key]) { | ||
}); | ||
return segmentInfo; | ||
}; | ||
/** | ||
@@ -1529,2 +1676,3 @@ * Contains Segment information and attributes needed to construct a Playlist object | ||
*/ | ||
var inheritBaseUrls = function inheritBaseUrls(adaptationSetAttributes, adaptationSetBaseUrls, adaptationSetSegmentInfo) { | ||
@@ -1536,7 +1684,8 @@ return function (representation) { | ||
var representationSegmentInfo = getSegmentInformation(representation); | ||
return repBaseUrls.map(function (baseUrl) { | ||
return { | ||
segmentInfo: merge(adaptationSetSegmentInfo, representationSegmentInfo), | ||
attributes: merge(attributes, { baseUrl: baseUrl }) | ||
attributes: merge(attributes, { | ||
baseUrl: baseUrl | ||
}) | ||
}; | ||
@@ -1546,3 +1695,2 @@ }); | ||
}; | ||
/** | ||
@@ -1557,2 +1705,3 @@ * Tranforms a series of content protection nodes to | ||
*/ | ||
var generateKeySystemInformation = function generateKeySystemInformation(contentProtectionNodes) { | ||
@@ -1564,4 +1713,5 @@ return contentProtectionNodes.reduce(function (acc, node) { | ||
if (keySystem) { | ||
acc[keySystem] = { attributes: attributes }; | ||
acc[keySystem] = { | ||
attributes: attributes | ||
}; | ||
var psshNode = findChildren(node, 'cenc:pssh')[0]; | ||
@@ -1572,3 +1722,2 @@ | ||
var psshBuffer = pssh && decodeB64ToUint8Array(pssh); | ||
acc[keySystem].pssh = psshBuffer; | ||
@@ -1581,3 +1730,2 @@ } | ||
}; | ||
/** | ||
@@ -1607,2 +1755,4 @@ * Maps an AdaptationSet node to a list of Representation information objects | ||
*/ | ||
var toRepresentations = function toRepresentations(periodAttributes, periodBaseUrls, periodSegmentInfo) { | ||
@@ -1613,10 +1763,12 @@ return function (adaptationSet) { | ||
var role = findChildren(adaptationSet, 'Role')[0]; | ||
var roleAttributes = { role: parseAttributes(role) }; | ||
var roleAttributes = { | ||
role: parseAttributes(role) | ||
}; | ||
var attrs = merge(periodAttributes, adaptationSetAttributes, roleAttributes); | ||
var contentProtection = generateKeySystemInformation(findChildren(adaptationSet, 'ContentProtection')); | ||
if (Object.keys(contentProtection).length) { | ||
attrs = merge(attrs, { contentProtection: contentProtection }); | ||
attrs = merge(attrs, { | ||
contentProtection: contentProtection | ||
}); | ||
} | ||
@@ -1627,7 +1779,5 @@ | ||
var adaptationSetSegmentInfo = merge(periodSegmentInfo, segmentInfo); | ||
return flatten(representations.map(inheritBaseUrls(attrs, adaptationSetBaseUrls, adaptationSetSegmentInfo))); | ||
}; | ||
}; | ||
/** | ||
@@ -1658,14 +1808,18 @@ * Maps an Period node to a list of Representation inforamtion objects for all | ||
*/ | ||
var toAdaptationSets = function toAdaptationSets(mpdAttributes, mpdBaseUrls) { | ||
return function (period, periodIndex) { | ||
return function (period, index) { | ||
var periodBaseUrls = buildBaseUrls(mpdBaseUrls, findChildren(period, 'BaseURL')); | ||
var periodAtt = parseAttributes(period); | ||
var periodAttributes = merge(mpdAttributes, periodAtt, { periodIndex: periodIndex }); | ||
var parsedPeriodId = parseInt(periodAtt.id, 10); // fallback to mapping index if Period@id is not a number | ||
var periodIndex = window$1.isNaN(parsedPeriodId) ? index : parsedPeriodId; | ||
var periodAttributes = merge(mpdAttributes, { | ||
periodIndex: periodIndex | ||
}); | ||
var adaptationSets = findChildren(period, 'AdaptationSet'); | ||
var periodSegmentInfo = getSegmentInformation(period); | ||
return flatten(adaptationSets.map(toRepresentations(periodAttributes, periodBaseUrls, periodSegmentInfo))); | ||
}; | ||
}; | ||
/** | ||
@@ -1688,15 +1842,18 @@ * Traverses the mpd xml tree to generate a list of Representation information objects | ||
*/ | ||
var inheritAttributes = function inheritAttributes(mpd) { | ||
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var _options$manifestUri = options.manifestUri, | ||
manifestUri = _options$manifestUri === undefined ? '' : _options$manifestUri, | ||
_options$NOW = options.NOW, | ||
NOW = _options$NOW === undefined ? Date.now() : _options$NOW, | ||
_options$clientOffset = options.clientOffset, | ||
clientOffset = _options$clientOffset === undefined ? 0 : _options$clientOffset; | ||
var inheritAttributes = function inheritAttributes(mpd, options) { | ||
if (options === void 0) { | ||
options = {}; | ||
} | ||
var _options = options, | ||
_options$manifestUri = _options.manifestUri, | ||
manifestUri = _options$manifestUri === void 0 ? '' : _options$manifestUri, | ||
_options$NOW = _options.NOW, | ||
NOW = _options$NOW === void 0 ? Date.now() : _options$NOW, | ||
_options$clientOffset = _options.clientOffset, | ||
clientOffset = _options$clientOffset === void 0 ? 0 : _options$clientOffset; | ||
var periods = findChildren(mpd, 'Period'); | ||
if (periods.length !== 1) { | ||
// TODO add support for multiperiod | ||
if (!periods.length) { | ||
throw new Error(errors.INVALID_NUMBER_OF_PERIOD); | ||
@@ -1707,7 +1864,5 @@ } | ||
var mpdBaseUrls = buildBaseUrls([manifestUri], findChildren(mpd, 'BaseURL')); | ||
mpdAttributes.sourceDuration = mpdAttributes.mediaPresentationDuration || 0; | ||
mpdAttributes.NOW = NOW; | ||
mpdAttributes.clientOffset = clientOffset; | ||
return flatten(periods.map(toAdaptationSets(mpdAttributes, mpdBaseUrls))); | ||
@@ -1721,3 +1876,3 @@ }; | ||
var parser = new window.DOMParser(); | ||
var parser = new window$1.DOMParser(); | ||
var xml = parser.parseFromString(manifestString, 'application/xml'); | ||
@@ -1741,2 +1896,3 @@ var mpd = xml && xml.documentElement.tagName === 'MPD' ? xml.documentElement : null; | ||
*/ | ||
var parseUTCTimingScheme = function parseUTCTimingScheme(mpd) { | ||
@@ -1756,2 +1912,3 @@ var UTCTimingNode = findChildren(mpd, 'UTCTiming')[0]; | ||
break; | ||
case 'urn:mpeg:dash:utc:http-xsdate:2014': | ||
@@ -1763,2 +1920,3 @@ case 'urn:mpeg:dash:utc:http-iso:2014': | ||
break; | ||
case 'urn:mpeg:dash:utc:direct:2014': | ||
@@ -1769,2 +1927,3 @@ case 'urn:mpeg:dash:utc:direct:2012': | ||
break; | ||
case 'urn:mpeg:dash:utc:http-ntp:2014': | ||
@@ -1781,7 +1940,5 @@ case 'urn:mpeg:dash:utc:ntp:2014': | ||
var VERSION = version; | ||
var parse = function parse(manifestString, options) { | ||
return toM3u8(toPlaylists(inheritAttributes(stringToMpdXml(manifestString), options))); | ||
}; | ||
/** | ||
@@ -1795,2 +1952,3 @@ * Parses the manifest for a UTCTiming node, returning the nodes attributes if found | ||
*/ | ||
var parseUTCTiming = function parseUTCTiming(manifestString) { | ||
@@ -1797,0 +1955,0 @@ return parseUTCTimingScheme(stringToMpdXml(manifestString)); |
@@ -1,12 +0,104 @@ | ||
/** | ||
* mpd-parser | ||
* @version 0.6.1 | ||
* @copyright 2018 Brightcove, Inc | ||
* @license Apache-2.0 | ||
*/ | ||
import URLToolkit from 'url-toolkit'; | ||
import window from 'global/window'; | ||
/*! @name mpd-parser @version 0.7.0 @license Apache-2.0 */ | ||
import window$1 from 'global/window'; | ||
var version = "0.6.1"; | ||
var version = "0.7.0"; | ||
var isObject = function isObject(obj) { | ||
return !!obj && typeof obj === 'object'; | ||
}; | ||
var merge = function merge() { | ||
for (var _len = arguments.length, objects = new Array(_len), _key = 0; _key < _len; _key++) { | ||
objects[_key] = arguments[_key]; | ||
} | ||
return objects.reduce(function (result, source) { | ||
Object.keys(source).forEach(function (key) { | ||
if (Array.isArray(result[key]) && Array.isArray(source[key])) { | ||
result[key] = result[key].concat(source[key]); | ||
} else if (isObject(result[key]) && isObject(source[key])) { | ||
result[key] = merge(result[key], source[key]); | ||
} else { | ||
result[key] = source[key]; | ||
} | ||
}); | ||
return result; | ||
}, {}); | ||
}; | ||
var values = function values(o) { | ||
return Object.keys(o).map(function (k) { | ||
return o[k]; | ||
}); | ||
}; | ||
var range = function range(start, end) { | ||
var result = []; | ||
for (var i = start; i < end; i++) { | ||
result.push(i); | ||
} | ||
return result; | ||
}; | ||
var flatten = function flatten(lists) { | ||
return lists.reduce(function (x, y) { | ||
return x.concat(y); | ||
}, []); | ||
}; | ||
var from = function from(list) { | ||
if (!list.length) { | ||
return []; | ||
} | ||
var result = []; | ||
for (var i = 0; i < list.length; i++) { | ||
result.push(list[i]); | ||
} | ||
return result; | ||
}; | ||
var findIndexes = function findIndexes(l, key) { | ||
return l.reduce(function (a, e, i) { | ||
if (e[key]) { | ||
a.push(i); | ||
} | ||
return a; | ||
}, []); | ||
}; | ||
var mergeDiscontiguousPlaylists = function mergeDiscontiguousPlaylists(playlists) { | ||
var mergedPlaylists = values(playlists.reduce(function (acc, playlist) { | ||
// assuming playlist IDs are the same across periods | ||
// TODO: handle multiperiod where representation sets are not the same | ||
// across periods | ||
var name = playlist.attributes.id + (playlist.attributes.lang || ''); // Periods after first | ||
if (acc[name]) { | ||
var _acc$name$segments; | ||
// first segment of subsequent periods signal a discontinuity | ||
playlist.segments[0].discontinuity = true; | ||
(_acc$name$segments = acc[name].segments).push.apply(_acc$name$segments, playlist.segments); // bubble up contentProtection, this assumes all DRM content | ||
// has the same contentProtection | ||
if (playlist.attributes.contentProtection) { | ||
acc[name].attributes.contentProtection = playlist.attributes.contentProtection; | ||
} | ||
} else { | ||
// first Period | ||
acc[name] = playlist; | ||
} | ||
return acc; | ||
}, {})); | ||
return mergedPlaylists.map(function (playlist) { | ||
playlist.discontinuityStarts = findIndexes(playlist.segments, 'discontinuity'); | ||
return playlist; | ||
}); | ||
}; | ||
var formatAudioPlaylist = function formatAudioPlaylist(_ref) { | ||
@@ -17,3 +109,2 @@ var _attributes; | ||
segments = _ref.segments; | ||
var playlist = { | ||
@@ -40,3 +131,2 @@ attributes: (_attributes = { | ||
}; | ||
var formatVttPlaylist = function formatVttPlaylist(_ref2) { | ||
@@ -56,6 +146,7 @@ var _attributes2; | ||
number: 0 | ||
}]; | ||
// targetDuration should be the same duration as the only segment | ||
}]; // targetDuration should be the same duration as the only segment | ||
attributes.duration = attributes.sourceDuration; | ||
} | ||
return { | ||
@@ -75,3 +166,2 @@ attributes: (_attributes2 = { | ||
}; | ||
var organizeAudioPlaylists = function organizeAudioPlaylists(playlists) { | ||
@@ -81,10 +171,9 @@ return playlists.reduce(function (a, playlist) { | ||
var language = playlist.attributes.lang || ''; | ||
var label = 'main'; | ||
if (language) { | ||
label = playlist.attributes.lang + ' (' + role + ')'; | ||
} | ||
label = playlist.attributes.lang + " (" + role + ")"; | ||
} // skip if we already have the highest quality audio for a language | ||
// skip if we already have the highest quality audio for a language | ||
if (a[label] && a[label].playlists[0].attributes.BANDWIDTH > playlist.attributes.bandwidth) { | ||
@@ -97,16 +186,13 @@ return a; | ||
autoselect: true, | ||
'default': role === 'main', | ||
default: role === 'main', | ||
playlists: [formatAudioPlaylist(playlist)], | ||
uri: '' | ||
}; | ||
return a; | ||
}, {}); | ||
}; | ||
var organizeVttPlaylists = function organizeVttPlaylists(playlists) { | ||
return playlists.reduce(function (a, playlist) { | ||
var label = playlist.attributes.lang || 'text'; | ||
var label = playlist.attributes.lang || 'text'; // skip if we already have subtitles | ||
// skip if we already have subtitles | ||
if (a[label]) { | ||
@@ -118,3 +204,3 @@ return a; | ||
language: label, | ||
'default': false, | ||
default: false, | ||
autoselect: false, | ||
@@ -124,7 +210,5 @@ playlists: [formatVttPlaylist(playlist)], | ||
}; | ||
return a; | ||
}, {}); | ||
}; | ||
var formatVideoPlaylist = function formatVideoPlaylist(_ref3) { | ||
@@ -135,3 +219,2 @@ var _attributes3; | ||
segments = _ref3.segments; | ||
var playlist = { | ||
@@ -164,3 +247,2 @@ attributes: (_attributes3 = { | ||
}; | ||
var toM3u8 = function toM3u8(dashPlaylists) { | ||
@@ -171,11 +253,10 @@ var _mediaGroups; | ||
return {}; | ||
} | ||
} // grab all master attributes | ||
// grab all master attributes | ||
var _dashPlaylists$0$attr = dashPlaylists[0].attributes, | ||
duration = _dashPlaylists$0$attr.sourceDuration, | ||
_dashPlaylists$0$attr2 = _dashPlaylists$0$attr.minimumUpdatePeriod, | ||
minimumUpdatePeriod = _dashPlaylists$0$attr2 === undefined ? 0 : _dashPlaylists$0$attr2; | ||
minimumUpdatePeriod = _dashPlaylists$0$attr2 === void 0 ? 0 : _dashPlaylists$0$attr2; | ||
var videoOnly = function videoOnly(_ref4) { | ||
@@ -185,2 +266,3 @@ var attributes = _ref4.attributes; | ||
}; | ||
var audioOnly = function audioOnly(_ref5) { | ||
@@ -190,2 +272,3 @@ var attributes = _ref5.attributes; | ||
}; | ||
var vttOnly = function vttOnly(_ref6) { | ||
@@ -196,6 +279,5 @@ var attributes = _ref6.attributes; | ||
var videoPlaylists = dashPlaylists.filter(videoOnly).map(formatVideoPlaylist); | ||
var audioPlaylists = dashPlaylists.filter(audioOnly); | ||
var videoPlaylists = mergeDiscontiguousPlaylists(dashPlaylists.filter(videoOnly)).map(formatVideoPlaylist); | ||
var audioPlaylists = mergeDiscontiguousPlaylists(dashPlaylists.filter(audioOnly)); | ||
var vttPlaylists = dashPlaylists.filter(vttOnly); | ||
var master = { | ||
@@ -227,33 +309,167 @@ allowCache: true, | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { | ||
return typeof obj; | ||
} : function (obj) { | ||
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; | ||
}; | ||
var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; | ||
var isObject = function isObject(obj) { | ||
return !!obj && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object'; | ||
}; | ||
function createCommonjsModule(fn, module) { | ||
return module = { exports: {} }, fn(module, module.exports), module.exports; | ||
} | ||
var merge = function merge() { | ||
for (var _len = arguments.length, objects = Array(_len), _key = 0; _key < _len; _key++) { | ||
objects[_key] = arguments[_key]; | ||
} | ||
var urlToolkit = createCommonjsModule(function (module, exports) { | ||
// see https://tools.ietf.org/html/rfc1808 | ||
return objects.reduce(function (result, source) { | ||
/* jshint ignore:start */ | ||
(function(root) { | ||
/* jshint ignore:end */ | ||
Object.keys(source).forEach(function (key) { | ||
var URL_REGEX = /^((?:[a-zA-Z0-9+\-.]+:)?)(\/\/[^\/?#]*)?((?:[^\/\?#]*\/)*.*?)??(;.*?)?(\?.*?)?(#.*?)?$/; | ||
var FIRST_SEGMENT_REGEX = /^([^\/?#]*)(.*)$/; | ||
var SLASH_DOT_REGEX = /(?:\/|^)\.(?=\/)/g; | ||
var SLASH_DOT_DOT_REGEX = /(?:\/|^)\.\.\/(?!\.\.\/).*?(?=\/)/g; | ||
if (Array.isArray(result[key]) && Array.isArray(source[key])) { | ||
result[key] = result[key].concat(source[key]); | ||
} else if (isObject(result[key]) && isObject(source[key])) { | ||
result[key] = merge(result[key], source[key]); | ||
} else { | ||
result[key] = source[key]; | ||
var URLToolkit = { // jshint ignore:line | ||
// If opts.alwaysNormalize is true then the path will always be normalized even when it starts with / or // | ||
// E.g | ||
// With opts.alwaysNormalize = false (default, spec compliant) | ||
// http://a.com/b/cd + /e/f/../g => http://a.com/e/f/../g | ||
// With opts.alwaysNormalize = true (not spec compliant) | ||
// http://a.com/b/cd + /e/f/../g => http://a.com/e/g | ||
buildAbsoluteURL: function(baseURL, relativeURL, opts) { | ||
opts = opts || {}; | ||
// remove any remaining space and CRLF | ||
baseURL = baseURL.trim(); | ||
relativeURL = relativeURL.trim(); | ||
if (!relativeURL) { | ||
// 2a) If the embedded URL is entirely empty, it inherits the | ||
// entire base URL (i.e., is set equal to the base URL) | ||
// and we are done. | ||
if (!opts.alwaysNormalize) { | ||
return baseURL; | ||
} | ||
var basePartsForNormalise = URLToolkit.parseURL(baseURL); | ||
if (!basePartsForNormalise) { | ||
throw new Error('Error trying to parse base URL.'); | ||
} | ||
basePartsForNormalise.path = URLToolkit.normalizePath(basePartsForNormalise.path); | ||
return URLToolkit.buildURLFromParts(basePartsForNormalise); | ||
} | ||
}); | ||
return result; | ||
}, {}); | ||
}; | ||
var relativeParts = URLToolkit.parseURL(relativeURL); | ||
if (!relativeParts) { | ||
throw new Error('Error trying to parse relative URL.'); | ||
} | ||
if (relativeParts.scheme) { | ||
// 2b) If the embedded URL starts with a scheme name, it is | ||
// interpreted as an absolute URL and we are done. | ||
if (!opts.alwaysNormalize) { | ||
return relativeURL; | ||
} | ||
relativeParts.path = URLToolkit.normalizePath(relativeParts.path); | ||
return URLToolkit.buildURLFromParts(relativeParts); | ||
} | ||
var baseParts = URLToolkit.parseURL(baseURL); | ||
if (!baseParts) { | ||
throw new Error('Error trying to parse base URL.'); | ||
} | ||
if (!baseParts.netLoc && baseParts.path && baseParts.path[0] !== '/') { | ||
// If netLoc missing and path doesn't start with '/', assume everthing before the first '/' is the netLoc | ||
// This causes 'example.com/a' to be handled as '//example.com/a' instead of '/example.com/a' | ||
var pathParts = FIRST_SEGMENT_REGEX.exec(baseParts.path); | ||
baseParts.netLoc = pathParts[1]; | ||
baseParts.path = pathParts[2]; | ||
} | ||
if (baseParts.netLoc && !baseParts.path) { | ||
baseParts.path = '/'; | ||
} | ||
var builtParts = { | ||
// 2c) Otherwise, the embedded URL inherits the scheme of | ||
// the base URL. | ||
scheme: baseParts.scheme, | ||
netLoc: relativeParts.netLoc, | ||
path: null, | ||
params: relativeParts.params, | ||
query: relativeParts.query, | ||
fragment: relativeParts.fragment | ||
}; | ||
if (!relativeParts.netLoc) { | ||
// 3) If the embedded URL's <net_loc> is non-empty, we skip to | ||
// Step 7. Otherwise, the embedded URL inherits the <net_loc> | ||
// (if any) of the base URL. | ||
builtParts.netLoc = baseParts.netLoc; | ||
// 4) If the embedded URL path is preceded by a slash "/", the | ||
// path is not relative and we skip to Step 7. | ||
if (relativeParts.path[0] !== '/') { | ||
if (!relativeParts.path) { | ||
// 5) If the embedded URL path is empty (and not preceded by a | ||
// slash), then the embedded URL inherits the base URL path | ||
builtParts.path = baseParts.path; | ||
// 5a) if the embedded URL's <params> is non-empty, we skip to | ||
// step 7; otherwise, it inherits the <params> of the base | ||
// URL (if any) and | ||
if (!relativeParts.params) { | ||
builtParts.params = baseParts.params; | ||
// 5b) if the embedded URL's <query> is non-empty, we skip to | ||
// step 7; otherwise, it inherits the <query> of the base | ||
// URL (if any) and we skip to step 7. | ||
if (!relativeParts.query) { | ||
builtParts.query = baseParts.query; | ||
} | ||
} | ||
} else { | ||
// 6) The last segment of the base URL's path (anything | ||
// following the rightmost slash "/", or the entire path if no | ||
// slash is present) is removed and the embedded URL's path is | ||
// appended in its place. | ||
var baseURLPath = baseParts.path; | ||
var newPath = baseURLPath.substring(0, baseURLPath.lastIndexOf('/') + 1) + relativeParts.path; | ||
builtParts.path = URLToolkit.normalizePath(newPath); | ||
} | ||
} | ||
} | ||
if (builtParts.path === null) { | ||
builtParts.path = opts.alwaysNormalize ? URLToolkit.normalizePath(relativeParts.path) : relativeParts.path; | ||
} | ||
return URLToolkit.buildURLFromParts(builtParts); | ||
}, | ||
parseURL: function(url) { | ||
var parts = URL_REGEX.exec(url); | ||
if (!parts) { | ||
return null; | ||
} | ||
return { | ||
scheme: parts[1] || '', | ||
netLoc: parts[2] || '', | ||
path: parts[3] || '', | ||
params: parts[4] || '', | ||
query: parts[5] || '', | ||
fragment: parts[6] || '' | ||
}; | ||
}, | ||
normalizePath: function(path) { | ||
// The following operations are | ||
// then applied, in order, to the new path: | ||
// 6a) All occurrences of "./", where "." is a complete path | ||
// segment, are removed. | ||
// 6b) If the path ends with "." as a complete path segment, | ||
// that "." is removed. | ||
path = path.split('').reverse().join('').replace(SLASH_DOT_REGEX, ''); | ||
// 6c) All occurrences of "<segment>/../", where <segment> is a | ||
// complete path segment not equal to "..", are removed. | ||
// Removal of these path segments is performed iteratively, | ||
// removing the leftmost matching pattern on each iteration, | ||
// until no matching pattern remains. | ||
// 6d) If the path ends with "<segment>/..", where <segment> is a | ||
// complete path segment not equal to "..", that | ||
// "<segment>/.." is removed. | ||
while (path.length !== (path = path.replace(SLASH_DOT_DOT_REGEX, '')).length) {} // jshint ignore:line | ||
return path.split('').reverse().join(''); | ||
}, | ||
buildURLFromParts: function(parts) { | ||
return parts.scheme + parts.netLoc + parts.path + parts.params + parts.query + parts.fragment; | ||
} | ||
}; | ||
/* jshint ignore:start */ | ||
module.exports = URLToolkit; | ||
})(commonjsGlobal); | ||
/* jshint ignore:end */ | ||
}); | ||
var resolveUrl = function resolveUrl(baseUrl, relativeUrl) { | ||
@@ -263,10 +479,10 @@ // return early if we don't need to resolve | ||
return relativeUrl; | ||
} | ||
} // if the base URL is relative then combine with the current location | ||
// if the base URL is relative then combine with the current location | ||
if (!/\/\//i.test(baseUrl)) { | ||
baseUrl = URLToolkit.buildAbsoluteURL(window.location.href, baseUrl); | ||
baseUrl = urlToolkit.buildAbsoluteURL(window$1.location.href, baseUrl); | ||
} | ||
return URLToolkit.buildAbsoluteURL(baseUrl, relativeUrl); | ||
return urlToolkit.buildAbsoluteURL(baseUrl, relativeUrl); | ||
}; | ||
@@ -298,10 +514,10 @@ | ||
*/ | ||
var urlTypeToSegment = function urlTypeToSegment(_ref) { | ||
var _ref$baseUrl = _ref.baseUrl, | ||
baseUrl = _ref$baseUrl === undefined ? '' : _ref$baseUrl, | ||
baseUrl = _ref$baseUrl === void 0 ? '' : _ref$baseUrl, | ||
_ref$source = _ref.source, | ||
source = _ref$source === undefined ? '' : _ref$source, | ||
source = _ref$source === void 0 ? '' : _ref$source, | ||
_ref$range = _ref.range, | ||
range = _ref$range === undefined ? '' : _ref$range; | ||
range = _ref$range === void 0 ? '' : _ref$range; | ||
var init = { | ||
@@ -316,3 +532,2 @@ uri: source, | ||
var endRange = parseInt(ranges[1], 10); | ||
init.byterange = { | ||
@@ -347,8 +562,7 @@ length: endRange - startRange, | ||
_attributes$timescale = attributes.timescale, | ||
timescale = _attributes$timescale === undefined ? 1 : _attributes$timescale, | ||
timescale = _attributes$timescale === void 0 ? 1 : _attributes$timescale, | ||
_attributes$start = attributes.start, | ||
start = _attributes$start === undefined ? 0 : _attributes$start, | ||
start = _attributes$start === void 0 ? 0 : _attributes$start, | ||
_attributes$minimumUp = attributes.minimumUpdatePeriod, | ||
minimumUpdatePeriod = _attributes$minimumUp === undefined ? 0 : _attributes$minimumUp; | ||
minimumUpdatePeriod = _attributes$minimumUp === void 0 ? 0 : _attributes$minimumUp; | ||
var now = (NOW + clientOffset) / 1000; | ||
@@ -358,6 +572,4 @@ var periodStartWC = availabilityStartTime + start; | ||
var periodDuration = periodEndWC - periodStartWC; | ||
return Math.ceil((periodDuration * timescale - time) / duration); | ||
}; | ||
/** | ||
@@ -376,16 +588,17 @@ * Uses information provided by SegmentTemplate.SegmentTimeline to determine segment | ||
*/ | ||
var parseByTimeline = function parseByTimeline(attributes, segmentTimeline) { | ||
var _attributes$type = attributes.type, | ||
type = _attributes$type === undefined ? 'static' : _attributes$type, | ||
type = _attributes$type === void 0 ? 'static' : _attributes$type, | ||
_attributes$minimumUp2 = attributes.minimumUpdatePeriod, | ||
minimumUpdatePeriod = _attributes$minimumUp2 === undefined ? 0 : _attributes$minimumUp2, | ||
minimumUpdatePeriod = _attributes$minimumUp2 === void 0 ? 0 : _attributes$minimumUp2, | ||
_attributes$media = attributes.media, | ||
media = _attributes$media === undefined ? '' : _attributes$media, | ||
media = _attributes$media === void 0 ? '' : _attributes$media, | ||
sourceDuration = attributes.sourceDuration, | ||
_attributes$timescale2 = attributes.timescale, | ||
timescale = _attributes$timescale2 === undefined ? 1 : _attributes$timescale2, | ||
timescale = _attributes$timescale2 === void 0 ? 1 : _attributes$timescale2, | ||
_attributes$startNumb = attributes.startNumber, | ||
startNumber = _attributes$startNumb === undefined ? 1 : _attributes$startNumb, | ||
startNumber = _attributes$startNumb === void 0 ? 1 : _attributes$startNumb, | ||
timeline = attributes.periodIndex; | ||
var segments = []; | ||
@@ -407,3 +620,2 @@ var time = -1; | ||
// discontinuity | ||
// TODO: How to handle this type of discontinuity | ||
@@ -428,3 +640,2 @@ // timeline++ here would treat it like HLS discontuity and content would | ||
// with $Time$ values of [0, 1, 2, 5, 6, 7, 8, 9, 10, 11] ? | ||
time = segmentTime; | ||
@@ -457,3 +668,8 @@ } | ||
while (number < end) { | ||
segments.push({ number: number, duration: duration / timescale, time: time, timeline: timeline }); | ||
segments.push({ | ||
number: number, | ||
duration: duration / timescale, | ||
time: time, | ||
timeline: timeline | ||
}); | ||
time += duration; | ||
@@ -467,32 +683,2 @@ number++; | ||
var range = function range(start, end) { | ||
var result = []; | ||
for (var i = start; i < end; i++) { | ||
result.push(i); | ||
} | ||
return result; | ||
}; | ||
var flatten = function flatten(lists) { | ||
return lists.reduce(function (x, y) { | ||
return x.concat(y); | ||
}, []); | ||
}; | ||
var from = function from(list) { | ||
if (!list.length) { | ||
return []; | ||
} | ||
var result = []; | ||
for (var i = 0; i < list.length; i++) { | ||
result.push(list[i]); | ||
} | ||
return result; | ||
}; | ||
/** | ||
@@ -502,2 +688,3 @@ * Functions for calculating the range of available segments in static and dynamic | ||
*/ | ||
var segmentRange = { | ||
@@ -512,9 +699,7 @@ /** | ||
*/ | ||
'static': function _static(attributes) { | ||
static: function _static(attributes) { | ||
var duration = attributes.duration, | ||
_attributes$timescale = attributes.timescale, | ||
timescale = _attributes$timescale === undefined ? 1 : _attributes$timescale, | ||
timescale = _attributes$timescale === void 0 ? 1 : _attributes$timescale, | ||
sourceDuration = attributes.sourceDuration; | ||
return { | ||
@@ -526,3 +711,2 @@ start: 0, | ||
/** | ||
@@ -541,11 +725,10 @@ * Returns the current live window range of available segments for a dynamic MPD | ||
_attributes$timescale2 = attributes.timescale, | ||
timescale = _attributes$timescale2 === undefined ? 1 : _attributes$timescale2, | ||
timescale = _attributes$timescale2 === void 0 ? 1 : _attributes$timescale2, | ||
duration = attributes.duration, | ||
_attributes$start = attributes.start, | ||
start = _attributes$start === undefined ? 0 : _attributes$start, | ||
start = _attributes$start === void 0 ? 0 : _attributes$start, | ||
_attributes$minimumUp = attributes.minimumUpdatePeriod, | ||
minimumUpdatePeriod = _attributes$minimumUp === undefined ? 0 : _attributes$minimumUp, | ||
minimumUpdatePeriod = _attributes$minimumUp === void 0 ? 0 : _attributes$minimumUp, | ||
_attributes$timeShift = attributes.timeShiftBufferDepth, | ||
timeShiftBufferDepth = _attributes$timeShift === undefined ? Infinity : _attributes$timeShift; | ||
timeShiftBufferDepth = _attributes$timeShift === void 0 ? Infinity : _attributes$timeShift; | ||
var now = (NOW + clientOffset) / 1000; | ||
@@ -558,3 +741,2 @@ var periodStartWC = availabilityStartTime + start; | ||
var availableEnd = Math.floor((now - periodStartWC) * timescale / duration); | ||
return { | ||
@@ -566,3 +748,2 @@ start: Math.max(0, availableStart), | ||
}; | ||
/** | ||
@@ -591,2 +772,3 @@ * Maps a range of numbers to objects with information needed to build the corresponding | ||
*/ | ||
var toSegments = function toSegments(attributes) { | ||
@@ -596,8 +778,6 @@ return function (number, index) { | ||
_attributes$timescale3 = attributes.timescale, | ||
timescale = _attributes$timescale3 === undefined ? 1 : _attributes$timescale3, | ||
timescale = _attributes$timescale3 === void 0 ? 1 : _attributes$timescale3, | ||
periodIndex = attributes.periodIndex, | ||
_attributes$startNumb = attributes.startNumber, | ||
startNumber = _attributes$startNumb === undefined ? 1 : _attributes$startNumb; | ||
startNumber = _attributes$startNumb === void 0 ? 1 : _attributes$startNumb; | ||
return { | ||
@@ -611,3 +791,2 @@ number: startNumber + number, | ||
}; | ||
/** | ||
@@ -623,8 +802,9 @@ * Returns a list of objects containing segment timing and duration info used for | ||
*/ | ||
var parseByDuration = function parseByDuration(attributes) { | ||
var _attributes$type = attributes.type, | ||
type = _attributes$type === undefined ? 'static' : _attributes$type, | ||
type = _attributes$type === void 0 ? 'static' : _attributes$type, | ||
duration = attributes.duration, | ||
_attributes$timescale4 = attributes.timescale, | ||
timescale = _attributes$timescale4 === undefined ? 1 : _attributes$timescale4, | ||
timescale = _attributes$timescale4 === void 0 ? 1 : _attributes$timescale4, | ||
sourceDuration = attributes.sourceDuration; | ||
@@ -639,5 +819,4 @@ | ||
if (type === 'static') { | ||
var index = segments.length - 1; | ||
var index = segments.length - 1; // final segment may be less than full segment duration | ||
// final segment may be less than full segment duration | ||
segments[index].duration = sourceDuration - duration / timescale * index; | ||
@@ -650,3 +829,2 @@ } | ||
var identifierPattern = /\$([A-z]*)(?:(%0)([0-9]+)d)?\$/g; | ||
/** | ||
@@ -688,2 +866,3 @@ * Replaces template identifiers with corresponding values. To be used as the callback | ||
*/ | ||
var identifierReplacement = function identifierReplacement(values) { | ||
@@ -717,6 +896,5 @@ return function (match, identifier, format, width) { | ||
return '' + new Array(width - value.length + 1).join('0') + value; | ||
return "" + new Array(width - value.length + 1).join('0') + value; | ||
}; | ||
}; | ||
/** | ||
@@ -740,6 +918,6 @@ * Constructs a segment url from a template string | ||
*/ | ||
var constructTemplateUrl = function constructTemplateUrl(url, values) { | ||
return url.replace(identifierPattern, identifierReplacement(values)); | ||
}; | ||
/** | ||
@@ -758,2 +936,3 @@ * Generates a list of objects containing timing and duration information about each | ||
*/ | ||
var parseTemplateInfo = function parseTemplateInfo(attributes, segmentTimeline) { | ||
@@ -777,3 +956,2 @@ if (!attributes.duration && !segmentTimeline) { | ||
}; | ||
/** | ||
@@ -791,2 +969,3 @@ * Generates a list of segments using information provided by the SegmentTemplate element | ||
*/ | ||
var segmentsFromTemplate = function segmentsFromTemplate(attributes, segmentTimeline) { | ||
@@ -797,7 +976,7 @@ var templateValues = { | ||
}; | ||
var _attributes$initializ = attributes.initialization, | ||
initialization = _attributes$initializ === undefined ? { sourceURL: '', range: '' } : _attributes$initializ; | ||
initialization = _attributes$initializ === void 0 ? { | ||
sourceURL: '', | ||
range: '' | ||
} : _attributes$initializ; | ||
var mapSegment = urlTypeToSegment({ | ||
@@ -808,11 +987,7 @@ baseUrl: attributes.baseUrl, | ||
}); | ||
var segments = parseTemplateInfo(attributes, segmentTimeline); | ||
return segments.map(function (segment) { | ||
templateValues.Number = segment.number; | ||
templateValues.Time = segment.time; | ||
var uri = constructTemplateUrl(attributes.media || '', templateValues); | ||
return { | ||
@@ -850,8 +1025,7 @@ uri: uri, | ||
*/ | ||
var SegmentURLToSegmentObject = function SegmentURLToSegmentObject(attributes, segmentUrl) { | ||
var baseUrl = attributes.baseUrl, | ||
_attributes$initializ = attributes.initialization, | ||
initialization = _attributes$initializ === undefined ? {} : _attributes$initializ; | ||
initialization = _attributes$initializ === void 0 ? {} : _attributes$initializ; | ||
var initSegment = urlTypeToSegment({ | ||
@@ -862,3 +1036,2 @@ baseUrl: baseUrl, | ||
}); | ||
var segment = urlTypeToSegment({ | ||
@@ -869,8 +1042,5 @@ baseUrl: baseUrl, | ||
}); | ||
segment.map = initSegment; | ||
return segment; | ||
}; | ||
/** | ||
@@ -889,8 +1059,8 @@ * Generates a list of segments using information provided by the SegmentList element | ||
*/ | ||
var segmentsFromList = function segmentsFromList(attributes, segmentTimeline) { | ||
var duration = attributes.duration, | ||
_attributes$segmentUr = attributes.segmentUrls, | ||
segmentUrls = _attributes$segmentUr === undefined ? [] : _attributes$segmentUr; | ||
// Per spec (5.3.9.2.1) no way to determine segment duration OR | ||
segmentUrls = _attributes$segmentUr === void 0 ? [] : _attributes$segmentUr; // 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. | ||
@@ -905,3 +1075,3 @@ | ||
}); | ||
var segmentTimeInfo = void 0; | ||
var segmentTimeInfo; | ||
@@ -919,3 +1089,2 @@ if (duration) { | ||
var segment = segmentUrlMap[index]; | ||
segment.timeline = segmentTime.timeline; | ||
@@ -925,10 +1094,9 @@ segment.duration = segmentTime.duration; | ||
return segment; | ||
} | ||
// Since we're mapping we should get rid of any blank segments (in case | ||
} // 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(function (segment) { | ||
return segment; | ||
}); | ||
return segments; | ||
@@ -947,15 +1115,14 @@ }; | ||
*/ | ||
var segmentsFromBase = function segmentsFromBase(attributes) { | ||
var baseUrl = attributes.baseUrl, | ||
_attributes$initializ = attributes.initialization, | ||
initialization = _attributes$initializ === undefined ? {} : _attributes$initializ, | ||
initialization = _attributes$initializ === void 0 ? {} : _attributes$initializ, | ||
sourceDuration = attributes.sourceDuration, | ||
_attributes$timescale = attributes.timescale, | ||
timescale = _attributes$timescale === undefined ? 1 : _attributes$timescale, | ||
timescale = _attributes$timescale === void 0 ? 1 : _attributes$timescale, | ||
_attributes$indexRang = attributes.indexRange, | ||
indexRange = _attributes$indexRang === undefined ? '' : _attributes$indexRang, | ||
duration = attributes.duration; | ||
indexRange = _attributes$indexRang === void 0 ? '' : _attributes$indexRang, | ||
duration = attributes.duration; // base url is required for SegmentBase to work, per spec (Section 5.3.9.2.1) | ||
// base url is required for SegmentBase to work, per spec (Section 5.3.9.2.1) | ||
if (!baseUrl) { | ||
@@ -970,8 +1137,10 @@ throw new Error(errors.NO_BASE_URL); | ||
}); | ||
var segment = urlTypeToSegment({ baseUrl: baseUrl, source: baseUrl, range: indexRange }); | ||
var segment = urlTypeToSegment({ | ||
baseUrl: baseUrl, | ||
source: baseUrl, | ||
range: indexRange | ||
}); | ||
segment.map = initSegment; // If there is a duration, use it, otherwise use the given duration of the source | ||
// (since SegmentBase is only for one total segment) | ||
segment.map = initSegment; | ||
// If there is a duration, use it, otherwise use the given duration of the source | ||
// (since SegmentBase is only for one total segment) | ||
if (duration) { | ||
@@ -987,7 +1156,6 @@ var segmentTimeInfo = parseByDuration(attributes); | ||
segment.timeline = 0; | ||
} | ||
} // This is used for mediaSequence | ||
// This is used for mediaSequence | ||
segment.number = 0; | ||
return [segment]; | ||
@@ -999,6 +1167,5 @@ }; | ||
segmentInfo = _ref.segmentInfo; | ||
var segmentAttributes; | ||
var segmentsFn; | ||
var segmentAttributes = void 0; | ||
var segmentsFn = void 0; | ||
if (segmentInfo.template) { | ||
@@ -1016,10 +1183,11 @@ segmentsFn = segmentsFromTemplate; | ||
if (!segmentsFn) { | ||
return { attributes: attributes }; | ||
return { | ||
attributes: attributes | ||
}; | ||
} | ||
var segments = segmentsFn(segmentAttributes, segmentInfo.timeline); | ||
// The @duration attribute will be used to determin the playlist's targetDuration which | ||
var segments = segmentsFn(segmentAttributes, segmentInfo.timeline); // The @duration attribute will be used to determin the playlist's targetDuration which | ||
// must be in seconds. Since we've generated the segment list, we no longer need | ||
// @duration to be in @timescale units, so we can convert it here. | ||
if (segmentAttributes.duration) { | ||
@@ -1029,5 +1197,3 @@ var _segmentAttributes = segmentAttributes, | ||
_segmentAttributes$ti = _segmentAttributes.timescale, | ||
timescale = _segmentAttributes$ti === undefined ? 1 : _segmentAttributes$ti; | ||
timescale = _segmentAttributes$ti === void 0 ? 1 : _segmentAttributes$ti; | ||
segmentAttributes.duration = duration / timescale; | ||
@@ -1049,3 +1215,2 @@ } else if (segments.length) { | ||
}; | ||
var toPlaylists = function toPlaylists(representations) { | ||
@@ -1061,3 +1226,2 @@ return representations.map(generateSegments); | ||
}; | ||
var getContent = function getContent(element) { | ||
@@ -1072,5 +1236,4 @@ return element.textContent.trim(); | ||
var SECONDS_IN_HOUR = 60 * 60; | ||
var SECONDS_IN_MIN = 60; | ||
var SECONDS_IN_MIN = 60; // P10Y10M10DT10H10M10.1S | ||
// P10Y10M10DT10H10M10.1S | ||
var durationRegex = /P(?:(\d*)Y)?(?:(\d*)M)?(?:(\d*)D)?(?:T(?:(\d*)H)?(?:(\d*)M)?(?:([\d.]*)S)?)?/; | ||
@@ -1093,10 +1256,8 @@ var match = durationRegex.exec(str); | ||
}; | ||
var parseDate = function parseDate(str) { | ||
// Date format without timezone according to ISO 8601 | ||
// YYY-MM-DDThh:mm:ss.ssssss | ||
var dateRegex = /^\d+-\d+-\d+T\d+:\d+:\d+(\.\d+)?$/; | ||
var dateRegex = /^\d+-\d+-\d+T\d+:\d+:\d+(\.\d+)?$/; // If the date string does not specifiy a timezone, we must specifiy UTC. This is | ||
// expressed by ending with 'Z' | ||
// If the date string does not specifiy a timezone, we must specifiy UTC. This is | ||
// expressed by ending with 'Z' | ||
if (dateRegex.test(str)) { | ||
@@ -1109,3 +1270,2 @@ str += 'Z'; | ||
// TODO: maybe order these in some way that makes it easy to find specific attributes | ||
var parsers = { | ||
@@ -1125,3 +1285,2 @@ /** | ||
/** | ||
@@ -1141,3 +1300,2 @@ * Specifies the Segment availability start time for all Segments referred to in this | ||
/** | ||
@@ -1156,3 +1314,2 @@ * Specifies the smallest period between potential changes to the MPD. Format is a | ||
/** | ||
@@ -1171,3 +1328,2 @@ * Specifies the duration of the smallest time shifting buffer for any Representation | ||
/** | ||
@@ -1186,3 +1342,2 @@ * Specifies the PeriodStart time of the Period relative to the availabilityStarttime. | ||
/** | ||
@@ -1200,3 +1355,2 @@ * Specifies the width of the visual presentation | ||
/** | ||
@@ -1214,3 +1368,2 @@ * Specifies the height of the visual presentation | ||
/** | ||
@@ -1228,3 +1381,2 @@ * Specifies the bitrate of the representation | ||
/** | ||
@@ -1242,3 +1394,2 @@ * Specifies the number of the first Media Segment in this Representation in the Period | ||
/** | ||
@@ -1256,3 +1407,2 @@ * Specifies the timescale in units per seconds | ||
/** | ||
@@ -1280,3 +1430,2 @@ * Specifies the constant approximate Segment duration | ||
/** | ||
@@ -1294,3 +1443,2 @@ * Specifies the Segment duration, in units of the value of the @timescale. | ||
/** | ||
@@ -1309,3 +1457,2 @@ * Specifies the MPD start time, in @timescale units, the first Segment in the series | ||
/** | ||
@@ -1324,3 +1471,2 @@ * Specifies the repeat count of the number of following contiguous Segments with the | ||
/** | ||
@@ -1339,3 +1485,2 @@ * Default parser for all other attributes. Acts as a no-op and just returns the value | ||
}; | ||
/** | ||
@@ -1350,2 +1495,3 @@ * Gets all the attributes and values of the provided node, parses attributes with known | ||
*/ | ||
var parseAttributes = function parseAttributes(el) { | ||
@@ -1358,5 +1504,3 @@ if (!(el && el.attributes)) { | ||
var parseFn = parsers[e.name] || parsers.DEFAULT; | ||
a[e.name] = parseFn(e.value); | ||
return a; | ||
@@ -1367,3 +1511,3 @@ }, {}); | ||
function decodeB64ToUint8Array(b64Text) { | ||
var decodedString = window.atob(b64Text); | ||
var decodedString = window$1.atob(b64Text); | ||
var array = new Uint8Array(decodedString.length); | ||
@@ -1374,2 +1518,3 @@ | ||
} | ||
return array; | ||
@@ -1384,3 +1529,2 @@ } | ||
}; | ||
/** | ||
@@ -1396,2 +1540,3 @@ * Builds a list of urls that is the product of the reference urls and BaseURL values | ||
*/ | ||
var buildBaseUrls = function buildBaseUrls(referenceUrls, baseUrlElements) { | ||
@@ -1408,3 +1553,2 @@ if (!baseUrlElements.length) { | ||
}; | ||
/** | ||
@@ -1432,2 +1576,3 @@ * Contains all Segment information for its containing AdaptationSet | ||
*/ | ||
var getSegmentInformation = function getSegmentInformation(adaptationSet) { | ||
@@ -1437,3 +1582,5 @@ var segmentTemplate = findChildren(adaptationSet, 'SegmentTemplate')[0]; | ||
var segmentUrls = segmentList && findChildren(segmentList, 'SegmentURL').map(function (s) { | ||
return merge({ tag: 'SegmentURL' }, parseAttributes(s)); | ||
return merge({ | ||
tag: 'SegmentURL' | ||
}, parseAttributes(s)); | ||
}); | ||
@@ -1444,5 +1591,3 @@ var segmentBase = findChildren(adaptationSet, 'SegmentBase')[0]; | ||
var segmentInitializationParentNode = segmentList || segmentBase || segmentTemplate; | ||
var segmentInitialization = segmentInitializationParentNode && findChildren(segmentInitializationParentNode, 'Initialization')[0]; | ||
// SegmentTemplate is handled slightly differently, since it can have both | ||
var segmentInitialization = segmentInitializationParentNode && findChildren(segmentInitializationParentNode, 'Initialization')[0]; // SegmentTemplate is handled slightly differently, since it can have both | ||
// @initialization and an <Initialization> node. @initialization can be templated, | ||
@@ -1452,2 +1597,3 @@ // while the node can have a url and range specified. If the <SegmentTemplate> has | ||
// the node, as this interaction is not defined in the spec. | ||
var template = segmentTemplate && parseAttributes(segmentTemplate); | ||
@@ -1461,3 +1607,5 @@ | ||
// for <SegmentTemplate> | ||
template.initialization = { sourceURL: template.initialization }; | ||
template.initialization = { | ||
sourceURL: template.initialization | ||
}; | ||
} | ||
@@ -1478,3 +1626,2 @@ | ||
}; | ||
Object.keys(segmentInfo).forEach(function (key) { | ||
@@ -1485,6 +1632,4 @@ if (!segmentInfo[key]) { | ||
}); | ||
return segmentInfo; | ||
}; | ||
/** | ||
@@ -1525,2 +1670,3 @@ * Contains Segment information and attributes needed to construct a Playlist object | ||
*/ | ||
var inheritBaseUrls = function inheritBaseUrls(adaptationSetAttributes, adaptationSetBaseUrls, adaptationSetSegmentInfo) { | ||
@@ -1532,7 +1678,8 @@ return function (representation) { | ||
var representationSegmentInfo = getSegmentInformation(representation); | ||
return repBaseUrls.map(function (baseUrl) { | ||
return { | ||
segmentInfo: merge(adaptationSetSegmentInfo, representationSegmentInfo), | ||
attributes: merge(attributes, { baseUrl: baseUrl }) | ||
attributes: merge(attributes, { | ||
baseUrl: baseUrl | ||
}) | ||
}; | ||
@@ -1542,3 +1689,2 @@ }); | ||
}; | ||
/** | ||
@@ -1553,2 +1699,3 @@ * Tranforms a series of content protection nodes to | ||
*/ | ||
var generateKeySystemInformation = function generateKeySystemInformation(contentProtectionNodes) { | ||
@@ -1560,4 +1707,5 @@ return contentProtectionNodes.reduce(function (acc, node) { | ||
if (keySystem) { | ||
acc[keySystem] = { attributes: attributes }; | ||
acc[keySystem] = { | ||
attributes: attributes | ||
}; | ||
var psshNode = findChildren(node, 'cenc:pssh')[0]; | ||
@@ -1568,3 +1716,2 @@ | ||
var psshBuffer = pssh && decodeB64ToUint8Array(pssh); | ||
acc[keySystem].pssh = psshBuffer; | ||
@@ -1577,3 +1724,2 @@ } | ||
}; | ||
/** | ||
@@ -1603,2 +1749,4 @@ * Maps an AdaptationSet node to a list of Representation information objects | ||
*/ | ||
var toRepresentations = function toRepresentations(periodAttributes, periodBaseUrls, periodSegmentInfo) { | ||
@@ -1609,10 +1757,12 @@ return function (adaptationSet) { | ||
var role = findChildren(adaptationSet, 'Role')[0]; | ||
var roleAttributes = { role: parseAttributes(role) }; | ||
var roleAttributes = { | ||
role: parseAttributes(role) | ||
}; | ||
var attrs = merge(periodAttributes, adaptationSetAttributes, roleAttributes); | ||
var contentProtection = generateKeySystemInformation(findChildren(adaptationSet, 'ContentProtection')); | ||
if (Object.keys(contentProtection).length) { | ||
attrs = merge(attrs, { contentProtection: contentProtection }); | ||
attrs = merge(attrs, { | ||
contentProtection: contentProtection | ||
}); | ||
} | ||
@@ -1623,7 +1773,5 @@ | ||
var adaptationSetSegmentInfo = merge(periodSegmentInfo, segmentInfo); | ||
return flatten(representations.map(inheritBaseUrls(attrs, adaptationSetBaseUrls, adaptationSetSegmentInfo))); | ||
}; | ||
}; | ||
/** | ||
@@ -1654,14 +1802,18 @@ * Maps an Period node to a list of Representation inforamtion objects for all | ||
*/ | ||
var toAdaptationSets = function toAdaptationSets(mpdAttributes, mpdBaseUrls) { | ||
return function (period, periodIndex) { | ||
return function (period, index) { | ||
var periodBaseUrls = buildBaseUrls(mpdBaseUrls, findChildren(period, 'BaseURL')); | ||
var periodAtt = parseAttributes(period); | ||
var periodAttributes = merge(mpdAttributes, periodAtt, { periodIndex: periodIndex }); | ||
var parsedPeriodId = parseInt(periodAtt.id, 10); // fallback to mapping index if Period@id is not a number | ||
var periodIndex = window$1.isNaN(parsedPeriodId) ? index : parsedPeriodId; | ||
var periodAttributes = merge(mpdAttributes, { | ||
periodIndex: periodIndex | ||
}); | ||
var adaptationSets = findChildren(period, 'AdaptationSet'); | ||
var periodSegmentInfo = getSegmentInformation(period); | ||
return flatten(adaptationSets.map(toRepresentations(periodAttributes, periodBaseUrls, periodSegmentInfo))); | ||
}; | ||
}; | ||
/** | ||
@@ -1684,15 +1836,18 @@ * Traverses the mpd xml tree to generate a list of Representation information objects | ||
*/ | ||
var inheritAttributes = function inheritAttributes(mpd) { | ||
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var _options$manifestUri = options.manifestUri, | ||
manifestUri = _options$manifestUri === undefined ? '' : _options$manifestUri, | ||
_options$NOW = options.NOW, | ||
NOW = _options$NOW === undefined ? Date.now() : _options$NOW, | ||
_options$clientOffset = options.clientOffset, | ||
clientOffset = _options$clientOffset === undefined ? 0 : _options$clientOffset; | ||
var inheritAttributes = function inheritAttributes(mpd, options) { | ||
if (options === void 0) { | ||
options = {}; | ||
} | ||
var _options = options, | ||
_options$manifestUri = _options.manifestUri, | ||
manifestUri = _options$manifestUri === void 0 ? '' : _options$manifestUri, | ||
_options$NOW = _options.NOW, | ||
NOW = _options$NOW === void 0 ? Date.now() : _options$NOW, | ||
_options$clientOffset = _options.clientOffset, | ||
clientOffset = _options$clientOffset === void 0 ? 0 : _options$clientOffset; | ||
var periods = findChildren(mpd, 'Period'); | ||
if (periods.length !== 1) { | ||
// TODO add support for multiperiod | ||
if (!periods.length) { | ||
throw new Error(errors.INVALID_NUMBER_OF_PERIOD); | ||
@@ -1703,7 +1858,5 @@ } | ||
var mpdBaseUrls = buildBaseUrls([manifestUri], findChildren(mpd, 'BaseURL')); | ||
mpdAttributes.sourceDuration = mpdAttributes.mediaPresentationDuration || 0; | ||
mpdAttributes.NOW = NOW; | ||
mpdAttributes.clientOffset = clientOffset; | ||
return flatten(periods.map(toAdaptationSets(mpdAttributes, mpdBaseUrls))); | ||
@@ -1717,3 +1870,3 @@ }; | ||
var parser = new window.DOMParser(); | ||
var parser = new window$1.DOMParser(); | ||
var xml = parser.parseFromString(manifestString, 'application/xml'); | ||
@@ -1737,2 +1890,3 @@ var mpd = xml && xml.documentElement.tagName === 'MPD' ? xml.documentElement : null; | ||
*/ | ||
var parseUTCTimingScheme = function parseUTCTimingScheme(mpd) { | ||
@@ -1752,2 +1906,3 @@ var UTCTimingNode = findChildren(mpd, 'UTCTiming')[0]; | ||
break; | ||
case 'urn:mpeg:dash:utc:http-xsdate:2014': | ||
@@ -1759,2 +1914,3 @@ case 'urn:mpeg:dash:utc:http-iso:2014': | ||
break; | ||
case 'urn:mpeg:dash:utc:direct:2014': | ||
@@ -1765,2 +1921,3 @@ case 'urn:mpeg:dash:utc:direct:2012': | ||
break; | ||
case 'urn:mpeg:dash:utc:http-ntp:2014': | ||
@@ -1777,7 +1934,5 @@ case 'urn:mpeg:dash:utc:ntp:2014': | ||
var VERSION = version; | ||
var parse = function parse(manifestString, options) { | ||
return toM3u8(toPlaylists(inheritAttributes(stringToMpdXml(manifestString), options))); | ||
}; | ||
/** | ||
@@ -1791,2 +1946,3 @@ * Parses the manifest for a UTCTiming node, returning the nodes attributes if found | ||
*/ | ||
var parseUTCTiming = function parseUTCTiming(manifestString) { | ||
@@ -1793,0 +1949,0 @@ return parseUTCTimingScheme(stringToMpdXml(manifestString)); |
@@ -1,7 +0,2 @@ | ||
/** | ||
* mpd-parser | ||
* @version 0.6.1 | ||
* @copyright 2018 Brightcove, Inc | ||
* @license Apache-2.0 | ||
*/ | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e(t.mpdParser={})}(this,function(t){"use strict";var e=function(t){var e,r=t.attributes,n=t.segments,i={attributes:(e={NAME:r.id,AUDIO:"audio",SUBTITLES:"subs",RESOLUTION:{width:r.width,height:r.height},CODECS:r.codecs,BANDWIDTH:r.bandwidth},e["PROGRAM-ID"]=1,e),uri:"",endList:"static"===(r.type||"static"),timeline:r.periodIndex,resolvedUri:"",targetDuration:r.duration,segments:n,mediaSequence:n.length?n[0].number:1};return r.contentProtection&&(i.contentProtection=r.contentProtection),i},r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},n=function(t){return!!t&&"object"===(void 0===t?"undefined":r(t))},i=function t(){for(var e=arguments.length,r=Array(e),i=0;i<e;i++)r[i]=arguments[i];return r.reduce(function(e,r){return Object.keys(r).forEach(function(i){Array.isArray(e[i])&&Array.isArray(r[i])?e[i]=e[i].concat(r[i]):n(e[i])&&n(r[i])?e[i]=t(e[i],r[i]):e[i]=r[i]}),e},{})},a="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},u=function(t,e){return e={exports:{}},t(e,e.exports),e.exports}(function(t,e){!function(e){var r=/^((?:[^\/;?#]+:)?)(\/\/[^\/\;?#]*)?(.*?)??(;.*?)?(\?.*?)?(#.*?)?$/,n=/^([^\/;?#]*)(.*)$/,i=/(?:\/|^)\.(?=\/)/g,a=/(?:\/|^)\.\.\/(?!\.\.\/).*?(?=\/)/g,u={buildAbsoluteURL:function(t,e,r){if(r=r||{},t=t.trim(),!(e=e.trim())){if(!r.alwaysNormalize)return t;var i=this.parseURL(t);if(!o)throw new Error("Error trying to parse base URL.");return i.path=u.normalizePath(i.path),u.buildURLFromParts(i)}var a=this.parseURL(e);if(!a)throw new Error("Error trying to parse relative URL.");if(a.scheme)return r.alwaysNormalize?(a.path=u.normalizePath(a.path),u.buildURLFromParts(a)):e;var o=this.parseURL(t);if(!o)throw new Error("Error trying to parse base URL.");if(!o.netLoc&&o.path&&"/"!==o.path[0]){var s=n.exec(o.path);o.netLoc=s[1],o.path=s[2]}o.netLoc&&!o.path&&(o.path="/");var c={scheme:o.scheme,netLoc:a.netLoc,path:null,params:a.params,query:a.query,fragment:a.fragment};if(!a.netLoc&&(c.netLoc=o.netLoc,"/"!==a.path[0]))if(a.path){var d=o.path,l=d.substring(0,d.lastIndexOf("/")+1)+a.path;c.path=u.normalizePath(l)}else c.path=o.path,a.params||(c.params=o.params,a.query||(c.query=o.query));return null===c.path&&(c.path=r.alwaysNormalize?u.normalizePath(a.path):a.path),u.buildURLFromParts(c)},parseURL:function(t){var e=r.exec(t);return e?{scheme:e[1]||"",netLoc:e[2]||"",path:e[3]||"",params:e[4]||"",query:e[5]||"",fragment:e[6]||""}:null},normalizePath:function(t){for(t=t.split("").reverse().join("").replace(i,"");t.length!==(t=t.replace(a,"")).length;);return t.split("").reverse().join("")},buildURLFromParts:function(t){return t.scheme+t.netLoc+t.path+t.params+t.query+t.fragment}};t.exports=u}()}),o="undefined"!=typeof window?window:void 0!==a?a:"undefined"!=typeof self?self:{},s=function(t,e){return/^[a-z]+:/i.test(e)?e:(/\/\//i.test(t)||(t=u.buildAbsoluteURL(o.location.href,t)),u.buildAbsoluteURL(t,e))},c=function(t){var e=t.baseUrl,r=void 0===e?"":e,n=t.source,i=void 0===n?"":n,a=t.range,u=void 0===a?"":a,o={uri:i,resolvedUri:s(r||"",i)};if(u){var c=u.split("-"),d=parseInt(c[0],10),l=parseInt(c[1],10);o.byterange={length:l-d,offset:d}}return o},d=function(t,e,r){var n=t.NOW,i=t.clientOffset,a=t.availabilityStartTime,u=t.timescale,o=void 0===u?1:u,s=t.start,c=void 0===s?0:s,d=t.minimumUpdatePeriod,l=(n+i)/1e3+(void 0===d?0:d)-(a+c);return Math.ceil((l*o-e)/r)},l=function(t,e){for(var r=t.type,n=void 0===r?"static":r,i=t.minimumUpdatePeriod,a=void 0===i?0:i,u=t.media,o=void 0===u?"":u,s=t.sourceDuration,c=t.timescale,l=void 0===c?1:c,m=t.startNumber,f=void 0===m?1:m,p=t.periodIndex,h=[],v=-1,b=0;b<e.length;b++){var g=e[b],U=g.d,y=g.r||0,I=g.t||0;v<0&&(v=I),I&&I>v&&(v=I);var D=void 0;if(y<0){var L=b+1;D=L===e.length?"dynamic"===n&&a>0&&o.indexOf("$Number$")>0?d(t,v,U):(s*l-v)/U:(e[L].t-v)/U}else D=y+1;for(var w=f+h.length+D,E=f+h.length;E<w;)h.push({number:E,duration:U/l,time:v,timeline:p}),v+=U,E++}return h},m=function(t){return t.reduce(function(t,e){return t.concat(e)},[])},f=function(t){if(!t.length)return[];for(var e=[],r=0;r<t.length;r++)e.push(t[r]);return e},p={static:function(t){var e=t.duration,r=t.timescale,n=void 0===r?1:r,i=t.sourceDuration;return{start:0,end:Math.ceil(i/(e/n))}},dynamic:function(t){var e=t.NOW,r=t.clientOffset,n=t.availabilityStartTime,i=t.timescale,a=void 0===i?1:i,u=t.duration,o=t.start,s=void 0===o?0:o,c=t.minimumUpdatePeriod,d=void 0===c?0:c,l=t.timeShiftBufferDepth,m=void 0===l?1/0:l,f=(e+r)/1e3,p=n+s,h=f+d-p,v=Math.ceil(h*a/u),b=Math.floor((f-p-m)*a/u),g=Math.floor((f-p)*a/u);return{start:Math.max(0,b),end:Math.min(v,g)}}},h=function(t){var e=t.type,r=void 0===e?"static":e,n=t.duration,i=t.timescale,a=void 0===i?1:i,u=t.sourceDuration,o=p[r](t),s=function(t,e){for(var r=[],n=t;n<e;n++)r.push(n);return r}(o.start,o.end).map(function(t){return function(e,r){var n=t.duration,i=t.timescale,a=void 0===i?1:i,u=t.periodIndex,o=t.startNumber;return{number:(void 0===o?1:o)+e,duration:n/a,timeline:u,time:r*n}}}(t));if("static"===r){var c=s.length-1;s[c].duration=u-n/a*c}return s},v=/\$([A-z]*)(?:(%0)([0-9]+)d)?\$/g,b=function(t,e){return t.replace(v,function(t){return function(e,r,n,i){if("$$"===e)return"$";if(void 0===t[r])return e;var a=""+t[r];return"RepresentationID"===r?a:(i=n?parseInt(i,10):1,a.length>=i?a:""+new Array(i-a.length+1).join("0")+a)}}(e))},g=function(t,e){var r={RepresentationID:t.id,Bandwidth:t.bandwidth||0},n=t.initialization,i=void 0===n?{sourceURL:"",range:""}:n,a=c({baseUrl:t.baseUrl,source:b(i.sourceURL,r),range:i.range});return function(t,e){return t.duration||e?t.duration?h(t):l(t,e):[{number:t.startNumber||1,duration:t.sourceDuration,time:0,timeline:t.periodIndex}]}(t,e).map(function(e){r.Number=e.number,r.Time=e.time;var n=b(t.media||"",r);return{uri:n,timeline:e.timeline,duration:e.duration,resolvedUri:s(t.baseUrl||"",n),map:a,number:e.number}})},U="INVALID_NUMBER_OF_PERIOD",y="DASH_EMPTY_MANIFEST",I="DASH_INVALID_XML",D="NO_BASE_URL",L="SEGMENT_TIME_UNSPECIFIED",w="UNSUPPORTED_UTC_TIMING_SCHEME",E=function(t,e){var r=t.duration,n=t.segmentUrls,i=void 0===n?[]:n;if(!r&&!e||r&&e)throw new Error(L);var a=i.map(function(e){return function(t,e){var r=t.baseUrl,n=t.initialization,i=void 0===n?{}:n,a=c({baseUrl:r,source:i.sourceURL,range:i.range}),u=c({baseUrl:r,source:e.media,range:e.mediaRange});return u.map=a,u}(t,e)}),u=void 0;r&&(u=h(t)),e&&(u=l(t,e));return u.map(function(t,e){if(a[e]){var r=a[e];return r.timeline=t.timeline,r.duration=t.duration,r.number=t.number,r}}).filter(function(t){return t})},R=function(t){var e=t.baseUrl,r=t.initialization,n=void 0===r?{}:r,i=t.sourceDuration,a=t.timescale,u=void 0===a?1:a,o=t.indexRange,s=void 0===o?"":o,d=t.duration;if(!e)throw new Error(D);var l=c({baseUrl:e,source:n.sourceURL,range:n.range}),m=c({baseUrl:e,source:e,range:s});if(m.map=l,d){var f=h(t);f.length&&(m.duration=f[0].duration,m.timeline=f[0].timeline)}else i&&(m.duration=i/u,m.timeline=0);return m.number=0,[m]},S=function(t){var e=t.attributes,r=t.segmentInfo,n=void 0,a=void 0;if(r.template?(a=g,n=i(e,r.template)):r.base?(a=R,n=i(e,r.base)):r.list&&(a=E,n=i(e,r.list)),!a)return{attributes:e};var u=a(n,r.timeline);if(n.duration){var o=n,s=o.duration,c=o.timescale,d=void 0===c?1:c;n.duration=s/d}else u.length?n.duration=u.reduce(function(t,e){return Math.max(t,Math.ceil(e.duration))},0):n.duration=0;return{attributes:n,segments:u}},T=function(t,e){return f(t.childNodes).filter(function(t){return t.tagName===e})},P=function(t){return t.textContent.trim()},N=function(t){var e=/P(?:(\d*)Y)?(?:(\d*)M)?(?:(\d*)D)?(?:T(?:(\d*)H)?(?:(\d*)M)?(?:([\d.]*)S)?)?/.exec(t);if(!e)return 0;var r=e.slice(1),n=r[0],i=r[1],a=r[2],u=r[3],o=r[4],s=r[5];return 31536e3*parseFloat(n||0)+2592e3*parseFloat(i||0)+86400*parseFloat(a||0)+3600*parseFloat(u||0)+60*parseFloat(o||0)+parseFloat(s||0)},A={mediaPresentationDuration:function(t){return N(t)},availabilityStartTime:function(t){return function(t){return/^\d+-\d+-\d+T\d+:\d+:\d+(\.\d+)?$/.test(t)&&(t+="Z"),Date.parse(t)}(t)/1e3},minimumUpdatePeriod:function(t){return N(t)},timeShiftBufferDepth:function(t){return N(t)},start:function(t){return N(t)},width:function(t){return parseInt(t,10)},height:function(t){return parseInt(t,10)},bandwidth:function(t){return parseInt(t,10)},startNumber:function(t){return parseInt(t,10)},timescale:function(t){return parseInt(t,10)},duration:function(t){var e=parseInt(t,10);return isNaN(e)?N(t):e},d:function(t){return parseInt(t,10)},t:function(t){return parseInt(t,10)},r:function(t){return parseInt(t,10)},DEFAULT:function(t){return t}},O=function(t){return t&&t.attributes?f(t.attributes).reduce(function(t,e){var r=A[e.name]||A.DEFAULT;return t[e.name]=r(e.value),t},{}):{}},x={"urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b":"org.w3.clearkey","urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed":"com.widevine.alpha","urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95":"com.microsoft.playready","urn:uuid:f239e769-efa3-4850-9c16-a903c6932efb":"com.adobe.primetime"},M=function(t,e){return e.length?m(t.map(function(t){return e.map(function(e){return s(t,P(e))})})):t},z=function(t){var e=T(t,"SegmentTemplate")[0],r=T(t,"SegmentList")[0],n=r&&T(r,"SegmentURL").map(function(t){return i({tag:"SegmentURL"},O(t))}),a=T(t,"SegmentBase")[0],u=r||e,o=u&&T(u,"SegmentTimeline")[0],s=r||a||e,c=s&&T(s,"Initialization")[0],d=e&&O(e);d&&c?d.initialization=c&&O(c):d&&d.initialization&&(d.initialization={sourceURL:d.initialization});var l={template:d,timeline:o&&T(o,"S").map(function(t){return O(t)}),list:r&&i(O(r),{segmentUrls:n,initialization:O(c)}),base:a&&i(O(a),{initialization:O(c)})};return Object.keys(l).forEach(function(t){l[t]||delete l[t]}),l},B=function(t){return t.reduce(function(t,e){var r=O(e),n=x[r.schemeIdUri];if(n){t[n]={attributes:r};var i=T(e,"cenc:pssh")[0];if(i){var a=P(i),u=a&&function(t){for(var e=o.atob(t),r=new Uint8Array(e.length),n=0;n<e.length;n++)r[n]=e.charCodeAt(n);return r}(a);t[n].pssh=u}}return t},{})},C=function(t,e,r){return function(n){var a=O(n),u=M(e,T(n,"BaseURL")),o=T(n,"Role")[0],s={role:O(o)},c=i(t,a,s),d=B(T(n,"ContentProtection"));Object.keys(d).length&&(c=i(c,{contentProtection:d}));var l=z(n),f=T(n,"Representation"),p=i(r,l);return m(f.map(function(t,e,r){return function(n){var a=T(n,"BaseURL"),u=M(e,a),o=i(t,O(n)),s=z(n);return u.map(function(t){return{segmentInfo:i(r,s),attributes:i(o,{baseUrl:t})}})}}(c,u,p)))}},F=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=e.manifestUri,n=void 0===r?"":r,a=e.NOW,u=void 0===a?Date.now():a,o=e.clientOffset,s=void 0===o?0:o,c=T(t,"Period");if(1!==c.length)throw new Error(U);var d=O(t),l=M([n],T(t,"BaseURL"));return d.sourceDuration=d.mediaPresentationDuration||0,d.NOW=u,d.clientOffset=s,m(c.map(function(t,e){return function(r,n){var a=M(e,T(r,"BaseURL")),u=O(r),o=i(t,u,{periodIndex:n}),s=T(r,"AdaptationSet"),c=z(r);return m(s.map(C(o,a,c)))}}(d,l)))},_=function(t){if(""===t)throw new Error(y);var e=(new o.DOMParser).parseFromString(t,"application/xml"),r=e&&"MPD"===e.documentElement.tagName?e.documentElement:null;if(!r||r&&r.getElementsByTagName("parsererror").length>0)throw new Error(I);return r};t.VERSION="0.6.1",t.parse=function(t,r){return function(t){var r;if(!t.length)return{};var n=t[0].attributes,i=n.sourceDuration,a=n.minimumUpdatePeriod,u=void 0===a?0:a,o=t.filter(function(t){var e=t.attributes;return"video/mp4"===e.mimeType||"video"===e.contentType}).map(e),s=t.filter(function(t){var e=t.attributes;return"audio/mp4"===e.mimeType||"audio"===e.contentType}),c=t.filter(function(t){var e=t.attributes;return"text/vtt"===e.mimeType||"text"===e.contentType}),d={allowCache:!0,discontinuityStarts:[],segments:[],endList:!0,mediaGroups:(r={AUDIO:{},VIDEO:{}},r["CLOSED-CAPTIONS"]={},r.SUBTITLES={},r),uri:"",duration:i,playlists:o,minimumUpdatePeriod:1e3*u};return s.length&&(d.mediaGroups.AUDIO.audio=function(t){return t.reduce(function(t,e){var r=e.attributes.role&&e.attributes.role.value||"main",n=e.attributes.lang||"",i="main";return n&&(i=e.attributes.lang+" ("+r+")"),t[i]&&t[i].playlists[0].attributes.BANDWIDTH>e.attributes.bandwidth?t:(t[i]={language:n,autoselect:!0,default:"main"===r,playlists:[function(t){var e,r=t.attributes,n=t.segments,i={attributes:(e={NAME:r.id,BANDWIDTH:r.bandwidth,CODECS:r.codecs},e["PROGRAM-ID"]=1,e),uri:"",endList:"static"===(r.type||"static"),timeline:r.periodIndex,resolvedUri:"",targetDuration:r.duration,segments:n,mediaSequence:n.length?n[0].number:1};return r.contentProtection&&(i.contentProtection=r.contentProtection),i}(e)],uri:""},t)},{})}(s)),c.length&&(d.mediaGroups.SUBTITLES.subs=function(t){return t.reduce(function(t,e){var r=e.attributes.lang||"text";return t[r]?t:(t[r]={language:r,default:!1,autoselect:!1,playlists:[function(t){var e,r=t.attributes,n=t.segments;return void 0===n&&(n=[{uri:r.baseUrl,timeline:r.periodIndex,resolvedUri:r.baseUrl||"",duration:r.sourceDuration,number:0}],r.duration=r.sourceDuration),{attributes:(e={NAME:r.id,BANDWIDTH:r.bandwidth},e["PROGRAM-ID"]=1,e),uri:"",endList:"static"===(r.type||"static"),timeline:r.periodIndex,resolvedUri:r.baseUrl||"",targetDuration:r.duration,segments:n,mediaSequence:n.length?n[0].number:1}}(e)],uri:""},t)},{})}(c)),d}(function(t){return t.map(S)}(F(_(t),r)))},t.parseUTCTiming=function(t){return function(t){var e=T(t,"UTCTiming")[0];if(!e)return null;var r=O(e);switch(r.schemeIdUri){case"urn:mpeg:dash:utc:http-head:2014":case"urn:mpeg:dash:utc:http-head:2012":r.method="HEAD";break;case"urn:mpeg:dash:utc:http-xsdate:2014":case"urn:mpeg:dash:utc:http-iso:2014":case"urn:mpeg:dash:utc:http-xsdate:2012":case"urn:mpeg:dash:utc:http-iso:2012":r.method="GET";break;case"urn:mpeg:dash:utc:direct:2014":case"urn:mpeg:dash:utc:direct:2012":r.method="DIRECT",r.value=Date.parse(r.value);break;case"urn:mpeg:dash:utc:http-ntp:2014":case"urn:mpeg:dash:utc:ntp:2014":case"urn:mpeg:dash:utc:sntp:2014":default:throw new Error(w)}return r}(_(t))}}); | ||
/*! @name mpd-parser @version 0.7.0 @license Apache-2.0 */ | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("global/window")):"function"==typeof define&&define.amd?define(["exports","global/window"],e):e(t.mpdParser={},t.window)}(this,function(t,e){"use strict";e=e&&e.hasOwnProperty("default")?e.default:e;var r=function(t){return!!t&&"object"==typeof t},n=function t(){for(var e=arguments.length,n=new Array(e),i=0;i<e;i++)n[i]=arguments[i];return n.reduce(function(e,n){return Object.keys(n).forEach(function(i){Array.isArray(e[i])&&Array.isArray(n[i])?e[i]=e[i].concat(n[i]):r(e[i])&&r(n[i])?e[i]=t(e[i],n[i]):e[i]=n[i]}),e},{})},i=function(t){return t.reduce(function(t,e){return t.concat(e)},[])},a=function(t){if(!t.length)return[];for(var e=[],r=0;r<t.length;r++)e.push(t[r]);return e},u=function(t){var e;return(e=t.reduce(function(t,e){var r,n=e.attributes.id+(e.attributes.lang||"");t[n]?(e.segments[0].discontinuity=!0,(r=t[n].segments).push.apply(r,e.segments),e.attributes.contentProtection&&(t[n].attributes.contentProtection=e.attributes.contentProtection)):t[n]=e;return t},{}),Object.keys(e).map(function(t){return e[t]})).map(function(t){var e,r;return t.discontinuityStarts=(e=t.segments,r="discontinuity",e.reduce(function(t,e,n){return e[r]&&t.push(n),t},[])),t})},o=function(t){var e,r=t.attributes,n=t.segments,i={attributes:(e={NAME:r.id,AUDIO:"audio",SUBTITLES:"subs",RESOLUTION:{width:r.width,height:r.height},CODECS:r.codecs,BANDWIDTH:r.bandwidth},e["PROGRAM-ID"]=1,e),uri:"",endList:"static"===(r.type||"static"),timeline:r.periodIndex,resolvedUri:"",targetDuration:r.duration,segments:n,mediaSequence:n.length?n[0].number:1};return r.contentProtection&&(i.contentProtection=r.contentProtection),i};"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;var s,c=(function(t,e){var r,n,i,a,u;r=/^((?:[a-zA-Z0-9+\-.]+:)?)(\/\/[^\/?#]*)?((?:[^\/\?#]*\/)*.*?)??(;.*?)?(\?.*?)?(#.*?)?$/,n=/^([^\/?#]*)(.*)$/,i=/(?:\/|^)\.(?=\/)/g,a=/(?:\/|^)\.\.\/(?!\.\.\/).*?(?=\/)/g,u={buildAbsoluteURL:function(t,e,r){if(r=r||{},t=t.trim(),!(e=e.trim())){if(!r.alwaysNormalize)return t;var i=u.parseURL(t);if(!i)throw new Error("Error trying to parse base URL.");return i.path=u.normalizePath(i.path),u.buildURLFromParts(i)}var a=u.parseURL(e);if(!a)throw new Error("Error trying to parse relative URL.");if(a.scheme)return r.alwaysNormalize?(a.path=u.normalizePath(a.path),u.buildURLFromParts(a)):e;var o=u.parseURL(t);if(!o)throw new Error("Error trying to parse base URL.");if(!o.netLoc&&o.path&&"/"!==o.path[0]){var s=n.exec(o.path);o.netLoc=s[1],o.path=s[2]}o.netLoc&&!o.path&&(o.path="/");var c={scheme:o.scheme,netLoc:a.netLoc,path:null,params:a.params,query:a.query,fragment:a.fragment};if(!a.netLoc&&(c.netLoc=o.netLoc,"/"!==a.path[0]))if(a.path){var d=o.path,l=d.substring(0,d.lastIndexOf("/")+1)+a.path;c.path=u.normalizePath(l)}else c.path=o.path,a.params||(c.params=o.params,a.query||(c.query=o.query));return null===c.path&&(c.path=r.alwaysNormalize?u.normalizePath(a.path):a.path),u.buildURLFromParts(c)},parseURL:function(t){var e=r.exec(t);return e?{scheme:e[1]||"",netLoc:e[2]||"",path:e[3]||"",params:e[4]||"",query:e[5]||"",fragment:e[6]||""}:null},normalizePath:function(t){for(t=t.split("").reverse().join("").replace(i,"");t.length!==(t=t.replace(a,"")).length;);return t.split("").reverse().join("")},buildURLFromParts:function(t){return t.scheme+t.netLoc+t.path+t.params+t.query+t.fragment}},t.exports=u}(s={exports:{}},s.exports),s.exports),d=function(t,r){return/^[a-z]+:/i.test(r)?r:(/\/\//i.test(t)||(t=c.buildAbsoluteURL(e.location.href,t)),c.buildAbsoluteURL(t,r))},l=function(t){var e=t.baseUrl,r=void 0===e?"":e,n=t.source,i=void 0===n?"":n,a=t.range,u=void 0===a?"":a,o={uri:i,resolvedUri:d(r||"",i)};if(u){var s=u.split("-"),c=parseInt(s[0],10),l=parseInt(s[1],10);o.byterange={length:l-c,offset:c}}return o},m=function(t,e,r){var n=t.NOW,i=t.clientOffset,a=t.availabilityStartTime,u=t.timescale,o=void 0===u?1:u,s=t.start,c=void 0===s?0:s,d=t.minimumUpdatePeriod,l=(n+i)/1e3+(void 0===d?0:d)-(a+c);return Math.ceil((l*o-e)/r)},f=function(t,e){for(var r=t.type,n=void 0===r?"static":r,i=t.minimumUpdatePeriod,a=void 0===i?0:i,u=t.media,o=void 0===u?"":u,s=t.sourceDuration,c=t.timescale,d=void 0===c?1:c,l=t.startNumber,f=void 0===l?1:l,p=t.periodIndex,h=[],v=-1,b=0;b<e.length;b++){var g=e[b],U=g.d,y=g.r||0,I=g.t||0;v<0&&(v=I),I&&I>v&&(v=I);var D=void 0;if(y<0){var w=b+1;D=w===e.length?"dynamic"===n&&a>0&&o.indexOf("$Number$")>0?m(t,v,U):(s*d-v)/U:(e[w].t-v)/U}else D=y+1;for(var L=f+h.length+D,E=f+h.length;E<L;)h.push({number:E,duration:U/d,time:v,timeline:p}),v+=U,E++}return h},p={static:function(t){var e=t.duration,r=t.timescale,n=void 0===r?1:r,i=t.sourceDuration;return{start:0,end:Math.ceil(i/(e/n))}},dynamic:function(t){var e=t.NOW,r=t.clientOffset,n=t.availabilityStartTime,i=t.timescale,a=void 0===i?1:i,u=t.duration,o=t.start,s=void 0===o?0:o,c=t.minimumUpdatePeriod,d=void 0===c?0:c,l=t.timeShiftBufferDepth,m=void 0===l?1/0:l,f=(e+r)/1e3,p=n+s,h=f+d-p,v=Math.ceil(h*a/u),b=Math.floor((f-p-m)*a/u),g=Math.floor((f-p)*a/u);return{start:Math.max(0,b),end:Math.min(v,g)}}},h=function(t){var e=t.type,r=void 0===e?"static":e,n=t.duration,i=t.timescale,a=void 0===i?1:i,u=t.sourceDuration,o=p[r](t),s=function(t,e){for(var r=[],n=t;n<e;n++)r.push(n);return r}(o.start,o.end).map(function(t){return function(e,r){var n=t.duration,i=t.timescale,a=void 0===i?1:i,u=t.periodIndex,o=t.startNumber;return{number:(void 0===o?1:o)+e,duration:n/a,timeline:u,time:r*n}}}(t));if("static"===r){var c=s.length-1;s[c].duration=u-n/a*c}return s},v=/\$([A-z]*)(?:(%0)([0-9]+)d)?\$/g,b=function(t,e){return t.replace(v,function(t){return function(e,r,n,i){if("$$"===e)return"$";if(void 0===t[r])return e;var a=""+t[r];return"RepresentationID"===r?a:(i=n?parseInt(i,10):1,a.length>=i?a:""+new Array(i-a.length+1).join("0")+a)}}(e))},g=function(t,e){var r={RepresentationID:t.id,Bandwidth:t.bandwidth||0},n=t.initialization,i=void 0===n?{sourceURL:"",range:""}:n,a=l({baseUrl:t.baseUrl,source:b(i.sourceURL,r),range:i.range});return function(t,e){return t.duration||e?t.duration?h(t):f(t,e):[{number:t.startNumber||1,duration:t.sourceDuration,time:0,timeline:t.periodIndex}]}(t,e).map(function(e){r.Number=e.number,r.Time=e.time;var n=b(t.media||"",r);return{uri:n,timeline:e.timeline,duration:e.duration,resolvedUri:d(t.baseUrl||"",n),map:a,number:e.number}})},U="INVALID_NUMBER_OF_PERIOD",y="DASH_EMPTY_MANIFEST",I="DASH_INVALID_XML",D="NO_BASE_URL",w="SEGMENT_TIME_UNSPECIFIED",L="UNSUPPORTED_UTC_TIMING_SCHEME",E=function(t,e){var r=t.duration,n=t.segmentUrls,i=void 0===n?[]:n;if(!r&&!e||r&&e)throw new Error(w);var a,u=i.map(function(e){return function(t,e){var r=t.baseUrl,n=t.initialization,i=void 0===n?{}:n,a=l({baseUrl:r,source:i.sourceURL,range:i.range}),u=l({baseUrl:r,source:e.media,range:e.mediaRange});return u.map=a,u}(t,e)});return r&&(a=h(t)),e&&(a=f(t,e)),a.map(function(t,e){if(u[e]){var r=u[e];return r.timeline=t.timeline,r.duration=t.duration,r.number=t.number,r}}).filter(function(t){return t})},P=function(t){var e=t.baseUrl,r=t.initialization,n=void 0===r?{}:r,i=t.sourceDuration,a=t.timescale,u=void 0===a?1:a,o=t.indexRange,s=void 0===o?"":o,c=t.duration;if(!e)throw new Error(D);var d=l({baseUrl:e,source:n.sourceURL,range:n.range}),m=l({baseUrl:e,source:e,range:s});if(m.map=d,c){var f=h(t);f.length&&(m.duration=f[0].duration,m.timeline=f[0].timeline)}else i&&(m.duration=i/u,m.timeline=0);return m.number=0,[m]},R=function(t){var e,r,i=t.attributes,a=t.segmentInfo;if(a.template?(r=g,e=n(i,a.template)):a.base?(r=P,e=n(i,a.base)):a.list&&(r=E,e=n(i,a.list)),!r)return{attributes:i};var u=r(e,a.timeline);if(e.duration){var o=e,s=o.duration,c=o.timescale,d=void 0===c?1:c;e.duration=s/d}else u.length?e.duration=u.reduce(function(t,e){return Math.max(t,Math.ceil(e.duration))},0):e.duration=0;return{attributes:e,segments:u}},T=function(t,e){return a(t.childNodes).filter(function(t){return t.tagName===e})},N=function(t){return t.textContent.trim()},S=function(t){var e=/P(?:(\d*)Y)?(?:(\d*)M)?(?:(\d*)D)?(?:T(?:(\d*)H)?(?:(\d*)M)?(?:([\d.]*)S)?)?/.exec(t);if(!e)return 0;var r=e.slice(1),n=r[0],i=r[1],a=r[2],u=r[3],o=r[4],s=r[5];return 31536e3*parseFloat(n||0)+2592e3*parseFloat(i||0)+86400*parseFloat(a||0)+3600*parseFloat(u||0)+60*parseFloat(o||0)+parseFloat(s||0)},A={mediaPresentationDuration:function(t){return S(t)},availabilityStartTime:function(t){return/^\d+-\d+-\d+T\d+:\d+:\d+(\.\d+)?$/.test(e=t)&&(e+="Z"),Date.parse(e)/1e3;var e},minimumUpdatePeriod:function(t){return S(t)},timeShiftBufferDepth:function(t){return S(t)},start:function(t){return S(t)},width:function(t){return parseInt(t,10)},height:function(t){return parseInt(t,10)},bandwidth:function(t){return parseInt(t,10)},startNumber:function(t){return parseInt(t,10)},timescale:function(t){return parseInt(t,10)},duration:function(t){var e=parseInt(t,10);return isNaN(e)?S(t):e},d:function(t){return parseInt(t,10)},t:function(t){return parseInt(t,10)},r:function(t){return parseInt(t,10)},DEFAULT:function(t){return t}},O=function(t){return t&&t.attributes?a(t.attributes).reduce(function(t,e){var r=A[e.name]||A.DEFAULT;return t[e.name]=r(e.value),t},{}):{}};var x={"urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b":"org.w3.clearkey","urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed":"com.widevine.alpha","urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95":"com.microsoft.playready","urn:uuid:f239e769-efa3-4850-9c16-a903c6932efb":"com.adobe.primetime"},M=function(t,e){return e.length?i(t.map(function(t){return e.map(function(e){return d(t,N(e))})})):t},z=function(t){var e=T(t,"SegmentTemplate")[0],r=T(t,"SegmentList")[0],i=r&&T(r,"SegmentURL").map(function(t){return n({tag:"SegmentURL"},O(t))}),a=T(t,"SegmentBase")[0],u=r||e,o=u&&T(u,"SegmentTimeline")[0],s=r||a||e,c=s&&T(s,"Initialization")[0],d=e&&O(e);d&&c?d.initialization=c&&O(c):d&&d.initialization&&(d.initialization={sourceURL:d.initialization});var l={template:d,timeline:o&&T(o,"S").map(function(t){return O(t)}),list:r&&n(O(r),{segmentUrls:i,initialization:O(c)}),base:a&&n(O(a),{initialization:O(c)})};return Object.keys(l).forEach(function(t){l[t]||delete l[t]}),l},B=function(t){return t.reduce(function(t,r){var n=O(r),i=x[n.schemeIdUri];if(i){t[i]={attributes:n};var a=T(r,"cenc:pssh")[0];if(a){var u=N(a),o=u&&function(t){for(var r=e.atob(t),n=new Uint8Array(r.length),i=0;i<r.length;i++)n[i]=r.charCodeAt(i);return n}(u);t[i].pssh=o}}return t},{})},C=function(t,e,r){return function(a){var u=O(a),o=M(e,T(a,"BaseURL")),s=T(a,"Role")[0],c={role:O(s)},d=n(t,u,c),l=B(T(a,"ContentProtection"));Object.keys(l).length&&(d=n(d,{contentProtection:l}));var m=z(a),f=T(a,"Representation"),p=n(r,m);return i(f.map(function(t,e,r){return function(i){var a=T(i,"BaseURL"),u=M(e,a),o=n(t,O(i)),s=z(i);return u.map(function(t){return{segmentInfo:n(r,s),attributes:n(o,{baseUrl:t})}})}}(d,o,p)))}},F=function(t,r){void 0===r&&(r={});var a=r,u=a.manifestUri,o=void 0===u?"":u,s=a.NOW,c=void 0===s?Date.now():s,d=a.clientOffset,l=void 0===d?0:d,m=T(t,"Period");if(!m.length)throw new Error(U);var f=O(t),p=M([o],T(t,"BaseURL"));return f.sourceDuration=f.mediaPresentationDuration||0,f.NOW=c,f.clientOffset=l,i(m.map(function(t,r){return function(a,u){var o=M(r,T(a,"BaseURL")),s=O(a),c=parseInt(s.id,10),d=e.isNaN(c)?u:c,l=n(t,{periodIndex:d}),m=T(a,"AdaptationSet"),f=z(a);return i(m.map(C(l,o,f)))}}(f,p)))},_=function(t){if(""===t)throw new Error(y);var r=(new e.DOMParser).parseFromString(t,"application/xml"),n=r&&"MPD"===r.documentElement.tagName?r.documentElement:null;if(!n||n&&n.getElementsByTagName("parsererror").length>0)throw new Error(I);return n};t.VERSION="0.7.0",t.parse=function(t,e){return function(t){var e;if(!t.length)return{};var r=t[0].attributes,n=r.sourceDuration,i=r.minimumUpdatePeriod,a=void 0===i?0:i,s=u(t.filter(function(t){var e=t.attributes;return"video/mp4"===e.mimeType||"video"===e.contentType})).map(o),c=u(t.filter(function(t){var e=t.attributes;return"audio/mp4"===e.mimeType||"audio"===e.contentType})),d=t.filter(function(t){var e=t.attributes;return"text/vtt"===e.mimeType||"text"===e.contentType}),l={allowCache:!0,discontinuityStarts:[],segments:[],endList:!0,mediaGroups:(e={AUDIO:{},VIDEO:{}},e["CLOSED-CAPTIONS"]={},e.SUBTITLES={},e),uri:"",duration:n,playlists:s,minimumUpdatePeriod:1e3*a};return c.length&&(l.mediaGroups.AUDIO.audio=c.reduce(function(t,e){var r=e.attributes.role&&e.attributes.role.value||"main",n=e.attributes.lang||"",i="main";return n&&(i=e.attributes.lang+" ("+r+")"),t[i]&&t[i].playlists[0].attributes.BANDWIDTH>e.attributes.bandwidth?t:(t[i]={language:n,autoselect:!0,default:"main"===r,playlists:[function(t){var e,r=t.attributes,n=t.segments,i={attributes:(e={NAME:r.id,BANDWIDTH:r.bandwidth,CODECS:r.codecs},e["PROGRAM-ID"]=1,e),uri:"",endList:"static"===(r.type||"static"),timeline:r.periodIndex,resolvedUri:"",targetDuration:r.duration,segments:n,mediaSequence:n.length?n[0].number:1};return r.contentProtection&&(i.contentProtection=r.contentProtection),i}(e)],uri:""},t)},{})),d.length&&(l.mediaGroups.SUBTITLES.subs=function(t){return t.reduce(function(t,e){var r,n,i,a,u=e.attributes.lang||"text";return t[u]?t:(t[u]={language:u,default:!1,autoselect:!1,playlists:[(r=e,i=r.attributes,a=r.segments,void 0===a&&(a=[{uri:i.baseUrl,timeline:i.periodIndex,resolvedUri:i.baseUrl||"",duration:i.sourceDuration,number:0}],i.duration=i.sourceDuration),{attributes:(n={NAME:i.id,BANDWIDTH:i.bandwidth},n["PROGRAM-ID"]=1,n),uri:"",endList:"static"===(i.type||"static"),timeline:i.periodIndex,resolvedUri:i.baseUrl||"",targetDuration:i.duration,segments:a,mediaSequence:a.length?a[0].number:1})],uri:""},t)},{})}(d)),l}(F(_(t),e).map(R))},t.parseUTCTiming=function(t){return function(t){var e=T(t,"UTCTiming")[0];if(!e)return null;var r=O(e);switch(r.schemeIdUri){case"urn:mpeg:dash:utc:http-head:2014":case"urn:mpeg:dash:utc:http-head:2012":r.method="HEAD";break;case"urn:mpeg:dash:utc:http-xsdate:2014":case"urn:mpeg:dash:utc:http-iso:2014":case"urn:mpeg:dash:utc:http-xsdate:2012":case"urn:mpeg:dash:utc:http-iso:2012":r.method="GET";break;case"urn:mpeg:dash:utc:direct:2014":case"urn:mpeg:dash:utc:direct:2012":r.method="DIRECT",r.value=Date.parse(r.value);break;case"urn:mpeg:dash:utc:http-ntp:2014":case"urn:mpeg:dash:utc:ntp:2014":case"urn:mpeg:dash:utc:sntp:2014":default:throw new Error(L)}return r}(_(t))},Object.defineProperty(t,"__esModule",{value:!0})}); |
116
package.json
{ | ||
"name": "mpd-parser", | ||
"version": "0.6.1", | ||
"version": "0.7.0", | ||
"description": "mpd parser", | ||
@@ -13,21 +13,26 @@ "main": "dist/mpd-parser.cjs.js", | ||
"prebuild": "npm run clean", | ||
"build": "rollup -c scripts/rollup.config.js", | ||
"clean": "rimraf dist", | ||
"postclean": "mkdirp dist", | ||
"docs": "run-p docs:*", | ||
"docs:api": "jsdoc src -r -d docs/api", | ||
"build": "npm-run-all -p build:*", | ||
"build:js": "rollup -c scripts/rollup.config.js", | ||
"clean": "shx rm -rf ./dist ./test/dist", | ||
"postclean": "shx mkdir -p ./dist ./test/dist", | ||
"docs": "npm-run-all docs:*", | ||
"docs:api": "jsdoc src -g plugins/markdown -r -d docs/api", | ||
"docs:toc": "doctoc README.md", | ||
"lint": "vjsstandard", | ||
"prestart": "npm run build", | ||
"start": "run-p start:server test:server watch:js", | ||
"start:server": "static -a 0.0.0.0 -p 9999 -H '{\"Cache-Control\": \"no-cache, must-revalidate\"}' .", | ||
"pretest": "npm run lint", | ||
"test": "karma start test/karma.conf.js", | ||
"test:server": "karma start test/karma.conf.js --singleRun=false --auto-watch --no-browsers", | ||
"watch:js": "rollup -c scripts/rollup.config.js -w", | ||
"server": "karma start scripts/karma.conf.js --singleRun=false --auto-watch", | ||
"start": "npm-run-all -p server watch", | ||
"pretest": "npm-run-all lint build", | ||
"test": "karma start scripts/karma.conf.js", | ||
"update-changelog": "conventional-changelog -p videojs -i CHANGELOG.md -s", | ||
"preversion": "npm test", | ||
"version": "node scripts/version.js", | ||
"prepublish": "in-publish && npm run build || not-in-publish" | ||
"version": "is-prerelease || npm run update-changelog && git add CHANGELOG.md", | ||
"watch": "npm-run-all -p watch:*", | ||
"watch:js": "npm run build:js -- -w", | ||
"posttest": "shx cat test/dist/coverage/text.txt", | ||
"prepublishOnly": "npm run build && vjsverify" | ||
}, | ||
"keywords": [], | ||
"keywords": [ | ||
"videojs", | ||
"videojs-plugin" | ||
], | ||
"author": "Brightcove, Inc", | ||
@@ -39,4 +44,3 @@ "license": "Apache-2.0", | ||
"docs", | ||
"scripts", | ||
"test/karma.conf.js" | ||
"test/dist" | ||
] | ||
@@ -50,48 +54,52 @@ }, | ||
"scripts/", | ||
"src/" | ||
"src/", | ||
"test/" | ||
], | ||
"devDependencies": { | ||
"babel-eslint": "^8.2.1", | ||
"babel-plugin-external-helpers": "^6.22.0", | ||
"babel-plugin-transform-object-assign": "^6.8.0", | ||
"babel-preset-es2015": "^6.14.0", | ||
"babel-preset-es3": "^1.0.1", | ||
"chg": "^0.3.2", | ||
"conventional-changelog-cli": "^1.3.1", | ||
"conventional-changelog-cli": "^2.0.1", | ||
"conventional-changelog-videojs": "^3.0.0", | ||
"doctoc": "^0.15.0", | ||
"in-publish": "^2.0.0", | ||
"jsdoc": "^3.4.0", | ||
"karma": "^1.7.0", | ||
"karma-chrome-launcher": "^2.2.0", | ||
"karma-coverage": "^1.1.1", | ||
"karma-qunit": "^1.2.1", | ||
"karma-rollup-preprocessor": "^5.0.2", | ||
"mkdirp": "^0.5.1", | ||
"node-static": "^0.7.9", | ||
"npm-run-all": "^4.0.2", | ||
"qunitjs": "^2.4.1", | ||
"rimraf": "^2.6.1", | ||
"rollup": "^0.51.8", | ||
"rollup-plugin-babel": "^2.7.1", | ||
"rollup-plugin-commonjs": "^8.0.2", | ||
"rollup-plugin-istanbul": "^2.0.1", | ||
"rollup-plugin-json": "^2.1.1", | ||
"rollup-plugin-multi-entry": "^2.0.2", | ||
"rollup-plugin-node-resolve": "^3.0.0", | ||
"doctoc": "^1.3.1", | ||
"husky": "^1.0.0-rc.13", | ||
"jsdoc": "https://github.com/BrandonOCasey/jsdoc#feat/plugin-from-cli", | ||
"karma": "^3.0.0", | ||
"lint-staged": "^7.2.2", | ||
"not-prerelease": "^1.0.1", | ||
"npm-run-all": "^4.1.3", | ||
"rollup": "^0.66.0", | ||
"rollup-plugin-string": "^2.0.2", | ||
"rollup-plugin-uglify": "^2.0.1", | ||
"rollup-watch": "^3.2.2", | ||
"semver": "^5.3.0", | ||
"sinon": "^4.1.2", | ||
"uglify-es": "^3.2.1", | ||
"videojs-standard": "^6.0.0" | ||
"shx": "^0.3.2", | ||
"sinon": "^6.1.5", | ||
"videojs-generate-karma-config": "~3.0.0", | ||
"videojs-generate-rollup-config": "~2.2.0", | ||
"videojs-standard": "~7.1.0", | ||
"pkg-ok": "^2.2.0", | ||
"npm-merge-driver-install": "^1.0.0", | ||
"videojs-generator-verify": "~1.0.4" | ||
}, | ||
"generator-videojs-plugin": { | ||
"version": "5.0.0" | ||
"version": "7.3.2" | ||
}, | ||
"dependencies": { | ||
"global": "^4.3.0", | ||
"global": "^4.3.2", | ||
"url-toolkit": "^2.1.1" | ||
}, | ||
"browserslist": [ | ||
"defaults", | ||
"ie 11" | ||
], | ||
"lint-staged": { | ||
"*.js": [ | ||
"vjsstandard --fix", | ||
"git add" | ||
], | ||
"README.md": [ | ||
"npm run docs:toc", | ||
"git add" | ||
] | ||
}, | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "lint-staged" | ||
} | ||
} | ||
} |
# mpd-parser | ||
[![Build Status](https://travis-ci.org/videojs/mpd-parser.svg?branch=master)](https://travis-ci.org/videojs/mpd-parser) | ||
[![Greenkeeper badge](https://badges.greenkeeper.io/videojs/mpd-parser.svg)](https://greenkeeper.io/) | ||
[![Slack Status](http://slack.videojs.com/badge.svg)](http://slack.videojs.com) | ||
[![NPM](https://nodei.co/npm/mpd-parser.png?downloads=true&downloadRank=true)](https://nodei.co/npm/mpd-parser/) | ||
mpd parser | ||
@@ -4,0 +10,0 @@ |
@@ -1,87 +0,24 @@ | ||
import babel from 'rollup-plugin-babel'; | ||
import commonjs from 'rollup-plugin-commonjs'; | ||
import json from 'rollup-plugin-json'; | ||
import resolve from 'rollup-plugin-node-resolve'; | ||
import uglify from 'rollup-plugin-uglify'; | ||
import { minify } from 'uglify-es'; | ||
import pkg from '../package.json'; | ||
const generate = require('videojs-generate-rollup-config'); | ||
const string = require('rollup-plugin-string'); | ||
const date = new Date(); | ||
// see https://github.com/videojs/videojs-generate-rollup-config | ||
// for options | ||
const options = { | ||
input: 'src/index.js', | ||
plugins(defaults) { | ||
defaults.test.unshift('string'); | ||
const banner = | ||
`/** | ||
* ${pkg.name} | ||
* @version ${pkg.version} | ||
* @copyright ${date.getFullYear()} ${pkg.author} | ||
* @license ${pkg.license} | ||
*/`; | ||
return defaults; | ||
}, | ||
primedPlugins(defaults) { | ||
defaults.string = string({include: ['test/manifests/*.mpd']}); | ||
const plugins = [ | ||
resolve({ browser: true, main: true, jsnext: true }), | ||
json(), | ||
commonjs({ sourceMap: false }), | ||
babel() | ||
]; | ||
return defaults; | ||
} | ||
}; | ||
const config = generate(options); | ||
export default [ | ||
/** | ||
* Rollup configuration for packaging the plugin in a module that is consumable | ||
* as the `src` of a `script` tag or via AMD or similar client-side loading. | ||
* | ||
* This module DOES include its dependencies. | ||
*/ | ||
{ | ||
name: 'mpdParser', | ||
input: 'src/index.js', | ||
output: { | ||
file: 'dist/mpd-parser.js', | ||
format: 'umd' | ||
}, | ||
legacy: true, | ||
banner, | ||
plugins | ||
}, { | ||
name: 'mpdParser', | ||
input: 'src/index.js', | ||
output: { | ||
file: 'dist/mpd-parser.min.js', | ||
format: 'umd' | ||
}, | ||
legacy: true, | ||
banner, | ||
plugins: plugins | ||
.concat([uglify({output: {comments: 'some'}}, minify)]) | ||
}, | ||
// Add additonal builds/customization here! | ||
/** | ||
* Rollup configuration for packaging the plugin in a module that is consumable | ||
* by either CommonJS (e.g. Node or Browserify) or ECMAScript (e.g. Rollup). | ||
* | ||
* These modules DO NOT include their dependencies as we expect those to be | ||
* handled by the module system. | ||
*/ | ||
{ | ||
name: 'mpdParser', | ||
input: 'src/index.js', | ||
legacy: true, | ||
banner, | ||
external: ['global/window', 'url-toolkit'], | ||
plugins: [ json(), babel({exclude: 'node_modules/**'}) ], | ||
output: [ | ||
{file: 'dist/mpd-parser.cjs.js', format: 'cjs'} | ||
] | ||
}, { | ||
name: 'mpdParser', | ||
input: 'src/index.js', | ||
legacy: true, | ||
banner, | ||
external: ['global/window', 'url-toolkit'], | ||
plugins: [ | ||
json({ preferConst: true }), | ||
babel({ exclude: 'node_modules/**' }) | ||
], | ||
output: [ | ||
{file: 'dist/mpd-parser.es.js', format: 'es'} | ||
] | ||
} | ||
]; | ||
// export the builds to rollup | ||
export default Object.values(config.builds); |
@@ -0,1 +1,2 @@ | ||
import window from 'global/window'; | ||
import { flatten } from './utils/list'; | ||
@@ -151,15 +152,15 @@ import { merge } from './utils/object'; | ||
(adaptationSetAttributes, adaptationSetBaseUrls, adaptationSetSegmentInfo) => | ||
(representation) => { | ||
const repBaseUrlElements = findChildren(representation, 'BaseURL'); | ||
const repBaseUrls = buildBaseUrls(adaptationSetBaseUrls, repBaseUrlElements); | ||
const attributes = merge(adaptationSetAttributes, parseAttributes(representation)); | ||
const representationSegmentInfo = getSegmentInformation(representation); | ||
(representation) => { | ||
const repBaseUrlElements = findChildren(representation, 'BaseURL'); | ||
const repBaseUrls = buildBaseUrls(adaptationSetBaseUrls, repBaseUrlElements); | ||
const attributes = merge(adaptationSetAttributes, parseAttributes(representation)); | ||
const representationSegmentInfo = getSegmentInformation(representation); | ||
return repBaseUrls.map(baseUrl => { | ||
return { | ||
segmentInfo: merge(adaptationSetSegmentInfo, representationSegmentInfo), | ||
attributes: merge(attributes, { baseUrl }) | ||
}; | ||
}); | ||
}; | ||
return repBaseUrls.map(baseUrl => { | ||
return { | ||
segmentInfo: merge(adaptationSetSegmentInfo, representationSegmentInfo), | ||
attributes: merge(attributes, { baseUrl }) | ||
}; | ||
}); | ||
}; | ||
@@ -225,3 +226,3 @@ /** | ||
const adaptationSetBaseUrls = buildBaseUrls(periodBaseUrls, | ||
findChildren(adaptationSet, 'BaseURL')); | ||
findChildren(adaptationSet, 'BaseURL')); | ||
const role = findChildren(adaptationSet, 'Role')[0]; | ||
@@ -231,4 +232,4 @@ const roleAttributes = { role: parseAttributes(role) }; | ||
let attrs = merge(periodAttributes, | ||
adaptationSetAttributes, | ||
roleAttributes); | ||
adaptationSetAttributes, | ||
roleAttributes); | ||
@@ -275,6 +276,9 @@ const contentProtection = generateKeySystemInformation( | ||
*/ | ||
export const toAdaptationSets = (mpdAttributes, mpdBaseUrls) => (period, periodIndex) => { | ||
export const toAdaptationSets = (mpdAttributes, mpdBaseUrls) => (period, index) => { | ||
const periodBaseUrls = buildBaseUrls(mpdBaseUrls, findChildren(period, 'BaseURL')); | ||
const periodAtt = parseAttributes(period); | ||
const periodAttributes = merge(mpdAttributes, periodAtt, { periodIndex }); | ||
const parsedPeriodId = parseInt(periodAtt.id, 10); | ||
// fallback to mapping index if Period@id is not a number | ||
const periodIndex = window.isNaN(parsedPeriodId) ? index : parsedPeriodId; | ||
const periodAttributes = merge(mpdAttributes, { periodIndex }); | ||
const adaptationSets = findChildren(period, 'AdaptationSet'); | ||
@@ -312,4 +316,3 @@ const periodSegmentInfo = getSegmentInformation(period); | ||
if (periods.length !== 1) { | ||
// TODO add support for multiperiod | ||
if (!periods.length) { | ||
throw new Error(errors.INVALID_NUMBER_OF_PERIOD); | ||
@@ -316,0 +319,0 @@ } |
@@ -12,3 +12,3 @@ import window from 'global/window'; | ||
const mpd = xml && xml.documentElement.tagName === 'MPD' ? | ||
xml.documentElement : null; | ||
xml.documentElement : null; | ||
@@ -15,0 +15,0 @@ if (!mpd || mpd && |
@@ -0,1 +1,39 @@ | ||
import { values } from './utils/object'; | ||
import { findIndexes } from './utils/list'; | ||
const mergeDiscontiguousPlaylists = playlists => { | ||
const mergedPlaylists = values(playlists.reduce((acc, playlist) => { | ||
// assuming playlist IDs are the same across periods | ||
// TODO: handle multiperiod where representation sets are not the same | ||
// across periods | ||
const name = playlist.attributes.id + (playlist.attributes.lang || ''); | ||
// Periods after first | ||
if (acc[name]) { | ||
// first segment of subsequent periods signal a discontinuity | ||
playlist.segments[0].discontinuity = true; | ||
acc[name].segments.push(...playlist.segments); | ||
// bubble up contentProtection, this assumes all DRM content | ||
// has the same contentProtection | ||
if (playlist.attributes.contentProtection) { | ||
acc[name].attributes.contentProtection = | ||
playlist.attributes.contentProtection; | ||
} | ||
} else { | ||
// first Period | ||
acc[name] = playlist; | ||
} | ||
return acc; | ||
}, {})); | ||
return mergedPlaylists.map(playlist => { | ||
playlist.discontinuityStarts = | ||
findIndexes(playlist.segments, 'discontinuity'); | ||
return playlist; | ||
}); | ||
}; | ||
export const formatAudioPlaylist = ({ attributes, segments }) => { | ||
@@ -154,4 +192,6 @@ const playlist = { | ||
const videoPlaylists = dashPlaylists.filter(videoOnly).map(formatVideoPlaylist); | ||
const audioPlaylists = dashPlaylists.filter(audioOnly); | ||
const videoPlaylists = mergeDiscontiguousPlaylists( | ||
dashPlaylists.filter(videoOnly) | ||
).map(formatVideoPlaylist); | ||
const audioPlaylists = mergeDiscontiguousPlaylists(dashPlaylists.filter(audioOnly)); | ||
const vttPlaylists = dashPlaylists.filter(vttOnly); | ||
@@ -158,0 +198,0 @@ |
@@ -26,1 +26,9 @@ export const range = (start, end) => { | ||
}; | ||
export const findIndexes = (l, key) => l.reduce((a, e, i) => { | ||
if (e[key]) { | ||
a.push(i); | ||
} | ||
return a; | ||
}, []); |
@@ -22,1 +22,3 @@ const isObject = (obj) => { | ||
}; | ||
export const values = o => Object.keys(o).map(k => o[k]); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
942776
19
53
31644
165
3
Updatedglobal@^4.3.2