Bug 1259788 - Ensure ready state is updated when first track added after NotifyTracksAvailable(). r?jesup draft
authorAndreas Pehrson <pehrsons@gmail.com>
Fri, 19 Aug 2016 13:41:48 +0200
changeset 404933 991e26a8f8273a7d6ad8286d3ddc60113265b2c4
parent 404932 6edf56f7cc330b37b6877e9fb94d7f0b9f85805d
child 404934 42c3a58cc00e3891391d0f247d0c736e97d6ad44
push id27359
push userpehrsons@gmail.com
push dateWed, 24 Aug 2016 14:53:56 +0000
reviewersjesup
bugs1259788
milestone51.0a1
Bug 1259788 - Ensure ready state is updated when first track added after NotifyTracksAvailable(). r?jesup MozReview-Commit-ID: 1FwPfety82M
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
--- 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