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