Bug 1299072: P8. Pass decoding error details through SeekTask. r=jwwang
authorJean-Yves Avenard <jyavenard@mozilla.com>
Sun, 11 Sep 2016 00:45:34 +1000
changeset 357296 16f9471eb78db9c978667f41a1ed713037a11b3f
parent 357295 59b96d2ec6db2e11e568e17fa85f3d9c0a5c9972
child 357297 a17052bc7da442bdad9b5ee1ae25d0683fc7112a
push id1324
push usermtabara@mozilla.com
push dateMon, 16 Jan 2017 13:07:44 +0000
treeherdermozilla-release@a01c49833940 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwwang
bugs1299072
milestone51.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 1299072: P8. Pass decoding error details through SeekTask. r=jwwang MozReview-Commit-ID: bfsL6rBUfm
dom/media/AccurateSeekTask.cpp
dom/media/NextFrameSeekTask.cpp
dom/media/SeekTask.cpp
dom/media/SeekTask.h
--- a/dom/media/AccurateSeekTask.cpp
+++ b/dom/media/AccurateSeekTask.cpp
@@ -56,17 +56,17 @@ AccurateSeekTask::~AccurateSeekTask()
 }
 
 void
 AccurateSeekTask::Discard()
 {
   AssertOwnerThread();
 
   // Disconnect MDSM.
-  RejectIfExist(__func__);
+  RejectIfExist(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
 
   // Disconnect MediaDecoderReaderWrapper.
   mSeekRequest.DisconnectIfExists();
   CancelCallbacks();
 
   mIsDiscarded = true;
 }
 
@@ -115,17 +115,17 @@ AccurateSeekTask::DropAudioUpToSeekTarge
 {
   AssertOwnerThread();
 
   RefPtr<AudioData> audio(aSample->As<AudioData>());
   MOZ_ASSERT(audio && mTarget.IsAccurate());
 
   CheckedInt64 sampleDuration = FramesToUsecs(audio->mFrames, mAudioRate);
   if (!sampleDuration.isValid()) {
-    return NS_ERROR_FAILURE;
+    return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR;
   }
 
   if (audio->mTime + sampleDuration.value() <= mTarget.GetTime().ToMicroseconds()) {
     // Our seek target lies after the frames in this AudioData. Don't
     // push it onto the audio queue, and keep decoding forwards.
     return NS_OK;
   }
 
@@ -149,17 +149,17 @@ AccurateSeekTask::DropAudioUpToSeekTarge
   NS_ASSERTION(mTarget.GetTime().ToMicroseconds() >= audio->mTime,
                "Target must at or be after data start.");
   NS_ASSERTION(mTarget.GetTime().ToMicroseconds() < audio->mTime + sampleDuration.value(),
                "Data must end after target.");
 
   CheckedInt64 framesToPrune =
     UsecsToFrames(mTarget.GetTime().ToMicroseconds() - audio->mTime, mAudioRate);
   if (!framesToPrune.isValid()) {
-    return NS_ERROR_FAILURE;
+    return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR;
   }
   if (framesToPrune.value() > audio->mFrames) {
     // We've messed up somehow. Don't try to trim frames, the |frames|
     // variable below will overflow.
     DECODER_WARN("Can't prune more frames that we have!");
     return NS_ERROR_FAILURE;
   }
   uint32_t frames = audio->mFrames - static_cast<uint32_t>(framesToPrune.value());
@@ -169,17 +169,17 @@ AccurateSeekTask::DropAudioUpToSeekTarge
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   memcpy(audioData.get(),
          audio->mAudioData.get() + (framesToPrune.value() * channels),
          frames * channels * sizeof(AudioDataValue));
   CheckedInt64 duration = FramesToUsecs(frames, mAudioRate);
   if (!duration.isValid()) {
-    return NS_ERROR_FAILURE;
+    return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR;
   }
   RefPtr<AudioData> data(new AudioData(audio->mOffset,
                                        mTarget.GetTime().ToMicroseconds(),
                                        duration.value(),
                                        frames,
                                        Move(audioData),
                                        channels,
                                        audio->mRate));
@@ -255,17 +255,17 @@ AccurateSeekTask::OnSeekResolved(media::
 
 void
 AccurateSeekTask::OnSeekRejected(nsresult aResult)
 {
   AssertOwnerThread();
 
   mSeekRequest.Complete();
   MOZ_ASSERT(NS_FAILED(aResult), "Cancels should also disconnect mSeekRequest");
-  RejectIfExist(__func__);
+  RejectIfExist(aResult, __func__);
 }
 
 void
 AccurateSeekTask::AdjustFastSeekIfNeeded(MediaData* aSample)
 {
   AssertOwnerThread();
   if (mTarget.IsFast() &&
       mTarget.GetTime() > mCurrentTimeBeforeSeek &&
@@ -303,20 +303,23 @@ AccurateSeekTask::OnAudioDecoded(MediaDa
   }
 
   AdjustFastSeekIfNeeded(audio);
 
   if (mTarget.IsFast()) {
     // Non-precise seek; we can stop the seek at the first sample.
     mSeekedAudioData = audio;
     mDoneAudioSeeking = true;
-  } else if (NS_FAILED(DropAudioUpToSeekTarget(audio))) {
-    CancelCallbacks();
-    RejectIfExist(__func__);
-    return;
+  } else {
+    nsresult rv = DropAudioUpToSeekTarget(audio);
+    if (NS_FAILED(rv)) {
+      CancelCallbacks();
+      RejectIfExist(rv, __func__);
+      return;
+    }
   }
 
   if (!mDoneAudioSeeking) {
     RequestAudioData();
     return;
   }
   MaybeFinishSeek();
 }
@@ -365,17 +368,17 @@ AccurateSeekTask::OnNotDecoded(MediaData
       }
     }
     MaybeFinishSeek();
     return;
   }
 
   // This is a decode error, delegate to the generic error path.
   CancelCallbacks();
-  RejectIfExist(__func__);
+  RejectIfExist(aError, __func__);
 }
 
 void
 AccurateSeekTask::OnVideoDecoded(MediaData* aVideoSample)
 {
   AssertOwnerThread();
   MOZ_ASSERT(!mSeekTaskPromise.IsEmpty(), "Seek shouldn't be finished");
 
@@ -388,20 +391,23 @@ AccurateSeekTask::OnVideoDecoded(MediaDa
   SAMPLE_LOG("OnVideoDecoded [%lld,%lld]", video->mTime, video->GetEndTime());
 
   AdjustFastSeekIfNeeded(video);
 
   if (mTarget.IsFast()) {
     // Non-precise seek. We can stop the seek at the first sample.
     mSeekedVideoData = video;
     mDoneVideoSeeking = true;
-  } else if (NS_FAILED(DropVideoUpToSeekTarget(video.get()))) {
-    CancelCallbacks();
-    RejectIfExist(__func__);
-    return;
+  } else {
+    nsresult rv = DropVideoUpToSeekTarget(video.get());
+    if (NS_FAILED(rv)) {
+      CancelCallbacks();
+      RejectIfExist(rv, __func__);
+      return;
+    }
   }
 
   if (!mDoneVideoSeeking) {
     RequestVideoData();
     return;
   }
   MaybeFinishSeek();
 }
--- a/dom/media/NextFrameSeekTask.cpp
+++ b/dom/media/NextFrameSeekTask.cpp
@@ -48,17 +48,17 @@ NextFrameSeekTask::~NextFrameSeekTask()
 }
 
 void
 NextFrameSeekTask::Discard()
 {
   AssertOwnerThread();
 
   // Disconnect MDSM.
-  RejectIfExist(__func__);
+  RejectIfExist(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
 
   // Disconnect MediaDecoderReader.
   CancelCallbacks();
 
   mIsDiscarded = true;
 }
 
 bool
@@ -248,17 +248,17 @@ NextFrameSeekTask::OnVideoNotDecoded(con
         MOZ_ASSERT(false, "Shouldn't want more data for ended video.");
         break;
       default:
         // We might lose the audio sample after canceling the callbacks.
         // However it doesn't really matter because MDSM is gonna shut down
         // when seek fails.
         CancelCallbacks();
         // Reject the promise since we can't finish video seek anyway.
-        RejectIfExist(__func__);
+        RejectIfExist(aError, __func__);
         break;
     }
     return;
   }
 
   MaybeFinishSeek();
 }
 
@@ -298,17 +298,17 @@ NextFrameSeekTask::SetCallbacks()
   mVideoWaitCallback = mReader->VideoWaitCallback().Connect(
     OwnerThread(), [this] (WaitCallbackData aData) {
     if (NeedMoreVideo()) {
       if (aData.is<MediaData::Type>()) {
         RequestVideoData();
       } else {
         // Reject if we can't finish video seeking.
         CancelCallbacks();
-        RejectIfExist(__func__);
+        RejectIfExist(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
       }
       return;
     }
     MaybeFinishSeek();
   });
 }
 
 void
--- a/dom/media/SeekTask.cpp
+++ b/dom/media/SeekTask.cpp
@@ -41,23 +41,24 @@ SeekTask::Resolve(const char* aCallSite)
   val.mSeekedVideoData = mSeekedVideoData;
   val.mIsAudioQueueFinished = mIsAudioQueueFinished;
   val.mIsVideoQueueFinished = mIsVideoQueueFinished;
 
   mSeekTaskPromise.Resolve(val, aCallSite);
 }
 
 void
-SeekTask::RejectIfExist(const char* aCallSite)
+SeekTask::RejectIfExist(const MediaResult& aError, const char* aCallSite)
 {
   AssertOwnerThread();
 
   SeekTaskRejectValue val;
   val.mIsAudioQueueFinished = mIsAudioQueueFinished;
   val.mIsVideoQueueFinished = mIsVideoQueueFinished;
+  val.mError = aError;
 
   mSeekTaskPromise.RejectIfExists(val, aCallSite);
 }
 
 void
 SeekTask::AssertOwnerThread() const
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
--- a/dom/media/SeekTask.h
+++ b/dom/media/SeekTask.h
@@ -3,16 +3,17 @@
 /* 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/. */
 
 #ifndef SEEK_TASK_H
 #define SEEK_TASK_H
 
 #include "mozilla/MozPromise.h"
+#include "MediaResult.h"
 #include "SeekTarget.h"
 
 namespace mozilla {
 
 class AbstractThread;
 class MediaData;
 class MediaDecoderReaderWrapper;
 
@@ -25,18 +26,25 @@ struct SeekTaskResolveValue
   RefPtr<MediaData> mSeekedAudioData;
   RefPtr<MediaData> mSeekedVideoData;
   bool mIsAudioQueueFinished;
   bool mIsVideoQueueFinished;
 };
 
 struct SeekTaskRejectValue
 {
+  SeekTaskRejectValue()
+    : mIsAudioQueueFinished(false)
+    , mIsVideoQueueFinished(false)
+    , mError(NS_ERROR_DOM_MEDIA_FATAL_ERR)
+  {
+  }
   bool mIsAudioQueueFinished;
   bool mIsVideoQueueFinished;
+  MediaResult mError;
 };
 
 class SeekTask {
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SeekTask)
 
 public:
   static const bool IsExclusive = true;
@@ -57,17 +65,17 @@ protected:
            AbstractThread* aThread,
            MediaDecoderReaderWrapper* aReader,
            const SeekTarget& aTarget);
 
   virtual ~SeekTask();
 
   void Resolve(const char* aCallSite);
 
-  void RejectIfExist(const char* aCallSite);
+  void RejectIfExist(const MediaResult& aError, const char* aCallSite);
 
   void AssertOwnerThread() const;
 
   AbstractThread* OwnerThread() const;
 
   /*
    * Data shared with MDSM.
    */