Bug 1756260 - part3 : implement a mechanism to communicate with the MediaEngine in the remote process. r=jolin

This patch implements a new IPDL which is used for communicating with the remote media engine. It will be used between the content process and the RDD process.

For each media engine pair, they would share an unique ID, which is used to indentify different engine pairs (if any) and for querying a specific engine via Id, which is implemented in the next patch.

Depends on D140014

Differential Revision: https://phabricator.services.mozilla.com/D139204
This commit is contained in:
alwu 2022-05-11 17:46:13 +00:00
Родитель d072277522
Коммит 8f62b3b6f3
13 изменённых файлов: 700 добавлений и 2 удалений

Просмотреть файл

@ -5,6 +5,9 @@
#include "ExternalEngineStateMachine.h"
#include "PerformanceRecorder.h"
#ifdef MOZ_WMF
# include "mozilla/MFMediaEngineChild.h"
#endif
#include "mozilla/ProfilerLabels.h"
namespace mozilla {
@ -78,7 +81,9 @@ ExternalEngineStateMachine::ExternalEngineStateMachine(
: MediaDecoderStateMachineBase(aDecoder, aReader),
mState(State::InitEngine) {
LOG("Created ExternalEngineStateMachine");
// TODO : create the engine in following patch.
#ifdef MOZ_WMF
mEngine.reset(new MFMediaEngineWrapper(this));
#endif
if (mEngine) {
mEngine->Init(!mMinimizePreroll)
->Then(OwnerThread(), __func__, this,

Просмотреть файл

@ -0,0 +1,243 @@
/* 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 "MFMediaEngineChild.h"
#include "MFMediaEngineUtils.h"
#include "RemoteDecoderManagerChild.h"
#include "mozilla/WindowsVersion.h"
namespace mozilla {
#define CLOG(msg, ...) \
MOZ_LOG(gMFMediaEngineLog, LogLevel::Debug, \
("MFMediaEngineChild=%p, Id=%" PRId64 ", " msg, this, this->Id(), \
##__VA_ARGS__))
#define WLOG(msg, ...) \
MOZ_LOG(gMFMediaEngineLog, LogLevel::Debug, \
("MFMediaEngineWrapper=%p, Id=%" PRId64 ", " msg, this, this->Id(), \
##__VA_ARGS__))
using media::TimeUnit;
MFMediaEngineChild::MFMediaEngineChild(MFMediaEngineWrapper* aOwner)
: mOwner(aOwner),
mManagerThread(RemoteDecoderManagerChild::GetManagerThread()),
mMediaEngineId(0 /* invalid id, will be initialized later */) {}
RefPtr<GenericNonExclusivePromise> MFMediaEngineChild::Init(
bool aShouldPreload) {
if (!mManagerThread) {
return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE,
__func__);
}
if (!IsWin8OrLater()) {
CLOG("Media engine can only be used after Windows8");
return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE,
__func__);
}
CLOG("Init");
MOZ_ASSERT(mMediaEngineId == 0);
RefPtr<GenericNonExclusivePromise> p =
RemoteDecoderManagerChild::LaunchRDDProcessIfNeeded();
RefPtr<MFMediaEngineChild> self = this;
p = p->Then(
mManagerThread, __func__,
[self, this, aShouldPreload](bool) -> RefPtr<GenericNonExclusivePromise> {
RefPtr<RemoteDecoderManagerChild> manager =
RemoteDecoderManagerChild::GetSingleton(RemoteDecodeIn::RddProcess);
if (!manager || !manager->CanSend()) {
return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE,
__func__);
}
mIPDLSelfRef = this;
Unused << manager->SendPMFMediaEngineConstructor(this);
RefPtr<GenericNonExclusivePromise::Private> promise =
new GenericNonExclusivePromise::Private(__func__);
MediaEngineInfoIPDL info(aShouldPreload);
SendInitMediaEngine(info)->Then(
mManagerThread, __func__,
[promise, self, this](uint64_t aId) {
// Id 0 is used to indicate error.
if (aId == 0) {
CLOG("Failed to initialize MFMediaEngineChild");
promise->Reject(NS_ERROR_FAILURE, __func__);
return;
}
mMediaEngineId = aId;
CLOG("Initialized MFMediaEngineChild");
promise->Resolve(true, __func__);
},
[promise, self,
this](const mozilla::ipc::ResponseRejectReason& aReason) {
CLOG("Failed to initialize MFMediaEngineChild");
promise->Reject(NS_ERROR_FAILURE, __func__);
});
return promise;
},
[](nsresult aResult) {
return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_FAILURE,
__func__);
});
return p;
}
mozilla::ipc::IPCResult MFMediaEngineChild::RecvRequestSample(TrackType aType) {
AssertOnManagerThread();
if (!mOwner) {
return IPC_OK();
}
if (aType == TrackType::kVideoTrack) {
mOwner->NotifyEvent(ExternalEngineEvent::RequestForVideo);
} else if (aType == TrackType::kAudioTrack) {
mOwner->NotifyEvent(ExternalEngineEvent::RequestForAudio);
}
return IPC_OK();
}
mozilla::ipc::IPCResult MFMediaEngineChild::RecvUpdateCurrentTime(
double aCurrentTimeInSecond) {
AssertOnManagerThread();
if (mOwner) {
mOwner->UpdateCurrentTime(aCurrentTimeInSecond);
}
return IPC_OK();
}
void MFMediaEngineChild::OwnerDestroyed() {
Unused << ManagerThread()->Dispatch(NS_NewRunnableFunction(
"MFMediaEngineChild::OwnerDestroy", [self = RefPtr{this}, this] {
self->mOwner = nullptr;
// Ask to destroy IPDL.
if (CanSend()) {
MFMediaEngineChild::Send__delete__(this);
}
}));
}
void MFMediaEngineChild::IPDLActorDestroyed() {
AssertOnManagerThread();
mIPDLSelfRef = nullptr;
}
MFMediaEngineWrapper::MFMediaEngineWrapper(ExternalEngineStateMachine* aOwner)
: ExternalPlaybackEngine(aOwner),
mEngine(new MFMediaEngineChild(this)),
mCurrentTimeInSecond(0.0) {}
RefPtr<GenericNonExclusivePromise> MFMediaEngineWrapper::Init(
bool aShouldPreload) {
WLOG("Init");
return mEngine->Init(aShouldPreload);
}
MFMediaEngineWrapper::~MFMediaEngineWrapper() { mEngine->OwnerDestroyed(); }
void MFMediaEngineWrapper::Play() {
WLOG("Play");
MOZ_ASSERT(IsInited());
Unused << ManagerThread()->Dispatch(
NS_NewRunnableFunction("MFMediaEngineWrapper::Play",
[engine = mEngine] { engine->SendPlay(); }));
}
void MFMediaEngineWrapper::Pause() {
WLOG("Pause");
MOZ_ASSERT(IsInited());
Unused << ManagerThread()->Dispatch(
NS_NewRunnableFunction("MFMediaEngineWrapper::Pause",
[engine = mEngine] { engine->SendPause(); }));
}
void MFMediaEngineWrapper::Seek(const TimeUnit& aTargetTime) {
auto currentTimeInSecond = aTargetTime.ToSeconds();
mCurrentTimeInSecond = currentTimeInSecond;
WLOG("Seek to %f", currentTimeInSecond);
MOZ_ASSERT(IsInited());
Unused << ManagerThread()->Dispatch(NS_NewRunnableFunction(
"MFMediaEngineWrapper::Seek", [engine = mEngine, currentTimeInSecond] {
engine->SendSeek(currentTimeInSecond);
}));
}
void MFMediaEngineWrapper::Shutdown() {
WLOG("Shutdown");
Unused << ManagerThread()->Dispatch(
NS_NewRunnableFunction("MFMediaEngineWrapper::Shutdown",
[engine = mEngine] { engine->SendShutdown(); }));
}
void MFMediaEngineWrapper::SetPlaybackRate(double aPlaybackRate) {
WLOG("Set playback rate %f", aPlaybackRate);
MOZ_ASSERT(IsInited());
Unused << ManagerThread()->Dispatch(
NS_NewRunnableFunction("MFMediaEngineWrapper::SetPlaybackRate",
[engine = mEngine, aPlaybackRate] {
engine->SendSetVolume(aPlaybackRate);
}));
}
void MFMediaEngineWrapper::SetVolume(double aVolume) {
WLOG("Set volume %f", aVolume);
MOZ_ASSERT(IsInited());
Unused << ManagerThread()->Dispatch(NS_NewRunnableFunction(
"MFMediaEngineWrapper::SetVolume",
[engine = mEngine, aVolume] { engine->SendSetVolume(aVolume); }));
}
void MFMediaEngineWrapper::SetLooping(bool aLooping) {
WLOG("Set looping %d", aLooping);
MOZ_ASSERT(IsInited());
Unused << ManagerThread()->Dispatch(NS_NewRunnableFunction(
"MFMediaEngineWrapper::SetLooping",
[engine = mEngine, aLooping] { engine->SendSetLooping(aLooping); }));
}
void MFMediaEngineWrapper::SetPreservesPitch(bool aPreservesPitch) {
// Media Engine doesn't support this.
}
void MFMediaEngineWrapper::NotifyEndOfStream(TrackInfo::TrackType aType) {
WLOG("NotifyEndOfStream, type=%s", TrackTypeToStr(aType));
MOZ_ASSERT(IsInited());
Unused << ManagerThread()->Dispatch(NS_NewRunnableFunction(
"MFMediaEngineWrapper::NotifyEndOfStream",
[engine = mEngine, aType] { engine->SendNotifyEndOfStream(aType); }));
}
void MFMediaEngineWrapper::SetMediaInfo(const MediaInfo& aInfo) {
WLOG("SetMediaInfo, hasAudio=%d, hasVideo=%d", aInfo.HasAudio(),
aInfo.HasVideo());
MOZ_ASSERT(IsInited());
Unused << ManagerThread()->Dispatch(NS_NewRunnableFunction(
"MFMediaEngineWrapper::SetMediaInfo", [engine = mEngine, aInfo] {
MediaInfoIPDL info(aInfo.HasAudio() ? Some(aInfo.mAudio) : Nothing(),
aInfo.HasVideo() ? Some(aInfo.mVideo) : Nothing());
engine->SendNotifyMediaInfo(info);
}));
}
TimeUnit MFMediaEngineWrapper::GetCurrentPosition() {
return TimeUnit::FromSeconds(mCurrentTimeInSecond);
}
void MFMediaEngineWrapper::UpdateCurrentTime(double aCurrentTimeInSecond) {
AssertOnManagerThread();
WLOG("Update current time %f", aCurrentTimeInSecond);
mCurrentTimeInSecond = aCurrentTimeInSecond;
NotifyEvent(ExternalEngineEvent::Timeupdate);
}
void MFMediaEngineWrapper::NotifyEvent(ExternalEngineEvent aEvent) {
AssertOnManagerThread();
WLOG("Received event %s", ExternalEngineEventToStr(aEvent));
mOwner->NotifyEvent(aEvent);
}
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,107 @@
/* 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 DOM_MEDIA_IPC_MFMEDIAENGINECHILD_H_
#define DOM_MEDIA_IPC_MFMEDIAENGINECHILD_H_
#include "ExternalEngineStateMachine.h"
#include "TimeUnits.h"
#include "mozilla/Atomics.h"
#include "mozilla/PMFMediaEngineChild.h"
namespace mozilla {
class MFMediaEngineWrapper;
/**
* MFMediaEngineChild is a wrapper class for a MediaEngine in the content
* process. It communicates with MFMediaEngineParent in the remote process by
* using IPDL interfaces to send commands to the MediaEngine.
* https://docs.microsoft.com/en-us/windows/win32/api/mfmediaengine/nn-mfmediaengine-imfmediaengine
*/
class MFMediaEngineChild final : public PMFMediaEngineChild {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MFMediaEngineChild);
explicit MFMediaEngineChild(MFMediaEngineWrapper* aOwner);
void OwnerDestroyed();
void IPDLActorDestroyed();
RefPtr<GenericNonExclusivePromise> Init(bool aShouldPreload);
// Methods for PMFMediaEngineChild
mozilla::ipc::IPCResult RecvRequestSample(TrackInfo::TrackType aType);
mozilla::ipc::IPCResult RecvUpdateCurrentTime(double aCurrentTimeInSecond);
nsISerialEventTarget* ManagerThread() { return mManagerThread; }
void AssertOnManagerThread() const {
MOZ_ASSERT(mManagerThread->IsOnCurrentThread());
}
uint64_t Id() const { return mMediaEngineId; }
private:
~MFMediaEngineChild() = default;
// Only modified on the manager thread.
MFMediaEngineWrapper* MOZ_NON_OWNING_REF mOwner;
const nsCOMPtr<nsISerialEventTarget> mManagerThread;
// This represents an unique Id to indentify the media engine in the remote
// process. Zero is used for the status before initializaing Id from the
// remote process.
// Modified on the manager thread, and read on other threads.
Atomic<uint64_t> mMediaEngineId;
RefPtr<MFMediaEngineChild> mIPDLSelfRef;
};
/**
* MFMediaEngineWrapper acts as an external playback engine, which is
* implemented by using the Media Foundation Media Engine. It holds hold an
* actor used to communicate with the engine in the remote process. Its methods
* are all thread-safe.
*/
class MFMediaEngineWrapper final : public ExternalPlaybackEngine {
public:
explicit MFMediaEngineWrapper(ExternalEngineStateMachine* aOwner);
~MFMediaEngineWrapper();
// Methods for ExternalPlaybackEngine
RefPtr<GenericNonExclusivePromise> Init(bool aShouldPreload) override;
void Play() override;
void Pause() override;
void Seek(const media::TimeUnit& aTargetTime) override;
void Shutdown() override;
void SetPlaybackRate(double aPlaybackRate) override;
void SetVolume(double aVolume) override;
void SetLooping(bool aLooping) override;
void SetPreservesPitch(bool aPreservesPitch) override;
media::TimeUnit GetCurrentPosition() override;
void NotifyEndOfStream(TrackInfo::TrackType aType) override;
uint64_t Id() const override { return mEngine->Id(); }
void SetMediaInfo(const MediaInfo& aInfo) override;
nsISerialEventTarget* ManagerThread() { return mEngine->ManagerThread(); }
void AssertOnManagerThread() const { mEngine->AssertOnManagerThread(); }
private:
friend class MFMediaEngineChild;
bool IsInited() const { return mEngine->Id() != 0; }
void UpdateCurrentTime(double aCurrentTimeInSecond);
void NotifyEvent(ExternalEngineEvent aEvent);
const RefPtr<MFMediaEngineChild> mEngine;
// The current time which we receive from the MediaEngine or set by the state
// machine when seeking.
std::atomic<double> mCurrentTimeInSecond;
};
} // namespace mozilla
#endif // DOM_MEDIA_IPC_MFMEDIAENGINECHILD_H_

Просмотреть файл

@ -0,0 +1,138 @@
/* 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 "MFMediaEngineParent.h"
#include "MFMediaEngineUtils.h"
#include "RemoteDecoderManagerParent.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/StaticMutex.h"
#include "mozilla/StaticPtr.h"
namespace mozilla {
#define LOG(msg, ...) \
MOZ_LOG(gMFMediaEngineLog, LogLevel::Debug, \
("MFMediaEngineParent=%p, Id=%" PRId64 ", " msg, this, this->Id(), \
##__VA_ARGS__))
using MediaEngineMap = nsTHashMap<nsUint64HashKey, MFMediaEngineParent*>;
static StaticAutoPtr<MediaEngineMap> sMediaEngines;
StaticMutex sMediaEnginesLock;
static void RegisterMediaEngine(MFMediaEngineParent* aMediaEngine) {
MOZ_ASSERT(aMediaEngine);
StaticMutexAutoLock lock(sMediaEnginesLock);
if (!sMediaEngines) {
sMediaEngines = new MediaEngineMap();
}
sMediaEngines->InsertOrUpdate(aMediaEngine->Id(), aMediaEngine);
}
static void UnregisterMedieEngine(MFMediaEngineParent* aMediaEngine) {
StaticMutexAutoLock lock(sMediaEnginesLock);
if (sMediaEngines) {
sMediaEngines->Remove(aMediaEngine->Id());
}
}
/* static */
MFMediaEngineParent* MFMediaEngineParent::GetMediaEngineById(uint64_t aId) {
StaticMutexAutoLock lock(sMediaEnginesLock);
return sMediaEngines->Get(aId);
}
MFMediaEngineParent::MFMediaEngineParent(RemoteDecoderManagerParent* aManager)
: mMediaEngineId(++sMediaEngineIdx), mManager(aManager) {
MOZ_ASSERT(aManager);
MOZ_ASSERT(mMediaEngineId != 0);
MOZ_ASSERT(XRE_IsRDDProcess());
LOG("Created MFMediaEngineParent");
RegisterMediaEngine(this);
mIPDLSelfRef = this;
}
MFMediaEngineParent::~MFMediaEngineParent() {
LOG("Destoryed MFMediaEngineParent");
UnregisterMedieEngine(this);
}
mozilla::ipc::IPCResult MFMediaEngineParent::RecvInitMediaEngine(
const MediaEngineInfoIPDL& aInfo, InitMediaEngineResolver&& aResolver) {
AssertOnManagerThread();
aResolver(mMediaEngineId);
return IPC_OK();
}
mozilla::ipc::IPCResult MFMediaEngineParent::RecvNotifyMediaInfo(
const MediaInfoIPDL& aInfo) {
AssertOnManagerThread();
// TODO : implement this by using media engine
return IPC_OK();
}
mozilla::ipc::IPCResult MFMediaEngineParent::RecvPlay() {
AssertOnManagerThread();
// TODO : implement this by using media engine
return IPC_OK();
}
mozilla::ipc::IPCResult MFMediaEngineParent::RecvPause() {
AssertOnManagerThread();
// TODO : implement this by using media engine
return IPC_OK();
}
mozilla::ipc::IPCResult MFMediaEngineParent::RecvSeek(
double aTargetTimeInSecond) {
AssertOnManagerThread();
// TODO : implement this by using media engine
return IPC_OK();
}
mozilla::ipc::IPCResult MFMediaEngineParent::RecvSetVolume(double aVolume) {
AssertOnManagerThread();
// TODO : implement this by using media engine
return IPC_OK();
}
mozilla::ipc::IPCResult MFMediaEngineParent::RecvSetPlaybackRate(
double aPlaybackRate) {
AssertOnManagerThread();
// TODO : implement this by using media engine
return IPC_OK();
}
mozilla::ipc::IPCResult MFMediaEngineParent::RecvSetLooping(bool aLooping) {
AssertOnManagerThread();
// TODO : implement this by using media engine
return IPC_OK();
}
mozilla::ipc::IPCResult MFMediaEngineParent::RecvNotifyEndOfStream(
TrackInfo::TrackType aType) {
AssertOnManagerThread();
// TODO : implement this by using media engine
return IPC_OK();
}
mozilla::ipc::IPCResult MFMediaEngineParent::RecvShutdown() {
AssertOnManagerThread();
LOG("Shutdown");
return IPC_OK();
}
void MFMediaEngineParent::Destroy() {
AssertOnManagerThread();
mIPDLSelfRef = nullptr;
}
void MFMediaEngineParent::AssertOnManagerThread() const {
MOZ_ASSERT(mManager->OnManagerThread());
}
#undef LOG
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,72 @@
/* 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 DOM_MEDIA_IPC_MFMEDIAENGINEPARENT_H_
#define DOM_MEDIA_IPC_MFMEDIAENGINEPARENT_H_
#include "MediaInfo.h"
#include "PlatformDecoderModule.h"
#include "mozilla/PMFMediaEngineParent.h"
namespace mozilla {
class MFMediaEngineStream;
class RemoteDecoderManagerParent;
/**
* MFMediaEngineParent is a wrapper class for a MediaEngine in the RDD process.
* It's responsible to create the media engine and its related classes, such as
* a custom media source, media engine extension, media engine notify...e.t.c
* It communicates with MFMediaEngineChild in the content process to receive
* commands and direct them to the media engine.
* https://docs.microsoft.com/en-us/windows/win32/api/mfmediaengine/nn-mfmediaengine-imfmediaengine
*/
class MFMediaEngineParent final : public PMFMediaEngineParent {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MFMediaEngineParent);
explicit MFMediaEngineParent(RemoteDecoderManagerParent* aManager);
using TrackType = TrackInfo::TrackType;
static MFMediaEngineParent* GetMediaEngineById(uint64_t aId);
uint64_t Id() const { return mMediaEngineId; }
// Methods for PMFMediaEngineParent
mozilla::ipc::IPCResult RecvInitMediaEngine(
const MediaEngineInfoIPDL& aInfo, InitMediaEngineResolver&& aResolver);
mozilla::ipc::IPCResult RecvNotifyMediaInfo(const MediaInfoIPDL& aInfo);
mozilla::ipc::IPCResult RecvPlay();
mozilla::ipc::IPCResult RecvPause();
mozilla::ipc::IPCResult RecvSeek(double aTargetTimeInSecond);
mozilla::ipc::IPCResult RecvSetVolume(double aVolume);
mozilla::ipc::IPCResult RecvSetPlaybackRate(double aPlaybackRate);
mozilla::ipc::IPCResult RecvSetLooping(bool aLooping);
mozilla::ipc::IPCResult RecvNotifyEndOfStream(TrackInfo::TrackType aType);
mozilla::ipc::IPCResult RecvShutdown();
void Destroy();
private:
~MFMediaEngineParent();
void AssertOnManagerThread() const;
// This generates unique id for each MFMediaEngineParent instance, and it
// would be increased monotonically.
static inline uint64_t sMediaEngineIdx = 0;
const uint64_t mMediaEngineId;
// The life cycle of this class is determined by the actor in the content
// process, we would hold a reference until the content actor asks us to
// destroy.
RefPtr<MFMediaEngineParent> mIPDLSelfRef;
const RefPtr<RemoteDecoderManagerParent> mManager;
};
} // namespace mozilla
#endif // DOM_MEDIA_IPC_MFMEDIAENGINEPARENT_H_

Просмотреть файл

@ -0,0 +1,12 @@
/* 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 DOM_MEDIA_IPC_MFMEDIAENGINEUTILS_H_
#define DOM_MEDIA_IPC_MFMEDIAENGINEUTILS_H_
#include "mozilla/Logging.h"
static inline mozilla::LazyLogModule gMFMediaEngineLog("MFMediaEngine");
#endif // DOM_MEDIA_IPC_MFMEDIAENGINECHILD_H_

Просмотреть файл

@ -0,0 +1,50 @@
/* 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;
using mozilla::AudioInfo from "MediaInfo.h";
using mozilla::VideoInfo from "MediaInfo.h";
using mozilla::MediaResult from "MediaResult.h";
using mozilla::TrackInfo::TrackType from "MediaInfo.h";
namespace mozilla {
struct MediaEngineInfoIPDL
{
bool preload;
};
struct MediaInfoIPDL
{
AudioInfo? audioInfo;
VideoInfo? videoInfo;
};
[ManualDealloc]
async protocol PMFMediaEngine
{
manager PRemoteDecoderManager;
parent:
// Return 0 if media engine can't be created.
async InitMediaEngine(MediaEngineInfoIPDL info) returns (uint64_t id);
async NotifyMediaInfo(MediaInfoIPDL info);
async Play();
async Pause();
async Seek(double targetTimeInSecond);
async SetVolume(double volume);
async SetPlaybackRate(double playbackRate);
async SetLooping(bool looping);
async NotifyEndOfStream(TrackType type);
async Shutdown();
async __delete__();
child:
async UpdateCurrentTime(double currentTimeInSecond);
async RequestSample(TrackType type);
};
} // namespace mozilla

Просмотреть файл

@ -3,6 +3,9 @@
* 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/. */
#ifdef MOZ_WMF
include protocol PMFMediaEngine;
#endif
include protocol PTexture;
include protocol PRemoteDecoder;
include LayersSurfaces;
@ -33,8 +36,14 @@ union RemoteDecoderInfoIPDL
sync protocol PRemoteDecoderManager
{
manages PRemoteDecoder;
#ifdef MOZ_WMF
manages PMFMediaEngine;
#endif
parent:
#ifdef MOZ_WMF
async PMFMediaEngine();
#endif
async PRemoteDecoder(RemoteDecoderInfoIPDL info,
OptionSet options,
TextureFactoryIdentifier? identifier);

Просмотреть файл

@ -23,6 +23,10 @@
#include "nsIObserver.h"
#include "mozilla/StaticPrefs_media.h"
#ifdef MOZ_WMF
# include "MFMediaEngineChild.h"
#endif
namespace mozilla {
using namespace layers;
@ -560,6 +564,21 @@ bool RemoteDecoderManagerChild::DeallocPRemoteDecoderChild(
return true;
}
PMFMediaEngineChild* RemoteDecoderManagerChild::AllocPMFMediaEngineChild() {
MOZ_ASSERT_UNREACHABLE(
"RemoteDecoderManagerChild cannot create MFMediaEngineChild classes");
return nullptr;
}
bool RemoteDecoderManagerChild::DeallocPMFMediaEngineChild(
PMFMediaEngineChild* actor) {
#ifdef MOZ_WMF
MFMediaEngineChild* child = static_cast<MFMediaEngineChild*>(actor);
child->IPDLActorDestroyed();
#endif
return true;
}
RemoteDecoderManagerChild::RemoteDecoderManagerChild(RemoteDecodeIn aLocation)
: mLocation(aLocation) {
MOZ_ASSERT(mLocation == RemoteDecodeIn::GpuProcess ||

Просмотреть файл

@ -15,6 +15,7 @@
namespace mozilla {
class PMFMediaEngineChild;
class RemoteDecoderChild;
enum class RemoteDecodeIn {
@ -104,6 +105,9 @@ class RemoteDecoderManagerChild final
const Maybe<layers::TextureFactoryIdentifier>& aIdentifier);
bool DeallocPRemoteDecoderChild(PRemoteDecoderChild* actor);
PMFMediaEngineChild* AllocPMFMediaEngineChild();
bool DeallocPMFMediaEngineChild(PMFMediaEngineChild* actor);
private:
explicit RemoteDecoderManagerChild(RemoteDecodeIn aLocation);
~RemoteDecoderManagerChild() = default;

Просмотреть файл

@ -23,6 +23,10 @@
#include "mozilla/layers/VideoBridgeChild.h"
#include "mozilla/layers/VideoBridgeParent.h"
#ifdef MOZ_WMF
# include "MFMediaEngineParent.h"
#endif
namespace mozilla {
using namespace ipc;
@ -218,6 +222,23 @@ bool RemoteDecoderManagerParent::DeallocPRemoteDecoderParent(
return true;
}
PMFMediaEngineParent* RemoteDecoderManagerParent::AllocPMFMediaEngineParent() {
#ifdef MOZ_WMF
return new MFMediaEngineParent(this);
#else
return nullptr;
#endif
}
bool RemoteDecoderManagerParent::DeallocPMFMediaEngineParent(
PMFMediaEngineParent* actor) {
#ifdef MOZ_WMF
MFMediaEngineParent* parent = static_cast<MFMediaEngineParent*>(actor);
parent->Destroy();
#endif
return true;
}
void RemoteDecoderManagerParent::Open(
Endpoint<PRemoteDecoderManagerParent>&& aEndpoint) {
if (!aEndpoint.Bind(this)) {

Просмотреть файл

@ -13,6 +13,7 @@
namespace mozilla {
class PDMFactory;
class PMFMediaEngineParent;
class RemoteDecoderManagerParent final
: public PRemoteDecoderManagerParent,
@ -60,6 +61,9 @@ class RemoteDecoderManagerParent final
const Maybe<layers::TextureFactoryIdentifier>& aIdentifier);
bool DeallocPRemoteDecoderParent(PRemoteDecoderParent* actor);
PMFMediaEngineParent* AllocPMFMediaEngineParent();
bool DeallocPMFMediaEngineParent(PMFMediaEngineParent* actor);
mozilla::ipc::IPCResult RecvReadback(const SurfaceDescriptorGPUVideo& aSD,
SurfaceDescriptor* aResult);
mozilla::ipc::IPCResult RecvDeallocateSurfaceDescriptorGPUVideo(

Просмотреть файл

@ -8,11 +8,11 @@
IPDL_SOURCES += [
"PMediaDecoderParams.ipdlh",
"PRemoteDecoder.ipdl",
"PRemoteDecoderManager.ipdl",
]
PREPROCESSED_IPDL_SOURCES += [
"PRDD.ipdl",
"PRemoteDecoderManager.ipdl",
]
EXPORTS.mozilla += [
@ -54,6 +54,20 @@ SOURCES += [
"RemoteVideoDecoder.cpp",
]
if CONFIG["MOZ_WMF"]:
IPDL_SOURCES += [
"PMFMediaEngine.ipdl",
]
SOURCES += [
"MFMediaEngineChild.cpp",
"MFMediaEngineParent.cpp",
]
EXPORTS.mozilla += [
"MFMediaEngineChild.h",
"MFMediaEngineParent.h",
"MFMediaEngineUtils.h",
]
# so we can include nsMacUtilsImpl.h in RDDParent.cpp for sandboxing
LOCAL_INCLUDES += [
"/xpcom/base",