mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Backed out 12 changesets (bug 1471535) for VideoDecoderChild failures CLOSED TREE
Backed out changeset 3d8a11458d79 (bug 1471535) Backed out changeset 2176010bc1fe (bug 1471535) Backed out changeset dfb4d3462b22 (bug 1471535) Backed out changeset ea6b73ded74d (bug 1471535) Backed out changeset 404d760a9e82 (bug 1471535) Backed out changeset 28ae4b6fab68 (bug 1471535) Backed out changeset af91e1f04c2d (bug 1471535) Backed out changeset d39fef4334b3 (bug 1471535) Backed out changeset a038821cd8ae (bug 1471535) Backed out changeset 5dcc74a938c6 (bug 1471535) Backed out changeset 53aff7e699b4 (bug 1471535) Backed out changeset f3f6abc052f0 (bug 1471535) --HG-- rename : dom/media/ipc/GpuDecoderModule.cpp => dom/media/ipc/RemoteVideoDecoder.cpp rename : dom/media/ipc/GpuDecoderModule.h => dom/media/ipc/RemoteVideoDecoder.h
This commit is contained in:
parent
d9766a1241
commit
fc8134a16a
@ -20,7 +20,6 @@
|
||||
#include "mozilla/NullPrincipal.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/ProcessHangMonitorIPC.h"
|
||||
#include "mozilla/RemoteDecoderManagerChild.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/StaticPrefs.h"
|
||||
#include "mozilla/TelemetryIPC.h"
|
||||
@ -1511,14 +1510,6 @@ ContentChild::RecvReinitRenderingForDeviceReset()
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentChild::RecvInitRemoteDecoder(
|
||||
Endpoint<PRemoteDecoderManagerChild>&& aRemoteManager)
|
||||
{
|
||||
RemoteDecoderManagerChild::InitForContent(std::move(aRemoteManager));
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
|
||||
extern "C" {
|
||||
CGError
|
||||
|
@ -211,10 +211,6 @@ public:
|
||||
|
||||
mozilla::ipc::IPCResult RecvReinitRenderingForDeviceReset() override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
RecvInitRemoteDecoder(
|
||||
Endpoint<PRemoteDecoderManagerChild>&& aRemoteManager) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvSetProcessSandbox(const MaybeFileDesc& aBroker) override;
|
||||
|
||||
virtual PBrowserChild* AllocPBrowserChild(const TabId& aTabId,
|
||||
|
@ -95,7 +95,6 @@
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/ProcessHangMonitor.h"
|
||||
#include "mozilla/ProcessHangMonitorIPC.h"
|
||||
#include "mozilla/RDDProcessManager.h"
|
||||
#include "mozilla/recordreplay/ParentIPC.h"
|
||||
#include "mozilla/Scheduler.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
@ -2656,23 +2655,6 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority)
|
||||
|
||||
gpm->AddListener(this);
|
||||
|
||||
if (StaticPrefs::MediaRddProcessEnabled()) {
|
||||
RDDProcessManager* rdd = RDDProcessManager::Get();
|
||||
|
||||
Endpoint<PRemoteDecoderManagerChild> remoteManager;
|
||||
bool rddOpened = rdd->CreateContentBridge(OtherPid(),
|
||||
&remoteManager);
|
||||
MOZ_ASSERT(rddOpened);
|
||||
|
||||
if (rddOpened) {
|
||||
// not using std::move here (like in SendInitRendering above) because
|
||||
// clang-tidy says:
|
||||
// Warning: Passing result of std::move() as a const reference
|
||||
// argument; no move will actually happen
|
||||
Unused << SendInitRemoteDecoder(remoteManager);
|
||||
}
|
||||
}
|
||||
|
||||
nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
|
||||
if (sheetService) {
|
||||
// This looks like a lot of work, but in a normal browser session we just
|
||||
|
@ -5,7 +5,6 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MemoryReportRequest.h"
|
||||
#include "mozilla/RDDParent.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/gfx/GPUParent.h"
|
||||
@ -127,9 +126,6 @@ public:
|
||||
case GeckoProcessType_GPU:
|
||||
Unused << gfx::GPUParent::GetSingleton()->SendAddMemoryReport(memreport);
|
||||
break;
|
||||
case GeckoProcessType_RDD:
|
||||
Unused << RDDParent::GetSingleton()->SendAddMemoryReport(memreport);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unhandled process type");
|
||||
}
|
||||
@ -167,9 +163,6 @@ public:
|
||||
case GeckoProcessType_GPU:
|
||||
sent = gfx::GPUParent::GetSingleton()->SendFinishMemoryReport(mGeneration);
|
||||
break;
|
||||
case GeckoProcessType_RDD:
|
||||
sent = RDDParent::GetSingleton()->SendFinishMemoryReport(mGeneration);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unhandled process type");
|
||||
}
|
||||
|
@ -43,7 +43,6 @@ include protocol PURLClassifier;
|
||||
include protocol PURLClassifierLocal;
|
||||
include protocol PVRManager;
|
||||
include protocol PVideoDecoderManager;
|
||||
include protocol PRemoteDecoderManager;
|
||||
include protocol PProfiler;
|
||||
include protocol PScriptCache;
|
||||
include DOMTypes;
|
||||
@ -398,8 +397,6 @@ child:
|
||||
// Re-create the rendering stack for a device reset.
|
||||
async ReinitRenderingForDeviceReset();
|
||||
|
||||
async InitRemoteDecoder(Endpoint<PRemoteDecoderManagerChild> decoder);
|
||||
|
||||
/**
|
||||
* Enable system-level sandboxing features, if available. Can
|
||||
* usually only be performed zero or one times. The child may
|
||||
|
@ -1,98 +0,0 @@
|
||||
/* -*- 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 "GpuDecoderModule.h"
|
||||
|
||||
#include "base/thread.h"
|
||||
#include "mozilla/layers/SynchronousTask.h"
|
||||
#include "mozilla/StaticPrefs.h"
|
||||
|
||||
#include "RemoteMediaDataDecoder.h"
|
||||
#include "VideoDecoderChild.h"
|
||||
#include "VideoDecoderManagerChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using base::Thread;
|
||||
using dom::VideoDecoderChild;
|
||||
using dom::VideoDecoderManagerChild;
|
||||
using namespace ipc;
|
||||
using namespace layers;
|
||||
using namespace gfx;
|
||||
|
||||
nsresult
|
||||
GpuDecoderModule::Startup()
|
||||
{
|
||||
if (!VideoDecoderManagerChild::GetManagerThread()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mWrapped->Startup();
|
||||
}
|
||||
|
||||
bool
|
||||
GpuDecoderModule::SupportsMimeType(const nsACString& aMimeType,
|
||||
DecoderDoctorDiagnostics* aDiagnostics) const
|
||||
{
|
||||
return mWrapped->SupportsMimeType(aMimeType, aDiagnostics);
|
||||
}
|
||||
|
||||
bool
|
||||
GpuDecoderModule::Supports(const TrackInfo& aTrackInfo,
|
||||
DecoderDoctorDiagnostics* aDiagnostics) const
|
||||
{
|
||||
return mWrapped->Supports(aTrackInfo, aDiagnostics);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsRemoteAcceleratedCompositor(KnowsCompositor* aKnows)
|
||||
{
|
||||
TextureFactoryIdentifier ident = aKnows->GetTextureFactoryIdentifier();
|
||||
return ident.mParentBackend != LayersBackend::LAYERS_BASIC &&
|
||||
ident.mParentProcessType == GeckoProcessType_GPU;
|
||||
}
|
||||
|
||||
already_AddRefed<MediaDataDecoder>
|
||||
GpuDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
|
||||
{
|
||||
if (!StaticPrefs::MediaGpuProcessDecoder() ||
|
||||
!aParams.mKnowsCompositor ||
|
||||
!IsRemoteAcceleratedCompositor(aParams.mKnowsCompositor))
|
||||
{
|
||||
return mWrapped->CreateVideoDecoder(aParams);
|
||||
}
|
||||
|
||||
RefPtr<VideoDecoderChild> child = new VideoDecoderChild();
|
||||
RefPtr<RemoteMediaDataDecoder> object = new RemoteMediaDataDecoder(
|
||||
child,
|
||||
VideoDecoderManagerChild::GetManagerThread(),
|
||||
VideoDecoderManagerChild::GetManagerAbstractThread());
|
||||
|
||||
SynchronousTask task("InitIPDL");
|
||||
MediaResult result(NS_OK);
|
||||
VideoDecoderManagerChild::GetManagerThread()->Dispatch(
|
||||
NS_NewRunnableFunction(
|
||||
"dom::GpuDecoderModule::CreateVideoDecoder",
|
||||
[&, child]() {
|
||||
AutoCompleteTask complete(&task);
|
||||
result = child->InitIPDL(
|
||||
aParams.VideoConfig(),
|
||||
aParams.mRate.mValue,
|
||||
aParams.mOptions,
|
||||
aParams.mKnowsCompositor->GetTextureFactoryIdentifier());
|
||||
}),
|
||||
NS_DISPATCH_NORMAL);
|
||||
task.Wait();
|
||||
|
||||
if (NS_FAILED(result)) {
|
||||
if (aParams.mError) {
|
||||
*aParams.mError = result;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return object.forget();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
@ -1,50 +0,0 @@
|
||||
/* -*- 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/. */
|
||||
#ifndef include_dom_media_ipc_GpuDecoderModule_h
|
||||
#define include_dom_media_ipc_GpuDecoderModule_h
|
||||
#include "PlatformDecoderModule.h"
|
||||
|
||||
#include "MediaData.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// A PDM implementation that creates a RemoteMediaDataDecoder (a
|
||||
// MediaDataDecoder) that proxies to a VideoDecoderChild. The
|
||||
// VideoDecoderChild will talk to a VideoDecoderParent running on the
|
||||
// GPU process.
|
||||
// We currently require a 'wrapped' PDM in order to be able to answer
|
||||
// SupportsMimeType and DecoderNeedsConversion. Ideally we'd check these
|
||||
// over IPDL using the manager protocol
|
||||
class GpuDecoderModule : public PlatformDecoderModule
|
||||
{
|
||||
public:
|
||||
explicit GpuDecoderModule(PlatformDecoderModule* aWrapped)
|
||||
: mWrapped(aWrapped)
|
||||
{}
|
||||
|
||||
nsresult Startup() override;
|
||||
|
||||
bool SupportsMimeType(const nsACString& aMimeType,
|
||||
DecoderDoctorDiagnostics* aDiagnostics) const override;
|
||||
bool Supports(const TrackInfo& aTrackInfo,
|
||||
DecoderDoctorDiagnostics* aDiagnostics) const override;
|
||||
|
||||
already_AddRefed<MediaDataDecoder> CreateVideoDecoder(
|
||||
const CreateDecoderParams& aParams) override;
|
||||
|
||||
already_AddRefed<MediaDataDecoder> CreateAudioDecoder(
|
||||
const CreateDecoderParams& aParams) override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<PlatformDecoderModule> mWrapped;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // include_dom_media_ipc_GpuDecoderModule_h
|
@ -1,47 +0,0 @@
|
||||
/* -*- 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/. */
|
||||
#ifndef include_dom_media_ipc_IRemoteDecoderChild_h
|
||||
#define include_dom_media_ipc_IRemoteDecoderChild_h
|
||||
|
||||
#include "PlatformDecoderModule.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// This interface mirrors the MediaDataDecoder plus a bit (DestroyIPDL)
|
||||
// to allow proxying to a remote decoder in RemoteDecoderModule or
|
||||
// GpuDecoderModule. RemoteAudioDecoderChild, RemoteVideoDecoderChild,
|
||||
// and VideoDecoderChild (for GPU) implement this interface.
|
||||
class IRemoteDecoderChild
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(IRemoteDecoderChild);
|
||||
|
||||
virtual RefPtr<MediaDataDecoder::InitPromise> Init() = 0;
|
||||
virtual RefPtr<MediaDataDecoder::DecodePromise> Decode(
|
||||
MediaRawData* aSample) = 0;
|
||||
virtual RefPtr<MediaDataDecoder::DecodePromise> Drain() = 0;
|
||||
virtual RefPtr<MediaDataDecoder::FlushPromise> Flush() = 0;
|
||||
virtual void Shutdown() = 0;
|
||||
virtual bool IsHardwareAccelerated(nsACString& aFailureReason) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual nsCString GetDescriptionName() const = 0;
|
||||
virtual void SetSeekThreshold(const media::TimeUnit& aTime) {}
|
||||
virtual MediaDataDecoder::ConversionRequired NeedsConversion() const
|
||||
{
|
||||
return MediaDataDecoder::ConversionRequired::kNeedNone;
|
||||
}
|
||||
|
||||
virtual void DestroyIPDL() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~IRemoteDecoderChild() {}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // include_dom_media_ipc_IRemoteDecoderChild_h
|
@ -44,49 +44,6 @@ namespace IPC {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<mozilla::AudioInfo>
|
||||
{
|
||||
typedef mozilla::AudioInfo paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
// TrackInfo
|
||||
WriteParam(aMsg, aParam.mMimeType);
|
||||
|
||||
// AudioInfo
|
||||
WriteParam(aMsg, aParam.mRate);
|
||||
WriteParam(aMsg, aParam.mChannels);
|
||||
WriteParam(aMsg, aParam.mChannelMap);
|
||||
WriteParam(aMsg, aParam.mBitDepth);
|
||||
WriteParam(aMsg, aParam.mProfile);
|
||||
WriteParam(aMsg, aParam.mExtendedProfile);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
|
||||
{
|
||||
if (ReadParam(aMsg, aIter, &aResult->mMimeType) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mRate) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mChannels) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mChannelMap) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mBitDepth) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mProfile) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mExtendedProfile)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<mozilla::MediaDataDecoder::ConversionRequired>
|
||||
: public ContiguousEnumSerializerInclusive<
|
||||
mozilla::MediaDataDecoder::ConversionRequired,
|
||||
mozilla::MediaDataDecoder::ConversionRequired(0),
|
||||
mozilla::MediaDataDecoder::ConversionRequired(
|
||||
mozilla::MediaDataDecoder::ConversionRequired::kNeedAnnexB)> {};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif // mozilla_dom_media_MediaIPCUtils_h
|
||||
|
@ -1,23 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
struct MediaDataIPDL
|
||||
{
|
||||
int64_t offset;
|
||||
int64_t time;
|
||||
int64_t timecode;
|
||||
int64_t duration;
|
||||
uint32_t frames;
|
||||
bool keyframe;
|
||||
};
|
||||
|
||||
struct MediaRawDataIPDL
|
||||
{
|
||||
MediaDataIPDL base;
|
||||
Shmem buffer;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
@ -1,47 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; 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 MemoryReportTypes;
|
||||
|
||||
include protocol PProfiler;
|
||||
include protocol PRemoteDecoderManager;
|
||||
|
||||
using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// This protocol allows the UI process to talk to the RDD
|
||||
// (RemoteDataDecoder) process. There is one instance of this protocol,
|
||||
// with the RDDParent living on the main thread of the RDD process and
|
||||
// the RDDChild living on the main thread of the UI process.
|
||||
protocol PRDD
|
||||
{
|
||||
parent:
|
||||
|
||||
// args TBD, sent by UI process to initiate core settings
|
||||
async Init();
|
||||
|
||||
async InitProfiler(Endpoint<PProfilerChild> endpoint);
|
||||
|
||||
async NewContentRemoteDecoderManager(
|
||||
Endpoint<PRemoteDecoderManagerParent> endpoint);
|
||||
|
||||
async RequestMemoryReport(uint32_t generation,
|
||||
bool anonymize,
|
||||
bool minimizeMemoryUsage,
|
||||
MaybeFileDesc DMDFile);
|
||||
|
||||
child:
|
||||
// args TBD, sent when init complete. Occurs once, after Init().
|
||||
async InitComplete();
|
||||
|
||||
async InitCrashReporter(Shmem shmem, NativeThreadId threadId);
|
||||
|
||||
async AddMemoryReport(MemoryReport aReport);
|
||||
async FinishMemoryReport(uint32_t aGeneration);
|
||||
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
@ -1,27 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; 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 protocol PRemoteVideoDecoder;
|
||||
include "mozilla/dom/MediaIPCUtils.h";
|
||||
|
||||
using VideoInfo from "MediaInfo.h";
|
||||
using AudioInfo from "MediaInfo.h";
|
||||
using mozilla::CreateDecoderParams::OptionSet from "PlatformDecoderModule.h";
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
sync protocol PRemoteDecoderManager
|
||||
{
|
||||
manages PRemoteVideoDecoder;
|
||||
|
||||
parent:
|
||||
sync PRemoteVideoDecoder(VideoInfo info,
|
||||
float framerate,
|
||||
OptionSet options)
|
||||
returns (bool success,
|
||||
nsCString aErrorDescription);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
@ -1,60 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; 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 "mozilla/dom/MediaIPCUtils.h";
|
||||
|
||||
include protocol PRemoteDecoderManager;
|
||||
include PMediaDecoderParams;
|
||||
include LayersSurfaces;
|
||||
using mozilla::MediaDataDecoder::ConversionRequired from "PlatformDecoderModule.h";
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
struct RemoteVideoDataIPDL
|
||||
{
|
||||
MediaDataIPDL base;
|
||||
IntSize display;
|
||||
IntSize frameSize;
|
||||
SurfaceDescriptorBuffer sdBuffer;
|
||||
int32_t frameID;
|
||||
};
|
||||
|
||||
// This protocol provides a way to use MediaDataDecoder across processes.
|
||||
// The parent side currently is only implemented to work with
|
||||
// RemoteDecoderModule.
|
||||
// The child side runs in the content process, and the parent side runs
|
||||
// in the RDD process. We run a separate IPDL thread for both sides.
|
||||
async protocol PRemoteVideoDecoder
|
||||
{
|
||||
manager PRemoteDecoderManager;
|
||||
parent:
|
||||
async Init();
|
||||
|
||||
async Input(MediaRawDataIPDL data);
|
||||
|
||||
async Flush();
|
||||
async Drain();
|
||||
async Shutdown();
|
||||
|
||||
async SetSeekThreshold(int64_t time);
|
||||
|
||||
async __delete__();
|
||||
|
||||
child:
|
||||
async InitComplete(nsCString decoderDescription,
|
||||
ConversionRequired conversion);
|
||||
async InitFailed(nsresult reason);
|
||||
|
||||
async FlushComplete();
|
||||
|
||||
// Each output includes a SurfaceDescriptorBuffer that represents the decoded
|
||||
// frame.
|
||||
async VideoOutput(RemoteVideoDataIPDL data);
|
||||
async InputExhausted();
|
||||
async DrainComplete();
|
||||
async Error(nsresult error);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
@ -6,13 +6,22 @@
|
||||
include "mozilla/dom/MediaIPCUtils.h";
|
||||
|
||||
include protocol PVideoDecoderManager;
|
||||
include PMediaDecoderParams;
|
||||
include LayersSurfaces;
|
||||
using mozilla::layers::LayersBackend from "mozilla/layers/LayersTypes.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
struct MediaDataIPDL
|
||||
{
|
||||
int64_t offset;
|
||||
int64_t time;
|
||||
int64_t timecode;
|
||||
int64_t duration;
|
||||
uint32_t frames;
|
||||
bool keyframe;
|
||||
};
|
||||
|
||||
struct VideoDataIPDL
|
||||
{
|
||||
MediaDataIPDL base;
|
||||
@ -22,6 +31,12 @@ struct VideoDataIPDL
|
||||
int32_t frameID;
|
||||
};
|
||||
|
||||
struct MediaRawDataIPDL
|
||||
{
|
||||
MediaDataIPDL base;
|
||||
Shmem buffer;
|
||||
};
|
||||
|
||||
// This protocol provides a way to use MediaDataDecoder across processes.
|
||||
// The parent side currently is only implemented to work with
|
||||
// Window Media Foundation, but can be extended easily to support other backends.
|
||||
|
@ -1,145 +0,0 @@
|
||||
/* -*- 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 "RDDChild.h"
|
||||
|
||||
#include "mozilla/dom/MemoryReportRequest.h"
|
||||
#include "mozilla/ipc/CrashReporterHost.h"
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
#include "ProfilerParent.h"
|
||||
#endif
|
||||
#include "RDDProcessHost.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace layers;
|
||||
|
||||
RDDChild::RDDChild(RDDProcessHost* aHost)
|
||||
: mHost(aHost),
|
||||
mRDDReady(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(RDDChild);
|
||||
}
|
||||
|
||||
RDDChild::~RDDChild()
|
||||
{
|
||||
MOZ_COUNT_DTOR(RDDChild);
|
||||
}
|
||||
|
||||
void
|
||||
RDDChild::Init()
|
||||
{
|
||||
SendInit();
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
Unused << SendInitProfiler(ProfilerParent::CreateForProcess(OtherPid()));
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
RDDChild::EnsureRDDReady()
|
||||
{
|
||||
if (mRDDReady) {
|
||||
return true;
|
||||
}
|
||||
|
||||
mRDDReady = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RDDChild::RecvInitComplete()
|
||||
{
|
||||
// We synchronously requested RDD parameters before this arrived.
|
||||
if (mRDDReady) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mRDDReady = true;
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RDDChild::RecvInitCrashReporter(Shmem&& aShmem, const NativeThreadId& aThreadId)
|
||||
{
|
||||
mCrashReporter = MakeUnique<ipc::CrashReporterHost>(
|
||||
GeckoProcessType_RDD,
|
||||
aShmem,
|
||||
aThreadId);
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
bool
|
||||
RDDChild::SendRequestMemoryReport(const uint32_t& aGeneration,
|
||||
const bool& aAnonymize,
|
||||
const bool& aMinimizeMemoryUsage,
|
||||
const MaybeFileDesc& aDMDFile)
|
||||
{
|
||||
mMemoryReportRequest = MakeUnique<MemoryReportRequestHost>(aGeneration);
|
||||
Unused << PRDDChild::SendRequestMemoryReport(aGeneration,
|
||||
aAnonymize,
|
||||
aMinimizeMemoryUsage,
|
||||
aDMDFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RDDChild::RecvAddMemoryReport(const MemoryReport& aReport)
|
||||
{
|
||||
if (mMemoryReportRequest) {
|
||||
mMemoryReportRequest->RecvReport(aReport);
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RDDChild::RecvFinishMemoryReport(const uint32_t& aGeneration)
|
||||
{
|
||||
if (mMemoryReportRequest) {
|
||||
mMemoryReportRequest->Finish(aGeneration);
|
||||
mMemoryReportRequest = nullptr;
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
RDDChild::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
if (aWhy == AbnormalShutdown) {
|
||||
if (mCrashReporter) {
|
||||
mCrashReporter->GenerateCrashReport(OtherPid());
|
||||
mCrashReporter = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
mHost->OnChannelClosed();
|
||||
}
|
||||
|
||||
class DeferredDeleteRDDChild : public Runnable
|
||||
{
|
||||
public:
|
||||
explicit DeferredDeleteRDDChild(UniquePtr<RDDChild>&& aChild)
|
||||
: Runnable("gfx::DeferredDeleteRDDChild")
|
||||
, mChild(std::move(aChild))
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP Run() override {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
UniquePtr<RDDChild> mChild;
|
||||
};
|
||||
|
||||
/* static */ void
|
||||
RDDChild::Destroy(UniquePtr<RDDChild>&& aChild)
|
||||
{
|
||||
NS_DispatchToMainThread(new DeferredDeleteRDDChild(std::move(aChild)));
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
@ -1,65 +0,0 @@
|
||||
/* -*- 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/. */
|
||||
#ifndef _include_dom_media_ipc_RDDChild_h_
|
||||
#define _include_dom_media_ipc_RDDChild_h_
|
||||
#include "mozilla/PRDDChild.h"
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace ipc {
|
||||
class CrashReporterHost;
|
||||
} // namespace ipc
|
||||
namespace dom {
|
||||
class MemoryReportRequestHost;
|
||||
} // namespace dom
|
||||
|
||||
class RDDProcessHost;
|
||||
|
||||
class RDDChild final : public PRDDChild
|
||||
{
|
||||
typedef mozilla::dom::MemoryReportRequestHost MemoryReportRequestHost;
|
||||
|
||||
public:
|
||||
explicit RDDChild(RDDProcessHost* aHost);
|
||||
~RDDChild();
|
||||
|
||||
void Init();
|
||||
|
||||
bool EnsureRDDReady();
|
||||
|
||||
// PRDDChild overrides.
|
||||
mozilla::ipc::IPCResult RecvInitComplete() override;
|
||||
mozilla::ipc::IPCResult RecvInitCrashReporter(
|
||||
Shmem&& shmem,
|
||||
const NativeThreadId& aThreadId) override;
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
mozilla::ipc::IPCResult RecvAddMemoryReport(
|
||||
const MemoryReport& aReport) override;
|
||||
mozilla::ipc::IPCResult RecvFinishMemoryReport(
|
||||
const uint32_t& aGeneration) override;
|
||||
|
||||
bool SendRequestMemoryReport(const uint32_t& aGeneration,
|
||||
const bool& aAnonymize,
|
||||
const bool& aMinimizeMemoryUsage,
|
||||
const MaybeFileDesc& aDMDFile);
|
||||
|
||||
static void Destroy(UniquePtr<RDDChild>&& aChild);
|
||||
|
||||
private:
|
||||
RDDProcessHost* mHost;
|
||||
UniquePtr<ipc::CrashReporterHost> mCrashReporter;
|
||||
UniquePtr<MemoryReportRequestHost> mMemoryReportRequest;
|
||||
bool mRDDReady;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // _include_dom_media_ipc_RDDChild_h_
|
@ -1,160 +0,0 @@
|
||||
/* -*- 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 "RDDParent.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
# include <process.h>
|
||||
# include <dwrite.h>
|
||||
#endif
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/HangDetails.h"
|
||||
#include "mozilla/RemoteDecoderManagerChild.h"
|
||||
#include "mozilla/RemoteDecoderManagerParent.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/dom/MemoryReportRequest.h"
|
||||
#include "mozilla/ipc/CrashReporterClient.h"
|
||||
#include "mozilla/ipc/ProcessChild.h"
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
#include "ChildProfilerController.h"
|
||||
#endif
|
||||
#include "nsDebugImpl.h"
|
||||
#include "nsThreadManager.h"
|
||||
#include "ProcessUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace ipc;
|
||||
|
||||
static RDDParent* sRDDParent;
|
||||
|
||||
RDDParent::RDDParent()
|
||||
: mLaunchTime(TimeStamp::Now())
|
||||
{
|
||||
sRDDParent = this;
|
||||
}
|
||||
|
||||
RDDParent::~RDDParent()
|
||||
{
|
||||
sRDDParent = nullptr;
|
||||
}
|
||||
|
||||
/* static */ RDDParent*
|
||||
RDDParent::GetSingleton()
|
||||
{
|
||||
return sRDDParent;
|
||||
}
|
||||
|
||||
bool
|
||||
RDDParent::Init(base::ProcessId aParentPid,
|
||||
const char* aParentBuildID,
|
||||
MessageLoop* aIOLoop,
|
||||
IPC::Channel* aChannel)
|
||||
{
|
||||
// Initialize the thread manager before starting IPC. Otherwise, messages
|
||||
// may be posted to the main thread and we won't be able to process them.
|
||||
if (NS_WARN_IF(NS_FAILED(nsThreadManager::get().Init()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now it's safe to start IPC.
|
||||
if (NS_WARN_IF(!Open(aChannel, aParentPid, aIOLoop))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsDebugImpl::SetMultiprocessMode("RDD");
|
||||
|
||||
// This must be checked before any IPDL message, which may hit sentinel
|
||||
// errors due to parent and content processes having different
|
||||
// versions.
|
||||
MessageChannel* channel = GetIPCChannel();
|
||||
if (channel && !channel->SendBuildIDsMatchMessage(aParentBuildID)) {
|
||||
// We need to quit this process if the buildID doesn't match the parent's.
|
||||
// This can occur when an update occurred in the background.
|
||||
ProcessChild::QuickExit();
|
||||
}
|
||||
|
||||
// Init crash reporter support.
|
||||
CrashReporterClient::InitSingleton(this);
|
||||
|
||||
if (NS_FAILED(NS_InitMinimalXPCOM())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mozilla::ipc::SetThisProcessName("RDD Process");
|
||||
return true;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RDDParent::RecvInit()
|
||||
{
|
||||
Unused << SendInitComplete();
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RDDParent::RecvInitProfiler(Endpoint<PProfilerChild>&& aEndpoint)
|
||||
{
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
mProfilerController = ChildProfilerController::Create(std::move(aEndpoint));
|
||||
#endif
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RDDParent::RecvNewContentRemoteDecoderManager(
|
||||
Endpoint<PRemoteDecoderManagerParent>&& aEndpoint)
|
||||
{
|
||||
if (!RemoteDecoderManagerParent::CreateForContent(std::move(aEndpoint))) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RDDParent::RecvRequestMemoryReport(const uint32_t& aGeneration,
|
||||
const bool& aAnonymize,
|
||||
const bool& aMinimizeMemoryUsage,
|
||||
const MaybeFileDesc& aDMDFile)
|
||||
{
|
||||
nsPrintfCString processName("RDD (pid %u)", (unsigned)getpid());
|
||||
|
||||
mozilla::dom::MemoryReportRequestClient::Start(aGeneration,
|
||||
aAnonymize,
|
||||
aMinimizeMemoryUsage,
|
||||
aDMDFile,
|
||||
processName);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
RDDParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
if (AbnormalShutdown == aWhy) {
|
||||
NS_WARNING("Shutting down RDD process early due to a crash!");
|
||||
ProcessChild::QuickExit();
|
||||
}
|
||||
|
||||
#ifndef NS_FREE_PERMANENT_DATA
|
||||
// No point in going through XPCOM shutdown because we don't keep persistent
|
||||
// state.
|
||||
ProcessChild::QuickExit();
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
if (mProfilerController) {
|
||||
mProfilerController->Shutdown();
|
||||
mProfilerController = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
CrashReporterClient::DestroySingleton();
|
||||
XRE_ShutdownChildProcess();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
@ -1,53 +0,0 @@
|
||||
/* -*- 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/. */
|
||||
#ifndef _include_dom_media_ipc_RDDParent_h__
|
||||
#define _include_dom_media_ipc_RDDParent_h__
|
||||
#include "mozilla/PRDDParent.h"
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class TimeStamp;
|
||||
class ChildProfilerController;
|
||||
|
||||
class RDDParent final : public PRDDParent
|
||||
{
|
||||
public:
|
||||
RDDParent();
|
||||
~RDDParent();
|
||||
|
||||
static RDDParent* GetSingleton();
|
||||
|
||||
bool Init(base::ProcessId aParentPid,
|
||||
const char* aParentBuildID,
|
||||
MessageLoop* aIOLoop,
|
||||
IPC::Channel* aChannel);
|
||||
|
||||
mozilla::ipc::IPCResult RecvInit() override;
|
||||
mozilla::ipc::IPCResult RecvInitProfiler(
|
||||
Endpoint<PProfilerChild>&& aEndpoint) override;
|
||||
|
||||
mozilla::ipc::IPCResult RecvNewContentRemoteDecoderManager(
|
||||
Endpoint<PRemoteDecoderManagerParent>&& aEndpoint) override;
|
||||
mozilla::ipc::IPCResult RecvRequestMemoryReport(
|
||||
const uint32_t& generation,
|
||||
const bool& anonymize,
|
||||
const bool& minimizeMemoryUsage,
|
||||
const MaybeFileDesc& DMDFile) override;
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
private:
|
||||
const TimeStamp mLaunchTime;
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
RefPtr<ChildProfilerController> mProfilerController;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // _include_dom_media_ipc_RDDParent_h__
|
@ -1,257 +0,0 @@
|
||||
/* -*- 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 "RDDProcessHost.h"
|
||||
|
||||
#include "chrome/common/process_watcher.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/StaticPrefs.h"
|
||||
|
||||
#include "RDDChild.h"
|
||||
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace ipc;
|
||||
|
||||
RDDProcessHost::RDDProcessHost(Listener* aListener)
|
||||
: GeckoChildProcessHost(GeckoProcessType_RDD),
|
||||
mListener(aListener),
|
||||
mTaskFactory(this),
|
||||
mLaunchPhase(LaunchPhase::Unlaunched),
|
||||
mProcessToken(0),
|
||||
mShutdownRequested(false),
|
||||
mChannelClosed(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(RDDProcessHost);
|
||||
}
|
||||
|
||||
RDDProcessHost::~RDDProcessHost()
|
||||
{
|
||||
MOZ_COUNT_DTOR(RDDProcessHost);
|
||||
}
|
||||
|
||||
bool
|
||||
RDDProcessHost::Launch(StringVector aExtraOpts)
|
||||
{
|
||||
MOZ_ASSERT(mLaunchPhase == LaunchPhase::Unlaunched);
|
||||
MOZ_ASSERT(!mRDDChild);
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
mSandboxLevel = Preferences::GetInt("security.sandbox.rdd.level");
|
||||
#endif
|
||||
|
||||
mLaunchPhase = LaunchPhase::Waiting;
|
||||
mLaunchTime = TimeStamp::Now();
|
||||
|
||||
if (!GeckoChildProcessHost::AsyncLaunch(aExtraOpts)) {
|
||||
mLaunchPhase = LaunchPhase::Complete;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
RDDProcessHost::WaitForLaunch()
|
||||
{
|
||||
if (mLaunchPhase == LaunchPhase::Complete) {
|
||||
return !!mRDDChild;
|
||||
}
|
||||
|
||||
int32_t timeoutMs = StaticPrefs::MediaRddProcessStartupTimeoutMs();
|
||||
|
||||
// If one of the following environment variables are set we can
|
||||
// effectively ignore the timeout - as we can guarantee the RDD
|
||||
// process will be terminated
|
||||
if (PR_GetEnv("MOZ_DEBUG_CHILD_PROCESS") ||
|
||||
PR_GetEnv("MOZ_DEBUG_CHILD_PAUSE")) {
|
||||
timeoutMs = 0;
|
||||
}
|
||||
|
||||
// Our caller expects the connection to be finished after we return, so we
|
||||
// immediately set up the IPDL actor and fire callbacks. The IO thread will
|
||||
// still dispatch a notification to the main thread - we'll just ignore it.
|
||||
bool result = GeckoChildProcessHost::WaitUntilConnected(timeoutMs);
|
||||
InitAfterConnect(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
RDDProcessHost::OnChannelConnected(int32_t peer_pid)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
GeckoChildProcessHost::OnChannelConnected(peer_pid);
|
||||
|
||||
// Post a task to the main thread. Take the lock because mTaskFactory is not
|
||||
// thread-safe.
|
||||
RefPtr<Runnable> runnable;
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
runnable =
|
||||
mTaskFactory.NewRunnableMethod(&RDDProcessHost::OnChannelConnectedTask);
|
||||
}
|
||||
NS_DispatchToMainThread(runnable);
|
||||
}
|
||||
|
||||
void
|
||||
RDDProcessHost::OnChannelError()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
GeckoChildProcessHost::OnChannelError();
|
||||
|
||||
// Post a task to the main thread. Take the lock because mTaskFactory is not
|
||||
// thread-safe.
|
||||
RefPtr<Runnable> runnable;
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
runnable =
|
||||
mTaskFactory.NewRunnableMethod(&RDDProcessHost::OnChannelErrorTask);
|
||||
}
|
||||
NS_DispatchToMainThread(runnable);
|
||||
}
|
||||
|
||||
void
|
||||
RDDProcessHost::OnChannelConnectedTask()
|
||||
{
|
||||
if (mLaunchPhase == LaunchPhase::Waiting) {
|
||||
InitAfterConnect(true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RDDProcessHost::OnChannelErrorTask()
|
||||
{
|
||||
if (mLaunchPhase == LaunchPhase::Waiting) {
|
||||
InitAfterConnect(false);
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t sRDDProcessTokenCounter = 0;
|
||||
|
||||
void
|
||||
RDDProcessHost::InitAfterConnect(bool aSucceeded)
|
||||
{
|
||||
MOZ_ASSERT(mLaunchPhase == LaunchPhase::Waiting);
|
||||
MOZ_ASSERT(!mRDDChild);
|
||||
|
||||
mLaunchPhase = LaunchPhase::Complete;
|
||||
|
||||
if (aSucceeded) {
|
||||
mProcessToken = ++sRDDProcessTokenCounter;
|
||||
mRDDChild = MakeUnique<RDDChild>(this);
|
||||
DebugOnly<bool> rv =
|
||||
mRDDChild->Open(GetChannel(), base::GetProcId(GetChildProcessHandle()));
|
||||
MOZ_ASSERT(rv);
|
||||
|
||||
mRDDChild->Init();
|
||||
}
|
||||
|
||||
if (mListener) {
|
||||
mListener->OnProcessLaunchComplete(this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RDDProcessHost::Shutdown()
|
||||
{
|
||||
MOZ_ASSERT(!mShutdownRequested);
|
||||
|
||||
mListener = nullptr;
|
||||
|
||||
if (mRDDChild) {
|
||||
// OnChannelClosed uses this to check if the shutdown was expected or
|
||||
// unexpected.
|
||||
mShutdownRequested = true;
|
||||
|
||||
// The channel might already be closed if we got here unexpectedly.
|
||||
if (!mChannelClosed) {
|
||||
mRDDChild->Close();
|
||||
}
|
||||
|
||||
#ifndef NS_FREE_PERMANENT_DATA
|
||||
// No need to communicate shutdown, the RDD process doesn't need to
|
||||
// communicate anything back.
|
||||
KillHard("NormalShutdown");
|
||||
#endif
|
||||
|
||||
// If we're shutting down unexpectedly, we're in the middle of handling an
|
||||
// ActorDestroy for PRDDChild, which is still on the stack. We'll return
|
||||
// back to OnChannelClosed.
|
||||
//
|
||||
// Otherwise, we'll wait for OnChannelClose to be called whenever PRDDChild
|
||||
// acknowledges shutdown.
|
||||
return;
|
||||
}
|
||||
|
||||
DestroyProcess();
|
||||
}
|
||||
|
||||
void
|
||||
RDDProcessHost::OnChannelClosed()
|
||||
{
|
||||
mChannelClosed = true;
|
||||
|
||||
if (!mShutdownRequested && mListener) {
|
||||
// This is an unclean shutdown. Notify our listener that we're going away.
|
||||
mListener->OnProcessUnexpectedShutdown(this);
|
||||
} else {
|
||||
DestroyProcess();
|
||||
}
|
||||
|
||||
// Release the actor.
|
||||
RDDChild::Destroy(std::move(mRDDChild));
|
||||
MOZ_ASSERT(!mRDDChild);
|
||||
}
|
||||
|
||||
void
|
||||
RDDProcessHost::KillHard(const char* aReason)
|
||||
{
|
||||
ProcessHandle handle = GetChildProcessHandle();
|
||||
if (!base::KillProcess(handle, base::PROCESS_END_KILLED_BY_USER, false)) {
|
||||
NS_WARNING("failed to kill subprocess!");
|
||||
}
|
||||
|
||||
SetAlreadyDead();
|
||||
}
|
||||
|
||||
uint64_t
|
||||
RDDProcessHost::GetProcessToken() const
|
||||
{
|
||||
return mProcessToken;
|
||||
}
|
||||
|
||||
static void
|
||||
RDDDelayedDeleteSubprocess(GeckoChildProcessHost* aSubprocess)
|
||||
{
|
||||
XRE_GetIOMessageLoop()->
|
||||
PostTask(
|
||||
mozilla::MakeAndAddRef<DeleteTask<GeckoChildProcessHost>>(aSubprocess));
|
||||
}
|
||||
|
||||
void
|
||||
RDDProcessHost::KillProcess()
|
||||
{
|
||||
KillHard("DiagnosticKill");
|
||||
}
|
||||
|
||||
void
|
||||
RDDProcessHost::DestroyProcess()
|
||||
{
|
||||
// Cancel all tasks. We don't want anything triggering after our caller
|
||||
// expects this to go away.
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mTaskFactory.RevokeAll();
|
||||
}
|
||||
|
||||
MessageLoop::current()->
|
||||
PostTask(NewRunnableFunction("DestroyProcessRunnable",
|
||||
RDDDelayedDeleteSubprocess,
|
||||
this));
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
@ -1,143 +0,0 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#ifndef _include_dom_media_ipc_RDDProcessHost_h_
|
||||
#define _include_dom_media_ipc_RDDProcessHost_h_
|
||||
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
||||
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/ipc/ProtocolUtils.h"
|
||||
#include "mozilla/ipc/TaskFactory.h"
|
||||
|
||||
class nsITimer;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class RDDChild;
|
||||
|
||||
// RDDProcessHost is the "parent process" container for a subprocess handle and
|
||||
// IPC connection. It owns the parent process IPDL actor, which in this case,
|
||||
// is a RDDChild.
|
||||
//
|
||||
// RDDProcessHosts are allocated and managed by RDDProcessManager. For all
|
||||
// intents and purposes it is a singleton, though more than one may be allocated
|
||||
// at a time due to its shutdown being asynchronous.
|
||||
class RDDProcessHost final : public mozilla::ipc::GeckoChildProcessHost
|
||||
{
|
||||
friend class RDDChild;
|
||||
|
||||
public:
|
||||
class Listener {
|
||||
public:
|
||||
virtual void OnProcessLaunchComplete(RDDProcessHost* aHost)
|
||||
{}
|
||||
|
||||
// The RDDProcessHost has unexpectedly shutdown or had its connection
|
||||
// severed. This is not called if an error occurs after calling
|
||||
// Shutdown().
|
||||
virtual void OnProcessUnexpectedShutdown(RDDProcessHost* aHost)
|
||||
{}
|
||||
};
|
||||
|
||||
explicit RDDProcessHost(Listener* listener);
|
||||
~RDDProcessHost();
|
||||
|
||||
// Launch the subprocess asynchronously. On failure, false is returned.
|
||||
// Otherwise, true is returned, and the OnProcessLaunchComplete listener
|
||||
// callback will be invoked either when a connection has been established, or
|
||||
// if a connection could not be established due to an asynchronous error.
|
||||
//
|
||||
// @param aExtraOpts (StringVector)
|
||||
// Extra options to pass to the subprocess.
|
||||
bool Launch(StringVector aExtraOpts);
|
||||
|
||||
// If the process is being launched, block until it has launched and
|
||||
// connected. If a launch task is pending, it will fire immediately.
|
||||
//
|
||||
// Returns true if the process is successfully connected; false otherwise.
|
||||
bool WaitForLaunch();
|
||||
|
||||
// Inform the process that it should clean up its resources and shut
|
||||
// down. This initiates an asynchronous shutdown sequence. After this
|
||||
// method returns, it is safe for the caller to forget its pointer to
|
||||
// the RDDProcessHost.
|
||||
//
|
||||
// After this returns, the attached Listener is no longer used.
|
||||
void Shutdown();
|
||||
|
||||
// Return the actor for the top-level actor of the process. If the process
|
||||
// has not connected yet, this returns null.
|
||||
RDDChild* GetActor() const {
|
||||
return mRDDChild.get();
|
||||
}
|
||||
|
||||
// Return a unique id for this process, guaranteed not to be shared with any
|
||||
// past or future instance of RDDProcessHost.
|
||||
uint64_t GetProcessToken() const;
|
||||
|
||||
bool IsConnected() const {
|
||||
return !!mRDDChild;
|
||||
}
|
||||
|
||||
// Return the time stamp for when we tried to launch the RDD process.
|
||||
// This is currently used for Telemetry so that we can determine how
|
||||
// long RDD processes take to spin up. Note this doesn't denote a
|
||||
// successful launch, just when we attempted launch.
|
||||
TimeStamp GetLaunchTime() const {
|
||||
return mLaunchTime;
|
||||
}
|
||||
|
||||
// Called on the IO thread.
|
||||
void OnChannelConnected(int32_t peer_pid) override;
|
||||
void OnChannelError() override;
|
||||
|
||||
void SetListener(Listener* aListener);
|
||||
|
||||
// Used for tests and diagnostics
|
||||
void KillProcess();
|
||||
|
||||
private:
|
||||
// Called on the main thread.
|
||||
void OnChannelConnectedTask();
|
||||
void OnChannelErrorTask();
|
||||
|
||||
// Called on the main thread after a connection has been established.
|
||||
void InitAfterConnect(bool aSucceeded);
|
||||
|
||||
// Called on the main thread when the mRDDChild actor is shutting down.
|
||||
void OnChannelClosed();
|
||||
|
||||
// Kill the remote process, triggering IPC shutdown.
|
||||
void KillHard(const char* aReason);
|
||||
|
||||
void DestroyProcess();
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(RDDProcessHost);
|
||||
|
||||
Listener* mListener;
|
||||
mozilla::ipc::TaskFactory<RDDProcessHost> mTaskFactory;
|
||||
|
||||
enum class LaunchPhase {
|
||||
Unlaunched,
|
||||
Waiting,
|
||||
Complete
|
||||
};
|
||||
LaunchPhase mLaunchPhase;
|
||||
|
||||
UniquePtr<RDDChild> mRDDChild;
|
||||
uint64_t mProcessToken;
|
||||
|
||||
bool mShutdownRequested;
|
||||
bool mChannelClosed;
|
||||
|
||||
TimeStamp mLaunchTime;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // _include_dom_media_ipc_RDDProcessHost_h_
|
@ -1,53 +0,0 @@
|
||||
/* -*- 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 "RDDProcessImpl.h"
|
||||
|
||||
#include "mozilla/ipc/IOThreadChild.h"
|
||||
|
||||
#if defined(OS_WIN) && defined(MOZ_SANDBOX)
|
||||
#include "mozilla/sandboxTarget.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace ipc;
|
||||
|
||||
RDDProcessImpl::RDDProcessImpl(ProcessId aParentPid)
|
||||
: ProcessChild(aParentPid)
|
||||
{
|
||||
}
|
||||
|
||||
RDDProcessImpl::~RDDProcessImpl()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
RDDProcessImpl::Init(int aArgc, char* aArgv[])
|
||||
{
|
||||
#if defined(MOZ_SANDBOX) && defined(OS_WIN)
|
||||
mozilla::SandboxTarget::Instance()->StartSandbox();
|
||||
#endif
|
||||
char* parentBuildID = nullptr;
|
||||
for (int i = 1; i < aArgc; i++) {
|
||||
if (strcmp(aArgv[i], "-parentBuildID") == 0) {
|
||||
parentBuildID = aArgv[i + 1];
|
||||
}
|
||||
}
|
||||
|
||||
return mRDD.Init(ParentPid(),
|
||||
parentBuildID,
|
||||
IOThreadChild::message_loop(),
|
||||
IOThreadChild::channel());
|
||||
}
|
||||
|
||||
void
|
||||
RDDProcessImpl::CleanUp()
|
||||
{
|
||||
NS_ShutdownXPCOM(nullptr);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -1,42 +0,0 @@
|
||||
/* -*- 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/. */
|
||||
#ifndef _include_dom_media_ipc_RDDProcessImpl_h__
|
||||
#define _include_dom_media_ipc_RDDProcessImpl_h__
|
||||
#include "mozilla/ipc/ProcessChild.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
# include "mozilla/mscom/MainThreadRuntime.h"
|
||||
#endif
|
||||
|
||||
#include "RDDParent.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// This class owns the subprocess instance of a PRDD - which in this case,
|
||||
// is a RDDParent. It is instantiated as a singleton in XRE_InitChildProcess.
|
||||
class RDDProcessImpl final : public ipc::ProcessChild
|
||||
{
|
||||
public:
|
||||
explicit RDDProcessImpl(ProcessId aParentPid);
|
||||
~RDDProcessImpl();
|
||||
|
||||
bool Init(int aArgc, char* aArgv[]) override;
|
||||
void CleanUp() override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(RDDProcessImpl);
|
||||
|
||||
RDDParent mRDD;
|
||||
|
||||
#if defined(XP_WIN)
|
||||
// This object initializes and configures COM.
|
||||
mozilla::mscom::MainThreadRuntime mCOMRuntime;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // _include_dom_media_ipc_RDDProcessImpl_h__
|
@ -1,317 +0,0 @@
|
||||
/* -*- 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 "RDDProcessManager.h"
|
||||
|
||||
#include "mozilla/RemoteDecoderManagerChild.h"
|
||||
#include "mozilla/RemoteDecoderManagerParent.h"
|
||||
#include "mozilla/StaticPrefs.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
|
||||
#include "nsAppRunner.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "RDDChild.h"
|
||||
#include "RDDProcessHost.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace mozilla::layers;
|
||||
|
||||
static StaticAutoPtr<RDDProcessManager> sRDDSingleton;
|
||||
|
||||
RDDProcessManager*
|
||||
RDDProcessManager::Get()
|
||||
{
|
||||
return sRDDSingleton;
|
||||
}
|
||||
|
||||
void
|
||||
RDDProcessManager::Initialize()
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
sRDDSingleton = new RDDProcessManager();
|
||||
}
|
||||
|
||||
void
|
||||
RDDProcessManager::Shutdown()
|
||||
{
|
||||
sRDDSingleton = nullptr;
|
||||
}
|
||||
|
||||
RDDProcessManager::RDDProcessManager()
|
||||
: mTaskFactory(this),
|
||||
mNumProcessAttempts(0),
|
||||
mProcess(nullptr),
|
||||
mProcessToken(0),
|
||||
mRDDChild(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(RDDProcessManager);
|
||||
|
||||
mObserver = new Observer(this);
|
||||
nsContentUtils::RegisterShutdownObserver(mObserver);
|
||||
}
|
||||
|
||||
RDDProcessManager::~RDDProcessManager()
|
||||
{
|
||||
MOZ_COUNT_DTOR(RDDProcessManager);
|
||||
|
||||
// The RDD process should have already been shut down.
|
||||
MOZ_ASSERT(!mProcess && !mRDDChild);
|
||||
|
||||
// We should have already removed observers.
|
||||
MOZ_ASSERT(!mObserver);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(RDDProcessManager::Observer, nsIObserver);
|
||||
|
||||
RDDProcessManager::Observer::Observer(RDDProcessManager* aManager)
|
||||
: mManager(aManager)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDDProcessManager::Observer::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const char16_t* aData)
|
||||
{
|
||||
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
|
||||
mManager->OnXPCOMShutdown();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
RDDProcessManager::OnXPCOMShutdown()
|
||||
{
|
||||
if (mObserver) {
|
||||
nsContentUtils::UnregisterShutdownObserver(mObserver);
|
||||
mObserver = nullptr;
|
||||
}
|
||||
|
||||
CleanShutdown();
|
||||
}
|
||||
|
||||
void
|
||||
RDDProcessManager::LaunchRDDProcess()
|
||||
{
|
||||
if (mProcess) {
|
||||
return;
|
||||
}
|
||||
|
||||
mNumProcessAttempts++;
|
||||
|
||||
std::vector<std::string> extraArgs;
|
||||
nsCString parentBuildID(mozilla::PlatformBuildID());
|
||||
extraArgs.push_back("-parentBuildID");
|
||||
extraArgs.push_back(parentBuildID.get());
|
||||
|
||||
// The subprocess is launched asynchronously, so we wait for a callback to
|
||||
// acquire the IPDL actor.
|
||||
mProcess = new RDDProcessHost(this);
|
||||
if (!mProcess->Launch(extraArgs)) {
|
||||
DestroyProcess();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RDDProcessManager::EnsureRDDReady()
|
||||
{
|
||||
if (mProcess && !mProcess->IsConnected()) {
|
||||
if (!mProcess->WaitForLaunch()) {
|
||||
// If this fails, we should have fired OnProcessLaunchComplete and
|
||||
// removed the process.
|
||||
MOZ_ASSERT(!mProcess && !mRDDChild);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mRDDChild) {
|
||||
if (mRDDChild->EnsureRDDReady()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the initialization above fails, we likely have a RDD process teardown
|
||||
// waiting in our message queue (or will soon).
|
||||
DestroyProcess();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
RDDProcessManager::OnProcessLaunchComplete(RDDProcessHost* aHost)
|
||||
{
|
||||
MOZ_ASSERT(mProcess && mProcess == aHost);
|
||||
|
||||
if (!mProcess->IsConnected()) {
|
||||
DestroyProcess();
|
||||
return;
|
||||
}
|
||||
|
||||
mRDDChild = mProcess->GetActor();
|
||||
mProcessToken = mProcess->GetProcessToken();
|
||||
|
||||
CrashReporter::AnnotateCrashReport(
|
||||
CrashReporter::Annotation::RDDProcessStatus,
|
||||
NS_LITERAL_CSTRING("Running"));
|
||||
}
|
||||
|
||||
void
|
||||
RDDProcessManager::OnProcessUnexpectedShutdown(RDDProcessHost* aHost)
|
||||
{
|
||||
MOZ_ASSERT(mProcess && mProcess == aHost);
|
||||
|
||||
DestroyProcess();
|
||||
}
|
||||
|
||||
void
|
||||
RDDProcessManager::NotifyRemoteActorDestroyed(const uint64_t& aProcessToken)
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
RefPtr<Runnable> task = mTaskFactory.NewRunnableMethod(
|
||||
&RDDProcessManager::NotifyRemoteActorDestroyed, aProcessToken);
|
||||
NS_DispatchToMainThread(task.forget());
|
||||
return;
|
||||
}
|
||||
|
||||
if (mProcessToken != aProcessToken) {
|
||||
// This token is for an older process; we can safely ignore it.
|
||||
return;
|
||||
}
|
||||
|
||||
// One of the bridged top-level actors for the RDD process has been
|
||||
// prematurely terminated, and we're receiving a notification. This
|
||||
// can happen if the ActorDestroy for a bridged protocol fires
|
||||
// before the ActorDestroy for PRDDChild.
|
||||
OnProcessUnexpectedShutdown(mProcess);
|
||||
}
|
||||
|
||||
void
|
||||
RDDProcessManager::CleanShutdown()
|
||||
{
|
||||
DestroyProcess();
|
||||
}
|
||||
|
||||
void
|
||||
RDDProcessManager::KillProcess()
|
||||
{
|
||||
if (!mProcess) {
|
||||
return;
|
||||
}
|
||||
|
||||
mProcess->KillProcess();
|
||||
}
|
||||
|
||||
void
|
||||
RDDProcessManager::DestroyProcess()
|
||||
{
|
||||
if (!mProcess) {
|
||||
return;
|
||||
}
|
||||
|
||||
mProcess->Shutdown();
|
||||
mProcessToken = 0;
|
||||
mProcess = nullptr;
|
||||
mRDDChild = nullptr;
|
||||
|
||||
CrashReporter::AnnotateCrashReport(
|
||||
CrashReporter::Annotation::RDDProcessStatus,
|
||||
NS_LITERAL_CSTRING("Destroyed"));
|
||||
}
|
||||
|
||||
bool
|
||||
RDDProcessManager::CreateContentBridge(
|
||||
base::ProcessId aOtherProcess,
|
||||
ipc::Endpoint<PRemoteDecoderManagerChild>* aOutRemoteDecoderManager)
|
||||
{
|
||||
if (!EnsureRDDReady() ||
|
||||
!StaticPrefs::MediaRddProcessEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ipc::Endpoint<PRemoteDecoderManagerParent> parentPipe;
|
||||
ipc::Endpoint<PRemoteDecoderManagerChild> childPipe;
|
||||
|
||||
nsresult rv = PRemoteDecoderManager::CreateEndpoints(
|
||||
mRDDChild->OtherPid(),
|
||||
aOtherProcess,
|
||||
&parentPipe,
|
||||
&childPipe);
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_LOG(sPDMLog,
|
||||
LogLevel::Debug,
|
||||
("Could not create content remote decoder: %d", int(rv)));
|
||||
return false;
|
||||
}
|
||||
|
||||
mRDDChild->SendNewContentRemoteDecoderManager(std::move(parentPipe));
|
||||
|
||||
*aOutRemoteDecoderManager = std::move(childPipe);
|
||||
return true;
|
||||
}
|
||||
|
||||
base::ProcessId
|
||||
RDDProcessManager::RDDProcessPid()
|
||||
{
|
||||
base::ProcessId rddPid = mRDDChild
|
||||
? mRDDChild->OtherPid()
|
||||
: -1;
|
||||
return rddPid;
|
||||
}
|
||||
|
||||
class RDDMemoryReporter : public MemoryReportingProcess
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RDDMemoryReporter, override)
|
||||
|
||||
bool IsAlive() const override {
|
||||
return !!GetChild();
|
||||
}
|
||||
|
||||
bool SendRequestMemoryReport(const uint32_t& aGeneration,
|
||||
const bool& aAnonymize,
|
||||
const bool& aMinimizeMemoryUsage,
|
||||
const dom::MaybeFileDesc& aDMDFile) override
|
||||
{
|
||||
RDDChild* child = GetChild();
|
||||
if (!child) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return child->SendRequestMemoryReport(
|
||||
aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile);
|
||||
}
|
||||
|
||||
int32_t Pid() const override {
|
||||
if (RDDChild* child = GetChild()) {
|
||||
return (int32_t)child->OtherPid();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
RDDChild* GetChild() const {
|
||||
if (RDDProcessManager* rddpm = RDDProcessManager::Get()) {
|
||||
if (RDDChild* child = rddpm->GetRDDChild()) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
~RDDMemoryReporter() = default;
|
||||
};
|
||||
|
||||
RefPtr<MemoryReportingProcess>
|
||||
RDDProcessManager::GetProcessMemoryReporter()
|
||||
{
|
||||
if (!EnsureRDDReady()) {
|
||||
return nullptr;
|
||||
}
|
||||
return new RDDMemoryReporter();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
@ -1,108 +0,0 @@
|
||||
/* -*- 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/. */
|
||||
#ifndef _include_dom_media_ipc_RDDProcessManager_h_
|
||||
#define _include_dom_media_ipc_RDDProcessManager_h_
|
||||
#include "mozilla/RDDProcessHost.h"
|
||||
|
||||
#include "mozilla/ipc/TaskFactory.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class MemoryReportingProcess;
|
||||
class PRemoteDecoderManagerChild;
|
||||
class RDDChild;
|
||||
|
||||
// The RDDProcessManager is a singleton responsible for creating RDD-bound
|
||||
// objects that may live in another process. Currently, it provides access
|
||||
// to the RDD process via ContentParent.
|
||||
class RDDProcessManager final : public RDDProcessHost::Listener
|
||||
{
|
||||
public:
|
||||
static void Initialize();
|
||||
static void Shutdown();
|
||||
static RDDProcessManager* Get();
|
||||
|
||||
~RDDProcessManager();
|
||||
|
||||
// If not using a RDD process, launch a new RDD process asynchronously.
|
||||
void LaunchRDDProcess();
|
||||
|
||||
// Ensure that RDD-bound methods can be used. If no RDD process is being
|
||||
// used, or one is launched and ready, this function returns immediately.
|
||||
// Otherwise it blocks until the RDD process has finished launching.
|
||||
bool EnsureRDDReady();
|
||||
|
||||
bool CreateContentBridge(
|
||||
base::ProcessId aOtherProcess,
|
||||
mozilla::ipc::Endpoint<PRemoteDecoderManagerChild>*
|
||||
aOutRemoteDecoderManager);
|
||||
|
||||
void OnProcessLaunchComplete(RDDProcessHost* aHost) override;
|
||||
void OnProcessUnexpectedShutdown(RDDProcessHost* aHost) override;
|
||||
|
||||
// Notify the RDDProcessManager that a top-level PRDD protocol has been
|
||||
// terminated. This may be called from any thread.
|
||||
void NotifyRemoteActorDestroyed(const uint64_t& aProcessToken);
|
||||
|
||||
// Used for tests and diagnostics
|
||||
void KillProcess();
|
||||
|
||||
// Returns -1 if there is no RDD process, or the platform pid for it.
|
||||
base::ProcessId RDDProcessPid();
|
||||
|
||||
// If a RDD process is present, create a MemoryReportingProcess object.
|
||||
// Otherwise, return null.
|
||||
RefPtr<MemoryReportingProcess> GetProcessMemoryReporter();
|
||||
|
||||
// Returns access to the PRDD protocol if a RDD process is present.
|
||||
RDDChild* GetRDDChild() {
|
||||
return mRDDChild;
|
||||
}
|
||||
|
||||
// Returns whether or not a RDD process was ever launched.
|
||||
bool AttemptedRDDProcess() const {
|
||||
return mNumProcessAttempts > 0;
|
||||
}
|
||||
|
||||
private:
|
||||
// Called from our xpcom-shutdown observer.
|
||||
void OnXPCOMShutdown();
|
||||
|
||||
RDDProcessManager();
|
||||
|
||||
// Shutdown the RDD process.
|
||||
void CleanShutdown();
|
||||
void DestroyProcess();
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(RDDProcessManager);
|
||||
|
||||
class Observer final : public nsIObserver {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
explicit Observer(RDDProcessManager* aManager);
|
||||
|
||||
protected:
|
||||
~Observer() {}
|
||||
|
||||
RDDProcessManager* mManager;
|
||||
};
|
||||
friend class Observer;
|
||||
|
||||
private:
|
||||
RefPtr<Observer> mObserver;
|
||||
mozilla::ipc::TaskFactory<RDDProcessManager> mTaskFactory;
|
||||
uint32_t mNumProcessAttempts;
|
||||
|
||||
// Fields that are associated with the current RDD process.
|
||||
RDDProcessHost* mProcess;
|
||||
uint64_t mProcessToken;
|
||||
RDDChild* mRDDChild;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // _include_dom_media_ipc_RDDProcessManager_h_
|
@ -1,151 +0,0 @@
|
||||
/* -*- 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 "RemoteDecoderManagerChild.h"
|
||||
|
||||
#include "base/task.h"
|
||||
|
||||
#include "RemoteVideoDecoderChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Only modified on the main-thread
|
||||
StaticRefPtr<nsIThread> sRemoteDecoderManagerChildThread;
|
||||
StaticRefPtr<AbstractThread> sRemoteDecoderManagerChildAbstractThread;
|
||||
|
||||
// Only accessed from sRemoteDecoderManagerChildThread
|
||||
static StaticRefPtr<RemoteDecoderManagerChild> sRemoteDecoderManagerChild;
|
||||
|
||||
/* static */ void
|
||||
RemoteDecoderManagerChild::InitializeThread()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!sRemoteDecoderManagerChildThread) {
|
||||
RefPtr<nsIThread> childThread;
|
||||
nsresult rv = NS_NewNamedThread("RemVidChild", getter_AddRefs(childThread));
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
sRemoteDecoderManagerChildThread = childThread;
|
||||
|
||||
sRemoteDecoderManagerChildAbstractThread =
|
||||
AbstractThread::CreateXPCOMThreadWrapper(childThread, false);
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
RemoteDecoderManagerChild::InitForContent(
|
||||
Endpoint<PRemoteDecoderManagerChild>&& aVideoManager)
|
||||
{
|
||||
InitializeThread();
|
||||
sRemoteDecoderManagerChildThread->Dispatch(
|
||||
NewRunnableFunction("InitForContentRunnable",
|
||||
&Open,
|
||||
std::move(aVideoManager)),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
RemoteDecoderManagerChild::Shutdown()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (sRemoteDecoderManagerChildThread) {
|
||||
sRemoteDecoderManagerChildThread->Dispatch(
|
||||
NS_NewRunnableFunction("dom::RemoteDecoderManagerChild::Shutdown",
|
||||
[]() {
|
||||
if (sRemoteDecoderManagerChild &&
|
||||
sRemoteDecoderManagerChild->CanSend()) {
|
||||
sRemoteDecoderManagerChild->Close();
|
||||
sRemoteDecoderManagerChild = nullptr;
|
||||
}
|
||||
}),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
sRemoteDecoderManagerChildAbstractThread = nullptr;
|
||||
sRemoteDecoderManagerChildThread->Shutdown();
|
||||
sRemoteDecoderManagerChildThread = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ RemoteDecoderManagerChild*
|
||||
RemoteDecoderManagerChild::GetSingleton()
|
||||
{
|
||||
MOZ_ASSERT(NS_GetCurrentThread() == GetManagerThread());
|
||||
return sRemoteDecoderManagerChild;
|
||||
}
|
||||
|
||||
/* static */ nsIThread*
|
||||
RemoteDecoderManagerChild::GetManagerThread()
|
||||
{
|
||||
return sRemoteDecoderManagerChildThread;
|
||||
}
|
||||
|
||||
/* static */ AbstractThread*
|
||||
RemoteDecoderManagerChild::GetManagerAbstractThread()
|
||||
{
|
||||
return sRemoteDecoderManagerChildAbstractThread;
|
||||
}
|
||||
|
||||
PRemoteVideoDecoderChild*
|
||||
RemoteDecoderManagerChild::AllocPRemoteVideoDecoderChild(
|
||||
const VideoInfo& /* not used */,
|
||||
const float& /* not used */,
|
||||
const CreateDecoderParams::OptionSet& /* not used */,
|
||||
bool* /* not used */,
|
||||
nsCString* /* not used */)
|
||||
{
|
||||
return new RemoteVideoDecoderChild();
|
||||
}
|
||||
|
||||
bool
|
||||
RemoteDecoderManagerChild::DeallocPRemoteVideoDecoderChild(
|
||||
PRemoteVideoDecoderChild* actor)
|
||||
{
|
||||
RemoteVideoDecoderChild* child = static_cast<RemoteVideoDecoderChild*>(actor);
|
||||
child->IPDLActorDestroyed();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
RemoteDecoderManagerChild::Open(
|
||||
Endpoint<PRemoteDecoderManagerChild>&& aEndpoint)
|
||||
{
|
||||
sRemoteDecoderManagerChild = nullptr;
|
||||
if (aEndpoint.IsValid()) {
|
||||
RefPtr<RemoteDecoderManagerChild> manager = new RemoteDecoderManagerChild();
|
||||
if (aEndpoint.Bind(manager)) {
|
||||
sRemoteDecoderManagerChild = manager;
|
||||
manager->InitIPDL();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RemoteDecoderManagerChild::InitIPDL()
|
||||
{
|
||||
mCanSend = true;
|
||||
mIPDLSelfRef = this;
|
||||
}
|
||||
|
||||
void
|
||||
RemoteDecoderManagerChild::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
mCanSend = false;
|
||||
}
|
||||
|
||||
void
|
||||
RemoteDecoderManagerChild::DeallocPRemoteDecoderManagerChild()
|
||||
{
|
||||
mIPDLSelfRef = nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
RemoteDecoderManagerChild::CanSend()
|
||||
{
|
||||
MOZ_ASSERT(NS_GetCurrentThread() == GetManagerThread());
|
||||
return mCanSend;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
@ -1,63 +0,0 @@
|
||||
/* -*- 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/. */
|
||||
#ifndef include_dom_media_ipc_RemoteDecoderManagerChild_h
|
||||
#define include_dom_media_ipc_RemoteDecoderManagerChild_h
|
||||
#include "mozilla/PRemoteDecoderManagerChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class RemoteDecoderManagerChild final : public PRemoteDecoderManagerChild
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteDecoderManagerChild)
|
||||
|
||||
// Can only be called from the manager thread
|
||||
static RemoteDecoderManagerChild* GetSingleton();
|
||||
|
||||
// Can be called from any thread.
|
||||
static nsIThread* GetManagerThread();
|
||||
static AbstractThread* GetManagerAbstractThread();
|
||||
|
||||
// Main thread only
|
||||
static void InitForContent(
|
||||
Endpoint<PRemoteDecoderManagerChild>&& aVideoManager);
|
||||
static void Shutdown();
|
||||
|
||||
bool CanSend();
|
||||
|
||||
protected:
|
||||
void InitIPDL();
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
void DeallocPRemoteDecoderManagerChild() override;
|
||||
|
||||
PRemoteVideoDecoderChild* AllocPRemoteVideoDecoderChild(
|
||||
const VideoInfo& aVideoInfo,
|
||||
const float& aFramerate,
|
||||
const CreateDecoderParams::OptionSet& aOptions,
|
||||
bool* aSuccess,
|
||||
nsCString* aErrorDescription) override;
|
||||
bool DeallocPRemoteVideoDecoderChild(
|
||||
PRemoteVideoDecoderChild* actor) override;
|
||||
|
||||
private:
|
||||
// Main thread only
|
||||
static void InitializeThread();
|
||||
|
||||
RemoteDecoderManagerChild() = default;
|
||||
~RemoteDecoderManagerChild() = default;
|
||||
|
||||
static void Open(Endpoint<PRemoteDecoderManagerChild>&& aEndpoint);
|
||||
|
||||
RefPtr<RemoteDecoderManagerChild> mIPDLSelfRef;
|
||||
|
||||
// Should only ever be accessed on the manager thread.
|
||||
bool mCanSend = false;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // include_dom_media_ipc_RemoteDecoderManagerChild_h
|
@ -1,216 +0,0 @@
|
||||
/* -*- 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 "RemoteDecoderManagerParent.h"
|
||||
|
||||
#if XP_WIN
|
||||
#include <objbase.h>
|
||||
#endif
|
||||
|
||||
#include "RemoteVideoDecoderParent.h"
|
||||
#include "VideoUtils.h" // for MediaThreadType
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
StaticRefPtr<nsIThread> sRemoteDecoderManagerParentThread;
|
||||
StaticRefPtr<TaskQueue> sRemoteDecoderManagerTaskQueue;
|
||||
|
||||
class RemoteDecoderManagerThreadHolder
|
||||
{
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteDecoderManagerThreadHolder)
|
||||
|
||||
public:
|
||||
RemoteDecoderManagerThreadHolder() { }
|
||||
|
||||
private:
|
||||
~RemoteDecoderManagerThreadHolder()
|
||||
{
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||
"dom::RemoteDecoderManagerThreadHolder::~RemoteDecoderManagerThreadHolder",
|
||||
[]() {
|
||||
sRemoteDecoderManagerParentThread->Shutdown();
|
||||
sRemoteDecoderManagerParentThread = nullptr;
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
StaticRefPtr<RemoteDecoderManagerThreadHolder>
|
||||
sRemoteDecoderManagerParentThreadHolder;
|
||||
|
||||
class RemoteDecoderManagerThreadShutdownObserver : public nsIObserver
|
||||
{
|
||||
virtual ~RemoteDecoderManagerThreadShutdownObserver() = default;
|
||||
public:
|
||||
RemoteDecoderManagerThreadShutdownObserver() = default;
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic,
|
||||
const char16_t* aData) override
|
||||
{
|
||||
MOZ_ASSERT(strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0);
|
||||
|
||||
RemoteDecoderManagerParent::ShutdownThreads();
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
NS_IMPL_ISUPPORTS(RemoteDecoderManagerThreadShutdownObserver, nsIObserver);
|
||||
|
||||
bool
|
||||
RemoteDecoderManagerParent::StartupThreads()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (sRemoteDecoderManagerParentThread) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
|
||||
if (!observerService) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<nsIThread> managerThread;
|
||||
nsresult rv =
|
||||
NS_NewNamedThread("RemVidParent", getter_AddRefs(managerThread));
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
sRemoteDecoderManagerParentThread = managerThread;
|
||||
sRemoteDecoderManagerParentThreadHolder =
|
||||
new RemoteDecoderManagerThreadHolder();
|
||||
#if XP_WIN
|
||||
sRemoteDecoderManagerParentThread->Dispatch(
|
||||
NS_NewRunnableFunction(
|
||||
"RemoteDecoderManagerParent::StartupThreads",
|
||||
[]() {
|
||||
DebugOnly<HRESULT> hr = CoInitializeEx(0, COINIT_MULTITHREADED);
|
||||
MOZ_ASSERT(SUCCEEDED(hr));
|
||||
}),
|
||||
NS_DISPATCH_NORMAL);
|
||||
#endif
|
||||
|
||||
sRemoteDecoderManagerTaskQueue = new TaskQueue(
|
||||
managerThread.forget(),
|
||||
"RemoteDecoderManagerParent::sRemoteDecoderManagerTaskQueue");
|
||||
|
||||
auto* obs = new RemoteDecoderManagerThreadShutdownObserver();
|
||||
observerService->AddObserver(obs, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
RemoteDecoderManagerParent::ShutdownThreads()
|
||||
{
|
||||
sRemoteDecoderManagerTaskQueue = nullptr;
|
||||
|
||||
sRemoteDecoderManagerParentThreadHolder = nullptr;
|
||||
while (sRemoteDecoderManagerParentThread) {
|
||||
NS_ProcessNextEvent(nullptr, true);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RemoteDecoderManagerParent::OnManagerThread()
|
||||
{
|
||||
return NS_GetCurrentThread() == sRemoteDecoderManagerParentThread;
|
||||
}
|
||||
|
||||
bool
|
||||
RemoteDecoderManagerParent::CreateForContent(
|
||||
Endpoint<PRemoteDecoderManagerParent>&& aEndpoint)
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_RDD);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!StartupThreads()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<RemoteDecoderManagerParent> parent =
|
||||
new RemoteDecoderManagerParent(sRemoteDecoderManagerParentThreadHolder);
|
||||
|
||||
RefPtr<Runnable> task =
|
||||
NewRunnableMethod<Endpoint<PRemoteDecoderManagerParent>&&>(
|
||||
"dom::RemoteDecoderManagerParent::Open",
|
||||
parent,
|
||||
&RemoteDecoderManagerParent::Open,
|
||||
std::move(aEndpoint));
|
||||
sRemoteDecoderManagerParentThread->Dispatch(task.forget(),
|
||||
NS_DISPATCH_NORMAL);
|
||||
return true;
|
||||
}
|
||||
|
||||
RemoteDecoderManagerParent::RemoteDecoderManagerParent(
|
||||
RemoteDecoderManagerThreadHolder* aHolder)
|
||||
: mThreadHolder(aHolder)
|
||||
{
|
||||
MOZ_COUNT_CTOR(RemoteDecoderManagerParent);
|
||||
}
|
||||
|
||||
RemoteDecoderManagerParent::~RemoteDecoderManagerParent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(RemoteDecoderManagerParent);
|
||||
}
|
||||
|
||||
void
|
||||
RemoteDecoderManagerParent::ActorDestroy(
|
||||
mozilla::ipc::IProtocol::ActorDestroyReason)
|
||||
{
|
||||
mThreadHolder = nullptr;
|
||||
}
|
||||
|
||||
PRemoteVideoDecoderParent*
|
||||
RemoteDecoderManagerParent::AllocPRemoteVideoDecoderParent(
|
||||
const VideoInfo& aVideoInfo,
|
||||
const float& aFramerate,
|
||||
const CreateDecoderParams::OptionSet& aOptions,
|
||||
bool* aSuccess,
|
||||
nsCString* aErrorDescription)
|
||||
{
|
||||
RefPtr<TaskQueue> decodeTaskQueue = new TaskQueue(
|
||||
GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER),
|
||||
"RemoteVideoDecoderParent::mDecodeTaskQueue");
|
||||
|
||||
auto* parent = new RemoteVideoDecoderParent(this,
|
||||
aVideoInfo,
|
||||
aFramerate,
|
||||
aOptions,
|
||||
sRemoteDecoderManagerTaskQueue,
|
||||
decodeTaskQueue,
|
||||
aSuccess,
|
||||
aErrorDescription);
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
bool
|
||||
RemoteDecoderManagerParent::DeallocPRemoteVideoDecoderParent(
|
||||
PRemoteVideoDecoderParent* actor)
|
||||
{
|
||||
RemoteVideoDecoderParent* parent =
|
||||
static_cast<RemoteVideoDecoderParent*>(actor);
|
||||
parent->Destroy();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
RemoteDecoderManagerParent::Open(
|
||||
Endpoint<PRemoteDecoderManagerParent>&& aEndpoint)
|
||||
{
|
||||
if (!aEndpoint.Bind(this)) {
|
||||
// We can't recover from this.
|
||||
MOZ_CRASH("Failed to bind RemoteDecoderManagerParent to endpoint");
|
||||
}
|
||||
AddRef();
|
||||
}
|
||||
|
||||
void
|
||||
RemoteDecoderManagerParent::DeallocPRemoteDecoderManagerParent()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
@ -1,53 +0,0 @@
|
||||
/* -*- 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/. */
|
||||
#ifndef include_dom_media_ipc_RemoteDecoderManagerParent_h
|
||||
#define include_dom_media_ipc_RemoteDecoderManagerParent_h
|
||||
#include "mozilla/PRemoteDecoderManagerParent.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class RemoteDecoderManagerThreadHolder;
|
||||
|
||||
class RemoteDecoderManagerParent final : public PRemoteDecoderManagerParent
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteDecoderManagerParent)
|
||||
|
||||
static bool CreateForContent(
|
||||
Endpoint<PRemoteDecoderManagerParent>&& aEndpoint);
|
||||
|
||||
static bool StartupThreads();
|
||||
static void ShutdownThreads();
|
||||
|
||||
bool OnManagerThread();
|
||||
|
||||
protected:
|
||||
PRemoteVideoDecoderParent* AllocPRemoteVideoDecoderParent(
|
||||
const VideoInfo& aVideoInfo,
|
||||
const float& aFramerate,
|
||||
const CreateDecoderParams::OptionSet& aOptions,
|
||||
bool* aSuccess,
|
||||
nsCString* aErrorDescription) override;
|
||||
bool DeallocPRemoteVideoDecoderParent(
|
||||
PRemoteVideoDecoderParent* actor) override;
|
||||
|
||||
void ActorDestroy(mozilla::ipc::IProtocol::ActorDestroyReason) override;
|
||||
|
||||
void DeallocPRemoteDecoderManagerParent() override;
|
||||
|
||||
private:
|
||||
explicit RemoteDecoderManagerParent(
|
||||
RemoteDecoderManagerThreadHolder* aThreadHolder);
|
||||
~RemoteDecoderManagerParent();
|
||||
|
||||
void Open(Endpoint<PRemoteDecoderManagerParent>&& aEndpoint);
|
||||
|
||||
RefPtr<RemoteDecoderManagerThreadHolder> mThreadHolder;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // include_dom_media_ipc_RemoteDecoderManagerParent_h
|
@ -1,88 +0,0 @@
|
||||
/* -*- 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 "RemoteDecoderModule.h"
|
||||
|
||||
#include "base/thread.h"
|
||||
#include "mozilla/layers/SynchronousTask.h"
|
||||
#include "mozilla/StaticPrefs.h"
|
||||
|
||||
#ifdef MOZ_AV1
|
||||
#include "AOMDecoder.h"
|
||||
#endif
|
||||
#include "RemoteDecoderManagerChild.h"
|
||||
#include "RemoteMediaDataDecoder.h"
|
||||
#include "RemoteVideoDecoderChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using base::Thread;
|
||||
using namespace ipc;
|
||||
using namespace layers;
|
||||
|
||||
nsresult
|
||||
RemoteDecoderModule::Startup()
|
||||
{
|
||||
if (!RemoteDecoderManagerChild::GetManagerThread()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
RemoteDecoderModule::SupportsMimeType(
|
||||
const nsACString& aMimeType,
|
||||
DecoderDoctorDiagnostics* aDiagnostics) const
|
||||
{
|
||||
bool supports = false;
|
||||
|
||||
#ifdef MOZ_AV1
|
||||
if (StaticPrefs::MediaAv1Enabled()) {
|
||||
supports |= AOMDecoder::IsAV1(aMimeType);
|
||||
}
|
||||
#endif
|
||||
MOZ_LOG(sPDMLog, LogLevel::Debug, ("Sandbox decoder %s requested type",
|
||||
supports ? "supports" : "rejects"));
|
||||
return supports;
|
||||
}
|
||||
|
||||
already_AddRefed<MediaDataDecoder>
|
||||
RemoteDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
|
||||
{
|
||||
RemoteVideoDecoderChild* child = new RemoteVideoDecoderChild();
|
||||
RefPtr<RemoteMediaDataDecoder> object =
|
||||
new RemoteMediaDataDecoder(
|
||||
child,
|
||||
RemoteDecoderManagerChild::GetManagerThread(),
|
||||
RemoteDecoderManagerChild::GetManagerAbstractThread());
|
||||
|
||||
// (per Matt Woodrow) We can't use NS_DISPATCH_SYNC here since that
|
||||
// can spin the event loop while it waits.
|
||||
SynchronousTask task("InitIPDL");
|
||||
MediaResult result(NS_OK);
|
||||
RemoteDecoderManagerChild::GetManagerThread()->Dispatch(
|
||||
NS_NewRunnableFunction(
|
||||
"dom::RemoteDecoderModule::CreateVideoDecoder",
|
||||
[&, child]() {
|
||||
AutoCompleteTask complete(&task);
|
||||
result = child->InitIPDL(
|
||||
aParams.VideoConfig(),
|
||||
aParams.mRate.mValue,
|
||||
aParams.mOptions);
|
||||
}),
|
||||
NS_DISPATCH_NORMAL);
|
||||
task.Wait();
|
||||
|
||||
if (NS_FAILED(result)) {
|
||||
if (aParams.mError) {
|
||||
*aParams.mError = result;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return object.forget();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
@ -1,38 +0,0 @@
|
||||
/* -*- 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/. */
|
||||
#ifndef include_dom_media_ipc_RemoteDecoderModule_h
|
||||
#define include_dom_media_ipc_RemoteDecoderModule_h
|
||||
#include "PlatformDecoderModule.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// A PDM implementation that creates a RemoteMediaDataDecoder (a
|
||||
// MediaDataDecoder) that proxies to a RemoteVideoDecoderChild.
|
||||
// A decoder child will talk to its respective decoder parent
|
||||
// (RemoteVideoDecoderParent) on the RDD process.
|
||||
class RemoteDecoderModule : public PlatformDecoderModule
|
||||
{
|
||||
public:
|
||||
RemoteDecoderModule() = default;
|
||||
|
||||
nsresult Startup() override;
|
||||
|
||||
bool SupportsMimeType(const nsACString& aMimeType,
|
||||
DecoderDoctorDiagnostics* aDiagnostics) const override;
|
||||
|
||||
already_AddRefed<MediaDataDecoder> CreateVideoDecoder(
|
||||
const CreateDecoderParams& aParams) override;
|
||||
|
||||
already_AddRefed<MediaDataDecoder> CreateAudioDecoder(
|
||||
const CreateDecoderParams& aParams) override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // include_dom_media_ipc_RemoteDecoderModule_h
|
@ -1,140 +0,0 @@
|
||||
/* -*- 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 "RemoteMediaDataDecoder.h"
|
||||
|
||||
#include "base/thread.h"
|
||||
|
||||
#include "IRemoteDecoderChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using base::Thread;
|
||||
|
||||
RemoteMediaDataDecoder::RemoteMediaDataDecoder(
|
||||
IRemoteDecoderChild* aChild,
|
||||
nsIThread* aManagerThread,
|
||||
AbstractThread* aAbstractManagerThread)
|
||||
: mChild(aChild)
|
||||
, mManagerThread(aManagerThread)
|
||||
, mAbstractManagerThread(aAbstractManagerThread)
|
||||
{
|
||||
}
|
||||
|
||||
RemoteMediaDataDecoder::~RemoteMediaDataDecoder()
|
||||
{
|
||||
// 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.
|
||||
RefPtr<IRemoteDecoderChild> child = mChild.forget();
|
||||
|
||||
RefPtr<Runnable> task = NS_NewRunnableFunction(
|
||||
"dom::RemoteMediaDataDecoder::~RemoteMediaDataDecoder", [child]() {
|
||||
MOZ_ASSERT(child);
|
||||
child->DestroyIPDL();
|
||||
});
|
||||
|
||||
// Drop our references to the child so that the last ref
|
||||
// always gets released on the manager thread.
|
||||
child = nullptr;
|
||||
|
||||
mManagerThread->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
RefPtr<MediaDataDecoder::InitPromise>
|
||||
RemoteMediaDataDecoder::Init()
|
||||
{
|
||||
RefPtr<RemoteMediaDataDecoder> self = this;
|
||||
return InvokeAsync(mAbstractManagerThread,
|
||||
__func__,
|
||||
[self]() { return self->mChild->Init(); })
|
||||
->Then(mAbstractManagerThread,
|
||||
__func__,
|
||||
[self, this](TrackType aTrack) {
|
||||
mDescription =
|
||||
mChild->GetDescriptionName() + NS_LITERAL_CSTRING(" (remote)");
|
||||
mIsHardwareAccelerated =
|
||||
mChild->IsHardwareAccelerated(mHardwareAcceleratedReason);
|
||||
mConversion = mChild->NeedsConversion();
|
||||
return InitPromise::CreateAndResolve(aTrack, __func__);
|
||||
},
|
||||
[self](const MediaResult& aError) {
|
||||
return InitPromise::CreateAndReject(aError, __func__);
|
||||
});
|
||||
}
|
||||
|
||||
RefPtr<MediaDataDecoder::DecodePromise>
|
||||
RemoteMediaDataDecoder::Decode(MediaRawData* aSample)
|
||||
{
|
||||
RefPtr<RemoteMediaDataDecoder> self = this;
|
||||
RefPtr<MediaRawData> sample = aSample;
|
||||
return InvokeAsync(mAbstractManagerThread, __func__, [self, sample]() {
|
||||
return self->mChild->Decode(sample);
|
||||
});
|
||||
}
|
||||
|
||||
RefPtr<MediaDataDecoder::FlushPromise>
|
||||
RemoteMediaDataDecoder::Flush()
|
||||
{
|
||||
RefPtr<RemoteMediaDataDecoder> self = this;
|
||||
return InvokeAsync(mAbstractManagerThread, __func__, [self]() {
|
||||
return self->mChild->Flush();
|
||||
});
|
||||
}
|
||||
|
||||
RefPtr<MediaDataDecoder::DecodePromise>
|
||||
RemoteMediaDataDecoder::Drain()
|
||||
{
|
||||
RefPtr<RemoteMediaDataDecoder> self = this;
|
||||
return InvokeAsync(mAbstractManagerThread, __func__, [self]() {
|
||||
return self->mChild->Drain();
|
||||
});
|
||||
}
|
||||
|
||||
RefPtr<ShutdownPromise>
|
||||
RemoteMediaDataDecoder::Shutdown()
|
||||
{
|
||||
RefPtr<RemoteMediaDataDecoder> self = this;
|
||||
return InvokeAsync(mAbstractManagerThread, __func__, [self]() {
|
||||
self->mChild->Shutdown();
|
||||
return ShutdownPromise::CreateAndResolve(true, __func__);
|
||||
});
|
||||
}
|
||||
|
||||
bool
|
||||
RemoteMediaDataDecoder::IsHardwareAccelerated(nsACString& aFailureReason) const
|
||||
{
|
||||
aFailureReason = mHardwareAcceleratedReason;
|
||||
return mIsHardwareAccelerated;
|
||||
}
|
||||
|
||||
void
|
||||
RemoteMediaDataDecoder::SetSeekThreshold(const media::TimeUnit& aTime)
|
||||
{
|
||||
RefPtr<RemoteMediaDataDecoder> self = this;
|
||||
media::TimeUnit time = aTime;
|
||||
mManagerThread->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;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
@ -1,68 +0,0 @@
|
||||
/* -*- 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/. */
|
||||
#ifndef include_dom_media_ipc_RemoteMediaDataDecoder_h
|
||||
#define include_dom_media_ipc_RemoteMediaDataDecoder_h
|
||||
#include "PlatformDecoderModule.h"
|
||||
|
||||
#include "MediaData.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class GpuDecoderModule;
|
||||
class IRemoteDecoderChild;
|
||||
class RemoteDecoderModule;
|
||||
class RemoteMediaDataDecoder;
|
||||
|
||||
DDLoggedTypeCustomNameAndBase(RemoteMediaDataDecoder,
|
||||
RemoteMediaDataDecoder,
|
||||
MediaDataDecoder);
|
||||
|
||||
// A MediaDataDecoder implementation that proxies through IPDL
|
||||
// to a 'real' decoder in the GPU or RDD process.
|
||||
// All requests get forwarded to a *DecoderChild instance that
|
||||
// operates solely on the provided manager and abstract manager threads.
|
||||
class RemoteMediaDataDecoder
|
||||
: public MediaDataDecoder
|
||||
, public DecoderDoctorLifeLogger<RemoteMediaDataDecoder>
|
||||
{
|
||||
public:
|
||||
friend class GpuDecoderModule;
|
||||
friend class RemoteDecoderModule;
|
||||
|
||||
// MediaDataDecoder
|
||||
RefPtr<InitPromise> Init() override;
|
||||
RefPtr<DecodePromise> Decode(MediaRawData* aSample) override;
|
||||
RefPtr<DecodePromise> Drain() override;
|
||||
RefPtr<FlushPromise> Flush() override;
|
||||
RefPtr<ShutdownPromise> Shutdown() override;
|
||||
bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
|
||||
void SetSeekThreshold(const media::TimeUnit& aTime) override;
|
||||
nsCString GetDescriptionName() const override;
|
||||
ConversionRequired NeedsConversion() const override;
|
||||
|
||||
private:
|
||||
RemoteMediaDataDecoder(IRemoteDecoderChild* aChild,
|
||||
nsIThread* aManagerThread,
|
||||
AbstractThread* aAbstractManagerThread);
|
||||
~RemoteMediaDataDecoder();
|
||||
|
||||
// Only ever written to from the reader task queue (during the constructor and
|
||||
// destructor when we can guarantee no other threads are accessing it). Only
|
||||
// read from the manager thread.
|
||||
RefPtr<IRemoteDecoderChild> mChild;
|
||||
nsIThread* mManagerThread;
|
||||
AbstractThread* mAbstractManagerThread;
|
||||
// Only ever written/modified during decoder initialisation.
|
||||
// As such can be accessed from any threads after that.
|
||||
nsCString mDescription = NS_LITERAL_CSTRING("RemoteMediaDataDecoder");
|
||||
bool mIsHardwareAccelerated = false;
|
||||
nsCString mHardwareAcceleratedReason;
|
||||
ConversionRequired mConversion = ConversionRequired::kNeedNone;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // include_dom_media_ipc_RemoteMediaDataDecoder_h
|
218
dom/media/ipc/RemoteVideoDecoder.cpp
Normal file
218
dom/media/ipc/RemoteVideoDecoder.cpp
Normal file
@ -0,0 +1,218 @@
|
||||
/* -*- 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 "mozilla/StaticPrefs.h"
|
||||
#include "base/thread.h"
|
||||
#include "MediaInfo.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()
|
||||
: mActor(new VideoDecoderChild())
|
||||
, mDescription("RemoteVideoDecoder")
|
||||
, mIsHardwareAccelerated(false)
|
||||
, mConversion(MediaDataDecoder::ConversionRequired::kNeedNone)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
RefPtr<Runnable> task = NS_NewRunnableFunction(
|
||||
"dom::RemoteVideoDecoder::~RemoteVideoDecoder", [actor]() {
|
||||
MOZ_ASSERT(actor);
|
||||
actor->DestroyIPDL();
|
||||
});
|
||||
|
||||
// Drop out references to the actor so that the last ref
|
||||
// always gets released on the manager thread.
|
||||
actor = nullptr;
|
||||
mActor = nullptr;
|
||||
|
||||
VideoDecoderManagerChild::GetManagerThread()->Dispatch(task.forget(),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
RefPtr<MediaDataDecoder::InitPromise>
|
||||
RemoteVideoDecoder::Init()
|
||||
{
|
||||
RefPtr<RemoteVideoDecoder> self = this;
|
||||
return InvokeAsync(VideoDecoderManagerChild::GetManagerAbstractThread(),
|
||||
__func__,
|
||||
[self]() { return self->mActor->Init(); })
|
||||
->Then(VideoDecoderManagerChild::GetManagerAbstractThread(),
|
||||
__func__,
|
||||
[self, this](TrackType aTrack) {
|
||||
mDescription =
|
||||
mActor->GetDescriptionName() + NS_LITERAL_CSTRING(" (remote)");
|
||||
mIsHardwareAccelerated =
|
||||
mActor->IsHardwareAccelerated(mHardwareAcceleratedReason);
|
||||
mConversion = mActor->NeedsConversion();
|
||||
return InitPromise::CreateAndResolve(aTrack, __func__);
|
||||
},
|
||||
[self](const MediaResult& aError) {
|
||||
return InitPromise::CreateAndReject(aError, __func__);
|
||||
});
|
||||
}
|
||||
|
||||
RefPtr<MediaDataDecoder::DecodePromise>
|
||||
RemoteVideoDecoder::Decode(MediaRawData* aSample)
|
||||
{
|
||||
RefPtr<RemoteVideoDecoder> self = this;
|
||||
RefPtr<MediaRawData> sample = aSample;
|
||||
return InvokeAsync(VideoDecoderManagerChild::GetManagerAbstractThread(),
|
||||
__func__,
|
||||
[self, sample]() { return self->mActor->Decode(sample); });
|
||||
}
|
||||
|
||||
RefPtr<MediaDataDecoder::FlushPromise>
|
||||
RemoteVideoDecoder::Flush()
|
||||
{
|
||||
RefPtr<RemoteVideoDecoder> self = this;
|
||||
return InvokeAsync(VideoDecoderManagerChild::GetManagerAbstractThread(),
|
||||
__func__, [self]() { return self->mActor->Flush(); });
|
||||
}
|
||||
|
||||
RefPtr<MediaDataDecoder::DecodePromise>
|
||||
RemoteVideoDecoder::Drain()
|
||||
{
|
||||
RefPtr<RemoteVideoDecoder> self = this;
|
||||
return InvokeAsync(VideoDecoderManagerChild::GetManagerAbstractThread(),
|
||||
__func__, [self]() { return self->mActor->Drain(); });
|
||||
}
|
||||
|
||||
RefPtr<ShutdownPromise>
|
||||
RemoteVideoDecoder::Shutdown()
|
||||
{
|
||||
RefPtr<RemoteVideoDecoder> self = this;
|
||||
return InvokeAsync(VideoDecoderManagerChild::GetManagerAbstractThread(),
|
||||
__func__, [self]() {
|
||||
self->mActor->Shutdown();
|
||||
return ShutdownPromise::CreateAndResolve(true, __func__);
|
||||
});
|
||||
}
|
||||
|
||||
bool
|
||||
RemoteVideoDecoder::IsHardwareAccelerated(nsACString& aFailureReason) const
|
||||
{
|
||||
aFailureReason = mHardwareAcceleratedReason;
|
||||
return mIsHardwareAccelerated;
|
||||
}
|
||||
|
||||
void
|
||||
RemoteVideoDecoder::SetSeekThreshold(const media::TimeUnit& aTime)
|
||||
{
|
||||
RefPtr<RemoteVideoDecoder> self = this;
|
||||
media::TimeUnit time = aTime;
|
||||
VideoDecoderManagerChild::GetManagerThread()->Dispatch(
|
||||
NS_NewRunnableFunction("dom::RemoteVideoDecoder::SetSeekThreshold",
|
||||
[=]() {
|
||||
MOZ_ASSERT(self->mActor);
|
||||
self->mActor->SetSeekThreshold(time);
|
||||
}),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
MediaDataDecoder::ConversionRequired
|
||||
RemoteVideoDecoder::NeedsConversion() const
|
||||
{
|
||||
return mConversion;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
bool
|
||||
RemoteDecoderModule::Supports(const TrackInfo& aTrackInfo,
|
||||
DecoderDoctorDiagnostics* aDiagnostics) const
|
||||
{
|
||||
return mWrapped->Supports(aTrackInfo, aDiagnostics);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsRemoteAcceleratedCompositor(KnowsCompositor* aKnows)
|
||||
{
|
||||
TextureFactoryIdentifier ident = aKnows->GetTextureFactoryIdentifier();
|
||||
return ident.mParentBackend != LayersBackend::LAYERS_BASIC &&
|
||||
ident.mParentProcessType == GeckoProcessType_GPU;
|
||||
}
|
||||
|
||||
already_AddRefed<MediaDataDecoder>
|
||||
RemoteDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
|
||||
{
|
||||
if (!StaticPrefs::MediaGpuProcessDecoder() ||
|
||||
!aParams.mKnowsCompositor ||
|
||||
!IsRemoteAcceleratedCompositor(aParams.mKnowsCompositor))
|
||||
{
|
||||
return mWrapped->CreateVideoDecoder(aParams);
|
||||
}
|
||||
|
||||
RefPtr<RemoteVideoDecoder> object = new RemoteVideoDecoder();
|
||||
|
||||
SynchronousTask task("InitIPDL");
|
||||
MediaResult result(NS_OK);
|
||||
VideoDecoderManagerChild::GetManagerThread()->Dispatch(
|
||||
NS_NewRunnableFunction(
|
||||
"dom::RemoteDecoderModule::CreateVideoDecoder",
|
||||
[&]() {
|
||||
AutoCompleteTask complete(&task);
|
||||
result = object->mActor->InitIPDL(
|
||||
aParams.VideoConfig(),
|
||||
aParams.mRate.mValue,
|
||||
aParams.mOptions,
|
||||
aParams.mKnowsCompositor->GetTextureFactoryIdentifier());
|
||||
}),
|
||||
NS_DISPATCH_NORMAL);
|
||||
task.Wait();
|
||||
|
||||
if (NS_FAILED(result)) {
|
||||
if (aParams.mError) {
|
||||
*aParams.mError = result;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return object.forget();
|
||||
}
|
||||
|
||||
nsCString
|
||||
RemoteVideoDecoder::GetDescriptionName() const
|
||||
{
|
||||
return mDescription;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
100
dom/media/ipc/RemoteVideoDecoder.h
Normal file
100
dom/media/ipc/RemoteVideoDecoder.h
Normal file
@ -0,0 +1,100 @@
|
||||
/* -*- 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/. */
|
||||
#ifndef include_dom_ipc_RemoteVideoDecoder_h
|
||||
#define include_dom_ipc_RemoteVideoDecoder_h
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "MediaData.h"
|
||||
#include "PlatformDecoderModule.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
class RemoteVideoDecoder;
|
||||
}
|
||||
DDLoggedTypeCustomNameAndBase(dom::RemoteVideoDecoder,
|
||||
RemoteVideoDecoder,
|
||||
MediaDataDecoder);
|
||||
|
||||
namespace dom {
|
||||
|
||||
class VideoDecoderChild;
|
||||
class RemoteDecoderModule;
|
||||
|
||||
// A MediaDataDecoder implementation that proxies through IPDL
|
||||
// to a 'real' decoder in the GPU process.
|
||||
// All requests get forwarded to a VideoDecoderChild instance that
|
||||
// operates solely on the VideoDecoderManagerChild thread.
|
||||
class RemoteVideoDecoder
|
||||
: public MediaDataDecoder
|
||||
, public DecoderDoctorLifeLogger<RemoteVideoDecoder>
|
||||
{
|
||||
public:
|
||||
friend class RemoteDecoderModule;
|
||||
|
||||
// MediaDataDecoder
|
||||
RefPtr<InitPromise> Init() override;
|
||||
RefPtr<DecodePromise> Decode(MediaRawData* aSample) override;
|
||||
RefPtr<DecodePromise> Drain() override;
|
||||
RefPtr<FlushPromise> Flush() override;
|
||||
RefPtr<ShutdownPromise> Shutdown() override;
|
||||
bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
|
||||
void SetSeekThreshold(const media::TimeUnit& aTime) override;
|
||||
nsCString GetDescriptionName() const override;
|
||||
ConversionRequired NeedsConversion() const override;
|
||||
|
||||
private:
|
||||
RemoteVideoDecoder();
|
||||
~RemoteVideoDecoder();
|
||||
|
||||
// Only ever written to from the reader task queue (during the constructor and
|
||||
// destructor when we can guarantee no other threads are accessing it). Only
|
||||
// read from the manager thread.
|
||||
RefPtr<VideoDecoderChild> mActor;
|
||||
// Only ever written/modified during decoder initialisation.
|
||||
// As such can be accessed from any threads after that.
|
||||
nsCString mDescription;
|
||||
bool mIsHardwareAccelerated;
|
||||
nsCString mHardwareAcceleratedReason;
|
||||
MediaDataDecoder::ConversionRequired mConversion;
|
||||
};
|
||||
|
||||
// A PDM implementation that creates RemoteVideoDecoders.
|
||||
// We currently require a 'wrapped' PDM in order to be able to answer SupportsMimeType
|
||||
// and DecoderNeedsConversion. Ideally we'd check these over IPDL using the manager
|
||||
// protocol
|
||||
class RemoteDecoderModule : public PlatformDecoderModule
|
||||
{
|
||||
public:
|
||||
explicit RemoteDecoderModule(PlatformDecoderModule* aWrapped)
|
||||
: mWrapped(aWrapped)
|
||||
{}
|
||||
|
||||
nsresult Startup() override;
|
||||
|
||||
bool SupportsMimeType(const nsACString& aMimeType,
|
||||
DecoderDoctorDiagnostics* aDiagnostics) const override;
|
||||
bool Supports(const TrackInfo& aTrackInfo,
|
||||
DecoderDoctorDiagnostics* aDiagnostics) const override;
|
||||
|
||||
already_AddRefed<MediaDataDecoder> CreateVideoDecoder(
|
||||
const CreateDecoderParams& aParams) override;
|
||||
|
||||
already_AddRefed<MediaDataDecoder> CreateAudioDecoder(
|
||||
const CreateDecoderParams& aParams) override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<PlatformDecoderModule> mWrapped;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // include_dom_ipc_RemoteVideoDecoder_h
|
@ -1,365 +0,0 @@
|
||||
/* -*- 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 "RemoteVideoDecoderChild.h"
|
||||
|
||||
#include "base/thread.h"
|
||||
#include "mozilla/layers/ImageDataSerializer.h"
|
||||
|
||||
#include "ImageContainer.h" // for PlanarYCbCrData and BufferRecycleBin
|
||||
#include "RemoteDecoderManagerChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using base::Thread;
|
||||
using namespace layers; // for PlanarYCbCrData and BufferRecycleBin
|
||||
|
||||
RemoteVideoDecoderChild::RemoteVideoDecoderChild()
|
||||
: mThread(RemoteDecoderManagerChild::GetManagerThread())
|
||||
, mCanSend(false)
|
||||
, mInitialized(false)
|
||||
, mIsHardwareAccelerated(false)
|
||||
, mConversion(MediaDataDecoder::ConversionRequired::kNeedNone)
|
||||
, mBufferRecycleBin(new BufferRecycleBin)
|
||||
{
|
||||
}
|
||||
|
||||
RemoteVideoDecoderChild::~RemoteVideoDecoderChild()
|
||||
{
|
||||
AssertOnManagerThread();
|
||||
mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
|
||||
}
|
||||
|
||||
RefPtr<mozilla::layers::Image>
|
||||
RemoteVideoDecoderChild::DeserializeImage(
|
||||
const SurfaceDescriptorBuffer& aSdBuffer,
|
||||
const IntSize& aPicSize)
|
||||
{
|
||||
MOZ_ASSERT(aSdBuffer.desc().type() == BufferDescriptor::TYCbCrDescriptor);
|
||||
if (aSdBuffer.desc().type() != BufferDescriptor::TYCbCrDescriptor) {
|
||||
return nullptr;
|
||||
}
|
||||
const YCbCrDescriptor& descriptor = aSdBuffer.desc().get_YCbCrDescriptor();
|
||||
|
||||
uint8_t* buffer = nullptr;
|
||||
const MemoryOrShmem& memOrShmem = aSdBuffer.data();
|
||||
switch (memOrShmem.type()) {
|
||||
case MemoryOrShmem::Tuintptr_t:
|
||||
buffer = reinterpret_cast<uint8_t*>(memOrShmem.get_uintptr_t());
|
||||
break;
|
||||
case MemoryOrShmem::TShmem:
|
||||
buffer = memOrShmem.get_Shmem().get<uint8_t>();
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false, "Unknown MemoryOrShmem type");
|
||||
}
|
||||
if (!buffer) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PlanarYCbCrData pData;
|
||||
pData.mYSize = descriptor.ySize();
|
||||
pData.mYStride = descriptor.yStride();
|
||||
pData.mCbCrSize = descriptor.cbCrSize();
|
||||
pData.mCbCrStride = descriptor.cbCrStride();
|
||||
// default mYSkip, mCbSkip, mCrSkip because not held in YCbCrDescriptor
|
||||
pData.mYSkip = pData.mCbSkip = pData.mCrSkip = 0;
|
||||
// default mPicX, mPicY because not held in YCbCrDescriptor
|
||||
pData.mPicX = pData.mPicY = 0;
|
||||
pData.mPicSize = aPicSize;
|
||||
pData.mStereoMode = descriptor.stereoMode();
|
||||
pData.mColorDepth = descriptor.colorDepth();
|
||||
pData.mYUVColorSpace = descriptor.yUVColorSpace();
|
||||
pData.mYChannel = ImageDataSerializer::GetYChannel(buffer, descriptor);
|
||||
pData.mCbChannel = ImageDataSerializer::GetCbChannel(buffer, descriptor);
|
||||
pData.mCrChannel = ImageDataSerializer::GetCrChannel(buffer, descriptor);
|
||||
|
||||
// images coming from AOMDecoder are RecyclingPlanarYCbCrImages.
|
||||
RefPtr<RecyclingPlanarYCbCrImage> image =
|
||||
new RecyclingPlanarYCbCrImage(mBufferRecycleBin);
|
||||
image->CopyData(pData);
|
||||
|
||||
switch (memOrShmem.type()) {
|
||||
case MemoryOrShmem::Tuintptr_t:
|
||||
delete [] reinterpret_cast<uint8_t*>(memOrShmem.get_uintptr_t());
|
||||
break;
|
||||
case MemoryOrShmem::TShmem:
|
||||
DeallocShmem(memOrShmem.get_Shmem());
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false, "Unknown MemoryOrShmem type");
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RemoteVideoDecoderChild::RecvVideoOutput(const RemoteVideoDataIPDL& aData)
|
||||
{
|
||||
AssertOnManagerThread();
|
||||
|
||||
RefPtr<Image> image = DeserializeImage(aData.sdBuffer(), aData.frameSize());
|
||||
|
||||
RefPtr<VideoData> video = VideoData::CreateFromImage(
|
||||
aData.display(),
|
||||
aData.base().offset(),
|
||||
media::TimeUnit::FromMicroseconds(aData.base().time()),
|
||||
media::TimeUnit::FromMicroseconds(aData.base().duration()),
|
||||
image,
|
||||
aData.base().keyframe(),
|
||||
media::TimeUnit::FromMicroseconds(aData.base().timecode()));
|
||||
|
||||
mDecodedData.AppendElement(std::move(video));
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RemoteVideoDecoderChild::RecvInputExhausted()
|
||||
{
|
||||
AssertOnManagerThread();
|
||||
mDecodePromise.ResolveIfExists(std::move(mDecodedData), __func__);
|
||||
mDecodedData = MediaDataDecoder::DecodedData();
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RemoteVideoDecoderChild::RecvDrainComplete()
|
||||
{
|
||||
AssertOnManagerThread();
|
||||
mDrainPromise.ResolveIfExists(std::move(mDecodedData), __func__);
|
||||
mDecodedData = MediaDataDecoder::DecodedData();
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RemoteVideoDecoderChild::RecvError(const nsresult& aError)
|
||||
{
|
||||
AssertOnManagerThread();
|
||||
mDecodedData = MediaDataDecoder::DecodedData();
|
||||
mDecodePromise.RejectIfExists(aError, __func__);
|
||||
mDrainPromise.RejectIfExists(aError, __func__);
|
||||
mFlushPromise.RejectIfExists(aError, __func__);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RemoteVideoDecoderChild::RecvInitComplete(const nsCString& aDecoderDescription,
|
||||
const ConversionRequired& aConversion)
|
||||
{
|
||||
AssertOnManagerThread();
|
||||
mInitPromise.ResolveIfExists(TrackInfo::kVideoTrack, __func__);
|
||||
mInitialized = true;
|
||||
mDescription = aDecoderDescription;
|
||||
mConversion = aConversion;
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RemoteVideoDecoderChild::RecvInitFailed(const nsresult& aReason)
|
||||
{
|
||||
AssertOnManagerThread();
|
||||
mInitPromise.RejectIfExists(aReason, __func__);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RemoteVideoDecoderChild::RecvFlushComplete()
|
||||
{
|
||||
AssertOnManagerThread();
|
||||
mFlushPromise.ResolveIfExists(true, __func__);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
RemoteVideoDecoderChild::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
mCanSend = false;
|
||||
}
|
||||
|
||||
MediaResult
|
||||
RemoteVideoDecoderChild::InitIPDL(
|
||||
const VideoInfo& aVideoInfo,
|
||||
float aFramerate,
|
||||
const CreateDecoderParams::OptionSet& aOptions)
|
||||
{
|
||||
RefPtr<RemoteDecoderManagerChild> manager =
|
||||
RemoteDecoderManagerChild::GetSingleton();
|
||||
|
||||
// The manager isn't available because RemoteDecoderManagerChild has been
|
||||
// initialized with null end points and we don't want to decode video on RDD
|
||||
// process anymore. Return false here so that we can fallback to other PDMs.
|
||||
if (!manager) {
|
||||
return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
|
||||
RESULT_DETAIL("RemoteDecoderManager is not available."));
|
||||
}
|
||||
|
||||
if (!manager->CanSend()) {
|
||||
return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
|
||||
RESULT_DETAIL("RemoteDecoderManager unable to send."));
|
||||
}
|
||||
|
||||
mIPDLSelfRef = this;
|
||||
bool success = false;
|
||||
nsCString errorDescription;
|
||||
if (manager->SendPRemoteVideoDecoderConstructor(this,
|
||||
aVideoInfo,
|
||||
aFramerate,
|
||||
aOptions,
|
||||
&success,
|
||||
&errorDescription)) {
|
||||
mCanSend = true;
|
||||
}
|
||||
|
||||
return success ? MediaResult(NS_OK) :
|
||||
MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, errorDescription);
|
||||
}
|
||||
|
||||
void
|
||||
RemoteVideoDecoderChild::DestroyIPDL()
|
||||
{
|
||||
if (mCanSend) {
|
||||
PRemoteVideoDecoderChild::Send__delete__(this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RemoteVideoDecoderChild::IPDLActorDestroyed()
|
||||
{
|
||||
mIPDLSelfRef = nullptr;
|
||||
}
|
||||
|
||||
// MediaDataDecoder methods
|
||||
|
||||
RefPtr<MediaDataDecoder::InitPromise>
|
||||
RemoteVideoDecoderChild::Init()
|
||||
{
|
||||
AssertOnManagerThread();
|
||||
|
||||
if (!mIPDLSelfRef || !mCanSend) {
|
||||
return MediaDataDecoder::InitPromise::CreateAndReject(
|
||||
NS_ERROR_DOM_MEDIA_DECODE_ERR, __func__);
|
||||
}
|
||||
|
||||
SendInit();
|
||||
|
||||
return mInitPromise.Ensure(__func__);
|
||||
}
|
||||
|
||||
RefPtr<MediaDataDecoder::DecodePromise>
|
||||
RemoteVideoDecoderChild::Decode(MediaRawData* aSample)
|
||||
{
|
||||
AssertOnManagerThread();
|
||||
|
||||
if (!mCanSend) {
|
||||
return MediaDataDecoder::DecodePromise::CreateAndReject(
|
||||
NS_ERROR_DOM_MEDIA_DECODE_ERR, __func__);
|
||||
}
|
||||
|
||||
// TODO: It would be nice to add an allocator method to
|
||||
// MediaDataDecoder so that the demuxer could write directly
|
||||
// into shmem rather than requiring a copy here.
|
||||
Shmem buffer;
|
||||
if (!AllocShmem(aSample->Size(), Shmem::SharedMemory::TYPE_BASIC, &buffer)) {
|
||||
return MediaDataDecoder::DecodePromise::CreateAndReject(
|
||||
NS_ERROR_DOM_MEDIA_DECODE_ERR, __func__);
|
||||
}
|
||||
|
||||
memcpy(buffer.get<uint8_t>(), aSample->Data(), aSample->Size());
|
||||
|
||||
MediaRawDataIPDL sample(MediaDataIPDL(aSample->mOffset,
|
||||
aSample->mTime.ToMicroseconds(),
|
||||
aSample->mTimecode.ToMicroseconds(),
|
||||
aSample->mDuration.ToMicroseconds(),
|
||||
aSample->mFrames,
|
||||
aSample->mKeyframe),
|
||||
buffer);
|
||||
SendInput(sample);
|
||||
return mDecodePromise.Ensure(__func__);
|
||||
}
|
||||
|
||||
RefPtr<MediaDataDecoder::FlushPromise>
|
||||
RemoteVideoDecoderChild::Flush()
|
||||
{
|
||||
AssertOnManagerThread();
|
||||
mDecodePromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
|
||||
mDrainPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
|
||||
if (!mCanSend) {
|
||||
return MediaDataDecoder::FlushPromise::CreateAndReject(
|
||||
NS_ERROR_DOM_MEDIA_DECODE_ERR, __func__);
|
||||
}
|
||||
SendFlush();
|
||||
return mFlushPromise.Ensure(__func__);
|
||||
}
|
||||
|
||||
RefPtr<MediaDataDecoder::DecodePromise>
|
||||
RemoteVideoDecoderChild::Drain()
|
||||
{
|
||||
AssertOnManagerThread();
|
||||
if (!mCanSend) {
|
||||
return MediaDataDecoder::DecodePromise::CreateAndReject(
|
||||
NS_ERROR_DOM_MEDIA_DECODE_ERR, __func__);
|
||||
}
|
||||
SendDrain();
|
||||
return mDrainPromise.Ensure(__func__);
|
||||
}
|
||||
|
||||
void
|
||||
RemoteVideoDecoderChild::Shutdown()
|
||||
{
|
||||
AssertOnManagerThread();
|
||||
mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
|
||||
if (mCanSend) {
|
||||
SendShutdown();
|
||||
}
|
||||
mInitialized = false;
|
||||
}
|
||||
|
||||
bool
|
||||
RemoteVideoDecoderChild::IsHardwareAccelerated(nsACString& aFailureReason) const
|
||||
{
|
||||
AssertOnManagerThread();
|
||||
aFailureReason = mHardwareAcceleratedReason;
|
||||
return mIsHardwareAccelerated;
|
||||
}
|
||||
|
||||
nsCString
|
||||
RemoteVideoDecoderChild::GetDescriptionName() const
|
||||
{
|
||||
AssertOnManagerThread();
|
||||
return mDescription;
|
||||
}
|
||||
|
||||
void
|
||||
RemoteVideoDecoderChild::SetSeekThreshold(const media::TimeUnit& aTime)
|
||||
{
|
||||
AssertOnManagerThread();
|
||||
if (mCanSend) {
|
||||
SendSetSeekThreshold(aTime.ToMicroseconds());
|
||||
}
|
||||
}
|
||||
|
||||
MediaDataDecoder::ConversionRequired
|
||||
RemoteVideoDecoderChild::NeedsConversion() const
|
||||
{
|
||||
AssertOnManagerThread();
|
||||
return mConversion;
|
||||
}
|
||||
|
||||
void
|
||||
RemoteVideoDecoderChild::AssertOnManagerThread() const
|
||||
{
|
||||
MOZ_ASSERT(NS_GetCurrentThread() == mThread);
|
||||
}
|
||||
|
||||
RemoteDecoderManagerChild*
|
||||
RemoteVideoDecoderChild::GetManager()
|
||||
{
|
||||
if (!mCanSend) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<RemoteDecoderManagerChild*>(Manager());
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
@ -1,94 +0,0 @@
|
||||
/* -*- 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/. */
|
||||
#ifndef include_dom_media_ipc_RemoteVideoDecoderChild_h
|
||||
#define include_dom_media_ipc_RemoteVideoDecoderChild_h
|
||||
#include "mozilla/PRemoteVideoDecoderChild.h"
|
||||
#include "IRemoteDecoderChild.h"
|
||||
|
||||
#include "MediaResult.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
class BufferRecycleBin;
|
||||
}
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class RemoteDecoderManagerChild;
|
||||
using mozilla::MediaDataDecoder;
|
||||
|
||||
class RemoteVideoDecoderChild final : public PRemoteVideoDecoderChild
|
||||
, public IRemoteDecoderChild
|
||||
{
|
||||
public:
|
||||
explicit RemoteVideoDecoderChild();
|
||||
|
||||
// PRemoteVideoDecoderChild
|
||||
mozilla::ipc::IPCResult RecvVideoOutput(
|
||||
const RemoteVideoDataIPDL& aData) override;
|
||||
mozilla::ipc::IPCResult RecvInputExhausted() override;
|
||||
mozilla::ipc::IPCResult RecvDrainComplete() override;
|
||||
mozilla::ipc::IPCResult RecvError(const nsresult& aError) override;
|
||||
mozilla::ipc::IPCResult RecvInitComplete(
|
||||
const nsCString& aDecoderDescription,
|
||||
const ConversionRequired& aConversion) override;
|
||||
mozilla::ipc::IPCResult RecvInitFailed(const nsresult& aReason) override;
|
||||
mozilla::ipc::IPCResult RecvFlushComplete() override;
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
// IRemoteDecoderChild
|
||||
RefPtr<MediaDataDecoder::InitPromise> Init() override;
|
||||
RefPtr<MediaDataDecoder::DecodePromise> Decode(MediaRawData* aSample) override;
|
||||
RefPtr<MediaDataDecoder::DecodePromise> Drain() override;
|
||||
RefPtr<MediaDataDecoder::FlushPromise> Flush() override;
|
||||
void Shutdown() override;
|
||||
bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
|
||||
nsCString GetDescriptionName() const override;
|
||||
void SetSeekThreshold(const media::TimeUnit& aTime) override;
|
||||
MediaDataDecoder::ConversionRequired NeedsConversion() const override;
|
||||
void DestroyIPDL() override;
|
||||
|
||||
MOZ_IS_CLASS_INIT
|
||||
MediaResult InitIPDL(const VideoInfo& aVideoInfo,
|
||||
float aFramerate,
|
||||
const CreateDecoderParams::OptionSet& aOptions);
|
||||
|
||||
// Called from IPDL when our actor has been destroyed
|
||||
void IPDLActorDestroyed();
|
||||
|
||||
RemoteDecoderManagerChild* GetManager();
|
||||
|
||||
private:
|
||||
~RemoteVideoDecoderChild();
|
||||
|
||||
void AssertOnManagerThread() const;
|
||||
RefPtr<mozilla::layers::Image> DeserializeImage(
|
||||
const SurfaceDescriptorBuffer& sdBuffer,
|
||||
const IntSize& aPicSize);
|
||||
|
||||
RefPtr<RemoteVideoDecoderChild> mIPDLSelfRef;
|
||||
RefPtr<nsIThread> mThread;
|
||||
|
||||
MozPromiseHolder<MediaDataDecoder::InitPromise> mInitPromise;
|
||||
MozPromiseHolder<MediaDataDecoder::DecodePromise> mDecodePromise;
|
||||
MozPromiseHolder<MediaDataDecoder::DecodePromise> mDrainPromise;
|
||||
MozPromiseHolder<MediaDataDecoder::FlushPromise> mFlushPromise;
|
||||
|
||||
nsCString mHardwareAcceleratedReason;
|
||||
nsCString mDescription;
|
||||
bool mCanSend;
|
||||
bool mInitialized;
|
||||
bool mIsHardwareAccelerated;
|
||||
MediaDataDecoder::ConversionRequired mConversion;
|
||||
MediaDataDecoder::DecodedData mDecodedData;
|
||||
RefPtr<mozilla::layers::BufferRecycleBin> mBufferRecycleBin;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // include_dom_media_ipc_RemoteVideoDecoderChild_h
|
@ -1,261 +0,0 @@
|
||||
/* -*- 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 "RemoteVideoDecoderParent.h"
|
||||
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
#ifdef MOZ_AV1
|
||||
#include "AOMDecoder.h"
|
||||
#endif
|
||||
#include "ImageContainer.h"
|
||||
#include "RemoteDecoderManagerParent.h"
|
||||
#include "RemoteDecoderModule.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using media::TimeUnit;
|
||||
using namespace layers; // for PlanarYCbCrImage and BufferRecycleBin
|
||||
|
||||
RemoteVideoDecoderParent::RemoteVideoDecoderParent(
|
||||
RemoteDecoderManagerParent* aParent,
|
||||
const VideoInfo& aVideoInfo,
|
||||
float aFramerate,
|
||||
const CreateDecoderParams::OptionSet& aOptions,
|
||||
TaskQueue* aManagerTaskQueue,
|
||||
TaskQueue* aDecodeTaskQueue,
|
||||
bool* aSuccess,
|
||||
nsCString* aErrorDescription)
|
||||
: mParent(aParent)
|
||||
, mManagerTaskQueue(aManagerTaskQueue)
|
||||
, mDecodeTaskQueue(aDecodeTaskQueue)
|
||||
, mDestroyed(false)
|
||||
, mVideoInfo(aVideoInfo)
|
||||
{
|
||||
MOZ_COUNT_CTOR(RemoteVideoDecoderParent);
|
||||
MOZ_ASSERT(OnManagerThread());
|
||||
// We hold a reference to ourselves to keep us alive until IPDL
|
||||
// explictly destroys us. There may still be refs held by
|
||||
// tasks, but no new ones should be added after we're
|
||||
// destroyed.
|
||||
mIPDLSelfRef = this;
|
||||
|
||||
CreateDecoderParams params(mVideoInfo);
|
||||
params.mTaskQueue = mDecodeTaskQueue;
|
||||
params.mImageContainer = new layers::ImageContainer();
|
||||
params.mRate = CreateDecoderParams::VideoFrameRate(aFramerate);
|
||||
params.mOptions = aOptions;
|
||||
MediaResult error(NS_OK);
|
||||
params.mError = &error;
|
||||
|
||||
#ifdef MOZ_AV1
|
||||
if (AOMDecoder::IsAV1(params.mConfig.mMimeType)) {
|
||||
mDecoder = new AOMDecoder(params);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (NS_FAILED(error)) {
|
||||
MOZ_ASSERT(aErrorDescription);
|
||||
*aErrorDescription = error.Description();
|
||||
}
|
||||
|
||||
*aSuccess = !!mDecoder;
|
||||
}
|
||||
|
||||
RemoteVideoDecoderParent::~RemoteVideoDecoderParent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(RemoteVideoDecoderParent);
|
||||
}
|
||||
|
||||
void
|
||||
RemoteVideoDecoderParent::Destroy()
|
||||
{
|
||||
MOZ_ASSERT(OnManagerThread());
|
||||
mDestroyed = true;
|
||||
mIPDLSelfRef = nullptr;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RemoteVideoDecoderParent::RecvInit()
|
||||
{
|
||||
MOZ_ASSERT(OnManagerThread());
|
||||
RefPtr<RemoteVideoDecoderParent> self = this;
|
||||
mDecoder->Init()->Then(mManagerTaskQueue, __func__,
|
||||
[self] (TrackInfo::TrackType aTrack) {
|
||||
MOZ_ASSERT(aTrack == TrackInfo::kVideoTrack);
|
||||
if (self->mDecoder) {
|
||||
Unused << self->SendInitComplete(self->mDecoder->GetDescriptionName(),
|
||||
self->mDecoder->NeedsConversion());
|
||||
}
|
||||
},
|
||||
[self] (MediaResult aReason) {
|
||||
if (!self->mDestroyed) {
|
||||
Unused << self->SendInitFailed(aReason);
|
||||
}
|
||||
});
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RemoteVideoDecoderParent::RecvInput(const MediaRawDataIPDL& aData)
|
||||
{
|
||||
MOZ_ASSERT(OnManagerThread());
|
||||
// XXX: This copies the data into a buffer owned by the MediaRawData. Ideally
|
||||
// we'd just take ownership of the shmem.
|
||||
RefPtr<MediaRawData> data = new MediaRawData(aData.buffer().get<uint8_t>(),
|
||||
aData.buffer().Size<uint8_t>());
|
||||
if (aData.buffer().Size<uint8_t>() && !data->Data()) {
|
||||
// OOM
|
||||
Error(NS_ERROR_OUT_OF_MEMORY);
|
||||
return IPC_OK();
|
||||
}
|
||||
data->mOffset = aData.base().offset();
|
||||
data->mTime = TimeUnit::FromMicroseconds(aData.base().time());
|
||||
data->mTimecode = TimeUnit::FromMicroseconds(aData.base().timecode());
|
||||
data->mDuration = TimeUnit::FromMicroseconds(aData.base().duration());
|
||||
data->mKeyframe = aData.base().keyframe();
|
||||
|
||||
DeallocShmem(aData.buffer());
|
||||
|
||||
RefPtr<RemoteVideoDecoderParent> self = this;
|
||||
mDecoder->Decode(data)->Then(
|
||||
mManagerTaskQueue, __func__,
|
||||
[self, this](const MediaDataDecoder::DecodedData& aResults) {
|
||||
if (mDestroyed) {
|
||||
return;
|
||||
}
|
||||
ProcessDecodedData(aResults);
|
||||
Unused << SendInputExhausted();
|
||||
},
|
||||
[self](const MediaResult& aError) { self->Error(aError); });
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
RemoteVideoDecoderParent::ProcessDecodedData(
|
||||
const MediaDataDecoder::DecodedData& aData)
|
||||
{
|
||||
MOZ_ASSERT(OnManagerThread());
|
||||
|
||||
for (const auto& data : aData) {
|
||||
MOZ_ASSERT(data->mType == MediaData::VIDEO_DATA,
|
||||
"Can only decode videos using RemoteVideoDecoderParent!");
|
||||
VideoData* video = static_cast<VideoData*>(data.get());
|
||||
|
||||
MOZ_ASSERT(video->mImage, "Decoded video must output a layer::Image to "
|
||||
"be used with RemoteVideoDecoderParent");
|
||||
|
||||
PlanarYCbCrImage* image =
|
||||
static_cast<PlanarYCbCrImage*>(video->mImage.get());
|
||||
|
||||
SurfaceDescriptorBuffer sdBuffer;
|
||||
Shmem buffer;
|
||||
if (AllocShmem(image->GetDataSize(),
|
||||
Shmem::SharedMemory::TYPE_BASIC, &buffer) &&
|
||||
image->GetDataSize() == buffer.Size<uint8_t>()) {
|
||||
sdBuffer.data() = buffer;
|
||||
image->BuildSurfaceDescriptorBuffer(sdBuffer);
|
||||
}
|
||||
|
||||
RemoteVideoDataIPDL output(
|
||||
MediaDataIPDL(data->mOffset, data->mTime.ToMicroseconds(),
|
||||
data->mTimecode.ToMicroseconds(),
|
||||
data->mDuration.ToMicroseconds(),
|
||||
data->mFrames, data->mKeyframe),
|
||||
video->mDisplay,
|
||||
image->GetSize(),
|
||||
sdBuffer,
|
||||
video->mFrameID);
|
||||
Unused << SendVideoOutput(output);
|
||||
}
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RemoteVideoDecoderParent::RecvFlush()
|
||||
{
|
||||
MOZ_ASSERT(!mDestroyed);
|
||||
MOZ_ASSERT(OnManagerThread());
|
||||
RefPtr<RemoteVideoDecoderParent> self = this;
|
||||
mDecoder->Flush()->Then(
|
||||
mManagerTaskQueue, __func__,
|
||||
[self]() {
|
||||
if (!self->mDestroyed) {
|
||||
Unused << self->SendFlushComplete();
|
||||
}
|
||||
},
|
||||
[self](const MediaResult& aError) { self->Error(aError); });
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RemoteVideoDecoderParent::RecvDrain()
|
||||
{
|
||||
MOZ_ASSERT(!mDestroyed);
|
||||
MOZ_ASSERT(OnManagerThread());
|
||||
RefPtr<RemoteVideoDecoderParent> self = this;
|
||||
mDecoder->Drain()->Then(
|
||||
mManagerTaskQueue, __func__,
|
||||
[self, this](const MediaDataDecoder::DecodedData& aResults) {
|
||||
if (!mDestroyed) {
|
||||
ProcessDecodedData(aResults);
|
||||
Unused << SendDrainComplete();
|
||||
}
|
||||
},
|
||||
[self](const MediaResult& aError) { self->Error(aError); });
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RemoteVideoDecoderParent::RecvShutdown()
|
||||
{
|
||||
MOZ_ASSERT(!mDestroyed);
|
||||
MOZ_ASSERT(OnManagerThread());
|
||||
if (mDecoder) {
|
||||
mDecoder->Shutdown();
|
||||
}
|
||||
mDecoder = nullptr;
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RemoteVideoDecoderParent::RecvSetSeekThreshold(const int64_t& aTime)
|
||||
{
|
||||
MOZ_ASSERT(!mDestroyed);
|
||||
MOZ_ASSERT(OnManagerThread());
|
||||
mDecoder->SetSeekThreshold(TimeUnit::FromMicroseconds(aTime));
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
RemoteVideoDecoderParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
MOZ_ASSERT(!mDestroyed);
|
||||
MOZ_ASSERT(OnManagerThread());
|
||||
if (mDecoder) {
|
||||
mDecoder->Shutdown();
|
||||
mDecoder = nullptr;
|
||||
}
|
||||
if (mDecodeTaskQueue) {
|
||||
mDecodeTaskQueue->BeginShutdown();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RemoteVideoDecoderParent::Error(const MediaResult& aError)
|
||||
{
|
||||
MOZ_ASSERT(OnManagerThread());
|
||||
if (!mDestroyed) {
|
||||
Unused << SendError(aError);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RemoteVideoDecoderParent::OnManagerThread()
|
||||
{
|
||||
return mParent->OnManagerThread();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
@ -1,62 +0,0 @@
|
||||
/* -*- 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/. */
|
||||
#ifndef include_dom_media_ipc_RemoteVideoDecoderParent_h
|
||||
#define include_dom_media_ipc_RemoteVideoDecoderParent_h
|
||||
#include "mozilla/PRemoteVideoDecoderParent.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class RemoteDecoderManagerParent;
|
||||
|
||||
class RemoteVideoDecoderParent final : public PRemoteVideoDecoderParent
|
||||
{
|
||||
public:
|
||||
// We refcount this class since the task queue can have runnables
|
||||
// that reference us.
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteVideoDecoderParent)
|
||||
|
||||
RemoteVideoDecoderParent(RemoteDecoderManagerParent* aParent,
|
||||
const VideoInfo& aVideoInfo,
|
||||
float aFramerate,
|
||||
const CreateDecoderParams::OptionSet& aOptions,
|
||||
TaskQueue* aManagerTaskQueue,
|
||||
TaskQueue* aDecodeTaskQueue,
|
||||
bool* aSuccess,
|
||||
nsCString* aErrorDescription);
|
||||
|
||||
void Destroy();
|
||||
|
||||
// PRemoteVideoDecoderParent
|
||||
mozilla::ipc::IPCResult RecvInit() override;
|
||||
mozilla::ipc::IPCResult RecvInput(const MediaRawDataIPDL& aData) override;
|
||||
mozilla::ipc::IPCResult RecvFlush() override;
|
||||
mozilla::ipc::IPCResult RecvDrain() override;
|
||||
mozilla::ipc::IPCResult RecvShutdown() override;
|
||||
mozilla::ipc::IPCResult RecvSetSeekThreshold(const int64_t& aTime) override;
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
private:
|
||||
bool OnManagerThread();
|
||||
void Error(const MediaResult& aError);
|
||||
|
||||
~RemoteVideoDecoderParent();
|
||||
void ProcessDecodedData(const MediaDataDecoder::DecodedData& aData);
|
||||
|
||||
RefPtr<RemoteDecoderManagerParent> mParent;
|
||||
RefPtr<RemoteVideoDecoderParent> mIPDLSelfRef;
|
||||
RefPtr<TaskQueue> mManagerTaskQueue;
|
||||
RefPtr<TaskQueue> mDecodeTaskQueue;
|
||||
RefPtr<MediaDataDecoder> mDecoder;
|
||||
|
||||
// Can only be accessed from the manager thread
|
||||
bool mDestroyed;
|
||||
VideoInfo mVideoInfo;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // include_dom_media_ipc_RemoteVideoDecoderParent_h
|
@ -9,7 +9,6 @@
|
||||
#include "MediaResult.h"
|
||||
#include "PlatformDecoderModule.h"
|
||||
#include "mozilla/dom/PVideoDecoderChild.h"
|
||||
#include "IRemoteDecoderChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -19,11 +18,12 @@ class RemoteDecoderModule;
|
||||
class VideoDecoderManagerChild;
|
||||
|
||||
class VideoDecoderChild final : public PVideoDecoderChild
|
||||
, public IRemoteDecoderChild
|
||||
{
|
||||
public:
|
||||
explicit VideoDecoderChild();
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoDecoderChild)
|
||||
|
||||
// PVideoDecoderChild
|
||||
mozilla::ipc::IPCResult RecvOutput(const VideoDataIPDL& aData) override;
|
||||
mozilla::ipc::IPCResult RecvInputExhausted() override;
|
||||
@ -38,22 +38,22 @@ public:
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
RefPtr<MediaDataDecoder::InitPromise> Init() override;
|
||||
RefPtr<MediaDataDecoder::DecodePromise> Decode(MediaRawData* aSample) override;
|
||||
RefPtr<MediaDataDecoder::DecodePromise> Drain() override;
|
||||
RefPtr<MediaDataDecoder::FlushPromise> Flush() override;
|
||||
void Shutdown() override;
|
||||
bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
|
||||
nsCString GetDescriptionName() const override;
|
||||
void SetSeekThreshold(const media::TimeUnit& aTime) override;
|
||||
MediaDataDecoder::ConversionRequired NeedsConversion() const override;
|
||||
void DestroyIPDL() override;
|
||||
RefPtr<MediaDataDecoder::InitPromise> Init();
|
||||
RefPtr<MediaDataDecoder::DecodePromise> Decode(MediaRawData* aSample);
|
||||
RefPtr<MediaDataDecoder::DecodePromise> Drain();
|
||||
RefPtr<MediaDataDecoder::FlushPromise> Flush();
|
||||
void Shutdown();
|
||||
bool IsHardwareAccelerated(nsACString& aFailureReason) const;
|
||||
nsCString GetDescriptionName() const;
|
||||
void SetSeekThreshold(const media::TimeUnit& aTime);
|
||||
MediaDataDecoder::ConversionRequired NeedsConversion() const;
|
||||
|
||||
MOZ_IS_CLASS_INIT
|
||||
MediaResult InitIPDL(const VideoInfo& aVideoInfo,
|
||||
float aFramerate,
|
||||
const CreateDecoderParams::OptionSet& aOptions,
|
||||
const layers::TextureFactoryIdentifier& aIdentifier);
|
||||
void DestroyIPDL();
|
||||
|
||||
// Called from IPDL when our actor has been destroyed
|
||||
void IPDLActorDestroyed();
|
||||
|
@ -6,46 +6,19 @@
|
||||
|
||||
|
||||
IPDL_SOURCES += [
|
||||
'PMediaDecoderParams.ipdlh',
|
||||
'PRDD.ipdl',
|
||||
'PRemoteDecoderManager.ipdl',
|
||||
'PRemoteVideoDecoder.ipdl',
|
||||
'PVideoDecoder.ipdl',
|
||||
'PVideoDecoderManager.ipdl',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla += [
|
||||
'GpuDecoderModule.h',
|
||||
'RDDChild.h',
|
||||
'RDDParent.h',
|
||||
'RDDProcessHost.h',
|
||||
'RDDProcessImpl.h',
|
||||
'RDDProcessManager.h',
|
||||
'RemoteDecoderManagerChild.h',
|
||||
'RemoteDecoderManagerParent.h',
|
||||
'RemoteDecoderModule.h',
|
||||
'RemoteMediaDataDecoder.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'MediaIPCUtils.h',
|
||||
'RemoteVideoDecoder.h',
|
||||
'VideoDecoderManagerChild.h',
|
||||
'VideoDecoderManagerParent.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'GpuDecoderModule.cpp',
|
||||
'RDDChild.cpp',
|
||||
'RDDParent.cpp',
|
||||
'RDDProcessHost.cpp',
|
||||
'RDDProcessImpl.cpp',
|
||||
'RDDProcessManager.cpp',
|
||||
'RemoteDecoderManagerChild.cpp',
|
||||
'RemoteDecoderManagerParent.cpp',
|
||||
'RemoteDecoderModule.cpp',
|
||||
'RemoteMediaDataDecoder.cpp',
|
||||
'RemoteVideoDecoderChild.cpp',
|
||||
'RemoteVideoDecoderParent.cpp',
|
||||
'RemoteVideoDecoder.cpp',
|
||||
'VideoDecoderChild.cpp',
|
||||
'VideoDecoderManagerChild.cpp',
|
||||
'VideoDecoderManagerParent.cpp',
|
||||
|
@ -45,8 +45,7 @@
|
||||
|
||||
#include "MP4Decoder.h"
|
||||
#include "VPXDecoder.h"
|
||||
#include "mozilla/GpuDecoderModule.h"
|
||||
#include "mozilla/RemoteDecoderModule.h"
|
||||
#include "mozilla/dom/RemoteVideoDecoder.h"
|
||||
|
||||
#include "H264.h"
|
||||
|
||||
@ -353,15 +352,10 @@ PDMFactory::CreatePDMs()
|
||||
return;
|
||||
}
|
||||
|
||||
if (StaticPrefs::MediaRddProcessEnabled()) {
|
||||
m = new RemoteDecoderModule;
|
||||
StartupPDM(m);
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
if (StaticPrefs::MediaWmfEnabled() && !IsWin7AndPre2000Compatible()) {
|
||||
m = new WMFDecoderModule();
|
||||
RefPtr<PlatformDecoderModule> remote = new GpuDecoderModule(m);
|
||||
RefPtr<PlatformDecoderModule> remote = new dom::RemoteDecoderModule(m);
|
||||
StartupPDM(remote);
|
||||
mWMFFailedToLoad = !StartupPDM(m);
|
||||
} else {
|
||||
|
@ -33,9 +33,11 @@ namespace layers {
|
||||
class ImageContainer;
|
||||
} // namespace layers
|
||||
|
||||
class GpuDecoderModule;
|
||||
class MediaDataDecoder;
|
||||
namespace dom {
|
||||
class RemoteDecoderModule;
|
||||
}
|
||||
|
||||
class MediaDataDecoder;
|
||||
class TaskQueue;
|
||||
class CDMProxy;
|
||||
|
||||
@ -212,9 +214,8 @@ protected:
|
||||
|
||||
friend class MediaChangeMonitor;
|
||||
friend class PDMFactory;
|
||||
friend class GpuDecoderModule;
|
||||
friend class dom::RemoteDecoderModule;
|
||||
friend class EMEDecoderModule;
|
||||
friend class RemoteDecoderModule;
|
||||
|
||||
// Indicates if the PlatformDecoderModule supports decoding of aColorDepth.
|
||||
// Should override this method when the platform can support color depth != 8.
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "AppleDecoderModule.h"
|
||||
#include "AppleUtils.h"
|
||||
#include "AppleVTLinker.h"
|
||||
#include "MacIOSurfaceImage.h"
|
||||
#include "MediaData.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "H264.h"
|
||||
@ -437,7 +436,7 @@ AppleVTDecoder::OutputFrame(CVPixelBufferRef aImage,
|
||||
|
||||
RefPtr<MacIOSurface> macSurface = new MacIOSurface(surface);
|
||||
|
||||
RefPtr<layers::Image> image = new layers::MacIOSurfaceImage(macSurface);
|
||||
RefPtr<layers::Image> image = new MacIOSurfaceImage(macSurface);
|
||||
|
||||
data =
|
||||
VideoData::CreateFromImage(info.mDisplay,
|
||||
|
@ -4,12 +4,8 @@
|
||||
* 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 "VsyncBridgeParent.h"
|
||||
#include "mozilla/layers/CompositorBridgeParent.h"
|
||||
#include "mozilla/layers/CompositorThread.h"
|
||||
|
||||
using mozilla::layers::CompositorBridgeParent;
|
||||
using mozilla::layers::CompositorThreadHolder;
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "mozilla/layers/CompositorTypes.h"
|
||||
#include "mozilla/layers/ImageBridgeChild.h" // for ImageBridgeChild
|
||||
#include "mozilla/layers/ImageClient.h" // for ImageClient
|
||||
#include "mozilla/layers/ImageDataSerializer.h" // for SurfaceDescriptorBuffer
|
||||
#include "mozilla/layers/LayersMessages.h"
|
||||
#include "mozilla/layers/SharedPlanarYCbCrImage.h"
|
||||
#include "mozilla/layers/SharedSurfacesChild.h" // for SharedSurfacesAnimation
|
||||
@ -52,10 +51,6 @@ Atomic<int32_t> Image::sSerialCounter(0);
|
||||
|
||||
Atomic<uint32_t> ImageContainer::sGenerationCounter(0);
|
||||
|
||||
static void
|
||||
CopyPlane(uint8_t* aDst, const uint8_t* aSrc,
|
||||
const gfx::IntSize& aSize, int32_t aStride, int32_t aSkip);
|
||||
|
||||
RefPtr<PlanarYCbCrImage>
|
||||
ImageFactory::CreatePlanarYCbCrImage(const gfx::IntSize& aScaleHint, BufferRecycleBin *aRecycleBin)
|
||||
{
|
||||
@ -487,61 +482,6 @@ PlanarYCbCrImage::PlanarYCbCrImage()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
PlanarYCbCrImage::BuildSurfaceDescriptorBuffer(
|
||||
SurfaceDescriptorBuffer& aSdBuffer)
|
||||
{
|
||||
const PlanarYCbCrData* pdata = GetData();
|
||||
MOZ_ASSERT(pdata, "must have PlanarYCbCrData");
|
||||
MOZ_ASSERT(pdata->mYSkip == 0 && pdata->mCbSkip == 0 && pdata->mCrSkip == 0,
|
||||
"YCbCrDescriptor doesn't hold skip values");
|
||||
MOZ_ASSERT(pdata->mPicX == 0 && pdata->mPicY == 0,
|
||||
"YCbCrDescriptor doesn't hold picx or picy");
|
||||
|
||||
uint32_t yOffset;
|
||||
uint32_t cbOffset;
|
||||
uint32_t crOffset;
|
||||
ImageDataSerializer::ComputeYCbCrOffsets(pdata->mYStride,
|
||||
pdata->mYSize.height,
|
||||
pdata->mCbCrStride,
|
||||
pdata->mCbCrSize.height,
|
||||
yOffset, cbOffset, crOffset);
|
||||
|
||||
aSdBuffer.desc() = YCbCrDescriptor(pdata->mYSize, pdata->mYStride,
|
||||
pdata->mCbCrSize, pdata->mCbCrStride,
|
||||
yOffset, cbOffset, crOffset,
|
||||
pdata->mStereoMode,
|
||||
pdata->mColorDepth,
|
||||
pdata->mYUVColorSpace,
|
||||
/*hasIntermediateBuffer*/ false);
|
||||
|
||||
uint8_t* buffer = nullptr;
|
||||
const MemoryOrShmem& memOrShmem = aSdBuffer.data();
|
||||
switch (memOrShmem.type()) {
|
||||
case MemoryOrShmem::Tuintptr_t:
|
||||
buffer = reinterpret_cast<uint8_t*>(memOrShmem.get_uintptr_t());
|
||||
break;
|
||||
case MemoryOrShmem::TShmem:
|
||||
buffer = memOrShmem.get_Shmem().get<uint8_t>();
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false, "Unknown MemoryOrShmem type");
|
||||
}
|
||||
MOZ_ASSERT(buffer, "no valid buffer available to copy image data");
|
||||
if (!buffer) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
CopyPlane(buffer+yOffset, pdata->mYChannel,
|
||||
pdata->mYSize, pdata->mYStride, pdata->mYSkip);
|
||||
CopyPlane(buffer+cbOffset, pdata->mCbChannel,
|
||||
pdata->mCbCrSize, pdata->mCbCrStride, pdata->mCbSkip);
|
||||
CopyPlane(buffer+crOffset, pdata->mCrChannel,
|
||||
pdata->mCbCrSize, pdata->mCbCrStride, pdata->mCrSkip);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
RecyclingPlanarYCbCrImage::~RecyclingPlanarYCbCrImage()
|
||||
{
|
||||
if (mBuffer) {
|
||||
|
@ -170,7 +170,6 @@ class NVImage;
|
||||
#ifdef XP_WIN
|
||||
class D3D11YCbCrRecycleAllocator;
|
||||
#endif
|
||||
class SurfaceDescriptorBuffer;
|
||||
|
||||
struct ImageBackendData
|
||||
{
|
||||
@ -889,14 +888,6 @@ public:
|
||||
|
||||
PlanarYCbCrImage* AsPlanarYCbCrImage() override { return this; }
|
||||
|
||||
/**
|
||||
* Build a SurfaceDescriptorBuffer with this image. The provided
|
||||
* SurfaceDescriptorBuffer must already have a valid MemoryOrShmem set
|
||||
* with a capacity large enough to hold |GetDataSize|.
|
||||
*/
|
||||
virtual nsresult BuildSurfaceDescriptorBuffer(
|
||||
SurfaceDescriptorBuffer& aSdBuffer);
|
||||
|
||||
protected:
|
||||
already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/FontPropertyTypes.h"
|
||||
#include "mozilla/RDDProcessManager.h"
|
||||
#include "mozilla/image/ImageMemoryReporter.h"
|
||||
#include "mozilla/layers/CompositorManagerChild.h"
|
||||
#include "mozilla/layers/CompositorThread.h"
|
||||
@ -768,7 +767,6 @@ void
|
||||
gfxPlatform::Init()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(!XRE_IsGPUProcess(), "GFX: Not allowed in GPU process.");
|
||||
MOZ_RELEASE_ASSERT(!XRE_IsRDDProcess(), "GFX: Not allowed in RDD process.");
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread(), "GFX: Not in main thread.");
|
||||
|
||||
if (gEverInitialized) {
|
||||
@ -784,7 +782,6 @@ gfxPlatform::Init()
|
||||
|
||||
if (XRE_IsParentProcess() || recordreplay::IsRecordingOrReplaying()) {
|
||||
GPUProcessManager::Initialize();
|
||||
RDDProcessManager::Initialize();
|
||||
|
||||
if (Preferences::GetBool("media.wmf.skip-blacklist")) {
|
||||
gfxVars::SetPDMWMFDisableD3D11Dlls(nsCString());
|
||||
@ -886,12 +883,6 @@ gfxPlatform::Init()
|
||||
gpu->LaunchGPUProcess();
|
||||
}
|
||||
|
||||
if (XRE_IsParentProcess() &&
|
||||
Preferences::GetBool("media.rdd-process.enabled", false)) {
|
||||
RDDProcessManager* rdd = RDDProcessManager::Get();
|
||||
if (rdd) { rdd->LaunchRDDProcess(); }
|
||||
}
|
||||
|
||||
if (XRE_IsParentProcess() || recordreplay::IsRecordingOrReplaying()) {
|
||||
if (gfxPlatform::ForceSoftwareVsync()) {
|
||||
gPlatform->mVsyncSource = (gPlatform)->gfxPlatform::CreateHardwareVsyncSource();
|
||||
@ -1170,7 +1161,6 @@ gfxPlatform::Shutdown()
|
||||
if (XRE_IsParentProcess()) {
|
||||
GPUProcessManager::Shutdown();
|
||||
VRProcessManager::Shutdown();
|
||||
RDDProcessManager::Shutdown();
|
||||
}
|
||||
|
||||
gfx::Factory::ShutDown();
|
||||
|
@ -94,9 +94,6 @@ CrashReporterHost::FinalizeCrashReport()
|
||||
case GeckoProcessType_GPU:
|
||||
type = NS_LITERAL_CSTRING("gpu");
|
||||
break;
|
||||
case GeckoProcessType_RDD:
|
||||
type = NS_LITERAL_CSTRING("rdd");
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("unknown process type");
|
||||
break;
|
||||
@ -169,10 +166,6 @@ CrashReporterHost::NotifyCrashService(GeckoProcessType aProcessType,
|
||||
processType = nsICrashService::PROCESS_TYPE_GPU;
|
||||
telemetryKey.AssignLiteral("gpu");
|
||||
break;
|
||||
case GeckoProcessType_RDD:
|
||||
processType = nsICrashService::PROCESS_TYPE_RDD;
|
||||
telemetryKey.AssignLiteral("rdd");
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("unknown process type");
|
||||
return;
|
||||
|
@ -143,10 +143,8 @@ auto
|
||||
GeckoChildProcessHost::GetPathToBinary(FilePath& exePath, GeckoProcessType processType) -> BinaryPathType
|
||||
{
|
||||
if (sRunSelfAsContentProc &&
|
||||
(processType == GeckoProcessType_Content ||
|
||||
processType == GeckoProcessType_GPU ||
|
||||
processType == GeckoProcessType_VR ||
|
||||
processType == GeckoProcessType_RDD)) {
|
||||
(processType == GeckoProcessType_Content || processType == GeckoProcessType_GPU ||
|
||||
processType == GeckoProcessType_VR)) {
|
||||
#if defined(OS_WIN)
|
||||
wchar_t exePathBuf[MAXPATHLEN];
|
||||
if (!::GetModuleFileNameW(nullptr, exePathBuf, MAXPATHLEN)) {
|
||||
@ -747,12 +745,9 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector<std::string> aExtraOpts)
|
||||
// Add the application directory path (-appdir path)
|
||||
AddAppDirToCommandLine(childArgv);
|
||||
|
||||
// Tmp dir that the GPU or RDD process should use for crash reports.
|
||||
// This arg is always populated (but possibly with an empty value) for
|
||||
// a GPU or RDD child process.
|
||||
if (mProcessType == GeckoProcessType_GPU ||
|
||||
mProcessType == GeckoProcessType_RDD ||
|
||||
mProcessType == GeckoProcessType_VR) {
|
||||
// Tmp dir that the GPU process should use for crash reports. This arg is
|
||||
// always populated (but possibly with an empty value) for a GPU child process.
|
||||
if (mProcessType == GeckoProcessType_GPU || mProcessType == GeckoProcessType_VR) {
|
||||
nsCOMPtr<nsIFile> file;
|
||||
CrashReporter::GetChildProcessTmpDir(getter_AddRefs(file));
|
||||
nsAutoCString path;
|
||||
@ -994,11 +989,6 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector<std::string> aExtraOpts)
|
||||
// TODO: Implement sandbox for VR process, Bug 1430043.
|
||||
}
|
||||
break;
|
||||
case GeckoProcessType_RDD:
|
||||
if (mSandboxLevel > 0 && !PR_GetEnv("MOZ_DISABLE_RDD_SANDBOX")) {
|
||||
// TODO: Implement sandbox for RDD process, Bug 1498624.
|
||||
}
|
||||
break;
|
||||
case GeckoProcessType_Default:
|
||||
default:
|
||||
MOZ_CRASH("Bad process type in GeckoChildProcessHost");
|
||||
@ -1024,11 +1014,9 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector<std::string> aExtraOpts)
|
||||
// Win app model id
|
||||
cmdLine.AppendLooseValue(mGroupId.get());
|
||||
|
||||
// Tmp dir that the GPU or RDD process should use for crash reports.
|
||||
// This arg is always populated (but possibly with an empty value) for
|
||||
// a GPU or RDD child process.
|
||||
if (mProcessType == GeckoProcessType_GPU ||
|
||||
mProcessType == GeckoProcessType_RDD) {
|
||||
// Tmp dir that the GPU process should use for crash reports. This arg is
|
||||
// always populated (but possibly with an empty value) for a GPU child process.
|
||||
if (mProcessType == GeckoProcessType_GPU) {
|
||||
nsCOMPtr<nsIFile> file;
|
||||
CrashReporter::GetChildProcessTmpDir(getter_AddRefs(file));
|
||||
nsString path;
|
||||
@ -1083,7 +1071,6 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector<std::string> aExtraOpts)
|
||||
// child processes.
|
||||
if (mProcessType == GeckoProcessType_Content ||
|
||||
mProcessType == GeckoProcessType_GPU ||
|
||||
mProcessType == GeckoProcessType_RDD ||
|
||||
mProcessType == GeckoProcessType_VR ||
|
||||
mProcessType == GeckoProcessType_GMPlugin) {
|
||||
if (!mSandboxBroker.AddTargetPeer(process)) {
|
||||
|
@ -914,8 +914,6 @@ description =
|
||||
description =
|
||||
[PGMPVideoEncoder::NeedShmem]
|
||||
description =
|
||||
[PRemoteDecoderManager::PRemoteVideoDecoder]
|
||||
description = See Bug 1505976 - investigate changing to async instead of matching GPU pattern
|
||||
[PVideoDecoderManager::PVideoDecoder]
|
||||
description =
|
||||
[PVideoDecoderManager::Readback]
|
||||
|
@ -226,12 +226,11 @@ nsLayoutModuleInitialize()
|
||||
return;
|
||||
}
|
||||
|
||||
if (XRE_GetProcessType() == GeckoProcessType_GPU ||
|
||||
XRE_GetProcessType() == GeckoProcessType_RDD) {
|
||||
// We mark the layout module as being available in the GPU and RDD
|
||||
// process so that XPCOM's component manager initializes the power
|
||||
// manager service, which is needed for nsAppShell. However, we
|
||||
// don't actually need anything in the layout module itself.
|
||||
if (XRE_GetProcessType() == GeckoProcessType_GPU) {
|
||||
// We mark the layout module as being available in the GPU process so that
|
||||
// XPCOM's component manager initializes the power manager service, which
|
||||
// is needed for nsAppShell. However, we don't actually need anything in
|
||||
// the layout module itself.
|
||||
return;
|
||||
}
|
||||
|
||||
@ -677,8 +676,7 @@ static void
|
||||
LayoutModuleDtor()
|
||||
{
|
||||
if (XRE_GetProcessType() == GeckoProcessType_GPU ||
|
||||
XRE_GetProcessType() == GeckoProcessType_VR ||
|
||||
XRE_GetProcessType() == GeckoProcessType_RDD) {
|
||||
XRE_GetProcessType() == GeckoProcessType_VR) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1069,18 +1069,6 @@ VARCACHE_PREF(
|
||||
)
|
||||
#undef PREF_VALUE
|
||||
|
||||
VARCACHE_PREF(
|
||||
"media.rdd-process.enabled",
|
||||
MediaRddProcessEnabled,
|
||||
RelaxedAtomicBool, false
|
||||
)
|
||||
|
||||
VARCACHE_PREF(
|
||||
"media.rdd-process.startup_timeout_ms",
|
||||
MediaRddProcessStartupTimeoutMs,
|
||||
RelaxedAtomicInt32, 5000
|
||||
)
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
// Enable the MediaCodec PlatformDecoderModule by default.
|
||||
|
@ -177,9 +177,6 @@ this.CrashManager.prototype = Object.freeze({
|
||||
// A crash in the GPU process.
|
||||
PROCESS_TYPE_GPU: "gpu",
|
||||
|
||||
// A crash in the RDD process.
|
||||
PROCESS_TYPE_RDD: "rdd",
|
||||
|
||||
// A real crash.
|
||||
CRASH_TYPE_CRASH: "crash",
|
||||
|
||||
@ -463,8 +460,7 @@ this.CrashManager.prototype = Object.freeze({
|
||||
|
||||
// Send a telemetry ping for each non-main process crash
|
||||
if (processType === this.PROCESS_TYPE_CONTENT ||
|
||||
processType === this.PROCESS_TYPE_GPU ||
|
||||
processType === this.PROCESS_TYPE_RDD) {
|
||||
processType === this.PROCESS_TYPE_GPU) {
|
||||
this._sendCrashPing(id, processType, date, metadata);
|
||||
}
|
||||
})();
|
||||
|
@ -179,9 +179,6 @@ CrashService.prototype = Object.freeze({
|
||||
case Ci.nsICrashService.PROCESS_TYPE_GPU:
|
||||
processType = Services.crashmanager.PROCESS_TYPE_GPU;
|
||||
break;
|
||||
case Ci.nsICrashService.PROCESS_TYPE_RDD:
|
||||
processType = Services.crashmanager.PROCESS_TYPE_RDD;
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unrecognized PROCESS_TYPE: " + processType);
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ interface nsICrashService : nsISupports
|
||||
const long PROCESS_TYPE_PLUGIN = 2;
|
||||
const long PROCESS_TYPE_GMPLUGIN = 3;
|
||||
const long PROCESS_TYPE_GPU = 4;
|
||||
const long PROCESS_TYPE_RDD = 5;
|
||||
|
||||
const long CRASH_TYPE_CRASH = 0;
|
||||
const long CRASH_TYPE_HANG = 1;
|
||||
|
@ -394,8 +394,6 @@ add_task(async function test_addCrash() {
|
||||
"gmplugin-crash", DUMMY_DATE);
|
||||
await m.addCrash(m.PROCESS_TYPE_GPU, m.CRASH_TYPE_CRASH,
|
||||
"gpu-crash", DUMMY_DATE);
|
||||
await m.addCrash(m.PROCESS_TYPE_RDD, m.CRASH_TYPE_CRASH,
|
||||
"rdd-crash", DUMMY_DATE);
|
||||
|
||||
await m.addCrash(m.PROCESS_TYPE_MAIN, m.CRASH_TYPE_CRASH,
|
||||
"changing-item", DUMMY_DATE);
|
||||
@ -403,7 +401,7 @@ add_task(async function test_addCrash() {
|
||||
"changing-item", DUMMY_DATE_2);
|
||||
|
||||
crashes = await m.getCrashes();
|
||||
Assert.equal(crashes.length, 10);
|
||||
Assert.equal(crashes.length, 9);
|
||||
|
||||
let map = new Map(crashes.map(crash => [crash.id, crash]));
|
||||
|
||||
@ -455,12 +453,6 @@ add_task(async function test_addCrash() {
|
||||
Assert.equal(crash.type, m.PROCESS_TYPE_GPU + "-" + m.CRASH_TYPE_CRASH);
|
||||
Assert.ok(crash.isOfType(m.PROCESS_TYPE_GPU, m.CRASH_TYPE_CRASH));
|
||||
|
||||
crash = map.get("rdd-crash");
|
||||
Assert.ok(!!crash);
|
||||
Assert.equal(crash.crashDate, DUMMY_DATE);
|
||||
Assert.equal(crash.type, m.PROCESS_TYPE_RDD + "-" + m.CRASH_TYPE_CRASH);
|
||||
Assert.ok(crash.isOfType(m.PROCESS_TYPE_RDD, m.CRASH_TYPE_CRASH));
|
||||
|
||||
crash = map.get("changing-item");
|
||||
Assert.ok(!!crash);
|
||||
Assert.equal(crash.crashDate, DUMMY_DATE_2);
|
||||
@ -473,7 +465,6 @@ add_task(async function test_child_process_crash_ping() {
|
||||
const EXPECTED_PROCESSES = [
|
||||
m.PROCESS_TYPE_CONTENT,
|
||||
m.PROCESS_TYPE_GPU,
|
||||
m.PROCESS_TYPE_RDD,
|
||||
];
|
||||
|
||||
const UNEXPECTED_PROCESSES = [
|
||||
|
@ -22,7 +22,6 @@ const {
|
||||
PROCESS_TYPE_PLUGIN,
|
||||
PROCESS_TYPE_GMPLUGIN,
|
||||
PROCESS_TYPE_GPU,
|
||||
PROCESS_TYPE_RDD,
|
||||
CRASH_TYPE_CRASH,
|
||||
CRASH_TYPE_HANG,
|
||||
SUBMISSION_RESULT_OK,
|
||||
@ -354,33 +353,6 @@ add_task(async function test_add_gpu_crash() {
|
||||
Assert.equal(crashes.length, 2);
|
||||
});
|
||||
|
||||
add_task(async function test_add_rdd_crash() {
|
||||
let s = await getStore();
|
||||
|
||||
Assert.ok(
|
||||
s.addCrash(PROCESS_TYPE_RDD, CRASH_TYPE_CRASH, "id1", new Date())
|
||||
);
|
||||
Assert.equal(s.crashesCount, 1);
|
||||
|
||||
let c = s.crashes[0];
|
||||
Assert.ok(c.crashDate);
|
||||
Assert.equal(c.type, PROCESS_TYPE_RDD + "-" + CRASH_TYPE_CRASH);
|
||||
Assert.ok(c.isOfType(PROCESS_TYPE_RDD, CRASH_TYPE_CRASH));
|
||||
|
||||
Assert.ok(
|
||||
s.addCrash(PROCESS_TYPE_RDD, CRASH_TYPE_CRASH, "id2", new Date())
|
||||
);
|
||||
Assert.equal(s.crashesCount, 2);
|
||||
|
||||
Assert.ok(
|
||||
s.addCrash(PROCESS_TYPE_RDD, CRASH_TYPE_CRASH, "id1", new Date())
|
||||
);
|
||||
Assert.equal(s.crashesCount, 2);
|
||||
|
||||
let crashes = s.getCrashesOfType(PROCESS_TYPE_RDD, CRASH_TYPE_CRASH);
|
||||
Assert.equal(crashes.length, 2);
|
||||
});
|
||||
|
||||
add_task(async function test_add_mixed_types() {
|
||||
let s = await getStore();
|
||||
|
||||
@ -392,11 +364,10 @@ add_task(async function test_add_mixed_types() {
|
||||
s.addCrash(PROCESS_TYPE_PLUGIN, CRASH_TYPE_CRASH, "pcrash", new Date()) &&
|
||||
s.addCrash(PROCESS_TYPE_PLUGIN, CRASH_TYPE_HANG, "phang", new Date()) &&
|
||||
s.addCrash(PROCESS_TYPE_GMPLUGIN, CRASH_TYPE_CRASH, "gmpcrash", new Date()) &&
|
||||
s.addCrash(PROCESS_TYPE_GPU, CRASH_TYPE_CRASH, "gpucrash", new Date()) &&
|
||||
s.addCrash(PROCESS_TYPE_RDD, CRASH_TYPE_CRASH, "rddcrash", new Date())
|
||||
s.addCrash(PROCESS_TYPE_GPU, CRASH_TYPE_CRASH, "gpucrash", new Date())
|
||||
);
|
||||
|
||||
Assert.equal(s.crashesCount, 9);
|
||||
Assert.equal(s.crashesCount, 8);
|
||||
|
||||
await s.save();
|
||||
|
||||
@ -405,7 +376,7 @@ add_task(async function test_add_mixed_types() {
|
||||
|
||||
await s.load();
|
||||
|
||||
Assert.equal(s.crashesCount, 9);
|
||||
Assert.equal(s.crashesCount, 8);
|
||||
|
||||
let crashes = s.getCrashesOfType(PROCESS_TYPE_MAIN, CRASH_TYPE_CRASH);
|
||||
Assert.equal(crashes.length, 1);
|
||||
@ -423,8 +394,6 @@ add_task(async function test_add_mixed_types() {
|
||||
Assert.equal(crashes.length, 1);
|
||||
crashes = s.getCrashesOfType(PROCESS_TYPE_GPU, CRASH_TYPE_CRASH);
|
||||
Assert.equal(crashes.length, 1);
|
||||
crashes = s.getCrashesOfType(PROCESS_TYPE_RDD, CRASH_TYPE_CRASH);
|
||||
Assert.equal(crashes.length, 1);
|
||||
});
|
||||
|
||||
// Crashes added beyond the high water mark behave properly.
|
||||
|
@ -11467,9 +11467,7 @@
|
||||
"gmplugin-crash",
|
||||
"gmplugin-hang",
|
||||
"gpu-crash",
|
||||
"gpu-hang",
|
||||
"rdd-crash",
|
||||
"rdd-hang"
|
||||
"gpu-hang"
|
||||
],
|
||||
"releaseChannelCollection": "opt-out",
|
||||
"description": "An attempt to submit a crash. Keyed on the CrashManager Crash.type."
|
||||
|
@ -548,8 +548,8 @@ PluginVersion:
|
||||
|
||||
ProcessType:
|
||||
description: >
|
||||
Type of the process that crashed, can hold the values "content", "plugin",
|
||||
"gpu" or "rdd" currently.
|
||||
Type of the process that crashed, can hold the values "content", "plugin" or
|
||||
"gpu" currently.
|
||||
type: string
|
||||
|
||||
ProductName:
|
||||
@ -586,11 +586,6 @@ ProxyStreamValid:
|
||||
Set to "false" when encountering an invalid IPC proxy stream.
|
||||
type: string
|
||||
|
||||
RDDProcessStatus:
|
||||
description: >
|
||||
Status of the RDD process, can be set to "Running" or "Destroyed"
|
||||
type: string
|
||||
|
||||
RecordReplay:
|
||||
description: >
|
||||
Set to 1 if this crash happened in a Web Replay middleman, recording,
|
||||
|
@ -785,10 +785,9 @@ SYNC_ENUMS(GMPLUGIN, GMPlugin)
|
||||
SYNC_ENUMS(GPU, GPU)
|
||||
SYNC_ENUMS(PDFIUM, PDFium)
|
||||
SYNC_ENUMS(VR, VR)
|
||||
SYNC_ENUMS(RDD, RDD)
|
||||
|
||||
// .. and ensure that that is all of them:
|
||||
static_assert(GeckoProcessType_RDD + 1 == GeckoProcessType_End,
|
||||
static_assert(GeckoProcessType_VR + 1 == GeckoProcessType_End,
|
||||
"Did not find the final GeckoProcessType");
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -5128,12 +5127,6 @@ XRE_IsGPUProcess()
|
||||
return XRE_GetProcessType() == GeckoProcessType_GPU;
|
||||
}
|
||||
|
||||
bool
|
||||
XRE_IsRDDProcess()
|
||||
{
|
||||
return XRE_GetProcessType() == GeckoProcessType_RDD;
|
||||
}
|
||||
|
||||
bool
|
||||
XRE_IsVRProcess()
|
||||
{
|
||||
@ -5171,11 +5164,6 @@ XRE_IsPluginProcess()
|
||||
bool
|
||||
XRE_UseNativeEventProcessing()
|
||||
{
|
||||
#ifdef XP_MACOSX
|
||||
if (XRE_IsRDDProcess()) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if (XRE_IsContentProcess()) {
|
||||
static bool sInited = false;
|
||||
static bool sUseNativeEventProcessing = false;
|
||||
|
@ -59,7 +59,6 @@
|
||||
|
||||
#include "mozilla/AbstractThread.h"
|
||||
#include "mozilla/FilePreferences.h"
|
||||
#include "mozilla/RDDProcessImpl.h"
|
||||
|
||||
#include "mozilla/ipc/BrowserProcessSubThread.h"
|
||||
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
||||
@ -626,8 +625,7 @@ XRE_InitChildProcess(int aArgc,
|
||||
MOZ_ASSERT(!*end, "invalid parent PID");
|
||||
|
||||
nsCOMPtr<nsIFile> crashReportTmpDir;
|
||||
if (XRE_GetProcessType() == GeckoProcessType_GPU ||
|
||||
XRE_GetProcessType() == GeckoProcessType_RDD) {
|
||||
if (XRE_GetProcessType() == GeckoProcessType_GPU) {
|
||||
aArgc--;
|
||||
if (strlen(aArgv[aArgc])) { // if it's empty, ignore it
|
||||
nsresult rv = XRE_GetFileFromPath(aArgv[aArgc], getter_AddRefs(crashReportTmpDir));
|
||||
@ -678,7 +676,6 @@ XRE_InitChildProcess(int aArgc,
|
||||
case GeckoProcessType_Content:
|
||||
case GeckoProcessType_GPU:
|
||||
case GeckoProcessType_VR:
|
||||
case GeckoProcessType_RDD:
|
||||
// Content processes need the XPCOM/chromium frankenventloop
|
||||
uiLoopType = MessageLoop::TYPE_MOZILLA_CHILD;
|
||||
break;
|
||||
@ -750,10 +747,6 @@ XRE_InitChildProcess(int aArgc,
|
||||
process = new gfx::VRProcessChild(parentPID);
|
||||
break;
|
||||
|
||||
case GeckoProcessType_RDD:
|
||||
process = new RDDProcessImpl(parentPID);
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Unknown main thread class");
|
||||
}
|
||||
|
@ -314,31 +314,29 @@ nsAppShell::Init()
|
||||
mAutoreleasePools = ::CFArrayCreateMutable(nullptr, 0, nullptr);
|
||||
NS_ENSURE_STATE(mAutoreleasePools);
|
||||
|
||||
if (XRE_GetProcessType() != GeckoProcessType_RDD) {
|
||||
// Get the path of the nib file, which lives in the GRE location
|
||||
nsCOMPtr<nsIFile> nibFile;
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(nibFile));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// Get the path of the nib file, which lives in the GRE location
|
||||
nsCOMPtr<nsIFile> nibFile;
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(nibFile));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nibFile->AppendNative(NS_LITERAL_CSTRING("res"));
|
||||
nibFile->AppendNative(NS_LITERAL_CSTRING("MainMenu.nib"));
|
||||
nibFile->AppendNative(NS_LITERAL_CSTRING("res"));
|
||||
nibFile->AppendNative(NS_LITERAL_CSTRING("MainMenu.nib"));
|
||||
|
||||
nsAutoCString nibPath;
|
||||
rv = nibFile->GetNativePath(nibPath);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsAutoCString nibPath;
|
||||
rv = nibFile->GetNativePath(nibPath);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// This call initializes NSApplication unless:
|
||||
// 1) we're using xre -- NSApp's already been initialized by
|
||||
// MacApplicationDelegate.mm's EnsureUseCocoaDockAPI().
|
||||
// 2) an embedding app that uses NSApplicationMain() is running -- NSApp's
|
||||
// already been initialized and its main run loop is already running.
|
||||
[NSBundle loadNibFile:
|
||||
[NSString stringWithUTF8String:(const char*)nibPath.get()]
|
||||
externalNameTable:
|
||||
[NSDictionary dictionaryWithObject:[GeckoNSApplication sharedApplication]
|
||||
forKey:@"NSOwner"]
|
||||
withZone:NSDefaultMallocZone()];
|
||||
}
|
||||
// This call initializes NSApplication unless:
|
||||
// 1) we're using xre -- NSApp's already been initialized by
|
||||
// MacApplicationDelegate.mm's EnsureUseCocoaDockAPI().
|
||||
// 2) an embedding app that uses NSApplicationMain() is running -- NSApp's
|
||||
// already been initialized and its main run loop is already running.
|
||||
[NSBundle loadNibFile:
|
||||
[NSString stringWithUTF8String:(const char*)nibPath.get()]
|
||||
externalNameTable:
|
||||
[NSDictionary dictionaryWithObject:[GeckoNSApplication sharedApplication]
|
||||
forKey:@"NSOwner"]
|
||||
withZone:NSDefaultMallocZone()];
|
||||
|
||||
mDelegate = [[AppShellDelegate alloc] initWithAppShell:this];
|
||||
NS_ENSURE_STATE(mDelegate);
|
||||
@ -373,7 +371,7 @@ nsAppShell::Init()
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv = nsBaseAppShell::Init();
|
||||
rv = nsBaseAppShell::Init();
|
||||
|
||||
if (!gAppShellMethodsSwizzled) {
|
||||
// We should only replace the original terminate: method if we're not
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include "mozilla/MemoryReportingProcess.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/RDDProcessManager.h"
|
||||
#include "mozilla/ResultExtensions.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
@ -1926,12 +1925,6 @@ nsMemoryReporterManager::StartGettingReports()
|
||||
}
|
||||
}
|
||||
|
||||
if (RDDProcessManager* rdd = RDDProcessManager::Get()) {
|
||||
if (RefPtr<MemoryReportingProcess> proc = rdd->GetProcessMemoryReporter()) {
|
||||
s->mChildrenPending.AppendElement(proc.forget());
|
||||
}
|
||||
}
|
||||
|
||||
if (!s->mChildrenPending.IsEmpty()) {
|
||||
nsCOMPtr<nsITimer> timer;
|
||||
rv = NS_NewTimerWithFuncCallback(
|
||||
|
@ -8,7 +8,6 @@
|
||||
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Poison.h"
|
||||
#include "mozilla/RemoteDecoderManagerChild.h"
|
||||
#include "mozilla/SharedThreadPool.h"
|
||||
#include "mozilla/XPCOM.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
@ -901,7 +900,6 @@ ShutdownXPCOM(nsIServiceManager* aServMgr)
|
||||
NS_ProcessPendingEvents(thread);
|
||||
gfxPlatform::ShutdownLayersIPC();
|
||||
mozilla::dom::VideoDecoderManagerChild::Shutdown();
|
||||
mozilla::RemoteDecoderManagerChild::Shutdown();
|
||||
|
||||
mozilla::scache::StartupCache::DeleteSingleton();
|
||||
if (observerService)
|
||||
|
@ -390,7 +390,6 @@ enum GeckoProcessType
|
||||
GeckoProcessType_GPU, // GPU and compositor process
|
||||
GeckoProcessType_PDFium, // Gecko PDFium process
|
||||
GeckoProcessType_VR, // VR process
|
||||
GeckoProcessType_RDD, // RDD (RemoteDataDecoder process)
|
||||
GeckoProcessType_End,
|
||||
GeckoProcessType_Invalid = GeckoProcessType_End
|
||||
};
|
||||
@ -403,8 +402,7 @@ static const char* const kGeckoProcessTypeString[] = {
|
||||
"geckomediaplugin",
|
||||
"gpu",
|
||||
"pdfium",
|
||||
"vr",
|
||||
"rdd"
|
||||
"vr"
|
||||
};
|
||||
|
||||
static_assert(MOZ_ARRAY_LENGTH(kGeckoProcessTypeString) ==
|
||||
@ -482,9 +480,6 @@ XRE_API(bool,
|
||||
XRE_API(bool,
|
||||
XRE_IsGPUProcess, ())
|
||||
|
||||
XRE_API(bool,
|
||||
XRE_IsRDDProcess, ())
|
||||
|
||||
XRE_API(bool,
|
||||
XRE_IsVRProcess, ())
|
||||
|
||||
|
@ -360,8 +360,7 @@ nsComponentManagerImpl::Init()
|
||||
nsLayoutModuleInitialize();
|
||||
|
||||
bool loadChromeManifests = (XRE_GetProcessType() != GeckoProcessType_GPU &&
|
||||
XRE_GetProcessType() != GeckoProcessType_VR &&
|
||||
XRE_GetProcessType() != GeckoProcessType_RDD);
|
||||
XRE_GetProcessType() != GeckoProcessType_VR);
|
||||
if (loadChromeManifests) {
|
||||
// The overall order in which chrome.manifests are expected to be treated
|
||||
// is the following:
|
||||
@ -441,7 +440,7 @@ static bool
|
||||
ProcessSelectorMatches(Module::ProcessSelector aSelector)
|
||||
{
|
||||
GeckoProcessType type = XRE_GetProcessType();
|
||||
if (type == GeckoProcessType_GPU || type == GeckoProcessType_RDD) {
|
||||
if (type == GeckoProcessType_GPU) {
|
||||
return !!(aSelector & Module::ALLOW_IN_GPU_PROCESS);
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,6 @@ interface nsIXULRuntime : nsISupports
|
||||
const unsigned long PROCESS_TYPE_GPU = 5;
|
||||
const unsigned long PROCESS_TYPE_PDFIUM = 6;
|
||||
const unsigned long PROCESS_TYPE_VR = 7;
|
||||
const unsigned long PROCESS_TYPE_RDD = 8;
|
||||
|
||||
/**
|
||||
* The type of the caller's process. Returns one of the values above.
|
||||
|
Loading…
Reference in New Issue
Block a user