mediasource-remove.html (13875B)
1 <!DOCTYPE html> 2 <!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> 3 <html> 4 <head> 5 <meta charset="utf-8"> 6 <title>SourceBuffer.remove() test cases.</title> 7 <script src="/resources/testharness.js"></script> 8 <script src="/resources/testharnessreport.js"></script> 9 <script src="mediasource-util.js"></script> 10 </head> 11 <body> 12 <div id="log"></div> 13 <script> 14 mediasource_test(function(test, mediaElement, mediaSource) 15 { 16 var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE); 17 18 mediaSource.duration = 10; 19 20 assert_throws_js(TypeError, function() 21 { 22 sourceBuffer.remove(-1, 2); 23 }, "remove"); 24 25 test.done(); 26 }, "Test remove with an negative start."); 27 28 mediasource_test(function(test, mediaElement, mediaSource) 29 { 30 var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE); 31 32 mediaSource.duration = 10; 33 34 [ undefined, NaN, Infinity, -Infinity ].forEach(function(item) 35 { 36 assert_throws_js(TypeError, function() 37 { 38 sourceBuffer.remove(item, 2); 39 }, "remove"); 40 }); 41 42 test.done(); 43 }, "Test remove with non-finite start."); 44 45 mediasource_test(function(test, mediaElement, mediaSource) 46 { 47 var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE); 48 49 mediaSource.duration = 10; 50 51 assert_throws_js(TypeError, function() 52 { 53 sourceBuffer.remove(11, 12); 54 }, "remove"); 55 56 test.done(); 57 }, "Test remove with a start beyond the duration."); 58 59 mediasource_test(function(test, mediaElement, mediaSource) 60 { 61 var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE); 62 63 mediaSource.duration = 10; 64 65 assert_throws_js(TypeError, function() 66 { 67 sourceBuffer.remove(2, 1); 68 }, "remove"); 69 70 test.done(); 71 }, "Test remove with a start larger than the end."); 72 73 mediasource_test(function(test, mediaElement, mediaSource) 74 { 75 var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE); 76 77 mediaSource.duration = 10; 78 79 assert_throws_js(TypeError, function() 80 { 81 sourceBuffer.remove(0, Number.NEGATIVE_INFINITY); 82 }, "remove"); 83 84 test.done(); 85 }, "Test remove with a NEGATIVE_INFINITY end."); 86 87 mediasource_test(function(test, mediaElement, mediaSource) 88 { 89 var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE); 90 91 mediaSource.duration = 10; 92 93 assert_throws_js(TypeError, function() 94 { 95 sourceBuffer.remove(0, Number.NaN); 96 }, "remove"); 97 98 test.done(); 99 }, "Test remove with a NaN end."); 100 101 mediasource_test(function(test, mediaElement, mediaSource) 102 { 103 var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE); 104 105 mediaSource.duration = 10; 106 107 mediaSource.removeSourceBuffer(sourceBuffer); 108 109 assert_throws_dom("InvalidStateError", function() 110 { 111 sourceBuffer.remove(1, 2); 112 }, "remove"); 113 114 test.done(); 115 }, "Test remove after SourceBuffer removed from mediaSource."); 116 117 mediasource_test(function(test, mediaElement, mediaSource) 118 { 119 var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE); 120 121 assert_false(sourceBuffer.updating, "updating is false"); 122 assert_equals(mediaSource.duration, NaN, "duration isn't set"); 123 124 assert_throws_js(TypeError, function() 125 { 126 sourceBuffer.remove(0, 0); 127 }, "remove"); 128 129 test.done(); 130 }, "Test remove with a NaN duration."); 131 132 mediasource_test(function(test, mediaElement, mediaSource) 133 { 134 var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE); 135 136 mediaSource.duration = 10; 137 138 test.expectEvent(sourceBuffer, "updatestart"); 139 test.expectEvent(sourceBuffer, "update"); 140 test.expectEvent(sourceBuffer, "updateend"); 141 sourceBuffer.remove(1, 2); 142 143 assert_true(sourceBuffer.updating, "updating"); 144 145 assert_throws_dom("InvalidStateError", function() 146 { 147 sourceBuffer.remove(3, 4); 148 }, "remove"); 149 150 test.waitForExpectedEvents(function() 151 { 152 test.done(); 153 }); 154 }, "Test remove while update pending."); 155 156 mediasource_test(function(test, mediaElement, mediaSource) 157 { 158 var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE); 159 160 mediaSource.duration = 10; 161 162 test.expectEvent(sourceBuffer, "updatestart"); 163 test.expectEvent(sourceBuffer, "update"); 164 test.expectEvent(sourceBuffer, "updateend"); 165 sourceBuffer.remove(1, 2); 166 167 assert_true(sourceBuffer.updating, "updating"); 168 169 assert_throws_dom("InvalidStateError", function() 170 { 171 sourceBuffer.abort(); 172 }, "abort"); 173 174 assert_true(sourceBuffer.updating, "updating"); 175 176 test.waitForExpectedEvents(function() 177 { 178 test.done(); 179 }); 180 }, "Test aborting a remove operation."); 181 182 mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) 183 { 184 sourceBuffer.appendBuffer(mediaData); 185 186 test.expectEvent(sourceBuffer, "updatestart"); 187 test.expectEvent(sourceBuffer, "update"); 188 test.expectEvent(sourceBuffer, "updateend"); 189 190 test.waitForExpectedEvents(function() 191 { 192 assert_less_than(mediaSource.duration, 10) 193 194 mediaSource.duration = 10; 195 196 sourceBuffer.remove(mediaSource.duration, mediaSource.duration + 2); 197 198 assert_true(sourceBuffer.updating, "updating"); 199 test.expectEvent(sourceBuffer, "updatestart"); 200 test.expectEvent(sourceBuffer, "update"); 201 test.expectEvent(sourceBuffer, "updateend"); 202 }); 203 204 test.waitForExpectedEvents(function() 205 { 206 test.done(); 207 }); 208 209 }, "Test remove with a start at the duration."); 210 211 mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) 212 { 213 sourceBuffer.appendBuffer(mediaData); 214 215 test.expectEvent(sourceBuffer, "updatestart"); 216 test.expectEvent(sourceBuffer, "update"); 217 test.expectEvent(sourceBuffer, "updateend"); 218 219 test.waitForExpectedEvents(function() 220 { 221 assert_less_than(mediaSource.duration, 10) 222 223 mediaSource.duration = 10; 224 225 sourceBuffer.remove(1, 1 + 0.9 / (1000 * 1000)); 226 227 assert_true(sourceBuffer.updating, "updating"); 228 test.expectEvent(sourceBuffer, "updatestart"); 229 test.expectEvent(sourceBuffer, "update"); 230 test.expectEvent(sourceBuffer, "updateend"); 231 }); 232 233 test.waitForExpectedEvents(function() 234 { 235 test.done(); 236 }); 237 238 }, "Test remove with a nanosecond range."); 239 240 mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) 241 { 242 test.expectEvent(sourceBuffer, "updatestart"); 243 test.expectEvent(sourceBuffer, "update"); 244 test.expectEvent(sourceBuffer, "updateend"); 245 sourceBuffer.appendBuffer(mediaData); 246 247 test.waitForExpectedEvents(function() 248 { 249 mediaSource.endOfStream(); 250 251 assert_equals(mediaSource.readyState, "ended"); 252 253 test.expectEvent(sourceBuffer, "updatestart"); 254 test.expectEvent(sourceBuffer, "update"); 255 test.expectEvent(sourceBuffer, "updateend"); 256 test.expectEvent(mediaSource, "sourceopen"); 257 sourceBuffer.remove(1, 2); 258 259 assert_true(sourceBuffer.updating, "updating"); 260 assert_equals(mediaSource.readyState, "open"); 261 }); 262 263 test.waitForExpectedEvents(function() 264 { 265 assert_false(sourceBuffer.updating, "updating"); 266 test.done(); 267 }); 268 }, "Test remove transitioning readyState from 'ended' to 'open'."); 269 270 function removeAppendedDataTests(callback, description) 271 { 272 mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) 273 { 274 test.expectEvent(sourceBuffer, "updatestart"); 275 test.expectEvent(sourceBuffer, "update"); 276 test.expectEvent(sourceBuffer, "updateend"); 277 sourceBuffer.appendBuffer(mediaData); 278 279 test.waitForExpectedEvents(function() 280 { 281 mediaSource.endOfStream(); 282 assert_false(sourceBuffer.updating, "updating"); 283 284 var start = Math.max(segmentInfo.media[0].timev, segmentInfo.media[0].timea).toFixed(3); 285 var duration = mediaElement.duration.toFixed(3); 286 var subType = MediaSourceUtil.getSubType(segmentInfo.type); 287 288 assertBufferedEquals(sourceBuffer, "{ [" + start + ", " + duration + ") }", "Initial buffered range."); 289 callback(test, mediaSource, sourceBuffer, duration, subType, segmentInfo); 290 }); 291 }, description); 292 }; 293 function removeAndCheckBufferedRanges(test, mediaSource, sourceBuffer, start, end, expected) 294 { 295 test.expectEvent(sourceBuffer, "updatestart"); 296 test.expectEvent(sourceBuffer, "update"); 297 test.expectEvent(sourceBuffer, "updateend"); 298 sourceBuffer.remove(start, end); 299 300 test.waitForExpectedEvents(function() 301 { 302 mediaSource.endOfStream(); 303 assert_false(sourceBuffer.updating, "updating"); 304 305 assertBufferedEquals(sourceBuffer, expected, "Buffered ranges after remove()."); 306 test.done(); 307 }); 308 } 309 310 removeAppendedDataTests(function(test, mediaSource, sourceBuffer, duration, subType, segmentInfo) 311 { 312 removeAndCheckBufferedRanges(test, mediaSource, sourceBuffer, 0, Number.POSITIVE_INFINITY, "{ }"); 313 }, "Test removing all appended data."); 314 315 removeAppendedDataTests(function(test, mediaSource, sourceBuffer, duration, subType, segmentInfo) 316 { 317 var expectations = { 318 webm: ("{ [3.315, " + duration + ") }"), 319 mp4: ("{ [3.298, " + duration + ") }"), 320 }; 321 322 // Note: Range doesn't start exactly at the end of the remove range because there isn't 323 // a keyframe there. The resulting range starts at the first keyframe >= the end time. 324 removeAndCheckBufferedRanges(test, mediaSource, sourceBuffer, 0, 3, expectations[subType]); 325 }, "Test removing beginning of appended data."); 326 327 removeAppendedDataTests(function(test, mediaSource, sourceBuffer, duration, subType, segmentInfo) 328 { 329 var start = Math.max(segmentInfo.media[0].timev, segmentInfo.media[0].timea).toFixed(3); 330 var expectations = { 331 webm: ("{ [" + start + ", 1.005) [3.315, " + duration + ") }"), 332 mp4: ("{ [" + start + ", 0.997) [3.298, " + duration + ") }"), 333 }; 334 335 // Note: The first resulting range ends slightly after start because the removal algorithm only removes 336 // frames with a timestamp >= the start time. If a frame starts before and ends after the remove() start 337 // timestamp, then it stays in the buffer. 338 removeAndCheckBufferedRanges(test, mediaSource, sourceBuffer, 1, 3, expectations[subType]); 339 }, "Test removing the middle of appended data."); 340 341 removeAppendedDataTests(function(test, mediaSource, sourceBuffer, duration, subType, segmentInfo) 342 { 343 var start = Math.max(segmentInfo.media[0].timev, segmentInfo.media[0].timea).toFixed(3); 344 var expectations = { 345 webm: "{ [" + start + ", 1.013) }", 346 mp4: "{ [" + start + ", 1.022) }", 347 }; 348 349 removeAndCheckBufferedRanges(test, mediaSource, sourceBuffer, 1, Number.POSITIVE_INFINITY, expectations[subType]); 350 }, "Test removing the end of appended data."); 351 </script> 352 </body> 353 </html>