зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
d072277522
Коммит
8f62b3b6f3
|
@ -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",
|
||||
|
|
Загрузка…
Ссылка в новой задаче