ChromiumCDMParent.h (9827B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef ChromiumCDMParent_h_ 7 #define ChromiumCDMParent_h_ 8 9 #include "DecryptJob.h" 10 #include "GMPCrashHelper.h" 11 #include "GMPCrashHelperHolder.h" 12 #include "GMPMessageUtils.h" 13 #include "ImageContainer.h" 14 #include "PlatformDecoderModule.h" 15 #include "ReorderQueue.h" 16 #include "mozilla/Maybe.h" 17 #include "mozilla/RefPtr.h" 18 #include "mozilla/Span.h" 19 #include "mozilla/gmp/PChromiumCDMParent.h" 20 #include "nsTHashMap.h" 21 22 class ChromiumCDMCallback; 23 24 namespace mozilla { 25 26 class ErrorResult; 27 class MediaRawData; 28 class ChromiumCDMProxy; 29 30 namespace gmp { 31 32 class GMPContentParent; 33 34 /** 35 * ChromiumCDMParent is the content process IPC actor used to communicate with a 36 * CDM in the GMP process (where ChromiumCDMChild lives). All non-static 37 * members of this class are GMP thread only. 38 */ 39 class ChromiumCDMParent final : public PChromiumCDMParent, 40 public GMPCrashHelperHolder { 41 friend class PChromiumCDMParent; 42 43 public: 44 typedef MozPromise<bool, MediaResult, /* IsExclusive = */ true> InitPromise; 45 46 // Mark AddRef and Release as `final`, as they overload pure virtual 47 // implementations in PChromiumCDMParent. 48 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ChromiumCDMParent, final) 49 50 ChromiumCDMParent(GMPContentParent* aContentParent, uint32_t aPluginId); 51 52 uint32_t PluginId() const { return mPluginId; } 53 54 RefPtr<InitPromise> Init(ChromiumCDMCallback* aCDMCallback, 55 bool aAllowDistinctiveIdentifier, 56 bool aAllowPersistentState, 57 nsIEventTarget* aMainThread); 58 59 void CreateSession(uint32_t aCreateSessionToken, uint32_t aSessionType, 60 uint32_t aInitDataType, uint32_t aPromiseId, 61 const nsTArray<uint8_t>& aInitData); 62 63 void LoadSession(uint32_t aPromiseId, uint32_t aSessionType, 64 nsString aSessionId); 65 66 void SetServerCertificate(uint32_t aPromiseId, 67 const nsTArray<uint8_t>& aCert); 68 69 void UpdateSession(const nsCString& aSessionId, uint32_t aPromiseId, 70 const nsTArray<uint8_t>& aResponse); 71 72 void CloseSession(const nsCString& aSessionId, uint32_t aPromiseId); 73 74 void RemoveSession(const nsCString& aSessionId, uint32_t aPromiseId); 75 76 // Notifies this parent of the current output protection status. This will 77 // update cached status and resolve outstanding queries from the CDM if one 78 // exists. 79 void NotifyOutputProtectionStatus(bool aSuccess, uint32_t aLinkMask, 80 uint32_t aProtectionMask); 81 82 void GetStatusForPolicy(uint32_t aPromiseId, 83 const dom::HDCPVersion& aMinHdcpVersion); 84 85 RefPtr<DecryptPromise> Decrypt(MediaRawData* aSample); 86 87 // TODO: Add functions for clients to send data to CDM, and 88 // a Close() function. 89 RefPtr<MediaDataDecoder::InitPromise> InitializeVideoDecoder( 90 const gmp::CDMVideoDecoderConfig& aConfig, const VideoInfo& aInfo, 91 RefPtr<layers::ImageContainer> aImageContainer, 92 RefPtr<layers::KnowsCompositor> aKnowsCompositor); 93 94 RefPtr<MediaDataDecoder::DecodePromise> DecryptAndDecodeFrame( 95 MediaRawData* aSample); 96 97 RefPtr<MediaDataDecoder::FlushPromise> FlushVideoDecoder(); 98 99 RefPtr<MediaDataDecoder::DecodePromise> Drain(); 100 101 RefPtr<ShutdownPromise> ShutdownVideoDecoder(); 102 103 void Shutdown(); 104 105 protected: 106 ~ChromiumCDMParent() = default; 107 108 ipc::IPCResult Recv__delete__() override; 109 ipc::IPCResult RecvOnResolvePromiseWithKeyStatus(const uint32_t& aPromiseId, 110 const uint32_t& aKeyStatus); 111 ipc::IPCResult RecvOnResolveNewSessionPromise(const uint32_t& aPromiseId, 112 const nsCString& aSessionId); 113 ipc::IPCResult RecvResolveLoadSessionPromise(const uint32_t& aPromiseId, 114 const bool& aSuccessful); 115 ipc::IPCResult RecvOnResolvePromise(const uint32_t& aPromiseId); 116 ipc::IPCResult RecvOnRejectPromise(const uint32_t& aPromiseId, 117 const uint32_t& aError, 118 const uint32_t& aSystemCode, 119 const nsCString& aErrorMessage); 120 ipc::IPCResult RecvOnSessionMessage(const nsCString& aSessionId, 121 const uint32_t& aMessageType, 122 nsTArray<uint8_t>&& aMessage); 123 ipc::IPCResult RecvOnSessionKeysChange( 124 const nsCString& aSessionId, nsTArray<CDMKeyInformation>&& aKeysInfo); 125 ipc::IPCResult RecvOnExpirationChange(const nsCString& aSessionId, 126 const double& aSecondsSinceEpoch); 127 ipc::IPCResult RecvOnSessionClosed(const nsCString& aSessionId); 128 ipc::IPCResult RecvOnQueryOutputProtectionStatus(); 129 ipc::IPCResult RecvDecryptedShmem(const uint32_t& aId, 130 const uint32_t& aStatus, 131 ipc::Shmem&& aData); 132 ipc::IPCResult RecvDecryptedData(const uint32_t& aId, const uint32_t& aStatus, 133 nsTArray<uint8_t>&& aData); 134 ipc::IPCResult RecvDecryptFailed(const uint32_t& aId, 135 const uint32_t& aStatus); 136 ipc::IPCResult RecvOnDecoderInitDone(const uint32_t& aStatus); 137 ipc::IPCResult RecvDecodedShmem(const CDMVideoFrame& aFrame, 138 ipc::Shmem&& aShmem); 139 ipc::IPCResult RecvDecodedData(const CDMVideoFrame& aFrame, 140 nsTArray<uint8_t>&& aData); 141 ipc::IPCResult RecvDecodeFailed(const uint32_t& aStatus); 142 ipc::IPCResult RecvShutdown(); 143 ipc::IPCResult RecvResetVideoDecoderComplete(); 144 ipc::IPCResult RecvDrainComplete(); 145 ipc::IPCResult RecvIncreaseShmemPoolSize(); 146 void ActorDestroy(ActorDestroyReason aWhy) override; 147 bool SendBufferToCDM(uint32_t aSizeInBytes); 148 149 void ReorderAndReturnOutput(RefPtr<VideoData>&& aFrame); 150 151 void RejectPromise(uint32_t aPromiseId, ErrorResult&& aException, 152 const nsCString& aErrorMessage); 153 154 void ResolvePromise(uint32_t aPromiseId); 155 // Helpers to reject our promise if we are shut down. 156 void RejectPromiseShutdown(uint32_t aPromiseId); 157 // Helper to reject our promise with an InvalidStateError and the given 158 // message. 159 void RejectPromiseWithStateError(uint32_t aPromiseId, 160 const nsCString& aErrorMessage); 161 162 // Complete the CDMs request for us to check protection status by responding 163 // to the CDM child with the requested info. 164 void CompleteQueryOutputProtectionStatus(bool aSuccess, uint32_t aLinkMask, 165 uint32_t aProtectionMask); 166 167 bool InitCDMInputBuffer(gmp::CDMInputBuffer& aBuffer, MediaRawData* aSample); 168 169 bool PurgeShmems(); 170 bool EnsureSufficientShmems(size_t aVideoFrameSize); 171 already_AddRefed<VideoData> CreateVideoFrame(const CDMVideoFrame& aFrame, 172 Span<uint8_t> aData); 173 174 const uint32_t mPluginId; 175 GMPContentParent* mContentParent; 176 // Note: this pointer is a weak reference as ChromiumCDMProxy has a strong 177 // reference to the ChromiumCDMCallback. 178 ChromiumCDMCallback* mCDMCallback = nullptr; 179 nsTHashMap<nsUint32HashKey, uint32_t> mPromiseToCreateSessionToken; 180 nsTArray<RefPtr<DecryptJob>> mDecrypts; 181 182 MozPromiseHolder<InitPromise> mInitPromise; 183 184 MozPromiseHolder<MediaDataDecoder::InitPromise> mInitVideoDecoderPromise; 185 MozPromiseHolder<MediaDataDecoder::DecodePromise> mDecodePromise; 186 187 RefPtr<layers::ImageContainer> mImageContainer; 188 RefPtr<layers::KnowsCompositor> mKnowsCompositor; 189 VideoInfo mVideoInfo; 190 int64_t mLastStreamOffset = 0; 191 192 MozPromiseHolder<MediaDataDecoder::FlushPromise> mFlushDecoderPromise; 193 194 size_t mVideoFrameBufferSize = 0; 195 196 // Count of the number of shmems in the set used to return decoded video 197 // frames from the CDM to Gecko. 198 uint32_t mVideoShmemsActive = 0; 199 // Maximum number of shmems to use to return decoded video frames. 200 uint32_t mVideoShmemLimit; 201 202 // Tracks if we have an outstanding request for output protection information. 203 // This will be set to true if the CDM requests the information and we haven't 204 // yet received it from up the stack and need to query up. 205 bool mAwaitingOutputProtectionInformation = false; 206 // The cached link mask for QueryOutputProtectionStatus related calls. If 207 // this isn't set we'll call up the stack to MediaKeys to request the 208 // information, otherwise we'll use the cached value and rely on MediaKeys 209 // to notify us if the mask changes. 210 Maybe<uint32_t> mOutputProtectionLinkMask; 211 212 bool mIsShutdown = false; 213 bool mVideoDecoderInitialized = false; 214 bool mActorDestroyed = false; 215 bool mAbnormalShutdown = false; 216 217 // The H.264 decoder in Widevine CDM versions 970 and later output in decode 218 // order rather than presentation order, so we reorder in presentation order 219 // before presenting. mMaxRefFrames is non-zero if we have an initialized 220 // decoder and we are decoding H.264. If so, it stores the maximum length of 221 // the reorder queue that we need. Note we may have multiple decoders for the 222 // life time of this object, but never more than one active at once. 223 uint32_t mMaxRefFrames = 0; 224 ReorderQueue mReorderQueue; 225 226 #ifdef DEBUG 227 // The GMP thread. Used to MOZ_ASSERT methods run on the GMP thread. 228 const nsCOMPtr<nsISerialEventTarget> mGMPThread; 229 #endif 230 }; 231 232 } // namespace gmp 233 } // namespace mozilla 234 235 #endif // ChromiumCDMParent_h_