UNPKG

rx-player

Version:
346 lines (345 loc) 13.1 kB
"use strict"; /** * Copyright 2015 CANAL+ Group * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MPDError = void 0; exports.ValueParser = ValueParser; exports.parseBase64 = parseBase64; exports.parseBoolean = parseBoolean; exports.parseByteRange = parseByteRange; exports.parseDateTime = parseDateTime; exports.parseDuration = parseDuration; exports.parseIntOrBoolean = parseIntOrBoolean; exports.parseMaybeDividedNumber = parseMaybeDividedNumber; exports.parseMPDFloat = parseMPDFloat; exports.parseMPDInteger = parseMPDInteger; exports.parseScheme = parseScheme; // XML-Schema // <http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd> var log_1 = require("../../../../../log"); var base64_1 = require("../../../../../utils/base64"); var is_non_empty_string_1 = require("../../../../../utils/is_non_empty_string"); var iso8601Duration = /^P(([\d.]*)Y)?(([\d.]*)M)?(([\d.]*)D)?T?(([\d.]*)H)?(([\d.]*)M)?(([\d.]*)S)?/; var rangeRe = /([0-9]+)-([0-9]+)/; /** * Parse MPD boolean attributes. * * The returned value is a tuple of two elements where: * 1. the first value is the parsed boolean - or `null` if we could not parse * it * 2. the second value is a possible error encountered while parsing this * value - set to `null` if no error was encountered. * @param {string} val - The value to parse * @param {string} displayName - The name of the property. Used for error * formatting. * @returns {Array.<Boolean | Error | null>} */ function parseBoolean(val, displayName) { if (val === "true") { return [true, null]; } if (val === "false") { return [false, null]; } var error = new MPDError("`".concat(displayName, "` property is not a boolean value but \"").concat(val, "\"")); return [false, error]; } /** * Parse MPD integer attributes. * * The returned value is a tuple of two elements where: * 1. the first value is the parsed boolean - or `null` if we could not parse * it * 2. the second value is a possible error encountered while parsing this * value - set to `null` if no error was encountered. * @param {string} val - The value to parse * @param {string} displayName - The name of the property. Used for error * formatting. * @returns {Array.<number | Error | null>} */ function parseMPDInteger(val, displayName) { var toInt = parseInt(val, 10); if (isNaN(toInt)) { var error = new MPDError("`".concat(displayName, "` property is not an integer value but \"").concat(val, "\"")); return [null, error]; } return [toInt, null]; } /** * Parse MPD float attributes. * * The returned value is a tuple of two elements where: * 1. the first value is the parsed boolean - or `null` if we could not parse * it * 2. the second value is a possible error encountered while parsing this * value - set to `null` if no error was encountered. * @param {string} val - The value to parse * @param {string} displayName - The name of the property. Used for error * formatting. * @returns {Array.<number | Error | null>} */ function parseMPDFloat(val, displayName) { if (val === "INF") { return [Infinity, null]; } var toInt = parseFloat(val); if (isNaN(toInt)) { var error = new MPDError("`".concat(displayName, "` property is invalid: \"").concat(val, "\"")); return [null, error]; } return [toInt, null]; } /** * Parse MPD attributes which are either integer or boolean values. * * The returned value is a tuple of two elements where: * 1. the first value is the parsed value - or `null` if we could not parse * it * 2. the second value is a possible error encountered while parsing this * value - set to `null` if no error was encountered. * @param {string} val - The value to parse * @param {string} displayName - The name of the property. Used for error * formatting. * @returns {Array.<Boolean | number | Error | null>} */ function parseIntOrBoolean(val, displayName) { if (val === "true") { return [true, null]; } if (val === "false") { return [false, null]; } var toInt = parseInt(val, 10); if (isNaN(toInt)) { var error = new MPDError("`".concat(displayName, "` property is not a boolean nor an integer but \"").concat(val, "\"")); return [null, error]; } return [toInt, null]; } /** * Parse MPD date attributes. * * The returned value is a tuple of two elements where: * 1. the first value is the parsed value - or `null` if we could not parse * it * 2. the second value is a possible error encountered while parsing this * value - set to `null` if no error was encountered. * @param {string} val - The value to parse * @param {string} displayName - The name of the property. Used for error * formatting. * @returns {Array.<Date | null | Error>} */ function parseDateTime(val, displayName) { var parsed = Date.parse(val); if (isNaN(parsed)) { var error = new MPDError("`".concat(displayName, "` is in an invalid date format: \"").concat(val, "\"")); return [null, error]; } return [new Date(Date.parse(val)).getTime() / 1000, null]; } /** * Parse MPD ISO8601 duration attributes into seconds. * * The returned value is a tuple of two elements where: * 1. the first value is the parsed value - or `null` if we could not parse * it * 2. the second value is a possible error encountered while parsing this * value - set to `null` if no error was encountered. * @param {string} val - The value to parse * @param {string} displayName - The name of the property. Used for error * formatting. * @returns {Array.<number | Error | null>} */ function parseDuration(val, displayName) { if (!(0, is_non_empty_string_1.default)(val)) { var error = new MPDError("`".concat(displayName, "` property is empty")); return [0, error]; } var match = iso8601Duration.exec(val); if (match === null) { var error = new MPDError("`".concat(displayName, "` property has an unrecognized format \"").concat(val, "\"")); return [null, error]; } var duration = parseFloat((0, is_non_empty_string_1.default)(match[2]) ? match[2] : "0") * 365 * 24 * 60 * 60 + parseFloat((0, is_non_empty_string_1.default)(match[4]) ? match[4] : "0") * 30 * 24 * 60 * 60 + parseFloat((0, is_non_empty_string_1.default)(match[6]) ? match[6] : "0") * 24 * 60 * 60 + parseFloat((0, is_non_empty_string_1.default)(match[8]) ? match[8] : "0") * 60 * 60 + parseFloat((0, is_non_empty_string_1.default)(match[10]) ? match[10] : "0") * 60 + parseFloat((0, is_non_empty_string_1.default)(match[12]) ? match[12] : "0"); return [duration, null]; } /** * Parse MPD byterange attributes into arrays of two elements: the start and * the end. * * The returned value is a tuple of two elements where: * 1. the first value is the parsed value - or `null` if we could not parse * it * 2. the second value is a possible error encountered while parsing this * value - set to `null` if no error was encountered. * @param {string} val * @param {string} displayName * @returns {Array.<Array.<number> | Error | null>} */ function parseByteRange(val, displayName) { var match = rangeRe.exec(val); if (match === null) { var error = new MPDError("`".concat(displayName, "` property has an unrecognized format \"").concat(val, "\"")); return [null, error]; } else { return [[+match[1], +match[2]], null]; } } /** * Parse MPD base64 attribute into an Uint8Array. * the end. * * The returned value is a tuple of two elements where: * 1. the first value is the parsed value - or `null` if we could not parse * it * 2. the second value is a possible error encountered while parsing this * value - set to `null` if no error was encountered. * @param {string} val * @param {string} displayName * @returns {Uint8Array | Error | null>} */ function parseBase64(val, displayName) { try { return [(0, base64_1.base64ToBytes)(val), null]; } catch (_) { var error = new MPDError("`".concat(displayName, "` is not a valid base64 string: \"").concat(val, "\"")); return [null, error]; } } /** * Some values in the MPD can be expressed as divisions of integers (e.g. frame * rates). * This function tries to convert it to a floating point value. * @param {string} val * @param {string} displayName * @returns {Array.<number | Error | null>} */ function parseMaybeDividedNumber(val, displayName) { var matches = /^(\d+)\/(\d+)$/.exec(val); if (matches !== null) { // No need to check, we know both are numbers return [+matches[1] / +matches[2], null]; } return parseMPDFloat(val, displayName); } /** * @param {Element} root * @returns {Object} */ function parseScheme(root) { var schemeIdUri; var value; for (var i = 0; i < root.attributes.length; i++) { var attribute = root.attributes[i]; switch (attribute.name) { case "schemeIdUri": schemeIdUri = attribute.value; break; case "value": value = attribute.value; break; } } return { schemeIdUri: schemeIdUri, value: value }; } /** * Create a function to factorize the MPD parsing logic. * @param {Object} dest - The destination object which will contain the parsed * values. * @param {Array.<Error>} warnings - An array which will contain every parsing * error encountered. * @return {Function} */ function ValueParser(dest, warnings) { /** * Parse a single value and add it to the `dest` objects. * If an error arised while parsing, add it at the end of the `warnings` array. * @param {string} objKey - The key which will be added to the `dest` object. * @param {string} val - The value found in the MPD which we should parse. * @param {Function} parsingFn - The parsing function adapted for this value. * @param {string} displayName - The name of the key as it appears in the MPD. * This is used only in error formatting, */ return function (val, _a) { var asKey = _a.asKey, parser = _a.parser, dashName = _a.dashName; var _b = __read(parser(val, dashName), 2), parsingResult = _b[0], parsingError = _b[1]; if (parsingError !== null) { log_1.default.warn(parsingError.message); warnings.push(parsingError); } if (parsingResult !== null) { dest[asKey] = parsingResult; } }; } /** * Error arising when parsing the MPD. * @class MPDError * @extends Error */ var MPDError = /** @class */ (function (_super) { __extends(MPDError, _super); /** * @param {string} message */ function MPDError(message) { var _this = _super.call(this, message) || this; // @see https://stackoverflow.com/questions/41102060/typescript-extending-error-class Object.setPrototypeOf(_this, MPDError.prototype); _this.name = "MPDError"; return _this; } return MPDError; }(Error)); exports.MPDError = MPDError;