UNPKG

rx-player

Version:
113 lines (112 loc) 5.45 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 config from "../../../config"; import arrayIncludes from "../../../utils/array_includes"; import { excludeFromRanges, insertInto } from "../../../utils/ranges"; import { getFirstSegmentAfterPeriod, getLastSegmentBeforePeriod, SegmentSinkOperation, } from "../../segment_sinks"; export default function getRepresentationsSwitchingStrategy(period, adaptation, settings, segmentSink, playbackObserver) { var _a, _b, _c, _d; if (settings.switchingMode === "lazy") { return { type: "continue", value: undefined }; } const inventory = segmentSink.getLastKnownInventory(); const unwantedRange = []; for (const elt of inventory) { if (elt.infos.period.id === period.id && (elt.infos.adaptation.id !== adaptation.id || !arrayIncludes(settings.representationIds, elt.infos.representation.id))) { insertInto(unwantedRange, { start: (_a = elt.bufferedStart) !== null && _a !== void 0 ? _a : elt.start, end: (_b = elt.bufferedEnd) !== null && _b !== void 0 ? _b : elt.end, }); } } const pendingOperations = segmentSink.getPendingOperations(); for (const operation of pendingOperations) { if (operation.type === SegmentSinkOperation.Push) { const info = operation.value.inventoryInfos; if (info.period.id === period.id && (info.adaptation.id !== adaptation.id || !arrayIncludes(settings.representationIds, info.representation.id))) { const start = info.segment.time; const end = start + info.segment.duration; insertInto(unwantedRange, { start, end }); } } } // Continue if we have no other Adaptation buffered in the current Period if (unwantedRange.length === 0) { return { type: "continue", value: undefined }; } if (settings.switchingMode === "reload") { const readyState = playbackObserver.getReadyState(); if (readyState === undefined || readyState > 1) { return { type: "needs-reload", value: undefined }; } } // From here, clean-up data from the previous Adaptation, if one const shouldFlush = settings.switchingMode === "direct"; const rangesToExclude = []; // First, we don't want to accidentally remove some segments from the previous // Period (which overlap a little with this one) /** Last segment before one for the current period. */ const lastSegmentBefore = getLastSegmentBeforePeriod(inventory, period); if (lastSegmentBefore !== null && (lastSegmentBefore.bufferedEnd === undefined || period.start - lastSegmentBefore.bufferedEnd < 1)) { // Close to Period's start // Exclude data close to the period's start to avoid cleaning // to much rangesToExclude.push({ start: 0, end: period.start + 1 }); } if (!shouldFlush) { // exclude data around current position to avoid decoding issues const { ADAP_REP_SWITCH_BUFFER_PADDINGS } = config.getCurrent(); const bufferType = adaptation.type; /** Ranges that won't be cleaned from the current buffer. */ const paddingBefore = (_c = ADAP_REP_SWITCH_BUFFER_PADDINGS[bufferType].before) !== null && _c !== void 0 ? _c : 0; const paddingAfter = (_d = ADAP_REP_SWITCH_BUFFER_PADDINGS[bufferType].after) !== null && _d !== void 0 ? _d : 0; let currentTime = playbackObserver.getCurrentTime(); if (currentTime === undefined) { // TODO current position might be old. A better solution should be found. const lastObservation = playbackObserver.getReference().getValue(); currentTime = lastObservation.position.getPolled(); } rangesToExclude.push({ start: currentTime - paddingBefore, end: currentTime + paddingAfter, }); } // Now remove possible small range from the end if there is a segment from the // next Period if (period.end !== undefined) { /** first segment after for the current period. */ const firstSegmentAfter = getFirstSegmentAfterPeriod(inventory, period); if (firstSegmentAfter !== null && (firstSegmentAfter.bufferedStart === undefined || // Close to Period's end firstSegmentAfter.bufferedStart - period.end < 1)) { rangesToExclude.push({ start: period.end - 1, end: Number.MAX_VALUE }); } } const toRemove = excludeFromRanges(unwantedRange, rangesToExclude); if (toRemove.length === 0) { return { type: "continue", value: undefined }; } return shouldFlush ? { type: "flush-buffer", value: toRemove } : { type: "clean-buffer", value: toRemove }; }