bug 1108838 dispatch "stalled" even when no bytes have been received r=cpearce

This is important for MediaSource, where there is no initial request to set up
the stall counter by sending an initial progress event.

For sources using ChannelMediaResource, this means that stalled can now fire
before an HTTP response is received.

Also reset stalled timer on transitions to NETWORK_LOADING,
and don't run the progress timer while stalled.

--HG--
extra : rebase_source : cf2cf8a4de37ca4859761941946393e9747c0706
This commit is contained in:
Karl Tomlinson 2014-11-28 17:07:15 +13:00
parent ea461ded0e
commit 46260ad7b6
4 changed files with 48 additions and 28 deletions

View File

@ -3091,10 +3091,12 @@ void HTMLMediaElement::CheckProgress(bool aHaveNewProgress)
// If this is the first progress, or PROGRESS_MS has passed since the last
// progress event fired and more data has arrived since then, fire a
// progress event.
if (!mDataTime.IsNull() &&
(mProgressTime.IsNull() ||
(now - mProgressTime >= TimeDuration::FromMilliseconds(PROGRESS_MS) &&
mDataTime > mProgressTime))) {
NS_ASSERTION((mProgressTime.IsNull() && !aHaveNewProgress) ||
!mDataTime.IsNull(),
"null TimeStamp mDataTime should not be used in comparison");
if (mProgressTime.IsNull() ? aHaveNewProgress
: (now - mProgressTime >= TimeDuration::FromMilliseconds(PROGRESS_MS) &&
mDataTime > mProgressTime)) {
DispatchAsyncEvent(NS_LITERAL_STRING("progress"));
// Resolution() ensures that future data will have now > mProgressTime,
// and so will trigger another event. mDataTime is not reset because it
@ -3104,13 +3106,20 @@ void HTMLMediaElement::CheckProgress(bool aHaveNewProgress)
if (mDataTime > mProgressTime) {
mDataTime = mProgressTime;
}
if (!mProgressTimer) {
NS_ASSERTION(aHaveNewProgress,
"timer dispatched when there was no timer");
// Were stalled. Restart timer.
StartProgressTimer();
}
}
if (!mDataTime.IsNull() &&
now - mDataTime >= TimeDuration::FromMilliseconds(STALL_MS)) {
if (now - mDataTime >= TimeDuration::FromMilliseconds(STALL_MS)) {
DispatchAsyncEvent(NS_LITERAL_STRING("stalled"));
// Null it out
mDataTime = TimeStamp();
NS_ASSERTION(mProgressTimer, "detected stalled without timer");
// Stop timer events, which prevents repeated stalled events until there
// is more progress.
StopProgress();
}
}
@ -3121,28 +3130,38 @@ void HTMLMediaElement::ProgressTimerCallback(nsITimer* aTimer, void* aClosure)
decoder->CheckProgress(false);
}
nsresult HTMLMediaElement::StartProgress()
void HTMLMediaElement::StartProgressTimer()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING);
NS_ASSERTION(!mProgressTimer, "Already started progress timer.");
mProgressTimer = do_CreateInstance("@mozilla.org/timer;1");
return mProgressTimer->InitWithFuncCallback(ProgressTimerCallback,
this,
PROGRESS_MS,
nsITimer::TYPE_REPEATING_SLACK);
mProgressTimer->InitWithFuncCallback(ProgressTimerCallback,
this,
PROGRESS_MS,
nsITimer::TYPE_REPEATING_SLACK);
}
nsresult HTMLMediaElement::StopProgress()
void HTMLMediaElement::StartProgress()
{
// Record the time now for detecting stalled.
mDataTime = TimeStamp::NowLoRes();
// Reset mProgressTime so that mDataTime is not indicating bytes received
// after the last progress event.
mProgressTime = TimeStamp();
StartProgressTimer();
}
void HTMLMediaElement::StopProgress()
{
MOZ_ASSERT(NS_IsMainThread());
NS_ASSERTION(mProgressTimer, "Already stopped progress timer.");
if (!mProgressTimer) {
return;
}
nsresult rv = mProgressTimer->Cancel();
mProgressTimer->Cancel();
mProgressTimer = nullptr;
return rv;
}
void HTMLMediaElement::DownloadProgressed()

View File

@ -887,11 +887,15 @@ protected:
/**
* Start timer to update download progress.
*/
nsresult StartProgress();
void StartProgressTimer();
/**
* Stop progress information timer.
* Start sending progress and/or stalled events.
*/
nsresult StopProgress();
void StartProgress();
/**
* Stop progress information timer and events.
*/
void StopProgress();
/**
* Dispatches an error event to a child source element.
@ -1087,9 +1091,8 @@ protected:
// Time that data was last read from the media resource. Used for
// computing if the download has stalled and to rate limit progress events
// when data is arriving slower than PROGRESS_MS. A value of null indicates
// that a stall event has already fired and not to fire another one until
// more data is received. Read/Write from the main thread only.
// when data is arriving slower than PROGRESS_MS.
// Read/Write from the main thread only.
TimeStamp mDataTime;
// Media 'currentTime' value when the last timeupdate event occurred.

View File

@ -367,8 +367,7 @@ ChannelMediaResource::OnStartRequest(nsIRequest* aRequest)
mIgnoreResume = false;
}
// Fires an initial progress event and sets up the stall counter so stall events
// fire if no download occurs within the required time frame.
// Fires an initial progress event.
owner->DownloadProgressed();
return NS_OK;

View File

@ -740,8 +740,7 @@ RtspMediaResource::OnConnected(uint8_t aTrackIdx,
}
MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
NS_ENSURE_TRUE(owner, NS_ERROR_FAILURE);
// Fires an initial progress event and sets up the stall counter so stall events
// fire if no download occurs within the required time frame.
// Fires an initial progress event.
owner->DownloadProgressed();
dom::HTMLMediaElement* element = owner->GetMediaElement();