Percent buffered calculation now works correctly when the segment is not buffere…
…d and currentTime is within the segment (#715)
Showing
2 changed files
with
87 additions
and
11 deletions
... | @@ -198,27 +198,58 @@ const bufferIntersection = function(bufferA, bufferB) { | ... | @@ -198,27 +198,58 @@ const bufferIntersection = function(bufferA, bufferB) { |
198 | * covers adjusted according to currentTime | 198 | * covers adjusted according to currentTime |
199 | * @param {TimeRanges} referenceRange - the original time range that the | 199 | * @param {TimeRanges} referenceRange - the original time range that the |
200 | * segment covers | 200 | * segment covers |
201 | * @param {Number} currentTime - time in seconds where the current playback | ||
202 | * is at | ||
201 | * @param {TimeRanges} buffered - the currently buffered time ranges | 203 | * @param {TimeRanges} buffered - the currently buffered time ranges |
202 | * @returns {Number} percent of the segment currently buffered | 204 | * @returns {Number} percent of the segment currently buffered |
203 | */ | 205 | */ |
204 | const calculateBufferedPercent = function(segmentRange, referenceRange, buffered) { | 206 | const calculateBufferedPercent = function(adjustedRange, |
207 | referenceRange, | ||
208 | currentTime, | ||
209 | buffered) { | ||
205 | let referenceDuration = referenceRange.end(0) - referenceRange.start(0); | 210 | let referenceDuration = referenceRange.end(0) - referenceRange.start(0); |
206 | let segmentDuration = segmentRange.end(0) - segmentRange.start(0); | 211 | let adjustedDuration = adjustedRange.end(0) - adjustedRange.start(0); |
207 | let intersection = bufferIntersection(segmentRange, buffered); | 212 | let bufferMissingFromAdjusted = referenceDuration - adjustedDuration; |
208 | let count = intersection.length; | 213 | let adjustedIntersection = bufferIntersection(adjustedRange, buffered); |
214 | let referenceIntersection = bufferIntersection(referenceRange, buffered); | ||
215 | let adjustedOverlap = 0; | ||
216 | let referenceOverlap = 0; | ||
217 | |||
218 | let count = adjustedIntersection.length; | ||
209 | 219 | ||
210 | while (count--) { | 220 | while (count--) { |
211 | segmentDuration -= intersection.end(count) - intersection.start(count); | 221 | adjustedOverlap += adjustedIntersection.end(count) - |
222 | adjustedIntersection.start(count); | ||
223 | |||
224 | // If the current overlap segment starts at currentTime, then increase the | ||
225 | // overlap duration so that it actually starts at the beginning of referenceRange | ||
226 | // by including the difference between the two Range's durations | ||
227 | // This is a work around for the way Flash has no buffer before currentTime | ||
228 | if (adjustedIntersection.start(count) === currentTime) { | ||
229 | adjustedOverlap += bufferMissingFromAdjusted; | ||
230 | } | ||
212 | } | 231 | } |
213 | return (referenceDuration - segmentDuration) / referenceDuration * 100; | 232 | |
233 | count = referenceIntersection.length; | ||
234 | |||
235 | while (count--) { | ||
236 | referenceOverlap += referenceIntersection.end(count) - | ||
237 | referenceIntersection.start(count); | ||
238 | } | ||
239 | |||
240 | // Use whichever value is larger for the percentage-buffered since that value | ||
241 | // is likely more accurate because the only way | ||
242 | return Math.max(adjustedOverlap, referenceOverlap) / referenceDuration * 100; | ||
214 | }; | 243 | }; |
215 | 244 | ||
216 | /** | 245 | /** |
217 | * Return the amount of a segment specified by the mediaIndex overlaps | 246 | * Return the amount of a range specified by the startOfSegment and segmentDuration |
218 | * the current buffered content. | 247 | * overlaps the current buffered content. |
219 | * | 248 | * |
220 | * @param {Number} startOfSegment - the time where the segment begins | 249 | * @param {Number} startOfSegment - the time where the segment begins |
221 | * @param {Number} segmentDuration - the duration of the segment in seconds | 250 | * @param {Number} segmentDuration - the duration of the segment in seconds |
251 | * @param {Number} currentTime - time in seconds where the current playback | ||
252 | * is at | ||
222 | * @param {TimeRanges} buffered - the state of the buffer | 253 | * @param {TimeRanges} buffered - the state of the buffer |
223 | * @returns {Number} percentage of the segment's time range that is | 254 | * @returns {Number} percentage of the segment's time range that is |
224 | * already in `buffered` | 255 | * already in `buffered` |
... | @@ -254,6 +285,7 @@ const getSegmentBufferedPercent = function(startOfSegment, | ... | @@ -254,6 +285,7 @@ const getSegmentBufferedPercent = function(startOfSegment, |
254 | 285 | ||
255 | let percent = calculateBufferedPercent(adjustedSegmentRange, | 286 | let percent = calculateBufferedPercent(adjustedSegmentRange, |
256 | originalSegmentRange, | 287 | originalSegmentRange, |
288 | currentTime, | ||
257 | buffered); | 289 | buffered); |
258 | 290 | ||
259 | // If the segment is reported as having a zero duration, return 0% | 291 | // If the segment is reported as having a zero duration, return 0% | ... | ... |
... | @@ -94,7 +94,7 @@ QUnit.test('detects time range end-point changed by updates', function() { | ... | @@ -94,7 +94,7 @@ QUnit.test('detects time range end-point changed by updates', function() { |
94 | 94 | ||
95 | QUnit.module('Segment Percent Buffered Calculations'); | 95 | QUnit.module('Segment Percent Buffered Calculations'); |
96 | 96 | ||
97 | QUnit.test('calculates the percent buffered for segments', function() { | 97 | QUnit.test('calculates the percent buffered for segments in the simple case', function() { |
98 | let segmentStart = 10; | 98 | let segmentStart = 10; |
99 | let segmentDuration = 10; | 99 | let segmentDuration = 10; |
100 | let currentTime = 0; | 100 | let currentTime = 0; |
... | @@ -108,8 +108,8 @@ QUnit.test('calculates the percent buffered for segments', function() { | ... | @@ -108,8 +108,8 @@ QUnit.test('calculates the percent buffered for segments', function() { |
108 | QUnit.equal(percentBuffered, 40, 'calculated the buffered amount correctly'); | 108 | QUnit.equal(percentBuffered, 40, 'calculated the buffered amount correctly'); |
109 | }); | 109 | }); |
110 | 110 | ||
111 | QUnit.test('calculates the percent buffered for segments taking into account ' + | 111 | QUnit.test('consider the buffer before currentTime to be filled if the segement begins at ' + |
112 | 'currentTime', function() { | 112 | 'or before the currentTime', function() { |
113 | let segmentStart = 10; | 113 | let segmentStart = 10; |
114 | let segmentDuration = 10; | 114 | let segmentDuration = 10; |
115 | let currentTime = 15; | 115 | let currentTime = 15; |
... | @@ -123,6 +123,21 @@ QUnit.test('calculates the percent buffered for segments taking into account ' + | ... | @@ -123,6 +123,21 @@ QUnit.test('calculates the percent buffered for segments taking into account ' + |
123 | QUnit.equal(percentBuffered, 90, 'calculated the buffered amount correctly'); | 123 | QUnit.equal(percentBuffered, 90, 'calculated the buffered amount correctly'); |
124 | }); | 124 | }); |
125 | 125 | ||
126 | QUnit.test('does not consider the buffer before currentTime as filled if the segment ' + | ||
127 | 'begins after the currentTime', function() { | ||
128 | let segmentStart = 10; | ||
129 | let segmentDuration = 10; | ||
130 | let currentTime = 18; | ||
131 | let buffered = createTimeRanges([[19, 30]]); | ||
132 | let percentBuffered = Ranges.getSegmentBufferedPercent( | ||
133 | segmentStart, | ||
134 | segmentDuration, | ||
135 | currentTime, | ||
136 | buffered); | ||
137 | |||
138 | QUnit.equal(percentBuffered, 10, 'calculated the buffered amount correctly'); | ||
139 | }); | ||
140 | |||
126 | QUnit.test('calculates the percent buffered for segments with multiple buffered ' + | 141 | QUnit.test('calculates the percent buffered for segments with multiple buffered ' + |
127 | 'regions', function() { | 142 | 'regions', function() { |
128 | let segmentStart = 10; | 143 | let segmentStart = 10; |
... | @@ -166,3 +181,32 @@ QUnit.test('calculates the percent buffered as 0 for zero-length segments', func | ... | @@ -166,3 +181,32 @@ QUnit.test('calculates the percent buffered as 0 for zero-length segments', func |
166 | 181 | ||
167 | QUnit.equal(percentBuffered, 0, 'calculated the buffered amount correctly'); | 182 | QUnit.equal(percentBuffered, 0, 'calculated the buffered amount correctly'); |
168 | }); | 183 | }); |
184 | |||
185 | QUnit.test('calculates the percent buffered as 0 for segments that do not overlap ' + | ||
186 | 'buffered regions taking into account currentTime', function() { | ||
187 | let segmentStart = 10; | ||
188 | let segmentDuration = 10; | ||
189 | let currentTime = 19; | ||
190 | let buffered = createTimeRanges([[20, 30]]); | ||
191 | let percentBuffered = Ranges.getSegmentBufferedPercent( | ||
192 | segmentStart, | ||
193 | segmentDuration, | ||
194 | currentTime, | ||
195 | buffered); | ||
196 | |||
197 | QUnit.equal(percentBuffered, 0, 'calculated the buffered amount correctly'); | ||
198 | }); | ||
199 | |||
200 | QUnit.test('calculates the percent buffered for segments that end before currentTime', function() { | ||
201 | let segmentStart = 10; | ||
202 | let segmentDuration = 10; | ||
203 | let currentTime = 19.6; | ||
204 | let buffered = createTimeRanges([[0, 19.5]]); | ||
205 | let percentBuffered = Ranges.getSegmentBufferedPercent( | ||
206 | segmentStart, | ||
207 | segmentDuration, | ||
208 | currentTime, | ||
209 | buffered); | ||
210 | |||
211 | QUnit.equal(percentBuffered, 95, 'calculated the buffered amount correctly'); | ||
212 | }); | ... | ... |
-
Please register or sign in to post a comment