Bug 1299072: P8. Pass decoding error details through SeekTask. r?jwwang
MozReview-Commit-ID: bfsL6rBUfm
--- 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.
*/