tor-browser

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

PlatformEncoderModule.h (9328B)


      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 #if !defined(PlatformEncoderModule_h_)
      8 #  define PlatformEncoderModule_h_
      9 
     10 #  include "EncoderConfig.h"
     11 #  include "MP4Decoder.h"
     12 #  include "MediaCodecsSupport.h"
     13 #  include "MediaResult.h"
     14 #  include "VPXDecoder.h"
     15 #  include "VideoUtils.h"
     16 #  include "mozilla/Maybe.h"
     17 #  include "mozilla/MozPromise.h"
     18 #  include "mozilla/RefPtr.h"
     19 #  include "mozilla/TaskQueue.h"
     20 #  include "mozilla/dom/ImageBitmapBinding.h"
     21 #  include "nsISupportsImpl.h"
     22 
     23 namespace mozilla {
     24 
     25 class MediaDataEncoder;
     26 class MediaData;
     27 class EncoderConfigurationChangeList;
     28 
     29 class PlatformEncoderModule {
     30 public:
     31  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PlatformEncoderModule)
     32 
     33  virtual already_AddRefed<MediaDataEncoder> CreateVideoEncoder(
     34      const EncoderConfig& aConfig, const RefPtr<TaskQueue>& aTaskQueue) const {
     35    return nullptr;
     36  };
     37 
     38  virtual already_AddRefed<MediaDataEncoder> CreateAudioEncoder(
     39      const EncoderConfig& aConfig, const RefPtr<TaskQueue>& aTaskQueue) const {
     40    return nullptr;
     41  };
     42 
     43  using CreateEncoderPromise = MozPromise<RefPtr<MediaDataEncoder>, MediaResult,
     44                                          /* IsExclusive = */ true>;
     45 
     46  // Indicates if the PlatformDecoderModule supports encoding of a codec.
     47  virtual media::EncodeSupportSet Supports(
     48      const EncoderConfig& aConfig) const = 0;
     49  virtual media::EncodeSupportSet SupportsCodec(CodecType aCodecType) const = 0;
     50 
     51  // Returns a readable name for this Platform Encoder Module
     52  virtual const char* GetName() const = 0;
     53 
     54  // Asychronously create an encoder
     55  virtual RefPtr<PlatformEncoderModule::CreateEncoderPromise>
     56  AsyncCreateEncoder(const EncoderConfig& aEncoderConfig,
     57                     const RefPtr<TaskQueue>& aTaskQueue);
     58 
     59 protected:
     60  PlatformEncoderModule() = default;
     61  virtual ~PlatformEncoderModule() = default;
     62 };
     63 
     64 class MediaDataEncoder {
     65 public:
     66  NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
     67 
     68  using InitPromise = MozPromise<bool, MediaResult, /* IsExclusive = */ true>;
     69  using EncodedData = nsTArray<RefPtr<MediaRawData>>;
     70  using EncodePromise =
     71      MozPromise<EncodedData, MediaResult, /* IsExclusive = */ true>;
     72  using ReconfigurationPromise =
     73      MozPromise<bool, MediaResult, /* IsExclusive = */ true>;
     74 
     75  // Initialize the encoder. It should be ready to encode once the returned
     76  // promise resolves. The encoder should do any initialization here, rather
     77  // than in its constructor or PlatformEncoderModule::Create*Encoder(),
     78  // so that if the client needs to shutdown during initialization,
     79  // it can call Shutdown() to cancel this operation. Any initialization
     80  // that requires blocking the calling thread in this function *must*
     81  // be done here so that it can be canceled by calling Shutdown()!
     82  virtual RefPtr<InitPromise> Init() = 0;
     83 
     84  // Inserts a sample into the encoder's encode pipeline. The EncodePromise it
     85  // returns will be resolved with already encoded MediaRawData at the moment,
     86  // or empty when there is none available yet.
     87  virtual RefPtr<EncodePromise> Encode(const MediaData* aSample) = 0;
     88 
     89  // Inserts a batch of samples into the encoder's encode pipeline. The
     90  // EncodePromise it returns will be resolved with already encoded MediaRawData
     91  // at the moment, or empty when there is none available yet.
     92  virtual RefPtr<EncodePromise> Encode(nsTArray<RefPtr<MediaData>>&& aSamples) {
     93    MOZ_ASSERT_UNREACHABLE("Encode samples in a batch is not implemented");
     94    return EncodePromise::CreateAndReject(
     95        MediaResult(NS_ERROR_NOT_IMPLEMENTED,
     96                    "Encode samples in a batch is not implemented"),
     97        __func__);
     98  }
     99 
    100  // Attempt to reconfigure the encoder on the fly. This can fail if the
    101  // underlying PEM doesn't support this type of reconfiguration.
    102  virtual RefPtr<ReconfigurationPromise> Reconfigure(
    103      const RefPtr<const EncoderConfigurationChangeList>&
    104          aConfigurationChanges) = 0;
    105 
    106  // Causes all complete samples in the pipeline that can be encoded to be
    107  // output. It indicates that there is no more input sample to insert.
    108  // This function is asynchronous.
    109  // The MediaDataEncoder shall resolve the pending EncodePromise with drained
    110  // samples. Drain will be called multiple times until the resolved
    111  // EncodePromise is empty which indicates that there are no more samples to
    112  // drain.
    113  virtual RefPtr<EncodePromise> Drain() = 0;
    114 
    115  // Cancels all init/encode/drain operations, and shuts down the encoder. The
    116  // platform encoder should clean up any resources it's using and release
    117  // memory etc. The shutdown promise will be resolved once the encoder has
    118  // completed shutdown. The client will delete the decoder once the promise is
    119  // resolved.
    120  // The ShutdownPromise must only ever be resolved.
    121  virtual RefPtr<ShutdownPromise> Shutdown() = 0;
    122 
    123  virtual RefPtr<GenericPromise> SetBitrate(uint32_t aBitsPerSec) {
    124    return GenericPromise::CreateAndResolve(true, __func__);
    125  }
    126 
    127  // Decoder needs to decide whether or not hardware acceleration is supported
    128  // after creating. It doesn't need to call Init() before calling this
    129  // function.
    130  virtual bool IsHardwareAccelerated(nsACString& aFailureReason) const {
    131    return false;
    132  }
    133 
    134  // Return the name of the MediaDataEncoder, only used for encoding.
    135  // May be accessed in a non thread-safe fashion.
    136  virtual nsCString GetDescriptionName() const = 0;
    137 
    138  friend class PlatformEncoderModule;
    139 
    140 protected:
    141  virtual ~MediaDataEncoder() = default;
    142 };
    143 
    144 // Wrap a type to make it unique. This allows using ergonomically in the Variant
    145 // below. Simply aliasing with `using` isn't enough, because typedefs in C++
    146 // don't produce strong types, so two integer variants result in
    147 // the same type, making it ambiguous to the Variant code.
    148 // T is the type to be wrapped. Phantom is a type that is only used to
    149 // disambiguate and should be unique in the program.
    150 template <typename T, typename Phantom>
    151 class StrongTypedef {
    152 public:
    153  StrongTypedef() = default;
    154  explicit StrongTypedef(T const& value) : mValue(value) {}
    155  explicit StrongTypedef(T&& value) : mValue(std::move(value)) {}
    156  T& get() { return mValue; }
    157  T const& get() const { return mValue; }
    158 
    159 private:
    160  T mValue{};
    161 
    162  friend struct IPC::ParamTraits<StrongTypedef<T, Phantom>>;
    163 };
    164 
    165 // Dimensions of the video frames
    166 using DimensionsChange =
    167    StrongTypedef<gfx::IntSize, struct DimensionsChangeType>;
    168 // Expected display size of the encoded frames, can influence encoding
    169 using DisplayDimensionsChange =
    170    StrongTypedef<Maybe<gfx::IntSize>, struct DisplayDimensionsChangeType>;
    171 // If present, the bitrate in kbps of the encoded stream. If absent, let the
    172 // platform decide.
    173 using BitrateChange = StrongTypedef<Maybe<uint32_t>, struct BitrateChangeType>;
    174 // If present, the expected framerate of the output video stream. If absent,
    175 // infer from the input frames timestamp.
    176 using FramerateChange =
    177    StrongTypedef<Maybe<double>, struct FramerateChangeType>;
    178 // The bitrate mode (variable, constant) of the encoding
    179 using BitrateModeChange =
    180    StrongTypedef<BitrateMode, struct BitrateModeChangeType>;
    181 // The usage for the encoded stream, this influence latency, ordering, etc.
    182 using UsageChange = StrongTypedef<Usage, struct UsageChangeType>;
    183 // If present, the expected content of the video frames (screen, movie, etc.).
    184 // The value the string can have isn't decided just yet. When absent, the
    185 // encoder uses generic settings.
    186 using ContentHintChange =
    187    StrongTypedef<Maybe<nsString>, struct ContentHintTypeType>;
    188 // If present, the new sample-rate of the audio
    189 using SampleRateChange = StrongTypedef<uint32_t, struct SampleRateChangeType>;
    190 // If present, the new sample-rate of the audio
    191 using NumberOfChannelsChange =
    192    StrongTypedef<uint32_t, struct NumberOfChannelsChangeType>;
    193 
    194 // A change to a parameter of an encoder instance.
    195 using EncoderConfigurationItem =
    196    Variant<DimensionsChange, DisplayDimensionsChange, BitrateModeChange,
    197            BitrateChange, FramerateChange, UsageChange, ContentHintChange,
    198            SampleRateChange, NumberOfChannelsChange>;
    199 
    200 // A list of changes to an encoder configuration, that _might_ be able to change
    201 // on the fly. Not all encoder modules can adjust their configuration on the
    202 // fly.
    203 class EncoderConfigurationChangeList {
    204 public:
    205  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(EncoderConfigurationChangeList)
    206  bool Empty() const { return mChanges.IsEmpty(); }
    207  template <typename T>
    208  void Push(const T& aItem) {
    209    mChanges.AppendElement(aItem);
    210  }
    211  nsString ToString() const;
    212 
    213  nsTArray<EncoderConfigurationItem> mChanges;
    214 
    215 private:
    216  ~EncoderConfigurationChangeList() = default;
    217 };
    218 
    219 // Just by inspecting the configuration and before asking the PEM, it's
    220 // sometimes possible to know that a media won't be able to be encoded. For
    221 // example, VP8 encodes the frame size on 14 bits, so a resolution of more than
    222 // 16383x16383 pixels cannot work.
    223 bool CanLikelyEncode(const EncoderConfig& aConfig);
    224 
    225 }  // namespace mozilla
    226 
    227 #endif /* PlatformEncoderModule_h_ */