blob: f0b0ea45ca4cce67375f8a0e6b84ff19b295ea5c [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<title>media-source-seek-redundant-append</title>
<script src="media-source-loader.js"></script>
<script src="../video-test.js"></script>
<script>
var loader;
var source;
var sourceBuffer;
function waitSilentlyFor(element, type) {
return new Promise(resolve => {
element.addEventListener(type, event => {
resolve(event);
}, { once: true });
});
}
function waitForVideoToReach(time) {
return new Promise(resolve => {
consoleWrite(`START waitForVideoToReach(${time})`);
function timeupdateHandler() {
if (video.currentTime >= time) {
video.removeEventListener("timeupdate", timeupdateHandler);
consoleWrite(`SUCCESS waitForVideoToReach(${time})`);
resolve();
}
}
video.addEventListener("timeupdate", timeupdateHandler);
});
}
async function seekAndAppend(time, startSegment, endSegment) {
// Note: "seeked" and "update" can occur in any order because we may have noticed enough data to complete the
// seek before the whole append has been demuxed (demuxing occurs in a background thread and the main thread
// may be notified of new samples before the demuxer has finished the append).
// Therefore, we need to wait silently for these events in order for the test to have a reliable (non-flaky)
// output.
consoleWrite(`START seekAndAppend: time=${time}, segments=[${startSegment}, ${endSegment})`);
const seeked = waitSilentlyFor(mediaElement, "seeked");
mediaElement.currentTime = time;
for (let segmentNumber = startSegment; segmentNumber < endSegment; segmentNumber++) {
run(`sourceBuffer.appendBuffer(loader.mediaSegment(${segmentNumber}))`);
await waitSilentlyFor(sourceBuffer, 'update');
consoleWrite("Successful append");
}
await seeked;
consoleWrite(`SUCCESS seekAndAppend: time=${time}, segments=[${startSegment}, ${endSegment})`);
}
window.addEventListener('load', () => {
findMediaElement();
loader = new MediaSourceLoader('content/test-48khz-manifest.json');
loader.onload = async () => {
source = new MediaSource();
run('video.src = URL.createObjectURL(source)');
await waitFor(source, 'sourceopen');
const offset = 300;
run('sourceBuffer = source.addSourceBuffer(loader.type())');
run('sourceBuffer.appendBuffer(loader.initSegment())');
await waitFor(sourceBuffer, 'update');
run(`source.duration = ${offset + 10}`);
run(`sourceBuffer.timestampOffset = ${offset}`);
run('video.play()');
await seekAndAppend(offset, 0, 3); // Segment A
await waitForVideoToReach(offset + 0.2);
await seekAndAppend(offset + 9.2, 9, 10); // Segment C
await waitForVideoToReach(offset + 9.7);
run(`video.currentTime = ${offset + 8.9}`);
// Appending C again is redundant, but it should work.
await seekAndAppend(offset + 8.9, 8, 10); // Segment B+C
run('source.endOfStream()');
// After this point playback should finish in ~1.1 seconds (well under the timeout), not get stuck.
await waitFor(video, 'ended');
endTest();
};
loader.onerror = () => {
failTest('Media data loading failed');
};
});
</script>
</head>
<body>
<video controls></video>
</body>
</html>