Bug 1259788 - Ensure ready state is updated when first track added after NotifyTracksAvailable(). r?jesup
MozReview-Commit-ID: 1FwPfety82M
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -1383,16 +1383,18 @@ void HTMLMediaElement::NotifyMediaTrackD
void HTMLMediaElement::NotifyMediaStreamTracksAvailable(DOMMediaStream* aStream)
{
if (!mSrcStream || mSrcStream != aStream) {
return;
}
LOG(LogLevel::Debug, ("MediaElement %p MediaStream tracks available", this));
+ mSrcStreamTracksAvailable = true;
+
bool videoHasChanged = IsVideo() && HasVideo() != !VideoTracks()->IsEmpty();
if (videoHasChanged) {
// We are a video element and HasVideo() changed so update the screen
// wakelock
NotifyOwnerDocumentActivityChangedInternal();
}
@@ -2841,16 +2843,17 @@ private:
HTMLMediaElement* mWeak = nullptr;
};
NS_IMPL_ISUPPORTS(HTMLMediaElement::ShutdownObserver, nsIObserver)
HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
: nsGenericHTMLElement(aNodeInfo),
mWatchManager(this, AbstractThread::MainThread()),
+ mSrcStreamTracksAvailable(false),
mSrcStreamPausedCurrentTime(-1),
mShutdownObserver(new ShutdownObserver),
mCurrentLoadID(0),
mNetworkState(nsIDOMHTMLMediaElement::NETWORK_EMPTY),
mReadyState(nsIDOMHTMLMediaElement::HAVE_NOTHING, "HTMLMediaElement::mReadyState"),
mLoadWaitStatus(NOT_WAITING),
mVolume(1.0),
mPreloadAction(PRELOAD_UNDEFINED),
@@ -4162,16 +4165,17 @@ void HTMLMediaElement::EndSrcMediaStream
}
mMediaStreamSizeListener->Forget();
}
mSelectedVideoStreamTrack = nullptr;
mMediaStreamSizeListener = nullptr;
mSrcStream->UnregisterTrackListener(mMediaStreamTrackListener);
mMediaStreamTrackListener = nullptr;
+ mSrcStreamTracksAvailable = false;
mSrcStream->RemovePrincipalChangeObserver(this);
mSrcStreamVideoPrincipal = nullptr;
for (OutputMediaStream& ms : mOutputStreams) {
for (auto pair : ms.mTrackPorts) {
pair.second()->Destroy();
}
@@ -4236,16 +4240,18 @@ HTMLMediaElement::NotifyMediaStreamTrack
VideoTracks()->AddTrack(videoTrack);
// New MediaStreamTrack added, set the new added video track as selected
// video track when there is no selected track.
if (VideoTracks()->SelectedIndex() == -1) {
MOZ_ASSERT(!mSelectedVideoStreamTrack);
videoTrack->SetEnabledInternal(true, MediaTrack::FIRE_NO_EVENTS);
}
}
+
+ mWatchManager.ManualNotify(&HTMLMediaElement::UpdateReadyStateInternal);
}
void
HTMLMediaElement::NotifyMediaStreamTrackRemoved(const RefPtr<MediaStreamTrack>& aTrack)
{
MOZ_ASSERT(aTrack);
nsAutoString id;
@@ -4670,19 +4676,24 @@ HTMLMediaElement::UpdateReadyStateIntern
// on its own thread before MetadataLoaded gets a chance to run.
// The arrival of more data can't change us out of this readyState.
LOG(LogLevel::Debug, ("MediaElement %p UpdateReadyStateInternal() "
"Decoder ready state < HAVE_METADATA", this));
return;
}
if (mSrcStream && mReadyState < nsIDOMHTMLMediaElement::HAVE_METADATA) {
+ if (!mSrcStreamTracksAvailable) {
+ LOG(LogLevel::Debug, ("MediaElement %p UpdateReadyStateInternal() "
+ "MediaStreamTracks not available yet", this));
+ return;
+ }
+
bool hasAudioTracks = !AudioTracks()->IsEmpty();
bool hasVideoTracks = !VideoTracks()->IsEmpty();
-
if (!hasAudioTracks && !hasVideoTracks) {
LOG(LogLevel::Debug, ("MediaElement %p UpdateReadyStateInternal() "
"Stream with no tracks", this));
return;
}
if (IsVideo() && hasVideoTracks && !HasVideo()) {
LOG(LogLevel::Debug, ("MediaElement %p UpdateReadyStateInternal() "
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -1280,16 +1280,19 @@ protected:
// set in the src attribute.
RefPtr<DOMMediaStream> mSrcAttrStream;
// Holds a reference to the DOM wrapper for the MediaStream that we're
// actually playing.
// At most one of mDecoder and mSrcStream can be non-null.
RefPtr<DOMMediaStream> mSrcStream;
+ // True once mSrcStream's initial set of tracks are known.
+ bool mSrcStreamTracksAvailable;
+
// If non-negative, the time we should return for currentTime while playing
// mSrcStream.
double mSrcStreamPausedCurrentTime;
// Holds a reference to the stream connecting this stream to the capture sink.
RefPtr<MediaInputPort> mCaptureStreamPort;
// Holds references to the DOM wrappers for the MediaStreams that we're