blob: f1866c005e5dcab26c71d20ece86c7362978cf88 [file] [log] [blame]
<!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 mediaSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[0]);
assert_equals(mediaElement.readyState, mediaElement.HAVE_NOTHING);
assert_equals(mediaSource.duration, Number.NaN);
// readyState is changing as per the Initialization Segment Received algorithm.
var loadedmetadataCalled = false;
mediaElement.addEventListener("loadedmetadata", function metadata(e) {
loadedmetadataCalled = true;
e.target.removeEventListener(e.type, metadata);
});
sourceBuffer.addEventListener("updateend", function updateend(e) {
assert_true(loadedmetadataCalled);
assert_equals(mediaElement.readyState, mediaElement.HAVE_METADATA);
e.target.removeEventListener(e.type, updateend);
});
test.expectEvent(sourceBuffer, "updateend", "remainingInitSegment append ended.");
test.expectEvent(mediaElement, "loadedmetadata", "loadedmetadata event received.");
sourceBuffer.appendBuffer(initSegment);
test.waitForExpectedEvents(function()
{
assert_equals(mediaElement.readyState, mediaElement.HAVE_METADATA);
assert_equals(mediaSource.duration, segmentInfo.duration);
// readyState is changing as per the Coded Frame Processing algorithm.
var loadeddataCalled = false;
mediaElement.addEventListener("loadeddata", function loadeddata(e) {
loadeddataCalled = true;
e.target.removeEventListener(e.type, loadeddata);
});
sourceBuffer.addEventListener("updateend", function updateend(e) {
assert_true(loadeddataCalled);
assert_greater_than_equal(mediaElement.readyState, mediaElement.HAVE_CURRENT_DATA);
e.target.removeEventListener(e.type, updateend);
});
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 events order.");
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>