зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1508434 - p3: assert members are only accessed on task queue. r=jya
Differential Revision: https://phabricator.services.mozilla.com/D15740 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
d6ebba5265
Коммит
31377925fe
|
@ -511,11 +511,13 @@ RefPtr<MediaDataDecoder::FlushPromise> RemoteDataDecoder::Flush() {
|
|||
}
|
||||
|
||||
RefPtr<MediaDataDecoder::FlushPromise> RemoteDataDecoder::ProcessFlush() {
|
||||
AssertOnTaskQueue();
|
||||
|
||||
mDecodedData = DecodedData();
|
||||
mNumPendingInputs = 0;
|
||||
UpdatePendingInputStatus(PendingOp::CLEAR);
|
||||
mDecodePromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
|
||||
mDrainPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
|
||||
mDrainStatus = DrainStatus::DRAINED;
|
||||
SetState(State::DRAINED);
|
||||
mJavaDecoder->Flush();
|
||||
return FlushPromise::CreateAndResolve(true, __func__);
|
||||
}
|
||||
|
@ -523,19 +525,19 @@ RefPtr<MediaDataDecoder::FlushPromise> RemoteDataDecoder::ProcessFlush() {
|
|||
RefPtr<MediaDataDecoder::DecodePromise> RemoteDataDecoder::Drain() {
|
||||
RefPtr<RemoteDataDecoder> self = this;
|
||||
return InvokeAsync(mTaskQueue, __func__, [self, this]() {
|
||||
if (mShutdown) {
|
||||
if (GetState() == State::SHUTDOWN) {
|
||||
return DecodePromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED,
|
||||
__func__);
|
||||
}
|
||||
RefPtr<DecodePromise> p = mDrainPromise.Ensure(__func__);
|
||||
if (mDrainStatus == DrainStatus::DRAINED) {
|
||||
if (GetState() == State::DRAINED) {
|
||||
// There's no operation to perform other than returning any already
|
||||
// decoded data.
|
||||
ReturnDecodedData();
|
||||
return p;
|
||||
}
|
||||
|
||||
if (mDrainStatus == DrainStatus::DRAINING) {
|
||||
if (GetState() == State::DRAINING) {
|
||||
// Draining operation already pending, let it complete its course.
|
||||
return p;
|
||||
}
|
||||
|
@ -545,7 +547,7 @@ RefPtr<MediaDataDecoder::DecodePromise> RemoteDataDecoder::Drain() {
|
|||
if (NS_FAILED(rv)) {
|
||||
return DecodePromise::CreateAndReject(NS_ERROR_OUT_OF_MEMORY, __func__);
|
||||
}
|
||||
mDrainStatus = DrainStatus::DRAINING;
|
||||
SetState(State::DRAINING);
|
||||
bufferInfo->Set(0, 0, -1, MediaCodec::BUFFER_FLAG_END_OF_STREAM);
|
||||
mJavaDecoder->Input(nullptr, bufferInfo, nullptr);
|
||||
return p;
|
||||
|
@ -561,7 +563,7 @@ RefPtr<ShutdownPromise> RemoteDataDecoder::Shutdown() {
|
|||
|
||||
RefPtr<ShutdownPromise> RemoteDataDecoder::ProcessShutdown() {
|
||||
AssertOnTaskQueue();
|
||||
mShutdown = true;
|
||||
SetState(State::SHUTDOWN);
|
||||
if (mJavaDecoder) {
|
||||
mJavaDecoder->Release();
|
||||
mJavaDecoder = nullptr;
|
||||
|
@ -654,7 +656,7 @@ RefPtr<MediaDataDecoder::DecodePromise> RemoteDataDecoder::Decode(
|
|||
}
|
||||
bufferInfo->Set(0, sample->Size(), sample->mTime.ToMicroseconds(), 0);
|
||||
|
||||
self->mDrainStatus = DrainStatus::DRAINABLE;
|
||||
self->SetState(State::DRAINABLE);
|
||||
return self->mJavaDecoder->Input(bytes, bufferInfo,
|
||||
GetCryptoInfoFromSample(sample))
|
||||
? self->mDecodePromise.Ensure(__func__)
|
||||
|
@ -663,6 +665,21 @@ RefPtr<MediaDataDecoder::DecodePromise> RemoteDataDecoder::Decode(
|
|||
});
|
||||
}
|
||||
|
||||
void RemoteDataDecoder::UpdatePendingInputStatus(PendingOp aOp) {
|
||||
AssertOnTaskQueue();
|
||||
switch (aOp) {
|
||||
case PendingOp::INCREASE:
|
||||
mNumPendingInputs++;
|
||||
break;
|
||||
case PendingOp::DECREASE:
|
||||
mNumPendingInputs--;
|
||||
break;
|
||||
case PendingOp::CLEAR:
|
||||
mNumPendingInputs = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteDataDecoder::UpdateInputStatus(int64_t aTimestamp, bool aProcessed) {
|
||||
if (!mTaskQueue->IsCurrentThreadIn()) {
|
||||
nsresult rv = mTaskQueue->Dispatch(NewRunnableMethod<int64_t, bool>(
|
||||
|
@ -673,18 +690,17 @@ void RemoteDataDecoder::UpdateInputStatus(int64_t aTimestamp, bool aProcessed) {
|
|||
return;
|
||||
}
|
||||
AssertOnTaskQueue();
|
||||
if (mShutdown) {
|
||||
if (GetState() == State::SHUTDOWN) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aProcessed) {
|
||||
mNumPendingInputs++;
|
||||
} else if (mNumPendingInputs > 0) {
|
||||
mNumPendingInputs--;
|
||||
UpdatePendingInputStatus(PendingOp::INCREASE);
|
||||
} else if (HasPendingInputs()) {
|
||||
UpdatePendingInputStatus(PendingOp::DECREASE);
|
||||
}
|
||||
|
||||
if (mNumPendingInputs ==
|
||||
0 || // Input has been processed, request the next one.
|
||||
if (!HasPendingInputs() || // Input has been processed, request the next one.
|
||||
!mDecodedData.IsEmpty()) { // Previous output arrived before Decode().
|
||||
ReturnDecodedData();
|
||||
}
|
||||
|
@ -692,7 +708,7 @@ void RemoteDataDecoder::UpdateInputStatus(int64_t aTimestamp, bool aProcessed) {
|
|||
|
||||
void RemoteDataDecoder::UpdateOutputStatus(RefPtr<MediaData>&& aSample) {
|
||||
AssertOnTaskQueue();
|
||||
if (mShutdown) {
|
||||
if (GetState() == State::SHUTDOWN) {
|
||||
return;
|
||||
}
|
||||
if (IsUsefulData(aSample)) {
|
||||
|
@ -703,15 +719,14 @@ void RemoteDataDecoder::UpdateOutputStatus(RefPtr<MediaData>&& aSample) {
|
|||
|
||||
void RemoteDataDecoder::ReturnDecodedData() {
|
||||
AssertOnTaskQueue();
|
||||
MOZ_ASSERT(!mShutdown);
|
||||
MOZ_ASSERT(GetState() != State::SHUTDOWN);
|
||||
|
||||
// We only want to clear mDecodedData when we have resolved the promises.
|
||||
if (!mDecodePromise.IsEmpty()) {
|
||||
mDecodePromise.Resolve(std::move(mDecodedData), __func__);
|
||||
mDecodedData = DecodedData();
|
||||
} else if (!mDrainPromise.IsEmpty() &&
|
||||
(!mDecodedData.IsEmpty() ||
|
||||
mDrainStatus == DrainStatus::DRAINED)) {
|
||||
(!mDecodedData.IsEmpty() || GetState() == State::DRAINED)) {
|
||||
mDrainPromise.Resolve(std::move(mDecodedData), __func__);
|
||||
mDecodedData = DecodedData();
|
||||
}
|
||||
|
@ -727,10 +742,10 @@ void RemoteDataDecoder::DrainComplete() {
|
|||
return;
|
||||
}
|
||||
AssertOnTaskQueue();
|
||||
if (mShutdown) {
|
||||
if (GetState() == State::SHUTDOWN) {
|
||||
return;
|
||||
}
|
||||
mDrainStatus = DrainStatus::DRAINED;
|
||||
SetState(State::DRAINED);
|
||||
ReturnDecodedData();
|
||||
// Make decoder accept input again.
|
||||
mJavaDecoder->Flush();
|
||||
|
@ -745,7 +760,7 @@ void RemoteDataDecoder::Error(const MediaResult& aError) {
|
|||
return;
|
||||
}
|
||||
AssertOnTaskQueue();
|
||||
if (mShutdown) {
|
||||
if (GetState() == State::SHUTDOWN) {
|
||||
return;
|
||||
}
|
||||
mDecodePromise.RejectIfExists(aError, __func__);
|
||||
|
|
|
@ -51,6 +51,16 @@ class RemoteDataDecoder : public MediaDataDecoder,
|
|||
void Error(const MediaResult& aError);
|
||||
void AssertOnTaskQueue() { MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); }
|
||||
|
||||
enum class State { DRAINED, DRAINABLE, DRAINING, SHUTDOWN };
|
||||
void SetState(State aState) {
|
||||
AssertOnTaskQueue();
|
||||
mState = aState;
|
||||
}
|
||||
State GetState() {
|
||||
AssertOnTaskQueue();
|
||||
return mState;
|
||||
}
|
||||
|
||||
// Whether the sample will be used.
|
||||
virtual bool IsUsefulData(const RefPtr<MediaData>& aSample) { return true; }
|
||||
|
||||
|
@ -64,17 +74,20 @@ class RemoteDataDecoder : public MediaDataDecoder,
|
|||
nsString mDrmStubId;
|
||||
|
||||
RefPtr<TaskQueue> mTaskQueue;
|
||||
// Only ever accessed on mTaskqueue.
|
||||
bool mShutdown = false;
|
||||
|
||||
private:
|
||||
enum class PendingOp { INCREASE, DECREASE, CLEAR };
|
||||
void UpdatePendingInputStatus(PendingOp aOp);
|
||||
size_t HasPendingInputs() {
|
||||
AssertOnTaskQueue();
|
||||
return mNumPendingInputs > 0;
|
||||
}
|
||||
|
||||
// The following members must only be accessed on mTaskqueue.
|
||||
MozPromiseHolder<DecodePromise> mDecodePromise;
|
||||
MozPromiseHolder<DecodePromise> mDrainPromise;
|
||||
enum class DrainStatus {
|
||||
DRAINED,
|
||||
DRAINABLE,
|
||||
DRAINING,
|
||||
};
|
||||
DrainStatus mDrainStatus = DrainStatus::DRAINED;
|
||||
DecodedData mDecodedData;
|
||||
State mState = State::DRAINED;
|
||||
size_t mNumPendingInputs;
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче