b068a6e6 by David LaPalomento

pull apart segmentsDuration

Break segmentsDuration up into more manageable parts.
1 parent 3e508892
......@@ -5,39 +5,17 @@
'use strict';
var DEFAULT_TARGET_DURATION = 10;
var duration, seekable, segmentsDuration;
var accumulateDuration, duration, seekable, segmentsDuration;
/**
* Calculate the media duration from the segments associated with a
* playlist. The duration of a subinterval of the available segments
* may be calculated by specifying a start and end index.
*
* @param playlist {object} a media playlist object
* @param startSequence {number} (optional) an inclusive lower
* boundary for the playlist. Defaults to 0.
* @param endSequence {number} (optional) an exclusive upper boundary
* for the playlist. Defaults to playlist length.
* @param strict {boolean} (optional) if true, the interval between
* the final segment and the subsequent segment will not be included
* in the result
* @return {number} the duration between the start index and end
* index.
*/
segmentsDuration = function(playlist, startSequence, endSequence, strict) {
var targetDuration, i, j, segment, endSegment, expiredSegmentCount, result = 0;
startSequence = startSequence || 0;
i = startSequence;
endSequence = endSequence !== undefined ? endSequence : (playlist.segments || []).length;
targetDuration = playlist.targetDuration || DEFAULT_TARGET_DURATION;
// estimate expired segment duration using the target duration
expiredSegmentCount = Math.max(playlist.mediaSequence - startSequence, 0);
result += expiredSegmentCount * targetDuration;
i += expiredSegmentCount;
accumulateDuration = function(playlist, startSequence, endSequence, strict) {
var
result = 0,
targetDuration = playlist.targetDuration || DEFAULT_TARGET_DURATION,
segment, endSegment,
i, j;
// accumulate the segment durations into the result
for (; i < endSequence; i++) {
for (i = startSequence; i < endSequence; i++) {
segment = playlist.segments[i - playlist.mediaSequence];
// when PTS values aren't available, use information from the playlist
......@@ -49,7 +27,7 @@
// find the last segment with PTS info and use that to calculate
// the interval duration
for(j = i; j < endSequence - 1; j++) {
for (j = i; j < endSequence - 1; j++) {
endSegment = playlist.segments[j - playlist.mediaSequence + 1];
if (endSegment.maxVideoPts === undefined ||
endSegment.discontinuity) {
......@@ -81,6 +59,42 @@
};
/**
* Calculate the media duration from the segments associated with a
* playlist. The duration of a subinterval of the available segments
* may be calculated by specifying a start and end index.
*
* @param playlist {object} a media playlist object
* @param startSequence {number} (optional) an inclusive lower
* boundary for the playlist. Defaults to 0.
* @param endSequence {number} (optional) an exclusive upper boundary
* for the playlist. Defaults to playlist length.
* @param strict {boolean} (optional) if true, the interval between
* the final segment and the subsequent segment will not be included
* in the result
* @return {number} the duration between the start index and end
* index.
*/
segmentsDuration = function(playlist, startSequence, endSequence, strict) {
var targetDuration, expiredSegmentCount, result = 0;
startSequence = startSequence || 0;
endSequence = endSequence !== undefined ? endSequence : (playlist.segments || []).length;
targetDuration = playlist.targetDuration || DEFAULT_TARGET_DURATION;
// estimate expired segment duration using the target duration
expiredSegmentCount = Math.max(playlist.mediaSequence - startSequence, 0);
result += expiredSegmentCount * targetDuration;
// accumulate the segment durations into the result
result += accumulateDuration(playlist,
startSequence + expiredSegmentCount,
endSequence,
strict);
return result;
};
/**
* Calculates the duration of a playlist. If a start and end index
* are specified, the duration will be for the subset of the media
* timeline between those two indices. The total duration for live
......
......@@ -3,7 +3,7 @@
'use strict';
var Playlist = videojs.Hls.Playlist;
module('Playlist Utilities');
module('Playlist Duration');
test('total duration for live playlists is Infinity', function() {
var duration = Playlist.duration({
......@@ -16,7 +16,9 @@
equal(duration, Infinity, 'duration is infinity');
});
test('interval duration accounts for media sequences', function() {
module('Playlist Interval Duration');
test('accounts for media sequences', function() {
var duration = Playlist.duration({
mediaSequence: 10,
endList: true,
......@@ -38,7 +40,7 @@
equal(duration, 14 * 10, 'duration includes dropped segments');
});
test('interval duration uses PTS values when available', function() {
test('uses PTS values when available', function() {
var duration = Playlist.duration({
mediaSequence: 0,
endList: true,
......@@ -67,7 +69,7 @@
equal(duration, ((4 * 10 * 1000 + 2) - 1) * 0.001, 'used PTS values');
});
test('interval duration works when partial PTS information is available', function() {
test('works when partial PTS information is available', function() {
var firstInterval, secondInterval, duration = Playlist.duration({
mediaSequence: 0,
endList: true,
......@@ -111,7 +113,7 @@
'calculated with mixed intervals');
});
test('interval duration handles trailing segments without PTS information', function() {
test('handles trailing segments without PTS information', function() {
var duration = Playlist.duration({
mediaSequence: 0,
endList: true,
......@@ -139,7 +141,37 @@
equal(duration, 10 + 9 + 10, 'calculated duration');
});
test('interval duration counts the time between segments as part of the later segment duration', function() {
test('uses PTS intervals when the start and end segment have them', function() {
var playlist, duration;
playlist = {
mediaSequence: 0,
segments: [{
minVideoPts: 0,
minAudioPts: 0,
maxVideoPts: 10 * 1000,
maxAudioPts: 10 * 1000,
uri: '0.ts'
}, {
duration: 9,
uri: '1.ts'
},{
minVideoPts: 20 * 1000 + 100,
minAudioPts: 20 * 1000 + 100,
maxVideoPts: 30 * 1000 + 100,
maxAudioPts: 30 * 1000 + 100,
duration: 10,
uri: '2.ts'
}]
};
duration = Playlist.duration(playlist, 0, 2);
equal(duration, 20.1, 'used the PTS-based interval');
duration = Playlist.duration(playlist, 0, 3);
equal(duration, 30.1, 'used the PTS-based interval');
});
test('counts the time between segments as part of the later segment duration', function() {
var duration = Playlist.duration({
mediaSequence: 0,
endList: true,
......@@ -162,7 +194,7 @@
equal(duration, (1 * 10 * 1000 + 100) * 0.001, 'included the segment gap');
});
test('interval duration accounts for discontinuities', function() {
test('accounts for discontinuities', function() {
var duration = Playlist.duration({
mediaSequence: 0,
endList: true,
......@@ -186,7 +218,7 @@
equal(duration, 10 + 10, 'handles discontinuities');
});
test('interval duration does not count ending segment gaps across a discontinuity', function() {
test('does not count ending segment gaps across a discontinuity', function() {
var duration = Playlist.duration({
mediaSequence: 0,
endList: true,
......@@ -210,7 +242,7 @@
equal(duration, (1 * 10 * 1000) * 0.001, 'did not include the segment gap');
});
test('strict interval duration does not count ending segment gaps', function() {
test('strict duration does not count ending segment gaps', function() {
var duration = Playlist.duration({
mediaSequence: 0,
endList: true,
......@@ -233,6 +265,8 @@
equal(duration, (1 * 10 * 1000) * 0.001, 'did not include the segment gap');
});
module('Playlist Seekable');
test('calculates seekable time ranges from the available segments', function() {
var playlist = {
mediaSequence: 0,
......