UNPKG

rx-player

Version:
183 lines (174 loc) 5.41 kB
/** * 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. */ import idGenerator from "../../../utils/id_generator"; import getMonotonicTimeStamp from "../../../utils/monotonic_timestamp"; import type { IContentProtections, IContentProtectionInitData, IParsedAdaptation, IParsedManifest, IParsedPeriod, IParsedRepresentation, } from "../types"; import LocalRepresentationIndex from "./representation_index"; import type { IContentProtections as ILocalContentProtections, ILocalAdaptation, ILocalManifest, ILocalPeriod, ILocalRepresentation, } from "./types"; /** * @param {Object} localManifest * @returns {Object} */ export default function parseLocalManifest( localManifest: ILocalManifest, ): IParsedManifest { if (localManifest.type !== "local") { throw new Error("Invalid local manifest given. It misses the `type` property."); } if (localManifest.version !== "0.2") { throw new Error( `The current Local Manifest version (${localManifest.version})` + " is not compatible with the current version of the RxPlayer", ); } const periodIdGenerator = idGenerator(); const { minimumPosition, maximumPosition, isFinished } = localManifest; const parsedPeriods = localManifest.periods.map((period) => parsePeriod(period, { periodIdGenerator }), ); return { availabilityStartTime: 0, expired: localManifest.expired, transportType: "local", isDynamic: !isFinished, isLastPeriodKnown: true, isLive: false, uris: [], timeBounds: { minimumSafePosition: minimumPosition ?? 0, timeshiftDepth: null, maximumTimeData: { isLinear: false, maximumSafePosition: maximumPosition, livePosition: undefined, time: getMonotonicTimeStamp(), }, }, periods: parsedPeriods, }; } /** * @param {Object} period * @param {Object} ctxt * @returns {Object} */ function parsePeriod( period: ILocalPeriod, ctxt: { periodIdGenerator: () => string /* Generate next Period's id */ }, ): IParsedPeriod { const adaptationIdGenerator = idGenerator(); return { id: "period-" + ctxt.periodIdGenerator(), start: period.start, end: period.end, duration: period.end - period.start, thumbnailTracks: [], adaptations: period.adaptations.reduce<Partial<Record<string, IParsedAdaptation[]>>>( (acc, ada) => { const type = ada.type; let adaps = acc[type]; if (adaps === undefined) { adaps = []; acc[type] = adaps; } adaps.push(parseAdaptation(ada, { adaptationIdGenerator })); return acc; }, {}, ), }; } /** * @param {Object} adaptation * @param {Object} ctxt * @returns {Object} */ function parseAdaptation( adaptation: ILocalAdaptation, ctxt: { adaptationIdGenerator: () => string /* Generate next Adaptation's id */; }, ): IParsedAdaptation { const representationIdGenerator = idGenerator(); return { id: "adaptation-" + ctxt.adaptationIdGenerator(), type: adaptation.type, audioDescription: adaptation.audioDescription, closedCaption: adaptation.closedCaption, forcedSubtitles: adaptation.forcedSubtitles, language: adaptation.language, representations: adaptation.representations.map((representation) => parseRepresentation(representation, { representationIdGenerator }), ), }; } /** * @param {Object} representation * @returns {Object} */ function parseRepresentation( representation: ILocalRepresentation, ctxt: { representationIdGenerator: () => string }, ): IParsedRepresentation { const id = "representation-" + ctxt.representationIdGenerator(); const contentProtections = representation.contentProtections === undefined ? undefined : formatContentProtections(representation.contentProtections); return { id, cdnMetadata: null, bitrate: representation.bitrate, height: representation.height, width: representation.width, codecs: representation.codecs, isSpatialAudio: representation.isSpatialAudio, mimeType: representation.mimeType, index: new LocalRepresentationIndex(representation.index, id), contentProtections, }; } /** * Translate Local Manifest's `contentProtections` attribute to the one defined * for a `Manifest` structure. * @param {Object} localContentProtections * @returns {Object} */ function formatContentProtections( localContentProtections: ILocalContentProtections, ): IContentProtections { const keyIds = localContentProtections.keyIds.map((k) => k.keyId); const initData: IContentProtectionInitData[] = Object.keys( localContentProtections.initData, ).map((currType) => { const localInitData = localContentProtections.initData[currType] ?? []; return { type: currType, values: localInitData }; }); return { keyIds, initData }; }