Bug 1431010. P1 - pass RefPtr<> instead of a raw pointer so we can transfer ownership whenever possible. draft
authorJW Wang <jwwang@mozilla.com>
Wed, 17 Jan 2018 16:10:21 +0800
changeset 721917 80676fe03822356ed1afb1ae9fdeabdddf97bc85
parent 721916 12552221c0180adbc7b44f2ae1df916313b09ced
child 721918 43ef4ffe86127352b01c806a5d0408826e436ff7
push id95998
push userjwwang@mozilla.com
push dateThu, 18 Jan 2018 02:56:14 +0000
bugs1431010
milestone59.0a1
Bug 1431010. P1 - pass RefPtr<> instead of a raw pointer so we can transfer ownership whenever possible. MozReview-Commit-ID: 65SI3HZHyGO
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -180,21 +180,22 @@ class MediaDecoderStateMachine::StateObj
 public:
   virtual ~StateObject() { }
   virtual void Exit() { }   // Exit action.
   virtual void Step() { }   // Perform a 'cycle' of this state object.
   virtual State GetState() const = 0;
 
   // Event handlers for various events.
   virtual void HandleAudioCaptured() { }
-  virtual void HandleAudioDecoded(AudioData* aAudio)
+  virtual void HandleAudioDecoded(RefPtr<AudioData> aAudio)
   {
     Crash("Unexpected event!", __func__);
   }
-  virtual void HandleVideoDecoded(VideoData* aVideo, TimeStamp aDecodeStart)
+  virtual void HandleVideoDecoded(RefPtr<VideoData> aVideo,
+                                  TimeStamp aDecodeStart)
   {
     Crash("Unexpected event!", __func__);
   }
   virtual void HandleAudioWaited(MediaData::Type aType)
   {
     Crash("Unexpected event!", __func__);
   }
   virtual void HandleVideoWaited(MediaData::Type aType)
@@ -447,18 +448,21 @@ public:
 
   void HandleResumeVideoDecoding(const TimeUnit&) override
   {
     // Do nothing since we won't resume decoding until exiting dormant.
   }
 
   void HandlePlayStateChanged(MediaDecoder::PlayState aPlayState) override;
 
-  void HandleAudioDecoded(AudioData*) override { MaybeReleaseResources(); }
-  void HandleVideoDecoded(VideoData*, TimeStamp) override
+  void HandleAudioDecoded(RefPtr<AudioData>) override
+  {
+    MaybeReleaseResources();
+  }
+  void HandleVideoDecoded(RefPtr<VideoData>, TimeStamp) override
   {
     MaybeReleaseResources();
   }
   void HandleWaitingForAudio() override { MaybeReleaseResources(); }
   void HandleWaitingForVideo() override { MaybeReleaseResources(); }
   void HandleAudioCanceled() override { MaybeReleaseResources(); }
   void HandleVideoCanceled() override { MaybeReleaseResources(); }
   void HandleEndOfAudio() override { MaybeReleaseResources(); }
@@ -498,25 +502,26 @@ public:
   {
     // mPendingSeek is either moved in MaybeFinishDecodeFirstFrame()
     // or should be rejected here before transition to SHUTDOWN.
     mPendingSeek.RejectIfExists(__func__);
   }
 
   State GetState() const override { return DECODER_STATE_DECODING_FIRSTFRAME; }
 
-  void HandleAudioDecoded(AudioData* aAudio) override
+  void HandleAudioDecoded(RefPtr<AudioData> aAudio) override
   {
-    mMaster->PushAudio(aAudio);
+    mMaster->PushAudio(aAudio.forget());
     MaybeFinishDecodeFirstFrame();
   }
 
-  void HandleVideoDecoded(VideoData* aVideo, TimeStamp aDecodeStart) override
+  void HandleVideoDecoded(RefPtr<VideoData> aVideo,
+                          TimeStamp aDecodeStart) override
   {
-    mMaster->PushVideo(aVideo);
+    mMaster->PushVideo(aVideo.forget());
     MaybeFinishDecodeFirstFrame();
   }
 
   void HandleWaitingForAudio() override
   {
     mMaster->WaitForData(MediaData::AUDIO_DATA);
   }
 
@@ -624,26 +629,27 @@ public:
 
   void Step() override;
 
   State GetState() const override
   {
     return DECODER_STATE_DECODING;
   }
 
-  void HandleAudioDecoded(AudioData* aAudio) override
+  void HandleAudioDecoded(RefPtr<AudioData> aAudio) override
   {
-    mMaster->PushAudio(aAudio);
+    mMaster->PushAudio(aAudio.forget());
     DispatchDecodeTasksIfNeeded();
     MaybeStopPrerolling();
   }
 
-  void HandleVideoDecoded(VideoData* aVideo, TimeStamp aDecodeStart) override
+  void HandleVideoDecoded(RefPtr<VideoData> aVideo,
+                          TimeStamp aDecodeStart) override
   {
-    mMaster->PushVideo(aVideo);
+    mMaster->PushVideo(aVideo.forget());
     DispatchDecodeTasksIfNeeded();
     MaybeStopPrerolling();
   }
 
   void HandleAudioCanceled() override
   {
     mMaster->RequestAudioData();
   }
@@ -865,18 +871,18 @@ public:
 
   virtual void Exit() override = 0;
 
   State GetState() const override
   {
     return DECODER_STATE_SEEKING;
   }
 
-  void HandleAudioDecoded(AudioData* aAudio) override = 0;
-  void HandleVideoDecoded(VideoData* aVideo,
+  void HandleAudioDecoded(RefPtr<AudioData> aAudio) override = 0;
+  void HandleVideoDecoded(RefPtr<VideoData> aVideo,
                           TimeStamp aDecodeStart) override = 0;
   void HandleAudioWaited(MediaData::Type aType) override = 0;
   void HandleVideoWaited(MediaData::Type aType) override = 0;
 
   void HandleVideoSuspendTimeout() override
   {
     // Do nothing since we want a valid video frame to show when seek is done.
   }
@@ -917,57 +923,58 @@ public:
     mSeekJob.RejectIfExists(__func__);
 
     // Disconnect ReaderProxy.
     mSeekRequest.DisconnectIfExists();
 
     mWaitRequest.DisconnectIfExists();
   }
 
-  void HandleAudioDecoded(AudioData* aAudio) override
+  void HandleAudioDecoded(RefPtr<AudioData> aAudio) override
   {
     MOZ_ASSERT(!mDoneAudioSeeking || !mDoneVideoSeeking,
                "Seek shouldn't be finished");
     MOZ_ASSERT(aAudio);
 
     AdjustFastSeekIfNeeded(aAudio);
 
     if (mSeekJob.mTarget->IsFast()) {
       // Non-precise seek; we can stop the seek at the first sample.
-      mMaster->PushAudio(aAudio);
+      mMaster->PushAudio(aAudio.forget());
       mDoneAudioSeeking = true;
     } else {
-      nsresult rv = DropAudioUpToSeekTarget(aAudio);
+      nsresult rv = DropAudioUpToSeekTarget(aAudio.forget());
       if (NS_FAILED(rv)) {
         mMaster->DecodeError(rv);
         return;
       }
     }
 
     if (!mDoneAudioSeeking) {
       RequestAudioData();
       return;
     }
     MaybeFinishSeek();
   }
 
-  void HandleVideoDecoded(VideoData* aVideo, TimeStamp aDecodeStart) override
+  void HandleVideoDecoded(RefPtr<VideoData> aVideo,
+                          TimeStamp aDecodeStart) override
   {
     MOZ_ASSERT(!mDoneAudioSeeking || !mDoneVideoSeeking,
                "Seek shouldn't be finished");
     MOZ_ASSERT(aVideo);
 
     AdjustFastSeekIfNeeded(aVideo);
 
     if (mSeekJob.mTarget->IsFast()) {
       // Non-precise seek. We can stop the seek at the first sample.
-      mMaster->PushVideo(aVideo);
+      mMaster->PushVideo(aVideo.forget());
       mDoneVideoSeeking = true;
     } else {
-      nsresult rv = DropVideoUpToSeekTarget(aVideo);
+      nsresult rv = DropVideoUpToSeekTarget(aVideo.forget());
       if (NS_FAILED(rv)) {
         mMaster->DecodeError(rv);
         return;
       }
     }
 
     if (!mDoneVideoSeeking) {
       RequestVideoData();
@@ -1175,17 +1182,17 @@ protected:
       // seek and decode to the seek target. This is not conformant to the
       // spec, fastSeek should always be fast, but until we get the time to
       // change all Readers to seek to the keyframe after the currentTime
       // in this case, we'll just decode forward. Bug 1026330.
       mSeekJob.mTarget->SetType(SeekTarget::Accurate);
     }
   }
 
-  nsresult DropAudioUpToSeekTarget(AudioData* aAudio)
+  nsresult DropAudioUpToSeekTarget(RefPtr<AudioData> aAudio)
   {
     MOZ_ASSERT(aAudio && mSeekJob.mTarget->IsAccurate());
 
     auto sampleDuration = FramesToTimeUnit(
       aAudio->mFrames, Info().mAudio.mRate);
     if (!sampleDuration.IsValid()) {
       return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR;
     }
@@ -1201,17 +1208,17 @@ protected:
       // The seek target doesn't lie in the audio block just after the last
       // audio frames we've seen which were before the seek target. This
       // could have been the first audio data we've seen after seek, i.e. the
       // seek terminated after the seek target in the audio stream. Just
       // abort the audio decode-to-target, the state machine will play
       // silence to cover the gap. Typically this happens in poorly muxed
       // files.
       SLOGW("Audio not synced after seek, maybe a poorly muxed file?");
-      mMaster->PushAudio(aAudio);
+      mMaster->PushAudio(aAudio.forget());
       mDoneAudioSeeking = true;
       return NS_OK;
     }
 
     // The seek target lies somewhere in this AudioData's frames, strip off
     // any frames which lie before the seek target, so we'll begin playback
     // exactly at the seek target.
     NS_ASSERTION(mSeekJob.mTarget->GetTime() >= audioTime,
@@ -1245,23 +1252,23 @@ protected:
       return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR;
     }
     RefPtr<AudioData> data(new AudioData(
       aAudio->mOffset, mSeekJob.mTarget->GetTime(),
       duration, frames, Move(audioData), channels,
       aAudio->mRate));
     MOZ_ASSERT(AudioQueue().GetSize() == 0,
                "Should be the 1st sample after seeking");
-    mMaster->PushAudio(data);
+    mMaster->PushAudio(data.forget());
     mDoneAudioSeeking = true;
 
     return NS_OK;
   }
 
-  nsresult DropVideoUpToSeekTarget(VideoData* aVideo)
+  nsresult DropVideoUpToSeekTarget(RefPtr<VideoData> aVideo)
   {
     MOZ_ASSERT(aVideo);
     SLOG("DropVideoUpToSeekTarget() frame [%" PRId64 ", %" PRId64 "]",
          aVideo->mTime.ToMicroseconds(), aVideo->GetEndTime().ToMicroseconds());
     const auto target = GetSeekTarget();
 
     // If the frame end time is less than the seek target, we won't want
     // to display this frame after the seek, so discard it.
@@ -1284,17 +1291,17 @@ protected:
       SLOG("DropVideoUpToSeekTarget() found video frame [%" PRId64 ", %" PRId64
            "] containing target=%" PRId64,
            aVideo->mTime.ToMicroseconds(),
            aVideo->GetEndTime().ToMicroseconds(),
            target.ToMicroseconds());
 
       MOZ_ASSERT(VideoQueue().GetSize() == 0,
                  "Should be the 1st sample after seeking");
-      mMaster->PushVideo(aVideo);
+      mMaster->PushVideo(aVideo.forget());
       mDoneVideoSeeking = true;
     }
 
     return NS_OK;
   }
 
   void HandleEndOfAudioInternal()
   {
@@ -1385,29 +1392,30 @@ public:
   {
     // Disconnect my async seek operation.
     if (mAsyncSeekTask) { mAsyncSeekTask->Cancel(); }
 
     // Disconnect MediaDecoder.
     mSeekJob.RejectIfExists(__func__);
   }
 
-  void HandleAudioDecoded(AudioData* aAudio) override
+  void HandleAudioDecoded(RefPtr<AudioData> aAudio) override
   {
-    mMaster->PushAudio(aAudio);
+    mMaster->PushAudio(aAudio.forget());
   }
 
-  void HandleVideoDecoded(VideoData* aVideo, TimeStamp aDecodeStart) override
+  void HandleVideoDecoded(RefPtr<VideoData> aVideo,
+                          TimeStamp aDecodeStart) override
   {
     MOZ_ASSERT(aVideo);
     MOZ_ASSERT(!mSeekJob.mPromise.IsEmpty(), "Seek shouldn't be finished");
     MOZ_ASSERT(NeedMoreVideo());
 
     if (aVideo->mTime > mCurrentTime) {
-      mMaster->PushVideo(aVideo);
+      mMaster->PushVideo(aVideo.forget());
       FinishSeek();
     } else {
       RequestVideoData();
     }
   }
 
   void HandleWaitingForAudio() override
   {
@@ -1658,27 +1666,27 @@ public:
     // dispatch an event so that the UI can change in response to the end
     // of video-only seek.
     mMaster->mOnPlaybackEvent.Notify(
       MediaPlaybackEvent::VideoOnlySeekCompleted);
 
     AccurateSeekingState::Exit();
   }
 
-  void HandleAudioDecoded(AudioData* aAudio) override
+  void HandleAudioDecoded(RefPtr<AudioData> aAudio) override
   {
     MOZ_ASSERT(mDoneAudioSeeking && !mDoneVideoSeeking,
                "Seek shouldn't be finished");
     MOZ_ASSERT(aAudio);
 
     // Video-only seek doesn't reset audio decoder. There might be pending audio
     // requests when AccurateSeekTask::Seek() begins. We will just store the
     // data without checking |mDiscontinuity| or calling
     // DropAudioUpToSeekTarget().
-    mMaster->PushAudio(aAudio);
+    mMaster->PushAudio(aAudio.forget());
   }
 
   void HandleWaitingForAudio() override { }
 
   void HandleAudioCanceled() override { }
 
   void HandleEndOfAudio() override { }
 
@@ -1799,30 +1807,31 @@ public:
     mMaster->mOnNextFrameStatus.Notify(
       MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_BUFFERING);
   }
 
   void Step() override;
 
   State GetState() const override { return DECODER_STATE_BUFFERING; }
 
-  void HandleAudioDecoded(AudioData* aAudio) override
+  void HandleAudioDecoded(RefPtr<AudioData> aAudio) override
   {
-    mMaster->PushAudio(aAudio);
+    mMaster->PushAudio(aAudio.forget());
     if (!mMaster->HaveEnoughDecodedAudio()) {
       mMaster->RequestAudioData();
     }
     // This might be the sample we need to exit buffering.
     // Schedule Step() to check it.
     mMaster->ScheduleStateMachine();
   }
 
-  void HandleVideoDecoded(VideoData* aVideo, TimeStamp aDecodeStart) override
+  void HandleVideoDecoded(RefPtr<VideoData> aVideo,
+                          TimeStamp aDecodeStart) override
   {
-    mMaster->PushVideo(aVideo);
+    mMaster->PushVideo(aVideo.forget());
     if (!mMaster->HaveEnoughDecodedVideo()) {
       mMaster->RequestVideoData(media::TimeUnit());
     }
     // This might be the sample we need to exit buffering.
     // Schedule Step() to check it.
     mMaster->ScheduleStateMachine();
   }
 
@@ -2834,25 +2843,25 @@ MediaDecoderStateMachine::HaveEnoughDeco
 
 bool MediaDecoderStateMachine::HaveEnoughDecodedVideo()
 {
   MOZ_ASSERT(OnTaskQueue());
   return VideoQueue().GetSize() >= GetAmpleVideoFrames() * mPlaybackRate + 1;
 }
 
 void
-MediaDecoderStateMachine::PushAudio(AudioData* aSample)
+MediaDecoderStateMachine::PushAudio(RefPtr<AudioData> aSample)
 {
   MOZ_ASSERT(OnTaskQueue());
   MOZ_ASSERT(aSample);
   AudioQueue().Push(aSample);
 }
 
 void
-MediaDecoderStateMachine::PushVideo(VideoData* aSample)
+MediaDecoderStateMachine::PushVideo(RefPtr<VideoData> aSample)
 {
   MOZ_ASSERT(OnTaskQueue());
   MOZ_ASSERT(aSample);
   aSample->mFrameID = ++mCurrentFrameID;
   VideoQueue().Push(aSample);
 }
 
 void
@@ -3222,17 +3231,17 @@ MediaDecoderStateMachine::RequestAudioDa
       MOZ_ASSERT(aAudio);
       mAudioDataRequest.Complete();
       // audio->GetEndTime() is not always mono-increasing in chained ogg.
       mDecodedAudioEndTime = std::max(
         aAudio->GetEndTime(), mDecodedAudioEndTime);
       LOGV("OnAudioDecoded [%" PRId64 ",%" PRId64 "]",
            aAudio->mTime.ToMicroseconds(),
            aAudio->GetEndTime().ToMicroseconds());
-      mStateObj->HandleAudioDecoded(aAudio);
+      mStateObj->HandleAudioDecoded(aAudio.forget());
     },
     [this, self] (const MediaResult& aError) {
       LOGV("OnAudioNotDecoded aError=%s", aError.ErrorName().get());
       mAudioDataRequest.Complete();
       switch (aError.Code()) {
         case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
           mStateObj->HandleWaitingForAudio();
           break;
@@ -3268,17 +3277,17 @@ MediaDecoderStateMachine::RequestVideoDa
       MOZ_ASSERT(aVideo);
       mVideoDataRequest.Complete();
       // Handle abnormal or negative timestamps.
       mDecodedVideoEndTime = std::max(
         mDecodedVideoEndTime, aVideo->GetEndTime());
       LOGV("OnVideoDecoded [%" PRId64 ",%" PRId64 "]",
            aVideo->mTime.ToMicroseconds(),
            aVideo->GetEndTime().ToMicroseconds());
-      mStateObj->HandleVideoDecoded(aVideo, videoDecodeStartTime);
+      mStateObj->HandleVideoDecoded(aVideo.forget(), videoDecodeStartTime);
     },
     [this, self] (const MediaResult& aError) {
       LOGV("OnVideoNotDecoded aError=%s" , aError.ErrorName().get());
       mVideoDataRequest.Complete();
       switch (aError.Code()) {
         case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
           mStateObj->HandleWaitingForVideo();
           break;
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -370,18 +370,18 @@ protected:
   virtual ~MediaDecoderStateMachine();
 
   void BufferedRangeUpdated();
 
   void ReaderSuspendedChanged();
 
   // Inserts a sample into the Audio/Video queue.
   // aSample must not be null.
-  void PushAudio(AudioData* aSample);
-  void PushVideo(VideoData* aSample);
+  void PushAudio(RefPtr<AudioData> aSample);
+  void PushVideo(RefPtr<VideoData> aSample);
 
   void OnAudioPopped(const RefPtr<AudioData>& aSample);
   void OnVideoPopped(const RefPtr<VideoData>& aSample);
 
   void AudioAudibleChanged(bool aAudible);
 
   void VolumeChanged();
   void SetPlaybackRate(double aPlaybackRate);