Bug 1299072: P8. Pass decoding error details through SeekTask. r?jwwang draft
authorJean-Yves Avenard <jyavenard@mozilla.com>
Sun, 11 Sep 2016 00:45:34 +1000
changeset 412873 e1ac5bb8f35716d9e0b65504caca52bb6742b9c8
parent 412872 618c06a14e1a3160f7787a90e00cd5e2cd678657
child 412874 c7545fb792215ba95dac388d3683bef179877142
push id29276
push userbmo:jyavenard@mozilla.com
push dateTue, 13 Sep 2016 03:29:20 +0000
reviewersjwwang
bugs1299072
milestone51.0a1
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.
    */