Bug 1259788 - Multi-track support for MediaTrackList. r?jesup draft
authorAndreas Pehrson <pehrsons@gmail.com>
Wed, 24 Aug 2016 10:58:04 +0200
changeset 404922 61b807c526b0cb5dd2be33fc6a809c00212741d9
parent 404498 52319b2a47758038ebc98b41fa2bc7ca870ed44e
child 404923 5e2b512bb84a12c2a6895538b564b5e86f8cb893
push id27359
push userpehrsons@gmail.com
push dateWed, 24 Aug 2016 14:53:56 +0000
reviewersjesup
bugs1259788
milestone51.0a1
Bug 1259788 - Multi-track support for MediaTrackList. r?jesup MozReview-Commit-ID: 1av5uvyCMYv
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
dom/media/AudioTrack.cpp
dom/media/MediaTrack.cpp
dom/media/MediaTrackList.cpp
dom/media/VideoTrack.cpp
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -1234,36 +1234,71 @@ void HTMLMediaElement::NotifyLoadError()
     QueueLoadFromSourceTask();
   } else {
     NS_WARNING("Should know the source we were loading from!");
   }
 }
 
 void HTMLMediaElement::NotifyMediaTrackEnabled(MediaTrack* aTrack)
 {
+  MOZ_ASSERT(aTrack);
   if (!aTrack) {
     return;
   }
 #ifdef DEBUG
   nsString id;
   aTrack->GetId(id);
 
-  LOG(LogLevel::Debug, ("MediaElement %p MediaStreamTrack enabled with id %s",
+  LOG(LogLevel::Debug, ("MediaElement %p MediaTrack with id %s enabled",
                         this, NS_ConvertUTF16toUTF8(id).get()));
 #endif
 
-  // TODO: We are dealing with single audio track and video track for now.
-  if (AudioTrack* track = aTrack->AsAudioTrack()) {
-    if (!track->Enabled()) {
+  MOZ_ASSERT((aTrack->AsAudioTrack() && aTrack->AsAudioTrack()->Enabled()) ||
+             (aTrack->AsVideoTrack() && aTrack->AsVideoTrack()->Selected()));
+
+  if (aTrack->AsAudioTrack()) {
+    SetMutedInternal(mMuted & ~MUTED_BY_AUDIO_TRACK);
+  } else if (aTrack->AsVideoTrack()) {
+    mDisableVideo = false;
+  }
+}
+
+void HTMLMediaElement::NotifyMediaTrackDisabled(MediaTrack* aTrack)
+{
+  MOZ_ASSERT(aTrack);
+  if (!aTrack) {
+    return;
+  }
+#ifdef DEBUG
+  nsString id;
+  aTrack->GetId(id);
+
+  LOG(LogLevel::Debug, ("MediaElement %p MediaTrack with id %s disabled",
+                        this, NS_ConvertUTF16toUTF8(id).get()));
+#endif
+
+  MOZ_ASSERT((!aTrack->AsAudioTrack() || !aTrack->AsAudioTrack()->Enabled()) &&
+             (!aTrack->AsVideoTrack() || !aTrack->AsVideoTrack()->Selected()));
+
+
+  if (aTrack->AsAudioTrack()) {
+    bool shouldMute = true;
+    for (uint32_t i = 0; i < AudioTracks()->Length(); ++i) {
+      if ((*AudioTracks())[i]->Enabled()) {
+        shouldMute = false;
+        break;
+      }
+    }
+    if (shouldMute) {
       SetMutedInternal(mMuted | MUTED_BY_AUDIO_TRACK);
-    } else {
-      SetMutedInternal(mMuted & ~MUTED_BY_AUDIO_TRACK);
     }
-  } else if (VideoTrack* track = aTrack->AsVideoTrack()) {
-    mDisableVideo = !track->Selected();
+  } else if (aTrack->AsVideoTrack()) {
+    if (VideoTracks()->SelectedIndex() == -1) {
+      mDisableVideo = false;
+    }
   }
 }
 
 void HTMLMediaElement::NotifyMediaStreamTracksAvailable(DOMMediaStream* aStream)
 {
   if (!mSrcStream || mSrcStream != aStream) {
     return;
   }
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -338,19 +338,29 @@ public:
   void NotifyAddedSource();
 
   /**
    * Called when there's been an error fetching the resource. This decides
    * whether it's appropriate to fire an error event.
    */
   void NotifyLoadError();
 
+  /**
+   * Called by one of our associated MediaTrackLists (audio/video) when an
+   * AudioTrack is enabled or a VideoTrack is selected.
+   */
   void NotifyMediaTrackEnabled(MediaTrack* aTrack);
 
   /**
+   * Called by one of our associated MediaTrackLists (audio/video) when an
+   * AudioTrack is disabled or a VideoTrack is unselected.
+   */
+  void NotifyMediaTrackDisabled(MediaTrack* aTrack);
+
+  /**
    * Called when tracks become available to the source media stream.
    */
   void NotifyMediaStreamTracksAvailable(DOMMediaStream* aStream);
 
   virtual bool IsNodeOfType(uint32_t aFlags) const override;
 
   /**
    * Returns the current load ID. Asynchronous events store the ID that was
--- a/dom/media/AudioTrack.cpp
+++ b/dom/media/AudioTrack.cpp
@@ -43,20 +43,27 @@ AudioTrack::SetEnabledInternal(bool aEna
   mEnabled = aEnabled;
 
   // If this AudioTrack is no longer in its original AudioTrackList, then
   // whether it is enabled or not has no effect on its original list.
   if (!mList) {
     return;
   }
 
-  if (!(aFlags & MediaTrack::FIRE_NO_EVENTS)) {
-    mList->CreateAndDispatchChangeEvent();
-
+  if (mEnabled) {
     HTMLMediaElement* element = mList->GetMediaElement();
     if (element) {
       element->NotifyMediaTrackEnabled(this);
     }
+  } else {
+    HTMLMediaElement* element = mList->GetMediaElement();
+    if (element) {
+      element->NotifyMediaTrackDisabled(this);
+    }
+  }
+
+  if (!(aFlags & MediaTrack::FIRE_NO_EVENTS)) {
+    mList->CreateAndDispatchChangeEvent();
   }
 }
 
 } // namespace dom
 } //namespace mozilla
--- a/dom/media/MediaTrack.cpp
+++ b/dom/media/MediaTrack.cpp
@@ -1,16 +1,18 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 et tw=78: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MediaTrack.h"
+#include "AudioTrack.h"
 #include "MediaTrackList.h"
+#include "VideoTrack.h"
 
 namespace mozilla {
 namespace dom {
 
 MediaTrack::MediaTrack(const nsAString& aId,
                        const nsAString& aKind,
                        const nsAString& aLabel,
                        const nsAString& aLanguage)
--- a/dom/media/MediaTrackList.cpp
+++ b/dom/media/MediaTrackList.cpp
@@ -67,22 +67,33 @@ MediaTrackList::GetTrackById(const nsASt
 
 void
 MediaTrackList::AddTrack(MediaTrack* aTrack)
 {
   mTracks.AppendElement(aTrack);
   aTrack->Init(GetOwner());
   aTrack->SetTrackList(this);
   CreateAndDispatchTrackEventRunner(aTrack, NS_LITERAL_STRING("addtrack"));
+
+  if ((!aTrack->AsAudioTrack() || !aTrack->AsAudioTrack()->Enabled()) &&
+      (!aTrack->AsVideoTrack() || !aTrack->AsVideoTrack()->Selected())) {
+    // Track not enabled, no need to notify media element.
+    return;
+  }
+
+  if (HTMLMediaElement* element = GetMediaElement()) {
+    element->NotifyMediaTrackEnabled(aTrack);
+  }
 }
 
 void
 MediaTrackList::RemoveTrack(const RefPtr<MediaTrack>& aTrack)
 {
   mTracks.RemoveElement(aTrack);
+  aTrack->SetEnabledInternal(false, MediaTrack::FIRE_NO_EVENTS);
   aTrack->SetTrackList(nullptr);
   CreateAndDispatchTrackEventRunner(aTrack, NS_LITERAL_STRING("removetrack"));
 }
 
 void
 MediaTrackList::RemoveTracks()
 {
   while (!mTracks.IsEmpty()) {
@@ -113,16 +124,17 @@ MediaTrackList::CreateVideoTrack(const n
   RefPtr<VideoTrack> track = new VideoTrack(aId, aKind, aLabel, aLanguage, aVideoTrack);
   return track.forget();
 }
 
 void
 MediaTrackList::EmptyTracks()
 {
   for (uint32_t i = 0; i < mTracks.Length(); ++i) {
+    mTracks[i]->SetEnabledInternal(false, MediaTrack::FIRE_NO_EVENTS);
     mTracks[i]->SetTrackList(nullptr);
   }
   mTracks.Clear();
 }
 
 void
 MediaTrackList::CreateAndDispatchChangeEvent()
 {
--- a/dom/media/VideoTrack.cpp
+++ b/dom/media/VideoTrack.cpp
@@ -73,26 +73,31 @@ VideoTrack::SetEnabledInternal(bool aEna
       }
 
       VideoTrack* track = list[i];
       track->SetSelected(false);
     }
 
     // Set the index of selected video track to the current's index.
     list.mSelectedIndex = curIndex;
+
+    HTMLMediaElement* element = mList->GetMediaElement();
+    if (element) {
+      element->NotifyMediaTrackEnabled(this);
+    }
   } else {
     list.mSelectedIndex = -1;
+
+    HTMLMediaElement* element = mList->GetMediaElement();
+    if (element) {
+      element->NotifyMediaTrackDisabled(this);
+    }
   }
 
   // Fire the change event at selection changes on this video track, shall
   // propose a spec change later.
   if (!(aFlags & MediaTrack::FIRE_NO_EVENTS)) {
     list.CreateAndDispatchChangeEvent();
-
-    HTMLMediaElement* element = mList->GetMediaElement();
-    if (element) {
-      element->NotifyMediaTrackEnabled(this);
-    }
   }
 }
 
 } // namespace dom
 } //namespace mozilla