/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=99: */ /* 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 "RemoteVideoDecoder.h" #include "VideoDecoderChild.h" #include "VideoDecoderManagerChild.h" #include "mozilla/layers/TextureClient.h" #include "base/thread.h" #include "MediaInfo.h" #include "MediaPrefs.h" #include "ImageContainer.h" #include "mozilla/layers/SynchronousTask.h" namespace mozilla { namespace dom { using base::Thread; using namespace ipc; using namespace layers; using namespace gfx; RemoteVideoDecoder::RemoteVideoDecoder(MediaDataDecoderCallback* aCallback) : mActor(new VideoDecoderChild()) { #ifdef DEBUG mCallback = aCallback; #endif MOZ_ASSERT(mCallback->OnReaderTaskQueue()); } RemoteVideoDecoder::~RemoteVideoDecoder() { // We're about to be destroyed and drop our ref to // VideoDecoderChild. Make sure we put a ref into the // task queue for the VideoDecoderChild thread to keep // it alive until we send the delete message. RefPtr<VideoDecoderChild> actor = mActor; VideoDecoderManagerChild::GetManagerThread()->Dispatch(NS_NewRunnableFunction([actor]() { MOZ_ASSERT(actor); actor->DestroyIPDL(); }), NS_DISPATCH_NORMAL); } RefPtr<MediaDataDecoder::InitPromise> RemoteVideoDecoder::Init() { MOZ_ASSERT(mCallback->OnReaderTaskQueue()); return InvokeAsync(VideoDecoderManagerChild::GetManagerAbstractThread(), this, __func__, &RemoteVideoDecoder::InitInternal); } RefPtr<MediaDataDecoder::InitPromise> RemoteVideoDecoder::InitInternal() { MOZ_ASSERT(mActor); MOZ_ASSERT(NS_GetCurrentThread() == VideoDecoderManagerChild::GetManagerThread()); return mActor->Init(); } void RemoteVideoDecoder::Input(MediaRawData* aSample) { MOZ_ASSERT(mCallback->OnReaderTaskQueue()); RefPtr<RemoteVideoDecoder> self = this; RefPtr<MediaRawData> sample = aSample; VideoDecoderManagerChild::GetManagerThread()->Dispatch(NS_NewRunnableFunction([self, sample]() { MOZ_ASSERT(self->mActor); self->mActor->Input(sample); }), NS_DISPATCH_NORMAL); } void RemoteVideoDecoder::Flush() { MOZ_ASSERT(mCallback->OnReaderTaskQueue()); RefPtr<RemoteVideoDecoder> self = this; VideoDecoderManagerChild::GetManagerThread()->Dispatch(NS_NewRunnableFunction([self]() { MOZ_ASSERT(self->mActor); self->mActor->Flush(); }), NS_DISPATCH_NORMAL); } void RemoteVideoDecoder::Drain() { MOZ_ASSERT(mCallback->OnReaderTaskQueue()); RefPtr<RemoteVideoDecoder> self = this; VideoDecoderManagerChild::GetManagerThread()->Dispatch(NS_NewRunnableFunction([self]() { MOZ_ASSERT(self->mActor); self->mActor->Drain(); }), NS_DISPATCH_NORMAL); } void RemoteVideoDecoder::Shutdown() { MOZ_ASSERT(mCallback->OnReaderTaskQueue()); SynchronousTask task("Shutdown"); RefPtr<RemoteVideoDecoder> self = this; VideoDecoderManagerChild::GetManagerThread()->Dispatch(NS_NewRunnableFunction([&]() { AutoCompleteTask complete(&task); MOZ_ASSERT(self->mActor); self->mActor->Shutdown(); }), NS_DISPATCH_NORMAL); task.Wait(); } bool RemoteVideoDecoder::IsHardwareAccelerated(nsACString& aFailureReason) const { MOZ_ASSERT(mCallback->OnReaderTaskQueue()); return mActor->IsHardwareAccelerated(aFailureReason); } void RemoteVideoDecoder::SetSeekThreshold(const media::TimeUnit& aTime) { MOZ_ASSERT(mCallback->OnReaderTaskQueue()); RefPtr<RemoteVideoDecoder> self = this; media::TimeUnit time = aTime; VideoDecoderManagerChild::GetManagerThread()->Dispatch(NS_NewRunnableFunction([=]() { MOZ_ASSERT(self->mActor); self->mActor->SetSeekThreshold(time); }), NS_DISPATCH_NORMAL); } nsresult RemoteDecoderModule::Startup() { if (!VideoDecoderManagerChild::GetManagerThread()) { return NS_ERROR_FAILURE; } return mWrapped->Startup(); } bool RemoteDecoderModule::SupportsMimeType(const nsACString& aMimeType, DecoderDoctorDiagnostics* aDiagnostics) const { return mWrapped->SupportsMimeType(aMimeType, aDiagnostics); } PlatformDecoderModule::ConversionRequired RemoteDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const { return mWrapped->DecoderNeedsConversion(aConfig); } already_AddRefed<MediaDataDecoder> RemoteDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams) { if (!MediaPrefs::PDMUseGPUDecoder() || !aParams.mKnowsCompositor || aParams.mKnowsCompositor->GetTextureFactoryIdentifier().mParentProcessType != GeckoProcessType_GPU) { return mWrapped->CreateVideoDecoder(aParams); } MediaDataDecoderCallback* callback = aParams.mCallback; MOZ_ASSERT(callback->OnReaderTaskQueue()); RefPtr<RemoteVideoDecoder> object = new RemoteVideoDecoder(callback); VideoInfo info = aParams.VideoConfig(); TextureFactoryIdentifier ident = aParams.mKnowsCompositor->GetTextureFactoryIdentifier(); VideoDecoderManagerChild::GetManagerThread()->Dispatch(NS_NewRunnableFunction([=]() { object->mActor->InitIPDL(callback, info, ident); }), NS_DISPATCH_NORMAL); return object.forget(); } } // namespace dom } // namespace mozilla