e45497bc by Jon-Carlos Rivera

Percent buffered calculation now works correctly when the segment is not buffere…

…d and currentTime is within the segment (#715)
1 parent cc311ea3
...@@ -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;
219
220 while (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 }
231 }
232
233 count = referenceIntersection.length;
209 234
210 while (count--) { 235 while (count--) {
211 segmentDuration -= intersection.end(count) - intersection.start(count); 236 referenceOverlap += referenceIntersection.end(count) -
237 referenceIntersection.start(count);
212 } 238 }
213 return (referenceDuration - segmentDuration) / referenceDuration * 100; 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 });
......