Bug 1053186 - AudioOffloadPlayer: Avoid glitch during start of playback. r=roc, a=2.0+
authorVasanthakumar Pandurangan <vasanth@codeaurora.org>
Mon, 18 Aug 2014 04:59:29 -0700
changeset 203671 2b622e00d27a658c38bf475a1a6a4e632591a959
parent 203670 3cd520e7358d1148db8fda62f6c889a9feeb280c
child 203672 7194d5ddc5e67c56a3a6ce30471e112cec09516e
push id197
push userryanvm@gmail.com
push dateTue, 19 Aug 2014 21:53:32 +0000
treeherdermozilla-b2g32_v2_0@7194d5ddc5e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, 2
bugs1053186
milestone32.0
Bug 1053186 - AudioOffloadPlayer: Avoid glitch during start of playback. r=roc, a=2.0+
content/media/AbstractMediaDecoder.h
content/media/MediaDecoderStateMachine.cpp
content/media/omx/MediaOmxDecoder.cpp
content/media/omx/MediaOmxDecoder.h
content/media/omx/MediaOmxReader.cpp
--- a/content/media/AbstractMediaDecoder.h
+++ b/content/media/AbstractMediaDecoder.h
@@ -111,18 +111,21 @@ public:
   // Returns the owner of this media decoder. The owner should only be used
   // on the main thread.
   virtual MediaDecoderOwner* GetOwner() = 0;
 
   // May be called by the reader to notify the decoder that the resources
   // required to begin playback have been acquired. Can be called on any thread.
   virtual void NotifyWaitingForResourcesStatusChanged() = 0;
 
-  // Called by Reader if the current audio track can be offloaded
-  virtual void SetCanOffloadAudio(bool aCanOffloadAudio) {}
+  // Set by Reader if the current audio track can be offloaded
+  virtual void SetPlatformCanOffloadAudio(bool aCanOffloadAudio) {}
+
+  // Called by Decoder/State machine to check audio offload condtions are met
+  virtual bool CheckDecoderCanOffloadAudio() { return false; }
 
   // Called from HTMLMediaElement when owner document activity changes
   virtual void SetElementVisibility(bool aIsVisible) {}
 
   // Stack based class to assist in notifying the frame statistics of
   // parsed and decoded frames. Use inside video demux & decode functions
   // to ensure all parsed and decoded frames are reported on all return paths.
   class AutoNotifyDecoded {
--- a/content/media/MediaDecoderStateMachine.cpp
+++ b/content/media/MediaDecoderStateMachine.cpp
@@ -1089,16 +1089,21 @@ int64_t MediaDecoderStateMachine::GetCur
 
 void MediaDecoderStateMachine::StartPlayback()
 {
   DECODER_LOG(PR_LOG_DEBUG, "StartPlayback()");
 
   NS_ASSERTION(!IsPlaying(), "Shouldn't be playing when StartPlayback() is called");
   AssertCurrentThreadInMonitor();
 
+  if (mDecoder->CheckDecoderCanOffloadAudio()) {
+    DECODER_LOG(PR_LOG_DEBUG, "Offloading playback");
+    return;
+  }
+
   mDecoder->NotifyPlaybackStarted();
   mPlayStartTime = TimeStamp::Now();
 
   NS_ASSERTION(IsPlaying(), "Should report playing by end of StartPlayback()");
   if (NS_FAILED(StartAudioThread())) {
     NS_WARNING("Failed to create audio thread");
   }
   mDecoder->GetReentrantMonitor().NotifyAll();
--- a/content/media/omx/MediaOmxDecoder.cpp
+++ b/content/media/omx/MediaOmxDecoder.cpp
@@ -45,34 +45,39 @@ MediaDecoder* MediaOmxDecoder::Clone()
 
 MediaDecoderStateMachine* MediaOmxDecoder::CreateStateMachine()
 {
   mReader = new MediaOmxReader(this);
   mReader->SetAudioChannel(GetAudioChannel());
   return new MediaDecoderStateMachine(this, mReader);
 }
 
-void MediaOmxDecoder::SetCanOffloadAudio(bool aCanOffloadAudio)
+void MediaOmxDecoder::SetPlatformCanOffloadAudio(bool aCanOffloadAudio)
 {
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
   mCanOffloadAudio = aCanOffloadAudio;
 }
 
+bool MediaOmxDecoder::CheckDecoderCanOffloadAudio()
+{
+  return (mCanOffloadAudio && !mFallbackToStateMachine && !mOutputStreams.Length() &&
+      mInitialPlaybackRate == 1.0);
+}
+
 void MediaOmxDecoder::MetadataLoaded(int aChannels,
                                      int aRate,
                                      bool aHasAudio,
                                      bool aHasVideo,
                                      MetadataTags* aTags)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MediaDecoder::MetadataLoaded(aChannels, aRate, aHasAudio, aHasVideo, aTags);
 
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
-  if (!mCanOffloadAudio || mFallbackToStateMachine || mOutputStreams.Length() ||
-      mInitialPlaybackRate != 1.0) {
+  if (!CheckDecoderCanOffloadAudio()) {
     DECODER_LOG(PR_LOG_DEBUG, ("In %s Offload Audio check failed",
         __PRETTY_FUNCTION__));
     return;
   }
 
 #ifdef MOZ_AUDIO_OFFLOAD
   mAudioOffloadPlayer = new AudioOffloadPlayer(this);
 #endif
@@ -81,16 +86,17 @@ void MediaOmxDecoder::MetadataLoaded(int
   if (err == OK) {
     PauseStateMachine();
     // Call ChangeState() to run AudioOffloadPlayer since offload state enabled
     ChangeState(mPlayState);
     return;
   }
 
   mAudioOffloadPlayer = nullptr;
+  mFallbackToStateMachine = true;
   DECODER_LOG(PR_LOG_DEBUG, ("In %s Unable to start offload audio %d."
       "Switching to normal mode", __PRETTY_FUNCTION__, err));
 }
 
 void MediaOmxDecoder::PauseStateMachine()
 {
   MOZ_ASSERT(NS_IsMainThread());
   GetReentrantMonitor().AssertCurrentThreadIn();
--- a/content/media/omx/MediaOmxDecoder.h
+++ b/content/media/omx/MediaOmxDecoder.h
@@ -27,17 +27,18 @@ public:
                               bool aHasVideo,
                               MetadataTags* aTags);
   virtual void ChangeState(PlayState aState);
   virtual void ApplyStateToStateMachine(PlayState aState);
   virtual void SetVolume(double aVolume);
   virtual void PlaybackPositionChanged();
   virtual void UpdateReadyStateForData();
   virtual void SetElementVisibility(bool aIsVisible);
-  virtual void SetCanOffloadAudio(bool aCanOffloadAudio);
+  virtual void SetPlatformCanOffloadAudio(bool aCanOffloadAudio);
+  virtual bool CheckDecoderCanOffloadAudio();
   virtual void AddOutputStream(ProcessedMediaStream* aStream,
                                bool aFinishWhenEnded);
   virtual void SetPlaybackRate(double aPlaybackRate);
 
   void AudioOffloadTearDown();
   int64_t GetSeekTime() { return mRequestedSeekTarget.mTime; }
   void ResetSeekTime() { mRequestedSeekTarget.Reset(); }
 
--- a/content/media/omx/MediaOmxReader.cpp
+++ b/content/media/omx/MediaOmxReader.cpp
@@ -449,14 +449,14 @@ void MediaOmxReader::CheckAudioOffload()
 
   DECODER_LOG(PR_LOG_DEBUG, ("%s meta %p, no video %d, no streaming %d,"
       " channel type %d", __FUNCTION__, meta.get(), hasNoVideo,
       isNotStreaming, mAudioChannel));
 
   if ((meta.get()) && hasNoVideo && isNotStreaming && isTypeMusic &&
       canOffloadStream(meta, false, false, AUDIO_STREAM_MUSIC)) {
     DECODER_LOG(PR_LOG_DEBUG, ("Can offload this audio stream"));
-    mDecoder->SetCanOffloadAudio(true);
+    mDecoder->SetPlatformCanOffloadAudio(true);
   }
 }
 #endif
 
 } // namespace mozilla