b068a6e6 by David LaPalomento

pull apart segmentsDuration

Break segmentsDuration up into more manageable parts.
1 parent 3e508892
...@@ -5,39 +5,17 @@ ...@@ -5,39 +5,17 @@
5 'use strict'; 5 'use strict';
6 6
7 var DEFAULT_TARGET_DURATION = 10; 7 var DEFAULT_TARGET_DURATION = 10;
8 var duration, seekable, segmentsDuration; 8 var accumulateDuration, duration, seekable, segmentsDuration;
9 9
10 /** 10 accumulateDuration = function(playlist, startSequence, endSequence, strict) {
11 * Calculate the media duration from the segments associated with a 11 var
12 * playlist. The duration of a subinterval of the available segments 12 result = 0,
13 * may be calculated by specifying a start and end index. 13 targetDuration = playlist.targetDuration || DEFAULT_TARGET_DURATION,
14 * 14 segment, endSegment,
15 * @param playlist {object} a media playlist object 15 i, j;
16 * @param startSequence {number} (optional) an inclusive lower
17 * boundary for the playlist. Defaults to 0.
18 * @param endSequence {number} (optional) an exclusive upper boundary
19 * for the playlist. Defaults to playlist length.
20 * @param strict {boolean} (optional) if true, the interval between
21 * the final segment and the subsequent segment will not be included
22 * in the result
23 * @return {number} the duration between the start index and end
24 * index.
25 */
26 segmentsDuration = function(playlist, startSequence, endSequence, strict) {
27 var targetDuration, i, j, segment, endSegment, expiredSegmentCount, result = 0;
28
29 startSequence = startSequence || 0;
30 i = startSequence;
31 endSequence = endSequence !== undefined ? endSequence : (playlist.segments || []).length;
32 targetDuration = playlist.targetDuration || DEFAULT_TARGET_DURATION;
33
34 // estimate expired segment duration using the target duration
35 expiredSegmentCount = Math.max(playlist.mediaSequence - startSequence, 0);
36 result += expiredSegmentCount * targetDuration;
37 i += expiredSegmentCount;
38 16
39 // accumulate the segment durations into the result 17 // accumulate the segment durations into the result
40 for (; i < endSequence; i++) { 18 for (i = startSequence; i < endSequence; i++) {
41 segment = playlist.segments[i - playlist.mediaSequence]; 19 segment = playlist.segments[i - playlist.mediaSequence];
42 20
43 // when PTS values aren't available, use information from the playlist 21 // when PTS values aren't available, use information from the playlist
...@@ -49,7 +27,7 @@ ...@@ -49,7 +27,7 @@
49 27
50 // find the last segment with PTS info and use that to calculate 28 // find the last segment with PTS info and use that to calculate
51 // the interval duration 29 // the interval duration
52 for(j = i; j < endSequence - 1; j++) { 30 for (j = i; j < endSequence - 1; j++) {
53 endSegment = playlist.segments[j - playlist.mediaSequence + 1]; 31 endSegment = playlist.segments[j - playlist.mediaSequence + 1];
54 if (endSegment.maxVideoPts === undefined || 32 if (endSegment.maxVideoPts === undefined ||
55 endSegment.discontinuity) { 33 endSegment.discontinuity) {
...@@ -81,6 +59,42 @@ ...@@ -81,6 +59,42 @@
81 }; 59 };
82 60
83 /** 61 /**
62 * Calculate the media duration from the segments associated with a
63 * playlist. The duration of a subinterval of the available segments
64 * may be calculated by specifying a start and end index.
65 *
66 * @param playlist {object} a media playlist object
67 * @param startSequence {number} (optional) an inclusive lower
68 * boundary for the playlist. Defaults to 0.
69 * @param endSequence {number} (optional) an exclusive upper boundary
70 * for the playlist. Defaults to playlist length.
71 * @param strict {boolean} (optional) if true, the interval between
72 * the final segment and the subsequent segment will not be included
73 * in the result
74 * @return {number} the duration between the start index and end
75 * index.
76 */
77 segmentsDuration = function(playlist, startSequence, endSequence, strict) {
78 var targetDuration, expiredSegmentCount, result = 0;
79
80 startSequence = startSequence || 0;
81 endSequence = endSequence !== undefined ? endSequence : (playlist.segments || []).length;
82 targetDuration = playlist.targetDuration || DEFAULT_TARGET_DURATION;
83
84 // estimate expired segment duration using the target duration
85 expiredSegmentCount = Math.max(playlist.mediaSequence - startSequence, 0);
86 result += expiredSegmentCount * targetDuration;
87
88 // accumulate the segment durations into the result
89 result += accumulateDuration(playlist,
90 startSequence + expiredSegmentCount,
91 endSequence,
92 strict);
93
94 return result;
95 };
96
97 /**
84 * Calculates the duration of a playlist. If a start and end index 98 * Calculates the duration of a playlist. If a start and end index
85 * are specified, the duration will be for the subset of the media 99 * are specified, the duration will be for the subset of the media
86 * timeline between those two indices. The total duration for live 100 * timeline between those two indices. The total duration for live
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
3 'use strict'; 3 'use strict';
4 var Playlist = videojs.Hls.Playlist; 4 var Playlist = videojs.Hls.Playlist;
5 5
6 module('Playlist Utilities'); 6 module('Playlist Duration');
7 7
8 test('total duration for live playlists is Infinity', function() { 8 test('total duration for live playlists is Infinity', function() {
9 var duration = Playlist.duration({ 9 var duration = Playlist.duration({
...@@ -16,7 +16,9 @@ ...@@ -16,7 +16,9 @@
16 equal(duration, Infinity, 'duration is infinity'); 16 equal(duration, Infinity, 'duration is infinity');
17 }); 17 });
18 18
19 test('interval duration accounts for media sequences', function() { 19 module('Playlist Interval Duration');
20
21 test('accounts for media sequences', function() {
20 var duration = Playlist.duration({ 22 var duration = Playlist.duration({
21 mediaSequence: 10, 23 mediaSequence: 10,
22 endList: true, 24 endList: true,
...@@ -38,7 +40,7 @@ ...@@ -38,7 +40,7 @@
38 equal(duration, 14 * 10, 'duration includes dropped segments'); 40 equal(duration, 14 * 10, 'duration includes dropped segments');
39 }); 41 });
40 42
41 test('interval duration uses PTS values when available', function() { 43 test('uses PTS values when available', function() {
42 var duration = Playlist.duration({ 44 var duration = Playlist.duration({
43 mediaSequence: 0, 45 mediaSequence: 0,
44 endList: true, 46 endList: true,
...@@ -67,7 +69,7 @@ ...@@ -67,7 +69,7 @@
67 equal(duration, ((4 * 10 * 1000 + 2) - 1) * 0.001, 'used PTS values'); 69 equal(duration, ((4 * 10 * 1000 + 2) - 1) * 0.001, 'used PTS values');
68 }); 70 });
69 71
70 test('interval duration works when partial PTS information is available', function() { 72 test('works when partial PTS information is available', function() {
71 var firstInterval, secondInterval, duration = Playlist.duration({ 73 var firstInterval, secondInterval, duration = Playlist.duration({
72 mediaSequence: 0, 74 mediaSequence: 0,
73 endList: true, 75 endList: true,
...@@ -111,7 +113,7 @@ ...@@ -111,7 +113,7 @@
111 'calculated with mixed intervals'); 113 'calculated with mixed intervals');
112 }); 114 });
113 115
114 test('interval duration handles trailing segments without PTS information', function() { 116 test('handles trailing segments without PTS information', function() {
115 var duration = Playlist.duration({ 117 var duration = Playlist.duration({
116 mediaSequence: 0, 118 mediaSequence: 0,
117 endList: true, 119 endList: true,
...@@ -139,7 +141,37 @@ ...@@ -139,7 +141,37 @@
139 equal(duration, 10 + 9 + 10, 'calculated duration'); 141 equal(duration, 10 + 9 + 10, 'calculated duration');
140 }); 142 });
141 143
142 test('interval duration counts the time between segments as part of the later segment duration', function() { 144 test('uses PTS intervals when the start and end segment have them', function() {
145 var playlist, duration;
146 playlist = {
147 mediaSequence: 0,
148 segments: [{
149 minVideoPts: 0,
150 minAudioPts: 0,
151 maxVideoPts: 10 * 1000,
152 maxAudioPts: 10 * 1000,
153 uri: '0.ts'
154 }, {
155 duration: 9,
156 uri: '1.ts'
157 },{
158 minVideoPts: 20 * 1000 + 100,
159 minAudioPts: 20 * 1000 + 100,
160 maxVideoPts: 30 * 1000 + 100,
161 maxAudioPts: 30 * 1000 + 100,
162 duration: 10,
163 uri: '2.ts'
164 }]
165 };
166 duration = Playlist.duration(playlist, 0, 2);
167
168 equal(duration, 20.1, 'used the PTS-based interval');
169
170 duration = Playlist.duration(playlist, 0, 3);
171 equal(duration, 30.1, 'used the PTS-based interval');
172 });
173
174 test('counts the time between segments as part of the later segment duration', function() {
143 var duration = Playlist.duration({ 175 var duration = Playlist.duration({
144 mediaSequence: 0, 176 mediaSequence: 0,
145 endList: true, 177 endList: true,
...@@ -162,7 +194,7 @@ ...@@ -162,7 +194,7 @@
162 equal(duration, (1 * 10 * 1000 + 100) * 0.001, 'included the segment gap'); 194 equal(duration, (1 * 10 * 1000 + 100) * 0.001, 'included the segment gap');
163 }); 195 });
164 196
165 test('interval duration accounts for discontinuities', function() { 197 test('accounts for discontinuities', function() {
166 var duration = Playlist.duration({ 198 var duration = Playlist.duration({
167 mediaSequence: 0, 199 mediaSequence: 0,
168 endList: true, 200 endList: true,
...@@ -186,7 +218,7 @@ ...@@ -186,7 +218,7 @@
186 equal(duration, 10 + 10, 'handles discontinuities'); 218 equal(duration, 10 + 10, 'handles discontinuities');
187 }); 219 });
188 220
189 test('interval duration does not count ending segment gaps across a discontinuity', function() { 221 test('does not count ending segment gaps across a discontinuity', function() {
190 var duration = Playlist.duration({ 222 var duration = Playlist.duration({
191 mediaSequence: 0, 223 mediaSequence: 0,
192 endList: true, 224 endList: true,
...@@ -210,7 +242,7 @@ ...@@ -210,7 +242,7 @@
210 equal(duration, (1 * 10 * 1000) * 0.001, 'did not include the segment gap'); 242 equal(duration, (1 * 10 * 1000) * 0.001, 'did not include the segment gap');
211 }); 243 });
212 244
213 test('strict interval duration does not count ending segment gaps', function() { 245 test('strict duration does not count ending segment gaps', function() {
214 var duration = Playlist.duration({ 246 var duration = Playlist.duration({
215 mediaSequence: 0, 247 mediaSequence: 0,
216 endList: true, 248 endList: true,
...@@ -233,6 +265,8 @@ ...@@ -233,6 +265,8 @@
233 equal(duration, (1 * 10 * 1000) * 0.001, 'did not include the segment gap'); 265 equal(duration, (1 * 10 * 1000) * 0.001, 'did not include the segment gap');
234 }); 266 });
235 267
268 module('Playlist Seekable');
269
236 test('calculates seekable time ranges from the available segments', function() { 270 test('calculates seekable time ranges from the available segments', function() {
237 var playlist = { 271 var playlist = {
238 mediaSequence: 0, 272 mediaSequence: 0,
......