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 "PlatformDecoderModule.h" 16 #include "ReorderQueue.h" 17 #include "TimeUnits.h" 18 #include "mozilla/Atomics.h" 19 #include "mozilla/gfx/Types.h" 20 21 namespace mozilla { 22 23 DDLoggedTypeDeclNameAndBase(AppleVTDecoder, MediaDataDecoder); 24 25 class AppleVTDecoder : public MediaDataDecoder, 26 public DecoderDoctorLifeLogger<AppleVTDecoder> { 27 public: 28 AppleVTDecoder(const VideoInfo& aConfig, 29 layers::ImageContainer* aImageContainer, 30 CreateDecoderParams::OptionSet aOptions, 31 layers::KnowsCompositor* aKnowsCompositor); 32 33 class AppleFrameRef { 34 public: 35 media::TimeUnit decode_timestamp; 36 media::TimeUnit composition_timestamp; 37 media::TimeUnit duration; 38 int64_t byte_offset; 39 bool is_sync_point; 40 AppleFrameRef(const MediaRawData & aSample)41 explicit AppleFrameRef(const MediaRawData& aSample) 42 : decode_timestamp(aSample.mTimecode), 43 composition_timestamp(aSample.mTime), 44 duration(aSample.mDuration), 45 byte_offset(aSample.mOffset), 46 is_sync_point(aSample.mKeyframe) {} 47 }; 48 49 RefPtr<InitPromise> Init() override; 50 RefPtr<DecodePromise> Decode(MediaRawData* aSample) override; 51 RefPtr<DecodePromise> Drain() override; 52 RefPtr<FlushPromise> Flush() override; 53 RefPtr<ShutdownPromise> Shutdown() override; 54 void SetSeekThreshold(const media::TimeUnit& aTime) override; 55 IsHardwareAccelerated(nsACString & aFailureReason)56 bool IsHardwareAccelerated(nsACString& aFailureReason) const override { 57 return mIsHardwareAccelerated; 58 } 59 GetDescriptionName()60 nsCString GetDescriptionName() const override { 61 return mIsHardwareAccelerated ? "apple hardware VT decoder"_ns 62 : "apple software VT decoder"_ns; 63 } 64 NeedsConversion()65 ConversionRequired NeedsConversion() const override { 66 return ConversionRequired::kNeedAVCC; 67 } 68 69 // Access from the taskqueue and the decoder's thread. 70 // OutputFrame is thread-safe. 71 void OutputFrame(CVPixelBufferRef aImage, AppleFrameRef aFrameRef); 72 void OnDecodeError(OSStatus aError); 73 74 private: 75 friend class AppleDecoderModule; // To access InitializeSession. 76 virtual ~AppleVTDecoder(); 77 RefPtr<FlushPromise> ProcessFlush(); 78 RefPtr<DecodePromise> ProcessDrain(); 79 void ProcessShutdown(); 80 void ProcessDecode(MediaRawData* aSample); 81 void MaybeResolveBufferedFrames(); 82 AssertOnTaskQueue()83 void AssertOnTaskQueue() { MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); } 84 85 AppleFrameRef* CreateAppleFrameRef(const MediaRawData* aSample); 86 CFDictionaryRef CreateOutputConfiguration(); 87 88 const RefPtr<MediaByteBuffer> mExtraData; 89 const uint32_t mPictureWidth; 90 const uint32_t mPictureHeight; 91 const uint32_t mDisplayWidth; 92 const uint32_t mDisplayHeight; 93 const gfx::YUVColorSpace mColorSpace; 94 const gfx::ColorRange mColorRange; 95 96 // Method to set up the decompression session. 97 MediaResult InitializeSession(); 98 nsresult WaitForAsynchronousFrames(); 99 CFDictionaryRef CreateDecoderSpecification(); 100 CFDictionaryRef CreateDecoderExtensions(); 101 102 enum class StreamType { Unknown, H264, VP9 }; 103 const StreamType mStreamType; 104 const RefPtr<TaskQueue> mTaskQueue; 105 const uint32_t mMaxRefFrames; 106 const RefPtr<layers::ImageContainer> mImageContainer; 107 const RefPtr<layers::KnowsCompositor> mKnowsCompositor; 108 const bool mUseSoftwareImages; 109 110 // Set on reader/decode thread calling Flush() to indicate that output is 111 // not required and so input samples on mTaskQueue need not be processed. 112 Atomic<bool> mIsFlushing; 113 // Protects mReorderQueue and mPromise. 114 Monitor mMonitor; 115 ReorderQueue mReorderQueue; 116 MozMonitoredPromiseHolder<DecodePromise> mPromise; 117 118 // Decoded frame will be dropped if its pts is smaller than this 119 // value. It shold be initialized before Input() or after Flush(). So it is 120 // safe to access it in OutputFrame without protecting. 121 Maybe<media::TimeUnit> mSeekTargetThreshold; 122 123 CMVideoFormatDescriptionRef mFormat; 124 VTDecompressionSessionRef mSession; 125 Atomic<bool> mIsHardwareAccelerated; 126 }; 127 128 } // namespace mozilla 129 130 #endif // mozilla_AppleVTDecoder_h 131