tor-browser

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

PlatformDecoderModule.h (27409B)


      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(PlatformDecoderModule_h_)
      8 #  define PlatformDecoderModule_h_
      9 
     10 #  include "DecoderDoctorLogger.h"
     11 #  include "GMPCrashHelper.h"
     12 #  include "MediaCodecsSupport.h"
     13 #  include "MediaEventSource.h"
     14 #  include "MediaInfo.h"
     15 #  include "MediaResult.h"
     16 #  include "PerformanceRecorder.h"
     17 #  include "mozilla/EnumSet.h"
     18 #  include "mozilla/EnumTypeTraits.h"
     19 #  include "mozilla/MozPromise.h"
     20 #  include "mozilla/PRemoteCDMActor.h"
     21 #  include "mozilla/RefPtr.h"
     22 #  include "mozilla/TaskQueue.h"
     23 #  include "mozilla/ipc/UtilityMediaService.h"
     24 #  include "mozilla/layers/KnowsCompositor.h"
     25 #  include "mozilla/layers/LayersTypes.h"
     26 #  include "nsTArray.h"
     27 
     28 namespace mozilla {
     29 class TrackInfo;
     30 class AudioInfo;
     31 class VideoInfo;
     32 class MediaRawData;
     33 class DecoderDoctorDiagnostics;
     34 
     35 namespace layers {
     36 class ImageContainer;
     37 }  // namespace layers
     38 
     39 class MediaDataDecoder;
     40 class RemoteDecoderModule;
     41 class CDMProxy;
     42 
     43 static LazyLogModule sPDMLog("PlatformDecoderModule");
     44 
     45 namespace media {
     46 
     47 template <typename T>
     48 static nsCString EnumSetToString(const EnumSet<T>& aSet) {
     49  nsCString str;
     50  for (const auto e : aSet) {
     51    if (!str.IsEmpty()) {
     52      str.AppendLiteral("|");
     53    }
     54    str.AppendPrintf("%s", EnumValueToString(e));
     55  }
     56  if (str.IsEmpty()) {
     57    str.AppendLiteral("Empty");
     58  }
     59  return str;
     60 }
     61 
     62 MOZ_DEFINE_ENUM_CLASS_WITH_TOSTRING(
     63    Option,
     64    (Default, LowLatency, HardwareDecoderNotAllowed, FullH264Parsing,
     65     ErrorIfNoInitializationData,  // By default frames delivered before
     66                                   // initialization data are dropped. Pass this
     67                                   // option to raise an error if frames are
     68                                   // delivered before initialization data.
     69     DefaultPlaybackDeviceMono,  // Currently only used by Opus on RDD to avoid
     70                                 // initialization of audio backends on RDD
     71     KeepOriginalPts,  // It can be that the decoder mangles the pts of decoded
     72                       // frames, this forces using the input PTS.
     73     Output8BitPerChannel,  // Convert decoded data to 8-bit per channel format.
     74                            // Useful when the consumer (webrender, WebGL, ...)
     75                            // doesn't support inputs higher than 8-bit. ONLY
     76                            // SUPPORTED BY DAV1DDecoder and FFmpegVideoDecoder.
     77 
     78     SENTINEL  // one past the last valid value
     79     ));
     80 
     81 using OptionSet = EnumSet<Option>;
     82 
     83 struct UseNullDecoder {
     84  UseNullDecoder() = default;
     85  explicit UseNullDecoder(bool aUseNullDecoder) : mUse(aUseNullDecoder) {}
     86  bool mUse = false;
     87 };
     88 
     89 // Do not wrap H264 decoder in a H264Converter.
     90 MOZ_DEFINE_ENUM_CLASS_WITH_BASE_AND_TOSTRING(Wrapper, uint8_t,
     91                                             (AudioTrimmer,
     92                                              MediaChangeMonitor));
     93 using WrapperSet = EnumSet<Wrapper>;
     94 static WrapperSet GetDefaultWrapperSet(const TrackInfo& aInfo) {
     95  // MediaChangeMonitor can work with some audio codecs like AAC but only
     96  // WebCodecs needs it, so it's only enabled for video by default.
     97  WrapperSet set;
     98  if (aInfo.IsVideo()) {
     99    set += Wrapper::MediaChangeMonitor;
    100  }
    101  if (aInfo.IsAudio()) {
    102    set += Wrapper::AudioTrimmer;
    103  }
    104  return set;
    105 }
    106 
    107 struct VideoFrameRate {
    108  VideoFrameRate() = default;
    109  explicit VideoFrameRate(float aFramerate) : mValue(aFramerate) {}
    110  float mValue = 0.0f;
    111 };
    112 
    113 }  // namespace media
    114 
    115 struct CreateDecoderParams;
    116 struct CreateDecoderParamsForAsync {
    117  using Option = media::Option;
    118  using OptionSet = media::OptionSet;
    119  explicit CreateDecoderParamsForAsync(const CreateDecoderParams& aParams);
    120  CreateDecoderParamsForAsync(CreateDecoderParamsForAsync&& aParams);
    121 
    122  const VideoInfo& VideoConfig() const {
    123    MOZ_ASSERT(mConfig->IsVideo());
    124    return *mConfig->GetAsVideoInfo();
    125  }
    126 
    127  const AudioInfo& AudioConfig() const {
    128    MOZ_ASSERT(mConfig->IsAudio());
    129    return *mConfig->GetAsAudioInfo();
    130  }
    131 
    132  UniquePtr<TrackInfo> mConfig;
    133  const RefPtr<layers::ImageContainer> mImageContainer;
    134  const RefPtr<layers::KnowsCompositor> mKnowsCompositor;
    135  const RefPtr<GMPCrashHelper> mCrashHelper;
    136  const RefPtr<PRemoteCDMActor> mCDM;
    137  const media::UseNullDecoder mUseNullDecoder;
    138  const media::WrapperSet mWrappers;
    139  const TrackInfo::TrackType mType = TrackInfo::kUndefinedTrack;
    140  std::function<MediaEventProducer<TrackInfo::TrackType>*()>
    141      mOnWaitingForKeyEvent;
    142  const OptionSet mOptions = OptionSet(Option::Default);
    143  const media::VideoFrameRate mRate;
    144  const Maybe<uint64_t> mMediaEngineId;
    145  const Maybe<TrackingId> mTrackingId;
    146 };
    147 
    148 struct MOZ_STACK_CLASS CreateDecoderParams final {
    149  using Option = media::Option;
    150  using OptionSet = media::OptionSet;
    151  using UseNullDecoder = media::UseNullDecoder;
    152  using WrapperSet = media::WrapperSet;
    153  using VideoFrameRate = media::VideoFrameRate;
    154  enum class EncryptedCustomIdent : bool {
    155    False,
    156    True,
    157  };
    158 
    159  explicit CreateDecoderParams(const TrackInfo& aConfig)
    160      : mConfig(aConfig), mWrappers(media::GetDefaultWrapperSet(aConfig)) {}
    161  CreateDecoderParams(const CreateDecoderParams& aParams) = default;
    162 
    163  MOZ_IMPLICIT CreateDecoderParams(const CreateDecoderParamsForAsync& aParams)
    164      : mConfig(*aParams.mConfig),
    165        mImageContainer(aParams.mImageContainer),
    166        mKnowsCompositor(aParams.mKnowsCompositor),
    167        mCrashHelper(aParams.mCrashHelper),
    168        mCDM(aParams.mCDM),
    169        mUseNullDecoder(aParams.mUseNullDecoder),
    170        mWrappers(aParams.mWrappers),
    171        mType(aParams.mType),
    172        mOnWaitingForKeyEvent(aParams.mOnWaitingForKeyEvent),
    173        mOptions(aParams.mOptions),
    174        mRate(aParams.mRate),
    175        mMediaEngineId(aParams.mMediaEngineId),
    176        mTrackingId(aParams.mTrackingId) {}
    177 
    178  template <typename T1, typename... Ts>
    179  CreateDecoderParams(const TrackInfo& aConfig, T1&& a1, Ts&&... args)
    180      : mConfig(aConfig), mWrappers(media::GetDefaultWrapperSet(aConfig)) {
    181    Set(std::forward<T1>(a1), std::forward<Ts>(args)...);
    182  }
    183 
    184  template <typename T1, typename... Ts>
    185  CreateDecoderParams(const CreateDecoderParams& aParams, T1&& a1, Ts&&... args)
    186      : CreateDecoderParams(aParams) {
    187    Set(std::forward<T1>(a1), std::forward<Ts>(args)...);
    188  }
    189 
    190  const VideoInfo& VideoConfig() const {
    191    MOZ_ASSERT(mConfig.IsVideo());
    192    return *mConfig.GetAsVideoInfo();
    193  }
    194 
    195  const AudioInfo& AudioConfig() const {
    196    MOZ_ASSERT(mConfig.IsAudio());
    197    return *mConfig.GetAsAudioInfo();
    198  }
    199 
    200  bool IsVideo() const { return mConfig.IsVideo(); }
    201 
    202  bool IsAudio() const { return mConfig.IsAudio(); }
    203 
    204  layers::LayersBackend GetLayersBackend() const {
    205    if (mKnowsCompositor) {
    206      return mKnowsCompositor->GetCompositorBackendType();
    207    }
    208    return layers::LayersBackend::LAYERS_NONE;
    209  }
    210 
    211  nsCString ToString() const {
    212    nsPrintfCString str("CreateDecoderParams @ %p: ", this);
    213    str.AppendPrintf("mConfig = %s", mConfig.ToString().get());
    214    str.AppendPrintf(", mImageContainer = %p", mImageContainer);
    215    str.AppendPrintf(", mError = %s",
    216                     mError ? mError->Description().get() : "null");
    217    str.AppendPrintf(", mKnowsCompositor = %p", mKnowsCompositor);
    218    str.AppendPrintf(", mCrashHelper = %p", mCrashHelper);
    219    str.AppendPrintf(", mCDM = %p", mCDM);
    220    str.AppendPrintf(", mUseNullDecoder = %s",
    221                     mUseNullDecoder.mUse ? "yes" : "no");
    222    str.AppendPrintf(", mWrappers = %s", EnumSetToString(mWrappers).get());
    223    str.AppendPrintf(", mType = %d", static_cast<int32_t>(mType));
    224    str.AppendPrintf(", mOnWaitingForKeyEvent = %s",
    225                     mOnWaitingForKeyEvent ? "yes" : "no");
    226    str.AppendPrintf(", mOptions = %s", EnumSetToString(mOptions).get());
    227    str.AppendPrintf(", mRate = %f", mRate.mValue);
    228    str.AppendPrintf(
    229        ", mMediaEngineId = %s",
    230        mMediaEngineId ? std::to_string(*mMediaEngineId).c_str() : "None");
    231    str.AppendPrintf(", mTrackingId = %s",
    232                     mTrackingId ? mTrackingId->ToString().get() : "None");
    233    str.AppendPrintf(
    234        ", mEncryptedCustomIdent = %s",
    235        mEncryptedCustomIdent == EncryptedCustomIdent::True ? "true" : "false");
    236    return {std::move(str)};
    237  }
    238 
    239  // CreateDecoderParams is a MOZ_STACK_CLASS, it is only used to
    240  // simplify the passing of arguments to Create*Decoder.
    241  // It is safe to use references and raw pointers.
    242  const TrackInfo& mConfig;
    243  layers::ImageContainer* mImageContainer = nullptr;
    244  MediaResult* mError = nullptr;
    245  layers::KnowsCompositor* mKnowsCompositor = nullptr;
    246  GMPCrashHelper* mCrashHelper = nullptr;
    247  PRemoteCDMActor* mCDM = nullptr;
    248  media::UseNullDecoder mUseNullDecoder;
    249  WrapperSet mWrappers;
    250  TrackInfo::TrackType mType = TrackInfo::kUndefinedTrack;
    251  std::function<MediaEventProducer<TrackInfo::TrackType>*()>
    252      mOnWaitingForKeyEvent;
    253  OptionSet mOptions = OptionSet(Option::Default);
    254  media::VideoFrameRate mRate;
    255  // Used on Windows when the MF media engine playback is enabled.
    256  Maybe<uint64_t> mMediaEngineId;
    257  Maybe<TrackingId> mTrackingId;
    258  EncryptedCustomIdent mEncryptedCustomIdent = EncryptedCustomIdent::False;
    259 
    260 private:
    261  void Set(layers::ImageContainer* aImageContainer) {
    262    mImageContainer = aImageContainer;
    263  }
    264  void Set(MediaResult* aError) { mError = aError; }
    265  void Set(GMPCrashHelper* aCrashHelper) { mCrashHelper = aCrashHelper; }
    266  void Set(PRemoteCDMActor* aCDM) { mCDM = aCDM; }
    267  void Set(UseNullDecoder aUseNullDecoder) {
    268    mUseNullDecoder = aUseNullDecoder;
    269  }
    270  void Set(const WrapperSet& aWrappers) { mWrappers = aWrappers; }
    271  void Set(const OptionSet& aOptions) { mOptions = aOptions; }
    272  void Set(VideoFrameRate aRate) { mRate = aRate; }
    273  void Set(layers::KnowsCompositor* aKnowsCompositor) {
    274    if (aKnowsCompositor) {
    275      mKnowsCompositor = aKnowsCompositor;
    276      MOZ_ASSERT(aKnowsCompositor->IsThreadSafe());
    277    }
    278  }
    279  void Set(TrackInfo::TrackType aType) { mType = aType; }
    280  void Set(std::function<MediaEventProducer<TrackInfo::TrackType>*()>&&
    281               aOnWaitingForKey) {
    282    mOnWaitingForKeyEvent = std::move(aOnWaitingForKey);
    283  }
    284  void Set(const std::function<MediaEventProducer<TrackInfo::TrackType>*()>&
    285               aOnWaitingForKey) {
    286    mOnWaitingForKeyEvent = aOnWaitingForKey;
    287  }
    288  void Set(const Maybe<uint64_t>& aMediaEngineId) {
    289    mMediaEngineId = aMediaEngineId;
    290  }
    291  void Set(const Maybe<TrackingId>& aTrackingId) { mTrackingId = aTrackingId; }
    292  void Set(const EncryptedCustomIdent aEncryptedCustomIdent) {
    293    mEncryptedCustomIdent = aEncryptedCustomIdent;
    294  }
    295  void Set(const CreateDecoderParams& aParams) {
    296    // Set all but mTrackInfo;
    297    mImageContainer = aParams.mImageContainer;
    298    mError = aParams.mError;
    299    mKnowsCompositor = aParams.mKnowsCompositor;
    300    mCrashHelper = aParams.mCrashHelper;
    301    mCDM = aParams.mCDM;
    302    mUseNullDecoder = aParams.mUseNullDecoder;
    303    mWrappers = aParams.mWrappers;
    304    mType = aParams.mType;
    305    mOnWaitingForKeyEvent = aParams.mOnWaitingForKeyEvent;
    306    mOptions = aParams.mOptions;
    307    mRate = aParams.mRate;
    308    mMediaEngineId = aParams.mMediaEngineId;
    309    mTrackingId = aParams.mTrackingId;
    310  }
    311  template <typename T1, typename T2, typename... Ts>
    312  void Set(T1&& a1, T2&& a2, Ts&&... args) {
    313    Set(std::forward<T1>(a1));
    314    Set(std::forward<T2>(a2), std::forward<Ts>(args)...);
    315  }
    316 };
    317 
    318 struct MOZ_STACK_CLASS SupportDecoderParams final {
    319  using Option = media::Option;
    320  using OptionSet = media::OptionSet;
    321  using UseNullDecoder = media::UseNullDecoder;
    322  using WrapperSet = media::WrapperSet;
    323  using VideoFrameRate = media::VideoFrameRate;
    324 
    325  explicit SupportDecoderParams(const TrackInfo& aConfig)
    326      : mConfig(aConfig), mWrappers(media::GetDefaultWrapperSet(aConfig)) {}
    327 
    328  explicit SupportDecoderParams(const CreateDecoderParams& aParams)
    329      : mConfig(aParams.mConfig),
    330        mError(aParams.mError),
    331        mKnowsCompositor(aParams.mKnowsCompositor),
    332        mCDM(aParams.mCDM),
    333        mUseNullDecoder(aParams.mUseNullDecoder),
    334        mWrappers(aParams.mWrappers),
    335        mOptions(aParams.mOptions),
    336        mRate(aParams.mRate),
    337        mMediaEngineId(aParams.mMediaEngineId) {}
    338 
    339  template <typename T1, typename... Ts>
    340  SupportDecoderParams(const TrackInfo& aConfig, T1&& a1, Ts&&... args)
    341      : mConfig(aConfig), mWrappers(media::GetDefaultWrapperSet(aConfig)) {
    342    Set(std::forward<T1>(a1), std::forward<Ts>(args)...);
    343  }
    344 
    345  const nsCString& MimeType() const { return mConfig.mMimeType; }
    346 
    347  const TrackInfo& mConfig;
    348  DecoderDoctorDiagnostics* mDiagnostics = nullptr;
    349  MediaResult* mError = nullptr;
    350  RefPtr<layers::KnowsCompositor> mKnowsCompositor;
    351  PRemoteCDMActor* mCDM = nullptr;
    352  UseNullDecoder mUseNullDecoder;
    353  WrapperSet mWrappers;
    354  OptionSet mOptions = OptionSet(Option::Default);
    355  VideoFrameRate mRate;
    356  Maybe<uint64_t> mMediaEngineId;
    357 
    358 private:
    359  void Set(DecoderDoctorDiagnostics* aDiagnostics) {
    360    mDiagnostics = aDiagnostics;
    361  }
    362  void Set(MediaResult* aError) { mError = aError; }
    363  void Set(PRemoteCDMActor* aCDM) { mCDM = aCDM; }
    364  void Set(media::UseNullDecoder aUseNullDecoder) {
    365    mUseNullDecoder = aUseNullDecoder;
    366  }
    367  void Set(const WrapperSet& aWrappers) { mWrappers = aWrappers; }
    368  void Set(const media::OptionSet& aOptions) { mOptions = aOptions; }
    369  void Set(media::VideoFrameRate aRate) { mRate = aRate; }
    370  void Set(layers::KnowsCompositor* aKnowsCompositor) {
    371    if (aKnowsCompositor) {
    372      mKnowsCompositor = aKnowsCompositor;
    373      MOZ_ASSERT(aKnowsCompositor->IsThreadSafe());
    374    }
    375  }
    376  void Set(const Maybe<uint64_t>& aMediaEngineId) {
    377    mMediaEngineId = aMediaEngineId;
    378  }
    379 
    380  template <typename T1, typename T2, typename... Ts>
    381  void Set(T1&& a1, T2&& a2, Ts&&... args) {
    382    Set(std::forward<T1>(a1));
    383    Set(std::forward<T2>(a2), std::forward<Ts>(args)...);
    384  }
    385 };
    386 
    387 // Used for IPDL serialization.
    388 // The 'value' have to be the biggest enum from CreateDecoderParams::Option.
    389 template <>
    390 struct MaxEnumValue<::mozilla::CreateDecoderParams::Option> {
    391  static constexpr unsigned int value =
    392      static_cast<unsigned int>(CreateDecoderParams::Option::SENTINEL);
    393 };
    394 
    395 // The PlatformDecoderModule interface is used by the MediaFormatReader to
    396 // abstract access to decoders provided by various
    397 // platforms.
    398 // Each platform (Windows, MacOSX, Linux, B2G etc) must implement a
    399 // PlatformDecoderModule to provide access to its decoders in order to get
    400 // decompressed H.264/AAC from the MediaFormatReader.
    401 //
    402 // Decoding is asynchronous, and should be performed on the task queue
    403 // provided if the underlying platform isn't already exposing an async API.
    404 //
    405 // A cross-platform decoder module that discards input and produces "blank"
    406 // output samples exists for testing, and is created when the pref
    407 // "media.use-blank-decoder" is true.
    408 
    409 class PlatformDecoderModule {
    410 public:
    411  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PlatformDecoderModule)
    412 
    413  virtual const char* Name() const = 0;
    414 
    415  // Perform any per-instance initialization.
    416  // This is called on the decode task queue.
    417  virtual nsresult Startup() { return NS_OK; }
    418 
    419  // Indicates if the PlatformDecoderModule supports decoding of aMimeType,
    420  // and whether or not hardware-accelerated decoding is supported.
    421  // The answer to both SupportsMimeType and Supports doesn't guarantee that
    422  // creation of a decoder will actually succeed.
    423  virtual media::DecodeSupportSet SupportsMimeType(
    424      const nsACString& aMimeType,
    425      DecoderDoctorDiagnostics* aDiagnostics) const = 0;
    426 
    427  virtual media::DecodeSupportSet Supports(
    428      const SupportDecoderParams& aParams,
    429      DecoderDoctorDiagnostics* aDiagnostics) const {
    430    const TrackInfo& trackInfo = aParams.mConfig;
    431    const media::DecodeSupportSet support =
    432        SupportsMimeType(trackInfo.mMimeType, aDiagnostics);
    433 
    434    // Bail early if we don't support this format at all
    435    if (support.isEmpty()) {
    436      return support;
    437    }
    438 
    439    const auto* videoInfo = trackInfo.GetAsVideoInfo();
    440 
    441    if (!videoInfo) {
    442      // No video stream = software decode only
    443      return media::DecodeSupport::SoftwareDecode;
    444    }
    445 
    446    // Check whether we support the desired color depth
    447    if (!SupportsColorDepth(videoInfo->mColorDepth, aDiagnostics)) {
    448      return media::DecodeSupportSet{};
    449    }
    450    return support;
    451  }
    452 
    453  using CreateDecoderPromise = MozPromise<RefPtr<MediaDataDecoder>, MediaResult,
    454                                          /* IsExclusive = */ true>;
    455 
    456 protected:
    457  PlatformDecoderModule() = default;
    458  virtual ~PlatformDecoderModule() = default;
    459 
    460  friend class MediaChangeMonitor;
    461  friend class PDMFactory;
    462  friend class EMEDecoderModule;
    463  friend class RemoteDecoderModule;
    464 
    465  // Indicates if the PlatformDecoderModule supports decoding of aColorDepth.
    466  // Should override this method when the platform can support color depth != 8.
    467  virtual bool SupportsColorDepth(
    468      gfx::ColorDepth aColorDepth,
    469      DecoderDoctorDiagnostics* aDiagnostics) const {
    470    return aColorDepth == gfx::ColorDepth::COLOR_8;
    471  }
    472 
    473  // Creates a Video decoder. The layers backend is passed in so that
    474  // decoders can determine whether hardware accelerated decoding can be used.
    475  // On Windows the task queue's threads in have MSCOM initialized with
    476  // COINIT_MULTITHREADED.
    477  // Returns nullptr if the decoder can't be created.
    478  // It is not safe to store a reference to aParams or aParams.mConfig as the
    479  // object isn't guaranteed to live after the call.
    480  // CreateVideoDecoder may need to make additional checks if the
    481  // CreateDecoderParams argument is actually supported and return nullptr if
    482  // not to allow for fallback PDMs to be tried.
    483  virtual already_AddRefed<MediaDataDecoder> CreateVideoDecoder(
    484      const CreateDecoderParams& aParams) = 0;
    485 
    486  // Creates an Audio decoder with the specified properties.
    487  // Returns nullptr if the decoder can't be created.
    488  // On Windows the task queue's threads in have MSCOM initialized with
    489  // COINIT_MULTITHREADED.
    490  // It is not safe to store a reference to aParams or aParams.mConfig as the
    491  // object isn't guaranteed to live after the call.
    492  // CreateAudioDecoder may need to make additional checks if the
    493  // CreateDecoderParams argument is actually supported and return nullptr if
    494  // not to allow for fallback PDMs to be tried.
    495  virtual already_AddRefed<MediaDataDecoder> CreateAudioDecoder(
    496      const CreateDecoderParams& aParams) = 0;
    497 
    498  // Asychronously create a decoder.
    499  virtual RefPtr<CreateDecoderPromise> AsyncCreateDecoder(
    500      const CreateDecoderParams& aParams);
    501 };
    502 
    503 DDLoggedTypeDeclName(MediaDataDecoder);
    504 
    505 // MediaDataDecoder is the interface exposed by decoders created by the
    506 // PlatformDecoderModule's Create*Decoder() functions. The type of
    507 // media data that the decoder accepts as valid input and produces as
    508 // output is determined when the MediaDataDecoder is created.
    509 //
    510 // Unless otherwise noted, all functions are only called on the decode task
    511 // queue.  An exception is the MediaDataDecoder in
    512 // MediaFormatReader::IsVideoAccelerated() for which all calls (Init(),
    513 // IsHardwareAccelerated(), and Shutdown()) are from the main thread.
    514 //
    515 // Don't block inside these functions, unless it's explicitly noted that you
    516 // should (like in Flush()).
    517 //
    518 // Decoding is done asynchronously.
    519 class MediaDataDecoder : public DecoderDoctorLifeLogger<MediaDataDecoder> {
    520 protected:
    521  virtual ~MediaDataDecoder() = default;
    522 
    523 public:
    524  using TrackType = TrackInfo::TrackType;
    525  using DecodedData = nsTArray<RefPtr<MediaData>>;
    526  using InitPromise = MozPromise<TrackType, MediaResult, true>;
    527  using DecodePromise = MozPromise<DecodedData, MediaResult, true>;
    528  using FlushPromise = MozPromise<bool, MediaResult, true>;
    529 
    530  NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
    531 
    532  // Initialize the decoder. The decoder should be ready to decode once
    533  // the promise resolves. The decoder should do any initialization here, rather
    534  // than in its constructor or PlatformDecoderModule::Create*Decoder(),
    535  // so that if the MediaFormatReader needs to shutdown during initialization,
    536  // it can call Shutdown() to cancel this operation. Any initialization
    537  // that requires blocking the calling thread in this function *must*
    538  // be done here so that it can be canceled by calling Shutdown()!
    539  // Methods Decode, DecodeBatch, Drain, Flush, Shutdown are guaranteed to be
    540  // called on the thread where Init() first ran.
    541  virtual RefPtr<InitPromise> Init() = 0;
    542 
    543  // Inserts a sample into the decoder's decode pipeline. The DecodePromise will
    544  // be resolved with the decoded MediaData. In case the decoder needs more
    545  // input, the DecodePromise may be resolved with an empty array of samples to
    546  // indicate that Decode should be called again before a MediaData is returned.
    547  virtual RefPtr<DecodePromise> Decode(MediaRawData* aSample) = 0;
    548 
    549  // This could probably be implemented as a wrapper that takes a
    550  // generic MediaDataDecoder and manages batching as needed.  For now
    551  // only AudioTrimmer with RemoteMediaDataDecoder supports batch
    552  // decoding.
    553  // Inserts an array of samples into the decoder's decode pipeline. The
    554  // DecodePromise will be resolved with the decoded MediaData. In case
    555  // the decoder needs more input, the DecodePromise may be resolved
    556  // with an empty array of samples to indicate that Decode should be
    557  // called again before a MediaData is returned.
    558  virtual bool CanDecodeBatch() const { return false; }
    559  virtual RefPtr<DecodePromise> DecodeBatch(
    560      nsTArray<RefPtr<MediaRawData>>&& aSamples) {
    561    MOZ_CRASH("DecodeBatch not implemented yet");
    562    return MediaDataDecoder::DecodePromise::CreateAndReject(
    563        NS_ERROR_DOM_MEDIA_DECODE_ERR, __func__);
    564  }
    565 
    566  // Causes all complete samples in the pipeline that can be decoded to be
    567  // output. If the decoder can't produce samples from the current output,
    568  // it drops the input samples. The decoder may be holding onto samples
    569  // that are required to decode samples that it expects to get in future.
    570  // This is called when the demuxer reaches end of stream.
    571  // This function is asynchronous.
    572  // The MediaDataDecoder shall resolve the pending DecodePromise with drained
    573  // samples. Drain will be called multiple times until the resolved
    574  // DecodePromise is empty which indicates that there are no more samples to
    575  // drain.
    576  virtual RefPtr<DecodePromise> Drain() = 0;
    577 
    578  // Causes all samples in the decoding pipeline to be discarded. When this
    579  // promise resolves, the decoder must be ready to accept new data for
    580  // decoding. This function is called when the demuxer seeks, before decoding
    581  // resumes after the seek. The current DecodePromise if any shall be rejected
    582  // with NS_ERROR_DOM_MEDIA_CANCELED
    583  virtual RefPtr<FlushPromise> Flush() = 0;
    584 
    585  // Cancels all init/decode/drain operations, and shuts down the decoder. The
    586  // platform decoder should clean up any resources it's using and release
    587  // memory etc. The shutdown promise will be resolved once the decoder has
    588  // completed shutdown. The reader calls Flush() before calling Shutdown(). The
    589  // reader will delete the decoder once the promise is resolved.
    590  // The ShutdownPromise must only ever be resolved.
    591  // Shutdown() may not be called if init hasn't been called first. It is
    592  // possible under some circumstances for the decoder to be deleted without
    593  // Init having been called first.
    594  virtual RefPtr<ShutdownPromise> Shutdown() = 0;
    595 
    596  // Called from the state machine task queue or main thread. Decoder needs to
    597  // decide whether or not hardware acceleration is supported after creating.
    598  // It doesn't need to call Init() before calling this function.
    599  virtual bool IsHardwareAccelerated(nsACString& aFailureReason) const {
    600    return false;
    601  }
    602 
    603  // Return the name of the MediaDataDecoder, only used for decoding.
    604  // May be accessed in a non thread-safe fashion.
    605  virtual nsCString GetDescriptionName() const = 0;
    606 
    607  virtual nsCString GetProcessName() const {
    608    nsCString rv = nsCString(XRE_GetProcessTypeString());
    609    if (XRE_IsUtilityProcess()) {
    610      rv += "+"_ns + mozilla::ipc::GetChildAudioActorName();
    611    }
    612    return rv;
    613  };
    614  virtual nsCString GetCodecName() const = 0;
    615 
    616  // Set a hint of seek target time to decoder. Decoder will drop any decoded
    617  // data which pts is smaller than this value. This threshold needs to be clear
    618  // after reset decoder. To clear it explicitly, call this method with
    619  // TimeUnit::Invalid().
    620  // Decoder may not honor this value. However, it'd be better that
    621  // video decoder implements this API to improve seek performance.
    622  // Note: it should be called before Input() or after Flush().
    623  virtual void SetSeekThreshold(const media::TimeUnit& aTime) {}
    624 
    625  // When playing adaptive playback, recreating an Android video decoder will
    626  // cause the transition not smooth during resolution change.
    627  // Reuse the decoder if the decoder support recycling.
    628  // Currently, only Android video decoder will return true.
    629  virtual bool SupportDecoderRecycling() const { return false; }
    630 
    631  // Recycling decoder is controlled by the pref and other different conditions
    632  // in our media pipeloine. True if the decoder should always be reused no
    633  // matter what situation is.
    634  virtual bool ShouldDecoderAlwaysBeRecycled() const { return false; }
    635 
    636  enum class ConversionRequired {
    637    kNeedNone = 0,
    638    kNeedAVCC = 1,
    639    kNeedAnnexB = 2,
    640    kNeedHVCC = 3,
    641  };
    642 
    643  // Indicates that the decoder requires a specific format.
    644  // The demuxed data will be converted accordingly before feeding it to
    645  // Decode().
    646  virtual ConversionRequired NeedsConversion() const {
    647    return ConversionRequired::kNeedNone;
    648  }
    649 
    650  // Properties specific to platform decoders. They can be consulted by the
    651  // client to improve playback smoothness. When not defined by the decoder, the
    652  // client can choose its own.
    653  // MaxNumVideoBuffers: some platform decoders have limited output buffers.
    654  // This specifies how many (output) video buffers can be held at most by the
    655  // client. Holding more will exhaust the deocder buffer pool and block further
    656  // decoding.
    657  // MinNumVideoBuffers: some platform decoders have decoding time longer than
    658  // frame duration. To avoid frame dropping in this case, the client queues
    659  // frames before starting to play. This value tells the client the least
    660  // amount of frames it should queue.
    661  // MaxNumCurrentImages: specifies how many (output) video buffers are current
    662  // (renderable) at a time.
    663  // The result is not accurated until Init() is resolved.
    664  MOZ_DEFINE_ENUM_CLASS_WITH_TOSTRING_AT_CLASS_SCOPE(PropertyName,
    665                                                     (MaxNumVideoBuffers,
    666                                                      MinNumVideoBuffers,
    667                                                      MaxNumCurrentImages));
    668  // Generic type for property values to avoid breaking existing client code in
    669  // the future.
    670  using PropertyValue = Variant<uint32_t>;
    671  virtual Maybe<PropertyValue> GetDecodeProperty(PropertyName aName) const {
    672    return Nothing();
    673  }
    674 };
    675 
    676 }  // namespace mozilla
    677 
    678 #endif