tor-browser

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

AppleVTDecoder.h (6214B)


      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_AppleVTDecoder_h
      8 #define mozilla_AppleVTDecoder_h
      9 
     10 #include <CoreFoundation/CFDictionary.h>  // For CFDictionaryRef
     11 #include <CoreMedia/CoreMedia.h>          // For CMVideoFormatDescriptionRef
     12 #include <VideoToolbox/VideoToolbox.h>    // For VTDecompressionSessionRef
     13 
     14 #include "AppleDecoderModule.h"
     15 #include "PerformanceRecorder.h"
     16 #include "PlatformDecoderModule.h"
     17 #include "ReorderQueue.h"
     18 #include "TimeUnits.h"
     19 #include "apple/AppleUtils.h"
     20 #include "mozilla/Atomics.h"
     21 #include "mozilla/DefineEnum.h"
     22 #include "mozilla/ProfilerUtils.h"
     23 #include "mozilla/gfx/Types.h"
     24 
     25 namespace mozilla {
     26 
     27 DDLoggedTypeDeclNameAndBase(AppleVTDecoder, MediaDataDecoder);
     28 
     29 class AppleVTDecoder final : public MediaDataDecoder,
     30                             public DecoderDoctorLifeLogger<AppleVTDecoder> {
     31 public:
     32  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AppleVTDecoder, final);
     33 
     34  AppleVTDecoder(const VideoInfo& aConfig,
     35                 layers::ImageContainer* aImageContainer,
     36                 const CreateDecoderParams::OptionSet& aOptions,
     37                 layers::KnowsCompositor* aKnowsCompositor,
     38                 Maybe<TrackingId> aTrackingId);
     39 
     40  class AppleFrameRef {
     41   public:
     42    media::TimeUnit decode_timestamp;
     43    media::TimeUnit composition_timestamp;
     44    media::TimeUnit duration;
     45    int64_t byte_offset;
     46    bool is_sync_point;
     47 
     48    explicit AppleFrameRef(const MediaRawData& aSample)
     49        : decode_timestamp(aSample.mTimecode),
     50          composition_timestamp(aSample.mTime),
     51          duration(aSample.mDuration),
     52          byte_offset(aSample.mOffset),
     53          is_sync_point(aSample.mKeyframe) {}
     54  };
     55 
     56  RefPtr<InitPromise> Init() override;
     57  RefPtr<DecodePromise> Decode(MediaRawData* aSample) override;
     58  RefPtr<DecodePromise> Drain() override;
     59  RefPtr<FlushPromise> Flush() override;
     60  RefPtr<ShutdownPromise> Shutdown() override;
     61  void SetSeekThreshold(const media::TimeUnit& aTime) override;
     62 
     63  bool IsHardwareAccelerated(nsACString& aFailureReason) const override {
     64    return mIsHardwareAccelerated;
     65  }
     66 
     67  nsCString GetDescriptionName() const override {
     68    return mIsHardwareAccelerated ? "apple hardware VT decoder"_ns
     69                                  : "apple software VT decoder"_ns;
     70  }
     71 
     72  nsCString GetCodecName() const override;
     73 
     74  ConversionRequired NeedsConversion() const override {
     75    if (mStreamType == StreamType::H264) {
     76      return ConversionRequired::kNeedAVCC;
     77    }
     78    if (mStreamType == StreamType::HEVC) {
     79      return ConversionRequired::kNeedHVCC;
     80    }
     81    return ConversionRequired::kNeedNone;
     82  }
     83 
     84  Maybe<PropertyValue> GetDecodeProperty(PropertyName aName) const override {
     85    // Some Intel GPU has long decoding time and needs more frames queued to
     86    // play smoothly. See bug 1230641.
     87    static constexpr uint32_t kMinNumOutputBuffers = 10;
     88    switch (aName) {
     89      case PropertyName::MinNumVideoBuffers:
     90        return Some(PropertyValue(kMinNumOutputBuffers));
     91      default:
     92        return MediaDataDecoder::GetDecodeProperty(aName);
     93    }
     94  }
     95 
     96  // Access from the taskqueue and the decoder's thread.
     97  // OutputFrame is thread-safe.
     98  void OutputFrame(CVPixelBufferRef aImage, AppleFrameRef aFrameRef);
     99  void OnDecodeError(OSStatus aError);
    100 
    101 private:
    102  friend class AppleDecoderModule;  // To access InitializeSession.
    103  virtual ~AppleVTDecoder();
    104  RefPtr<FlushPromise> ProcessFlush();
    105  RefPtr<DecodePromise> ProcessDrain();
    106  void ProcessShutdown();
    107  void ProcessDecode(MediaRawData* aSample);
    108  void MaybeResolveBufferedFrames();
    109 
    110  void MaybeRegisterCallbackThread();
    111 
    112  void AssertOnTaskQueue() { MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); }
    113 
    114  AppleFrameRef* CreateAppleFrameRef(const MediaRawData* aSample);
    115  CFDictionaryRef CreateOutputConfiguration();
    116 
    117  const RefPtr<MediaByteBuffer> mExtraData;
    118  const uint32_t mPictureWidth;
    119  const uint32_t mPictureHeight;
    120  const uint32_t mDisplayWidth;
    121  const uint32_t mDisplayHeight;
    122  const gfx::YUVColorSpace mColorSpace;
    123  const gfx::ColorSpace2 mColorPrimaries;
    124  const gfx::TransferFunction mTransferFunction;
    125  const gfx::ColorRange mColorRange;
    126  const gfx::ColorDepth mColorDepth;
    127 
    128  // Method to set up the decompression session.
    129  MediaResult InitializeSession();
    130  nsresult WaitForAsynchronousFrames();
    131  CFDictionaryRef CreateDecoderSpecification();
    132  CFDictionaryRef CreateDecoderExtensions();
    133 
    134  MOZ_DEFINE_ENUM_CLASS_WITH_TOSTRING_AT_CLASS_SCOPE(StreamType,
    135                                                     (Unknown, H264, VP9, AV1,
    136                                                      HEVC));
    137 
    138  StreamType GetStreamType(const nsCString& aMimeType) const;
    139  uint32_t GetMaxRefFrames(bool aIsLowLatency) const;
    140 
    141  const StreamType mStreamType;
    142  const RefPtr<TaskQueue> mTaskQueue;
    143  const uint32_t mMaxRefFrames;
    144  const RefPtr<layers::ImageContainer> mImageContainer;
    145  const RefPtr<layers::KnowsCompositor> mKnowsCompositor;
    146  const bool mUseSoftwareImages;
    147  const Maybe<TrackingId> mTrackingId;
    148 
    149  // Set on reader/decode thread calling Flush() to indicate that output is
    150  // not required and so input samples on mTaskQueue need not be processed.
    151  Atomic<bool> mIsFlushing;
    152  std::atomic<ProfilerThreadId> mCallbackThreadId;
    153  // Protects mReorderQueue and mPromise.
    154  Monitor mMonitor MOZ_UNANNOTATED;
    155  ReorderQueue mReorderQueue;
    156  MozMonitoredPromiseHolder<DecodePromise> mPromise;
    157 
    158  // Decoded frame will be dropped if its pts is smaller than this
    159  // value. It shold be initialized before Input() or after Flush(). So it is
    160  // safe to access it in OutputFrame without protecting.
    161  Maybe<media::TimeUnit> mSeekTargetThreshold;
    162 
    163  AutoCFTypeRef<CMVideoFormatDescriptionRef> mFormat;
    164  AutoCFTypeRef<VTDecompressionSessionRef> mSession;
    165  Atomic<bool> mIsHardwareAccelerated;
    166  PerformanceRecorderMulti<DecodeStage> mPerformanceRecorder;
    167 };
    168 
    169 }  // namespace mozilla
    170 
    171 #endif  // mozilla_AppleVTDecoder_h