mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1065215 - MSE endOfStream() called within an 'updateend' event can fail with 'object no longer usable' - r=karl
Reopens the MediaSource when SourceBuffer::Remove is called on an Ended MediaSource. Only run the Range Removal algorithm when MediaSource duration is changed instead of calling Remove on SourceBuffers. Updates tests for the fact that update{start,end} can now be called more than once due to DurationChange. --HG-- extra : rebase_source : e718144ba2c36b4fa0194719e7f06fe6e931e292
This commit is contained in:
parent
b90e1fb58c
commit
dd54ff036e
@ -418,14 +418,10 @@ void
|
||||
MediaSource::DurationChange(double aOldDuration, double aNewDuration)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MSE_DEBUG("MediaSource(%p)::DurationChange(aNewDuration=%f)", this, aNewDuration);
|
||||
MSE_DEBUG("MediaSource(%p)::DurationChange(aOldDuration=%f, aNewDuration=%f)", this, aOldDuration, aNewDuration);
|
||||
|
||||
if (aNewDuration < aOldDuration) {
|
||||
ErrorResult rv;
|
||||
mSourceBuffers->Remove(aNewDuration, aOldDuration, rv);
|
||||
if (rv.Failed()) {
|
||||
return;
|
||||
}
|
||||
mSourceBuffers->RangeRemoval(aNewDuration, aOldDuration);
|
||||
}
|
||||
// TODO: If partial audio frames/text cues exist, clamp duration based on mSourceBuffers.
|
||||
}
|
||||
|
@ -188,10 +188,19 @@ SourceBuffer::Remove(double aStart, double aEnd, ErrorResult& aRv)
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return;
|
||||
}
|
||||
if (mUpdating || mMediaSource->ReadyState() != MediaSourceReadyState::Open) {
|
||||
if (mUpdating) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
|
||||
mMediaSource->SetReadyState(MediaSourceReadyState::Open);
|
||||
}
|
||||
RangeRemoval(aStart, aEnd);
|
||||
}
|
||||
|
||||
void
|
||||
SourceBuffer::RangeRemoval(double aStart, double aEnd)
|
||||
{
|
||||
StartUpdating();
|
||||
/// TODO: Run coded frame removal algorithm.
|
||||
|
||||
|
@ -108,6 +108,9 @@ public:
|
||||
double GetBufferedStart();
|
||||
double GetBufferedEnd();
|
||||
|
||||
// Runs the range removal algorithm as defined by the MSE spec.
|
||||
void RangeRemoval(double aStart, double aEnd);
|
||||
|
||||
#if defined(DEBUG)
|
||||
void Dump(const char* aPath);
|
||||
#endif
|
||||
|
@ -108,15 +108,12 @@ SourceBufferList::AnyUpdating()
|
||||
}
|
||||
|
||||
void
|
||||
SourceBufferList::Remove(double aStart, double aEnd, ErrorResult& aRv)
|
||||
SourceBufferList::RangeRemoval(double aStart, double aEnd)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MSE_DEBUG("SourceBufferList(%p)::Remove(aStart=%f, aEnd=%f", this, aStart, aEnd);
|
||||
MSE_DEBUG("SourceBufferList(%p)::RangeRemoval(aStart=%f, aEnd=%f", this, aStart, aEnd);
|
||||
for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
|
||||
mSourceBuffers[i]->Remove(aStart, aEnd, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
mSourceBuffers[i]->RangeRemoval(aStart, aEnd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,9 +66,8 @@ public:
|
||||
// Returns true if updating is true on any SourceBuffers in the list.
|
||||
bool AnyUpdating();
|
||||
|
||||
// Calls Remove(aStart, aEnd) on each SourceBuffer in the list. Aborts on
|
||||
// first error, with result returned in aRv.
|
||||
void Remove(double aStart, double aEnd, ErrorResult& aRv);
|
||||
// Runs the range removal steps from the MSE specification on each SourceBuffer.
|
||||
void RangeRemoval(double aStart, double aEnd);
|
||||
|
||||
// Mark all SourceBuffers input buffers as ended.
|
||||
void Ended();
|
||||
|
@ -9,6 +9,8 @@ support-files =
|
||||
[test_MediaSource_disabled.html]
|
||||
[test_BufferedSeek.html]
|
||||
[test_BufferingWait.html]
|
||||
[test_EndOfStream.html]
|
||||
skip-if = (toolkit == 'android') #timeout android only bug 1101187
|
||||
[test_FrameSelection.html]
|
||||
[test_HaveMetadataUnbufferedSeek.html]
|
||||
[test_LoadedMetadataFired.html]
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var updateCount = 0;
|
||||
|
||||
runWithMSE(function (ms, v) {
|
||||
ms.addEventListener("sourceopen", function () {
|
||||
var sb = ms.addSourceBuffer("video/webm");
|
||||
@ -19,7 +21,13 @@ runWithMSE(function (ms, v) {
|
||||
fetchWithXHR("seek.webm", function (arrayBuffer) {
|
||||
sb.appendBuffer(new Uint8Array(arrayBuffer));
|
||||
sb.addEventListener("updateend", function () {
|
||||
ms.endOfStream()
|
||||
updateCount++;
|
||||
/* Ensure that we endOfStream on the first update event only as endOfStream can
|
||||
raise more if the duration of the last buffered range and the intial duration
|
||||
differ. See bug 1065207 */
|
||||
if (updateCount == 1) {
|
||||
ms.endOfStream();
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
|
50
dom/media/mediasource/test/test_EndOfStream.html
Normal file
50
dom/media/mediasource/test/test_EndOfStream.html
Normal file
@ -0,0 +1,50 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>MSE: endOfStream call after an appendBuffer</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="mediasource.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
runWithMSE(function () {
|
||||
var ms = new MediaSource();
|
||||
|
||||
var v = document.createElement("video");
|
||||
v.src = URL.createObjectURL(ms);
|
||||
document.body.appendChild(v);
|
||||
|
||||
ms.addEventListener("sourceopen", function () {
|
||||
var sb = ms.addSourceBuffer("video/webm");
|
||||
|
||||
fetchWithXHR("seek.webm", function (arrayBuffer) {
|
||||
sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 88966));
|
||||
var count = 0;
|
||||
sb.addEventListener("updateend", function () {
|
||||
++count;
|
||||
if (count == 1) {
|
||||
setTimeout(function() {
|
||||
var fail = false;
|
||||
try {
|
||||
ms.endOfStream();
|
||||
} catch (e) {
|
||||
fail = true;
|
||||
}
|
||||
ok(!fail, "MediaSource.endOfStream succeeded");
|
||||
SimpleTest.finish();
|
||||
}, 0);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -12,6 +12,8 @@
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var updateCount = 0;
|
||||
|
||||
runWithMSE(function (ms, v) {
|
||||
ms.addEventListener("sourceopen", function () {
|
||||
var sb = ms.addSourceBuffer("video/webm");
|
||||
@ -34,13 +36,13 @@ runWithMSE(function (ms, v) {
|
||||
fetchWithXHR("seek_lowres.webm", function (arrayBuffer) {
|
||||
// Append initialization segment.
|
||||
sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 438));
|
||||
var first = true;
|
||||
sb.addEventListener("updateend", function () {
|
||||
if (first) {
|
||||
updateCount++;
|
||||
if (updateCount == 1) {
|
||||
// Append media segment covering range [2, 4].
|
||||
sb.appendBuffer(new Uint8Array(arrayBuffer, 51003));
|
||||
first = false;
|
||||
} else {
|
||||
}
|
||||
else if (updateCount == 2) {
|
||||
ms.endOfStream();
|
||||
target = targets.shift();
|
||||
v.currentTime = target.currentTime;
|
||||
|
@ -57,7 +57,12 @@ runWithMSE(function () {
|
||||
sb.addEventListener("update", function () {
|
||||
is(sb.updating, false, "SourceBuffer.updating is expected value in update event");
|
||||
updateCount++;
|
||||
ms.endOfStream();
|
||||
/* Ensure that we endOfStream on the first update event only as endOfStream can
|
||||
raise more if the duration of the last buffered range and the intial duration
|
||||
differ. See bug 1065207 */
|
||||
if (updateCount == 1) {
|
||||
ms.endOfStream();
|
||||
}
|
||||
});
|
||||
|
||||
sb.addEventListener("updatestart", function () {
|
||||
@ -84,9 +89,10 @@ runWithMSE(function () {
|
||||
// XXX: Duration should be exactly 4.0, see bug 1065207.
|
||||
ok(Math.abs(v.duration - 4) <= 0.002, "Video has correct duration");
|
||||
ok(Math.abs(v.currentTime - 4) <= 0.002, "Video has played to end");
|
||||
is(updateCount, 1, "update event received");
|
||||
is(updateendCount, 1, "updateend event received");
|
||||
is(updatestartCount, 1, "updatestart event received");
|
||||
// XXX: 2 update events can be received dueto duration differences, see bug 1065207.
|
||||
ok(updateCount == 1 || updateCount == 2, "update event received");
|
||||
ok(updateendCount == 1 || updateendCount == 2, "updateend event received");
|
||||
ok(updatestartCount == 1 || updatestartCount == 2, "updatestart event received");
|
||||
is(loadedmetadataCount, 1, "loadedmetadata event received");
|
||||
v.parentNode.removeChild(v);
|
||||
SimpleTest.finish();
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var updateCount = 0;
|
||||
|
||||
runWithMSE(function (ms, v) {
|
||||
ms.addEventListener("sourceopen", function () {
|
||||
var sb = ms.addSourceBuffer("video/webm");
|
||||
@ -19,7 +21,13 @@ runWithMSE(function (ms, v) {
|
||||
fetchWithXHR("seek.webm", function (arrayBuffer) {
|
||||
sb.appendBuffer(new Uint8Array(arrayBuffer));
|
||||
sb.addEventListener("updateend", function () {
|
||||
ms.endOfStream()
|
||||
updateCount++;
|
||||
/* Ensure that we endOfStream on the first update event only as endOfStream can
|
||||
raise more if the duration of the last buffered range and the intial duration
|
||||
differ. See bug 1065207 */
|
||||
if (updateCount == 1) {
|
||||
ms.endOfStream();
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -24,7 +24,7 @@ runWithMSE(function (ms, v) {
|
||||
if (updateCount == 1) {
|
||||
sb.appendBuffer(new Uint8Array(arrayBuffer, 25223));
|
||||
}
|
||||
else {
|
||||
else if (updateCount == 2) {
|
||||
ms.endOfStream();
|
||||
}
|
||||
});
|
||||
|
@ -12,18 +12,20 @@
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var updateCount = 0;
|
||||
|
||||
runWithMSE(function (ms, v) {
|
||||
ms.addEventListener("sourceopen", function () {
|
||||
var sb = ms.addSourceBuffer("video/webm");
|
||||
|
||||
fetchWithXHR("seek.webm", function (arrayBuffer) {
|
||||
sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 318));
|
||||
var first = true;
|
||||
sb.addEventListener("updateend", function () {
|
||||
if (first) {
|
||||
updateCount++;
|
||||
if (updateCount == 1) {
|
||||
sb.appendBuffer(new Uint8Array(arrayBuffer, 318));
|
||||
first = false;
|
||||
} else {
|
||||
}
|
||||
else if (updateCount == 2) {
|
||||
ms.endOfStream();
|
||||
}
|
||||
});
|
||||
|
@ -12,20 +12,22 @@
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var updateCount = 0;
|
||||
|
||||
runWithMSE(function (ms, v) {
|
||||
ms.addEventListener("sourceopen", function () {
|
||||
var sb = ms.addSourceBuffer("video/webm");
|
||||
|
||||
fetchWithXHR("seek.webm", function (arrayBuffer) {
|
||||
sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 318));
|
||||
var first = true;
|
||||
sb.addEventListener("updateend", function () {
|
||||
if (first) {
|
||||
updateCount++;
|
||||
if (updateCount == 1) {
|
||||
window.setTimeout(function () {
|
||||
sb.appendBuffer(new Uint8Array(arrayBuffer, 318));
|
||||
first = false;
|
||||
}, 1000);
|
||||
} else {
|
||||
}
|
||||
else if (updateCount == 2) {
|
||||
ms.endOfStream();
|
||||
}
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user