tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

DecoderTemplate.h (10209B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozilla_dom_DecoderTemplate_h
      8 #define mozilla_dom_DecoderTemplate_h
      9 
     10 #include <queue>
     11 
     12 #include "SimpleMap.h"
     13 #include "WebCodecsUtils.h"
     14 #include "mozilla/DOMEventTargetHelper.h"
     15 #include "mozilla/DecoderAgent.h"
     16 #include "mozilla/MozPromise.h"
     17 #include "mozilla/RefPtr.h"
     18 #include "mozilla/Result.h"
     19 #include "mozilla/UniquePtr.h"
     20 #include "mozilla/dom/WorkerRef.h"
     21 #include "mozilla/media/MediaUtils.h"
     22 #include "nsStringFwd.h"
     23 
     24 namespace mozilla {
     25 
     26 class TrackInfo;
     27 
     28 namespace dom {
     29 
     30 class WebCodecsErrorCallback;
     31 class Promise;
     32 enum class CodecState : uint8_t;
     33 
     34 template <typename DecoderType>
     35 class DecoderTemplate : public DOMEventTargetHelper {
     36  using Self = DecoderTemplate<DecoderType>;
     37  using ConfigType = typename DecoderType::ConfigType;
     38  using ConfigTypeInternal = typename DecoderType::ConfigTypeInternal;
     39  using InputType = typename DecoderType::InputType;
     40  using InputTypeInternal = typename DecoderType::InputTypeInternal;
     41  using OutputType = typename DecoderType::OutputType;
     42  using OutputCallbackType = typename DecoderType::OutputCallbackType;
     43 
     44  /* ControlMessage classes */
     45 protected:
     46  class ConfigureMessage;
     47  class DecodeMessage;
     48  class FlushMessage;
     49 
     50  class ControlMessage {
     51   public:
     52    ControlMessage(WebCodecsId aConfigId) : mConfigId(aConfigId) {};
     53    virtual ~ControlMessage() = default;
     54    virtual void Cancel() = 0;
     55    virtual bool IsProcessing() = 0;
     56 
     57    virtual nsCString ToString() const = 0;
     58    virtual ConfigureMessage* AsConfigureMessage() { return nullptr; }
     59    virtual DecodeMessage* AsDecodeMessage() { return nullptr; }
     60    virtual FlushMessage* AsFlushMessage() { return nullptr; }
     61 
     62    // All the control message follows a specific configuration. Knowing the
     63    // associated configuration of a decode/flush request is helpful in
     64    // debugging logs. This id is used to identify which ConfigureMessage the
     65    // request follows.
     66    const WebCodecsId mConfigId;
     67  };
     68 
     69  class ConfigureMessage final
     70      : public ControlMessage,
     71        public MessageRequestHolder<DecoderAgent::ConfigurePromise> {
     72   public:
     73    static ConfigureMessage* Create(
     74        already_AddRefed<ConfigTypeInternal> aConfig);
     75 
     76    ~ConfigureMessage() = default;
     77    virtual void Cancel() override { Disconnect(); }
     78    virtual bool IsProcessing() override { return Exists(); };
     79    virtual nsCString ToString() const override;
     80    virtual ConfigureMessage* AsConfigureMessage() override { return this; }
     81    const ConfigTypeInternal& Config() { return *mConfig; }
     82    already_AddRefed<ConfigTypeInternal> TakeConfig() {
     83      return mConfig.forget();
     84    }
     85 
     86   private:
     87    ConfigureMessage(WebCodecsId aConfigId,
     88                     already_AddRefed<ConfigTypeInternal> aConfig);
     89 
     90    RefPtr<ConfigTypeInternal> mConfig;
     91    const nsCString mCodec;
     92  };
     93 
     94  class DecodeMessage final
     95      : public ControlMessage,
     96        public MessageRequestHolder<DecoderAgent::DecodePromise> {
     97   public:
     98    DecodeMessage(WebCodecsId aSeqId, WebCodecsId aConfigId,
     99                  UniquePtr<InputTypeInternal>&& aData);
    100    ~DecodeMessage() = default;
    101    virtual void Cancel() override { Disconnect(); }
    102    virtual bool IsProcessing() override { return Exists(); };
    103    virtual nsCString ToString() const override;
    104    virtual DecodeMessage* AsDecodeMessage() override { return this; }
    105 
    106    // The sequence id of a decode request associated with a specific
    107    // configuration.
    108    const WebCodecsId mSeqId;
    109    UniquePtr<InputTypeInternal> mData;
    110  };
    111 
    112  class FlushMessage final
    113      : public ControlMessage,
    114        public MessageRequestHolder<DecoderAgent::DecodePromise> {
    115   public:
    116    FlushMessage(WebCodecsId aSeqId, WebCodecsId aConfigId);
    117    ~FlushMessage() = default;
    118    virtual void Cancel() override { Disconnect(); }
    119    virtual bool IsProcessing() override { return Exists(); };
    120    virtual nsCString ToString() const override;
    121    virtual FlushMessage* AsFlushMessage() override { return this; }
    122 
    123    // The sequence id of a flush request associated with a specific
    124    // configuration.
    125    const WebCodecsId mSeqId;
    126    const int64_t mUniqueId;
    127  };
    128 
    129 protected:
    130  DecoderTemplate(nsIGlobalObject* aGlobalObject,
    131                  RefPtr<WebCodecsErrorCallback>&& aErrorCallback,
    132                  RefPtr<OutputCallbackType>&& aOutputCallback);
    133 
    134  virtual ~DecoderTemplate() = default;
    135 
    136  /* WebCodecs interfaces */
    137 public:
    138  IMPL_EVENT_HANDLER(dequeue)
    139 
    140  CodecState State() const { return mState; };
    141 
    142  uint32_t DecodeQueueSize() const { return mDecodeQueueSize; };
    143 
    144  void Configure(const ConfigType& aConfig, ErrorResult& aRv);
    145 
    146  void Decode(InputType& aInput, ErrorResult& aRv);
    147 
    148  already_AddRefed<Promise> Flush(ErrorResult& aRv);
    149 
    150  void Reset(ErrorResult& aRv);
    151 
    152  void Close(ErrorResult& aRv);
    153 
    154  /* Type conversion functions for the Decoder implementation */
    155 protected:
    156  virtual already_AddRefed<MediaRawData> InputDataToMediaRawData(
    157      UniquePtr<InputTypeInternal>&& aData, TrackInfo& aInfo,
    158      const ConfigTypeInternal& aConfig) = 0;
    159  virtual nsTArray<RefPtr<OutputType>> DecodedDataToOutputType(
    160      nsIGlobalObject* aGlobalObject, const nsTArray<RefPtr<MediaData>>&& aData,
    161      const ConfigTypeInternal& aConfig) = 0;
    162 
    163 protected:
    164  // DecoderTemplate can run on either main thread or worker thread.
    165  void AssertIsOnOwningThread() const {
    166    NS_ASSERT_OWNINGTHREAD(DecoderTemplate);
    167  }
    168 
    169  Result<Ok, nsresult> ResetInternal(const nsresult& aResult);
    170  // Calling this method calls the error callback synchronously.
    171  MOZ_CAN_RUN_SCRIPT
    172  void CloseInternal(const nsresult& aResult);
    173  // Calling this method doesn't call the error calback.
    174  Result<Ok, nsresult> CloseInternalWithAbort();
    175 
    176  MOZ_CAN_RUN_SCRIPT void ReportError(const nsresult& aResult);
    177  MOZ_CAN_RUN_SCRIPT void OutputDecodedData(
    178      const nsTArray<RefPtr<MediaData>>&& aData,
    179      const ConfigTypeInternal& aConfig);
    180 
    181  void ScheduleDequeueEventIfNeeded();
    182  nsresult FireEvent(nsAtom* aTypeWithOn, const nsAString& aEventType);
    183 
    184  void ProcessControlMessageQueue();
    185  void CancelPendingControlMessagesAndFlushPromises(const nsresult& aResult);
    186 
    187  // Queue a task to the control thread. This is to be used when a task needs to
    188  // perform multiple steps.
    189  template <typename Func>
    190  void QueueATask(const char* aName, Func&& aSteps);
    191 
    192  MessageProcessedResult ProcessConfigureMessage(
    193      UniquePtr<ControlMessage>& aMessage);
    194 
    195  MessageProcessedResult ProcessDecodeMessage(
    196      UniquePtr<ControlMessage>& aMessage);
    197 
    198  MessageProcessedResult ProcessFlushMessage(
    199      UniquePtr<ControlMessage>& aMessage);
    200 
    201  // Returns true when mAgent can be created.
    202  bool CreateDecoderAgent(DecoderAgent::Id aId,
    203                          already_AddRefed<ConfigTypeInternal> aConfig,
    204                          UniquePtr<TrackInfo>&& aInfo);
    205  void DestroyDecoderAgentIfAny();
    206 
    207  // Constant in practice, only set in ctor.
    208  RefPtr<WebCodecsErrorCallback> mErrorCallback;
    209  RefPtr<OutputCallbackType> mOutputCallback;
    210 
    211  CodecState mState;
    212  bool mKeyChunkRequired;
    213 
    214  bool mMessageQueueBlocked;
    215  std::queue<UniquePtr<ControlMessage>> mControlMessageQueue;
    216  UniquePtr<ControlMessage> mProcessingMessage;
    217 
    218  // When a flush request is initiated, a promise is created and stored in
    219  // mPendingFlushPromises until it is settled in the task delivering the flush
    220  // result or Reset() is called before the promise is settled.
    221  SimpleMap<int64_t, RefPtr<Promise>> mPendingFlushPromises;
    222 
    223  uint32_t mDecodeQueueSize;
    224  bool mDequeueEventScheduled;
    225 
    226  // A unique id tracking the ConfigureMessage and will be used as the
    227  // DecoderAgent's Id.
    228  uint32_t mLatestConfigureId;
    229  // Tracking how many decode data has been enqueued and this number will be
    230  // used as the DecodeMessage's sequence Id.
    231  size_t mDecodeCounter;
    232  // Tracking how many flush request has been enqueued and this number will be
    233  // used as the FlushMessage's sequence Id.
    234  size_t mFlushCounter;
    235 
    236  // DecoderAgent will be created every time "configure" is being processed, and
    237  // will be destroyed when "reset" or another "configure" is called (spec
    238  // allows calling two "configure" without a "reset" in between).
    239  RefPtr<DecoderAgent> mAgent;
    240  RefPtr<ConfigTypeInternal> mActiveConfig;
    241 
    242  // Used to add a nsIAsyncShutdownBlocker on main thread to block
    243  // xpcom-shutdown before the underlying MediaDataDecoder is created. The
    244  // blocker will be held until the underlying MediaDataDecoder has been shut
    245  // down. This blocker guarantees RemoteDecoderManagerChild's thread, where the
    246  // underlying RemoteMediaDataDecoder is on, outlives the
    247  // RemoteMediaDataDecoder, since the thread releasing, which happens on main
    248  // thread when getting a xpcom-shutdown signal, is blocked by the added
    249  // blocker. As a result, RemoteMediaDataDecoder can safely work on worker
    250  // thread with a holding blocker (otherwise, if RemoteDecoderManagerChild
    251  // releases its thread on main thread before RemoteMediaDataDecoder's
    252  // Shutdown() task run on worker thread, RemoteMediaDataDecoder has no thread
    253  // to run).
    254  UniquePtr<media::ShutdownBlockingTicket> mShutdownBlocker;
    255 
    256  // Held to make sure the dispatched tasks can be done before worker is going
    257  // away. As long as this worker-ref is held somewhere, the tasks dispatched to
    258  // the worker can be executed (otherwise the tasks would be canceled). This
    259  // ref should be activated as long as the underlying MediaDataDecoder is
    260  // alive, and should keep alive until mShutdownBlocker is dropped, so all
    261  // MediaDataDecoder's tasks and mShutdownBlocker-releasing task can be
    262  // executed.
    263  // TODO: Use StrongWorkerRef instead if this is always used in the same
    264  // thread?
    265  RefPtr<ThreadSafeWorkerRef> mWorkerRef;
    266 
    267  AsyncDurationTracker mAsyncDurationTracker;
    268 };
    269 
    270 }  // namespace dom
    271 }  // namespace mozilla
    272 
    273 #endif  // mozilla_dom_DecoderTemplate_h