Bug 1129263 - Part 6. Remove DOMMediaStream::TrackTypeHints. r=roc,jesup
authorAndreas Pehrson <pehrsons@gmail.com>
Mon, 09 Feb 2015 15:23:34 +0800
changeset 231544 8f725bbaff1cbff02442431982c13356e3ba5dc5
parent 231543 8f314a751ca772ffd6a738f907bcc32c2c839330
child 231545 bf6cd84214a546ecb053ef9df037a2ed0a74b023
push id28355
push userkwierso@gmail.com
push dateWed, 04 Mar 2015 00:49:07 +0000
treeherdermozilla-central@f42b9946f08f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, jesup
bugs1129263
milestone39.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1129263 - Part 6. Remove DOMMediaStream::TrackTypeHints. r=roc,jesup
dom/camera/DOMCameraControl.cpp
dom/html/HTMLMediaElement.cpp
dom/media/DOMMediaStream.cpp
dom/media/DOMMediaStream.h
dom/media/MediaManager.cpp
dom/media/MediaManager.h
dom/media/MediaRecorder.cpp
dom/media/MediaStreamGraph.cpp
dom/media/MediaStreamGraph.h
dom/media/MediaStreamGraphImpl.h
dom/media/webaudio/AudioDestinationNode.cpp
dom/media/webaudio/MediaStreamAudioDestinationNode.cpp
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
media/webrtc/signaling/test/FakeMediaStreams.h
--- a/dom/camera/DOMCameraControl.cpp
+++ b/dom/camera/DOMCameraControl.cpp
@@ -259,17 +259,16 @@ nsDOMCameraControl::nsDOMCameraControl(u
 #endif
     mCameraControl = ICameraControl::Create(aCameraId);
 #ifdef MOZ_WIDGET_GONK
   }
 #endif
   mCurrentConfiguration = initialConfig.forget();
 
   // Attach our DOM-facing media stream to our viewfinder stream.
-  SetHintContents(HINT_CONTENTS_VIDEO);
   InitStreamCommon(mInput);
   MOZ_ASSERT(mWindow, "Shouldn't be created with a null window!");
   if (mWindow->GetExtantDoc()) {
     CombineWithPrincipal(mWindow->GetExtantDoc()->NodePrincipal());
   }
 
   // Register a listener for camera events.
   mListener = new DOMCameraControlListener(this, mInput);
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -1853,54 +1853,41 @@ HTMLMediaElement::CaptureStreamInternal(
     return nullptr;
   }
 #ifdef MOZ_EME
   if (ContainsRestrictedContent()) {
     return nullptr;
   }
 #endif
   OutputMediaStream* out = mOutputStreams.AppendElement();
-  uint8_t hints = 0;
-  if (mReadyState >= nsIDOMHTMLMediaElement::HAVE_METADATA) {
-    hints = (HasAudio()? DOMMediaStream::HINT_CONTENTS_AUDIO : 0) |
-            (HasVideo()? DOMMediaStream::HINT_CONTENTS_VIDEO : 0);
-  } else {
-#ifdef DEBUG
-    // Estimate hints based on the type of the media element
-    // under the preference media.capturestream_hints for the
-    // debug builds only. This allows WebRTC Peer Connection
-    // to behave appropriately when media streams generated
-    // via mozCaptureStream*() are added to the Peer Connection.
-    // This functionality is planned to be used as part of Audio
-    // Quality Performance testing for WebRTC.
-    // Bug932845: Revisit this once hints mechanism is dealt with
-    // holistically.
-    if (Preferences::GetBool("media.capturestream_hints.enabled")) {
-      if (IsVideo() && GetVideoFrameContainer()) {
-        hints = DOMMediaStream::HINT_CONTENTS_VIDEO | DOMMediaStream::HINT_CONTENTS_AUDIO;
-      } else {
-        hints = DOMMediaStream::HINT_CONTENTS_AUDIO;
-      }
-    }
-#endif
-  }
-  out->mStream = DOMMediaStream::CreateTrackUnionStream(window, hints);
+  out->mStream = DOMMediaStream::CreateTrackUnionStream(window);
   nsRefPtr<nsIPrincipal> principal = GetCurrentPrincipal();
   out->mStream->CombineWithPrincipal(principal);
   out->mStream->SetCORSMode(mCORSMode);
   out->mFinishWhenEnded = aFinishWhenEnded;
 
   mAudioCaptured = true;
   // Block the output stream initially.
   // Decoders are responsible for removing the block while they are playing
   // back into the output stream.
   out->mStream->GetStream()->ChangeExplicitBlockerCount(1);
   if (mDecoder) {
     mDecoder->AddOutputStream(
         out->mStream->GetStream()->AsProcessedStream(), aFinishWhenEnded);
+    if (mReadyState >= HAVE_METADATA) {
+      // Expose the tracks to JS directly.
+      if (HasAudio()) {
+        TrackID audioTrackId = mMediaInfo.mAudio.mTrackInfo.mOutputId;
+        out->mStream->CreateDOMTrack(audioTrackId, MediaSegment::AUDIO);
+      }
+      if (HasVideo()) {
+        TrackID videoTrackId = mMediaInfo.mVideo.mTrackInfo.mOutputId;
+        out->mStream->CreateDOMTrack(videoTrackId, MediaSegment::VIDEO);
+      }
+    }
   }
   nsRefPtr<DOMMediaStream> result = out->mStream;
   return result.forget();
 }
 
 already_AddRefed<DOMMediaStream>
 HTMLMediaElement::MozCaptureStream(ErrorResult& aRv)
 {
@@ -2923,19 +2910,18 @@ private:
   Mutex mMutex;
   bool mPendingNotifyOutput;
 };
 
 class HTMLMediaElement::MediaStreamTracksAvailableCallback:
     public DOMMediaStream::OnTracksAvailableCallback
 {
 public:
-  explicit MediaStreamTracksAvailableCallback(HTMLMediaElement* aElement,
-                                              DOMMediaStream::TrackTypeHints aExpectedTracks = 0):
-      DOMMediaStream::OnTracksAvailableCallback(aExpectedTracks),
+  explicit MediaStreamTracksAvailableCallback(HTMLMediaElement* aElement):
+      DOMMediaStream::OnTracksAvailableCallback(),
       mElement(aElement)
     {}
   virtual void NotifyTracksAvailable(DOMMediaStream* aStream)
   {
     NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
 
     mElement->NotifyMediaStreamTracksAvailable(aStream);
   }
@@ -2982,35 +2968,34 @@ void HTMLMediaElement::SetupSrcMediaStre
   GetSrcMediaStream()->AddListener(mSrcStreamListener);
   if (mPaused) {
     GetSrcMediaStream()->ChangeExplicitBlockerCount(1);
   }
   if (mPausedForInactiveDocumentOrChannel) {
     GetSrcMediaStream()->ChangeExplicitBlockerCount(1);
   }
 
-  mSrcStream->OnTracksAvailable(new MediaStreamTracksAvailableCallback(this, DOMMediaStream::HINT_CONTENTS_AUDIO));
-  mSrcStream->OnTracksAvailable(new MediaStreamTracksAvailableCallback(this, DOMMediaStream::HINT_CONTENTS_VIDEO));
-
   ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_IDLE);
 
   ChangeDelayLoadStatus(false);
   GetSrcMediaStream()->AddAudioOutput(this);
   SetVolumeInternal();
   VideoFrameContainer* container = GetVideoFrameContainer();
   if (container) {
     GetSrcMediaStream()->AddVideoOutput(container);
   }
 
   CheckAutoplayDataReady();
 
   // Note: we must call DisconnectTrackListListeners(...)  before dropping
   // mSrcStream
   mSrcStream->ConstructMediaTracks(AudioTracks(), VideoTracks());
 
+  mSrcStream->OnTracksAvailable(new MediaStreamTracksAvailableCallback(this));
+
   // FirstFrameLoaded() will be called when the stream has current data.
 }
 
 void HTMLMediaElement::EndSrcMediaStreamPlayback()
 {
   MediaStream* stream = GetSrcMediaStream();
   if (stream) {
     stream->RemoveListener(mSrcStreamListener);
@@ -3079,22 +3064,26 @@ void HTMLMediaElement::MetadataLoaded(co
     DispatchAsyncEvent(NS_LITERAL_STRING("resize"));
   }
   DispatchAsyncEvent(NS_LITERAL_STRING("loadedmetadata"));
   if (mDecoder && mDecoder->IsTransportSeekable() && mDecoder->IsMediaSeekable()) {
     ProcessMediaFragmentURI();
     mDecoder->SetFragmentEndTime(mFragmentEnd);
   }
 
-  // Tracks just got known, pass the info along to the output streams
-  uint8_t hints = (HasAudio() ? DOMMediaStream::HINT_CONTENTS_AUDIO : 0) |
-                  (HasVideo() ? DOMMediaStream::HINT_CONTENTS_VIDEO : 0);
-  for (uint32_t i = 0; i < mOutputStreams.Length(); ++i) {
-    OutputMediaStream* out = &mOutputStreams[i];
-    out->mStream->SetHintContents(hints);
+  // Expose the tracks to JS directly.
+  for (OutputMediaStream& out : mOutputStreams) {
+    if (aInfo->HasAudio()) {
+      TrackID audioTrackId = aInfo->mAudio.mTrackInfo.mOutputId;
+      out.mStream->CreateDOMTrack(audioTrackId, MediaSegment::AUDIO);
+    }
+    if (aInfo->HasVideo()) {
+      TrackID videoTrackId = aInfo->mVideo.mTrackInfo.mOutputId;
+      out.mStream->CreateDOMTrack(videoTrackId, MediaSegment::VIDEO);
+    }
   }
 
   // If this element had a video track, but consists only of an audio track now,
   // delete the VideoFrameContainer. This happens when the src is changed to an
   // audio only file.
   // Else update its dimensions.
   if (!aInfo->HasVideo()) {
     ResetState();
@@ -4260,18 +4249,17 @@ void HTMLMediaElement::UpdateAudioChanne
     return;
   }
 
   bool playingThroughTheAudioChannel =
      (!mPaused &&
       (HasAttr(kNameSpaceID_None, nsGkAtoms::loop) ||
        (mReadyState >= nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA &&
         !IsPlaybackEnded() &&
-        !(mSrcStream && !(mSrcStream->GetTrackTypesAvailable() &
-                          DOMMediaStream::HINT_CONTENTS_AUDIO))) ||
+        (!mSrcStream || HasAudio())) ||
        mPlayingThroughTheAudioChannelBeforeSeek));
   if (playingThroughTheAudioChannel != mPlayingThroughTheAudioChannel) {
     mPlayingThroughTheAudioChannel = playingThroughTheAudioChannel;
 
     // If we are not playing, we don't need to create a new audioChannelAgent.
     if (!mAudioChannelAgent && !mPlayingThroughTheAudioChannel) {
        return;
     }
--- a/dom/media/DOMMediaStream.cpp
+++ b/dom/media/DOMMediaStream.cpp
@@ -269,56 +269,54 @@ DOMMediaStream::HasTrack(const MediaStre
 
 bool
 DOMMediaStream::IsFinished()
 {
   return !mStream || mStream->IsFinished();
 }
 
 void
-DOMMediaStream::InitSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents)
+DOMMediaStream::InitSourceStream(nsIDOMWindow* aWindow)
 {
   mWindow = aWindow;
-  SetHintContents(aHintContents);
-  MediaStreamGraph* gm = MediaStreamGraph::GetInstance(aHintContents);
+  MediaStreamGraph* gm = MediaStreamGraph::GetInstance();
   InitStreamCommon(gm->CreateSourceStream(this));
 }
 
 void
-DOMMediaStream::InitTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents)
+DOMMediaStream::InitTrackUnionStream(nsIDOMWindow* aWindow)
 {
   mWindow = aWindow;
-  SetHintContents(aHintContents);
-  MediaStreamGraph* gm = MediaStreamGraph::GetInstance(aHintContents);
+  MediaStreamGraph* gm = MediaStreamGraph::GetInstance();
   InitStreamCommon(gm->CreateTrackUnionStream(this));
 }
 
 void
 DOMMediaStream::InitStreamCommon(MediaStream* aStream)
 {
   mStream = aStream;
 
   // Setup track listener
   mListener = new StreamListener(this);
   aStream->AddListener(mListener);
 }
 
 already_AddRefed<DOMMediaStream>
-DOMMediaStream::CreateSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents)
+DOMMediaStream::CreateSourceStream(nsIDOMWindow* aWindow)
 {
   nsRefPtr<DOMMediaStream> stream = new DOMMediaStream();
-  stream->InitSourceStream(aWindow, aHintContents);
+  stream->InitSourceStream(aWindow);
   return stream.forget();
 }
 
 already_AddRefed<DOMMediaStream>
-DOMMediaStream::CreateTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents)
+DOMMediaStream::CreateTrackUnionStream(nsIDOMWindow* aWindow)
 {
   nsRefPtr<DOMMediaStream> stream = new DOMMediaStream();
-  stream->InitTrackUnionStream(aWindow, aHintContents);
+  stream->InitTrackUnionStream(aWindow);
   return stream.forget();
 }
 
 void
 DOMMediaStream::SetTrackEnabled(TrackID aTrackID, bool aEnabled)
 {
   if (mStream) {
     mStream->SetTrackEnabled(aTrackID, aEnabled);
@@ -381,33 +379,25 @@ DOMMediaStream::AddPrincipalChangeObserv
 }
 
 bool
 DOMMediaStream::RemovePrincipalChangeObserver(PrincipalChangeObserver* aObserver)
 {
   return mPrincipalChangeObservers.RemoveElement(aObserver);
 }
 
-void
-DOMMediaStream::SetHintContents(TrackTypeHints aHintContents)
-{
-  mHintContents |= aHintContents;
-}
-
 MediaStreamTrack*
 DOMMediaStream::CreateDOMTrack(TrackID aTrackID, MediaSegment::Type aType)
 {
   MediaStreamTrack* track;
   switch (aType) {
   case MediaSegment::AUDIO:
-    mHintContents |= HINT_CONTENTS_AUDIO;
     track = new AudioStreamTrack(this, aTrackID);
     break;
   case MediaSegment::VIDEO:
-    mHintContents |= HINT_CONTENTS_VIDEO;
     track = new VideoStreamTrack(this, aTrackID);
     break;
   default:
     MOZ_CRASH("Unhandled track type");
   }
   mTracks.AppendElement(track);
 
   return track;
@@ -419,39 +409,34 @@ DOMMediaStream::BindDOMTrack(TrackID aTr
   MediaStreamTrack* track = nullptr;
   bool bindSuccess = false;
   switch (aType) {
   case MediaSegment::AUDIO: {
     for (size_t i = 0; i < mTracks.Length(); ++i) {
       track = mTracks[i]->AsAudioStreamTrack();
       if (track && track->GetTrackID() == aTrackID) {
         bindSuccess = true;
-        mTrackTypesAvailable |= HINT_CONTENTS_AUDIO;
         break;
       }
     }
     break;
   }
   case MediaSegment::VIDEO: {
     for (size_t i = 0; i < mTracks.Length(); ++i) {
       track = mTracks[i]->AsVideoStreamTrack();
       if (track && track->GetTrackID() == aTrackID) {
         bindSuccess = true;
-        mTrackTypesAvailable |= HINT_CONTENTS_VIDEO;
         break;
       }
     }
     break;
   }
   default:
     MOZ_CRASH("Unhandled track type");
   }
-  if (bindSuccess) {
-    CheckTracksAvailable();
-  }
   return bindSuccess ? track : nullptr;
 }
 
 MediaStreamTrack*
 DOMMediaStream::GetDOMTrackFor(TrackID aTrackID)
 {
   for (uint32_t i = 0; i < mTracks.Length(); ++i) {
     MediaStreamTrack* t = mTracks[i];
@@ -508,23 +493,17 @@ DOMMediaStream::CheckTracksAvailable()
 {
   if (!mTracksCreated) {
     return;
   }
   nsTArray<nsAutoPtr<OnTracksAvailableCallback> > callbacks;
   callbacks.SwapElements(mRunOnTracksAvailable);
 
   for (uint32_t i = 0; i < callbacks.Length(); ++i) {
-    OnTracksAvailableCallback* cb = callbacks[i];
-    if (~mTrackTypesAvailable & cb->GetExpectedTracks()) {
-      // Some expected tracks not available yet. Try this callback again later.
-      *mRunOnTracksAvailable.AppendElement() = callbacks[i].forget();
-      continue;
-    }
-    cb->NotifyTracksAvailable(this);
+    callbacks[i]->NotifyTracksAvailable(this);
   }
 }
 
 already_AddRefed<AudioTrack>
 DOMMediaStream::CreateAudioTrack(AudioStreamTrack* aStreamTrack)
 {
   nsAutoString id;
   nsAutoString label;
@@ -547,24 +526,20 @@ DOMMediaStream::CreateVideoTrack(VideoSt
   return MediaTrackList::CreateVideoTrack(id, NS_LITERAL_STRING("main"),
                                           label, EmptyString());
 }
 
 void
 DOMMediaStream::ConstructMediaTracks(AudioTrackList* aAudioTrackList,
                                      VideoTrackList* aVideoTrackList)
 {
-  if (mHintContents & DOMMediaStream::HINT_CONTENTS_AUDIO) {
-    MediaTrackListListener listener(aAudioTrackList);
-    mMediaTrackListListeners.AppendElement(listener);
-  }
-  if (mHintContents & DOMMediaStream::HINT_CONTENTS_VIDEO) {
-    MediaTrackListListener listener(aVideoTrackList);
-    mMediaTrackListListeners.AppendElement(listener);
-  }
+  MediaTrackListListener audioListener(aAudioTrackList);
+  mMediaTrackListListeners.AppendElement(audioListener);
+  MediaTrackListListener videoListener(aVideoTrackList);
+  mMediaTrackListListeners.AppendElement(videoListener);
 
   int firstEnabledVideo = -1;
   for (uint32_t i = 0; i < mTracks.Length(); ++i) {
     if (AudioStreamTrack* t = mTracks[i]->AsAudioStreamTrack()) {
       nsRefPtr<AudioTrack> track = CreateAudioTrack(t);
       aAudioTrackList->AddTrack(track);
     } else if (VideoStreamTrack* t = mTracks[i]->AsVideoStreamTrack()) {
       nsRefPtr<VideoTrack> track = CreateVideoTrack(t);
@@ -643,43 +618,40 @@ void
 DOMLocalMediaStream::Stop()
 {
   if (mStream && mStream->AsSourceStream()) {
     mStream->AsSourceStream()->EndAllTrackAndFinish();
   }
 }
 
 already_AddRefed<DOMLocalMediaStream>
-DOMLocalMediaStream::CreateSourceStream(nsIDOMWindow* aWindow,
-                                        TrackTypeHints aHintContents)
+DOMLocalMediaStream::CreateSourceStream(nsIDOMWindow* aWindow)
 {
   nsRefPtr<DOMLocalMediaStream> stream = new DOMLocalMediaStream();
-  stream->InitSourceStream(aWindow, aHintContents);
+  stream->InitSourceStream(aWindow);
   return stream.forget();
 }
 
 already_AddRefed<DOMLocalMediaStream>
-DOMLocalMediaStream::CreateTrackUnionStream(nsIDOMWindow* aWindow,
-                                            TrackTypeHints aHintContents)
+DOMLocalMediaStream::CreateTrackUnionStream(nsIDOMWindow* aWindow)
 {
   nsRefPtr<DOMLocalMediaStream> stream = new DOMLocalMediaStream();
-  stream->InitTrackUnionStream(aWindow, aHintContents);
+  stream->InitTrackUnionStream(aWindow);
   return stream.forget();
 }
 
 DOMAudioNodeMediaStream::DOMAudioNodeMediaStream(AudioNode* aNode)
 : mStreamNode(aNode)
 {
 }
 
 DOMAudioNodeMediaStream::~DOMAudioNodeMediaStream()
 {
 }
 
 already_AddRefed<DOMAudioNodeMediaStream>
 DOMAudioNodeMediaStream::CreateTrackUnionStream(nsIDOMWindow* aWindow,
-                                                AudioNode* aNode,
-                                                TrackTypeHints aHintContents)
+                                                AudioNode* aNode)
 {
   nsRefPtr<DOMAudioNodeMediaStream> stream = new DOMAudioNodeMediaStream(aNode);
-  stream->InitTrackUnionStream(aWindow, aHintContents);
+  stream->InitTrackUnionStream(aWindow);
   return stream.forget();
 }
--- a/dom/media/DOMMediaStream.h
+++ b/dom/media/DOMMediaStream.h
@@ -172,60 +172,43 @@ public:
    * Called when the main-thread state of the MediaStream changed.
    */
   void NotifyStreamStateChanged();
 
   // Webrtc allows the remote side to name a stream whatever it wants, and we
   // need to surface this to content.
   void AssignId(const nsAString& aID) { mID = aID; }
 
-  // Indicate what track types we eventually expect to add to this stream
-  enum {
-    HINT_CONTENTS_AUDIO = 1 << 0,
-    HINT_CONTENTS_VIDEO = 1 << 1,
-    HINT_CONTENTS_UNKNOWN = 1 << 2
-  };
-  TrackTypeHints GetHintContents() const { return mHintContents; }
-  void SetHintContents(TrackTypeHints aHintContents);
-
-  TrackTypeHints GetTrackTypesAvailable() const { return mTrackTypesAvailable; }
-
   /**
    * Create an nsDOMMediaStream whose underlying stream is a SourceMediaStream.
    */
   static already_AddRefed<DOMMediaStream>
-  CreateSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents);
+  CreateSourceStream(nsIDOMWindow* aWindow);
 
   /**
    * Create an nsDOMMediaStream whose underlying stream is a TrackUnionStream.
    */
   static already_AddRefed<DOMMediaStream>
-  CreateTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents = 0);
+  CreateTrackUnionStream(nsIDOMWindow* aWindow);
 
   void SetLogicalStreamStartTime(StreamTime aTime)
   {
     mLogicalStreamStartTime = aTime;
   }
 
   // Notifications from StreamListener.
   // BindDOMTrack should only be called when it's safe to run script.
   MediaStreamTrack* BindDOMTrack(TrackID aTrackID, MediaSegment::Type aType);
   MediaStreamTrack* CreateDOMTrack(TrackID aTrackID, MediaSegment::Type aType);
   MediaStreamTrack* GetDOMTrackFor(TrackID aTrackID);
 
   class OnTracksAvailableCallback {
   public:
-    explicit OnTracksAvailableCallback(uint8_t aExpectedTracks = 0)
-      : mExpectedTracks(aExpectedTracks) {}
     virtual ~OnTracksAvailableCallback() {}
     virtual void NotifyTracksAvailable(DOMMediaStream* aStream) = 0;
-    TrackTypeHints GetExpectedTracks() { return mExpectedTracks; }
-    void SetExpectedTracks(TrackTypeHints aExpectedTracks) { mExpectedTracks = aExpectedTracks; }
-  private:
-    TrackTypeHints mExpectedTracks;
   };
   // When one track of the appropriate type has been added for each bit set
   // in aCallback->GetExpectedTracks(), run aCallback->NotifyTracksAvailable.
   // It is allowed to do anything, including run script.
   // aCallback may run immediately during this call if tracks are already
   // available!
   // We only care about track additions, we'll fire the notification even if
   // some of the tracks have been removed.
@@ -261,18 +244,18 @@ public:
   virtual void NotifyMediaStreamTrackCreated(MediaStreamTrack* aTrack);
 
   virtual void NotifyMediaStreamTrackEnded(MediaStreamTrack* aTrack);
 
 protected:
   virtual ~DOMMediaStream();
 
   void Destroy();
-  void InitSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents);
-  void InitTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents);
+  void InitSourceStream(nsIDOMWindow* aWindow);
+  void InitTrackUnionStream(nsIDOMWindow* aWindow);
   void InitStreamCommon(MediaStream* aStream);
   already_AddRefed<AudioTrack> CreateAudioTrack(AudioStreamTrack* aStreamTrack);
   already_AddRefed<VideoTrack> CreateVideoTrack(VideoStreamTrack* aStreamTrack);
 
   // Called when MediaStreamGraph has finished an iteration where tracks were
   // created.
   void TracksCreated();
 
@@ -299,20 +282,16 @@ protected:
   // Set to true after MediaStreamGraph has created tracks for mStream.
   bool mTracksCreated;
 
   nsString mID;
 
   // Keep these alive until the stream finishes
   nsTArray<nsCOMPtr<nsISupports> > mConsumersToKeepAlive;
 
-  // Indicate what track types we eventually expect to add to this stream
-  uint8_t mHintContents;
-  // Indicate what track types have arrived in this stream
-  uint8_t mTrackTypesAvailable;
   bool mNotifiedOfMediaStreamGraphShutdown;
 
   // Send notifications to AudioTrackList or VideoTrackList, if this MediaStream
   // is consumed by a HTMLMediaElement.
   nsTArray<MediaTrackListListener> mMediaTrackListListeners;
 
 private:
   void NotifyPrincipalChanged();
@@ -347,23 +326,23 @@ public:
   virtual void Stop();
 
   virtual MediaEngineSource* GetMediaEngine(TrackID aTrackID) { return nullptr; }
 
   /**
    * Create an nsDOMLocalMediaStream whose underlying stream is a SourceMediaStream.
    */
   static already_AddRefed<DOMLocalMediaStream>
-  CreateSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents);
+  CreateSourceStream(nsIDOMWindow* aWindow);
 
   /**
    * Create an nsDOMLocalMediaStream whose underlying stream is a TrackUnionStream.
    */
   static already_AddRefed<DOMLocalMediaStream>
-  CreateTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents = 0);
+  CreateTrackUnionStream(nsIDOMWindow* aWindow);
 
 protected:
   virtual ~DOMLocalMediaStream();
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(DOMLocalMediaStream,
                               NS_DOMLOCALMEDIASTREAM_IID)
 
@@ -376,18 +355,17 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DOMAudioNodeMediaStream, DOMMediaStream)
 
   /**
    * Create a DOMAudioNodeMediaStream whose underlying stream is a TrackUnionStream.
    */
   static already_AddRefed<DOMAudioNodeMediaStream>
   CreateTrackUnionStream(nsIDOMWindow* aWindow,
-                         AudioNode* aNode,
-                         TrackTypeHints aHintContents = 0);
+                         AudioNode* aNode);
 
 protected:
   ~DOMAudioNodeMediaStream();
 
 private:
   // If this object wraps a stream owned by an AudioNode, we need to ensure that
   // the node isn't cycle-collected too early.
   nsRefPtr<AudioNode> mStreamNode;
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -562,24 +562,20 @@ class nsDOMUserMediaStream : public DOML
 {
 public:
   static already_AddRefed<nsDOMUserMediaStream>
   CreateTrackUnionStream(nsIDOMWindow* aWindow,
                          GetUserMediaCallbackMediaStreamListener* aListener,
                          MediaEngineSource* aAudioSource,
                          MediaEngineSource* aVideoSource)
   {
-    DOMMediaStream::TrackTypeHints hints =
-      (aAudioSource ? DOMMediaStream::HINT_CONTENTS_AUDIO : 0) |
-      (aVideoSource ? DOMMediaStream::HINT_CONTENTS_VIDEO : 0);
-
     nsRefPtr<nsDOMUserMediaStream> stream = new nsDOMUserMediaStream(aListener,
                                                                      aAudioSource,
                                                                      aVideoSource);
-    stream->InitTrackUnionStream(aWindow, hints);
+    stream->InitTrackUnionStream(aWindow);
     return stream.forget();
   }
 
   nsDOMUserMediaStream(GetUserMediaCallbackMediaStreamListener* aListener,
                        MediaEngineSource *aAudioSource,
                        MediaEngineSource *aVideoSource) :
     mListener(aListener),
     mAudioSource(aAudioSource),
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -388,40 +388,33 @@ public:
       return;
 
     switch (mType) {
       case MEDIA_START:
         {
           NS_ASSERTION(!NS_IsMainThread(), "Never call on main thread");
           nsresult rv;
 
-          DOMMediaStream::TrackTypeHints expectedTracks = 0;
           if (mAudioSource) {
             rv = mAudioSource->Start(source, kAudioTrack);
-            if (NS_SUCCEEDED(rv)) {
-              expectedTracks |= DOMMediaStream::HINT_CONTENTS_AUDIO;
-            } else {
+            if (NS_FAILED(rv)) {
               ReturnCallbackError(rv, "Starting audio failed");
               return;
             }
           }
           if (mVideoSource) {
             rv = mVideoSource->Start(source, kVideoTrack);
-            if (NS_SUCCEEDED(rv)) {
-              expectedTracks |= DOMMediaStream::HINT_CONTENTS_VIDEO;
-            } else {
+            if (NS_FAILED(rv)) {
               ReturnCallbackError(rv, "Starting video failed");
               return;
             }
           }
           // Start() queued the tracks to be added synchronously to avoid races
           source->FinishAddTracks();
 
-          mOnTracksAvailableCallback->SetExpectedTracks(expectedTracks);
-
           source->SetPullEnabled(true);
           source->AdvanceKnownTracksTime(STREAM_TIME_MAX);
 
           MM_LOG(("started all sources"));
           // Forward mOnTracksAvailableCallback to GetUserMediaNotificationEvent,
           // because mOnTracksAvailableCallback needs to be added to mStream
           // on the main thread.
           nsIRunnable *event =
--- a/dom/media/MediaRecorder.cpp
+++ b/dom/media/MediaRecorder.cpp
@@ -290,33 +290,31 @@ class MediaRecorder::Session: public nsI
   // For Ensure recorder has tracks to record.
   class TracksAvailableCallback : public DOMMediaStream::OnTracksAvailableCallback
   {
   public:
     explicit TracksAvailableCallback(Session *aSession)
      : mSession(aSession) {}
     virtual void NotifyTracksAvailable(DOMMediaStream* aStream)
     {
-      uint8_t trackType = aStream->GetHintContents();
-      // ToDo: GetHintContents return 0 when recording media tags.
-      if (trackType == 0) {
-        nsTArray<nsRefPtr<mozilla::dom::AudioStreamTrack> > audioTracks;
-        aStream->GetAudioTracks(audioTracks);
-        nsTArray<nsRefPtr<mozilla::dom::VideoStreamTrack> > videoTracks;
-        aStream->GetVideoTracks(videoTracks);
-        // What is inside the track
-        if (videoTracks.Length() > 0) {
-          trackType |= DOMMediaStream::HINT_CONTENTS_VIDEO;
-        }
-        if (audioTracks.Length() > 0) {
-          trackType |= DOMMediaStream::HINT_CONTENTS_AUDIO;
-        }
+      uint8_t trackTypes = 0;
+      nsTArray<nsRefPtr<mozilla::dom::AudioStreamTrack>> audioTracks;
+      aStream->GetAudioTracks(audioTracks);
+      if (!audioTracks.IsEmpty()) {
+        trackTypes |= ContainerWriter::CREATE_AUDIO_TRACK;
       }
-      LOG(PR_LOG_DEBUG, ("Session.NotifyTracksAvailable track type = (%d)", trackType));
-      mSession->InitEncoder(trackType);
+
+      nsTArray<nsRefPtr<mozilla::dom::VideoStreamTrack>> videoTracks;
+      aStream->GetVideoTracks(videoTracks);
+      if (!videoTracks.IsEmpty()) {
+        trackTypes |= ContainerWriter::CREATE_VIDEO_TRACK;
+      }
+
+      LOG(PR_LOG_DEBUG, ("Session.NotifyTracksAvailable track type = (%d)", trackTypes));
+      mSession->InitEncoder(trackTypes);
     }
   private:
     nsRefPtr<Session> mSession;
   };
   // Main thread task.
   // To delete RecordingSession object.
   class DestroyRunnable : public nsRunnable
   {
@@ -537,17 +535,17 @@ private:
 
     DOMMediaStream* domStream = mRecorder->Stream();
     if (domStream) {
       // Get the track type hint from DOM media stream.
       TracksAvailableCallback* tracksAvailableCallback = new TracksAvailableCallback(this);
       domStream->OnTracksAvailable(tracksAvailableCallback);
     } else {
       // Web Audio node has only audio.
-      InitEncoder(DOMMediaStream::HINT_CONTENTS_AUDIO);
+      InitEncoder(ContainerWriter::CREATE_AUDIO_TRACK);
     }
   }
 
   bool Check3gppPermission()
   {
     nsCOMPtr<nsIDocument> doc = mRecorder->GetOwner()->GetExtantDoc();
     if (!doc) {
       return false;
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -2732,17 +2732,17 @@ ProcessedMediaStream::DestroyImpl()
   // The stream order is only important if there are connections, in which
   // case MediaInputPort::Disconnect() called SetStreamOrderDirty().
   // MediaStreamGraphImpl::RemoveStream() will also call
   // SetStreamOrderDirty(), for other reasons.
 }
 
 MediaStreamGraphImpl::MediaStreamGraphImpl(bool aRealtime,
                                            TrackRate aSampleRate,
-                                           DOMMediaStream::TrackTypeHints aHint= DOMMediaStream::HINT_CONTENTS_UNKNOWN,
+                                           bool aStartWithAudioDriver,
                                            dom::AudioChannel aChannel)
   : MediaStreamGraph(aSampleRate)
   , mProcessingGraphUpdateIndex(0)
   , mPortCount(0)
   , mNeedAnotherIteration(false)
   , mGraphDriverAsleep(false)
   , mMonitor("MediaStreamGraphImpl")
   , mLifecycleState(LIFECYCLE_THREAD_NOT_STARTED)
@@ -2771,25 +2771,25 @@ MediaStreamGraphImpl::MediaStreamGraphIm
 {
 #ifdef PR_LOGGING
   if (!gMediaStreamGraphLog) {
     gMediaStreamGraphLog = PR_NewLogModule("MediaStreamGraph");
   }
 #endif
 
   if (mRealtime) {
-    if (aHint & DOMMediaStream::HINT_CONTENTS_AUDIO) {
+    if (aStartWithAudioDriver) {
       AudioCallbackDriver* driver = new AudioCallbackDriver(this, aChannel);
       mDriver = driver;
       mMixer.AddCallback(driver);
     } else {
       mDriver = new SystemClockDriver(this);
     }
   } else {
-     mDriver = new OfflineClockDriver(this, MEDIA_GRAPH_TARGET_PERIOD_MS);
+    mDriver = new OfflineClockDriver(this, MEDIA_GRAPH_TARGET_PERIOD_MS);
   }
 
   mLastMainThreadUpdate = TimeStamp::Now();
 
   RegisterWeakMemoryReporter(this);
 }
 
 void
@@ -2828,32 +2828,33 @@ MediaStreamGraphShutdownObserver::Observ
     gGraphs.EnumerateRead(ForceShutdownEnumerator, nullptr);
     nsContentUtils::UnregisterShutdownObserver(this);
     gShutdownObserverRegistered = false;
   }
   return NS_OK;
 }
 
 MediaStreamGraph*
-MediaStreamGraph::GetInstance(DOMMediaStream::TrackTypeHints aHint, dom::AudioChannel aChannel)
+MediaStreamGraph::GetInstance(bool aStartWithAudioDriver,
+                              dom::AudioChannel aChannel)
 {
   NS_ASSERTION(NS_IsMainThread(), "Main thread only");
 
   uint32_t channel = static_cast<uint32_t>(aChannel);
   MediaStreamGraphImpl* graph = nullptr;
 
   if (!gGraphs.Get(channel, &graph)) {
     if (!gShutdownObserverRegistered) {
       gShutdownObserverRegistered = true;
       nsContentUtils::RegisterShutdownObserver(new MediaStreamGraphShutdownObserver());
     }
 
     CubebUtils::InitPreferredSampleRate();
 
-    graph = new MediaStreamGraphImpl(true, CubebUtils::PreferredSampleRate(), aHint, aChannel);
+    graph = new MediaStreamGraphImpl(true, CubebUtils::PreferredSampleRate(), aStartWithAudioDriver, aChannel);
     gGraphs.Put(channel, graph);
 
     STREAM_LOG(PR_LOG_DEBUG, ("Starting up MediaStreamGraph %p", graph));
   }
 
   return graph;
 }
 
--- a/dom/media/MediaStreamGraph.h
+++ b/dom/media/MediaStreamGraph.h
@@ -1176,17 +1176,17 @@ class MediaStreamGraph {
 public:
   // We ensure that the graph current time advances in multiples of
   // IdealAudioBlockSize()/AudioStream::PreferredSampleRate(). A stream that
   // never blocks and has a track with the ideal audio rate will produce audio
   // in multiples of the block size.
   //
 
   // Main thread only
-  static MediaStreamGraph* GetInstance(DOMMediaStream::TrackTypeHints aHint = DOMMediaStream::HINT_CONTENTS_UNKNOWN,
+  static MediaStreamGraph* GetInstance(bool aStartWithAudioDriver = false,
                                        dom::AudioChannel aChannel = dom::AudioChannel::Normal);
   static MediaStreamGraph* CreateNonRealtimeInstance(TrackRate aSampleRate);
   // Idempotent
   static void DestroyNonRealtimeInstance(MediaStreamGraph* aGraph);
 
   // Control API.
   /**
    * Create a stream that a media decoder (or some other source of
--- a/dom/media/MediaStreamGraphImpl.h
+++ b/dom/media/MediaStreamGraphImpl.h
@@ -94,17 +94,17 @@ public:
    * Set aRealtime to true in order to create a MediaStreamGraph which provides
    * support for real-time audio and video.  Set it to false in order to create
    * a non-realtime instance which just churns through its inputs and produces
    * output.  Those objects currently only support audio, and are used to
    * implement OfflineAudioContext.  They do not support MediaStream inputs.
    */
   explicit MediaStreamGraphImpl(bool aRealtime,
                                 TrackRate aSampleRate,
-                                DOMMediaStream::TrackTypeHints aHint,
+                                bool aStartWithAudioDriver = false,
                                 dom::AudioChannel aChannel = dom::AudioChannel::Normal);
 
   /**
    * Unregisters memory reporting and deletes this instance. This should be
    * called instead of calling the destructor directly.
    */
   void Destroy();
 
--- a/dom/media/webaudio/AudioDestinationNode.cpp
+++ b/dom/media/webaudio/AudioDestinationNode.cpp
@@ -349,19 +349,20 @@ AudioDestinationNode::AudioDestinationNo
   , mAudioChannel(AudioChannel::Normal)
   , mIsOffline(aIsOffline)
   , mHasFinished(false)
   , mAudioChannelAgentPlaying(false)
   , mExtraCurrentTime(0)
   , mExtraCurrentTimeSinceLastStartedBlocking(0)
   , mExtraCurrentTimeUpdatedSinceLastStableState(false)
 {
+  bool startWithAudioDriver = true;
   MediaStreamGraph* graph = aIsOffline ?
                             MediaStreamGraph::CreateNonRealtimeInstance(aSampleRate) :
-                            MediaStreamGraph::GetInstance(DOMMediaStream::HINT_CONTENTS_AUDIO, aChannel);
+                            MediaStreamGraph::GetInstance(startWithAudioDriver, aChannel);
   AudioNodeEngine* engine = aIsOffline ?
                             new OfflineDestinationNodeEngine(this, aNumberOfChannels,
                                                              aLength, aSampleRate) :
                             static_cast<AudioNodeEngine*>(new DestinationNodeEngine(this));
 
   mStream = graph->CreateAudioNodeStream(engine, MediaStreamGraph::EXTERNAL_STREAM);
   mStream->AddMainThreadListener(this);
   mStream->AddAudioOutput(&gWebAudioOutputKey);
--- a/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp
+++ b/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp
@@ -63,18 +63,17 @@ static bool FilterAudioNodeStreamTrack(S
 }
 
 MediaStreamAudioDestinationNode::MediaStreamAudioDestinationNode(AudioContext* aContext)
   : AudioNode(aContext,
               2,
               ChannelCountMode::Explicit,
               ChannelInterpretation::Speakers)
   , mDOMStream(DOMAudioNodeMediaStream::CreateTrackUnionStream(GetOwner(),
-                                                               this,
-                                                               DOMMediaStream::HINT_CONTENTS_AUDIO))
+                                                               this))
 {
   TrackUnionStream* tus = static_cast<TrackUnionStream*>(mDOMStream->GetStream());
   MOZ_ASSERT(tus == mDOMStream->GetStream()->AsProcessedStream());
   tus->SetTrackIDFilter(FilterAudioNodeStreamTrack);
 
   MediaStreamDestinationEngine* engine = new MediaStreamDestinationEngine(this, tus);
   mStream = aContext->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::INTERNAL_STREAM);
   mPort = tus->AllocateInputPort(mStream, 0);
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -177,20 +177,17 @@ private:
 #ifdef MOZILLA_INTERNAL_API
 class TracksAvailableCallback : public DOMMediaStream::OnTracksAvailableCallback
 {
 public:
   TracksAvailableCallback(size_t numNewAudioTracks,
                           size_t numNewVideoTracks,
                           const std::string& pcHandle,
                           nsRefPtr<PeerConnectionObserver> aObserver)
-  : DOMMediaStream::OnTracksAvailableCallback(
-      // Once DOMMediaStream can handle more than one of each, this will change.
-      (numNewAudioTracks ? DOMMediaStream::HINT_CONTENTS_AUDIO : 0) |
-      (numNewVideoTracks ? DOMMediaStream::HINT_CONTENTS_VIDEO : 0))
+  : DOMMediaStream::OnTracksAvailableCallback()
   , mObserver(aObserver)
   , mPcHandle(pcHandle)
   {}
 
   virtual void NotifyTracksAvailable(DOMMediaStream* aStream) MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
 
@@ -445,20 +442,20 @@ PeerConnectionImpl::~PeerConnectionImpl(
 
   // Right now, we delete PeerConnectionCtx at XPCOM shutdown only, but we
   // probably want to shut it down more aggressively to save memory.  We
   // could shut down here when there are no uses.  It might be more optimal
   // to release off a timer (and XPCOM Shutdown) to avoid churn
 }
 
 already_AddRefed<DOMMediaStream>
-PeerConnectionImpl::MakeMediaStream(uint32_t aHint)
+PeerConnectionImpl::MakeMediaStream()
 {
   nsRefPtr<DOMMediaStream> stream =
-    DOMMediaStream::CreateSourceStream(GetWindow(), aHint);
+    DOMMediaStream::CreateSourceStream(GetWindow());
 
 #ifdef MOZILLA_INTERNAL_API
   // Make the stream data (audio/video samples) accessible to the receiving page.
   // We're only certain that privacy hasn't been requested if we're connected.
   if (mDtlsConnected && !PrivacyRequested()) {
     nsIDocument* doc = GetWindow()->GetExtantDoc();
     if (!doc) {
       return nullptr;
@@ -481,21 +478,17 @@ PeerConnectionImpl::MakeMediaStream(uint
 nsresult
 PeerConnectionImpl::CreateRemoteSourceStreamInfo(nsRefPtr<RemoteSourceStreamInfo>*
                                                  aInfo,
                                                  const std::string& aStreamID)
 {
   MOZ_ASSERT(aInfo);
   PC_AUTO_ENTER_API_CALL_NO_CHECK();
 
-  // We need to pass a dummy hint here because FakeMediaStream currently
-  // needs to actually propagate a hint for local streams.
-  // TODO(ekr@rtfm.com): Clean up when we have explicit track lists.
-  // See bug 834835.
-  nsRefPtr<DOMMediaStream> stream = MakeMediaStream(0);
+  nsRefPtr<DOMMediaStream> stream = MakeMediaStream();
   if (!stream) {
     return NS_ERROR_FAILURE;
   }
 
   nsRefPtr<RemoteSourceStreamInfo> remote;
   remote = new RemoteSourceStreamInfo(stream.forget(), mMedia, aStreamID);
   *aInfo = remote;
 
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
@@ -259,17 +259,17 @@ public:
 
   static already_AddRefed<PeerConnectionImpl>
       Constructor(const mozilla::dom::GlobalObject& aGlobal, ErrorResult& rv);
   static PeerConnectionImpl* CreatePeerConnection();
   static nsresult ConvertRTCConfiguration(const RTCConfiguration& aSrc,
                                           IceConfiguration *aDst);
   static nsresult AddIceServer(const RTCIceServer& aServer,
                                IceConfiguration* aDst);
-  already_AddRefed<DOMMediaStream> MakeMediaStream(uint32_t aHint);
+  already_AddRefed<DOMMediaStream> MakeMediaStream();
 
   nsresult CreateRemoteSourceStreamInfo(nsRefPtr<RemoteSourceStreamInfo>* aInfo,
                                         const std::string& aId);
 
   // DataConnection observers
   void NotifyDataChannel(already_AddRefed<mozilla::DataChannel> aChannel)
 #ifdef MOZILLA_INTERNAL_API
     // PeerConnectionImpl only inherits from mozilla::DataChannelConnection
--- a/media/webrtc/signaling/test/FakeMediaStreams.h
+++ b/media/webrtc/signaling/test/FakeMediaStreams.h
@@ -275,17 +275,17 @@ public:
       std::ostringstream os;
       os << counter++;
       mID = os.str();
     }
 
   NS_DECL_THREADSAFE_ISUPPORTS
 
   static already_AddRefed<Fake_DOMMediaStream>
-  CreateSourceStream(nsIDOMWindow* aWindow, uint32_t aHintContents) {
+  CreateSourceStream(nsIDOMWindow* aWindow, uint32_t aHintContents = 0) {
     Fake_SourceMediaStream *source = new Fake_SourceMediaStream();
 
     nsRefPtr<Fake_DOMMediaStream> ds = new Fake_DOMMediaStream(source);
     ds->SetHintContents(aHintContents);
 
     return ds.forget();
   }