зеркало из https://github.com/mozilla/pjs.git
Bug 479863. AdFire 'suspend' event and do correct networkState transitions when downloads suspend and resume. Also avoid firing 'stalled' while the download is suspended. r=doublec
--HG-- extra : rebase_source : 0615871c062638d575a66e29b630040821a9f9cf
This commit is contained in:
Родитель
72572eda3e
Коммит
786308b090
|
@ -128,6 +128,20 @@ public:
|
|||
// when the resource has completed seeking.
|
||||
void SeekCompleted();
|
||||
|
||||
// Called by the media stream, on the main thread, when the download
|
||||
// has been suspended by the cache or because the element itself
|
||||
// asked the decoder to suspend the download.
|
||||
void DownloadSuspended();
|
||||
|
||||
// Called by the media stream, on the main thread, when the download
|
||||
// has been resumed by the cache or because the element itself
|
||||
// asked the decoder to resumed the download.
|
||||
void DownloadResumed();
|
||||
|
||||
// Called by the media decoder to indicate that the download has stalled
|
||||
// (no data has arrived for a while).
|
||||
void DownloadStalled();
|
||||
|
||||
// Draw the latest video data. See nsMediaDecoder for
|
||||
// details.
|
||||
void Paint(gfxContext* aContext,
|
||||
|
|
|
@ -617,8 +617,6 @@ nsresult nsHTMLMediaElement::LoadWithChannel(nsIChannel *aChannel,
|
|||
return rv;
|
||||
}
|
||||
|
||||
mBegun = PR_TRUE;
|
||||
|
||||
DispatchAsyncProgressEvent(NS_LITERAL_STRING("loadstart"));
|
||||
|
||||
return NS_OK;
|
||||
|
@ -1196,6 +1194,8 @@ nsresult nsHTMLMediaElement::InitializeDecoderForChannel(nsIChannel *aChannel,
|
|||
rv = mDecoder->Play();
|
||||
}
|
||||
|
||||
mBegun = PR_TRUE;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -1291,6 +1291,28 @@ void nsHTMLMediaElement::SeekCompleted()
|
|||
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("seeked"));
|
||||
}
|
||||
|
||||
void nsHTMLMediaElement::DownloadSuspended()
|
||||
{
|
||||
if (mBegun) {
|
||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE;
|
||||
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("suspend"));
|
||||
}
|
||||
}
|
||||
|
||||
void nsHTMLMediaElement::DownloadResumed()
|
||||
{
|
||||
if (mBegun) {
|
||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
|
||||
}
|
||||
}
|
||||
|
||||
void nsHTMLMediaElement::DownloadStalled()
|
||||
{
|
||||
if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING) {
|
||||
DispatchAsyncProgressEvent(NS_LITERAL_STRING("stalled"));
|
||||
}
|
||||
}
|
||||
|
||||
PRBool nsHTMLMediaElement::ShouldCheckAllowOrigin()
|
||||
{
|
||||
return nsContentUtils::GetBoolPref("media.enforce_same_site_origin",
|
||||
|
|
|
@ -985,9 +985,11 @@ nsMediaCache::Update()
|
|||
PRBool enableReading;
|
||||
if (stream->mStreamLength >= 0 &&
|
||||
desiredOffset >= stream->mStreamLength) {
|
||||
// We're at the end of the stream. Nothing to read.
|
||||
// We're at the end of the stream. Nothing to read, but we don't
|
||||
// need to suspend, we may as well just keep reading and hit EOF
|
||||
// (or discover more data if the server lied to us).
|
||||
LOG(PR_LOG_DEBUG, ("Stream %p at end of stream", stream));
|
||||
enableReading = PR_FALSE;
|
||||
enableReading = PR_TRUE;
|
||||
} else if (desiredOffset < stream->mStreamOffset) {
|
||||
// We're reading to try to catch up to where the current stream
|
||||
// reader wants to be. Better not stop.
|
||||
|
|
|
@ -171,7 +171,7 @@ void nsMediaDecoder::Progress(PRBool aTimer)
|
|||
|
||||
if (!mDataTime.IsNull() &&
|
||||
now - mDataTime >= TimeDuration::FromMilliseconds(STALL_MS)) {
|
||||
mElement->DispatchAsyncProgressEvent(NS_LITERAL_STRING("stalled"));
|
||||
mElement->DownloadStalled();
|
||||
// Null it out
|
||||
mDataTime = TimeStamp();
|
||||
}
|
||||
|
|
|
@ -501,17 +501,25 @@ void nsMediaChannelStream::Suspend(PRBool aCloseImmediately)
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Don't call on main thread");
|
||||
|
||||
nsHTMLMediaElement* element = mDecoder->GetMediaElement();
|
||||
if (!element) {
|
||||
// Shutting down; do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
if (mChannel) {
|
||||
if (aCloseImmediately && mCacheStream.IsSeekable()) {
|
||||
// Kill off our channel right now, but don't tell anyone about it.
|
||||
mIgnoreClose = PR_TRUE;
|
||||
CloseChannel();
|
||||
element->DownloadSuspended();
|
||||
} else if (mSuspendCount == 0) {
|
||||
{
|
||||
nsAutoLock lock(mLock);
|
||||
mChannelStatistics.Stop(TimeStamp::Now());
|
||||
}
|
||||
mChannel->Suspend();
|
||||
element->DownloadSuspended();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -523,6 +531,12 @@ void nsMediaChannelStream::Resume()
|
|||
NS_ASSERTION(NS_IsMainThread(), "Don't call on main thread");
|
||||
NS_ASSERTION(mSuspendCount > 0, "Too many resumes!");
|
||||
|
||||
nsHTMLMediaElement* element = mDecoder->GetMediaElement();
|
||||
if (!element) {
|
||||
// Shutting down; do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
--mSuspendCount;
|
||||
if (mSuspendCount == 0) {
|
||||
if (mChannel) {
|
||||
|
@ -535,9 +549,11 @@ void nsMediaChannelStream::Resume()
|
|||
// timed out the connection and we should reopen it.
|
||||
mReopenOnError = PR_TRUE;
|
||||
mChannel->Resume();
|
||||
element->DownloadResumed();
|
||||
} else {
|
||||
// Need to recreate the channel
|
||||
CacheClientSeek(mOffset, PR_FALSE);
|
||||
element->DownloadResumed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,9 +17,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=479863
|
|||
|
||||
</div>
|
||||
|
||||
<video id='v1' onerror="event.stopPropagation()"></video>
|
||||
<video id='v2' onerror="event.stopPropagation()" autobuffer></video>
|
||||
<video id='v3' onerror="event.stopPropagation()" autoplay></video>
|
||||
<video id='v4' onerror="event.stopPropagation()"></video>
|
||||
<video id='v5' onerror="event.stopPropagation()"></video>
|
||||
<video id='v6' onerror="event.stopPropagation()"></video>
|
||||
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
var stalls = { v1:false, v2:false, v3:false, v4:false, v5:false, v6:false };
|
||||
var loads = { v1:false, v2:false, v3:false, v4:false, v5:false, v6:false };
|
||||
var suspends = {};
|
||||
var loads = {};
|
||||
var totalLoadEvents = 0;
|
||||
var expectedLoadEvents = 6;
|
||||
|
||||
|
@ -27,13 +35,12 @@ function loaded(event) {
|
|||
loads[event.target.id] = true;
|
||||
++totalLoadEvents;
|
||||
if (totalLoadEvents == expectedLoadEvents) {
|
||||
ok(stalls.v1, "v1 should stall");
|
||||
// We might get accidental stalls on very slow machines, so lets not test these
|
||||
// ok(!stalls.v2, "v2 should not stall");
|
||||
// ok(!stalls.v3, "v3 should not stall");
|
||||
ok(stalls.v4, "v4 should stall");
|
||||
ok(stalls.v5, "v5 should stall");
|
||||
ok(stalls.v6, "v6 should stall");
|
||||
ok(suspends.v1, "v1 should suspend");
|
||||
ok(!suspends.v2, "v2 should not suspend");
|
||||
ok(!suspends.v3, "v3 should not suspend");
|
||||
ok(suspends.v4, "v4 should suspend");
|
||||
ok(suspends.v5, "v5 should suspend");
|
||||
ok(suspends.v6, "v6 should suspend");
|
||||
ok(loads.v1, "v1 should load after setting autobuffer");
|
||||
ok(loads.v2, "v2 should load");
|
||||
ok(loads.v3, "v3 should load");
|
||||
|
@ -43,8 +50,11 @@ function loaded(event) {
|
|||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
function stalled(event) {
|
||||
stalls[event.target.id] = true;
|
||||
|
||||
function suspended(event) {
|
||||
is(event.target.networkState, event.target.NETWORK_IDLE,
|
||||
event.target.id + " suspended networkState");
|
||||
suspends[event.target.id] = true;
|
||||
if (event.target.id == "v1") {
|
||||
event.target.autobuffer = true;
|
||||
} else if (event.target.id == "v4") {
|
||||
|
@ -55,17 +65,24 @@ function stalled(event) {
|
|||
event.target.autoplay = true;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<video id='v1' src="seek.ogv" onstalled="stalled(event)" onload="loaded(event)"></video>
|
||||
<video id='v2' src="seek.ogv" onstalled="stalled(event)" onload="loaded(event)" autobuffer></video>
|
||||
<video id='v3' src="seek.ogv" onstalled="stalled(event)" onload="loaded(event)" autoplay></video>
|
||||
<video id='v4' src="seek.ogv" onstalled="stalled(event)" onload="loaded(event)"></video>
|
||||
<video id='v5' src="seek.ogv" onstalled="stalled(event)" onload="loaded(event)"></video>
|
||||
<video id='v6' src="seek.ogv" onstalled="stalled(event)" onload="loaded(event)"></video>
|
||||
function logEvent(event) {
|
||||
dump(event.type + " " + event.target.id + "\n");
|
||||
}
|
||||
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
var key = Math.random();
|
||||
var eventList = ["metadataloaded", "loadeddata", "playing", "load", "stalled", "suspend", "ended"];
|
||||
for (var i = 1; i <= expectedLoadEvents; ++i) {
|
||||
var id = "v" + i;
|
||||
suspends[id] = loads[id] = false;
|
||||
var v = document.getElementById(id);
|
||||
v.addEventListener("suspend", suspended, false);
|
||||
v.addEventListener("load", loaded, false);
|
||||
for (var n = 0; n < eventList.length; ++n) {
|
||||
v.addEventListener(eventList[n], logEvent, false);
|
||||
}
|
||||
v.src = "seek.ogv?key=" + key + "&id=" + id;
|
||||
}
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</pre>
|
||||
|
|
|
@ -24,7 +24,7 @@ function log(msg) {
|
|||
|
||||
// We don't track: progress, canplay, canplaythrough and stalled events,
|
||||
// as these can be delivered out of order, and/or multiple times.
|
||||
var gEventTypes = [ 'loadstart', 'suspend', 'load', 'abort', 'error', 'emptied', 'play', 'pause', 'loadedmetadata', 'loadeddata', 'waiting', 'playing', 'seeking', 'seeked', 'timeupdate', 'ended', 'ratechange', 'durationchange', 'volumechange' ];
|
||||
var gEventTypes = [ 'loadstart', 'load', 'abort', 'error', 'emptied', 'play', 'pause', 'loadedmetadata', 'loadeddata', 'waiting', 'playing', 'seeking', 'seeked', 'timeupdate', 'ended', 'ratechange', 'durationchange', 'volumechange' ];
|
||||
|
||||
var gEventNum = 0;
|
||||
var gTestNum = 0;
|
||||
|
|
Загрузка…
Ссылка в новой задаче