|  | <!DOCTYPE html> | 
|  | <html> | 
|  | <head> | 
|  | <title>SourceBuffer.remove() test cases.</title> | 
|  | <script src="/resources/testharness.js"></script> | 
|  | <script src="/resources/testharnessreport.js"></script> | 
|  | <script src="mediasource-util.js"></script> | 
|  | </head> | 
|  | <body> | 
|  | <div id="log"></div> | 
|  | <script> | 
|  | mediasource_test(function(test, mediaElement, mediaSource) | 
|  | { | 
|  | var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE); | 
|  |  | 
|  | assert_throws("InvalidAccessError", function() | 
|  | { | 
|  | sourceBuffer.remove(-1, 2); | 
|  | }, "remove"); | 
|  |  | 
|  | test.done(); | 
|  | }, "Test remove with an negative start."); | 
|  |  | 
|  | mediasource_test(function(test, mediaElement, mediaSource) | 
|  | { | 
|  | var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE); | 
|  |  | 
|  | [ undefined, NaN, Infinity, -Infinity ].forEach(function(item) | 
|  | { | 
|  | assert_throws(new TypeError(), function() | 
|  | { | 
|  | sourceBuffer.remove(item, 2); | 
|  | }, "remove"); | 
|  | }); | 
|  |  | 
|  | test.done(); | 
|  | }, "Test remove with non-finite start."); | 
|  |  | 
|  | mediasource_test(function(test, mediaElement, mediaSource) | 
|  | { | 
|  | var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE); | 
|  |  | 
|  | mediaSource.duration = 10; | 
|  |  | 
|  | assert_throws("InvalidAccessError", function() | 
|  | { | 
|  | sourceBuffer.remove(11, 12); | 
|  | }, "remove"); | 
|  |  | 
|  | test.done(); | 
|  | }, "Test remove with a start beyond the duration."); | 
|  |  | 
|  | mediasource_test(function(test, mediaElement, mediaSource) | 
|  | { | 
|  | var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE); | 
|  |  | 
|  | mediaSource.duration = 10; | 
|  |  | 
|  | assert_throws("InvalidAccessError", function() | 
|  | { | 
|  | sourceBuffer.remove(2, 1); | 
|  | }, "remove"); | 
|  |  | 
|  | test.done(); | 
|  | }, "Test remove with a start larger than the end."); | 
|  |  | 
|  | mediasource_test(function(test, mediaElement, mediaSource) | 
|  | { | 
|  | var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE); | 
|  |  | 
|  | assert_throws("InvalidAccessError", function() | 
|  | { | 
|  | sourceBuffer.remove(0, Number.NEGATIVE_INFINITY); | 
|  | }, "remove"); | 
|  |  | 
|  | test.done(); | 
|  | }, "Test remove with a NEGATIVE_INFINITY end."); | 
|  |  | 
|  | mediasource_test(function(test, mediaElement, mediaSource) | 
|  | { | 
|  | var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE); | 
|  |  | 
|  | assert_throws("InvalidAccessError", function() | 
|  | { | 
|  | sourceBuffer.remove(0, Number.NaN); | 
|  | }, "remove"); | 
|  |  | 
|  | test.done(); | 
|  | }, "Test remove with a NaN end."); | 
|  |  | 
|  | mediasource_test(function(test, mediaElement, mediaSource) | 
|  | { | 
|  | var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE); | 
|  |  | 
|  | mediaSource.duration = 10; | 
|  |  | 
|  | mediaSource.removeSourceBuffer(sourceBuffer); | 
|  |  | 
|  | assert_throws("InvalidStateError", function() | 
|  | { | 
|  | sourceBuffer.remove(1, 2); | 
|  | }, "remove"); | 
|  |  | 
|  | test.done(); | 
|  | }, "Test remove after SourceBuffer removed from mediaSource."); | 
|  |  | 
|  |  | 
|  | mediasource_test(function(test, mediaElement, mediaSource) | 
|  | { | 
|  | var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE); | 
|  |  | 
|  | mediaSource.duration = 10; | 
|  |  | 
|  | test.expectEvent(sourceBuffer, "updatestart"); | 
|  | test.expectEvent(sourceBuffer, "update"); | 
|  | test.expectEvent(sourceBuffer, "updateend"); | 
|  | sourceBuffer.remove(1, 2); | 
|  |  | 
|  | assert_true(sourceBuffer.updating, "updating"); | 
|  |  | 
|  | assert_throws("InvalidStateError", function() | 
|  | { | 
|  | sourceBuffer.remove(3, 4); | 
|  | }, "remove"); | 
|  |  | 
|  | test.waitForExpectedEvents(function() | 
|  | { | 
|  | test.done(); | 
|  | }); | 
|  | }, "Test remove while update pending."); | 
|  |  | 
|  | mediasource_test(function(test, mediaElement, mediaSource) | 
|  | { | 
|  | var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE); | 
|  |  | 
|  | mediaSource.duration = 10; | 
|  |  | 
|  | test.expectEvent(sourceBuffer, "updatestart"); | 
|  | test.expectEvent(sourceBuffer, "abort"); | 
|  | test.expectEvent(sourceBuffer, "updateend"); | 
|  | sourceBuffer.remove(1, 2); | 
|  |  | 
|  | assert_true(sourceBuffer.updating, "updating"); | 
|  |  | 
|  | sourceBuffer.abort(); | 
|  |  | 
|  | assert_false(sourceBuffer.updating, "updating"); | 
|  |  | 
|  | test.waitForExpectedEvents(function() | 
|  | { | 
|  | test.done(); | 
|  | }); | 
|  | }, "Test aborting a remove operation."); | 
|  |  | 
|  | mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) | 
|  | { | 
|  | sourceBuffer.appendBuffer(mediaData); | 
|  |  | 
|  | test.expectEvent(sourceBuffer, "updatestart"); | 
|  | test.expectEvent(sourceBuffer, "update"); | 
|  | test.expectEvent(sourceBuffer, "updateend"); | 
|  |  | 
|  | test.waitForExpectedEvents(function() | 
|  | { | 
|  | assert_less_than(mediaSource.duration, 10) | 
|  |  | 
|  | mediaSource.duration = 10; | 
|  |  | 
|  | sourceBuffer.remove(mediaSource.duration, mediaSource.duration + 2); | 
|  |  | 
|  | assert_true(sourceBuffer.updating, "updating"); | 
|  | test.expectEvent(sourceBuffer, "updatestart"); | 
|  | test.expectEvent(sourceBuffer, "update"); | 
|  | test.expectEvent(sourceBuffer, "updateend"); | 
|  | }); | 
|  |  | 
|  | test.waitForExpectedEvents(function() | 
|  | { | 
|  | test.done(); | 
|  | }); | 
|  |  | 
|  | }, "Test remove with a start at the duration."); | 
|  |  | 
|  | mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) | 
|  | { | 
|  | test.expectEvent(sourceBuffer, "updatestart"); | 
|  | test.expectEvent(sourceBuffer, "update"); | 
|  | test.expectEvent(sourceBuffer, "updateend"); | 
|  | sourceBuffer.appendBuffer(mediaData); | 
|  |  | 
|  | test.waitForExpectedEvents(function() | 
|  | { | 
|  | mediaSource.endOfStream(); | 
|  |  | 
|  | assert_equals(mediaSource.readyState, "ended"); | 
|  |  | 
|  | test.expectEvent(sourceBuffer, "updatestart"); | 
|  | test.expectEvent(sourceBuffer, "update"); | 
|  | test.expectEvent(sourceBuffer, "updateend"); | 
|  | sourceBuffer.remove(1, 2); | 
|  |  | 
|  | assert_true(sourceBuffer.updating, "updating"); | 
|  | assert_equals(mediaSource.readyState, "open"); | 
|  | }); | 
|  |  | 
|  | test.waitForExpectedEvents(function() | 
|  | { | 
|  | assert_false(sourceBuffer.updating, "updating"); | 
|  | test.done(); | 
|  | }); | 
|  | }, "Test remove transitioning readyState from 'ended' to 'open'."); | 
|  |  | 
|  | function removeAppendedDataTests(callback, description) | 
|  | { | 
|  | mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) | 
|  | { | 
|  | test.expectEvent(sourceBuffer, "updatestart"); | 
|  | test.expectEvent(sourceBuffer, "update"); | 
|  | test.expectEvent(sourceBuffer, "updateend"); | 
|  | sourceBuffer.appendBuffer(mediaData); | 
|  |  | 
|  | test.waitForExpectedEvents(function() | 
|  | { | 
|  | mediaSource.endOfStream(); | 
|  | assert_false(sourceBuffer.updating, "updating"); | 
|  |  | 
|  | var duration = mediaElement.duration.toFixed(3); | 
|  | var subType = MediaSourceUtil.getSubType(segmentInfo.type); | 
|  |  | 
|  | assertBufferedEquals(sourceBuffer, "{ [0.000, " + duration + ") }", "Initial buffered range."); | 
|  | callback(test, mediaSource, sourceBuffer, duration, subType); | 
|  | }); | 
|  | }, description); | 
|  | }; | 
|  | function removeAndCheckBufferedRanges(test, mediaSource, sourceBuffer, start, end, expected) | 
|  | { | 
|  | test.expectEvent(sourceBuffer, "updatestart"); | 
|  | test.expectEvent(sourceBuffer, "update"); | 
|  | test.expectEvent(sourceBuffer, "updateend"); | 
|  | sourceBuffer.remove(start, end); | 
|  |  | 
|  | test.waitForExpectedEvents(function() | 
|  | { | 
|  | mediaSource.endOfStream(); | 
|  | assert_false(sourceBuffer.updating, "updating"); | 
|  |  | 
|  | assertBufferedEquals(sourceBuffer, expected, "Buffered ranges after remove()."); | 
|  | test.done(); | 
|  | }); | 
|  | } | 
|  |  | 
|  | removeAppendedDataTests(function(test, mediaSource, sourceBuffer, duration, subType) | 
|  | { | 
|  | removeAndCheckBufferedRanges(test, mediaSource, sourceBuffer, 0, Number.POSITIVE_INFINITY, "{ }"); | 
|  | }, "Test removing all appended data."); | 
|  |  | 
|  | removeAppendedDataTests(function(test, mediaSource, sourceBuffer, duration, subType) | 
|  | { | 
|  | var expectations = { | 
|  | webm: ("{ [3.187, " + duration + ") }"), | 
|  | mp4: ("{ [3.154, " + duration + ") }"), | 
|  | }; | 
|  |  | 
|  | // Note: Range doesn't start exactly at the end of the remove range because there isn't | 
|  | // a keyframe there. The resulting range starts at the first keyframe >= the end time. | 
|  | removeAndCheckBufferedRanges(test, mediaSource, sourceBuffer, 0, 3, expectations[subType]); | 
|  | }, "Test removing beginning of appended data."); | 
|  |  | 
|  | removeAppendedDataTests(function(test, mediaSource, sourceBuffer, duration, subType) | 
|  | { | 
|  | var expectations = { | 
|  | webm: ("{ [0.000, 1.012) [3.187, " + duration + ") }"), | 
|  | mp4: ("{ [0.000, 1.022) [3.154, " + duration + ") }"), | 
|  | }; | 
|  |  | 
|  | // Note: The first resulting range ends slightly after start because the removal algorithm only removes | 
|  | // frames with a timestamp >= the start time. If a frame starts before and ends after the remove() start | 
|  | // timestamp, then it stays in the buffer. | 
|  | removeAndCheckBufferedRanges(test, mediaSource, sourceBuffer, 1, 3, expectations[subType]); | 
|  | }, "Test removing the middle of appended data."); | 
|  |  | 
|  | removeAppendedDataTests(function(test, mediaSource, sourceBuffer, duration, subType) | 
|  | { | 
|  | var expectations = { | 
|  | webm: "{ [0.000, 1.012) }", | 
|  | mp4: "{ [0.000, 1.029) }", | 
|  | }; | 
|  |  | 
|  | removeAndCheckBufferedRanges(test, mediaSource, sourceBuffer, 1, Number.POSITIVE_INFINITY, expectations[subType]); | 
|  | }, "Test removing the end of appended data."); | 
|  | </script> | 
|  | </body> | 
|  | </html> |