summaryrefslogtreecommitdiffstats
path: root/dom/media/ipc/MFMediaEngineParent.h
blob: f606d3c44dd7f0fe44ddd771a3727d1e540915b2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/* 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 <Mfidl.h>
#include <winnt.h>
#include <wrl.h>

#include "MediaInfo.h"
#include "MFMediaEngineExtra.h"
#include "MFMediaEngineNotify.h"
#include "MFMediaEngineUtils.h"
#include "MFMediaSource.h"
#include "PlatformDecoderModule.h"
#include "mozilla/PMFMediaEngineParent.h"

namespace mozilla {

class MFCDMProxy;
class MFContentProtectionManager;
class MFMediaEngineExtension;
class MFMediaEngineStreamWrapper;
class MFMediaSource;
class RemoteDecoderManagerParent;

/**
 * MFMediaEngineParent is a wrapper class for a MediaEngine in the MF-CDM
 * 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);
  MFMediaEngineParent(RemoteDecoderManagerParent* aManager,
                      nsISerialEventTarget* aManagerThread);

  using TrackType = TrackInfo::TrackType;

  static MFMediaEngineParent* GetMediaEngineById(uint64_t aId);

  MFMediaEngineStreamWrapper* GetMediaEngineStream(
      TrackType aType, const CreateDecoderParams& aParam);

  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 RecvSetCDMProxyId(uint64_t aProxyId);
  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 CreateMediaEngine();

  void InitializeDXGIDeviceManager();

  void AssertOnManagerThread() const;

  void HandleMediaEngineEvent(MFMediaEngineEventWrapper aEvent);
  void HandleRequestSample(const SampleRequest& aRequest);

  void NotifyError(MF_MEDIA_ENGINE_ERR aError, HRESULT aResult = 0);

  void DestroyEngineIfExists(const Maybe<MediaResult>& aError = Nothing());

  void EnsureDcompSurfaceHandle();

  void UpdateStatisticsData();

  void SetMediaSourceOnEngine();

  Maybe<gfx::IntSize> DetectVideoSizeChange();
  void NotifyVideoResizing();

  // 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;
  const RefPtr<nsISerialEventTarget> mManagerThread;

  // Required classes for working with the media engine.
  Microsoft::WRL::ComPtr<IMFMediaEngine> mMediaEngine;
  Microsoft::WRL::ComPtr<MFMediaEngineNotify> mMediaEngineNotify;
  Microsoft::WRL::ComPtr<MFMediaEngineExtension> mMediaEngineExtension;
  Microsoft::WRL::ComPtr<MFMediaSource> mMediaSource;
#ifdef MOZ_WMF_CDM
  Microsoft::WRL::ComPtr<MFContentProtectionManager> mContentProtectionManager;
#endif

  MediaEventListener mMediaEngineEventListener;
  MediaEventListener mRequestSampleListener;
  bool mIsCreatedMediaEngine = false;

  Microsoft::WRL::ComPtr<IMFDXGIDeviceManager> mDXGIDeviceManager;

  // These will be always zero for audio playback.
  DWORD mDisplayWidth = 0;
  DWORD mDisplayHeight = 0;

  float mPlaybackRate = 1.0;

  // When flush happens inside the media engine, it will reset the statistic
  // data. Therefore, whenever the statistic data gets reset, we will use
  // `mCurrentPlaybackStatisticData` to track new data and store previous data
  // to `mPrevPlaybackStatisticData`. The sum of these two data is the total
  // statistic data for playback.
  StatisticData mCurrentPlaybackStatisticData;
  StatisticData mPrevPlaybackStatisticData;
};

}  // namespace mozilla

#endif  // DOM_MEDIA_IPC_MFMEDIAENGINEPARENT_H_