tor-browser

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

WMFMediaDataDecoder.h (5962B)


      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(WMFMediaDataDecoder_h_)
      8 #  define WMFMediaDataDecoder_h_
      9 
     10 #  include <set>
     11 
     12 #  include "MFTDecoder.h"
     13 #  include "PlatformDecoderModule.h"
     14 #  include "WMF.h"
     15 #  include "mozilla/RefPtr.h"
     16 
     17 namespace mozilla {
     18 
     19 // Encapsulates the initialization of the MFTDecoder appropriate for decoding
     20 // a given stream, and the process of converting the IMFSample produced
     21 // by the MFT into a MediaData object.
     22 class MFTManager {
     23 public:
     24  virtual ~MFTManager() {}
     25 
     26  // Submit a compressed sample for decoding.
     27  // This should forward to the MFTDecoder after performing
     28  // any required sample formatting.
     29  virtual HRESULT Input(MediaRawData* aSample) = 0;
     30 
     31  // Produces decoded output, if possible. Blocks until output can be produced,
     32  // or until no more is able to be produced.
     33  // Returns S_OK on success, or MF_E_TRANSFORM_NEED_MORE_INPUT if there's not
     34  // enough data to produce more output. If this returns a failure code other
     35  // than MF_E_TRANSFORM_NEED_MORE_INPUT, an error will be reported to the
     36  // MP4Reader.
     37  virtual HRESULT Output(int64_t aStreamOffset, RefPtr<MediaData>& aOutput) = 0;
     38 
     39  virtual void Flush() {
     40    mDecoder->Flush();
     41    mSeekTargetThreshold.reset();
     42  }
     43 
     44  void Drain() {
     45    if (FAILED(mDecoder->SendMFTMessage(MFT_MESSAGE_COMMAND_DRAIN, 0))) {
     46      NS_WARNING("Failed to send DRAIN command to MFT");
     47    }
     48  }
     49 
     50  // Destroys all resources.
     51  virtual void Shutdown() = 0;
     52 
     53  virtual bool IsHardwareAccelerated(nsACString& aFailureReason) const {
     54    return false;
     55  }
     56 
     57  virtual TrackInfo::TrackType GetType() = 0;
     58 
     59  virtual nsCString GetDescriptionName() const = 0;
     60 
     61  virtual nsCString GetCodecName() const = 0;
     62 
     63  virtual void SetSeekThreshold(const media::TimeUnit& aTime) {
     64    if (aTime.IsValid()) {
     65      mSeekTargetThreshold = Some(aTime);
     66    } else {
     67      mSeekTargetThreshold.reset();
     68    }
     69  }
     70 
     71  virtual bool HasSeekThreshold() const {
     72    return mSeekTargetThreshold.isSome();
     73  }
     74 
     75  virtual MediaDataDecoder::ConversionRequired NeedsConversion() const {
     76    return MediaDataDecoder::ConversionRequired::kNeedNone;
     77  }
     78 
     79  virtual bool UseZeroCopyVideoFrame() const { return false; }
     80 
     81 protected:
     82  // IMFTransform wrapper that performs the decoding.
     83  RefPtr<MFTDecoder> mDecoder;
     84 
     85  Maybe<media::TimeUnit> mSeekTargetThreshold;
     86 };
     87 
     88 DDLoggedTypeDeclNameAndBase(WMFMediaDataDecoder, MediaDataDecoder);
     89 
     90 // Decodes audio and video using Windows Media Foundation. Samples are decoded
     91 // using the MFTDecoder created by the MFTManager. This class implements
     92 // the higher-level logic that drives mapping the MFT to the async
     93 // MediaDataDecoder interface. The specifics of decoding the exact stream
     94 // type are handled by MFTManager and the MFTDecoder it creates.
     95 class WMFMediaDataDecoder final
     96    : public MediaDataDecoder,
     97      public DecoderDoctorLifeLogger<WMFMediaDataDecoder> {
     98 public:
     99  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WMFMediaDataDecoder, final);
    100 
    101  explicit WMFMediaDataDecoder(MFTManager* aOutputSource);
    102 
    103  RefPtr<MediaDataDecoder::InitPromise> Init() override;
    104 
    105  RefPtr<DecodePromise> Decode(MediaRawData* aSample) override;
    106 
    107  RefPtr<DecodePromise> Drain() override;
    108 
    109  RefPtr<FlushPromise> Flush() override;
    110 
    111  RefPtr<ShutdownPromise> Shutdown() override;
    112 
    113  bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
    114 
    115  nsCString GetDescriptionName() const override {
    116    return mMFTManager ? mMFTManager->GetDescriptionName() : "unknown"_ns;
    117  }
    118 
    119  nsCString GetCodecName() const override {
    120    return mMFTManager ? mMFTManager->GetCodecName() : ""_ns;
    121  }
    122 
    123  ConversionRequired NeedsConversion() const override {
    124    MOZ_ASSERT(mMFTManager);
    125    return mMFTManager->NeedsConversion();
    126  }
    127 
    128  virtual void SetSeekThreshold(const media::TimeUnit& aTime) override;
    129 
    130 private:
    131  ~WMFMediaDataDecoder();
    132 
    133  RefPtr<DecodePromise> ProcessError(HRESULT aError, const char* aReason);
    134 
    135  // Called on the task queue. Inserts the sample into the decoder, and
    136  // extracts output if available.
    137  RefPtr<DecodePromise> ProcessDecode(MediaRawData* aSample);
    138 
    139  // Called on the task queue. Extracts output if available, and delivers
    140  // it to the reader. Called after ProcessDecode() and ProcessDrain().
    141  HRESULT ProcessOutput(DecodedData& aResults);
    142 
    143  // Called on the task queue. Orders the MFT to flush.  There is no output to
    144  // extract.
    145  RefPtr<FlushPromise> ProcessFlush();
    146 
    147  // Called on the task queue. Orders the MFT to drain, and then extracts
    148  // all available output.
    149  RefPtr<DecodePromise> ProcessDrain();
    150 
    151  // Checks if `aOutput` should be discarded (guarded against) because its a
    152  // potentially invalid output from the decoder. This is done because the
    153  // Windows decoder appears to produce invalid outputs under certain
    154  // conditions.
    155  bool ShouldGuardAgaintIncorrectFirstSample(MediaData* aOutput) const;
    156 
    157  const RefPtr<TaskQueue> mTaskQueue;
    158 
    159  UniquePtr<MFTManager> mMFTManager;
    160 
    161  // The last offset into the media resource that was passed into Input().
    162  // This is used to approximate the decoder's position in the media resource.
    163  int64_t mLastStreamOffset;
    164  Maybe<media::TimeUnit> mLastTime;
    165  media::TimeUnit mLastDuration;
    166  // Before we get the first sample, this records the times of all samples we
    167  // send to the decoder which is used to validate if the first sample is valid.
    168  std::set<int64_t> mInputTimesSet;
    169  int64_t mSamplesCount = 0;
    170  int64_t mOutputsCount = 0;
    171 
    172  bool mIsShutDown = false;
    173 
    174  enum class DrainStatus {
    175    DRAINED,
    176    DRAINABLE,
    177    DRAINING,
    178  };
    179  DrainStatus mDrainStatus = DrainStatus::DRAINED;
    180 };
    181 
    182 }  // namespace mozilla
    183 
    184 #endif  // WMFMediaDataDecoder_h_