From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- dom/media/gmp/GMPContentParent.cpp | 204 +++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 dom/media/gmp/GMPContentParent.cpp (limited to 'dom/media/gmp/GMPContentParent.cpp') diff --git a/dom/media/gmp/GMPContentParent.cpp b/dom/media/gmp/GMPContentParent.cpp new file mode 100644 index 0000000000..153d4da7fe --- /dev/null +++ b/dom/media/gmp/GMPContentParent.cpp @@ -0,0 +1,204 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 "GMPContentParent.h" +#include "GMPLog.h" +#include "GMPParent.h" +#include "GMPServiceChild.h" +#include "GMPVideoDecoderParent.h" +#include "GMPVideoEncoderParent.h" +#include "ChromiumCDMParent.h" +#include "mozIGeckoMediaPluginService.h" +#include "mozilla/Logging.h" +#include "mozilla/Unused.h" +#include "base/task.h" + +namespace mozilla::gmp { + +static const char* GetBoolString(bool aBool) { + return aBool ? "true" : "false"; +} + +GMPContentParent::GMPContentParent(GMPParent* aParent) + : mParent(aParent), mPluginId(0) { + GMP_LOG_DEBUG("GMPContentParent::GMPContentParent(this=%p), aParent=%p", this, + aParent); + if (mParent) { + SetDisplayName(mParent->GetDisplayName()); + SetPluginId(mParent->GetPluginId()); + SetPluginType(mParent->GetPluginType()); + } +} + +GMPContentParent::~GMPContentParent() { + GMP_LOG_DEBUG( + "GMPContentParent::~GMPContentParent(this=%p) mVideoDecoders.IsEmpty=%s, " + "mVideoEncoders.IsEmpty=%s, mChromiumCDMs.IsEmpty=%s, " + "mCloseBlockerCount=%" PRIu32, + this, GetBoolString(mVideoDecoders.IsEmpty()), + GetBoolString(mVideoEncoders.IsEmpty()), + GetBoolString(mChromiumCDMs.IsEmpty()), mCloseBlockerCount); +} + +void GMPContentParent::ActorDestroy(ActorDestroyReason aWhy) { + GMP_LOG_DEBUG("GMPContentParent::ActorDestroy(this=%p, aWhy=%d)", this, + static_cast(aWhy)); + MOZ_ASSERT(mVideoDecoders.IsEmpty() && mVideoEncoders.IsEmpty() && + mChromiumCDMs.IsEmpty()); +} + +void GMPContentParent::CheckThread() { + MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread()); +} + +void GMPContentParent::ChromiumCDMDestroyed(ChromiumCDMParent* aCDM) { + GMP_LOG_DEBUG("GMPContentParent::ChromiumCDMDestroyed(this=%p, aCDM=%p)", + this, aCDM); + MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread()); + + MOZ_ALWAYS_TRUE(mChromiumCDMs.RemoveElement(aCDM)); + CloseIfUnused(); +} + +void GMPContentParent::VideoDecoderDestroyed(GMPVideoDecoderParent* aDecoder) { + GMP_LOG_DEBUG("GMPContentParent::VideoDecoderDestroyed(this=%p, aDecoder=%p)", + this, aDecoder); + MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread()); + + // If the constructor fails, we'll get called before it's added + Unused << NS_WARN_IF(!mVideoDecoders.RemoveElement(aDecoder)); + CloseIfUnused(); +} + +void GMPContentParent::VideoEncoderDestroyed(GMPVideoEncoderParent* aEncoder) { + GMP_LOG_DEBUG("GMPContentParent::VideoEncoderDestroyed(this=%p, aEncoder=%p)", + this, aEncoder); + MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread()); + + // If the constructor fails, we'll get called before it's added + Unused << NS_WARN_IF(!mVideoEncoders.RemoveElement(aEncoder)); + CloseIfUnused(); +} + +void GMPContentParent::AddCloseBlocker() { + MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread()); + ++mCloseBlockerCount; + GMP_LOG_DEBUG( + "GMPContentParent::AddCloseBlocker(this=%p) mCloseBlockerCount=%" PRIu32, + this, mCloseBlockerCount); +} + +void GMPContentParent::RemoveCloseBlocker() { + MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread()); + --mCloseBlockerCount; + GMP_LOG_DEBUG( + "GMPContentParent::RemoveCloseBlocker(this=%p) " + "mCloseBlockerCount=%" PRIu32, + this, mCloseBlockerCount); + CloseIfUnused(); +} + +void GMPContentParent::CloseIfUnused() { + MOZ_ASSERT(GMPEventTarget()->IsOnCurrentThread()); + GMP_LOG_DEBUG( + "GMPContentParent::CloseIfUnused(this=%p) mVideoDecoders.IsEmpty=%s, " + "mVideoEncoders.IsEmpty=%s, mChromiumCDMs.IsEmpty=%s, " + "mCloseBlockerCount=%" PRIu32, + this, GetBoolString(mVideoDecoders.IsEmpty()), + GetBoolString(mVideoEncoders.IsEmpty()), + GetBoolString(mChromiumCDMs.IsEmpty()), mCloseBlockerCount); + if (mVideoDecoders.IsEmpty() && mVideoEncoders.IsEmpty() && + mChromiumCDMs.IsEmpty() && mCloseBlockerCount == 0) { + RefPtr toClose; + if (mParent) { + toClose = mParent->ForgetGMPContentParent(); + } else { + toClose = this; + RefPtr gmp( + GeckoMediaPluginServiceChild::GetSingleton()); + if (gmp) { + gmp->RemoveGMPContentParent(toClose); + } + } + NS_DispatchToCurrentThread(NewRunnableMethod( + "gmp::GMPContentParent::Close", toClose, &GMPContentParent::Close)); + } +} + +nsCOMPtr GMPContentParent::GMPEventTarget() { + if (!mGMPEventTarget) { + GMP_LOG_DEBUG("GMPContentParent::GMPEventTarget(this=%p)", this); + nsCOMPtr mps = + do_GetService("@mozilla.org/gecko-media-plugin-service;1"); + MOZ_ASSERT(mps); + if (!mps) { + return nullptr; + } + // Not really safe if we just grab to the mGMPEventTarget, as we don't know + // what thread we're running on and other threads may be trying to + // access this without locks! However, debug only, and primary failure + // mode outside of compiler-helped TSAN is a leak. But better would be + // to use swap() under a lock. + nsCOMPtr gmpThread; + mps->GetThread(getter_AddRefs(gmpThread)); + MOZ_ASSERT(gmpThread); + + mGMPEventTarget = gmpThread; + } + + return mGMPEventTarget; +} + +already_AddRefed GMPContentParent::GetChromiumCDM( + const nsCString& aKeySystem) { + GMP_LOG_DEBUG("GMPContentParent::GetChromiumCDM(this=%p aKeySystem=%s)", this, + aKeySystem.get()); + + RefPtr parent = new ChromiumCDMParent(this, GetPluginId()); + if (!SendPChromiumCDMConstructor(parent, aKeySystem)) { + return nullptr; + } + + // TODO: Remove parent from mChromiumCDMs in ChromiumCDMParent::Destroy(). + mChromiumCDMs.AppendElement(parent); + + return parent.forget(); +} + +nsresult GMPContentParent::GetGMPVideoDecoder(GMPVideoDecoderParent** aGMPVD) { + GMP_LOG_DEBUG("GMPContentParent::GetGMPVideoDecoder(this=%p)", this); + + RefPtr vdp = new GMPVideoDecoderParent(this); + if (!SendPGMPVideoDecoderConstructor(vdp)) { + return NS_ERROR_FAILURE; + } + + // This addref corresponds to the Proxy pointer the consumer is returned. + // It's dropped by calling Close() on the interface. + vdp.get()->AddRef(); + *aGMPVD = vdp; + mVideoDecoders.AppendElement(vdp); + + return NS_OK; +} + +nsresult GMPContentParent::GetGMPVideoEncoder(GMPVideoEncoderParent** aGMPVE) { + GMP_LOG_DEBUG("GMPContentParent::GetGMPVideoEncoder(this=%p)", this); + + RefPtr vep = new GMPVideoEncoderParent(this); + if (!SendPGMPVideoEncoderConstructor(vep)) { + return NS_ERROR_FAILURE; + } + + // This addref corresponds to the Proxy pointer the consumer is returned. + // It's dropped by calling Close() on the interface. + vep.get()->AddRef(); + *aGMPVE = vep; + mVideoEncoders.AppendElement(vep); + + return NS_OK; +} + +} // namespace mozilla::gmp -- cgit v1.2.3