summaryrefslogtreecommitdiffstats
path: root/dom/media/ipc/MFMediaEngineChild.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/ipc/MFMediaEngineChild.h')
-rw-r--r--dom/media/ipc/MFMediaEngineChild.h138
1 files changed, 138 insertions, 0 deletions
diff --git a/dom/media/ipc/MFMediaEngineChild.h b/dom/media/ipc/MFMediaEngineChild.h
new file mode 100644
index 0000000000..92de3b9483
--- /dev/null
+++ b/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/. */
+
+#ifndef DOM_MEDIA_IPC_MFMEDIAENGINECHILD_H_
+#define DOM_MEDIA_IPC_MFMEDIAENGINECHILD_H_
+
+#include "ExternalEngineStateMachine.h"
+#include "MFMediaEngineUtils.h"
+#include "TimeUnits.h"
+#include "mozilla/Atomics.h"
+#include "mozilla/PMFMediaEngineChild.h"
+#include "mozilla/NotNull.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);
+
+ MFMediaEngineChild(MFMediaEngineWrapper* aOwner,
+ FrameStatistics* aFrameStats);
+
+ void OwnerDestroyed();
+ void IPDLActorDestroyed();
+
+ RefPtr<GenericNonExclusivePromise> Init(bool aShouldPreload);
+ void Shutdown();
+
+ // Methods for PMFMediaEngineChild
+ mozilla::ipc::IPCResult RecvRequestSample(TrackInfo::TrackType aType,
+ bool aIsEnough);
+ mozilla::ipc::IPCResult RecvUpdateCurrentTime(double aCurrentTimeInSecond);
+ mozilla::ipc::IPCResult RecvNotifyEvent(MFMediaEngineEvent aEvent);
+ mozilla::ipc::IPCResult RecvNotifyError(const MediaResult& aError);
+ mozilla::ipc::IPCResult RecvUpdateStatisticData(const StatisticData& aData);
+ mozilla::ipc::IPCResult RecvNotifyResizing(uint32_t aWidth, uint32_t aHeight);
+
+ nsISerialEventTarget* ManagerThread() { return mManagerThread; }
+ void AssertOnManagerThread() const {
+ MOZ_ASSERT(mManagerThread->IsOnCurrentThread());
+ }
+
+ uint64_t Id() const { return mMediaEngineId; }
+
+ private:
+ ~MFMediaEngineChild() = default;
+
+ uint64_t GetUpdatedRenderedFrames(const StatisticData& aData);
+ uint64_t GetUpdatedDroppedFrames(const StatisticData& aData);
+
+ // 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;
+
+ MozPromiseHolder<GenericNonExclusivePromise> mInitPromiseHolder;
+ MozPromiseRequestHolder<InitMediaEnginePromise> mInitEngineRequest;
+
+ // This is guaranteed always being alive in our lifetime.
+ NotNull<FrameStatistics*> const MOZ_NON_OWNING_REF mFrameStats;
+
+ bool mShutdown = false;
+
+ // Whenever the remote media engine process crashes, we will create a new
+ // engine child to rebuild the connection. These engine child shares the same
+ // frame stats data so we need to keep accumulate same data from previous
+ // engine.
+ Maybe<uint64_t> mAccumulatedPresentedFramesFromPrevEngine;
+ Maybe<uint64_t> mAccumulatedDroppedFramesFromPrevEngine;
+};
+
+/**
+ * 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:
+ MFMediaEngineWrapper(ExternalEngineStateMachine* aOwner,
+ FrameStatistics* aFrameStats);
+ ~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;
+ bool SetCDMProxy(CDMProxy* aProxy) override;
+ void NotifyResizing(uint32_t aWidth, uint32_t aHeight) 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);
+ void NotifyError(const MediaResult& aError);
+
+ 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_