Bug 1144481 - Use state mirroring for NextFrameStatus. r=jww

This commit is contained in:
Bobby Holley
2015-03-31 18:44:36 -07:00
parent 7a2a20e0d6
commit 1e4f8d4df5
10 changed files with 182 additions and 158 deletions

View File

@@ -700,7 +700,6 @@ void HTMLMediaElement::AbortExistingLoads()
mPendingEncryptedInitData.mInitDatas.Clear();
#endif // MOZ_EME
mSourcePointer = nullptr;
mNextFrameStatus = NEXT_FRAME_UNINITIALIZED;
mTags = nullptr;
@@ -2047,7 +2046,6 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
mNetworkState(nsIDOMHTMLMediaElement::NETWORK_EMPTY),
mReadyState(nsIDOMHTMLMediaElement::HAVE_NOTHING, "HTMLMediaElement::mReadyState"),
mReadyStateUpdater("HTMLMediaElement::mReadyStateUpdater"),
mNextFrameStatus(NEXT_FRAME_UNINITIALIZED, "HTMLMediaElement::mNextFrameStatus"),
mLoadWaitStatus(NOT_WAITING),
mVolume(1.0),
mPreloadAction(PRELOAD_UNDEFINED),
@@ -2113,7 +2111,6 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
MOZ_ASSERT(NS_IsMainThread());
mReadyStateUpdater->AddWeakCallback(this, &HTMLMediaElement::UpdateReadyStateInternal);
mReadyStateUpdater->Watch(mNextFrameStatus);
mReadyStateUpdater->Watch(mDownloadSuspendedByCache);
// Paradoxically, there is a self-edge whereby UpdateReadyStateInternal refuses
// to run until mReadyState reaches at least HAVE_METADATA by some other means.
@@ -2614,8 +2611,8 @@ HTMLMediaElement::ReportMSETelemetry()
ErrorResult ignore;
stalled = index != TimeRanges::NoIndex &&
(ranges->End(index, ignore) - t) < errorMargin;
stalled |= mNextFrameStatus == MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_BUFFERING &&
mReadyState == HTMLMediaElement::HAVE_CURRENT_DATA;
stalled |= mDecoder && NextFrameStatus() == MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_BUFFERING &&
mReadyState == HTMLMediaElement::HAVE_CURRENT_DATA;
if (stalled) {
state = STALLED;
}
@@ -2850,13 +2847,16 @@ nsresult HTMLMediaElement::FinishDecoderSetup(MediaDecoder* aDecoder,
return rv;
}
class HTMLMediaElement::StreamListener : public MediaStreamListener {
class HTMLMediaElement::StreamListener : public MediaStreamListener,
public WatchTarget
{
public:
explicit StreamListener(HTMLMediaElement* aElement) :
explicit StreamListener(HTMLMediaElement* aElement, const char* aName) :
WatchTarget(aName),
mElement(aElement),
mHaveCurrentData(false),
mBlocked(false),
mMutex("HTMLMediaElement::StreamListener"),
mMutex(aName),
mPendingNotifyOutput(false)
{}
void Forget() { mElement = nullptr; }
@@ -2869,24 +2869,25 @@ public:
mElement->PlaybackEnded();
}
}
void UpdateReadyStateForData()
MediaDecoderOwner::NextFrameStatus NextFrameStatus()
{
if (mElement && mHaveCurrentData) {
nsRefPtr<HTMLMediaElement> deathGrip = mElement;
mElement->UpdateReadyStateForData(
mBlocked ? MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_BUFFERING :
MediaDecoderOwner::NEXT_FRAME_AVAILABLE);
if (!mElement || !mHaveCurrentData) {
return MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
}
return mBlocked ? MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_BUFFERING
: MediaDecoderOwner::NEXT_FRAME_AVAILABLE;
}
void DoNotifyBlocked()
{
mBlocked = true;
UpdateReadyStateForData();
NotifyWatchers();
}
void DoNotifyUnblocked()
{
mBlocked = false;
UpdateReadyStateForData();
NotifyWatchers();
}
void DoNotifyOutput()
{
@@ -2906,7 +2907,7 @@ public:
nsRefPtr<HTMLMediaElement> deathGrip = mElement;
mElement->FirstFrameLoaded();
}
UpdateReadyStateForData();
NotifyWatchers();
DoNotifyOutput();
}
@@ -3070,8 +3071,9 @@ void HTMLMediaElement::SetupSrcMediaStreamPlayback(DOMMediaStream* aStream)
// XXX if we ever support capturing the output of a media element which is
// playing a stream, we'll need to add a CombineWithPrincipal call here.
mMediaStreamListener = new StreamListener(this);
mMediaStreamListener = new StreamListener(this, "HTMLMediaElement::mMediaStreamListener");
mMediaStreamSizeListener = new StreamSizeListener(this);
mReadyStateUpdater->Watch(*mMediaStreamListener);
GetSrcMediaStream()->AddListener(mMediaStreamListener);
// Listen for an initial image size on mSrcStream so we can get results even
@@ -3121,6 +3123,7 @@ void HTMLMediaElement::EndSrcMediaStreamPlayback()
}
// Kill its reference to this element
mReadyStateUpdater->Unwatch(*mMediaStreamListener);
mMediaStreamListener->Forget();
mMediaStreamListener = nullptr;
mMediaStreamSizeListener->Forget();
@@ -3504,11 +3507,6 @@ bool HTMLMediaElement::IsCORSSameOrigin()
ShouldCheckAllowOrigin();
}
void HTMLMediaElement::UpdateReadyStateForData(MediaDecoderOwner::NextFrameStatus aNextFrame)
{
mNextFrameStatus = aNextFrame;
}
void
HTMLMediaElement::UpdateReadyStateInternal()
{
@@ -3539,7 +3537,7 @@ HTMLMediaElement::UpdateReadyStateInternal()
MetadataLoaded(&mediaInfo, nsAutoPtr<const MetadataTags>(nullptr));
}
if (mNextFrameStatus == MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_SEEKING) {
if (NextFrameStatus() == MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_SEEKING) {
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
return;
}
@@ -3568,9 +3566,9 @@ HTMLMediaElement::UpdateReadyStateInternal()
return;
}
if (mNextFrameStatus != MediaDecoderOwner::NEXT_FRAME_AVAILABLE) {
if (NextFrameStatus() != MediaDecoderOwner::NEXT_FRAME_AVAILABLE) {
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA);
if (!mWaitingFired && mNextFrameStatus == MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_BUFFERING) {
if (!mWaitingFired && NextFrameStatus() == MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_BUFFERING) {
FireTimeUpdate(false);
DispatchAsyncEvent(NS_LITERAL_STRING("waiting"));
mWaitingFired = true;
@@ -4700,5 +4698,16 @@ HTMLMediaElement::SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv)
SetHTMLAttr(nsGkAtoms::mozaudiochannel, channel, aRv);
}
MediaDecoderOwner::NextFrameStatus
HTMLMediaElement::NextFrameStatus()
{
if (mDecoder) {
return mDecoder->NextFrameStatus();
} else if (mMediaStreamListener) {
return mMediaStreamListener->NextFrameStatus();
}
return NEXT_FRAME_UNINITIALIZED;
}
} // namespace dom
} // namespace mozilla