rx-player
Version:
Canal+ HTML5 Video Player
261 lines (260 loc) • 11.7 kB
JavaScript
"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 __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
Object.defineProperty(exports, "__esModule", { value: true });
var log_1 = require("../../log");
var array_find_1 = require("../../utils/array_find");
var is_null_or_undefined_1 = require("../../utils/is_null_or_undefined");
var languages_1 = require("../../utils/languages");
var representation_1 = require("./representation");
/**
* Normalized Adaptation structure.
* An `Adaptation` describes a single `Track`. For example a specific audio
* track (in a given language) or a specific video track.
* It istelf can be represented in different qualities, which we call here
* `Representation`.
* @class Adaptation
*/
var Adaptation = /** @class */ (function () {
/**
* @constructor
* @param {Object} parsedAdaptation
* @param {Object|undefined} [options]
*/
function Adaptation(parsedAdaptation, cachedCodecSupport, options) {
if (options === void 0) { options = {}; }
var trickModeTracks = parsedAdaptation.trickModeTracks;
var representationFilter = options.representationFilter, isManuallyAdded = options.isManuallyAdded;
this.id = parsedAdaptation.id;
this.type = parsedAdaptation.type;
if (parsedAdaptation.isTrickModeTrack !== undefined) {
this.isTrickModeTrack = parsedAdaptation.isTrickModeTrack;
}
if (parsedAdaptation.language !== undefined) {
this.language = parsedAdaptation.language;
this.normalizedLanguage = (0, languages_1.default)(parsedAdaptation.language);
}
if (parsedAdaptation.closedCaption !== undefined) {
this.isClosedCaption = parsedAdaptation.closedCaption;
}
if (parsedAdaptation.audioDescription !== undefined) {
this.isAudioDescription = parsedAdaptation.audioDescription;
}
if (parsedAdaptation.isDub !== undefined) {
this.isDub = parsedAdaptation.isDub;
}
if (parsedAdaptation.forcedSubtitles !== undefined) {
this.isForcedSubtitles = parsedAdaptation.forcedSubtitles;
}
if (parsedAdaptation.isSignInterpreted !== undefined) {
this.isSignInterpreted = parsedAdaptation.isSignInterpreted;
}
if (parsedAdaptation.label !== undefined) {
this.label = parsedAdaptation.label;
}
if (trickModeTracks !== undefined && trickModeTracks.length > 0) {
this.trickModeTracks = trickModeTracks.map(function (track) { return new Adaptation(track, cachedCodecSupport); });
}
var argsRepresentations = parsedAdaptation.representations;
var representations = [];
this.supportStatus = {
hasSupportedCodec: false,
hasCodecWithUndefinedSupport: false,
isDecipherable: false,
};
for (var i = 0; i < argsRepresentations.length; i++) {
var representation = new representation_1.default(argsRepresentations[i], this.type, cachedCodecSupport);
var shouldAdd = true;
if (!(0, is_null_or_undefined_1.default)(representationFilter)) {
var reprObject = {
id: representation.id,
bitrate: representation.bitrate,
codecs: representation.codecs,
height: representation.height,
width: representation.width,
frameRate: representation.frameRate,
hdrInfo: representation.hdrInfo,
};
if (representation.contentProtections !== undefined) {
reprObject.contentProtections = {};
if (representation.contentProtections.keyIds !== undefined) {
var keyIds = representation.contentProtections.keyIds;
reprObject.contentProtections.keyIds = keyIds;
}
}
shouldAdd = representationFilter(reprObject, {
trackType: this.type,
language: this.language,
normalizedLanguage: this.normalizedLanguage,
isClosedCaption: this.isClosedCaption,
isDub: this.isDub,
isAudioDescription: this.isAudioDescription,
isSignInterpreted: this.isSignInterpreted,
});
}
if (shouldAdd) {
representations.push(representation);
if (representation.isSupported === undefined) {
this.supportStatus.hasCodecWithUndefinedSupport = true;
if (this.supportStatus.hasSupportedCodec === false) {
this.supportStatus.hasSupportedCodec = undefined;
}
}
else if (representation.isSupported) {
this.supportStatus.hasSupportedCodec = true;
}
if (representation.decipherable === undefined) {
if (this.supportStatus.isDecipherable === false) {
this.supportStatus.isDecipherable = undefined;
}
}
else if (representation.decipherable) {
this.supportStatus.isDecipherable = true;
}
}
else {
log_1.default.debug("manifest", "Filtering Representation due to representationFilter", this.type, "Adaptation: ".concat(this.id), "Representation: ".concat(representation.id), "(".concat(representation.bitrate, ")"));
}
}
representations.sort(function (a, b) { return a.bitrate - b.bitrate; });
this.representations = representations;
// for manuallyAdded adaptations (not in the manifest)
this.manuallyAdded = isManuallyAdded === true;
}
/**
* Some environments (e.g. in a WebWorker) may not have the capability to know
* if a mimetype+codec combination is supported on the current platform.
*
* Calling `refreshCodecSupport` manually once the codecs supported are known
* by the current environnement allows to work-around this issue.
*
*
* If the right mimetype+codec combination is found in the provided object,
* this `Adaptation`'s `isSupported` property will be updated accordingly as
* well as all of its inner `Representation`'s `isSupported` attributes.
*
* @param {Array.<Object>} cachedCodecSupport
*/
Adaptation.prototype.refreshCodecSupport = function (cachedCodecSupport) {
var e_1, _a;
var hasCodecWithUndefinedSupport = false;
var hasSupportedRepresentation = false;
try {
for (var _b = __values(this.representations), _c = _b.next(); !_c.done; _c = _b.next()) {
var representation = _c.value;
representation.refreshCodecSupport(cachedCodecSupport);
if (representation.isSupported === undefined) {
hasCodecWithUndefinedSupport = true;
}
else if (representation.isSupported) {
hasSupportedRepresentation = true;
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_1) throw e_1.error; }
}
if (hasSupportedRepresentation) {
/* The adaptation is supported because at least one representation is supported */
this.supportStatus.hasSupportedCodec = true;
}
else if (hasCodecWithUndefinedSupport) {
/* The adaptation support is unknown because there is no representation explicitly
supported but there is codec with unknown support */
this.supportStatus.hasSupportedCodec = undefined;
}
else {
/* All codecs support are known and no codecs are supported, adaptation
is not supported */
this.supportStatus.hasSupportedCodec = false;
}
this.supportStatus.hasCodecWithUndefinedSupport = hasCodecWithUndefinedSupport;
};
/**
* Returns the Representation linked to the given ID.
* @param {number|string} wantedId
* @returns {Object|undefined}
*/
Adaptation.prototype.getRepresentation = function (wantedId) {
return (0, array_find_1.default)(this.representations, function (_a) {
var id = _a.id;
return wantedId === id;
});
};
/**
* Format the current `Adaptation`'s properties into a
* `IAdaptationMetadata` format which can better be communicated through
* another thread.
*
* Please bear in mind however that the returned object will not be updated
* when the current `Adaptation` instance is updated, it is only a
* snapshot at the current time.
*
* If you want to keep that data up-to-date with the current `Adaptation`
* instance, you will have to do it yourself.
*
* @returns {Object}
*/
Adaptation.prototype.getMetadataSnapshot = function () {
var e_2, _a;
var representations = [];
var baseRepresentations = this.representations;
try {
for (var baseRepresentations_1 = __values(baseRepresentations), baseRepresentations_1_1 = baseRepresentations_1.next(); !baseRepresentations_1_1.done; baseRepresentations_1_1 = baseRepresentations_1.next()) {
var representation = baseRepresentations_1_1.value;
representations.push(representation.getMetadataSnapshot());
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (baseRepresentations_1_1 && !baseRepresentations_1_1.done && (_a = baseRepresentations_1.return)) _a.call(baseRepresentations_1);
}
finally { if (e_2) throw e_2.error; }
}
return {
id: this.id,
type: this.type,
supportStatus: this.supportStatus,
language: this.language,
isForcedSubtitles: this.isForcedSubtitles,
isClosedCaption: this.isClosedCaption,
isAudioDescription: this.isAudioDescription,
isSignInterpreted: this.isSignInterpreted,
normalizedLanguage: this.normalizedLanguage,
representations: representations,
label: this.label,
isDub: this.isDub,
};
};
return Adaptation;
}());
exports.default = Adaptation;