Backed out changeset 78424c3ea6cb (bug 883731)

This commit is contained in:
Ed Morley 2013-06-19 09:51:05 +01:00
parent db5d45d578
commit ef197a10fb
6 changed files with 97 additions and 34 deletions

View File

@ -154,7 +154,13 @@ public:
// Called by the video decoder object, on the main thread,
// when it has read the first frame of the video
virtual void FirstFrameLoaded() MOZ_FINAL MOZ_OVERRIDE;
// aResourceFullyLoaded should be true if the resource has been
// fully loaded and the caller will call ResourceLoaded next.
virtual void FirstFrameLoaded(bool aResourceFullyLoaded) MOZ_FINAL MOZ_OVERRIDE;
// Called by the video decoder object, on the main thread,
// when the resource has completed downloading.
virtual void ResourceLoaded() MOZ_FINAL MOZ_OVERRIDE;
// Called by the video decoder object, on the main thread,
// when the resource has a network error during loading.

View File

@ -2581,7 +2581,7 @@ public:
{
mHaveCurrentData = true;
if (mElement) {
mElement->FirstFrameLoaded();
mElement->FirstFrameLoaded(false);
}
UpdateReadyStateForData();
DoNotifyOutput();
@ -2671,7 +2671,8 @@ void HTMLMediaElement::SetupSrcMediaStreamPlayback(DOMMediaStream* aStream)
}
AddRemoveSelfReference();
// FirstFrameLoaded() will be called when the stream has current data.
// FirstFrameLoaded(false) will be called when the stream has current data,
// to complete the setup by entering the HAVE_CURRENT_DATA state.
}
void HTMLMediaElement::EndSrcMediaStreamPlayback()
@ -2743,7 +2744,7 @@ void HTMLMediaElement::MetadataLoaded(int aChannels,
}
}
void HTMLMediaElement::FirstFrameLoaded()
void HTMLMediaElement::FirstFrameLoaded(bool aResourceFullyLoaded)
{
ChangeDelayLoadStatus(false);
UpdateReadyStateForData(NEXT_FRAME_UNAVAILABLE);
@ -2751,6 +2752,7 @@ void HTMLMediaElement::FirstFrameLoaded()
NS_ASSERTION(!mSuspendedAfterFirstFrame, "Should not have already suspended");
if (mDecoder && mAllowSuspendAfterFirstFrame && mPaused &&
!aResourceFullyLoaded &&
!HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay) &&
mPreloadAction == HTMLMediaElement::PRELOAD_METADATA) {
mSuspendedAfterFirstFrame = true;
@ -2772,6 +2774,26 @@ void HTMLMediaElement::FirstFrameLoaded()
}
}
void HTMLMediaElement::ResourceLoaded()
{
NS_ASSERTION(!mSrcStream, "Don't call this for streams");
mBegun = false;
mNetworkState = NETWORK_IDLE;
AddRemoveSelfReference();
if (mReadyState >= HAVE_METADATA) {
// MediaStream sources are put into HAVE_CURRENT_DATA state here on setup. If the
// stream is not blocked, we will receive a notification that will put it
// into HAVE_ENOUGH_DATA state.
ChangeReadyState(mSrcStream ? HAVE_CURRENT_DATA
: HAVE_ENOUGH_DATA);
}
// Ensure a progress event is dispatched at the end of download.
DispatchAsyncEvent(NS_LITERAL_STRING("progress"));
// The download has stopped.
DispatchAsyncEvent(NS_LITERAL_STRING("suspend"));
}
void HTMLMediaElement::NetworkError()
{
Error(nsIDOMMediaError::MEDIA_ERR_NETWORK);
@ -2916,7 +2938,7 @@ void HTMLMediaElement::UpdateReadyStateForData(NextFrameStatus aNextFrame)
if (mReadyState < HAVE_METADATA) {
// aNextFrame might have a next frame because the decoder can advance
// on its own thread before MetadataLoaded gets
// on its own thread before ResourceLoaded or MetadataLoaded gets
// a chance to run.
// The arrival of more data can't change us out of this readyState.
return;
@ -2933,8 +2955,6 @@ void HTMLMediaElement::UpdateReadyStateForData(NextFrameStatus aNextFrame)
// media cache is too small, and scripts are bound to fail. Don't force
// this transition if the decoder is in ended state; the readyState
// should remain at HAVE_CURRENT_DATA in this case.
// Note that this state transition includes the case where we finished
// downloaded the whole data stream.
ChangeReadyState(HAVE_ENOUGH_DATA);
return;
}

View File

@ -372,6 +372,7 @@ MediaDecoder::MediaDecoder() :
mIsDormant(false),
mPlayState(PLAY_STATE_PAUSED),
mNextState(PLAY_STATE_PAUSED),
mCalledResourceLoaded(false),
mIgnoreProgressData(false),
mInfiniteStream(false),
mTriggerPlaybackEndedWhenSourceStreamFinishes(false),
@ -742,13 +743,21 @@ void MediaDecoder::MetadataLoaded(int aChannels, int aRate, bool aHasAudio, bool
mOwner->MetadataLoaded(aChannels, aRate, aHasAudio, aHasVideo, aTags);
}
StartProgress();
if (!mCalledResourceLoaded) {
StartProgress();
} else if (mOwner) {
// Resource was loaded during metadata loading, when progress
// events are being ignored. Fire the final progress event.
mOwner->DispatchAsyncEvent(NS_LITERAL_STRING("progress"));
}
// Only inform the element of FirstFrameLoaded if not doing a load() in order
// to fulfill a seek, otherwise we'll get multiple loadedfirstframe events.
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
bool notifyResourceIsLoaded = !mCalledResourceLoaded &&
IsDataCachedToEndOfResource();
if (mOwner) {
mOwner->FirstFrameLoaded();
mOwner->FirstFrameLoaded(notifyResourceIsLoaded);
}
// This can run cache callbacks.
@ -767,11 +776,45 @@ void MediaDecoder::MetadataLoaded(int aChannels, int aRate, bool aHasAudio, bool
}
}
if (notifyResourceIsLoaded) {
ResourceLoaded();
}
// Run NotifySuspendedStatusChanged now to give us a chance to notice
// that autoplay should run.
NotifySuspendedStatusChanged();
}
void MediaDecoder::ResourceLoaded()
{
MOZ_ASSERT(NS_IsMainThread());
// Don't handle ResourceLoaded if we are shutting down, or if
// we need to ignore progress data due to seeking (in the case
// that the seek results in reaching end of file, we get a bogus call
// to ResourceLoaded).
if (mShuttingDown)
return;
{
// If we are seeking or loading then the resource loaded notification we get
// should be ignored, since it represents the end of the seek request.
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
if (mIgnoreProgressData || mCalledResourceLoaded || mPlayState == PLAY_STATE_LOADING)
return;
Progress(false);
mCalledResourceLoaded = true;
StopProgress();
}
// Ensure the final progress event gets fired
if (mOwner) {
mOwner->ResourceLoaded();
}
}
void MediaDecoder::NetworkError()
{
MOZ_ASSERT(NS_IsMainThread());
@ -977,12 +1020,12 @@ void MediaDecoder::NotifyDownloadEnded(nsresult aStatus)
}
if (NS_SUCCEEDED(aStatus)) {
UpdateReadyStateForData();
// A final progress event will be fired by the MediaResource calling
// DownloadSuspended on the element.
} else if (aStatus != NS_BASE_STREAM_CLOSED) {
ResourceLoaded();
}
else if (aStatus != NS_BASE_STREAM_CLOSED) {
NetworkError();
}
UpdateReadyStateForData();
}
void MediaDecoder::NotifyPrincipalChanged()

View File

@ -288,6 +288,9 @@ public:
nsresult OpenResource(MediaResource* aResource,
nsIStreamListener** aStreamListener);
// Called when the video file has completed downloading.
virtual void ResourceLoaded();
// Called if the media file encounters a network error.
virtual void NetworkError();
@ -1017,6 +1020,11 @@ public:
// This can only be PLAY_STATE_PAUSED or PLAY_STATE_PLAYING.
PlayState mNextState;
// True when we have fully loaded the resource and reported that
// to the element (i.e. reached NETWORK_LOADED state).
// Accessed on the main thread only.
bool mCalledResourceLoaded;
// True when seeking or otherwise moving the play position around in
// such a manner that progress event data is inaccurate. This is set
// during seek and duration operations to prevent the progress indicator

View File

@ -65,7 +65,11 @@ public:
// when it has read the first frame of the video
// aResourceFullyLoaded should be true if the resource has been
// fully loaded and the caller will call ResourceLoaded next.
virtual void FirstFrameLoaded() = 0;
virtual void FirstFrameLoaded(bool aResourceFullyLoaded) = 0;
// Called by the video decoder object, on the main thread,
// when the resource has completed downloading.
virtual void ResourceLoaded() = 0;
// Called by the video decoder object, on the main thread,
// when the resource has a network error during loading.

View File

@ -984,18 +984,11 @@ public:
mDecoder(aDecoder), mStatus(aStatus) {}
NS_IMETHOD Run() {
mDecoder->NotifyDownloadEnded(mStatus);
MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
if (owner) {
HTMLMediaElement* element = owner->GetMediaElement();
if (element) {
element->DownloadSuspended();
}
}
return NS_OK;
}
private:
nsRefPtr<MediaDecoder> mDecoder;
nsresult mStatus;
nsresult mStatus;
};
void
@ -1348,7 +1341,7 @@ public:
return std::max(aOffset, mSize);
}
virtual bool IsDataCachedToEndOfResource(int64_t aOffset) { return true; }
virtual bool IsSuspendedByCache() { return true; }
virtual bool IsSuspendedByCache() { return false; }
virtual bool IsSuspended() { return false; }
virtual bool IsTransportSeekable() MOZ_OVERRIDE { return true; }
@ -1398,18 +1391,7 @@ public:
}
NS_IMETHOD Run() {
// NotifySuspendedStatusChanged will tell the element that download
// has been suspended "by the cache", which is true since we never downloaded
// anything. The element can then transition to HAVE_ENOUGH_DATA.
mDecoder->NotifySuspendedStatusChanged();
mDecoder->NotifyDownloadEnded(NS_OK);
MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
if (owner) {
HTMLMediaElement* element = owner->GetMediaElement();
if (element) {
element->DownloadSuspended();
}
}
return NS_OK;
}