Bug 1347402 part 4 - move ConstructMediaTracks/RemoveMediaTracks to HTMLMediaElemnt; r?jwwang draft
authorKaku Kuo <kaku@mozilla.com>
Wed, 15 Mar 2017 17:33:21 +0800
changeset 500355 c0dee5b76d56d44a1d66387cd9cce0448879d9ca
parent 500354 762bbf5db2b749d174b72ec2eb37bf42718861c5
child 500356 4465dce920b5d3190c0eb0e5cee8052c0fad5dad
push id49701
push userbmo:kaku@mozilla.com
push dateFri, 17 Mar 2017 03:54:30 +0000
reviewersjwwang
bugs1347402
milestone55.0a1
Bug 1347402 part 4 - move ConstructMediaTracks/RemoveMediaTracks to HTMLMediaElemnt; r?jwwang ConstructMediaTracks and RemoveMediaTracks are actually HTMLMediaElement's responsibilities. MozReview-Commit-ID: 8lOdzD4pN7N
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
dom/media/MediaDecoder.cpp
dom/media/MediaDecoder.h
dom/media/MediaDecoderOwner.h
dom/media/gtest/MockMediaDecoderOwner.h
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -3715,16 +3715,17 @@ HTMLMediaElement::HTMLMediaElement(alrea
     mDownloadSuspendedByCache(false, "HTMLMediaElement::mDownloadSuspendedByCache"),
     mAudioChannel(AudioChannelService::GetDefaultAudioChannel()),
     mDisableVideo(false),
     mHasUserInteraction(false),
     mFirstFrameLoaded(false),
     mDefaultPlaybackStartPosition(0.0),
     mIsAudioTrackAudible(false),
     mHasSuspendTaint(false),
+    mMediaTracksConstructed(false),
     mVisibilityState(Visibility::APPROXIMATELY_NONVISIBLE),
     mErrorSink(new ErrorSink(this)),
     mAudioChannelWrapper(new AudioChannelAgentCallback(this, mAudioChannel))
 {
   ErrorResult rv;
 
   double defaultVolume = Preferences::GetFloat("media.default_volume", 1.0);
   SetVolume(defaultVolume, rv);
@@ -7410,16 +7411,61 @@ HTMLMediaElement::NotifyDecoderActivityC
 }
 
 nsIDocument*
 HTMLMediaElement::GetDocument() const
 {
   return OwnerDoc();
 }
 
+void
+HTMLMediaElement::ConstructMediaTracks(const MediaInfo* aInfo)
+{
+  if (mMediaTracksConstructed || !aInfo) {
+    return;
+  }
+
+  mMediaTracksConstructed = true;
+
+  AudioTrackList* audioList = AudioTracks();
+  if (audioList && aInfo->HasAudio()) {
+    const TrackInfo& info = aInfo->mAudio;
+    RefPtr<AudioTrack> track = MediaTrackList::CreateAudioTrack(
+    info.mId, info.mKind, info.mLabel, info.mLanguage, info.mEnabled);
+
+    audioList->AddTrack(track);
+  }
+
+  VideoTrackList* videoList = VideoTracks();
+  if (videoList && aInfo->HasVideo()) {
+    const TrackInfo& info = aInfo->mVideo;
+    RefPtr<VideoTrack> track = MediaTrackList::CreateVideoTrack(
+    info.mId, info.mKind, info.mLabel, info.mLanguage);
+
+    videoList->AddTrack(track);
+    track->SetEnabledInternal(info.mEnabled, MediaTrack::FIRE_NO_EVENTS);
+  }
+}
+
+void
+HTMLMediaElement::RemoveMediaTracks()
+{
+  AudioTrackList* audioList = AudioTracks();
+  if (audioList) {
+    audioList->RemoveTracks();
+  }
+
+  VideoTrackList* videoList = VideoTracks();
+  if (videoList) {
+    videoList->RemoveTracks();
+  }
+
+  mMediaTracksConstructed = false;
+}
+
 bool HasDebuggerPrivilege(JSContext* aCx, JSObject* aObj)
 {
   return nsContentUtils::CallerHasPermission(aCx,
                                              NS_LITERAL_STRING("debugger"));
  }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -771,16 +771,20 @@ public:
     CREATE_PATTERN,
     CREATE_IMAGEBITMAP,
     CAPTURE_STREAM,
   };
   void MarkAsContentSource(CallerAPI aAPI);
 
   nsIDocument* GetDocument() const override;
 
+  void ConstructMediaTracks(const MediaInfo* aInfo) override;
+
+  void RemoveMediaTracks() override;
+
 protected:
   virtual ~HTMLMediaElement();
 
   class AudioChannelAgentCallback;
   class ChannelLoader;
   class ErrorSink;
   class MediaLoadListener;
   class MediaStreamTracksAvailableCallback;
@@ -1730,16 +1734,20 @@ private:
 
   // True if the audio track is not silent.
   bool mIsAudioTrackAudible;
 
   // True if media element has been marked as 'tainted' and can't
   // participate in video decoder suspending.
   bool mHasSuspendTaint;
 
+  // True if audio tracks and video tracks are constructed and added into the
+  // track list, false if all tracks are removed from the track list.
+  bool mMediaTracksConstructed;
+
   Visibility mVisibilityState;
 
   UniquePtr<ErrorSink> mErrorSink;
 
   // This wrapper will handle all audio channel related stuffs, eg. the operations
   // of tab audio indicator, Fennec's media control.
   // Note: mAudioChannelWrapper might be null after GC happened.
   RefPtr<AudioChannelAgentCallback> mAudioChannelWrapper;
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -389,17 +389,16 @@ MediaDecoder::MediaDecoder(MediaDecoderO
   , mInfiniteStream(false)
   , mOwner(aOwner)
   , mAbstractMainThread(aOwner->AbstractMainThread())
   , mFrameStats(new FrameStatistics())
   , mVideoFrameContainer(aOwner->GetVideoFrameContainer())
   , mPlaybackStatistics(new MediaChannelStatistics())
   , mPinnedForSeek(false)
   , mMinimizePreroll(false)
-  , mMediaTracksConstructed(false)
   , mFiredMetadataLoaded(false)
   , mIsDocumentVisible(false)
   , mIsElementVisible(false)
   , mIsElementInTree(false)
   , mForcedHidden(false)
   , mHasSuspendTaint(false)
   , INIT_MIRROR(mStateMachineIsShutdown, true)
   , INIT_MIRROR(mBuffered, TimeIntervals())
@@ -803,17 +802,17 @@ MediaDecoder::GetCurrentPrincipal()
   MOZ_ASSERT(NS_IsMainThread());
   return mResource ? mResource->GetCurrentPrincipal() : nullptr;
 }
 
 void
 MediaDecoder::OnMetadataUpdate(TimedMetadata&& aMetadata)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  RemoveMediaTracks();
+  GetOwner()->RemoveMediaTracks();
   MetadataLoaded(nsAutoPtr<MediaInfo>(new MediaInfo(*aMetadata.mInfo)),
                  Move(aMetadata.mTags),
                  MediaDecoderEventVisibility::Observable);
   FirstFrameLoaded(Move(aMetadata.mInfo),
                    MediaDecoderEventVisibility::Observable);
 }
 
 void
@@ -826,17 +825,17 @@ MediaDecoder::MetadataLoaded(nsAutoPtr<M
 
   DECODER_LOG("MetadataLoaded, channels=%u rate=%u hasAudio=%d hasVideo=%d",
               aInfo->mAudio.mChannels, aInfo->mAudio.mRate,
               aInfo->HasAudio(), aInfo->HasVideo());
 
   mMediaSeekable = aInfo->mMediaSeekable;
   mMediaSeekableOnlyInBufferedRanges = aInfo->mMediaSeekableOnlyInBufferedRanges;
   mInfo = aInfo.forget();
-  ConstructMediaTracks();
+  GetOwner()->ConstructMediaTracks(mInfo);
 
   // Make sure the element and the frame (if any) are told about
   // our new size.
   if (aEventVisibility != MediaDecoderEventVisibility::Suppressed) {
     mFiredMetadataLoaded = true;
     GetOwner()->MetadataLoaded(mInfo,
                                nsAutoPtr<const MetadataTags>(aTags.forget()));
   }
@@ -1214,19 +1213,19 @@ MediaDecoder::ChangeState(PlayState aSta
   if (mNextState == aState) {
     mNextState = PLAY_STATE_PAUSED;
   }
 
   DECODER_LOG("ChangeState %s => %s", PlayStateStr(), ToPlayStateStr(aState));
   mPlayState = aState;
 
   if (mPlayState == PLAY_STATE_PLAYING) {
-    ConstructMediaTracks();
+    GetOwner()->ConstructMediaTracks(mInfo);
   } else if (IsEnded()) {
-    RemoveMediaTracks();
+    GetOwner()->RemoveMediaTracks();
   }
 }
 
 void
 MediaDecoder::UpdateLogicalPositionInternal()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
@@ -1776,77 +1775,16 @@ MediaDecoder::GetOwner() const
 {
   MOZ_ASSERT(NS_IsMainThread());
   // Check object lifetime when mOwner points to a media element.
   MOZ_DIAGNOSTIC_ASSERT(!mOwner || !mIsMediaElement || mElement);
   // mOwner is valid until shutdown.
   return mOwner;
 }
 
-void
-MediaDecoder::ConstructMediaTracks()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
-
-  if (mMediaTracksConstructed || !mInfo) {
-    return;
-  }
-
-  HTMLMediaElement* element = GetOwner()->GetMediaElement();
-  if (!element) {
-    return;
-  }
-
-  mMediaTracksConstructed = true;
-
-  AudioTrackList* audioList = element->AudioTracks();
-  if (audioList && mInfo->HasAudio()) {
-    const TrackInfo& info = mInfo->mAudio;
-    RefPtr<AudioTrack> track = MediaTrackList::CreateAudioTrack(
-    info.mId, info.mKind, info.mLabel, info.mLanguage, info.mEnabled);
-
-    audioList->AddTrack(track);
-  }
-
-  VideoTrackList* videoList = element->VideoTracks();
-  if (videoList && mInfo->HasVideo()) {
-    const TrackInfo& info = mInfo->mVideo;
-    RefPtr<VideoTrack> track = MediaTrackList::CreateVideoTrack(
-    info.mId, info.mKind, info.mLabel, info.mLanguage);
-
-    videoList->AddTrack(track);
-    track->SetEnabledInternal(info.mEnabled, MediaTrack::FIRE_NO_EVENTS);
-  }
-}
-
-void
-MediaDecoder::RemoveMediaTracks()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
-
-  HTMLMediaElement* element = GetOwner()->GetMediaElement();
-  if (!element) {
-    return;
-  }
-
-  AudioTrackList* audioList = element->AudioTracks();
-  if (audioList) {
-    audioList->RemoveTracks();
-  }
-
-  VideoTrackList* videoList = element->VideoTracks();
-  if (videoList) {
-    videoList->RemoveTracks();
-  }
-
-  mMediaTracksConstructed = false;
-}
-
 MediaDecoderOwner::NextFrameStatus
 MediaDecoder::NextFrameBufferedStatus()
 {
   MOZ_ASSERT(NS_IsMainThread());
   // Next frame hasn't been decoded yet.
   // Use the buffered range to consider if we have the next frame available.
   media::TimeUnit currentPosition =
     media::TimeUnit::FromMicroseconds(CurrentPosition());
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -394,25 +394,16 @@ private:
    * thread.
    ******/
 
   // Change to a new play state. This updates the mState variable and
   // notifies any thread blocking on this object's monitor of the
   // change. Call on the main thread only.
   virtual void ChangeState(PlayState aState);
 
-  // Called from MetadataLoaded(). Creates audio tracks and adds them to its
-  // owner's audio track list, and implies to video tracks respectively.
-  // Call on the main thread only.
-  void ConstructMediaTracks();
-
-  // Removes all audio tracks and video tracks that are previously added into
-  // the track list. Call on the main thread only.
-  void RemoveMediaTracks();
-
   // Called when the video has completed playing.
   // Call on the main thread only.
   void PlaybackEnded();
 
   void OnSeekRejected();
   void OnSeekResolved();
 
   void SeekingChanged()
@@ -697,20 +688,16 @@ protected:
   dom::AudioChannel mAudioChannel;
 
   // True if the decoder has been directed to minimize its preroll before
   // playback starts. After the first time playback starts, we don't attempt
   // to minimize preroll, as we assume the user is likely to keep playing,
   // or play the media again.
   bool mMinimizePreroll;
 
-  // True if audio tracks and video tracks are constructed and added into the
-  // track list, false if all tracks are removed from the track list.
-  bool mMediaTracksConstructed;
-
   // True if we've already fired metadataloaded.
   bool mFiredMetadataLoaded;
 
   // True if the media is seekable (i.e. supports random access).
   bool mMediaSeekable = true;
 
   // True if the media is only seekable within its buffered ranges
   // like WebMs with no cues.
--- a/dom/media/MediaDecoderOwner.h
+++ b/dom/media/MediaDecoderOwner.h
@@ -7,16 +7,17 @@
 #define MediaDecoderOwner_h_
 #include "AbstractMediaDecoder.h"
 #include "nsAutoPtr.h"
 
 namespace mozilla {
 
 class AbstractThread;
 class VideoFrameContainer;
+class MediaInfo;
 class MediaResult;
 
 namespace dom {
 class HTMLMediaElement;
 } // namespace dom
 
 class MediaDecoderOwner
 {
@@ -155,14 +156,22 @@ public:
   // Dispatches a "encrypted" event to the HTMLMediaElement, with the
   // provided init data. Actual dispatch may be delayed until HAVE_METADATA.
   // Main thread only.
   virtual void DispatchEncrypted(const nsTArray<uint8_t>& aInitData,
                                  const nsAString& aInitDataType) = 0;
 
   // Return the decoder owner's owner document.
   virtual nsIDocument* GetDocument() const = 0;
+
+  // Called by the media decoder to create audio/video tracks and add to its
+  // owner's track list.
+  virtual void ConstructMediaTracks(const MediaInfo* aInfo) = 0;
+
+  // Called by the media decoder to removes all audio/video tracks from its
+  // owner's track list.
+  virtual void RemoveMediaTracks() = 0;
 };
 
 } // namespace mozilla
 
 #endif
 
--- a/dom/media/gtest/MockMediaDecoderOwner.h
+++ b/dom/media/gtest/MockMediaDecoderOwner.h
@@ -50,12 +50,14 @@ public:
   void SetAudibleState(bool aAudible) override {}
   void NotifyXPCOMShutdown() override {}
   AbstractThread* AbstractMainThread() const override
   {
     // Non-DocGroup version for Mock.
     return AbstractThread::MainThread();
   }
   nsIDocument* GetDocument() const { return nullptr; }
+  void ConstructMediaTracks(const MediaInfo* aInfo) {}
+  void RemoveMediaTracks() {}
 };
 }
 
 #endif