DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (56e7b9127e89)

VCS Links

Line Code
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 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 ChromiumCDMParent_h_
#define ChromiumCDMParent_h_

#include "DecryptJob.h"
#include "GMPCrashHelper.h"
#include "GMPCrashHelperHolder.h"
#include "GMPMessageUtils.h"
#include "mozilla/gmp/PChromiumCDMParent.h"
#include "mozilla/RefPtr.h"
#include "nsDataHashtable.h"
#include "PlatformDecoderModule.h"
#include "ImageContainer.h"
#include "mozilla/Span.h"
#include "ReorderQueue.h"

class ChromiumCDMCallback;

namespace mozilla {

class MediaRawData;
class ChromiumCDMProxy;

namespace gmp {

class GMPContentParent;

class ChromiumCDMParent final
  : public PChromiumCDMParent
  , public GMPCrashHelperHolder
{
public:
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ChromiumCDMParent)

  ChromiumCDMParent(GMPContentParent* aContentParent, uint32_t aPluginId);

  uint32_t PluginId() const { return mPluginId; }

  bool Init(ChromiumCDMCallback* aCDMCallback,
            bool aAllowDistinctiveIdentifier,
            bool aAllowPersistentState,
            nsIEventTarget* aMainThread,
            nsCString& aOutFailureReason);

  void CreateSession(uint32_t aCreateSessionToken,
                     uint32_t aSessionType,
                     uint32_t aInitDataType,
                     uint32_t aPromiseId,
                     const nsTArray<uint8_t>& aInitData);

  void LoadSession(uint32_t aPromiseId,
                   uint32_t aSessionType,
                   nsString aSessionId);

  void SetServerCertificate(uint32_t aPromiseId,
                            const nsTArray<uint8_t>& aCert);

  void UpdateSession(const nsCString& aSessionId,
                     uint32_t aPromiseId,
                     const nsTArray<uint8_t>& aResponse);

  void CloseSession(const nsCString& aSessionId, uint32_t aPromiseId);

  void RemoveSession(const nsCString& aSessionId, uint32_t aPromiseId);

  void GetStatusForPolicy(uint32_t aPromiseId,
                          const nsCString& aMinHdcpVersion);

  RefPtr<DecryptPromise> Decrypt(MediaRawData* aSample);

  // TODO: Add functions for clients to send data to CDM, and
  // a Close() function.
  RefPtr<MediaDataDecoder::InitPromise> InitializeVideoDecoder(
    const gmp::CDMVideoDecoderConfig& aConfig,
    const VideoInfo& aInfo,
    RefPtr<layers::ImageContainer> aImageContainer);

  RefPtr<MediaDataDecoder::DecodePromise> DecryptAndDecodeFrame(
    MediaRawData* aSample);

  RefPtr<MediaDataDecoder::FlushPromise> FlushVideoDecoder();

  RefPtr<MediaDataDecoder::DecodePromise> Drain();

  RefPtr<ShutdownPromise> ShutdownVideoDecoder();

  void Shutdown();

protected:
  ~ChromiumCDMParent() {}

  ipc::IPCResult Recv__delete__() override;
  ipc::IPCResult RecvOnResolvePromiseWithKeyStatus(
    const uint32_t& aPromiseId,
    const uint32_t& aKeyStatus) override;
  ipc::IPCResult RecvOnResolveNewSessionPromise(
    const uint32_t& aPromiseId,
    const nsCString& aSessionId) override;
  ipc::IPCResult RecvResolveLoadSessionPromise(
    const uint32_t& aPromiseId,
    const bool& aSuccessful) override;
  ipc::IPCResult RecvOnResolvePromise(const uint32_t& aPromiseId) override;
  ipc::IPCResult RecvOnRejectPromise(const uint32_t& aPromiseId,
                                     const uint32_t& aError,
                                     const uint32_t& aSystemCode,
                                     const nsCString& aErrorMessage) override;
  ipc::IPCResult RecvOnSessionMessage(const nsCString& aSessionId,
                                      const uint32_t& aMessageType,
                                      nsTArray<uint8_t>&& aMessage) override;
  ipc::IPCResult RecvOnSessionKeysChange(
    const nsCString& aSessionId,
    nsTArray<CDMKeyInformation>&& aKeysInfo) override;
  ipc::IPCResult RecvOnExpirationChange(
    const nsCString& aSessionId,
    const double& aSecondsSinceEpoch) override;
  ipc::IPCResult RecvOnSessionClosed(const nsCString& aSessionId) override;
  ipc::IPCResult RecvOnLegacySessionError(const nsCString& aSessionId,
                                          const uint32_t& aError,
                                          const uint32_t& aSystemCode,
                                          const nsCString& aMessage) override;
  ipc::IPCResult RecvDecrypted(const uint32_t& aId,
                               const uint32_t& aStatus,
                               ipc::Shmem&& aData) override;
  ipc::IPCResult RecvDecryptFailed(const uint32_t& aId,
                                   const uint32_t& aStatus) override;
  ipc::IPCResult RecvOnDecoderInitDone(const uint32_t& aStatus) override;
  ipc::IPCResult RecvDecodedShmem(const CDMVideoFrame& aFrame,
                                  ipc::Shmem&& aShmem) override;
  ipc::IPCResult RecvDecodedData(const CDMVideoFrame& aFrame,
                                 nsTArray<uint8_t>&& aData) override;
  ipc::IPCResult RecvDecodeFailed(const uint32_t& aStatus) override;
  ipc::IPCResult RecvShutdown() override;
  ipc::IPCResult RecvResetVideoDecoderComplete() override;
  ipc::IPCResult RecvDrainComplete() override;
  ipc::IPCResult RecvIncreaseShmemPoolSize() override;
  void ActorDestroy(ActorDestroyReason aWhy) override;
  bool SendBufferToCDM(uint32_t aSizeInBytes);

  void ReorderAndReturnOutput(RefPtr<VideoData>&& aFrame);

  void RejectPromise(uint32_t aPromiseId,
                     nsresult aError,
                     const nsCString& aErrorMessage);

  void ResolvePromise(uint32_t aPromiseId);

  bool InitCDMInputBuffer(gmp::CDMInputBuffer& aBuffer, MediaRawData* aSample);

  bool PurgeShmems();
  bool EnsureSufficientShmems(size_t aVideoFrameSize);
  already_AddRefed<VideoData> CreateVideoFrame(const CDMVideoFrame& aFrame,
                                               Span<uint8_t> aData);

  const uint32_t mPluginId;
  GMPContentParent* mContentParent;
  // Note: this pointer is a weak reference as ChromiumCDMProxy has a strong reference to the
  // ChromiumCDMCallback.
  ChromiumCDMCallback* mCDMCallback = nullptr;
  nsDataHashtable<nsUint32HashKey, uint32_t> mPromiseToCreateSessionToken;
  nsTArray<RefPtr<DecryptJob>> mDecrypts;

  MozPromiseHolder<MediaDataDecoder::InitPromise> mInitVideoDecoderPromise;
  MozPromiseHolder<MediaDataDecoder::DecodePromise> mDecodePromise;

  RefPtr<layers::ImageContainer> mImageContainer;
  VideoInfo mVideoInfo;
  uint64_t mLastStreamOffset = 0;

  MozPromiseHolder<MediaDataDecoder::FlushPromise> mFlushDecoderPromise;

  size_t mVideoFrameBufferSize = 0;

  // Count of the number of shmems in the set used to return decoded video
  // frames from the CDM to Gecko.
  uint32_t mVideoShmemsActive = 0;
  // Maximum number of shmems to use to return decoded video frames.
  uint32_t mVideoShmemLimit;

  bool mIsShutdown = false;
  bool mVideoDecoderInitialized = false;
  bool mActorDestroyed = false;
  bool mAbnormalShutdown = false;

  // The H.264 decoder in Widevine CDM versions 970 and later output in decode
  // order rather than presentation order, so we reorder in presentation order
  // before presenting. mMaxRefFrames is non-zero if we have an initialized
  // decoder and we are decoding H.264. If so, it stores the maximum length of
  // the reorder queue that we need. Note we may have multiple decoders for the
  // life time of this object, but never more than one active at once.
  uint32_t mMaxRefFrames = 0;
  ReorderQueue mReorderQueue;

  // The main thread associated with the root document. Must be set in Init().
  nsCOMPtr<nsIEventTarget> mMainThread;
};

} // namespace gmp
} // namespace mozilla

#endif // ChromiumCDMParent_h_