/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */ #include "RemoteMediaDataDecoder.h" #include "RemoteDecoderChild.h" #include "RemoteDecoderManagerChild.h" namespace mozilla { #ifdef LOG # undef LOG #endif // LOG #define LOG(arg, ...) \ DDMOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, "::%s: " arg, __func__, \ ##__VA_ARGS__) RemoteMediaDataDecoder::RemoteMediaDataDecoder(RemoteDecoderChild* aChild) : mChild(aChild) { LOG("%p is created", this); } RemoteMediaDataDecoder::~RemoteMediaDataDecoder() { if (mChild) { // Shutdown didn't get called. This can happen if the creation of the // decoder got interrupted while pending. nsCOMPtr thread = RemoteDecoderManagerChild::GetManagerThread(); MOZ_ASSERT(thread); thread->Dispatch(NS_NewRunnableFunction( "RemoteMediaDataDecoderShutdown", [child = std::move(mChild), thread] { child->Shutdown()->Then( thread, __func__, [child](const ShutdownPromise::ResolveOrRejectValue& aValue) { child->DestroyIPDL(); }); })); } LOG("%p is released", this); } RefPtr RemoteMediaDataDecoder::Init() { RefPtr self = this; return InvokeAsync(RemoteDecoderManagerChild::GetManagerThread(), __func__, [self]() { return self->mChild->Init(); }) ->Then( RemoteDecoderManagerChild::GetManagerThread(), __func__, [self, this](TrackType aTrack) { // If shutdown has started in the meantime shutdown promise may // be resloved before this task. In this case mChild will be null // and the init promise has to be canceled. if (!mChild) { return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED, __func__); } mDescription = mChild->GetDescriptionName(); mProcessName = mChild->GetProcessName(); mCodecName = mChild->GetCodecName(); mIsHardwareAccelerated = mChild->IsHardwareAccelerated(mHardwareAcceleratedReason); mConversion = mChild->NeedsConversion(); LOG("%p RemoteDecoderChild has been initialized - description: %s, " "process: %s, codec: %s", this, mDescription.get(), mProcessName.get(), mCodecName.get()); return InitPromise::CreateAndResolve(aTrack, __func__); }, [self](const MediaResult& aError) { return InitPromise::CreateAndReject(aError, __func__); }); } RefPtr RemoteMediaDataDecoder::Decode( MediaRawData* aSample) { RefPtr self = this; RefPtr sample = aSample; return InvokeAsync( RemoteDecoderManagerChild::GetManagerThread(), __func__, [self, sample]() { return self->mChild->Decode(nsTArray>{sample}); }); } RefPtr RemoteMediaDataDecoder::DecodeBatch( nsTArray>&& aSamples) { RefPtr self = this; return InvokeAsync(RemoteDecoderManagerChild::GetManagerThread(), __func__, [self, samples = std::move(aSamples)]() { return self->mChild->Decode(samples); }); } RefPtr RemoteMediaDataDecoder::Flush() { RefPtr self = this; return InvokeAsync(RemoteDecoderManagerChild::GetManagerThread(), __func__, [self]() { return self->mChild->Flush(); }); } RefPtr RemoteMediaDataDecoder::Drain() { RefPtr self = this; return InvokeAsync(RemoteDecoderManagerChild::GetManagerThread(), __func__, [self]() { return self->mChild->Drain(); }); } RefPtr RemoteMediaDataDecoder::Shutdown() { RefPtr self = this; return InvokeAsync( RemoteDecoderManagerChild::GetManagerThread(), __func__, [self]() { RefPtr p = self->mChild->Shutdown(); // We're about to be destroyed and drop our ref to // *DecoderChild. Make sure we put a ref into the // task queue for the *DecoderChild thread to keep // it alive until we send the delete message. p->Then(RemoteDecoderManagerChild::GetManagerThread(), __func__, [child = std::move(self->mChild)]( const ShutdownPromise::ResolveOrRejectValue& aValue) { MOZ_ASSERT(aValue.IsResolve()); child->DestroyIPDL(); return ShutdownPromise::CreateAndResolveOrReject(aValue, __func__); }); return p; }); } bool RemoteMediaDataDecoder::IsHardwareAccelerated( nsACString& aFailureReason) const { aFailureReason = mHardwareAcceleratedReason; return mIsHardwareAccelerated; } void RemoteMediaDataDecoder::SetSeekThreshold(const media::TimeUnit& aTime) { RefPtr self = this; media::TimeUnit time = aTime; RemoteDecoderManagerChild::GetManagerThread()->Dispatch( NS_NewRunnableFunction("dom::RemoteMediaDataDecoder::SetSeekThreshold", [=]() { MOZ_ASSERT(self->mChild); self->mChild->SetSeekThreshold(time); }), NS_DISPATCH_NORMAL); } MediaDataDecoder::ConversionRequired RemoteMediaDataDecoder::NeedsConversion() const { return mConversion; } nsCString RemoteMediaDataDecoder::GetDescriptionName() const { return mDescription; } nsCString RemoteMediaDataDecoder::GetProcessName() const { return mProcessName; } nsCString RemoteMediaDataDecoder::GetCodecName() const { return mCodecName; } #undef LOG } // namespace mozilla