mirror of
https://github.com/servo/servo.git
synced 2025-10-04 02:29:12 +01:00
Update web-platform-tests to revision dc5cbf088edcdb266541d4e5a76149a2c6e716a0
This commit is contained in:
parent
1d40075f03
commit
079092dfea
2381 changed files with 90360 additions and 17722 deletions
|
@ -1,5 +1,3 @@
|
|||
@bit
|
||||
@acolwell
|
||||
@shishimaru
|
||||
@sideshowbarker
|
||||
@wolenetz
|
||||
|
|
|
@ -15,101 +15,74 @@ interface EventTarget {
|
|||
interface URL {};
|
||||
interface HTMLVideoElement {};
|
||||
interface AudioTrack {};
|
||||
interface AudioTrackList {};
|
||||
interface VideoTrack {};
|
||||
interface VideoTrackList {};
|
||||
interface TextTrack {};
|
||||
interface TextTrackList {};
|
||||
interface TimeRanges {};
|
||||
typedef double DOMHighResTimeStamp;
|
||||
</script>
|
||||
<script type=text/plain>
|
||||
[Constructor]
|
||||
interface MediaSource : EventTarget {
|
||||
readonly attribute SourceBufferList sourceBuffers;
|
||||
readonly attribute SourceBufferList activeSourceBuffers;
|
||||
readonly attribute ReadyState readyState;
|
||||
attribute unrestricted double duration;
|
||||
attribute EventHandler onsourceopen;
|
||||
attribute EventHandler onsourceended;
|
||||
attribute EventHandler onsourceclose;
|
||||
SourceBuffer addSourceBuffer (DOMString type);
|
||||
void removeSourceBuffer (SourceBuffer sourceBuffer);
|
||||
void endOfStream (optional EndOfStreamError error);
|
||||
void setLiveSeekableRange (double start, double end);
|
||||
void clearLiveSeekableRange ();
|
||||
static boolean isTypeSupported (DOMString type);
|
||||
readonly attribute SourceBufferList sourceBuffers;
|
||||
readonly attribute SourceBufferList activeSourceBuffers;
|
||||
readonly attribute ReadyState readyState;
|
||||
attribute unrestricted double duration;
|
||||
attribute EventHandler onsourceopen;
|
||||
attribute EventHandler onsourceended;
|
||||
attribute EventHandler onsourceclose;
|
||||
SourceBuffer addSourceBuffer(DOMString type);
|
||||
void removeSourceBuffer(SourceBuffer sourceBuffer);
|
||||
void endOfStream(optional EndOfStreamError error);
|
||||
void setLiveSeekableRange(double start, double end);
|
||||
void clearLiveSeekableRange();
|
||||
static boolean isTypeSupported(DOMString type);
|
||||
};
|
||||
|
||||
interface SourceBuffer : EventTarget {
|
||||
attribute AppendMode mode;
|
||||
readonly attribute boolean updating;
|
||||
readonly attribute TimeRanges buffered;
|
||||
attribute double timestampOffset;
|
||||
readonly attribute AudioTrackList audioTracks;
|
||||
readonly attribute VideoTrackList videoTracks;
|
||||
readonly attribute TextTrackList textTracks;
|
||||
attribute double appendWindowStart;
|
||||
attribute unrestricted double appendWindowEnd;
|
||||
attribute EventHandler onupdatestart;
|
||||
attribute EventHandler onupdate;
|
||||
attribute EventHandler onupdateend;
|
||||
attribute EventHandler onerror;
|
||||
attribute EventHandler onabort;
|
||||
void appendBuffer (ArrayBuffer data);
|
||||
void appendBuffer (ArrayBufferView data);
|
||||
void appendStream (ReadableStream stream, [EnforceRange] optional unsigned long long maxSize);
|
||||
void abort ();
|
||||
void remove (double start, unrestricted double end);
|
||||
attribute TrackDefaultList trackDefaults;
|
||||
attribute AppendMode mode;
|
||||
readonly attribute boolean updating;
|
||||
readonly attribute TimeRanges buffered;
|
||||
attribute double timestampOffset;
|
||||
readonly attribute AudioTrackList audioTracks;
|
||||
readonly attribute VideoTrackList videoTracks;
|
||||
readonly attribute TextTrackList textTracks;
|
||||
attribute double appendWindowStart;
|
||||
attribute unrestricted double appendWindowEnd;
|
||||
attribute EventHandler onupdatestart;
|
||||
attribute EventHandler onupdate;
|
||||
attribute EventHandler onupdateend;
|
||||
attribute EventHandler onerror;
|
||||
attribute EventHandler onabort;
|
||||
void appendBuffer(BufferSource data);
|
||||
void abort();
|
||||
void remove(double start, unrestricted double end);
|
||||
};
|
||||
|
||||
interface SourceBufferList : EventTarget {
|
||||
readonly attribute unsigned long length;
|
||||
attribute EventHandler onaddsourcebuffer;
|
||||
attribute EventHandler onremovesourcebuffer;
|
||||
readonly attribute unsigned long length;
|
||||
attribute EventHandler onaddsourcebuffer;
|
||||
attribute EventHandler onremovesourcebuffer;
|
||||
getter SourceBuffer (unsigned long index);
|
||||
};
|
||||
|
||||
interface VideoPlaybackQuality {
|
||||
readonly attribute DOMHighResTimeStamp creationTime;
|
||||
readonly attribute unsigned long totalVideoFrames;
|
||||
readonly attribute unsigned long droppedVideoFrames;
|
||||
readonly attribute unsigned long corruptedVideoFrames;
|
||||
readonly attribute double totalFrameDelay;
|
||||
};
|
||||
|
||||
[ Constructor (TrackDefaultType type, DOMString language, DOMString label, sequence<DOMString> kinds, optional DOMString byteStreamTrackID = "")]
|
||||
interface TrackDefault {
|
||||
readonly attribute TrackDefaultType type;
|
||||
readonly attribute DOMString byteStreamTrackID;
|
||||
readonly attribute DOMString language;
|
||||
readonly attribute DOMString label;
|
||||
sequence<DOMString> getKinds ();
|
||||
};
|
||||
|
||||
[ Constructor (optional sequence<TrackDefault> trackDefaults = [])]
|
||||
interface TrackDefaultList {
|
||||
readonly attribute unsigned long length;
|
||||
getter TrackDefault (unsigned long index);
|
||||
};
|
||||
|
||||
[Exposed=Window,DedicatedWorker,SharedWorker]
|
||||
partial interface URL {
|
||||
static DOMString createObjectURL (MediaSource mediaSource);
|
||||
};
|
||||
|
||||
partial interface HTMLVideoElement {
|
||||
VideoPlaybackQuality getVideoPlaybackQuality ();
|
||||
static DOMString createObjectURL(MediaSource mediaSource);
|
||||
};
|
||||
|
||||
partial interface AudioTrack {
|
||||
readonly attribute SourceBuffer? sourceBuffer;
|
||||
readonly attribute SourceBuffer? sourceBuffer;
|
||||
};
|
||||
|
||||
partial interface VideoTrack {
|
||||
readonly attribute SourceBuffer? sourceBuffer;
|
||||
readonly attribute SourceBuffer? sourceBuffer;
|
||||
};
|
||||
|
||||
partial interface TextTrack {
|
||||
readonly attribute SourceBuffer? sourceBuffer;
|
||||
readonly attribute SourceBuffer? sourceBuffer;
|
||||
};
|
||||
|
||||
enum EndOfStreamError {
|
||||
|
@ -127,15 +100,10 @@ enum ReadyState {
|
|||
"open",
|
||||
"ended"
|
||||
};
|
||||
|
||||
enum TrackDefaultType {
|
||||
"audio",
|
||||
"video",
|
||||
"text"
|
||||
};
|
||||
</script>
|
||||
<script>
|
||||
"use strict";
|
||||
setup({ explicit_done: true });
|
||||
var mediaSource;
|
||||
var sourceBuffer;
|
||||
var video = document.createElement("video");
|
||||
|
@ -151,11 +119,10 @@ var idlCheck = function() {
|
|||
idlArray.add_objects({
|
||||
MediaSource: ['mediaSource'],
|
||||
SourceBuffer: ['sourceBuffer'],
|
||||
SourceBufferList: ['mediaSource.sourceBuffers'],
|
||||
VideoPlaybackQuality: ['video.getVideoPlaybackQuality()'],
|
||||
TrackDefaultList: ['sourceBuffer.trackDefaults']
|
||||
SourceBufferList: ['mediaSource.sourceBuffers']
|
||||
});
|
||||
idlArray.test();
|
||||
done();
|
||||
}
|
||||
mediaSource = new MediaSource();
|
||||
video.src = URL.createObjectURL(mediaSource);
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
interfaces.html
|
||||
mediasource-activesourcebuffers.html
|
||||
mediasource-addsourcebuffer.html
|
||||
mediasource-addsourcebuffer-mode.html
|
||||
mediasource-append-buffer.html
|
||||
mediasource-appendbuffer-quota-exceeded.html
|
||||
mediasource-appendwindow.html
|
||||
mediasource-attach-stops-delaying-load-event.html
|
||||
mediasource-avtracks.html
|
||||
mediasource-buffered.html
|
||||
mediasource-closed.html
|
||||
mediasource-config-change-mp4-a-bitrate.html
|
||||
|
@ -17,16 +23,33 @@ mediasource-config-change-webm-av-video-bitrate.html
|
|||
mediasource-config-change-webm-v-bitrate.html
|
||||
mediasource-config-change-webm-v-framerate.html
|
||||
mediasource-config-change-webm-v-framesize.html
|
||||
mediasource-detach.html
|
||||
mediasource-duration-boundaryconditions.html
|
||||
mediasource-duration.html
|
||||
mediasource-endofstream.html
|
||||
mediasource-endofstream-invaliderror.html
|
||||
mediasource-getvideoplaybackquality.html
|
||||
mediasource-errors.html
|
||||
mediasource-is-type-supported.html
|
||||
mediasource-liveseekable.html
|
||||
mediasource-multiple-attach.html
|
||||
mediasource-play.html
|
||||
mediasource-play-then-seek-back.html
|
||||
mediasource-preload.html
|
||||
mediasource-redundant-seek.html
|
||||
mediasource-remove.html
|
||||
mediasource-removesourcebuffer.html
|
||||
mediasource-seekable.html
|
||||
mediasource-seek-beyond-duration.html
|
||||
mediasource-seek-during-pending-seek.html
|
||||
mediasource-sequencemode-append-buffer.html
|
||||
mediasource-sourcebufferlist.html
|
||||
mediasource-sourcebuffer-mode.html
|
||||
mediasource-sourcebuffer-mode-timestamps.html
|
||||
mediasource-timestamp-offset.html
|
||||
SourceBuffer-abort.html
|
||||
SourceBuffer-abort-readyState.html
|
||||
SourceBuffer-abort-removed.html
|
||||
SourceBuffer-abort-updating.html
|
||||
URL-createObjectURL.html
|
||||
URL-createObjectURL-null.html
|
||||
URL-createObjectURL-revoke.html
|
||||
|
|
|
@ -0,0 +1,238 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Checks MediaSource.activeSourceBuffers and changes to selected/enabled track state</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>
|
||||
// Audio / Video files supported by the user agent under test
|
||||
var subType = MediaSourceUtil.getSubType(MediaSourceUtil.AUDIO_ONLY_TYPE);
|
||||
var manifestFilenameAudio = subType + "/test-a-128k-44100Hz-1ch-manifest.json";
|
||||
var manifestFilenameVideo = subType + "/test-v-128k-320x240-30fps-10kfr-manifest.json";
|
||||
var manifestFilenameAV = subType + "/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr-manifest.json";
|
||||
|
||||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
{
|
||||
mediaElement.addEventListener("error", test.unreached_func("Unexpected event 'error'"));
|
||||
MediaSourceUtil.fetchManifestAndData(test, manifestFilenameAudio, function (typeAudio, dataAudio)
|
||||
{
|
||||
var sourceBuffer = mediaSource.addSourceBuffer(typeAudio);
|
||||
assert_equals(mediaSource.sourceBuffers.length, 1,
|
||||
"sourceBuffers list contains one SourceBuffer");
|
||||
assert_equals(mediaSource.activeSourceBuffers.length, 0,
|
||||
"activeSourceBuffers is empty to start with");
|
||||
|
||||
test.expectEvent(mediaSource.activeSourceBuffers, "addsourcebuffer");
|
||||
test.expectEvent(mediaElement, "loadedmetadata");
|
||||
sourceBuffer.appendBuffer(dataAudio);
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_equals(mediaSource.activeSourceBuffers.length, 1,
|
||||
"activeSourceBuffers updated when media element is loaded");
|
||||
assert_equals(mediaSource.activeSourceBuffers[0], sourceBuffer,
|
||||
"activeSourceBuffers contains sourceBuffer when media element is loaded");
|
||||
test.done();
|
||||
});
|
||||
});
|
||||
}, "SourceBuffer added to activeSourceBuffers list when its only audio track gets loaded (and thus becomes enabled).");
|
||||
|
||||
|
||||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
{
|
||||
mediaElement.addEventListener("error", test.unreached_func("Unexpected event 'error'"));
|
||||
MediaSourceUtil.fetchManifestAndData(test, manifestFilenameVideo, function (typeVideo, dataVideo)
|
||||
{
|
||||
var sourceBuffer = mediaSource.addSourceBuffer(typeVideo);
|
||||
assert_equals(mediaSource.sourceBuffers.length, 1,
|
||||
"sourceBuffers list contains one SourceBuffer");
|
||||
assert_equals(mediaSource.activeSourceBuffers.length, 0,
|
||||
"activeSourceBuffers is empty to start with");
|
||||
|
||||
test.expectEvent(mediaSource.activeSourceBuffers, "addsourcebuffer");
|
||||
test.expectEvent(mediaElement, "loadedmetadata");
|
||||
sourceBuffer.appendBuffer(dataVideo);
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_equals(mediaSource.activeSourceBuffers.length, 1,
|
||||
"activeSourceBuffers updated when media element is loaded");
|
||||
assert_equals(mediaSource.activeSourceBuffers[0], sourceBuffer,
|
||||
"activeSourceBuffers contains sourceBuffer when media element is loaded");
|
||||
test.done();
|
||||
});
|
||||
});
|
||||
}, "SourceBuffer added to activeSourceBuffers list when its only video track gets loaded (and thus becomes selected).");
|
||||
|
||||
function mediaSourceActiveSourceBufferOrderTest(addAudioFirst, appendAudioFirst)
|
||||
{
|
||||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
{
|
||||
mediaElement.addEventListener("error", test.unreached_func("Unexpected event 'error'"));
|
||||
MediaSourceUtil.fetchManifestAndData(test, manifestFilenameAudio, function (typeAudio, dataAudio)
|
||||
{
|
||||
MediaSourceUtil.fetchManifestAndData(test, manifestFilenameVideo, function (typeVideo, dataVideo)
|
||||
{
|
||||
var sourceBufferAudio, sourceBufferVideo, expectedFirstSB, expectedSecondSB;
|
||||
if (addAudioFirst) {
|
||||
expectedFirstSB = sourceBufferAudio = mediaSource.addSourceBuffer(typeAudio);
|
||||
expectedSecondSB = sourceBufferVideo = mediaSource.addSourceBuffer(typeVideo);
|
||||
} else {
|
||||
expectedFirstSB = sourceBufferVideo = mediaSource.addSourceBuffer(typeVideo);
|
||||
expectedSecondSB = sourceBufferAudio = mediaSource.addSourceBuffer(typeAudio);
|
||||
}
|
||||
|
||||
assert_equals(mediaSource.activeSourceBuffers.length, 0,
|
||||
"activeSourceBuffers is empty to start with");
|
||||
assert_equals(mediaSource.sourceBuffers.length, 2,
|
||||
"sourceBuffers list contains both SourceBuffers");
|
||||
assert_equals(mediaSource.sourceBuffers[0], expectedFirstSB,
|
||||
"first SourceBuffer matches expectation");
|
||||
assert_equals(mediaSource.sourceBuffers[1], expectedSecondSB,
|
||||
"second SourceBuffer matches expectation");
|
||||
test.expectEvent(mediaSource.activeSourceBuffers, "addsourcebuffer");
|
||||
test.expectEvent(mediaSource.activeSourceBuffers, "addsourcebuffer");
|
||||
test.expectEvent(mediaElement, "loadedmetadata");
|
||||
if (appendAudioFirst) {
|
||||
sourceBufferAudio.appendBuffer(dataAudio);
|
||||
sourceBufferVideo.appendBuffer(dataVideo);
|
||||
} else {
|
||||
sourceBufferVideo.appendBuffer(dataVideo);
|
||||
sourceBufferAudio.appendBuffer(dataAudio);
|
||||
}
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_equals(mediaSource.activeSourceBuffers.length, 2,
|
||||
"activeSourceBuffers list updated when tracks are loaded");
|
||||
assert_equals(mediaSource.activeSourceBuffers[0], mediaSource.sourceBuffers[0],
|
||||
"first active SourceBuffer matches first SourceBuffer");
|
||||
assert_equals(mediaSource.activeSourceBuffers[1], mediaSource.sourceBuffers[1],
|
||||
"second active SourceBuffer matches second SourceBuffer");
|
||||
test.done();
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
"Active SourceBuffers must appear in the same order as they appear in the sourceBuffers attribute: " +
|
||||
(addAudioFirst ? "audio is first sourceBuffer" : "video is first sourceBuffer") + ", " +
|
||||
(appendAudioFirst ? "audio media appended first" : "video media appended first"));
|
||||
}
|
||||
|
||||
mediaSourceActiveSourceBufferOrderTest(true, true);
|
||||
mediaSourceActiveSourceBufferOrderTest(true, false);
|
||||
mediaSourceActiveSourceBufferOrderTest(false, true);
|
||||
mediaSourceActiveSourceBufferOrderTest(false, false);
|
||||
|
||||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
{
|
||||
mediaElement.addEventListener("error", test.unreached_func("Unexpected event 'error'"));
|
||||
MediaSourceUtil.fetchManifestAndData(test, manifestFilenameAudio, function (typeAudio, dataAudio)
|
||||
{
|
||||
MediaSourceUtil.fetchManifestAndData(test, manifestFilenameVideo, function (typeVideo, dataVideo)
|
||||
{
|
||||
var sourceBufferAudio = mediaSource.addSourceBuffer(typeAudio);
|
||||
var sourceBufferVideo = mediaSource.addSourceBuffer(typeVideo);
|
||||
|
||||
test.expectEvent(sourceBufferAudio.audioTracks, "addtrack");
|
||||
test.expectEvent(sourceBufferVideo.videoTracks, "addtrack");
|
||||
sourceBufferAudio.appendBuffer(dataAudio);
|
||||
sourceBufferVideo.appendBuffer(dataVideo);
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_equals(mediaSource.activeSourceBuffers.length, 2,
|
||||
"activeSourceBuffers list updated when tracks are loaded");
|
||||
assert_equals(sourceBufferAudio.audioTracks.length, 1,
|
||||
"audio track list contains loaded audio track");
|
||||
assert_equals(sourceBufferVideo.videoTracks.length, 1,
|
||||
"video track list contains loaded video track");
|
||||
|
||||
test.expectEvent(mediaSource.activeSourceBuffers, "removesourcebuffer");
|
||||
sourceBufferAudio.audioTracks[0].enabled = false;
|
||||
});
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_equals(mediaSource.activeSourceBuffers.length, 1,
|
||||
"audio source buffer no longer in the activeSourceBuffers list");
|
||||
assert_equals(mediaSource.activeSourceBuffers[0], sourceBufferVideo,
|
||||
"activeSourceBuffers list only contains the video SourceBuffer");
|
||||
|
||||
test.expectEvent(mediaSource.activeSourceBuffers, "addsourcebuffer");
|
||||
test.expectEvent(mediaSource.activeSourceBuffers, "removesourcebuffer");
|
||||
sourceBufferAudio.audioTracks[0].enabled = true;
|
||||
sourceBufferVideo.videoTracks[0].selected = false;
|
||||
});
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_equals(mediaSource.activeSourceBuffers.length, 1,
|
||||
"video source buffer no longer in the activeSourceBuffers list");
|
||||
assert_equals(mediaSource.activeSourceBuffers[0], sourceBufferAudio,
|
||||
"activeSourceBuffers list only contains the audio SourceBuffer");
|
||||
test.done();
|
||||
});
|
||||
});
|
||||
});
|
||||
}, "Active SourceBuffers list reflects changes to selected audio/video tracks associated with separate SourceBuffers.");
|
||||
|
||||
|
||||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
{
|
||||
mediaElement.addEventListener("error", test.unreached_func("Unexpected event 'error'"));
|
||||
MediaSourceUtil.fetchManifestAndData(test, manifestFilenameAV, function (typeAV, dataAV)
|
||||
{
|
||||
var sourceBuffer = mediaSource.addSourceBuffer(typeAV);
|
||||
|
||||
test.expectEvent(sourceBuffer.audioTracks, "addtrack");
|
||||
test.expectEvent(sourceBuffer.videoTracks, "addtrack");
|
||||
sourceBuffer.appendBuffer(dataAV);
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_equals(mediaSource.activeSourceBuffers.length, 1,
|
||||
"activeSourceBuffers list updated when tracks are loaded");
|
||||
assert_equals(sourceBuffer.audioTracks.length, 1,
|
||||
"audio track list contains loaded audio track");
|
||||
assert_equals(sourceBuffer.videoTracks.length, 1,
|
||||
"video track list contains loaded video track");
|
||||
|
||||
mediaSource.activeSourceBuffers.addEventListener("removesourcebuffer", test.unreached_func(
|
||||
"Unexpected removal from activeSourceBuffers list"));
|
||||
mediaSource.activeSourceBuffers.addEventListener("addsourcebuffer", test.unreached_func(
|
||||
"Unexpected insertion in activeSourceBuffers list"));
|
||||
|
||||
// Changes should only trigger events at the
|
||||
// AudioTrack/VideoTrack instance
|
||||
test.expectEvent(sourceBuffer.audioTracks, "change");
|
||||
sourceBuffer.audioTracks[0].enabled = false;
|
||||
});
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_equals(mediaSource.activeSourceBuffers.length, 1,
|
||||
"activeSourceBuffers list unchanged");
|
||||
|
||||
test.expectEvent(sourceBuffer.videoTracks, "change");
|
||||
sourceBuffer.audioTracks[0].enabled = true;
|
||||
sourceBuffer.videoTracks[0].selected = false;
|
||||
});
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_equals(mediaSource.activeSourceBuffers.length, 1,
|
||||
"activeSourceBuffers list unchanged");
|
||||
test.done();
|
||||
});
|
||||
});
|
||||
}, "Active SourceBuffers list ignores changes to selected audio/video tracks " +
|
||||
"that do not affect the activation of the SourceBuffer.");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Checks MediaSource.addSourceBuffer() sets SourceBuffer.mode appropriately</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="mediasource-util.js"></script>
|
||||
<script>
|
||||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
{
|
||||
// Note all mime types in mediasource-util.js
|
||||
// set the "generate timestamps flag" to false
|
||||
var mime = MediaSourceUtil.VIDEO_ONLY_TYPE;
|
||||
var sourceBuffer = mediaSource.addSourceBuffer(mime);
|
||||
assert_equals(sourceBuffer.mode, "segments");
|
||||
test.done();
|
||||
}, "addSourceBuffer() sets SourceBuffer.mode to 'segments' when the generate timestamps flag is false");
|
||||
|
||||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
{
|
||||
var mime = 'audio/aac';
|
||||
if (!MediaSource.isTypeSupported(mime)) {
|
||||
mime = 'audio/mpeg';
|
||||
if (!MediaSource.isTypeSupported(mime)) {
|
||||
assert_unreached("Browser does not support the audio/aac and audio/mpeg MIME types used in this test");
|
||||
}
|
||||
}
|
||||
sourceBuffer = mediaSource.addSourceBuffer(mime);
|
||||
assert_equals(sourceBuffer.mode, "sequence");
|
||||
test.done();
|
||||
}, "addSourceBuffer() sets SourceBuffer.mode to 'sequence' when the generate timestamps flag is true");
|
||||
</script>
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>MediaSource.addSourceBuffer() test cases</title>
|
||||
|
@ -20,7 +21,7 @@
|
|||
|
||||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
{
|
||||
assert_throws("InvalidAccessError",
|
||||
assert_throws(new TypeError(),
|
||||
function() { mediaSource.addSourceBuffer(""); },
|
||||
"addSourceBuffer() threw an exception when passed an empty string.");
|
||||
test.done();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!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>
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<meta charset="utf-8">
|
||||
<meta name="timeout" content="long">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="mediasource-util.js"></script>
|
||||
<script>
|
||||
var subType = MediaSourceUtil.getSubType(MediaSourceUtil.AUDIO_ONLY_TYPE);
|
||||
var manifestFilenameAudio = subType + "/test-a-128k-44100Hz-1ch-manifest.json";
|
||||
|
||||
// Fill up a given SourceBuffer by appending data repeatedly via doAppendDataFunc until
|
||||
// an exception is thrown. The thrown exception is passed to onCaughtExceptionCallback.
|
||||
function fillUpSourceBuffer(test, sourceBuffer, doAppendDataFunc, onCaughtExceptionCallback) {
|
||||
// We are appending data repeatedly in sequence mode, there should be no gaps.
|
||||
assert_false(sourceBuffer.buffered.length > 1, "unexpected gap in buffered ranges.");
|
||||
try {
|
||||
doAppendDataFunc();
|
||||
} catch(ex) {
|
||||
onCaughtExceptionCallback(ex);
|
||||
}
|
||||
test.expectEvent(sourceBuffer, 'updateend', 'append ended.');
|
||||
test.waitForExpectedEvents(function() { fillUpSourceBuffer(test, sourceBuffer, doAppendDataFunc, onCaughtExceptionCallback); });
|
||||
}
|
||||
|
||||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
{
|
||||
mediaElement.addEventListener("error", test.unreached_func("Unexpected event 'error'"));
|
||||
MediaSourceUtil.fetchManifestAndData(test, manifestFilenameAudio, function(typeAudio, dataAudio)
|
||||
{
|
||||
var sourceBuffer = mediaSource.addSourceBuffer(typeAudio);
|
||||
sourceBuffer.mode = 'sequence';
|
||||
fillUpSourceBuffer(test, sourceBuffer,
|
||||
function () { // doAppendDataFunc
|
||||
sourceBuffer.appendBuffer(dataAudio);
|
||||
},
|
||||
function (ex) { // onCaughtExceptionCallback
|
||||
assert_equals(ex.name, 'QuotaExceededError');
|
||||
test.done();
|
||||
});
|
||||
});
|
||||
}, 'Appending data repeatedly should fill up the buffer and throw a QuotaExceededError when buffer is full.');
|
||||
</script>
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>SourceBuffer.appendWindowStart and SourceBuffer.appendWindowEnd test cases.</title>
|
||||
|
@ -44,35 +45,35 @@
|
|||
function() { sourceBuffer.appendWindowStart = Number.NaN; },
|
||||
"set appendWindowStart throws an exception for Number.NaN.");
|
||||
|
||||
assert_throws("InvalidAccessError",
|
||||
assert_throws(new TypeError(),
|
||||
function() { sourceBuffer.appendWindowStart = 600.0; },
|
||||
"set appendWindowStart throws an exception when greater than appendWindowEnd.");
|
||||
|
||||
assert_throws("InvalidAccessError",
|
||||
assert_throws(new TypeError(),
|
||||
function() { sourceBuffer.appendWindowStart = sourceBuffer.appendWindowEnd; },
|
||||
"set appendWindowStart throws an exception when equal to appendWindowEnd.");
|
||||
|
||||
assert_throws("InvalidAccessError",
|
||||
assert_throws(new TypeError(),
|
||||
function() { sourceBuffer.appendWindowEnd = sourceBuffer.appendWindowStart; },
|
||||
"set appendWindowEnd throws an exception when equal to appendWindowStart.");
|
||||
|
||||
assert_throws("InvalidAccessError",
|
||||
assert_throws(new TypeError(),
|
||||
function() { sourceBuffer.appendWindowEnd = sourceBuffer.appendWindowStart - 1; },
|
||||
"set appendWindowEnd throws an exception if less than appendWindowStart.");
|
||||
|
||||
assert_throws("InvalidAccessError",
|
||||
assert_throws(new TypeError(),
|
||||
function() { sourceBuffer.appendWindowStart = -100.0; },
|
||||
"set appendWindowStart throws an exception when less than 0.");
|
||||
|
||||
assert_throws("InvalidAccessError",
|
||||
assert_throws(new TypeError(),
|
||||
function() { sourceBuffer.appendWindowEnd = -100.0; },
|
||||
"set appendWindowEnd throws an exception when less than 0.");
|
||||
|
||||
assert_throws("InvalidAccessError",
|
||||
assert_throws(new TypeError(),
|
||||
function() { sourceBuffer.appendWindowEnd = Number.NaN; },
|
||||
"set appendWindowEnd throws an exception if NaN.");
|
||||
|
||||
assert_throws("InvalidAccessError",
|
||||
assert_throws(new TypeError(),
|
||||
function() { sourceBuffer.appendWindowEnd = undefined; },
|
||||
"set appendWindowEnd throws an exception if undefined.");
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<title>Tests that MediaSource attachment stops delaying the load event.</title>
|
||||
<link rel="author" title="Matthew Wolenetz" href="mailto:wolenetz@chromium.org"/>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
async_test(function(test)
|
||||
{
|
||||
var receivedLoadEvent = false;
|
||||
var receivedSourceOpenEvent = false;
|
||||
|
||||
window.addEventListener("load", test.step_func(function() {
|
||||
assert_false(receivedLoadEvent, "window should not receive multiple load events");
|
||||
receivedLoadEvent = true;
|
||||
assert_equals(document.readyState, "complete", "document should be complete");
|
||||
if (receivedLoadEvent && receivedSourceOpenEvent) {
|
||||
test.done();
|
||||
}
|
||||
}));
|
||||
|
||||
assert_equals(document.readyState, "loading", "document should not be complete yet");
|
||||
var video = document.createElement("video");
|
||||
var mediaSource = new MediaSource();
|
||||
|
||||
// |video| should stop delaying the load event long and complete the MediaSource attachment
|
||||
// before either a "progress", "stalled" or "suspend" event are enqueued.
|
||||
video.addEventListener("suspend", test.unreached_func("unexpected 'suspend' event"));
|
||||
video.addEventListener("stalled", test.unreached_func("unexpected 'stalled' event"));
|
||||
video.addEventListener("progress", test.unreached_func("unexpected 'progress' event"));
|
||||
|
||||
// No error is expected.
|
||||
video.addEventListener("error", test.unreached_func("unexpected 'error' event"));
|
||||
|
||||
mediaSource.addEventListener("sourceopen", test.step_func(function() {
|
||||
assert_false(receivedSourceOpenEvent, "only one sourceopen event should occur in this test");
|
||||
receivedSourceOpenEvent = true;
|
||||
assert_equals(video.networkState, video.NETWORK_LOADING);
|
||||
assert_equals(video.readyState, video.HAVE_NOTHING);
|
||||
if (receivedLoadEvent && receivedSourceOpenEvent) {
|
||||
test.done();
|
||||
}
|
||||
}));
|
||||
|
||||
var mediaSourceURL = URL.createObjectURL(mediaSource);
|
||||
video.src = mediaSourceURL;
|
||||
test.add_cleanup(function() { URL.revokeObjectURL(mediaSourceURL); });
|
||||
}, "MediaSource attachment should immediately stop delaying the load event");
|
||||
</script>
|
|
@ -0,0 +1,124 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<meta charset="utf-8">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="mediasource-util.js"></script>
|
||||
<script>
|
||||
mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
|
||||
sourceBuffer.appendBuffer(initSegment);
|
||||
test.expectEvent(sourceBuffer.audioTracks, "addtrack", "sourceBuffer.audioTracks addtrack event");
|
||||
test.expectEvent(sourceBuffer.videoTracks, "addtrack", "sourceBuffer.videoTracks addtrack event");
|
||||
test.expectEvent(mediaElement.audioTracks, "addtrack", "mediaElement.audioTracks addtrack event");
|
||||
test.expectEvent(mediaElement.videoTracks, "addtrack", "mediaElement.videoTracks addtrack event");
|
||||
test.expectEvent(mediaElement, "loadedmetadata", "loadedmetadata done.");
|
||||
test.expectEvent(sourceBuffer, "updateend", "initSegment append ended.");
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_equals(sourceBuffer.videoTracks.length, 1, "videoTracks.length");
|
||||
assert_equals(sourceBuffer.videoTracks[0].kind, "main", "videoTrack.kind");
|
||||
assert_equals(sourceBuffer.videoTracks[0].label, "", "videoTrack.label");
|
||||
assert_equals(sourceBuffer.videoTracks[0].language, "eng", "videoTrack.language");
|
||||
assert_equals(sourceBuffer.videoTracks[0].sourceBuffer, sourceBuffer, "videoTrack.sourceBuffer");
|
||||
// The first video track is selected by default.
|
||||
assert_true(sourceBuffer.videoTracks[0].selected, "sourceBuffer.videoTracks[0].selected");
|
||||
|
||||
assert_equals(sourceBuffer.audioTracks.length, 1, "audioTracks.length");
|
||||
assert_equals(sourceBuffer.audioTracks[0].kind, "main", "audioTrack.kind");
|
||||
assert_equals(sourceBuffer.audioTracks[0].label, "", "audioTrack.label");
|
||||
assert_equals(sourceBuffer.audioTracks[0].language, "eng", "audioTrack.language");
|
||||
assert_equals(sourceBuffer.audioTracks[0].sourceBuffer, sourceBuffer, "audioTrack.sourceBuffer");
|
||||
// The first audio track is enabled by default.
|
||||
assert_true(sourceBuffer.audioTracks[0].enabled, "sourceBuffer.audioTracks[0].enabled");
|
||||
|
||||
assert_not_equals(sourceBuffer.audioTracks[0].id, sourceBuffer.videoTracks[0].id, "track ids must be unique");
|
||||
|
||||
assert_equals(mediaElement.videoTracks.length, 1, "videoTracks.length");
|
||||
assert_equals(mediaElement.videoTracks[0], sourceBuffer.videoTracks[0], "mediaElement.videoTrack == sourceBuffer.videoTrack");
|
||||
|
||||
assert_equals(mediaElement.audioTracks.length, 1, "audioTracks.length");
|
||||
assert_equals(mediaElement.audioTracks[0], sourceBuffer.audioTracks[0], "mediaElement.audioTrack == sourceBuffer.audioTrack");
|
||||
|
||||
test.done();
|
||||
});
|
||||
}, "Check that media tracks and their properties are populated properly");
|
||||
|
||||
function verifyTrackRemoval(test, mediaElement, mediaSource, sourceBuffer, trackRemovalAction, successCallback) {
|
||||
assert_equals(sourceBuffer.audioTracks.length, 1, "audioTracks.length");
|
||||
assert_true(sourceBuffer.audioTracks[0].enabled, "sourceBuffer.audioTracks[0].enabled");
|
||||
assert_equals(sourceBuffer.videoTracks.length, 1, "videoTracks.length");
|
||||
assert_true(sourceBuffer.videoTracks[0].selected, "sourceBuffer.videoTracks[0].selected");
|
||||
|
||||
var audioTrack = sourceBuffer.audioTracks[0];
|
||||
var videoTrack = sourceBuffer.videoTracks[0];
|
||||
|
||||
// Verify removetrack events.
|
||||
test.expectEvent(sourceBuffer.audioTracks, "removetrack", "sourceBuffer.audioTracks removetrack event");
|
||||
test.expectEvent(sourceBuffer.videoTracks, "removetrack", "sourceBuffer.videoTracks removetrack event");
|
||||
test.expectEvent(mediaElement.audioTracks, "removetrack", "mediaElement.audioTracks removetrack event");
|
||||
test.expectEvent(mediaElement.videoTracks, "removetrack", "mediaElement.videoTracks removetrack event");
|
||||
|
||||
// Removing enabled audio track and selected video track should fire "change" events on mediaElement track lists.
|
||||
test.expectEvent(mediaElement.audioTracks, "change", "mediaElement.audioTracks changed.");
|
||||
test.expectEvent(mediaElement.videoTracks, "change", "mediaElement.videoTracks changed.");
|
||||
|
||||
trackRemovalAction();
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_equals(mediaSource.sourceBuffers.length, 0, "mediaSource.sourceBuffers.length");
|
||||
assert_equals(mediaElement.videoTracks.length, 0, "videoTracks.length");
|
||||
assert_equals(mediaElement.audioTracks.length, 0, "audioTracks.length");
|
||||
assert_equals(sourceBuffer.videoTracks.length, 0, "videoTracks.length");
|
||||
assert_equals(sourceBuffer.audioTracks.length, 0, "audioTracks.length");
|
||||
// Since audio and video tracks have been removed, their .sourceBuffer property should be null now.
|
||||
assert_equals(audioTrack.sourceBuffer, null, "audioTrack.sourceBuffer");
|
||||
assert_equals(videoTrack.sourceBuffer, null, "videoTrack.sourceBuffer");
|
||||
test.done();
|
||||
});
|
||||
}
|
||||
|
||||
mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
|
||||
sourceBuffer.appendBuffer(initSegment);
|
||||
test.expectEvent(sourceBuffer, "updateend", "initSegment append ended.");
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
verifyTrackRemoval(test, mediaElement, mediaSource, sourceBuffer, test.step_func(function ()
|
||||
{
|
||||
mediaSource.removeSourceBuffer(sourceBuffer);
|
||||
}));
|
||||
});
|
||||
}, "Media tracks must be removed when the SourceBuffer is removed from the MediaSource");
|
||||
|
||||
mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
|
||||
sourceBuffer.appendBuffer(initSegment);
|
||||
test.expectEvent(sourceBuffer, "updateend", "initSegment append ended.");
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
verifyTrackRemoval(test, mediaElement, mediaSource, sourceBuffer, test.step_func(function ()
|
||||
{
|
||||
mediaElement.src = "";
|
||||
}));
|
||||
});
|
||||
}, "Media tracks must be removed when the HTMLMediaElement.src is changed");
|
||||
|
||||
mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
|
||||
sourceBuffer.appendBuffer(initSegment);
|
||||
test.expectEvent(sourceBuffer, "updateend", "initSegment append ended.");
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
verifyTrackRemoval(test, mediaElement, mediaSource, sourceBuffer, test.step_func(function ()
|
||||
{
|
||||
mediaElement.load();
|
||||
}));
|
||||
});
|
||||
}, "Media tracks must be removed when HTMLMediaElement.load() is called");
|
||||
</script>
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>SourceBuffer.buffered test cases.</title>
|
||||
|
@ -14,14 +15,24 @@
|
|||
var manifestFilenameA = subType + "/test-a-128k-44100Hz-1ch-manifest.json";
|
||||
var manifestFilenameB = subType + "/test-v-128k-320x240-30fps-10kfr-manifest.json";
|
||||
|
||||
// Audio track expectations
|
||||
var expectationsA = {
|
||||
webm: "{ [0.000, 2.023) }",
|
||||
mp4: "{ [0.000, 2.043) }",
|
||||
};
|
||||
|
||||
// Video track expectations
|
||||
var expectationsB = {
|
||||
webm: "{ [0.000, 2.001) }",
|
||||
mp4: "{ [0.000, 2.000) }",
|
||||
mp4: "{ [0.067, 2.067) }",
|
||||
};
|
||||
|
||||
// Audio and Video intersection expectations.
|
||||
// https://w3c.github.io/media-source/index.html#dom-sourcebuffer-buffered
|
||||
// When mediaSource.readyState is "ended", then set the end time on the last range in track ranges to highest end time.
|
||||
var expectationsC = {
|
||||
webm: ["{ [0.000, 2.001) }", "{ [0.000, 2.023) }"],
|
||||
mp4: ["{ [0.067, 2.043) }", "{ [0.067, 2.067) }"]
|
||||
};
|
||||
|
||||
function mediaSourceDemuxedTest(callback, description)
|
||||
|
@ -69,15 +80,18 @@
|
|||
test.expectEvent(mediaElement, "loadedmetadata");
|
||||
appendData(test, mediaSource, dataA, dataB, function()
|
||||
{
|
||||
var expectedBeforeEndOfStreamIntersection = expectationsC[subType][0];
|
||||
var expectedAfterEndOfStreamIntersection = expectationsC[subType][1];
|
||||
|
||||
assertBufferedEquals(mediaSource.activeSourceBuffers[0], expectationsA[subType], "mediaSource.activeSourceBuffers[0]");
|
||||
assertBufferedEquals(mediaSource.activeSourceBuffers[1], expectationsB[subType], "mediaSource.activeSourceBuffers[1]");
|
||||
assertBufferedEquals(mediaElement, expectationsB[subType], "mediaElement.buffered");
|
||||
assertBufferedEquals(mediaElement, expectedBeforeEndOfStreamIntersection, "mediaElement.buffered");
|
||||
|
||||
mediaSource.endOfStream();
|
||||
|
||||
assertBufferedEquals(mediaSource.activeSourceBuffers[0], expectationsA[subType], "mediaSource.activeSourceBuffers[0]");
|
||||
assertBufferedEquals(mediaSource.activeSourceBuffers[1], expectationsB[subType], "mediaSource.activeSourceBuffers[1]");
|
||||
assertBufferedEquals(mediaElement, expectationsA[subType], "mediaElement.buffered");
|
||||
assertBufferedEquals(mediaElement, expectedAfterEndOfStreamIntersection, "mediaElement.buffered");
|
||||
|
||||
test.done();
|
||||
});
|
||||
|
@ -99,8 +113,8 @@
|
|||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
var expectationsAV = {
|
||||
webm: ["{ [0.000, 2.003) }", "{ [0.000, 2.023) }"],
|
||||
mp4: ["{ [0.000, 2.000) }", "{ [0.000, 2.043) }"],
|
||||
webm: ["{ [0.003, 2.004) }", "{ [0.003, 2.023) }"],
|
||||
mp4: ["{ [0.067, 2.043) }", "{ [0.067, 2.067) }"],
|
||||
};
|
||||
|
||||
var expectedBeforeEndOfStream = expectationsAV[subType][0];
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>MediaSource.readyState equals "closed" test cases.</title>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>MP4 audio-only bitrate change.</title>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>MP4 muxed audio & video with an audio bitrate change.</title>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>MP4 muxed audio & video with a video frame size change.</title>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>MP4 muxed audio & video with a video bitrate change.</title>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>MP4 video-only bitrate change.</title>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>MP4 video-only frame rate change.</title>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>MP4 video-only frame size change.</title>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>WebM audio-only bitrate change.</title>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>WebM muxed audio & video with an audio bitrate change.</title>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>WebM muxed audio & video with a video frame size change.</title>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>WebM muxed audio & video with a video bitrate change.</title>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>WebM video-only bitrate change.</title>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>WebM video-only frame rate change.</title>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>WebM video-only frame size change.</title>
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang).
|
||||
|
||||
// Extract & return the resolution string from a filename, if any.
|
||||
function resolutionFromFilename(filename)
|
||||
{
|
||||
|
@ -64,10 +66,9 @@ function mediaSourceConfigChangeTest(directory, idA, idB, description)
|
|||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_false(sourceBuffer.updating, "updating");
|
||||
assert_greater_than(mediaSource.duration, 2, "duration");
|
||||
|
||||
// Truncate the presentation to a duration of 2 seconds.
|
||||
mediaSource.duration = 2;
|
||||
sourceBuffer.remove(2, Infinity);
|
||||
|
||||
assert_true(sourceBuffer.updating, "updating");
|
||||
test.expectEvent(sourceBuffer, 'updatestart', 'sourceBuffer');
|
||||
|
@ -75,6 +76,17 @@ function mediaSourceConfigChangeTest(directory, idA, idB, description)
|
|||
test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
|
||||
});
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_false(sourceBuffer.updating, "updating");
|
||||
assert_greater_than(mediaSource.duration, 2, "duration");
|
||||
|
||||
// Truncate the presentation to a duration of 2 seconds.
|
||||
mediaSource.duration = 2;
|
||||
|
||||
test.expectEvent(mediaElement, "durationchange");
|
||||
});
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_false(sourceBuffer.updating, "updating");
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<meta charset="utf-8">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="mediasource-util.js"></script>
|
||||
<script>
|
||||
function mediasource_detach_test(testFunction, description)
|
||||
{
|
||||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
{
|
||||
var segmentInfo = MediaSourceUtil.SEGMENT_INFO;
|
||||
var sourceBuffer = mediaSource.addSourceBuffer(segmentInfo.type);
|
||||
|
||||
assert_equals(mediaElement.readyState, HTMLMediaElement.HAVE_NOTHING);
|
||||
assert_equals(mediaSource.readyState, 'open');
|
||||
|
||||
mediaSource.addEventListener('sourceclose', test.step_func(function (event)
|
||||
{
|
||||
assert_equals(mediaSource.sourceBuffers.length, 0, 'sourceBuffers is empty');
|
||||
assert_equals(mediaSource.activeSourceBuffers.length, 0, 'activeSourceBuffers is empty');
|
||||
assert_equals(mediaSource.readyState, 'closed', 'readyState is "closed"');
|
||||
assert_true(Number.isNaN(mediaSource.duration), 'duration is NaN');
|
||||
test.done();
|
||||
}));
|
||||
|
||||
MediaSourceUtil.loadBinaryData(test, segmentInfo.url, function(mediaData)
|
||||
{
|
||||
testFunction(test, mediaElement, mediaSource, sourceBuffer, mediaData);
|
||||
});
|
||||
}, description);
|
||||
}
|
||||
|
||||
mediasource_detach_test(function(test, mediaElement, mediaSource, sourceBuffer, mediaData)
|
||||
{
|
||||
mediaElement.load();
|
||||
}, 'Test media.load() before appending data will trigger MediaSource detaching from a media element.');
|
||||
|
||||
mediasource_detach_test(function(test, mediaElement, mediaSource, sourceBuffer, mediaData)
|
||||
{
|
||||
sourceBuffer.addEventListener('updateend', test.step_func(function (event)
|
||||
{
|
||||
assert_greater_than(mediaElement.readyState, HTMLMediaElement.HAVE_NOTHING, 'media readyState is greater than "HAVE_NOTHING"')
|
||||
assert_false(sourceBuffer.updating, 'updating attribute is false');
|
||||
mediaElement.load();
|
||||
}));
|
||||
|
||||
sourceBuffer.appendBuffer(mediaData);
|
||||
}, 'Test media.load() after appending data will trigger MediaSource detaching from a media element.');
|
||||
</script>
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>MediaSource.duration boundary condition test cases.</title>
|
||||
|
@ -49,14 +50,14 @@
|
|||
DurationBoundaryConditionTest(Number.MAX_VALUE, null, "Set duration to Number.MAX_VALUE");
|
||||
DurationBoundaryConditionTest(Number.MIN_VALUE, null, "Set duration to Number.MIN_VALUE");
|
||||
DurationBoundaryConditionTest(Number.MAX_VALUE - 1, null, "Set duration to Number.MAX_VALUE - 1");
|
||||
DurationBoundaryConditionTest(Number.MIN_VALUE - 1, "InvalidAccessError", "Set duration to Number.MIN_VALUE - 1");
|
||||
DurationBoundaryConditionTest(Number.MIN_VALUE - 1, new TypeError(), "Set duration to Number.MIN_VALUE - 1");
|
||||
DurationBoundaryConditionTest(Number.POSITIVE_INFINITY, null, "Set duration to Number.POSITIVE_INFINITY");
|
||||
DurationBoundaryConditionTest(Number.NEGATIVE_INFINITY, "InvalidAccessError", "Set duration to Number.NEGATIVE_INFINITY");
|
||||
DurationBoundaryConditionTest(-1 * Number.MAX_VALUE, "InvalidAccessError", "Set duration to lowest value.");
|
||||
DurationBoundaryConditionTest(-101.9, "InvalidAccessError", "Set duration to a negative double.");
|
||||
DurationBoundaryConditionTest(Number.NEGATIVE_INFINITY, new TypeError(), "Set duration to Number.NEGATIVE_INFINITY");
|
||||
DurationBoundaryConditionTest(-1 * Number.MAX_VALUE, new TypeError(), "Set duration to lowest value.");
|
||||
DurationBoundaryConditionTest(-101.9, new TypeError(), "Set duration to a negative double.");
|
||||
DurationBoundaryConditionTest(101.9, null, "Set duration to a positive double.");
|
||||
DurationBoundaryConditionTest(0, null, "Set duration to zero");
|
||||
DurationBoundaryConditionTest(NaN, "InvalidAccessError", "Set duration to NaN");
|
||||
DurationBoundaryConditionTest(NaN, new TypeError(), "Set duration to NaN");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>MediaSource.duration & HTMLMediaElement.duration test cases.</title>
|
||||
|
@ -9,6 +10,11 @@
|
|||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
|
||||
var subType = MediaSourceUtil.getSubType(MediaSourceUtil.AUDIO_ONLY_TYPE);
|
||||
var manifestFilenameAudio = subType + "/test-a-128k-44100Hz-1ch-manifest.json";
|
||||
var manifestFilenameVideo = subType + "/test-v-128k-320x240-30fps-10kfr-manifest.json";
|
||||
|
||||
function mediasource_truncated_duration_seek_test(testFunction, description, options)
|
||||
{
|
||||
return mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
|
@ -28,9 +34,6 @@
|
|||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_equals(mediaElement.duration, fullDuration, 'mediaElement fullDuration');
|
||||
assert_equals(mediaSource.duration, fullDuration, 'mediaSource fullDuration');
|
||||
|
||||
test.expectEvent(mediaElement, 'seeking', 'seeking to seekTo');
|
||||
test.expectEvent(mediaElement, 'timeupdate', 'timeupdate while seeking to seekTo');
|
||||
test.expectEvent(mediaElement, 'seeked', 'seeked to seekTo');
|
||||
|
@ -41,20 +44,44 @@
|
|||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_greater_than_equal(mediaElement.currentTime, seekTo, 'Playback time has reached seekTo');
|
||||
assert_equals(mediaElement.duration, fullDuration, 'mediaElement fullDuration after seekTo');
|
||||
assert_equals(mediaSource.duration, fullDuration, 'mediaSource fullDuration after seekTo');
|
||||
assert_false(mediaElement.seeking, 'mediaElement.seeking after seeked to seekTo');
|
||||
|
||||
test.expectEvent(mediaElement, 'seeking', 'Seeking to truncated duration');
|
||||
|
||||
assert_false(sourceBuffer.updating, 'sourceBuffer.updating');
|
||||
|
||||
mediaSource.duration = truncatedDuration;
|
||||
sourceBuffer.remove(truncatedDuration, Infinity);
|
||||
|
||||
assert_true(sourceBuffer.updating, 'sourceBuffer.updating');
|
||||
test.expectEvent(sourceBuffer, 'updatestart', 'sourceBuffer');
|
||||
test.expectEvent(sourceBuffer, 'update', 'sourceBuffer');
|
||||
test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
|
||||
});
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_greater_than_equal(mediaElement.currentTime, seekTo, 'Playback time has reached seekTo');
|
||||
assert_false(sourceBuffer.updating, 'sourceBuffer.updating');
|
||||
|
||||
// Remove will not remove partial frames, so the resulting duration is the highest end time
|
||||
// of the track buffer ranges, and is greater than or equal to the highest coded frame
|
||||
// presentation time across all track buffer ranges. We first obtain the intersected track buffer
|
||||
// ranges end time and set the duration to that value.
|
||||
truncatedDuration = sourceBuffer.buffered.end(sourceBuffer.buffered.length-1);
|
||||
assert_less_than(truncatedDuration, seekTo,
|
||||
'remove has removed the current playback position from at least one track buffer');
|
||||
|
||||
mediaSource.duration = truncatedDuration;
|
||||
test.expectEvent(mediaElement, 'seeking', 'Seeking to truncated duration');
|
||||
|
||||
// The actual duration may be slightly higher than truncatedDuration because the
|
||||
// duration is adjusted upwards if necessary to be the highest end time across all track buffer
|
||||
// ranges. Allow that increase here.
|
||||
assert_less_than_equal(truncatedDuration, mediaSource.duration,
|
||||
'Duration should not be less than what was set');
|
||||
// Here, we assume no test media coded frame duration is longer than 100ms.
|
||||
assert_less_than(mediaSource.duration - truncatedDuration, 0.1);
|
||||
|
||||
// Update our truncatedDuration to be the actual new duration.
|
||||
truncatedDuration = mediaSource.duration;
|
||||
|
||||
assert_true(mediaElement.seeking, 'Seeking after setting truncatedDuration');
|
||||
});
|
||||
|
@ -127,8 +154,10 @@
|
|||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_equals(mediaElement.currentTime, truncatedDuration,
|
||||
assert_greater_than_equal(mediaElement.currentTime, truncatedDuration,
|
||||
'Playback time has reached truncatedDuration');
|
||||
// The mediaSource.readyState is "ended". Buffered ranges have been adjusted to the longest track.
|
||||
truncatedDuration = sourceBuffer.buffered.end(sourceBuffer.buffered.length-1);
|
||||
assert_equals(mediaElement.duration, truncatedDuration,
|
||||
'mediaElement truncatedDuration after seek to it');
|
||||
assert_equals(mediaSource.duration, truncatedDuration,
|
||||
|
@ -150,8 +179,10 @@
|
|||
var durationchangeEventCounter = 0;
|
||||
var durationchangeEventHandler = test.step_func(function(event)
|
||||
{
|
||||
assert_equals(mediaElement.duration, newDuration, 'mediaElement newDuration');
|
||||
assert_equals(mediaSource.duration, newDuration, 'mediaSource newDuration');
|
||||
assert_equals(mediaElement.duration, mediaSource.duration, 'mediaElement newDuration');
|
||||
// Final duration may be greater than originally set as per MSE's 2.4.6 Duration change
|
||||
// Adjust newDuration accordingly.
|
||||
assert_less_than_equal(newDuration, mediaSource.duration, 'mediaSource newDuration');
|
||||
durationchangeEventCounter++;
|
||||
});
|
||||
|
||||
|
@ -164,17 +195,12 @@
|
|||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_equals(mediaElement.duration, fullDuration, 'mediaElement fullDuration');
|
||||
assert_equals(mediaSource.duration, fullDuration, 'mediaSource fullDuration');
|
||||
assert_less_than(mediaElement.currentTime, newDuration / 2, 'mediaElement currentTime');
|
||||
|
||||
// Media load also fires 'durationchange' event, so only start counting them now.
|
||||
mediaElement.addEventListener('durationchange', durationchangeEventHandler);
|
||||
|
||||
assert_false(sourceBuffer.updating, "updating");
|
||||
|
||||
// Truncate duration. This should result in one 'durationchange' fired.
|
||||
mediaSource.duration = newDuration;
|
||||
sourceBuffer.remove(newDuration, Infinity);
|
||||
|
||||
assert_true(sourceBuffer.updating, "updating");
|
||||
test.expectEvent(sourceBuffer, 'updatestart', 'sourceBuffer');
|
||||
|
@ -184,8 +210,19 @@
|
|||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
// Media load also fires 'durationchange' event, so only start counting them now.
|
||||
mediaElement.addEventListener('durationchange', durationchangeEventHandler);
|
||||
|
||||
assert_false(sourceBuffer.updating, "updating");
|
||||
|
||||
// Truncate duration. This should result in one 'durationchange' fired.
|
||||
mediaSource.duration = newDuration;
|
||||
|
||||
// Final duration may be greater than originally set as per MSE's 2.4.6 Duration change
|
||||
// Adjust newDuration accordingly.
|
||||
assert_true(newDuration <= mediaSource.duration, 'adjusted duration');
|
||||
newDuration = mediaSource.duration;
|
||||
|
||||
// Set duration again to make sure it does not trigger another 'durationchange' event.
|
||||
mediaSource.duration = newDuration;
|
||||
|
||||
|
@ -193,11 +230,10 @@
|
|||
test.expectEvent(mediaSource, 'sourceended', 'endOfStream acknowledged');
|
||||
mediaSource.endOfStream();
|
||||
|
||||
// endOfStream can change duration downwards slightly.
|
||||
// endOfStream can change duration slightly.
|
||||
// Allow for one more 'durationchange' event only in this case.
|
||||
var currentDuration = mediaSource.duration;
|
||||
if (currentDuration != newDuration) {
|
||||
assert_true(currentDuration > 0 && currentDuration < newDuration, 'adjusted duration');
|
||||
newDuration = currentDuration;
|
||||
++expectedDurationChangeEventCount;
|
||||
}
|
||||
|
@ -212,6 +248,136 @@
|
|||
});
|
||||
});
|
||||
}, 'Test setting same duration multiple times does not fire duplicate durationchange');
|
||||
|
||||
mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
assert_greater_than(segmentInfo.duration, 2, 'Sufficient test media duration');
|
||||
|
||||
var fullDuration = segmentInfo.duration;
|
||||
var newDuration = fullDuration / 2;
|
||||
|
||||
// Append all the segments
|
||||
test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
|
||||
test.expectEvent(mediaElement, 'loadedmetadata', 'mediaElement');
|
||||
sourceBuffer.appendBuffer(mediaData);
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_false(sourceBuffer.updating, "updating");
|
||||
|
||||
assert_throws("InvalidStateError", function()
|
||||
{
|
||||
mediaSource.duration = newDuration;
|
||||
}, "duration");
|
||||
|
||||
test.done();
|
||||
});
|
||||
}, 'Test setting the duration to less than the highest starting presentation timestamp will throw');
|
||||
|
||||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
{
|
||||
mediaElement.addEventListener("error", test.unreached_func("Unexpected event 'error'"));
|
||||
MediaSourceUtil.fetchManifestAndData(test, manifestFilenameAudio, function(typeAudio, dataAudio)
|
||||
{
|
||||
MediaSourceUtil.fetchManifestAndData(test, manifestFilenameVideo, function(typeVideo, dataVideo)
|
||||
{
|
||||
var sourceBufferAudio = mediaSource.addSourceBuffer(typeAudio);
|
||||
var sourceBufferVideo = mediaSource.addSourceBuffer(typeVideo);
|
||||
var newDuration = 1.2;
|
||||
|
||||
sourceBufferAudio.appendWindowEnd = 2.0;
|
||||
sourceBufferAudio.appendWindowStart = newDuration / 2.0;
|
||||
sourceBufferAudio.appendBuffer(dataAudio);
|
||||
|
||||
sourceBufferVideo.appendWindowEnd = 2.0;
|
||||
sourceBufferVideo.appendWindowStart = newDuration * 1.3;
|
||||
sourceBufferVideo.appendBuffer(dataVideo);
|
||||
|
||||
test.expectEvent(sourceBufferAudio, "updateend");
|
||||
test.expectEvent(sourceBufferVideo, "updateend");
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_equals(sourceBufferAudio.buffered.length, 1);
|
||||
assert_equals(sourceBufferVideo.buffered.length, 1);
|
||||
assert_less_than(sourceBufferAudio.buffered.start(0), newDuration);
|
||||
assert_greater_than(sourceBufferVideo.buffered.start(0), newDuration);
|
||||
assert_throws("InvalidStateError", function () { mediaSource.duration = newDuration; });
|
||||
test.done();
|
||||
});
|
||||
});
|
||||
});
|
||||
}, "Truncating the duration throws an InvalidStateError exception when new duration is less than the highest buffered range start time of one of the track buffers");
|
||||
|
||||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
{
|
||||
mediaElement.addEventListener("error", test.unreached_func("Unexpected event 'error'"));
|
||||
MediaSourceUtil.fetchManifestAndData(test, manifestFilenameAudio, function(typeAudio, dataAudio)
|
||||
{
|
||||
MediaSourceUtil.fetchManifestAndData(test, manifestFilenameVideo, function(typeVideo, dataVideo)
|
||||
{
|
||||
var sourceBufferAudio = mediaSource.addSourceBuffer(typeAudio);
|
||||
var sourceBufferVideo = mediaSource.addSourceBuffer(typeVideo);
|
||||
|
||||
// Buffer audio [0.8,1.8)
|
||||
sourceBufferAudio.timestampOffset = 0.8;
|
||||
sourceBufferAudio.appendWindowEnd = 1.8;
|
||||
sourceBufferAudio.appendBuffer(dataAudio);
|
||||
|
||||
// Buffer video [1.5,3)
|
||||
sourceBufferVideo.timestampOffset = 1.5;
|
||||
sourceBufferVideo.appendWindowEnd = 3;
|
||||
sourceBufferVideo.appendBuffer(dataVideo);
|
||||
|
||||
test.expectEvent(sourceBufferAudio, "updateend");
|
||||
test.expectEvent(sourceBufferVideo, "updateend");
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
var newDuration = 2.0;
|
||||
|
||||
// Verify the test setup
|
||||
assert_equals(sourceBufferAudio.buffered.length, 1);
|
||||
assert_equals(sourceBufferVideo.buffered.length, 1);
|
||||
assert_greater_than(sourceBufferAudio.buffered.end(0), 1.5);
|
||||
assert_less_than(sourceBufferAudio.buffered.end(0), newDuration);
|
||||
assert_less_than(sourceBufferVideo.buffered.start(0), newDuration);
|
||||
assert_greater_than(sourceBufferVideo.buffered.end(0), newDuration + 0.5);
|
||||
|
||||
// Verify the expected error
|
||||
// We assume relocated test video has at least one coded
|
||||
// frame presentation interval which fits in [>2.0,>2.5)
|
||||
assert_throws("InvalidStateError", function () { mediaSource.duration = newDuration; });
|
||||
test.done();
|
||||
});
|
||||
});
|
||||
});
|
||||
}, "Truncating the duration throws an InvalidStateError exception when new duration is less than a buffered coded frame presentation time");
|
||||
|
||||
mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
assert_less_than(segmentInfo.duration, 60, 'Sufficient test media duration');
|
||||
sourceBuffer.appendBuffer(mediaData);
|
||||
test.expectEvent(sourceBuffer, 'updateend', 'Media data appended to the SourceBuffer');
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
mediaSource.duration = 60;
|
||||
assert_false(sourceBuffer.updating, 'No SourceBuffer update when duration is increased');
|
||||
test.done();
|
||||
});
|
||||
}, 'Increasing the duration does not trigger any SourceBuffer update');
|
||||
|
||||
mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
assert_greater_than(segmentInfo.duration, 2, 'Sufficient test media duration');
|
||||
mediaElement.play();
|
||||
sourceBuffer.appendBuffer(mediaData);
|
||||
test.expectEvent(sourceBuffer, 'updateend', 'Media data appended to the SourceBuffer');
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
mediaSource.duration = 60;
|
||||
assert_false(sourceBuffer.updating, 'No SourceBuffer update when duration is increased');
|
||||
test.done();
|
||||
});
|
||||
}, 'Increasing the duration during media playback does not trigger any SourceBuffer update');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Invalid MediaSource.endOfStream() parameter test cases.</title>
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Calls to MediaSource.endOfStream() without error</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="mediasource-util.js"></script>
|
||||
<script>
|
||||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
{
|
||||
mediaSource.duration = 2;
|
||||
mediaSource.endOfStream();
|
||||
assert_equals(mediaSource.duration, 0);
|
||||
test.done();
|
||||
}, 'MediaSource.endOfStream(): duration truncated to 0 when there are no buffered coded frames');
|
||||
|
||||
mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
sourceBuffer.appendBuffer(mediaData);
|
||||
test.expectEvent(sourceBuffer, 'updateend',
|
||||
'Media buffer appended to SourceBuffer');
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
mediaSource.endOfStream();
|
||||
test.expectEvent(mediaElement, 'canplaythrough',
|
||||
'Media element may render the media content until the end');
|
||||
});
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_equals(mediaElement.readyState, HTMLMediaElement.HAVE_ENOUGH_DATA,
|
||||
'Media element has enough data to render the content');
|
||||
test.done();
|
||||
});
|
||||
}, 'MediaSource.endOfStream(): media element notified that it now has all of the media data');
|
||||
|
||||
function threeDecimalPlaces(number)
|
||||
{
|
||||
return Number(number.toFixed(3));
|
||||
}
|
||||
|
||||
mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
sourceBuffer.appendBuffer(mediaData);
|
||||
test.expectEvent(sourceBuffer, 'updateend',
|
||||
'Media buffer appended to SourceBuffer');
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_equals(sourceBuffer.buffered.length, 1,
|
||||
'Media data properly buffered');
|
||||
var highestEndTime = sourceBuffer.buffered.end(0);
|
||||
|
||||
// Note that segmentInfo.duration is expected to also be the
|
||||
// highest track buffer range end time. Therefore, endOfStream() should
|
||||
// not change duration with this media.
|
||||
assert_equals(threeDecimalPlaces(segmentInfo.duration), threeDecimalPlaces(mediaSource.duration));
|
||||
assert_less_than_equal(highestEndTime, mediaSource.duration,
|
||||
'Media duration may be slightly longer than intersected track buffered ranges');
|
||||
|
||||
// Set the duration even higher, then confirm that endOfStream() drops it back to be
|
||||
// the highest track buffer range end time.
|
||||
mediaSource.duration += 10;
|
||||
mediaSource.endOfStream();
|
||||
|
||||
assert_equals(sourceBuffer.buffered.length, 1,
|
||||
'Media data properly buffered after endOfStream');
|
||||
|
||||
assert_equals(threeDecimalPlaces(segmentInfo.duration), threeDecimalPlaces(mediaSource.duration));
|
||||
assert_less_than_equal(highestEndTime, mediaSource.duration,
|
||||
'Media duration may be slightly longer than intersected track buffered ranges');
|
||||
assert_equals(sourceBuffer.buffered.end(0), mediaSource.duration,
|
||||
'After endOfStream(), highest buffered range end time must be the highest track buffer range end time');
|
||||
|
||||
test.done();
|
||||
});
|
||||
}, 'MediaSource.endOfStream(): duration and buffered range end time before and after endOfStream');
|
||||
</script>
|
|
@ -0,0 +1,197 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<meta charset="utf-8">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="mediasource-util.js"></script>
|
||||
<script>
|
||||
function ErrorTest(testFunction, description)
|
||||
{
|
||||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
{
|
||||
var segmentInfo = MediaSourceUtil.SEGMENT_INFO;
|
||||
|
||||
if (!segmentInfo) {
|
||||
assert_unreached("No segment info compatible with this MediaSource implementation.");
|
||||
return;
|
||||
}
|
||||
|
||||
var sourceBuffer = mediaSource.addSourceBuffer(segmentInfo.type);
|
||||
MediaSourceUtil.loadBinaryData(test, segmentInfo.url, function(mediaData)
|
||||
{
|
||||
testFunction(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData);
|
||||
});
|
||||
}, description);
|
||||
}
|
||||
|
||||
ErrorTest(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
var mediaSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[0]);
|
||||
|
||||
test.expectEvent(sourceBuffer, "error", "sourceBuffer error.");
|
||||
test.expectEvent(sourceBuffer, "updateend", "mediaSegment append ended.");
|
||||
test.expectEvent(mediaElement, "error", "mediaElement error.");
|
||||
test.expectEvent(mediaSource, "sourceended", "mediaSource ended.");
|
||||
test.expectEvent(mediaSource, "sourceclose", "mediaSource closed.");
|
||||
sourceBuffer.appendBuffer(mediaSegment);
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_true(mediaElement.error != null);
|
||||
assert_equals(mediaElement.error.code, MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED);
|
||||
|
||||
assert_equals(mediaSource.sourceBuffers.length, 0);
|
||||
assert_equals(mediaSource.readyState, "closed");
|
||||
test.done();
|
||||
});
|
||||
}, "Appending media segment before the first initialization segment.");
|
||||
|
||||
ErrorTest(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
assert_equals(mediaElement.readyState, HTMLMediaElement.HAVE_NOTHING);
|
||||
|
||||
// Fail if the append error algorithm occurs, since the decode
|
||||
// error will be provided by us directly via endOfStream().
|
||||
sourceBuffer.addEventListener("error", test.unreached_func("'error' should not be fired on sourceBuffer"));
|
||||
|
||||
test.expectEvent(mediaElement, "error", "mediaElement error.");
|
||||
test.expectEvent(mediaSource, "sourceended", "mediaSource ended.");
|
||||
test.expectEvent(mediaSource, "sourceclose", "mediaSource closed.");
|
||||
|
||||
mediaSource.endOfStream("decode");
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_true(mediaElement.error != null);
|
||||
assert_equals(mediaElement.error.code, MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED);
|
||||
|
||||
assert_equals(mediaSource.sourceBuffers.length, 0);
|
||||
assert_equals(mediaSource.readyState, "closed");
|
||||
|
||||
// Give a short time for a broken implementation to errantly fire
|
||||
// "error" on sourceBuffer.
|
||||
test.step_timeout(test.step_func_done(), 0);
|
||||
});
|
||||
}, "Signaling 'decode' error via endOfStream() before initialization segment has been appended.");
|
||||
|
||||
ErrorTest(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
assert_equals(mediaElement.readyState, HTMLMediaElement.HAVE_NOTHING);
|
||||
|
||||
// Fail if the append error algorithm occurs, since the network
|
||||
// error will be provided by us directly via endOfStream().
|
||||
sourceBuffer.addEventListener("error", test.unreached_func("'error' should not be fired on sourceBuffer"));
|
||||
|
||||
test.expectEvent(mediaElement, "error", "mediaElement error.");
|
||||
test.expectEvent(mediaSource, "sourceended", "mediaSource ended.");
|
||||
test.expectEvent(mediaSource, "sourceclose", "mediaSource closed.");
|
||||
|
||||
mediaSource.endOfStream("network");
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_true(mediaElement.error != null);
|
||||
assert_equals(mediaElement.error.code, MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED);
|
||||
|
||||
assert_equals(mediaSource.sourceBuffers.length, 0);
|
||||
assert_equals(mediaSource.readyState, "closed");
|
||||
|
||||
// Give a short time for a broken implementation to errantly fire
|
||||
// "error" on sourceBuffer.
|
||||
test.step_timeout(test.step_func_done(), 0);
|
||||
});
|
||||
}, "Signaling 'network' error via endOfStream() before initialization segment has been appended.");
|
||||
|
||||
ErrorTest(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
|
||||
assert_equals(mediaElement.readyState, HTMLMediaElement.HAVE_NOTHING);
|
||||
|
||||
// Fail if the append error algorithm occurs, since the decode
|
||||
// error will be provided by us directly via endOfStream().
|
||||
sourceBuffer.addEventListener("error", test.unreached_func("'error' should not be fired on sourceBuffer"));
|
||||
|
||||
test.expectEvent(sourceBuffer, "updateend", "mediaSegment append ended.");
|
||||
test.expectEvent(mediaElement, "loadedmetadata", "mediaElement metadata.");
|
||||
sourceBuffer.appendBuffer(initSegment);
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_equals(mediaElement.readyState, HTMLMediaElement.HAVE_METADATA);
|
||||
|
||||
test.expectEvent(mediaElement, "error", "mediaElement error.");
|
||||
test.expectEvent(mediaSource, "sourceended", "mediaSource ended.");
|
||||
mediaSource.endOfStream("decode");
|
||||
});
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_true(mediaElement.error != null);
|
||||
assert_equals(mediaElement.error.code, MediaError.MEDIA_ERR_DECODE);
|
||||
assert_equals(mediaSource.readyState, "ended");
|
||||
|
||||
// Give a short time for a broken implementation to errantly fire
|
||||
// "error" on sourceBuffer.
|
||||
test.step_timeout(test.step_func_done(), 0);
|
||||
});
|
||||
|
||||
}, "Signaling 'decode' error via endOfStream() after initialization segment has been appended and the HTMLMediaElement has reached HAVE_METADATA.");
|
||||
|
||||
ErrorTest(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
|
||||
assert_equals(mediaElement.readyState, HTMLMediaElement.HAVE_NOTHING);
|
||||
|
||||
// Fail if the append error algorithm occurs, since the network
|
||||
// error will be provided by us directly via endOfStream().
|
||||
sourceBuffer.addEventListener("error", test.unreached_func("'error' should not be fired on sourceBuffer"));
|
||||
|
||||
test.expectEvent(sourceBuffer, "updateend", "mediaSegment append ended.");
|
||||
test.expectEvent(mediaElement, "loadedmetadata", "mediaElement metadata.");
|
||||
sourceBuffer.appendBuffer(initSegment);
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_equals(mediaElement.readyState, HTMLMediaElement.HAVE_METADATA);
|
||||
test.expectEvent(mediaElement, "error", "mediaElement error.");
|
||||
test.expectEvent(mediaSource, "sourceended", "mediaSource ended.");
|
||||
mediaSource.endOfStream("network");
|
||||
});
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_true(mediaElement.error != null);
|
||||
assert_equals(mediaElement.error.code, MediaError.MEDIA_ERR_NETWORK);
|
||||
assert_equals(mediaSource.readyState, "ended");
|
||||
|
||||
// Give a short time for a broken implementation to errantly fire
|
||||
// "error" on sourceBuffer.
|
||||
test.step_timeout(test.step_func_done(), 0);
|
||||
});
|
||||
}, "Signaling 'network' error via endOfStream() after initialization segment has been appended and the HTMLMediaElement has reached HAVE_METADATA.");
|
||||
|
||||
ErrorTest(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
assert_equals(mediaElement.readyState, HTMLMediaElement.HAVE_NOTHING);
|
||||
|
||||
var mediaSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[0]);
|
||||
var index = segmentInfo.init.size + (mediaSegment.length - 1) / 2;
|
||||
// Corrupt the media data from index of mediaData, so it can signal 'decode' error.
|
||||
// Here use mediaSegment to replace the original mediaData[index, index + mediaSegment.length]
|
||||
mediaData.set(mediaSegment, index);
|
||||
|
||||
test.expectEvent(mediaElement, "loadedmetadata", "mediaElement metadata.");
|
||||
test.expectEvent(sourceBuffer, "error", "sourceBuffer error.");
|
||||
test.expectEvent(sourceBuffer, "updateend", "mediaSegment append ended.");
|
||||
test.expectEvent(mediaElement, "error", "mediaElement error.");
|
||||
test.expectEvent(mediaSource, "sourceended", "mediaSource ended.");
|
||||
sourceBuffer.appendBuffer(mediaData);
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_true(mediaElement.error != null);
|
||||
assert_equals(mediaElement.error.code, MediaError.MEDIA_ERR_DECODE);
|
||||
test.done();
|
||||
});
|
||||
}, "Signaling 'decode' error via segment parser loop algorithm after initialization segment and partial media segment has been appended.");
|
||||
</script>
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>HTMLVideoElement.getVideoPlaybackQuality() test cases.</title>
|
||||
|
@ -17,45 +18,47 @@
|
|||
{
|
||||
var videoElement = e.target;
|
||||
var newQuality = videoElement.getVideoPlaybackQuality();
|
||||
var now = window.performance.now();
|
||||
|
||||
assert_not_equals(previousQuality, newQuality, "Verify new object");
|
||||
assert_greater_than(newQuality.creationTime, previousQuality.creationTime, "creationTime");
|
||||
assert_not_equals(previousQuality, newQuality,
|
||||
"New quality object is different from the previous one");
|
||||
assert_greater_than(newQuality.creationTime, previousQuality.creationTime,
|
||||
"creationTime increases monotonically");
|
||||
assert_approx_equals(newQuality.creationTime, now, 100,
|
||||
"creationTime roughly equals current time");
|
||||
|
||||
assert_greater_than_equal(newQuality.totalVideoFrames, 0, "totalVideoFrames >= 0");
|
||||
assert_greater_than_equal(newQuality.totalVideoFrames, previousQuality.totalVideoFrames, "totalVideoFrames");
|
||||
assert_greater_than_equal(newQuality.totalVideoFrames, previousQuality.totalVideoFrames,
|
||||
"totalVideoFrames increases monotonically");
|
||||
assert_less_than(newQuality.totalVideoFrames, 300,
|
||||
"totalVideoFrames should remain low as duration is less than 10s and framerate less than 30fps");
|
||||
|
||||
assert_greater_than_equal(newQuality.droppedVideoFrames, 0, "droppedVideoFrames >= 0");
|
||||
assert_greater_than_equal(newQuality.droppedVideoFrames, previousQuality.droppedVideoFrames, "droppedVideoFrames");
|
||||
assert_greater_than_equal(newQuality.droppedVideoFrames, previousQuality.droppedVideoFrames,
|
||||
"droppedVideoFrames increases monotonically");
|
||||
assert_less_than_equal(newQuality.droppedVideoFrames, newQuality.totalVideoFrames,
|
||||
"droppedVideoFrames is only a portion of totalVideoFrames");
|
||||
|
||||
assert_greater_than_equal(newQuality.corruptedVideoFrames, 0, "corruptedVideoFrames >= 0");
|
||||
assert_greater_than_equal(newQuality.corruptedVideoFrames, previousQuality.corruptedVideoFrames, "corruptedVideoFrames");
|
||||
assert_greater_than_equal(newQuality.corruptedVideoFrames, previousQuality.corruptedVideoFrames,
|
||||
"corruptedVideoFrames increases monotonically");
|
||||
assert_less_than_equal(newQuality.corruptedVideoFrames, newQuality.totalVideoFrames,
|
||||
"corruptedVideoFrames is only a portion of totalVideoFrames");
|
||||
|
||||
previousQuality = newQuality;
|
||||
timeUpdateCount++;
|
||||
}));
|
||||
|
||||
mediaElement.addEventListener('error', test.unreached_func("Unexpected event 'error'"));
|
||||
|
||||
test.expectEvent(sourceBuffer, 'updatestart', 'sourceBuffer');
|
||||
test.expectEvent(sourceBuffer, 'update', 'sourceBuffer');
|
||||
test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
|
||||
sourceBuffer.appendBuffer(mediaData);
|
||||
test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_false(sourceBuffer.updating, "updating");
|
||||
assert_greater_than(mediaSource.duration, 1, "duration");
|
||||
|
||||
mediaSource.duration = 1;
|
||||
|
||||
assert_true(sourceBuffer.updating, "updating");
|
||||
test.expectEvent(sourceBuffer, 'updatestart', 'sourceBuffer');
|
||||
test.expectEvent(sourceBuffer, 'update', 'sourceBuffer');
|
||||
test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
|
||||
});
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
mediaSource.endOfStream();
|
||||
assert_less_than(mediaSource.duration, 10, "duration");
|
||||
mediaElement.play();
|
||||
test.expectEvent(mediaElement, 'ended', 'mediaElement');
|
||||
});
|
||||
|
@ -66,6 +69,49 @@
|
|||
test.done();
|
||||
});
|
||||
}, "Test HTMLVideoElement.getVideoPlaybackQuality() with MediaSource API");
|
||||
|
||||
|
||||
mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
var previousQuality = mediaElement.getVideoPlaybackQuality();
|
||||
var timeUpdateCount = 0;
|
||||
var startTime = 0;
|
||||
mediaElement.addEventListener("timeupdate", test.step_func(function (e)
|
||||
{
|
||||
var videoElement = e.target;
|
||||
var newQuality = videoElement.getVideoPlaybackQuality();
|
||||
var now = window.performance.now();
|
||||
|
||||
assert_greater_than_equal(newQuality.totalFrameDelay, 0, "totalFrameDelay >= 0");
|
||||
assert_greater_than_equal(newQuality.totalFrameDelay, previousQuality.totalFrameDelay,
|
||||
"totalFrameDelay increases monotonically");
|
||||
assert_less_than(newQuality.totalFrameDelay, (now - startTime) / 1000,
|
||||
"totalFrameDelay does not exceed the time elapsed since playback started");
|
||||
|
||||
previousQuality = newQuality;
|
||||
timeUpdateCount++;
|
||||
}));
|
||||
|
||||
mediaElement.addEventListener('error', test.unreached_func("Unexpected event 'error'"));
|
||||
|
||||
sourceBuffer.appendBuffer(mediaData);
|
||||
test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_false(sourceBuffer.updating, "updating");
|
||||
mediaSource.endOfStream();
|
||||
assert_less_than(mediaSource.duration, 10, "duration");
|
||||
startTime = window.performance.now();
|
||||
mediaElement.play();
|
||||
test.expectEvent(mediaElement, 'ended', 'mediaElement');
|
||||
});
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_greater_than(timeUpdateCount, 2, "timeUpdateCount");
|
||||
test.done();
|
||||
});
|
||||
}, "Test the totalFrameDelay attribute of HTMLVideoElement.getVideoPlaybackQuality() with MediaSource API");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>MediaSource.isTypeSupported() 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>
|
||||
|
@ -34,6 +36,12 @@
|
|||
null
|
||||
], false, 'Test invalid MIME format');
|
||||
|
||||
test_type_support([
|
||||
'xxx',
|
||||
'text/html',
|
||||
'image/jpeg'
|
||||
], false, 'Test invalid MSE MIME media type');
|
||||
|
||||
test_type_support([
|
||||
'audio/webm;codecs="vp8"',
|
||||
'audio/mp4;codecs="avc1.4d001e"',
|
||||
|
@ -45,7 +53,6 @@
|
|||
'video/mp4;codecs="vp8"',
|
||||
'video/webm;codecs="mp4a.40.2"',
|
||||
'video/mp4;codecs="vorbis"',
|
||||
'video/webm;codecs="mp4a.40.2"',
|
||||
], false, 'Test invalid mismatch between minor type and codec ID');
|
||||
|
||||
test_type_support([
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<meta charset="utf-8">
|
||||
<title>Checks setting/clearing the live seekable range and HTMLMediaElement.seekable</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
|
@ -28,9 +29,9 @@ mediasource_test(function(test, mediaElement, mediaSource)
|
|||
var sourceBuffer = mediaSource.addSourceBuffer(mimetype);
|
||||
sourceBuffer.appendBuffer(new Uint8Array(0));
|
||||
assert_true(sourceBuffer.updating, "Updating set when a buffer is appended.");
|
||||
assert_throws("InvalidStateError", function() { mediaSource.setLiveSeekableRange(0, 1); });
|
||||
mediaSource.setLiveSeekableRange(0, 1);
|
||||
test.done();
|
||||
}, "setLiveSeekableRange throws an InvalidStateError exception if a SourceBuffer is updating");
|
||||
}, "setLiveSeekableRange does not restrict to not currently updating");
|
||||
|
||||
|
||||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
|
@ -40,9 +41,9 @@ mediasource_test(function(test, mediaElement, mediaSource)
|
|||
var sourceBuffer = mediaSource.addSourceBuffer(mimetype);
|
||||
sourceBuffer.appendBuffer(new Uint8Array(0));
|
||||
assert_true(sourceBuffer.updating, "Updating set when a buffer is appended.");
|
||||
assert_throws("InvalidStateError", function() { mediaSource.clearLiveSeekableRange(); });
|
||||
mediaSource.clearLiveSeekableRange();
|
||||
test.done();
|
||||
}, "clearLiveSeekableRange throws an InvalidStateError exception if a SourceBuffer is updating");
|
||||
}, "clearLiveSeekableRange does not restrict to not currently updating");
|
||||
|
||||
|
||||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
|
@ -133,4 +134,4 @@ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmen
|
|||
});
|
||||
});
|
||||
}, 'HTMLMediaElement.seekable returns the union of the buffered range and the live seekable range, when set');
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Test Attaching a MediaSource to multiple HTMLMediaElements.</title>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Simple MediaSource playback & seek test case.</title>
|
||||
|
@ -30,8 +31,6 @@
|
|||
|
||||
function finishSeekThenPlay()
|
||||
{
|
||||
assert_true(mediaElement.seeking, 'mediaElement is seeking');
|
||||
assert_equals(mediaElement.currentTime, 0.0, 'Current time is 0.0');
|
||||
test.expectEvent(mediaElement, 'seeked', 'mediaElement finished seek');
|
||||
|
||||
test.waitForExpectedEvents(confirmPlayThenEnd);
|
||||
|
@ -42,6 +41,7 @@
|
|||
assert_greater_than(mediaElement.currentTime, 0.0, 'Playback has started.');
|
||||
test.expectEvent(mediaElement, 'seeking', 'mediaElement');
|
||||
mediaElement.currentTime = 0.0;
|
||||
assert_true(mediaElement.seeking, 'mediaElement is seeking');
|
||||
|
||||
test.waitForExpectedEvents(finishSeekThenPlay);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Simple MediaSource playback test case.</title>
|
||||
|
@ -23,9 +24,8 @@
|
|||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_false(sourceBuffer.updating, "updating");
|
||||
assert_greater_than(mediaSource.duration, 1, "duration");
|
||||
|
||||
mediaSource.duration = 1;
|
||||
sourceBuffer.remove(1, Infinity);
|
||||
|
||||
assert_true(sourceBuffer.updating, "updating");
|
||||
test.expectEvent(sourceBuffer, 'updatestart', 'sourceBuffer');
|
||||
|
@ -33,6 +33,16 @@
|
|||
test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
|
||||
});
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_false(sourceBuffer.updating, "updating");
|
||||
assert_greater_than(mediaSource.duration, 1, "duration");
|
||||
|
||||
mediaSource.duration = 1;
|
||||
|
||||
test.expectEvent(mediaElement, "durationchange");
|
||||
});
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
mediaSource.endOfStream();
|
||||
|
|
|
@ -64,11 +64,9 @@
|
|||
|
||||
errorWithPreloadTest("auto", "revoked");
|
||||
errorWithPreloadTest("metadata", "revoked");
|
||||
errorWithPreloadTest("none", "revoked");
|
||||
|
||||
errorWithPreloadTest("auto", "corrupted");
|
||||
errorWithPreloadTest("metadata", "corrupted");
|
||||
errorWithPreloadTest("none", "corrupted");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Test MediaSource behavior when receiving multiple seek requests during a pending seek.</title>
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<!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>
|
||||
|
@ -13,7 +15,9 @@
|
|||
{
|
||||
var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
|
||||
|
||||
assert_throws("InvalidAccessError", function()
|
||||
mediaSource.duration = 10;
|
||||
|
||||
assert_throws(new TypeError(), function()
|
||||
{
|
||||
sourceBuffer.remove(-1, 2);
|
||||
}, "remove");
|
||||
|
@ -25,6 +29,8 @@
|
|||
{
|
||||
var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
|
||||
|
||||
mediaSource.duration = 10;
|
||||
|
||||
[ undefined, NaN, Infinity, -Infinity ].forEach(function(item)
|
||||
{
|
||||
assert_throws(new TypeError(), function()
|
||||
|
@ -42,7 +48,7 @@
|
|||
|
||||
mediaSource.duration = 10;
|
||||
|
||||
assert_throws("InvalidAccessError", function()
|
||||
assert_throws(new TypeError(), function()
|
||||
{
|
||||
sourceBuffer.remove(11, 12);
|
||||
}, "remove");
|
||||
|
@ -56,7 +62,7 @@
|
|||
|
||||
mediaSource.duration = 10;
|
||||
|
||||
assert_throws("InvalidAccessError", function()
|
||||
assert_throws(new TypeError(), function()
|
||||
{
|
||||
sourceBuffer.remove(2, 1);
|
||||
}, "remove");
|
||||
|
@ -68,7 +74,9 @@
|
|||
{
|
||||
var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
|
||||
|
||||
assert_throws("InvalidAccessError", function()
|
||||
mediaSource.duration = 10;
|
||||
|
||||
assert_throws(new TypeError(), function()
|
||||
{
|
||||
sourceBuffer.remove(0, Number.NEGATIVE_INFINITY);
|
||||
}, "remove");
|
||||
|
@ -80,7 +88,9 @@
|
|||
{
|
||||
var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
|
||||
|
||||
assert_throws("InvalidAccessError", function()
|
||||
mediaSource.duration = 10;
|
||||
|
||||
assert_throws(new TypeError(), function()
|
||||
{
|
||||
sourceBuffer.remove(0, Number.NaN);
|
||||
}, "remove");
|
||||
|
@ -104,6 +114,20 @@
|
|||
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)
|
||||
{
|
||||
|
@ -136,15 +160,18 @@
|
|||
mediaSource.duration = 10;
|
||||
|
||||
test.expectEvent(sourceBuffer, "updatestart");
|
||||
test.expectEvent(sourceBuffer, "abort");
|
||||
test.expectEvent(sourceBuffer, "update");
|
||||
test.expectEvent(sourceBuffer, "updateend");
|
||||
sourceBuffer.remove(1, 2);
|
||||
|
||||
assert_true(sourceBuffer.updating, "updating");
|
||||
|
||||
sourceBuffer.abort();
|
||||
assert_throws("InvalidStateError", function()
|
||||
{
|
||||
sourceBuffer.abort();
|
||||
}, "abort");
|
||||
|
||||
assert_false(sourceBuffer.updating, "updating");
|
||||
assert_true(sourceBuffer.updating, "updating");
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
|
@ -197,6 +224,7 @@
|
|||
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");
|
||||
|
@ -224,11 +252,12 @@
|
|||
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, "{ [0.000, " + duration + ") }", "Initial buffered range.");
|
||||
callback(test, mediaSource, sourceBuffer, duration, subType);
|
||||
assertBufferedEquals(sourceBuffer, "{ [" + start + ", " + duration + ") }", "Initial buffered range.");
|
||||
callback(test, mediaSource, sourceBuffer, duration, subType, segmentInfo);
|
||||
});
|
||||
}, description);
|
||||
};
|
||||
|
@ -249,16 +278,16 @@
|
|||
});
|
||||
}
|
||||
|
||||
removeAppendedDataTests(function(test, mediaSource, sourceBuffer, duration, subType)
|
||||
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)
|
||||
removeAppendedDataTests(function(test, mediaSource, sourceBuffer, duration, subType, segmentInfo)
|
||||
{
|
||||
var expectations = {
|
||||
webm: ("{ [3.187, " + duration + ") }"),
|
||||
mp4: ("{ [3.154, " + duration + ") }"),
|
||||
mp4: ("{ [3.187, " + duration + ") }"),
|
||||
};
|
||||
|
||||
// Note: Range doesn't start exactly at the end of the remove range because there isn't
|
||||
|
@ -266,11 +295,12 @@
|
|||
removeAndCheckBufferedRanges(test, mediaSource, sourceBuffer, 0, 3, expectations[subType]);
|
||||
}, "Test removing beginning of appended data.");
|
||||
|
||||
removeAppendedDataTests(function(test, mediaSource, sourceBuffer, duration, subType)
|
||||
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: ("{ [0.000, 1.012) [3.187, " + duration + ") }"),
|
||||
mp4: ("{ [0.000, 1.022) [3.154, " + duration + ") }"),
|
||||
webm: ("{ [" + start + ", 1.012) [3.187, " + duration + ") }"),
|
||||
mp4: ("{ [" + start + ", 0.996) [3.187, " + duration + ") }"),
|
||||
};
|
||||
|
||||
// Note: The first resulting range ends slightly after start because the removal algorithm only removes
|
||||
|
@ -279,11 +309,12 @@
|
|||
removeAndCheckBufferedRanges(test, mediaSource, sourceBuffer, 1, 3, expectations[subType]);
|
||||
}, "Test removing the middle of appended data.");
|
||||
|
||||
removeAppendedDataTests(function(test, mediaSource, sourceBuffer, duration, subType)
|
||||
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: "{ [0.000, 1.012) }",
|
||||
mp4: "{ [0.000, 1.029) }",
|
||||
webm: "{ [" + start + ", 1.029) }",
|
||||
mp4: "{ [" + start + ", 1.022) }",
|
||||
};
|
||||
|
||||
removeAndCheckBufferedRanges(test, mediaSource, sourceBuffer, 1, Number.POSITIVE_INFINITY, expectations[subType]);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>MediaSource.removeSourceBuffer() test cases.</title>
|
||||
|
@ -12,13 +13,13 @@
|
|||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
{
|
||||
var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
|
||||
assert_true(sourceBuffer != null, "New SourceBuffer returned");
|
||||
assert_class_string(sourceBuffer, "SourceBuffer", "New SourceBuffer returned");
|
||||
|
||||
mediaSource.removeSourceBuffer(sourceBuffer);
|
||||
|
||||
var sourceBuffer2 = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
|
||||
assert_true(sourceBuffer2 != null, "New SourceBuffer returned");
|
||||
assert_true(sourceBuffer != sourceBuffer2, "SourceBuffers are different instances.");
|
||||
assert_class_string(sourceBuffer2, "SourceBuffer", "New SourceBuffer returned");
|
||||
assert_not_equals(sourceBuffer, sourceBuffer2, "SourceBuffers are different instances.");
|
||||
assert_equals(mediaSource.sourceBuffers.length, 1, "sourceBuffers.length == 1");
|
||||
|
||||
test.done();
|
||||
|
@ -35,28 +36,63 @@
|
|||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
{
|
||||
var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
|
||||
assert_true(sourceBuffer != null, "New SourceBuffer returned");
|
||||
assert_class_string(sourceBuffer, "SourceBuffer", "New SourceBuffer returned");
|
||||
|
||||
mediaSource.removeSourceBuffer(sourceBuffer);
|
||||
|
||||
assert_throws("NotFoundError",
|
||||
function() { mediaSource.removeSourceBuffer(sourceBuffer); },
|
||||
"removeSourceBuffer() threw an exception when a SourceBuffer that was already removed.");
|
||||
"removeSourceBuffer() threw an exception for a SourceBuffer that was already removed.");
|
||||
|
||||
test.done();
|
||||
}, "Test calling removeSourceBuffer() twice with the same object.");
|
||||
|
||||
mediasource_test(function(test, mediaElement1, mediaSource1)
|
||||
{
|
||||
var sourceBuffer1 = mediaSource1.addSourceBuffer(MediaSourceUtil.AUDIO_ONLY_TYPE);
|
||||
assert_class_string(sourceBuffer1, "SourceBuffer", "New SourceBuffer returned");
|
||||
|
||||
var mediaElement2 = document.createElement("video");
|
||||
document.body.appendChild(mediaElement2);
|
||||
test.add_cleanup(function() { document.body.removeChild(mediaElement2); });
|
||||
|
||||
var mediaSource2 = new MediaSource();
|
||||
var mediaSource2URL = URL.createObjectURL(mediaSource2);
|
||||
mediaElement2.src = mediaSource2URL;
|
||||
test.expectEvent(mediaSource2, "sourceopen", "Second MediaSource opened");
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
URL.revokeObjectURL(mediaSource2URL);
|
||||
|
||||
var sourceBuffer2 = mediaSource2.addSourceBuffer(MediaSourceUtil.VIDEO_ONLY_TYPE);
|
||||
assert_class_string(sourceBuffer2, "SourceBuffer", "Second new SourceBuffer returned");
|
||||
assert_not_equals(mediaSource1, mediaSource2, "MediaSources are different instances");
|
||||
assert_not_equals(sourceBuffer1, sourceBuffer2, "SourceBuffers are different instances");
|
||||
assert_equals(mediaSource1.sourceBuffers[0], sourceBuffer1);
|
||||
assert_equals(mediaSource2.sourceBuffers[0], sourceBuffer2);
|
||||
assert_throws("NotFoundError",
|
||||
function() { mediaSource1.removeSourceBuffer(sourceBuffer2); },
|
||||
"MediaSource1.removeSourceBuffer() threw an exception for SourceBuffer2");
|
||||
assert_throws("NotFoundError",
|
||||
function() { mediaSource2.removeSourceBuffer(sourceBuffer1); },
|
||||
"MediaSource2.removeSourceBuffer() threw an exception for SourceBuffer1");
|
||||
mediaSource1.removeSourceBuffer(sourceBuffer1);
|
||||
mediaSource2.removeSourceBuffer(sourceBuffer2);
|
||||
test.done();
|
||||
});
|
||||
}, "Test calling removeSourceBuffer() for a sourceBuffer belonging to a different mediaSource instance.");
|
||||
|
||||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
{
|
||||
var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
|
||||
assert_true(sourceBuffer != null, "New SourceBuffer returned");
|
||||
assert_class_string(sourceBuffer, "SourceBuffer", "New SourceBuffer returned");
|
||||
|
||||
mediaSource.endOfStream();
|
||||
assert_true(mediaSource.readyState == "ended", "MediaSource in ended state");
|
||||
assert_equals(mediaSource.readyState, "ended", "MediaSource in ended state");
|
||||
mediaSource.removeSourceBuffer(sourceBuffer);
|
||||
|
||||
assert_true(mediaSource.sourceBuffers.length == 0, "MediaSource.sourceBuffers is empty");
|
||||
assert_true(mediaSource.activeSourceBuffers.length == 0, "MediaSource.activesourceBuffers is empty");
|
||||
assert_equals(mediaSource.sourceBuffers.length, 0, "MediaSource.sourceBuffers is empty");
|
||||
assert_equals(mediaSource.activeSourceBuffers.length, 0, "MediaSource.activesourceBuffers is empty");
|
||||
|
||||
test.done();
|
||||
}, "Test calling removeSourceBuffer() in ended state.");
|
||||
|
@ -71,8 +107,8 @@
|
|||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_true(mediaSource.sourceBuffers.length == 1, "MediaSource.sourceBuffers is not empty");
|
||||
assert_true(mediaSource.activeSourceBuffers.length == 1, "MediaSource.activesourceBuffers is not empty");
|
||||
assert_equals(mediaSource.sourceBuffers.length, 1, "MediaSource.sourceBuffers is not empty");
|
||||
assert_equals(mediaSource.activeSourceBuffers.length, 1, "MediaSource.activesourceBuffers is not empty");
|
||||
assert_equals(mediaElement.readyState, mediaElement.HAVE_METADATA);
|
||||
assert_equals(mediaSource.duration, segmentInfo.duration);
|
||||
test.expectEvent(mediaSource.activeSourceBuffers, "removesourcebuffer", "SourceBuffer removed from activeSourceBuffers.");
|
||||
|
@ -82,11 +118,29 @@
|
|||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_true(mediaSource.sourceBuffers.length == 0, "MediaSource.sourceBuffers is empty");
|
||||
assert_true(mediaSource.activeSourceBuffers.length == 0, "MediaSource.activesourceBuffers is empty");
|
||||
assert_equals(mediaSource.sourceBuffers.length, 0, "MediaSource.sourceBuffers is empty");
|
||||
assert_equals(mediaSource.activeSourceBuffers.length, 0, "MediaSource.activesourceBuffers is empty");
|
||||
test.done();
|
||||
});
|
||||
}, "Test removesourcebuffer event on activeSourceBuffers.");
|
||||
|
||||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
{
|
||||
mediaElement.addEventListener('error', test.unreached_func("Unexpected event 'error'"));
|
||||
var mimetype = MediaSourceUtil.AUDIO_VIDEO_TYPE;
|
||||
var sourceBuffer = mediaSource.addSourceBuffer(mimetype);
|
||||
sourceBuffer.appendBuffer(new Uint8Array(0));
|
||||
assert_true(sourceBuffer.updating, "Updating flag set when a buffer is appended.");
|
||||
test.expectEvent(sourceBuffer, 'abort');
|
||||
test.expectEvent(sourceBuffer, 'updateend');
|
||||
|
||||
mediaSource.removeSourceBuffer(sourceBuffer);
|
||||
assert_false(sourceBuffer.updating, "Updating flag reset after abort.");
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
test.done();
|
||||
});
|
||||
}, "Test abort event when removeSourceBuffer() called while SourceBuffer is updating");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Test MediaSource behavior when seeking beyond the duration of the clip.</title>
|
||||
|
@ -62,6 +63,15 @@
|
|||
{
|
||||
assert_equals(mediaElement.duration, segmentInfo.duration);
|
||||
assert_greater_than_equal(mediaElement.duration, 2.0, 'Duration is >2.0s.');
|
||||
|
||||
test.expectEvent(sourceBuffer, "updateend");
|
||||
sourceBuffer.remove(1.5, Infinity);
|
||||
assert_true(sourceBuffer.updating, "updating");
|
||||
});
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_false(sourceBuffer.updating, "updating");
|
||||
test.waitForCurrentTimeChange(mediaElement, function()
|
||||
{
|
||||
// Update duration.
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Test MediaSource behavior when a seek is requested while another seek is pending.</title>
|
||||
|
@ -30,7 +31,7 @@
|
|||
|
||||
// Seek to a new position before letting the initial seek to 0 completes.
|
||||
test.expectEvent(mediaElement, 'seeking', 'mediaElement');
|
||||
mediaElement.currentTime = secondSegmentInfo.timecode;
|
||||
mediaElement.currentTime = Math.max(secondSegmentInfo.timev, secondSegmentInfo.timea);
|
||||
assert_true(mediaElement.seeking, 'mediaElement is seeking');
|
||||
|
||||
// Append media data for time 0.
|
||||
|
@ -53,13 +54,36 @@
|
|||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
test.expectEvent(mediaSource, 'sourceended', 'mediaSource ended');
|
||||
mediaSource.endOfStream();
|
||||
if (sourceBuffer.updating)
|
||||
{
|
||||
// The event playing was fired prior to the appendBuffer completing.
|
||||
test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_false(sourceBuffer.updating, 'append have compleded');
|
||||
test.expectEvent(mediaSource, 'sourceended', 'mediaSource ended');
|
||||
mediaSource.endOfStream();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
test.expectEvent(mediaSource, 'sourceended', 'mediaSource ended');
|
||||
mediaSource.endOfStream();
|
||||
}
|
||||
});
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_greater_than(mediaElement.readyState, mediaElement.HAVE_CURRENT_DATA, 'Greater than HAVE_CURRENT_DATA');
|
||||
// Note: we just completed the seek. However, we only have less than a second worth of data to play. It is possible that
|
||||
// playback has reached the end since the seek completed.
|
||||
if (!mediaElement.paused)
|
||||
{
|
||||
assert_greater_than_equal(mediaElement.readyState, mediaElement.HAVE_CURRENT_DATA, 'Greater or equal than HAVE_CURRENT_DATA');
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_true(mediaElement.ended);
|
||||
}
|
||||
test.done();
|
||||
});
|
||||
|
||||
|
@ -94,7 +118,7 @@
|
|||
|
||||
// Seek to a new position.
|
||||
test.expectEvent(mediaElement, 'seeking', 'mediaElement');
|
||||
mediaElement.currentTime = secondSegmentInfo.timecode;
|
||||
mediaElement.currentTime = Math.max(secondSegmentInfo.timev, secondSegmentInfo.timea);
|
||||
assert_true(mediaElement.seeking, 'mediaElement is seeking');
|
||||
|
||||
});
|
||||
|
@ -105,7 +129,7 @@
|
|||
|
||||
// Seek to a second position while the first seek is still pending.
|
||||
test.expectEvent(mediaElement, 'seeking', 'mediaElement');
|
||||
mediaElement.currentTime = thirdSegmentInfo.timecode;
|
||||
mediaElement.currentTime = Math.max(thirdSegmentInfo.timev, thirdSegmentInfo.timea);
|
||||
assert_true(mediaElement.seeking, 'mediaElement is seeking');
|
||||
|
||||
// Append media data for the first seek position.
|
||||
|
@ -115,10 +139,10 @@
|
|||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_true(mediaElement.seeking, 'mediaElement is still seeking');
|
||||
// Note that we can't assume that the element is still seeking
|
||||
// when the seeking event is fired as the operation is asynchronous.
|
||||
|
||||
// Append media data for the second seek position.
|
||||
test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
|
||||
test.expectEvent(mediaElement, 'seeked', 'mediaElement finished seek');
|
||||
MediaSourceUtil.appendUntilEventFires(test, mediaElement, 'seeked', sourceBuffer, mediaData, segmentInfo, segmentIndex);
|
||||
});
|
||||
|
@ -127,13 +151,36 @@
|
|||
{
|
||||
assert_false(mediaElement.seeking, 'mediaElement is no longer seeking');
|
||||
|
||||
test.expectEvent(mediaSource, 'sourceended', 'mediaSource ended');
|
||||
mediaSource.endOfStream();
|
||||
if (sourceBuffer.updating)
|
||||
{
|
||||
// The event seeked was fired prior to the appendBuffer completing.
|
||||
test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_false(sourceBuffer.updating, 'append have compleded');
|
||||
test.expectEvent(mediaSource, 'sourceended', 'mediaSource ended');
|
||||
mediaSource.endOfStream();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
test.expectEvent(mediaSource, 'sourceended', 'mediaSource ended');
|
||||
mediaSource.endOfStream();
|
||||
}
|
||||
});
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_greater_than(mediaElement.readyState, mediaElement.HAVE_CURRENT_DATA, 'Greater than HAVE_CURRENT_DATA');
|
||||
// Note: we just completed the seek. However, we only have less than a second worth of data to play. It is possible that
|
||||
// playback has reached the end since the seek completed.
|
||||
if (!mediaElement.paused)
|
||||
{
|
||||
assert_greater_than_equal(mediaElement.readyState, mediaElement.HAVE_CURRENT_DATA, 'Greater or equal than HAVE_CURRENT_DATA');
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_true(mediaElement.ended);
|
||||
}
|
||||
test.done();
|
||||
});
|
||||
}, 'Test seeking to a new location during a pending seek.');
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<meta charset="utf-8">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="mediasource-util.js"></script>
|
||||
<script>
|
||||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
{
|
||||
mediaElement.addEventListener('error', test.unreached_func("Unexpected event 'error'"));
|
||||
mediaElement.addEventListener('ended', test.step_func_done(function () {}));
|
||||
|
||||
var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_ONLY_TYPE);
|
||||
|
||||
assertSeekableEquals(mediaElement, '{ }', 'mediaElement.seekable');
|
||||
test.done();
|
||||
}, 'Get seekable time ranges when the sourcebuffer is empty.');
|
||||
|
||||
mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
|
||||
test.expectEvent(mediaElement, 'durationchange', 'mediaElement got duration');
|
||||
sourceBuffer.appendBuffer(initSegment);
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_equals(mediaElement.duration, segmentInfo.duration);
|
||||
assertSeekableEquals(mediaElement, '{ [0.000, ' + segmentInfo.duration.toFixed(3) + ') }', 'mediaElement.seekable');
|
||||
test.done();
|
||||
});
|
||||
}, 'Get seekable time ranges after init segment received.');
|
||||
|
||||
mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
|
||||
test.expectEvent(mediaElement, 'durationchange', 'mediaElement got duration after initsegment');
|
||||
sourceBuffer.appendBuffer(initSegment);
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
test.expectEvent(mediaElement, 'durationchange', 'mediaElement got infinity duration');
|
||||
mediaSource.duration = Infinity;
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assertSeekableEquals(mediaElement, '{ }', 'mediaElement.seekable');
|
||||
|
||||
// Append a segment from the middle of the stream to make sure that seekable does not use buffered.start(0) or duration as first or last value
|
||||
var midSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[2]);
|
||||
test.expectEvent(sourceBuffer, 'update');
|
||||
test.expectEvent(sourceBuffer, 'updateend');
|
||||
sourceBuffer.appendBuffer(midSegment);
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_equals(mediaElement.seekable.length, 1, 'mediaElement.seekable.length');
|
||||
assert_equals(mediaElement.buffered.length, 1, 'mediaElement.buffered.length');
|
||||
assert_not_equals(mediaElement.seekable.start(0), mediaElement.buffered.start(0));
|
||||
assert_equals(mediaElement.seekable.start(0), 0);
|
||||
assert_not_equals(mediaElement.seekable.end(0), mediaElement.duration);
|
||||
assert_not_equals(mediaElement.seekable.end(0), mediaElement.buffered.start(0));
|
||||
assert_equals(mediaElement.seekable.end(0), mediaElement.buffered.end(0));
|
||||
test.done();
|
||||
});
|
||||
});
|
||||
});
|
||||
}, 'Get seekable time ranges on an infinite stream.');
|
||||
</script>
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>SourceBuffer.mode == "sequence" test cases.</title>
|
||||
|
@ -81,45 +82,55 @@
|
|||
|
||||
mediasource_sequencemode_test(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
assert_equals(segmentInfo.media[0].timecode, 0, "segment starts at time 0");
|
||||
var offset = Math.min(segmentInfo.media[0].timev, segmentInfo.media[0].timea);
|
||||
var expectedStart = Math.max(segmentInfo.media[0].timev, segmentInfo.media[0].timea) - offset;
|
||||
var expectedEnd = Math.min(segmentInfo.media[0].endtimev, segmentInfo.media[0].endtimea) - offset;
|
||||
var expectedEndEOS = Math.max(segmentInfo.media[0].endtimev, segmentInfo.media[0].endtimea) - offset;
|
||||
append_segment(test, sourceBuffer, mediaData, segmentInfo.media[0], function()
|
||||
{
|
||||
verify_offset_and_buffered(test, mediaSource, sourceBuffer,
|
||||
0, 0,
|
||||
segmentInfo.media[1].timecode + sourceBuffer.timestampOffset,
|
||||
segmentInfo.media[0].highest_end_time + sourceBuffer.timestampOffset,
|
||||
-offset, expectedStart,
|
||||
expectedEnd, expectedEndEOS,
|
||||
test.done);
|
||||
});
|
||||
}, "Test sequence AppendMode appendBuffer(first media segment)");
|
||||
|
||||
mediasource_sequencemode_test(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
assert_greater_than(segmentInfo.media[1].timecode, 0, "segment starts after time 0");
|
||||
var offset = Math.min(segmentInfo.media[1].timev, segmentInfo.media[1].timea);
|
||||
var expectedStart = Math.max(segmentInfo.media[1].timev, segmentInfo.media[1].timea) - offset;
|
||||
var expectedEnd = Math.min(segmentInfo.media[1].endtimev, segmentInfo.media[1].endtimea) - offset;
|
||||
var expectedEndEOS = Math.max(segmentInfo.media[1].endtimev, segmentInfo.media[1].endtimea) - offset;
|
||||
assert_greater_than(Math.min(segmentInfo.media[1].timev, segmentInfo.media[1].timea), 0,
|
||||
"segment starts after time 0");
|
||||
append_segment(test, sourceBuffer, mediaData, segmentInfo.media[1], function()
|
||||
{
|
||||
verify_offset_and_buffered(test, mediaSource, sourceBuffer,
|
||||
-segmentInfo.media[1].timecode, 0,
|
||||
segmentInfo.media[2].timecode + sourceBuffer.timestampOffset,
|
||||
segmentInfo.media[1].highest_end_time + sourceBuffer.timestampOffset,
|
||||
-offset, expectedStart,
|
||||
expectedEnd, expectedEndEOS,
|
||||
test.done);
|
||||
});
|
||||
}, "Test sequence AppendMode appendBuffer(second media segment)");
|
||||
|
||||
mediasource_sequencemode_test(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
assert_greater_than(segmentInfo.media[1].timecode, 0, "segment starts after time 0");
|
||||
assert_greater_than(Math.min(segmentInfo.media[1].timev, segmentInfo.media[1].timea), 0,
|
||||
"segment starts after time 0");
|
||||
append_segment(test, sourceBuffer, mediaData, segmentInfo.media[1], function()
|
||||
{
|
||||
assert_equals(segmentInfo.media[0].timecode, 0, "segment starts at time 0");
|
||||
append_segment(test, sourceBuffer, mediaData, segmentInfo.media[0], function()
|
||||
{
|
||||
var firstOffset = Math.min(segmentInfo.media[1].timev, segmentInfo.media[1].timea);
|
||||
var secondOffset = Math.max(segmentInfo.media[1].endtimev, segmentInfo.media[1].endtimea) - firstOffset;
|
||||
var expectedStart = Math.max(segmentInfo.media[1].timev, segmentInfo.media[1].timea) - firstOffset;
|
||||
var expectedEnd = Math.min(segmentInfo.media[0].endtimev, segmentInfo.media[0].endtimea) + secondOffset;
|
||||
var expectedEndEOS = Math.max(segmentInfo.media[0].endtimev, segmentInfo.media[0].endtimea) + secondOffset;
|
||||
// Current timestampOffset should reflect offset required to put media[0]
|
||||
// immediately after media[1]'s highest frame end timestamp (as was adjusted
|
||||
// by an earlier timestampOffset).
|
||||
verify_offset_and_buffered(test, mediaSource, sourceBuffer,
|
||||
segmentInfo.media[1].highest_end_time - segmentInfo.media[1].timecode, 0,
|
||||
segmentInfo.media[1].timecode + sourceBuffer.timestampOffset,
|
||||
segmentInfo.media[0].highest_end_time + sourceBuffer.timestampOffset,
|
||||
secondOffset, expectedStart,
|
||||
expectedEnd, expectedEndEOS,
|
||||
test.done);
|
||||
})
|
||||
});
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<title>SourceBuffer#mode with generate timestamps flag true</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
|
||||
<script>
|
||||
var mimes = ['audio/aac', 'audio/mpeg'];
|
||||
|
||||
//check the browser supports the MIME used in this test
|
||||
function isTypeSupported(mime) {
|
||||
if(!MediaSource.isTypeSupported(mime)) {
|
||||
this.step(function() {
|
||||
assert_unreached("Browser doesn't support the MIME used in this test: " + mime);
|
||||
});
|
||||
this.done();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function mediaTest(mime) {
|
||||
async_test(function(t) {
|
||||
if(!isTypeSupported.bind(t)(mime)) {
|
||||
return;
|
||||
}
|
||||
var mediaSource = new MediaSource();
|
||||
mediaSource.addEventListener('sourceopen', t.step_func_done(function(e) {
|
||||
var sourceBuffer = mediaSource.addSourceBuffer(mime);
|
||||
assert_equals(sourceBuffer.updating, false, "SourceBuffer.updating is false");
|
||||
assert_throws({name: 'TypeError'},
|
||||
function() {
|
||||
sourceBuffer.mode = "segments";
|
||||
},
|
||||
'SourceBuffer#mode with generate timestamps flag true');
|
||||
}), false);
|
||||
var video = document.createElement('video');
|
||||
video.src = window.URL.createObjectURL(mediaSource);
|
||||
}, mime + ' : ' +
|
||||
'If generate timestamps flag equals true and new mode equals "segments", ' +
|
||||
'then throw a TypeError exception and abort these steps.');
|
||||
}
|
||||
mimes.forEach(function(mime) {
|
||||
mediaTest(mime);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,6 +1,8 @@
|
|||
<!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.mode test cases.</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<meta charset="utf-8">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="mediasource-util.js"></script>
|
||||
<script>
|
||||
function sourceBufferTrackDefaultsTest(callback, description)
|
||||
{
|
||||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
{
|
||||
var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
|
||||
assert_array_equals(sourceBuffer.trackDefaults, [], "Empty initial SourceBuffer.trackDefaults");
|
||||
callback(test, mediaElement, mediaSource, sourceBuffer);
|
||||
}, description);
|
||||
};
|
||||
|
||||
sourceBufferTrackDefaultsTest(function(test, mediaElement, mediaSource, sourceBuffer)
|
||||
{
|
||||
var emptyList = new TrackDefaultList([]);
|
||||
assert_not_equals(sourceBuffer.trackDefaults, emptyList, "Initial trackDefaults object differs from new empty list");
|
||||
|
||||
sourceBuffer.trackDefaults = emptyList;
|
||||
|
||||
assert_array_equals(sourceBuffer.trackDefaults, [], "Round-tripped empty trackDefaults");
|
||||
assert_equals(sourceBuffer.trackDefaults, emptyList, "Round-tripped the empty TrackDefaultList object");
|
||||
test.done();
|
||||
}, "Test round-trip of empty SourceBuffer.trackDefaults");
|
||||
|
||||
sourceBufferTrackDefaultsTest(function(test, mediaElement, mediaSource, sourceBuffer)
|
||||
{
|
||||
var trackDefault = new TrackDefault("audio", "en-US", "audio label", ["main"], "1");
|
||||
var trackDefaults = new TrackDefaultList([ trackDefault ]);
|
||||
|
||||
sourceBuffer.trackDefaults = trackDefaults;
|
||||
|
||||
assert_array_equals(sourceBuffer.trackDefaults, trackDefaults, "Round-tripped non-empty trackDefaults");
|
||||
assert_equals(sourceBuffer.trackDefaults.length, 1, "Confirmed non-empty trackDefaults");
|
||||
assert_equals(sourceBuffer.trackDefaults, trackDefaults, "Round-tripped the non-empty TrackDefaultList object");
|
||||
test.done();
|
||||
}, "Test round-trip of non-empty SourceBuffer.trackDefaults");
|
||||
|
||||
sourceBufferTrackDefaultsTest(function(test, mediaElement, mediaSource, sourceBuffer)
|
||||
{
|
||||
mediaSource.removeSourceBuffer(sourceBuffer);
|
||||
assert_throws("InvalidStateError",
|
||||
function() { sourceBuffer.trackDefaults = new TrackDefaultList([]); },
|
||||
"Exception thrown when setting trackDefaults on SourceBuffer that is removed from MediaSource");
|
||||
test.done();
|
||||
}, "Test setting trackDefaults on an already-removed SourceBuffer");
|
||||
|
||||
mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
assert_array_equals(sourceBuffer.trackDefaults, [], "Empty initial SourceBuffer.trackDefaults");
|
||||
test.expectEvent(sourceBuffer, "updateend", "Append ended");
|
||||
sourceBuffer.appendBuffer(mediaData);
|
||||
assert_true(sourceBuffer.updating, "SourceBuffer is updating");
|
||||
|
||||
assert_throws("InvalidStateError",
|
||||
function() { sourceBuffer.trackDefaults = new TrackDefaultList([]); },
|
||||
"Exception thrown when setting trackDefaults on SourceBuffer that is updating");
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_false(sourceBuffer.updating, "SourceBuffer is not updating");
|
||||
sourceBuffer.trackDefaults = new TrackDefaultList([]);
|
||||
test.done();
|
||||
});
|
||||
}, "Test setting trackDefaults on a SourceBuffer that is updating");
|
||||
|
||||
sourceBufferTrackDefaultsTest(function(test, mediaElement, mediaSource, sourceBuffer)
|
||||
{
|
||||
assert_throws(new TypeError(),
|
||||
function() { sourceBuffer.trackDefaults = null; },
|
||||
"null should be disallowed by trackDefaults setter");
|
||||
test.done();
|
||||
}, "Test setting null SourceBuffer.trackDefaults");
|
||||
</script>
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>SourceBufferList test cases.</title>
|
||||
|
@ -13,10 +14,23 @@
|
|||
{
|
||||
assert_equals(mediaSource.sourceBuffers.length, expected.length, "sourceBuffers length");
|
||||
assert_equals(mediaSource.activeSourceBuffers.length, 0, "activeSourceBuffers length");
|
||||
for (var i = 0; i < expected.length; ++i)
|
||||
for (var i = 0; i < expected.length; ++i) {
|
||||
assert_equals(mediaSource.sourceBuffers[i], expected[i], "Verifying mediaSource.sourceBuffers[" + i + "]");
|
||||
}
|
||||
assert_equals(mediaSource.sourceBuffers[expected.length], undefined,
|
||||
"If index is greater than or equal to the length attribute then return undefined.");
|
||||
}
|
||||
|
||||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
{
|
||||
var sourceBufferA = mediaSource.addSourceBuffer(MediaSourceUtil.VIDEO_ONLY_TYPE);
|
||||
verifySourceBufferLists(mediaSource, [sourceBufferA]);
|
||||
|
||||
var sourceBufferB = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_ONLY_TYPE);
|
||||
verifySourceBufferLists(mediaSource, [sourceBufferA, sourceBufferB]);
|
||||
test.done();
|
||||
}, "Test SourceBufferList getter method");
|
||||
|
||||
mediasource_test(function(test, mediaElement, mediaSource)
|
||||
{
|
||||
test.expectEvent(mediaSource.sourceBuffers, "addsourcebuffer", "sourceBuffers");
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<html>
|
||||
<head>
|
||||
<title>SourceBuffer.timestampOffset test cases.</title>
|
||||
|
@ -16,6 +17,9 @@
|
|||
var segmentInfo = MediaSourceUtil.SEGMENT_INFO;
|
||||
var sourceBuffer = mediaSource.addSourceBuffer(segmentInfo.type);
|
||||
|
||||
assert_equals(sourceBuffer.timestampOffset, 0,
|
||||
"Initial timestampOffset of a SourceBuffer is 0");
|
||||
|
||||
if (expected == "TypeError") {
|
||||
assert_throws({name: "TypeError"},
|
||||
function() { sourceBuffer.timestampOffset = value; },
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<meta charset="utf-8">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
function checkConstructionSucceeds(type, language, label, kinds, byteStreamTrackID)
|
||||
{
|
||||
var trackDefault = new TrackDefault(type, language, label, kinds, byteStreamTrackID);
|
||||
assert_equals(trackDefault.type, type, "type");
|
||||
assert_equals(trackDefault.language, language, "language");
|
||||
assert_equals(trackDefault.label, label, "label");
|
||||
assert_equals(trackDefault.byteStreamTrackID, byteStreamTrackID, "byteStreamTrackID");
|
||||
assert_array_equals(trackDefault.kinds, kinds, "kinds");
|
||||
}
|
||||
|
||||
function checkConstructionFails(type, language, label, kinds, byteStreamTrackID)
|
||||
{
|
||||
assert_throws(new TypeError(),
|
||||
function() { new TrackDefault(type, language, label, kinds, byteStreamTrackID); },
|
||||
"TrackDefault construction threw an exception");
|
||||
}
|
||||
|
||||
function trackDefaultConstructionTest(type, language, label, kinds, byteStreamTrackID, expectation, description)
|
||||
{
|
||||
test(function()
|
||||
{
|
||||
if (expectation)
|
||||
checkConstructionSucceeds(type, language, label, kinds, byteStreamTrackID);
|
||||
else
|
||||
checkConstructionFails(type, language, label, kinds, byteStreamTrackID);
|
||||
}, description + ": type '" + type + "', language '" + language + "', label '" + label + "', multiple kinds, byteStreamTrackID '" + byteStreamTrackID + "'");
|
||||
|
||||
// If all of |kinds| are expected to succeed, also test each kind individually.
|
||||
if (!expectation || kinds.length <= 1)
|
||||
return;
|
||||
for (var i = 0; i < kinds.length; ++i) {
|
||||
test(function()
|
||||
{
|
||||
checkConstructionSucceeds(type, language, label, new Array(kinds[i]), byteStreamTrackID);
|
||||
}, description + ": type '" + type + "', language '" + language + "', label '" + label + "', kind '" + kinds[i] + "', byteStreamTrackID '" + byteStreamTrackID + "'");
|
||||
}
|
||||
}
|
||||
|
||||
var VALID_AUDIO_TRACK_KINDS = [
|
||||
"alternative",
|
||||
"descriptions",
|
||||
"main",
|
||||
"main-desc",
|
||||
"translation",
|
||||
"commentary",
|
||||
"",
|
||||
];
|
||||
|
||||
var VALID_VIDEO_TRACK_KINDS = [
|
||||
"alternative",
|
||||
"captions",
|
||||
"main",
|
||||
"sign",
|
||||
"subtitles",
|
||||
"commentary",
|
||||
"",
|
||||
];
|
||||
|
||||
var VALID_TEXT_TRACK_KINDS = [
|
||||
"subtitles",
|
||||
"captions",
|
||||
"descriptions",
|
||||
"chapters",
|
||||
"metadata",
|
||||
];
|
||||
|
||||
trackDefaultConstructionTest("audio", "en-US", "audio label", VALID_AUDIO_TRACK_KINDS, "1", true, "Test valid audio kinds");
|
||||
|
||||
trackDefaultConstructionTest("video", "en-US", "video label", VALID_VIDEO_TRACK_KINDS, "1", true, "Test valid video kinds");
|
||||
|
||||
trackDefaultConstructionTest("text", "en-US", "text label", VALID_TEXT_TRACK_KINDS, "1", true, "Test valid text kinds");
|
||||
|
||||
trackDefaultConstructionTest("audio", "en-US", "audio label", VALID_VIDEO_TRACK_KINDS, "1", false, "Test mixed valid and invalid audio kinds");
|
||||
|
||||
trackDefaultConstructionTest("video", "en-US", "video label", VALID_AUDIO_TRACK_KINDS, "1", false, "Test mixed valid and invalid video kinds");
|
||||
|
||||
trackDefaultConstructionTest("text", "en-US", "text label", VALID_VIDEO_TRACK_KINDS, "1", false, "Test mixed valid and invalid text kinds");
|
||||
|
||||
trackDefaultConstructionTest("invalid type", "en-US", "label", VALID_AUDIO_TRACK_KINDS, "1", false, "Test invalid 'type' parameter type passed to TrackDefault constructor");
|
||||
|
||||
test(function()
|
||||
{
|
||||
checkConstructionFails("audio", "en-US", "label", "this is not a valid sequence", "1");
|
||||
}, "Test invalid 'kinds' parameter type passed to TrackDefault constructor");
|
||||
|
||||
test(function()
|
||||
{
|
||||
var trackDefault = new TrackDefault("audio", "en-US", "label", VALID_AUDIO_TRACK_KINDS, "1");
|
||||
var kinds = trackDefault.kinds;
|
||||
kinds[0] = "invalid kind";
|
||||
assert_equals(kinds[0], "invalid kind", "local kinds is updated");
|
||||
assert_equals(VALID_AUDIO_TRACK_KINDS[0], "alternative", "local original kinds unchanged");
|
||||
assert_array_equals(trackDefault.kinds, VALID_AUDIO_TRACK_KINDS, "trackDefault kinds unchanged");
|
||||
}, "Test updating the retval of TrackDefault.kinds does not modify TrackDefault.kinds");
|
||||
</script>
|
|
@ -0,0 +1,60 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
|
||||
<meta charset="utf-8">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
test(function()
|
||||
{
|
||||
var originalTrackDefaults = [
|
||||
// Same everything, but different byteStreamTrackID, should be allowed by the constructor.
|
||||
new TrackDefault("audio", "en-US", "label", ["main"], ""),
|
||||
new TrackDefault("audio", "en-US", "label", ["main"], "1"),
|
||||
new TrackDefault("audio", "en-US", "label", ["main"], "2"),
|
||||
new TrackDefault("audio", "en-US", "label", [""], "3"),
|
||||
|
||||
// Same everything, but different type, should be allowed by the constructor.
|
||||
new TrackDefault("video", "en-US", "label", ["main"], ""),
|
||||
new TrackDefault("video", "en-US", "label", ["main"], "1"),
|
||||
new TrackDefault("video", "en-US", "label", ["main"], "2"),
|
||||
new TrackDefault("video", "en-US", "label", [""], "3")
|
||||
];
|
||||
|
||||
// Get a new array containing the same objects as |originalTrackDefaults|.
|
||||
var trackDefaults = originalTrackDefaults.slice();
|
||||
|
||||
var trackDefaultList = new TrackDefaultList(trackDefaults);
|
||||
assert_array_equals(trackDefaultList, originalTrackDefaults, "construction and read-back succeeded");
|
||||
assert_equals(trackDefaultList[trackDefaultList.length], undefined, "out of range indexed property getter result is undefined");
|
||||
assert_equals(trackDefaultList[trackDefaultList.length + 1], undefined, "out of range indexed property getter result is undefined");
|
||||
|
||||
// Introduce same-type, same-empty-string-byteStreamTrackId conflict in trackDefaults[0 vs 4].
|
||||
trackDefaults[4] = new TrackDefault("audio", "en-US", "label", ["main"], "");
|
||||
assert_equals(trackDefaults[0].type, trackDefaults[4].type, "same-type conflict setup");
|
||||
assert_equals(trackDefaults[0].byteStreamTrackID, trackDefaults[4].byteStreamTrackID, "same-byteStreamTrackID conflict setup");
|
||||
assert_throws("InvalidAccessError",
|
||||
function() { new TrackDefaultList(trackDefaults); },
|
||||
"TrackDefaultList construction should throw exception due to same type and byteStreamTrackID across at least 2 items in trackDefaults");
|
||||
|
||||
// Introduce same-type, same-non-empty-string-byteStreamTrackId conflict in trackDefaults[4 vs 5].
|
||||
trackDefaults[4] = new TrackDefault("video", "en-US", "label", ["main"], "1");
|
||||
assert_equals(trackDefaults[4].type, trackDefaults[5].type, "same-type conflict setup");
|
||||
assert_equals(trackDefaults[4].byteStreamTrackID, trackDefaults[5].byteStreamTrackID, "same-byteStreamTrackID conflict setup");
|
||||
assert_throws("InvalidAccessError",
|
||||
function() { new TrackDefaultList(trackDefaults); },
|
||||
"TrackDefaultList construction should throw exception due to same type and byteStreamTrackID across at least 2 items in trackDefaults");
|
||||
|
||||
// Confirm the constructed TrackDefaultList makes a shallow copy of the supplied TrackDefault sequence.
|
||||
assert_array_equals(trackDefaultList, originalTrackDefaults, "read-back of original trackDefaultList unchanged");
|
||||
|
||||
}, "Test track default list construction, length, and indexed property getter");
|
||||
|
||||
test(function()
|
||||
{
|
||||
var trackDefaultList = new TrackDefaultList();
|
||||
assert_array_equals(trackDefaultList, [], "empty list constructable without supplying optional trackDefaults parameter");
|
||||
|
||||
trackDefaultList = new TrackDefaultList([]);
|
||||
assert_array_equals(trackDefaultList, [], "empty list constructable by supplying empty sequence as optional trackDefaults parameter");
|
||||
}, "Test empty track default list construction with and without optional trackDefaults parameter");
|
||||
</script>
|
|
@ -1,3 +1,5 @@
|
|||
// Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang).
|
||||
|
||||
(function(window) {
|
||||
var SEGMENT_INFO_LIST = [
|
||||
{
|
||||
|
@ -6,34 +8,34 @@
|
|||
duration: 6.0756,
|
||||
init: { offset: 0, size: 1197 },
|
||||
media: [
|
||||
{ offset: 1241, size: 17845, timecode: 0.000000 },
|
||||
{ offset: 19130, size: 5551, timecode: 0.464800 },
|
||||
{ offset: 24725, size: 10944, timecode: 0.763600 },
|
||||
{ offset: 35713, size: 7131, timecode: 0.863200 },
|
||||
{ offset: 42888, size: 2513, timecode: 1.128800 },
|
||||
{ offset: 45457, size: 3022, timecode: 1.261600 },
|
||||
{ offset: 48479, size: 815, timecode: 1.427600 },
|
||||
{ offset: 49338, size: 2818, timecode: 1.460800 },
|
||||
{ offset: 52200, size: 11581, timecode: 1.593600 },
|
||||
{ offset: 63825, size: 3003, timecode: 1.726400 },
|
||||
{ offset: 66872, size: 6390, timecode: 1.892400 },
|
||||
{ offset: 73306, size: 3740, timecode: 2.124800 },
|
||||
{ offset: 77102, size: 11779, timecode: 2.324000 },
|
||||
{ offset: 88881, size: 851, timecode: 2.490000 },
|
||||
{ offset: 89776, size: 4236, timecode: 2.523200 },
|
||||
{ offset: 94056, size: 9538, timecode: 2.755600 },
|
||||
{ offset: 103638, size: 13295, timecode: 3.154000 },
|
||||
{ offset: 116977, size: 309, timecode: 3.386400 },
|
||||
{ offset: 117330, size: 5806, timecode: 3.419600 },
|
||||
{ offset: 123180, size: 4392, timecode: 3.751600 },
|
||||
{ offset: 127616, size: 15408, timecode: 3.984000 },
|
||||
{ offset: 143068, size: 9899, timecode: 4.216400 },
|
||||
{ offset: 153011, size: 11562, timecode: 4.780800 },
|
||||
{ offset: 164617, size: 7398, timecode: 4.946800 },
|
||||
{ offset: 172059, size: 5698, timecode: 5.212400 },
|
||||
{ offset: 177801, size: 11682, timecode: 5.511200 },
|
||||
{ offset: 189527, size: 3023, timecode: 5.677200 },
|
||||
{ offset: 192594, size: 5726, timecode: 5.843200 },
|
||||
{ offset: 1241, size: 17845, timev: 0.033200, timea: 0, endtimev: 0.531200, endtimea: 0.510839 },
|
||||
{ offset: 19130, size: 5551, timev: 0.464800, timea: 0.510839, endtimev: 0.796800, endtimea: 0.812698 },
|
||||
{ offset: 24725, size: 10944, timev: 0.796800, timea: 0.812698, endtimev: 0.929600, endtimea: 0.905578 },
|
||||
{ offset: 35713, size: 7131, timev: 0.863200, timea: 0.905578, endtimev: 1.195200, endtimea: 1.184217 },
|
||||
{ offset: 42888, size: 2513, timev: 1.128800, timea: 1.184217, endtimev: 1.328000, endtimea: 1.300317 },
|
||||
{ offset: 45457, size: 3022, timev: 1.261600, timea: 1.300317, endtimev: 1.460800, endtimea: 1.509297 },
|
||||
{ offset: 48479, size: 815, timev: 1.494000, timea: 1.509297, endtimev: 1.527200, endtimea: 1.532517 },
|
||||
{ offset: 49338, size: 2818, timev: 1.460800, timea: 1.532517, endtimev: 1.626800, endtimea: 1.648616 },
|
||||
{ offset: 52200, size: 11581, timev: 1.626800, timea: 1.648616, endtimev: 1.792800, endtimea: 1.764716 },
|
||||
{ offset: 63825, size: 3003, timev: 1.726400, timea: 1.764716, endtimev: 1.925600, endtimea: 1.973696 },
|
||||
{ offset: 66872, size: 6390, timev: 1.925600, timea: 1.973696, endtimev: 2.191200, endtimea: 2.159455 },
|
||||
{ offset: 73306, size: 3740, timev: 2.124800, timea: 2.159455, endtimev: 2.390400, endtimea: 2.368435 },
|
||||
{ offset: 77102, size: 11779, timev: 2.324000, timea: 2.368435, endtimev: 2.523200, endtimea: 2.577414 },
|
||||
{ offset: 88881, size: 851, timev: 2.556400, timea: 2.577414, endtimev: 2.589600, endtimea: 2.600634 },
|
||||
{ offset: 89776, size: 4236, timev: 2.523200, timea: 2.600634, endtimev: 2.788800, endtimea: 2.832834 },
|
||||
{ offset: 94056, size: 9538, timev: 2.788800, timea: 2.832834, endtimev: 3.187200, endtimea: 3.204353 },
|
||||
{ offset: 103638, size: 13295, timev: 3.187200, timea: 3.204353, endtimev: 3.452800, endtimea: 3.436553 },
|
||||
{ offset: 116977, size: 309, timev: 3.386400, timea: 3.436553, endtimev: 3.419600, endtimea: 3.506213 },
|
||||
{ offset: 117330, size: 5806, timev: 3.452800, timea: 3.506213, endtimev: 3.784800, endtimea: 3.831292 },
|
||||
{ offset: 123180, size: 4392, timev: 3.784800, timea: 3.831292, endtimev: 4.017200, endtimea: 4.040272 },
|
||||
{ offset: 127616, size: 15408, timev: 4.017200, timea: 4.040272, endtimev: 4.249600, endtimea: 4.295691 },
|
||||
{ offset: 143068, size: 9899, timev: 4.249600, timea: 4.295691, endtimev: 4.814000, endtimea: 4.829750 },
|
||||
{ offset: 153011, size: 11562, timev: 4.814000, timea: 4.829750, endtimev: 4.980000, endtimea: 5.015510 },
|
||||
{ offset: 164617, size: 7398, timev: 4.980000, timea: 5.015510, endtimev: 5.245600, endtimea: 5.294149 },
|
||||
{ offset: 172059, size: 5698, timev: 5.245600, timea: 5.294149, endtimev: 5.577600, endtimea: 5.549569 },
|
||||
{ offset: 177801, size: 11682, timev: 5.511200, timea: 5.549569, endtimev: 5.710400, endtimea: 5.758548 },
|
||||
{ offset: 189527, size: 3023, timev: 5.710400, timea: 5.758548, endtimev: 5.909600, endtimea: 5.897868 },
|
||||
{ offset: 192594, size: 5726, timev: 5.843200, timea: 5.897868, endtimev: 6.075600, endtimea: 6.037188 },
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -42,22 +44,22 @@
|
|||
duration: 6.042,
|
||||
init: { offset: 0, size: 4357 },
|
||||
media: [
|
||||
{ offset: 4357, size: 11830, timecode: 0 },
|
||||
{ offset: 16187, size: 12588, timecode: 0.385 },
|
||||
{ offset: 28775, size: 14588, timecode: 0.779 },
|
||||
{ offset: 43363, size: 13023, timecode: 1.174 },
|
||||
{ offset: 56386, size: 13127, timecode: 1.592 },
|
||||
{ offset: 69513, size: 14456, timecode: 1.987 },
|
||||
{ offset: 83969, size: 13458, timecode: 2.381 },
|
||||
{ offset: 97427, size: 14566, timecode: 2.776 },
|
||||
{ offset: 111993, size: 13201, timecode: 3.171 },
|
||||
{ offset: 125194, size: 14061, timecode: 3.566 },
|
||||
{ offset: 139255, size: 15353, timecode: 3.96 },
|
||||
{ offset: 154608, size: 13618, timecode: 4.378 },
|
||||
{ offset: 168226, size: 15094, timecode: 4.773 },
|
||||
{ offset: 183320, size: 13069, timecode: 5.168 },
|
||||
{ offset: 196389, size: 13788, timecode: 5.563 },
|
||||
{ offset: 210177, size: 9009, timecode: 5.957 },
|
||||
{ offset: 4357, size: 11830, timev: 0, timea: 0, endtimev: 0.398000, endtimea: 0.384000 },
|
||||
{ offset: 16187, size: 12588, timev: 0.398000, timea: 0.385000, endtimev: 0.798000, endtimea: 0.779000 },
|
||||
{ offset: 28775, size: 14588, timev: 0.797000, timea: 0.779000, endtimev: 1.195000, endtimea: 1.174000 },
|
||||
{ offset: 43363, size: 13023, timev: 1.195000, timea: 1.174000, endtimev: 1.593000, endtimea: 1.592000 },
|
||||
{ offset: 56386, size: 13127, timev: 1.594000, timea: 1.592000, endtimev: 1.992000, endtimea: 1.988000 },
|
||||
{ offset: 69513, size: 14456, timev: 1.992000, timea: 1.987000, endtimev: 2.390000, endtimea: 2.381000 },
|
||||
{ offset: 83969, size: 13458, timev: 2.390000, timea: 2.381000, endtimev: 2.790000, endtimea: 2.776000 },
|
||||
{ offset: 97427, size: 14566, timev: 2.789000, timea: 2.776000, endtimev: 3.187000, endtimea: 3.171000 },
|
||||
{ offset: 111993, size: 13201, timev: 3.187000, timea: 3.171000, endtimev: 3.585000, endtimea: 3.565000 },
|
||||
{ offset: 125194, size: 14061, timev: 3.586000, timea: 3.566000, endtimev: 3.984000, endtimea: 3.960000 },
|
||||
{ offset: 139255, size: 15353, timev: 3.984000, timea: 3.960000, endtimev: 4.382000, endtimea: 4.378000 },
|
||||
{ offset: 154608, size: 13618, timev: 4.382000, timea: 4.378000, endtimev: 4.782000, endtimea: 4.773000 },
|
||||
{ offset: 168226, size: 15094, timev: 4.781000, timea: 4.773000, endtimev: 5.179000, endtimea: 5.169000 },
|
||||
{ offset: 183320, size: 13069, timev: 5.179000, timea: 5.168000, endtimev: 5.577000, endtimea: 5.562000 },
|
||||
{ offset: 196389, size: 13788, timev: 5.578000, timea: 5.563000, endtimev: 5.976000, endtimea: 5.957000 },
|
||||
{ offset: 210177, size: 9009, timev: 5.976000, timea: 5.957000, endtimev: 6.042000, endtimea: 6.050000 },
|
||||
],
|
||||
}
|
||||
];
|
||||
|
@ -85,8 +87,12 @@
|
|||
assert_equals(eventInfo.description, expected.description, "Descriptions match for '" + event.type + "'.");
|
||||
|
||||
expectations.shift(1);
|
||||
if (t.waitCallbacks_.length > 0)
|
||||
if (t.waitCallbacks_.length > 1)
|
||||
setTimeout(waitHandler, 0);
|
||||
else if (t.waitCallbacks_.length == 1) {
|
||||
// Immediately call the callback.
|
||||
waitHandler();
|
||||
}
|
||||
});
|
||||
object.addEventListener(eventName, eventHandler);
|
||||
};
|
||||
|
@ -215,7 +221,8 @@
|
|||
var start = mediaInfo[0].offset;
|
||||
var numBytes = 0;
|
||||
var segmentIndex = 0;
|
||||
while (segmentIndex < mediaInfo.length && mediaInfo[segmentIndex].timecode <= playbackTimeToAdd)
|
||||
while (segmentIndex < mediaInfo.length
|
||||
&& Math.min(mediaInfo[segmentIndex].timev, mediaInfo[segmentIndex].timea) <= playbackTimeToAdd)
|
||||
{
|
||||
numBytes += mediaInfo[segmentIndex].size;
|
||||
++segmentIndex;
|
||||
|
@ -296,11 +303,14 @@
|
|||
|
||||
var i = startingIndex;
|
||||
var onAppendDone = function() {
|
||||
if (eventFired)
|
||||
if (eventFired || (i >= (segmentInfo.media.length - 1)))
|
||||
return;
|
||||
|
||||
i++;
|
||||
MediaSourceUtil.append(test, sourceBuffer, MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[i]), onAppendDone);
|
||||
if (i < segmentInfo.media.length)
|
||||
{
|
||||
MediaSourceUtil.append(test, sourceBuffer, MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[i]), onAppendDone);
|
||||
}
|
||||
};
|
||||
MediaSourceUtil.append(test, sourceBuffer, MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[i]), onAppendDone);
|
||||
|
||||
|
@ -359,6 +369,9 @@
|
|||
return media_test(function(test)
|
||||
{
|
||||
var mediaTag = document.createElement("video");
|
||||
if (!document.body) {
|
||||
document.body = document.createElement("body");
|
||||
}
|
||||
document.body.appendChild(mediaTag);
|
||||
|
||||
test.removeMediaElement_ = true;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue