<!DOCTYPE html> <!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> <html> <head> <meta charset="utf-8"> <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); mediaSource.duration = 10; assert_throws(new TypeError(), 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); mediaSource.duration = 10; [ 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(new TypeError(), 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(new TypeError(), 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); mediaSource.duration = 10; assert_throws(new TypeError(), 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); mediaSource.duration = 10; assert_throws(new TypeError(), 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); assert_false(sourceBuffer.updating, "updating is false"); assert_equals(mediaSource.duration, NaN, "duration isn't set"); assert_throws(new TypeError(), function() { sourceBuffer.remove(0, 0); }, "remove"); test.done(); }, "Test remove with a NaN duration."); 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, "update"); test.expectEvent(sourceBuffer, "updateend"); sourceBuffer.remove(1, 2); assert_true(sourceBuffer.updating, "updating"); assert_throws("InvalidStateError", function() { sourceBuffer.abort(); }, "abort"); assert_true(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"); test.expectEvent(mediaSource, "sourceopen"); 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 start = Math.max(segmentInfo.media[0].timev, segmentInfo.media[0].timea).toFixed(3); var duration = mediaElement.duration.toFixed(3); var subType = MediaSourceUtil.getSubType(segmentInfo.type); assertBufferedEquals(sourceBuffer, "{ [" + start + ", " + duration + ") }", "Initial buffered range."); callback(test, mediaSource, sourceBuffer, duration, subType, segmentInfo); }); }, 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, segmentInfo) { removeAndCheckBufferedRanges(test, mediaSource, sourceBuffer, 0, Number.POSITIVE_INFINITY, "{ }"); }, "Test removing all appended data."); removeAppendedDataTests(function(test, mediaSource, sourceBuffer, duration, subType, segmentInfo) { var expectations = { webm: ("{ [3.315, " + duration + ") }"), mp4: ("{ [3.298, " + 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, segmentInfo) { var start = Math.max(segmentInfo.media[0].timev, segmentInfo.media[0].timea).toFixed(3); var expectations = { webm: ("{ [" + start + ", 1.005) [3.315, " + duration + ") }"), mp4: ("{ [" + start + ", 0.997) [3.298, " + 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, segmentInfo) { var start = Math.max(segmentInfo.media[0].timev, segmentInfo.media[0].timea).toFixed(3); var expectations = { webm: "{ [" + start + ", 1.013) }", mp4: "{ [" + start + ", 1.022) }", }; removeAndCheckBufferedRanges(test, mediaSource, sourceBuffer, 1, Number.POSITIVE_INFINITY, expectations[subType]); }, "Test removing the end of appended data."); </script> </body> </html>