<!DOCTYPE html> <!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> <html> <head> <title>SourceBuffer.appendBuffer() 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_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) { mediaElement.addEventListener('error', test.unreached_func("Unexpected event 'error'")); test.expectEvent(sourceBuffer, "updatestart", "Append started."); test.expectEvent(sourceBuffer, "update", "Append success."); test.expectEvent(sourceBuffer, "updateend", "Append ended."); sourceBuffer.appendBuffer(mediaData); assert_true(sourceBuffer.updating, "updating attribute is true"); test.waitForExpectedEvents(function() { assert_false(sourceBuffer.updating, "updating attribute is false"); test.done(); }); }, "Test SourceBuffer.appendBuffer() event dispatching."); mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) { mediaElement.addEventListener('error', test.unreached_func("Unexpected event 'error'")); test.expectEvent(sourceBuffer, "updatestart", "Append started."); test.expectEvent(sourceBuffer, "update", "Append success."); test.expectEvent(sourceBuffer, "updateend", "Append ended."); sourceBuffer.appendBuffer(mediaData); assert_true(sourceBuffer.updating, "updating attribute is true"); assert_throws("InvalidStateError", function() { sourceBuffer.appendBuffer(mediaData); }, "appendBuffer() throws an exception there is a pending append."); assert_true(sourceBuffer.updating, "updating attribute is true"); test.waitForExpectedEvents(function() { assert_false(sourceBuffer.updating, "updating attribute is false"); test.done(); }); }, "Test SourceBuffer.appendBuffer() call during a pending appendBuffer()."); mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) { mediaElement.addEventListener('error', test.unreached_func("Unexpected event 'error'")); test.expectEvent(sourceBuffer, "updatestart", "Append started."); test.expectEvent(sourceBuffer, "abort", "Append aborted."); test.expectEvent(sourceBuffer, "updateend", "Append ended."); sourceBuffer.appendBuffer(mediaData); assert_true(sourceBuffer.updating, "updating attribute is true"); sourceBuffer.abort(); assert_false(sourceBuffer.updating, "updating attribute is false"); test.waitForExpectedEvents(function() { assert_false(sourceBuffer.updating, "updating attribute is false"); test.done(); }); }, "Test SourceBuffer.abort() call during a pending appendBuffer()."); mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) { mediaElement.addEventListener('error', test.unreached_func("Unexpected event 'error'")); test.expectEvent(sourceBuffer, "updatestart", "Append started."); test.expectEvent(sourceBuffer, "update", "Append success."); test.expectEvent(sourceBuffer, "updateend", "Append ended."); sourceBuffer.appendBuffer(mediaData); assert_true(sourceBuffer.updating, "updating attribute is true"); test.waitForExpectedEvents(function() { assert_false(sourceBuffer.updating, "updating attribute is false"); test.expectEvent(mediaSource, "sourceended", "MediaSource sourceended event"); mediaSource.endOfStream(); assert_equals(mediaSource.readyState, "ended", "MediaSource readyState is 'ended'"); }); test.waitForExpectedEvents(function() { assert_equals(mediaSource.readyState, "ended", "MediaSource readyState is 'ended'"); test.expectEvent(mediaSource, "sourceopen", "MediaSource sourceopen event"); test.expectEvent(sourceBuffer, "updatestart", "Append started."); test.expectEvent(sourceBuffer, "update", "Append success."); test.expectEvent(sourceBuffer, "updateend", "Append ended."); sourceBuffer.appendBuffer(mediaData); assert_equals(mediaSource.readyState, "open", "MediaSource readyState is 'open'"); assert_true(sourceBuffer.updating, "updating attribute is true"); }); test.waitForExpectedEvents(function() { assert_equals(mediaSource.readyState, "open", "MediaSource readyState is 'open'"); assert_false(sourceBuffer.updating, "updating attribute is false"); test.done(); }); }, "Test SourceBuffer.appendBuffer() triggering an 'ended' to 'open' transition."); mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) { test.expectEvent(sourceBuffer, "updatestart", "Append started."); test.expectEvent(sourceBuffer, "update", "Append success."); test.expectEvent(sourceBuffer, "updateend", "Append ended."); sourceBuffer.appendBuffer(mediaData); assert_true(sourceBuffer.updating, "updating attribute is true"); test.waitForExpectedEvents(function() { assert_false(sourceBuffer.updating, "updating attribute is false"); test.expectEvent(mediaSource, "sourceended", "MediaSource sourceended event"); mediaSource.endOfStream(); assert_equals(mediaSource.readyState, "ended", "MediaSource readyState is 'ended'"); }); test.waitForExpectedEvents(function() { assert_equals(mediaSource.readyState, "ended", "MediaSource readyState is 'ended'"); test.expectEvent(mediaSource, "sourceopen", "MediaSource sourceopen event"); test.expectEvent(sourceBuffer, "updatestart", "Append started."); test.expectEvent(sourceBuffer, "update", "Append success."); test.expectEvent(sourceBuffer, "updateend", "Append ended."); sourceBuffer.appendBuffer(new Uint8Array(0)); assert_equals(mediaSource.readyState, "open", "MediaSource readyState is 'open'"); assert_true(sourceBuffer.updating, "updating attribute is true"); }); test.waitForExpectedEvents(function() { assert_equals(mediaSource.readyState, "open", "MediaSource readyState is 'open'"); assert_false(sourceBuffer.updating, "updating attribute is false"); test.done(); }); }, "Test zero byte SourceBuffer.appendBuffer() call triggering an 'ended' to 'open' transition."); mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) { mediaElement.addEventListener('error', test.unreached_func("Unexpected event 'error'")); test.expectEvent(sourceBuffer, "updatestart", "Append started."); test.expectEvent(sourceBuffer, "abort", "Append aborted."); test.expectEvent(sourceBuffer, "updateend", "Append ended."); sourceBuffer.appendBuffer(mediaData); assert_true(sourceBuffer.updating, "updating attribute is true"); assert_equals(mediaSource.activeSourceBuffers.length, 0, "activeSourceBuffers.length"); test.expectEvent(mediaSource.sourceBuffers, "removesourcebuffer", "sourceBuffers"); mediaSource.removeSourceBuffer(sourceBuffer); assert_false(sourceBuffer.updating, "updating attribute is false"); assert_throws("InvalidStateError", function() { sourceBuffer.appendBuffer(mediaData); }, "appendBuffer() throws an exception because it isn't attached to the mediaSource anymore."); test.waitForExpectedEvents(function() { assert_false(sourceBuffer.updating, "updating attribute is false"); test.done(); }); }, "Test MediaSource.removeSourceBuffer() call during a pending appendBuffer()."); mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) { mediaElement.addEventListener('error', test.unreached_func("Unexpected event 'error'")); test.expectEvent(sourceBuffer, "updatestart", "Append started."); test.expectEvent(sourceBuffer, "updateend", "Append ended."); sourceBuffer.appendBuffer(mediaData); assert_true(sourceBuffer.updating, "updating attribute is true"); assert_throws("InvalidStateError", function() { mediaSource.duration = 1.0; }, "set duration throws an exception when updating attribute is true."); test.waitForExpectedEvents(function() { assert_false(sourceBuffer.updating, "updating attribute is false"); test.done(); }); }, "Test set MediaSource.duration during a pending appendBuffer() for one of its SourceBuffers."); mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) { mediaElement.addEventListener("error", test.unreached_func("Unexpected event 'error'")); mediaSource.addEventListener("sourceended", test.unreached_func("Unexpected event 'sourceended'")); test.expectEvent(sourceBuffer, "updatestart", "Append started."); test.expectEvent(sourceBuffer, "updateend", "Append ended."); sourceBuffer.appendBuffer(mediaData); assert_true(sourceBuffer.updating, "updating attribute is true"); assert_throws("InvalidStateError", function() { mediaSource.endOfStream(); }, "endOfStream() throws an exception when updating attribute is true."); assert_equals(mediaSource.readyState, "open"); test.waitForExpectedEvents(function() { assert_false(sourceBuffer.updating, "updating attribute is false"); assert_equals(mediaSource.readyState, "open"); test.done(); }); }, "Test MediaSource.endOfStream() during a pending appendBuffer() for one of its SourceBuffers."); mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) { mediaElement.addEventListener('error', test.unreached_func("Unexpected event 'error'")); test.expectEvent(sourceBuffer, "updatestart", "Append started."); test.expectEvent(sourceBuffer, "updateend", "Append ended."); sourceBuffer.appendBuffer(mediaData); assert_true(sourceBuffer.updating, "updating attribute is true"); assert_throws("InvalidStateError", function() { sourceBuffer.timestampOffset = 10.0; }, "set timestampOffset throws an exception when updating attribute is true."); test.waitForExpectedEvents(function() { assert_false(sourceBuffer.updating, "updating attribute is false"); test.done(); }); }, "Test set SourceBuffer.timestampOffset during a pending appendBuffer()."); mediasource_test(function(test, mediaElement, mediaSource) { var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.VIDEO_ONLY_TYPE); test.expectEvent(sourceBuffer, "updatestart", "Append started."); test.expectEvent(sourceBuffer, "update", "Append success."); test.expectEvent(sourceBuffer, "updateend", "Append ended."); sourceBuffer.appendBuffer(new Uint8Array(0)); assert_true(sourceBuffer.updating, "updating attribute is true"); test.waitForExpectedEvents(function() { assert_false(sourceBuffer.updating, "updating attribute is false"); test.done(); }); }, "Test appending an empty ArrayBufferView."); mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) { test.expectEvent(sourceBuffer, "updatestart", "Append started."); test.expectEvent(sourceBuffer, "update", "Append success."); test.expectEvent(sourceBuffer, "updateend", "Append ended."); var arrayBufferView = new Uint8Array(mediaData); assert_equals(arrayBufferView.length, mediaData.length, "arrayBufferView.length before transfer."); // Send the buffer as in a message so it gets neutered. window.postMessage( "test", "*", [arrayBufferView.buffer]); assert_equals(arrayBufferView.length, 0, "arrayBufferView.length after transfer."); sourceBuffer.appendBuffer(arrayBufferView); assert_true(sourceBuffer.updating, "updating attribute is true"); test.waitForExpectedEvents(function() { assert_false(sourceBuffer.updating, "updating attribute is false"); test.done(); }); }, "Test appending a neutered ArrayBufferView."); mediasource_test(function(test, mediaElement, mediaSource) { var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.VIDEO_ONLY_TYPE); test.expectEvent(sourceBuffer, "updatestart", "Append started."); test.expectEvent(sourceBuffer, "update", "Append success."); test.expectEvent(sourceBuffer, "updateend", "Append ended."); sourceBuffer.appendBuffer(new ArrayBuffer(0)); assert_true(sourceBuffer.updating, "updating attribute is true"); test.waitForExpectedEvents(function() { assert_false(sourceBuffer.updating, "updating attribute is false"); test.done(); }); }, "Test appending an empty ArrayBuffer."); mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) { test.expectEvent(sourceBuffer, "updatestart", "Append started."); test.expectEvent(sourceBuffer, "update", "Append success."); test.expectEvent(sourceBuffer, "updateend", "Append ended."); var arrayBuffer = mediaData.buffer.slice(0); assert_equals(arrayBuffer.byteLength, mediaData.buffer.byteLength, "arrayBuffer.byteLength before transfer."); // Send the buffer as in a message so it gets neutered. window.postMessage( "test", "*", [arrayBuffer]); assert_equals(arrayBuffer.byteLength, 0, "arrayBuffer.byteLength after transfer."); sourceBuffer.appendBuffer(arrayBuffer); assert_true(sourceBuffer.updating, "updating attribute is true"); test.waitForExpectedEvents(function() { assert_false(sourceBuffer.updating, "updating attribute is false"); test.done(); }); }, "Test appending a neutered ArrayBuffer."); mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) { var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init); var halfIndex = (initSegment.length + 1) / 2; var partialInitSegment = initSegment.subarray(0, halfIndex); var remainingInitSegment = initSegment.subarray(halfIndex); var mediaSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[0]); test.expectEvent(sourceBuffer, "updateend", "partialInitSegment append ended."); sourceBuffer.appendBuffer(partialInitSegment); test.waitForExpectedEvents(function() { assert_equals(mediaElement.readyState, mediaElement.HAVE_NOTHING); assert_equals(mediaSource.duration, Number.NaN); test.expectEvent(sourceBuffer, "updateend", "remainingInitSegment append ended."); test.expectEvent(mediaElement, "loadedmetadata", "loadedmetadata event received."); sourceBuffer.appendBuffer(remainingInitSegment); }); test.waitForExpectedEvents(function() { assert_equals(mediaElement.readyState, mediaElement.HAVE_METADATA); assert_equals(mediaSource.duration, segmentInfo.duration); test.expectEvent(sourceBuffer, "updateend", "mediaSegment append ended."); test.expectEvent(mediaElement, "loadeddata", "loadeddata fired."); sourceBuffer.appendBuffer(mediaSegment); }); test.waitForExpectedEvents(function() { assert_greater_than_equal(mediaElement.readyState, mediaElement.HAVE_CURRENT_DATA); assert_equals(sourceBuffer.updating, false); assert_equals(mediaSource.readyState, "open"); test.done(); }); }, "Test appendBuffer with partial init segments."); mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) { var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init); var mediaSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[0]); var halfIndex = (mediaSegment.length + 1) / 2; var partialMediaSegment = mediaSegment.subarray(0, halfIndex); var remainingMediaSegment = mediaSegment.subarray(halfIndex); test.expectEvent(sourceBuffer, "updateend", "InitSegment append ended."); test.expectEvent(mediaElement, "loadedmetadata", "loadedmetadata done."); sourceBuffer.appendBuffer(initSegment); test.waitForExpectedEvents(function() { assert_equals(mediaElement.readyState, mediaElement.HAVE_METADATA); assert_equals(mediaSource.duration, segmentInfo.duration); test.expectEvent(sourceBuffer, "updateend", "partial media segment append ended."); sourceBuffer.appendBuffer(partialMediaSegment); }); test.waitForExpectedEvents(function() { test.expectEvent(sourceBuffer, "updateend", "mediaSegment append ended."); test.expectEvent(mediaElement, "loadeddata", "loadeddata fired."); sourceBuffer.appendBuffer(remainingMediaSegment); }); test.waitForExpectedEvents(function() { assert_greater_than_equal(mediaElement.readyState, mediaElement.HAVE_CURRENT_DATA); assert_equals(mediaSource.readyState, "open"); assert_equals(sourceBuffer.updating, false); test.done(); }); }, "Test appendBuffer with partial media segments."); mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) { var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init); var partialInitSegment = initSegment.subarray(0, initSegment.length / 2); var mediaSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[0]); test.expectEvent(sourceBuffer, "updateend", "partialInitSegment append ended."); sourceBuffer.appendBuffer(partialInitSegment); test.waitForExpectedEvents(function() { // Call abort to reset the parser. sourceBuffer.abort(); // Append the full intiialization segment. test.expectEvent(sourceBuffer, "updateend", "initSegment append ended."); sourceBuffer.appendBuffer(initSegment); }); test.waitForExpectedEvents(function() { test.expectEvent(sourceBuffer, "updateend", "mediaSegment append ended."); test.expectEvent(mediaElement, "loadeddata", "loadeddata fired."); sourceBuffer.appendBuffer(mediaSegment); }); test.waitForExpectedEvents(function() { test.done(); }); }, "Test abort in the middle of an initialization segment."); mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) { test.expectEvent(mediaSource.sourceBuffers, "removesourcebuffer", "SourceBuffer removed."); mediaSource.removeSourceBuffer(sourceBuffer); test.waitForExpectedEvents(function() { assert_throws("InvalidStateError", function() { sourceBuffer.abort(); }, "sourceBuffer.abort() throws an exception for InvalidStateError."); test.done(); }); }, "Test abort after removing sourcebuffer."); mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) { var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init); var mediaSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[0]); test.expectEvent(sourceBuffer, "updateend", "initSegment append ended."); sourceBuffer.appendBuffer(initSegment); test.waitForExpectedEvents(function() { assert_equals(mediaSource.readyState, "open", "readyState is open after init segment appended."); test.expectEvent(sourceBuffer, "updateend", "mediaSegment append ended."); sourceBuffer.appendBuffer(mediaSegment); }); test.waitForExpectedEvents(function() { assert_equals(sourceBuffer.buffered.length, 1, "sourceBuffer has a buffered range"); assert_equals(mediaSource.readyState, "open", "readyState is open after media segment appended."); test.expectEvent(mediaSource, "sourceended", "source ended"); mediaSource.endOfStream(); }); test.waitForExpectedEvents(function() { assert_equals(mediaSource.readyState, "ended", "readyState is ended."); assert_throws("InvalidStateError", function() { sourceBuffer.abort(); }, "sourceBuffer.abort() throws an exception for InvalidStateError."); test.done(); }); }, "Test abort after readyState is ended following init segment and media segment."); mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) { test.expectEvent(sourceBuffer, "updatestart", "Append started."); test.expectEvent(sourceBuffer, "updateend", "Append ended."); sourceBuffer.appendWindowStart = 1; sourceBuffer.appendWindowEnd = 100; sourceBuffer.appendBuffer(mediaData); test.waitForExpectedEvents(function() { assert_false(sourceBuffer.updating, "updating attribute is false"); sourceBuffer.abort(); assert_equals(sourceBuffer.appendWindowStart, 0, "appendWindowStart is reset to 0"); assert_equals(sourceBuffer.appendWindowEnd, Number.POSITIVE_INFINITY, "appendWindowEnd is reset to +INFINITY"); test.done(); }); }, "Test abort after appendBuffer update ends."); mediasource_test(function(test, mediaElement, mediaSource) { var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.VIDEO_ONLY_TYPE); test.expectEvent(sourceBuffer, "updatestart", "Append started."); test.expectEvent(sourceBuffer, "update", "Append success."); test.expectEvent(sourceBuffer, "updateend", "Append ended."); assert_throws( { name: "TypeError"} , function() { sourceBuffer.appendBuffer(null); }, "appendBuffer(null) throws an exception."); test.done(); }, "Test appending null."); mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData) { mediaSource.removeSourceBuffer(sourceBuffer); assert_throws( { name: "InvalidStateError"} , function() { sourceBuffer.appendBuffer(mediaData); }, "appendBuffer() throws an exception when called after removeSourceBuffer()."); test.done(); }, "Test appending after removeSourceBuffer()."); </script> </body> </html>