зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 5db9f8fbcaf4 (bug 883731) for webplatform 3 test failures
This commit is contained in:
Родитель
c6b8533277
Коммит
9bfd94ee23
|
@ -162,9 +162,15 @@ public:
|
|||
virtual void MetadataLoaded(const MediaInfo* aInfo,
|
||||
const MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
||||
// Called by the decoder object, on the main thread,
|
||||
// when it has read the first frame of the video or audio.
|
||||
virtual void FirstFrameLoaded() MOZ_FINAL MOZ_OVERRIDE;
|
||||
// Called by the video decoder object, on the main thread,
|
||||
// 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(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.
|
||||
|
@ -232,6 +238,10 @@ public:
|
|||
// HAVE_FUTURE_DATA or HAVE_ENOUGH_DATA.
|
||||
virtual void UpdateReadyStateForData(MediaDecoderOwner::NextFrameStatus aNextFrame) MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
||||
// Use this method to change the mReadyState member, so required
|
||||
// events can be fired.
|
||||
void ChangeReadyState(nsMediaReadyState aState);
|
||||
|
||||
// Return true if we can activate autoplay assuming enough data has arrived.
|
||||
bool CanActivateAutoplay();
|
||||
|
||||
|
@ -530,7 +540,7 @@ public:
|
|||
|
||||
already_AddRefed<Promise> SetMediaKeys(MediaKeys* mediaKeys,
|
||||
ErrorResult& aRv);
|
||||
|
||||
|
||||
MediaWaitingFor WaitingFor() const;
|
||||
|
||||
mozilla::dom::EventHandlerNonNull* GetOnencrypted();
|
||||
|
@ -638,11 +648,6 @@ protected:
|
|||
nsCOMPtr<nsITimer> mTimer;
|
||||
};
|
||||
|
||||
/** Use this method to change the mReadyState member, so required
|
||||
* events can be fired.
|
||||
*/
|
||||
void ChangeReadyState(nsMediaReadyState aState);
|
||||
|
||||
/**
|
||||
* These two methods are called by the WakeLockBoolWrapper when the wakelock
|
||||
* has to be created or released.
|
||||
|
@ -928,7 +933,7 @@ protected:
|
|||
// desired, and we'll seek to the sync point (keyframe and/or start of the
|
||||
// next block of audio samples) preceeding seek target.
|
||||
void Seek(double aTime, SeekTarget::Type aSeekType, ErrorResult& aRv);
|
||||
|
||||
|
||||
// Update the audio channel playing state
|
||||
void UpdateAudioChannelPlayingState();
|
||||
|
||||
|
@ -1099,8 +1104,9 @@ protected:
|
|||
// Set to false when completed, or not yet started.
|
||||
bool mBegun;
|
||||
|
||||
// True if loadeddata has been fired.
|
||||
bool mLoadedDataFired;
|
||||
// True when the decoder has loaded enough data to display the
|
||||
// first frame of the content.
|
||||
bool mLoadedFirstFrame;
|
||||
|
||||
// Indicates whether current playback is a result of user action
|
||||
// (ie. calling of the Play method), or automatic playback due to
|
||||
|
|
|
@ -661,8 +661,7 @@ void HTMLMediaElement::AbortExistingLoads()
|
|||
}
|
||||
|
||||
mError = nullptr;
|
||||
mBegun = false;
|
||||
mLoadedDataFired = false;
|
||||
mLoadedFirstFrame = false;
|
||||
mAutoplaying = true;
|
||||
mIsLoadingFromSourceChildren = false;
|
||||
mSuspendedAfterFirstFrame = false;
|
||||
|
@ -2028,7 +2027,7 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
|
|||
mPlayed(new TimeRanges),
|
||||
mCurrentPlayRangeStart(-1.0),
|
||||
mBegun(false),
|
||||
mLoadedDataFired(false),
|
||||
mLoadedFirstFrame(false),
|
||||
mAutoplaying(true),
|
||||
mAutoplayEnabled(true),
|
||||
mPaused(true),
|
||||
|
@ -2777,7 +2776,7 @@ public:
|
|||
mHaveCurrentData = true;
|
||||
if (mElement) {
|
||||
nsRefPtr<HTMLMediaElement> deathGrip = mElement;
|
||||
mElement->FirstFrameLoaded();
|
||||
mElement->FirstFrameLoaded(false);
|
||||
}
|
||||
UpdateReadyStateForData();
|
||||
DoNotifyOutput();
|
||||
|
@ -2871,7 +2870,8 @@ void HTMLMediaElement::SetupSrcMediaStreamPlayback(DOMMediaStream* aStream)
|
|||
DispatchAsyncEvent(NS_LITERAL_STRING("suspend"));
|
||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE;
|
||||
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()
|
||||
|
@ -2921,7 +2921,6 @@ void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo,
|
|||
{
|
||||
mHasAudio = aInfo->HasAudio();
|
||||
mTags = aTags;
|
||||
mLoadedDataFired = false;
|
||||
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("durationchange"));
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("loadedmetadata"));
|
||||
|
@ -2941,19 +2940,25 @@ void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo,
|
|||
}
|
||||
}
|
||||
|
||||
void HTMLMediaElement::FirstFrameLoaded()
|
||||
void HTMLMediaElement::FirstFrameLoaded(bool aResourceFullyLoaded)
|
||||
{
|
||||
NS_ASSERTION(!mSuspendedAfterFirstFrame, "Should not have already suspended");
|
||||
|
||||
ChangeReadyState(aResourceFullyLoaded ?
|
||||
nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA :
|
||||
nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA);
|
||||
ChangeDelayLoadStatus(false);
|
||||
|
||||
NS_ASSERTION(!mSuspendedAfterFirstFrame, "Should not have already suspended");
|
||||
|
||||
if (mDecoder && mAllowSuspendAfterFirstFrame && mPaused &&
|
||||
!aResourceFullyLoaded &&
|
||||
!HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay) &&
|
||||
mPreloadAction == HTMLMediaElement::PRELOAD_METADATA) {
|
||||
mSuspendedAfterFirstFrame = true;
|
||||
mDecoder->Suspend();
|
||||
} else if (mDownloadSuspendedByCache &&
|
||||
mDecoder && !mDecoder->IsEnded()) {
|
||||
} else if (mLoadedFirstFrame &&
|
||||
mDownloadSuspendedByCache &&
|
||||
mDecoder &&
|
||||
!mDecoder->IsEnded()) {
|
||||
// We've already loaded the first frame, and the decoder has signalled
|
||||
// that the download has been suspended by the media cache. So move
|
||||
// readyState into HAVE_ENOUGH_DATA, in case there's script waiting
|
||||
|
@ -2967,6 +2972,26 @@ void HTMLMediaElement::FirstFrameLoaded()
|
|||
}
|
||||
}
|
||||
|
||||
void HTMLMediaElement::ResourceLoaded()
|
||||
{
|
||||
NS_ASSERTION(!mSrcStream, "Don't call this for streams");
|
||||
|
||||
mBegun = false;
|
||||
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE;
|
||||
AddRemoveSelfReference();
|
||||
if (mReadyState >= nsIDOMHTMLMediaElement::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 ? nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA
|
||||
: nsIDOMHTMLMediaElement::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);
|
||||
|
@ -3121,7 +3146,8 @@ void HTMLMediaElement::UpdateReadyStateForData(MediaDecoderOwner::NextFrameStatu
|
|||
{
|
||||
if (mReadyState < nsIDOMHTMLMediaElement::HAVE_METADATA) {
|
||||
// aNextFrame might have a next frame because the decoder can advance
|
||||
// on its own thread before MetadataLoaded gets a chance to run.
|
||||
// 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;
|
||||
}
|
||||
|
@ -3134,16 +3160,17 @@ void HTMLMediaElement::UpdateReadyStateForData(MediaDecoderOwner::NextFrameStatu
|
|||
return;
|
||||
}
|
||||
|
||||
if (mDownloadSuspendedByCache && mDecoder && !mDecoder->IsEnded()) {
|
||||
// The decoder has signaled that the download has been suspended by the
|
||||
if (mReadyState > nsIDOMHTMLMediaElement::HAVE_METADATA &&
|
||||
mDownloadSuspendedByCache &&
|
||||
mDecoder &&
|
||||
!mDecoder->IsEnded()) {
|
||||
// The decoder has signalled that the download has been suspended by the
|
||||
// media cache. So move readyState into HAVE_ENOUGH_DATA, in case there's
|
||||
// script waiting for a "canplaythrough" event; without this forced
|
||||
// transition, we will never fire the "canplaythrough" event if the
|
||||
// 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(nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA);
|
||||
return;
|
||||
}
|
||||
|
@ -3214,9 +3241,10 @@ void HTMLMediaElement::ChangeReadyState(nsMediaReadyState aState)
|
|||
|
||||
if (oldState < nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA &&
|
||||
mReadyState >= nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA &&
|
||||
!mLoadedDataFired) {
|
||||
!mLoadedFirstFrame)
|
||||
{
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("loadeddata"));
|
||||
mLoadedDataFired = true;
|
||||
mLoadedFirstFrame = true;
|
||||
}
|
||||
|
||||
if (mReadyState == nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA) {
|
||||
|
|
|
@ -1857,11 +1857,7 @@ MediaCacheStream::NotifyDataEnded(nsresult aStatus)
|
|||
mResourceID = gMediaCache->AllocateResourceID();
|
||||
}
|
||||
|
||||
// It is prudent to update channel/cache status before calling
|
||||
// CacheClientNotifyDataEnded() which will read |mChannelEnded|.
|
||||
FlushPartialBlockInternal(true);
|
||||
mChannelEnded = true;
|
||||
gMediaCache->QueueUpdate();
|
||||
|
||||
MediaCache::ResourceStreamIterator iter(mResourceID);
|
||||
while (MediaCacheStream* stream = iter.Next()) {
|
||||
|
@ -1875,6 +1871,9 @@ MediaCacheStream::NotifyDataEnded(nsresult aStatus)
|
|||
stream->mClient->CacheClientNotifyDataEnded(aStatus);
|
||||
}
|
||||
}
|
||||
|
||||
mChannelEnded = true;
|
||||
gMediaCache->QueueUpdate();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -440,6 +440,7 @@ MediaDecoder::MediaDecoder() :
|
|||
mIsExitingDormant(false),
|
||||
mPlayState(PLAY_STATE_PAUSED),
|
||||
mNextState(PLAY_STATE_PAUSED),
|
||||
mCalledResourceLoaded(false),
|
||||
mIgnoreProgressData(false),
|
||||
mInfiniteStream(false),
|
||||
mOwner(nullptr),
|
||||
|
@ -723,8 +724,20 @@ void MediaDecoder::MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags)
|
|||
mOwner->MetadataLoaded(aInfo, aTags);
|
||||
}
|
||||
|
||||
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.
|
||||
bool notifyResourceIsLoaded = !mCalledResourceLoaded &&
|
||||
IsDataCachedToEndOfResource();
|
||||
if (mOwner) {
|
||||
mOwner->FirstFrameLoaded();
|
||||
mOwner->FirstFrameLoaded(notifyResourceIsLoaded);
|
||||
}
|
||||
|
||||
// This can run cache callbacks.
|
||||
|
@ -743,11 +756,45 @@ void MediaDecoder::MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags)
|
|||
}
|
||||
}
|
||||
|
||||
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::ResetConnectionState()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
@ -982,12 +1029,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()
|
||||
|
|
|
@ -308,6 +308,9 @@ public:
|
|||
// Called in |Load| to open mResource.
|
||||
nsresult OpenResource(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();
|
||||
|
||||
|
@ -1156,6 +1159,11 @@ protected:
|
|||
// been requested. When a seek is started this is reset to invalid.
|
||||
SeekTarget mRequestedSeekTarget;
|
||||
|
||||
// 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
|
||||
|
|
|
@ -52,9 +52,15 @@ public:
|
|||
virtual void MetadataLoaded(const MediaInfo* aInfo,
|
||||
const MetadataTags* aTags) = 0;
|
||||
|
||||
// Called by the decoder object, on the main thread,
|
||||
// when it has read the first frame of the video or audio.
|
||||
virtual void FirstFrameLoaded() = 0;
|
||||
// Called by the video decoder object, on the main thread,
|
||||
// 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(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.
|
||||
|
|
|
@ -984,24 +984,11 @@ public:
|
|||
mDecoder(aDecoder), mStatus(aStatus) {}
|
||||
NS_IMETHOD Run() {
|
||||
mDecoder->NotifyDownloadEnded(mStatus);
|
||||
if (NS_SUCCEEDED(mStatus)) {
|
||||
MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
|
||||
if (owner) {
|
||||
dom::HTMLMediaElement* element = owner->GetMediaElement();
|
||||
if (element) {
|
||||
element->DownloadSuspended();
|
||||
}
|
||||
}
|
||||
// NotifySuspendedStatusChanged will tell the element that download
|
||||
// has been suspended "by the cache", which is true since we never download
|
||||
// anything. The element can then transition to HAVE_ENOUGH_DATA.
|
||||
mDecoder->NotifySuspendedStatusChanged();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
nsRefPtr<MediaDecoder> mDecoder;
|
||||
nsresult mStatus;
|
||||
nsresult mStatus;
|
||||
};
|
||||
|
||||
void
|
||||
|
@ -1261,8 +1248,8 @@ public:
|
|||
return std::max(aOffset, mSize);
|
||||
}
|
||||
virtual bool IsDataCachedToEndOfResource(int64_t aOffset) { return true; }
|
||||
virtual bool IsSuspendedByCache() { return true; }
|
||||
virtual bool IsSuspended() { return true; }
|
||||
virtual bool IsSuspendedByCache() { return false; }
|
||||
virtual bool IsSuspended() { return false; }
|
||||
virtual bool IsTransportSeekable() MOZ_OVERRIDE { return true; }
|
||||
|
||||
nsresult GetCachedRanges(nsTArray<MediaByteRange>& aRanges);
|
||||
|
|
Загрузка…
Ссылка в новой задаче