Bug 1238906 - part2 : notify audible state from MDSM to ME. r=jwwang
☠☠ backed out by cdc15e930dab ☠ ☠
authorAlastor Wu <alwu@mozilla.com>
Mon, 18 Jan 2016 10:50:47 +0800
changeset 280354 e729b30ba7b41f14d52ae6e9eefda909f265645d
parent 280353 1857bca40ac45d31ca0320273ac19baa230af3f5
child 280355 f4384563b945a517c61999ae0eb59a14f8d80bac
push id70413
push usercbook@mozilla.com
push dateMon, 18 Jan 2016 09:08:57 +0000
treeherdermozilla-inbound@e729b30ba7b4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwwang
bugs1238906
milestone46.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 1238906 - part2 : notify audible state from MDSM to ME. r=jwwang
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
dom/media/MediaDecoder.cpp
dom/media/MediaDecoder.h
dom/media/MediaDecoderOwner.h
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
dom/media/gtest/MockMediaDecoderOwner.h
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -2108,17 +2108,18 @@ HTMLMediaElement::HTMLMediaElement(alrea
     mAudioChannelVolume(1.0),
     mPlayingThroughTheAudioChannel(false),
     mDisableVideo(false),
     mPlayBlockedBecauseHidden(false),
     mMediaStreamTrackListener(nullptr),
     mElementInTreeState(ELEMENT_NOT_INTREE),
     mHasUserInteraction(false),
     mFirstFrameLoaded(false),
-    mDefaultPlaybackStartPosition(0.0)
+    mDefaultPlaybackStartPosition(0.0),
+    mIsAudioTrackAudible(false)
 {
   mAudioChannel = AudioChannelService::GetDefaultAudioChannel();
 
   mPaused.SetOuter(this);
 
   RegisterActivityObserver();
   NotifyOwnerDocumentActivityChangedInternal();
 
@@ -5164,10 +5165,19 @@ HTMLMediaElement::IsCurrentlyPlaying() c
     if (mDecoder && mDecoder->IsSeeking() && !mPlayingBeforeSeek) {
       return false;
     }
     return true;
   }
   return false;
 }
 
+void
+HTMLMediaElement::NotifyAudibleStateChanged(bool aAudible)
+{
+  if (mIsAudioTrackAudible != aAudible) {
+    mIsAudioTrackAudible = aAudible;
+    // To do ...
+  }
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -392,16 +392,19 @@ public:
   {
     return mNetworkState;
   }
 
   // Called by the media decoder object, on the main thread,
   // when the connection between Rtsp server and client gets lost.
   virtual void ResetConnectionState() final override;
 
+  // Called by media decoder when the audible state changed.
+  virtual void NotifyAudibleStateChanged(bool aAudible) final override;
+
   // XPCOM GetPreload() is OK
   void SetPreload(const nsAString& aValue, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::preload, aValue, aRv);
   }
 
   already_AddRefed<TimeRanges> Buffered() const;
 
@@ -1516,14 +1519,17 @@ private:
 
   // True if the first frame has been successfully loaded.
   bool mFirstFrameLoaded;
 
   // Media elements also have a default playback start position, which must
   // initially be set to zero seconds. This time is used to allow the element to
   // be seeked even before the media is loaded.
   double mDefaultPlaybackStartPosition;
+
+  // True if the audio track is producing audible sound.
+  bool mIsAudioTrackAudible;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLMediaElement_h
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -527,16 +527,18 @@ MediaDecoder::MediaDecoder(MediaDecoderO
                      MediaDecoderOwner::NEXT_FRAME_UNINITIALIZED,
                      "MediaDecoder::mNextFrameStatus (Mirror)")
   , mCurrentPosition(AbstractThread::MainThread(), 0,
                      "MediaDecoder::mCurrentPosition (Mirror)")
   , mStateMachineDuration(AbstractThread::MainThread(), NullableTimeUnit(),
                           "MediaDecoder::mStateMachineDuration (Mirror)")
   , mPlaybackPosition(AbstractThread::MainThread(), 0,
                       "MediaDecoder::mPlaybackPosition (Mirror)")
+  , mIsAudioDataAudible(AbstractThread::MainThread(), false,
+                        "MediaDecoder::mIsAudioDataAudible (Mirror)")
   , mVolume(AbstractThread::MainThread(), 0.0,
             "MediaDecoder::mVolume (Canonical)")
   , mPlaybackRate(AbstractThread::MainThread(), 1.0,
                   "MediaDecoder::mPlaybackRate (Canonical)")
   , mPreservesPitch(AbstractThread::MainThread(), true,
                     "MediaDecoder::mPreservesPitch (Canonical)")
   , mEstimatedDuration(AbstractThread::MainThread(), NullableTimeUnit(),
                        "MediaDecoder::mEstimatedDuration (Canonical)")
@@ -587,16 +589,18 @@ MediaDecoder::MediaDecoder(MediaDecoderO
   // mLogicalPosition
   mWatchManager.Watch(mCurrentPosition, &MediaDecoder::UpdateLogicalPosition);
   mWatchManager.Watch(mPlayState, &MediaDecoder::UpdateLogicalPosition);
   mWatchManager.Watch(mLogicallySeeking, &MediaDecoder::UpdateLogicalPosition);
 
   // mIgnoreProgressData
   mWatchManager.Watch(mLogicallySeeking, &MediaDecoder::SeekingChanged);
 
+  mWatchManager.Watch(mIsAudioDataAudible, &MediaDecoder::NotifyAudibleStateChanged);
+
   MediaShutdownManager::Instance().Register(this);
 }
 
 RefPtr<ShutdownPromise>
 MediaDecoder::Shutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
@@ -618,16 +622,18 @@ MediaDecoder::Shutdown()
   if (mDecoderStateMachine) {
     mTimedMetadataListener.Disconnect();
     mMetadataLoadedListener.Disconnect();
     mFirstFrameLoadedListener.Disconnect();
     mOnPlaybackEvent.Disconnect();
     mOnSeekingStart.Disconnect();
     mOnMediaNotSeekable.Disconnect();
 
+    mWatchManager.Unwatch(mIsAudioDataAudible, &MediaDecoder::NotifyAudibleStateChanged);
+
     shutdown = mDecoderStateMachine->BeginShutdown()
         ->Then(AbstractThread::MainThread(), __func__, this,
                &MediaDecoder::FinishShutdown,
                &MediaDecoder::FinishShutdown)
         ->CompletionPromise();
   }
 
   // Force any outstanding seek and byterange requests to complete
@@ -1468,23 +1474,25 @@ MediaDecoder::SetStateMachine(MediaDecod
 
   if (mDecoderStateMachine) {
     mStateMachineDuration.Connect(mDecoderStateMachine->CanonicalDuration());
     mBuffered.Connect(mDecoderStateMachine->CanonicalBuffered());
     mStateMachineIsShutdown.Connect(mDecoderStateMachine->CanonicalIsShutdown());
     mNextFrameStatus.Connect(mDecoderStateMachine->CanonicalNextFrameStatus());
     mCurrentPosition.Connect(mDecoderStateMachine->CanonicalCurrentPosition());
     mPlaybackPosition.Connect(mDecoderStateMachine->CanonicalPlaybackOffset());
+    mIsAudioDataAudible.Connect(mDecoderStateMachine->CanonicalIsAudioDataAudible());
   } else {
     mStateMachineDuration.DisconnectIfConnected();
     mBuffered.DisconnectIfConnected();
     mStateMachineIsShutdown.DisconnectIfConnected();
     mNextFrameStatus.DisconnectIfConnected();
     mCurrentPosition.DisconnectIfConnected();
     mPlaybackPosition.DisconnectIfConnected();
+    mIsAudioDataAudible.DisconnectIfConnected();
   }
 }
 
 ImageContainer*
 MediaDecoder::GetImageContainer()
 {
   return mVideoFrameContainer ? mVideoFrameContainer->GetImageContainer() : nullptr;
 }
@@ -1826,16 +1834,23 @@ MediaDecoder::NextFrameBufferedStatus()
     media::TimeUnit::FromMicroseconds(CurrentPosition());
   media::TimeInterval interval(currentPosition,
                                currentPosition + media::TimeUnit::FromMicroseconds(DEFAULT_NEXT_FRAME_AVAILABLE_BUFFERED));
   return GetBuffered().Contains(interval)
     ? MediaDecoderOwner::NEXT_FRAME_AVAILABLE
     : MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
 }
 
+void
+MediaDecoder::NotifyAudibleStateChanged()
+{
+  MOZ_ASSERT(!mShuttingDown);
+  mOwner->NotifyAudibleStateChanged(mIsAudioDataAudible);
+}
+
 MediaMemoryTracker::MediaMemoryTracker()
 {
 }
 
 void
 MediaMemoryTracker::InitMemoryReporter()
 {
   RegisterWeakAsyncMemoryReporter(this);
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -768,16 +768,19 @@ protected:
   Mirror<media::NullableTimeUnit> mStateMachineDuration;
 
   // Current playback position in the stream. This is (approximately)
   // where we're up to playing back the stream. This is not adjusted
   // during decoder seek operations, but it's updated at the end when we
   // start playing back again.
   Mirror<int64_t> mPlaybackPosition;
 
+  // Used to distiguish whether the audio is producing sound.
+  Mirror<bool> mIsAudioDataAudible;
+
   // Volume of playback.  0.0 = muted. 1.0 = full volume.
   Canonical<double> mVolume;
 
   // PlaybackRate and pitch preservation status we should start at.
   Canonical<double> mPlaybackRate;
 
   Canonical<bool> mPreservesPitch;
 
@@ -863,16 +866,19 @@ public:
   AbstractCanonical<int64_t>* CanonicalDecoderPosition() {
     return &mDecoderPosition;
   }
   AbstractCanonical<bool>* CanonicalMediaSeekable() {
     return &mMediaSeekable;
   }
 
 private:
+  // Notify owner when the audible state changed
+  void NotifyAudibleStateChanged();
+
   /* Functions called by ResourceCallback */
 
   // A media stream is assumed to be infinite if the metadata doesn't
   // contain the duration, and range requests are not supported, and
   // no headers give a hint of a possible duration (Content-Length,
   // Content-Duration, and variants), and we cannot seek in the media
   // stream to determine the duration.
   //
--- a/dom/media/MediaDecoderOwner.h
+++ b/dom/media/MediaDecoderOwner.h
@@ -125,16 +125,19 @@ public:
   // Called by the media decoder and the video frame to get the
   // ImageContainer containing the video data.
   virtual VideoFrameContainer* GetVideoFrameContainer() = 0;
 
   // Called by the media decoder object, on the main thread,
   // when the connection between Rtsp server and client gets lost.
   virtual void ResetConnectionState() = 0;
 
+  // Called by media decoder when the audible state changed
+  virtual void NotifyAudibleStateChanged(bool aAudible) = 0;
+
 #ifdef MOZ_EME
   // 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;
 #endif // MOZ_EME
 };
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -236,17 +236,16 @@ MediaDecoderStateMachine::MediaDecoderSt
   mCorruptFrames(60),
   mDecodingFirstFrame(true),
   mSentLoadedMetadataEvent(false),
   mSentFirstFrameLoadedEvent(false),
   mSentPlaybackEndedEvent(false),
   mOutputStreamManager(new OutputStreamManager()),
   mResource(aDecoder->GetResource()),
   mAudioOffloading(false),
-  mIsAudioDataAudible(false),
   mSilentDataDuration(0),
   mBuffered(mTaskQueue, TimeIntervals(),
             "MediaDecoderStateMachine::mBuffered (Mirror)"),
   mEstimatedDuration(mTaskQueue, NullableTimeUnit(),
                     "MediaDecoderStateMachine::mEstimatedDuration (Mirror)"),
   mExplicitDuration(mTaskQueue, Maybe<double>(),
                     "MediaDecoderStateMachine::mExplicitDuration (Mirror)"),
   mPlayState(mTaskQueue, MediaDecoder::PLAY_STATE_LOADING,
@@ -274,17 +273,19 @@ MediaDecoderStateMachine::MediaDecoderSt
             "MediaDecoderStateMachine::mDuration (Canonical"),
   mIsShutdown(mTaskQueue, false,
               "MediaDecoderStateMachine::mIsShutdown (Canonical)"),
   mNextFrameStatus(mTaskQueue, MediaDecoderOwner::NEXT_FRAME_UNINITIALIZED,
                    "MediaDecoderStateMachine::mNextFrameStatus (Canonical)"),
   mCurrentPosition(mTaskQueue, 0,
                    "MediaDecoderStateMachine::mCurrentPosition (Canonical)"),
   mPlaybackOffset(mTaskQueue, 0,
-                  "MediaDecoderStateMachine::mPlaybackOffset (Canonical)")
+                  "MediaDecoderStateMachine::mPlaybackOffset (Canonical)"),
+  mIsAudioDataAudible(mTaskQueue, false,
+                     "MediaDecoderStateMachine::mIsAudioDataAudible (Canonical)")
 {
   MOZ_COUNT_CTOR(MediaDecoderStateMachine);
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
 
   // Dispatch initialization that needs to happen on that task queue.
   nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethodWithArg<RefPtr<MediaDecoder>>(
     this, &MediaDecoderStateMachine::InitializationTask, aDecoder);
   mTaskQueue->Dispatch(r.forget());
@@ -2192,16 +2193,17 @@ MediaDecoderStateMachine::FinishShutdown
   mDecoderPosition.DisconnectIfConnected();
   mMediaSeekable.DisconnectIfConnected();
 
   mDuration.DisconnectAll();
   mIsShutdown.DisconnectAll();
   mNextFrameStatus.DisconnectAll();
   mCurrentPosition.DisconnectAll();
   mPlaybackOffset.DisconnectAll();
+  mIsAudioDataAudible.DisconnectAll();
 
   // Shut down the watch manager before shutting down our task queue.
   mWatchManager.Shutdown();
 
   MOZ_ASSERT(mState == DECODER_STATE_SHUTDOWN,
              "How did we escape from the shutdown state?");
   DECODER_LOG("Shutting down state machine task queue");
   return OwnerThread()->BeginShutdown();
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -1191,18 +1191,17 @@ private:
 
   MediaEventProducer<MediaEventType> mOnPlaybackEvent;
   MediaEventProducer<MediaDecoderEventVisibility> mOnSeekingStart;
 
   // True if audio is offloading.
   // Playback will not start when audio is offloading.
   bool mAudioOffloading;
 
-  // Used to distiguish continuous silent audio data.
-  bool mIsAudioDataAudible;
+  // Duration of the continuous silent data.
   uint32_t mSilentDataDuration;
 
 #ifdef MOZ_EME
   void OnCDMProxyReady(RefPtr<CDMProxy> aProxy);
   void OnCDMProxyNotReady();
   RefPtr<CDMProxy> mCDMProxy;
   MozPromiseRequestHolder<MediaDecoder::CDMProxyPromise> mCDMProxyPromise;
 #endif
@@ -1263,16 +1262,19 @@ private:
   // The time of the current frame in microseconds, corresponding to the "current
   // playback position" in HTML5. This is referenced from 0, which is the initial
   // playback position.
   Canonical<int64_t> mCurrentPosition;
 
   // Current playback position in the stream in bytes.
   Canonical<int64_t> mPlaybackOffset;
 
+  // Used to distiguish whether the audio is producing sound.
+  Canonical<bool> mIsAudioDataAudible;
+
 public:
   AbstractCanonical<media::TimeIntervals>* CanonicalBuffered() {
     return mReader->CanonicalBuffered();
   }
   AbstractCanonical<media::NullableTimeUnit>* CanonicalDuration() {
     return &mDuration;
   }
   AbstractCanonical<bool>* CanonicalIsShutdown() {
@@ -1282,13 +1284,16 @@ public:
     return &mNextFrameStatus;
   }
   AbstractCanonical<int64_t>* CanonicalCurrentPosition() {
     return &mCurrentPosition;
   }
   AbstractCanonical<int64_t>* CanonicalPlaybackOffset() {
     return &mPlaybackOffset;
   }
+  AbstractCanonical<bool>* CanonicalIsAudioDataAudible() {
+    return &mIsAudioDataAudible;
+  }
 };
 
 } // namespace mozilla
 
 #endif
--- a/dom/media/gtest/MockMediaDecoderOwner.h
+++ b/dom/media/gtest/MockMediaDecoderOwner.h
@@ -42,12 +42,13 @@ public:
   virtual void DownloadResumed(bool aForceNetworkLoading) override {}
   virtual void NotifySuspendedByCache(bool aIsSuspended) override {}
   virtual void NotifyDecoderPrincipalChanged() override {}
   virtual VideoFrameContainer* GetVideoFrameContainer() override
   {
     return nullptr;
   }
   virtual void ResetConnectionState() override {}
+  virtual void NotifyAudibleStateChanged(bool aAudible) override {};
 };
 }
 
 #endif