pull apart segmentsDuration
Break segmentsDuration up into more manageable parts.
Showing
2 changed files
with
88 additions
and
40 deletions
... | @@ -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, | ... | ... |
-
Please register or sign in to post a comment