rx-player
Version:
Canal+ HTML5 Video Player
155 lines (154 loc) • 5.3 kB
JavaScript
;
/**
* 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.calculateRepeat = calculateRepeat;
exports.getIndexSegmentEnd = getIndexSegmentEnd;
exports.toIndexTime = toIndexTime;
exports.fromIndexTime = fromIndexTime;
exports.getTimescaledRange = getTimescaledRange;
exports.checkDiscontinuity = checkDiscontinuity;
var is_null_or_undefined_1 = require("../../../utils/is_null_or_undefined");
/**
* Calculate the number of times a timeline element repeats based on the next
* element.
* @param {Object} element
* @param {Object|null|undefined} nextElement
* @param {number|undefined} maxPosition
* @returns {Number}
*/
function calculateRepeat(element, nextElement, maxPosition) {
var repeatCount = element.repeatCount;
if (repeatCount >= 0) {
return repeatCount;
}
// A negative value of the @r attribute of the S element indicates
// that the duration indicated in @d attribute repeats until the
// start of the next S element, the end of the Period or until the
// next MPD update.
var segmentEnd;
if (!(0, is_null_or_undefined_1.default)(nextElement)) {
segmentEnd = nextElement.start;
}
else if (maxPosition !== undefined) {
segmentEnd = maxPosition;
}
else {
segmentEnd = Number.MAX_VALUE;
}
return Math.ceil((segmentEnd - element.start) / element.duration) - 1;
}
/**
* Returns end of the segment given, in index time.
* @param {Object} segment
* @param {Object|null} [nextSegment]
* @param {number} maxPosition
* @returns {Number}
*/
function getIndexSegmentEnd(segment, nextSegment, maxPosition) {
var start = segment.start, duration = segment.duration;
if (duration <= 0) {
return start;
}
var repeat = calculateRepeat(segment, nextSegment, maxPosition);
return start + (repeat + 1) * duration;
}
/**
* Convert from `presentationTime`, the time of the segment at the moment it
* is decoded to `mediaTime`, the original time the segments point at.
* @param {number} time
* @param {Object} indexOptions
* @returns {number}
*/
function toIndexTime(time, indexOptions) {
var _a;
return time * indexOptions.timescale + ((_a = indexOptions.indexTimeOffset) !== null && _a !== void 0 ? _a : 0);
}
/**
* Convert from `mediaTime`, the original time the segments point at to
* `presentationTime`, the time of the segment at the moment it is decoded.
* @param {number} time
* @param {Object} indexOptions
* @returns {number}
*/
function fromIndexTime(time, indexOptions) {
var _a;
return (time - ((_a = indexOptions.indexTimeOffset) !== null && _a !== void 0 ? _a : 0)) / indexOptions.timescale;
}
/**
* @param {Number} start
* @param {Number} duration
* @param {Number} timescale
* @returns {Object} - Object with two properties:
* - up {Number}: timescaled timestamp of the beginning time
* - to {Number}: timescaled timestamp of the end time (start time + duration)
*/
function getTimescaledRange(start, duration, timescale) {
return [start * timescale, (start + duration) * timescale];
}
/**
* Get index of the last segment in the timeline starting before/at the given
* timescaled time.
* Returns -1 if the given time is lower than the start of the first available
* segment.
* @param {Object} timeline
* @param {Number} timeTScaled
* @returns {Number}
*/
function getIndexOfLastObjectBefore(timeline, timeTScaled) {
var low = 0;
var high = timeline.length;
while (low < high) {
var mid = (low + high) >>> 1; // Divide by two + floor
if (timeline[mid].start <= timeTScaled) {
low = mid + 1;
}
else {
high = mid;
}
}
return low - 1;
}
/**
* @param {Object} index
* @param {number} timeSec
* @param {number} [maxPosition]
* @returns {number|null}
*/
function checkDiscontinuity(index, timeSec, maxPosition) {
var timeline = index.timeline;
var scaledTime = toIndexTime(timeSec, index);
if (scaledTime < 0) {
return null;
}
var segmentIndex = getIndexOfLastObjectBefore(timeline, scaledTime);
if (segmentIndex < 0 || segmentIndex >= timeline.length - 1) {
return null;
}
var timelineItem = timeline[segmentIndex];
if (timelineItem.duration <= 0) {
return null;
}
var nextTimelineItem = timeline[segmentIndex + 1];
if (nextTimelineItem === undefined) {
return null;
}
var nextStart = nextTimelineItem.start;
var segmentEnd = getIndexSegmentEnd(timelineItem, nextTimelineItem, maxPosition);
return scaledTime >= segmentEnd && scaledTime < nextStart
? fromIndexTime(nextStart, index)
: null;
}