/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim:set ts=2 sw=2 sts=2 et cindent: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_AppleVTDecoder_h #define mozilla_AppleVTDecoder_h #include // For CFDictionaryRef #include // For CMVideoFormatDescriptionRef #include // For VTDecompressionSessionRef #include "AppleDecoderModule.h" #include "PerformanceRecorder.h" #include "PlatformDecoderModule.h" #include "ReorderQueue.h" #include "TimeUnits.h" #include "mozilla/Atomics.h" #include "mozilla/gfx/Types.h" #include "mozilla/ProfilerUtils.h" namespace mozilla { DDLoggedTypeDeclNameAndBase(AppleVTDecoder, MediaDataDecoder); class AppleVTDecoder final : public MediaDataDecoder, public DecoderDoctorLifeLogger { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AppleVTDecoder, final); AppleVTDecoder(const VideoInfo& aConfig, layers::ImageContainer* aImageContainer, CreateDecoderParams::OptionSet aOptions, layers::KnowsCompositor* aKnowsCompositor, Maybe aTrackingId); class AppleFrameRef { public: media::TimeUnit decode_timestamp; media::TimeUnit composition_timestamp; media::TimeUnit duration; int64_t byte_offset; bool is_sync_point; explicit AppleFrameRef(const MediaRawData& aSample) : decode_timestamp(aSample.mTimecode), composition_timestamp(aSample.mTime), duration(aSample.mDuration), byte_offset(aSample.mOffset), is_sync_point(aSample.mKeyframe) {} }; RefPtr Init() override; RefPtr Decode(MediaRawData* aSample) override; RefPtr Drain() override; RefPtr Flush() override; RefPtr Shutdown() override; void SetSeekThreshold(const media::TimeUnit& aTime) override; bool IsHardwareAccelerated(nsACString& aFailureReason) const override { return mIsHardwareAccelerated; } nsCString GetDescriptionName() const override { return mIsHardwareAccelerated ? "apple hardware VT decoder"_ns : "apple software VT decoder"_ns; } nsCString GetCodecName() const override; ConversionRequired NeedsConversion() const override { return ConversionRequired::kNeedAVCC; } // Access from the taskqueue and the decoder's thread. // OutputFrame is thread-safe. void OutputFrame(CVPixelBufferRef aImage, AppleFrameRef aFrameRef); void OnDecodeError(OSStatus aError); private: friend class AppleDecoderModule; // To access InitializeSession. virtual ~AppleVTDecoder(); RefPtr ProcessFlush(); RefPtr ProcessDrain(); void ProcessShutdown(); void ProcessDecode(MediaRawData* aSample); void MaybeResolveBufferedFrames(); void MaybeRegisterCallbackThread(); void AssertOnTaskQueue() { MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); } AppleFrameRef* CreateAppleFrameRef(const MediaRawData* aSample); CFDictionaryRef CreateOutputConfiguration(); const RefPtr mExtraData; const uint32_t mPictureWidth; const uint32_t mPictureHeight; const uint32_t mDisplayWidth; const uint32_t mDisplayHeight; const gfx::YUVColorSpace mColorSpace; const gfx::ColorSpace2 mColorPrimaries; const gfx::TransferFunction mTransferFunction; const gfx::ColorRange mColorRange; const gfx::ColorDepth mColorDepth; // Method to set up the decompression session. MediaResult InitializeSession(); nsresult WaitForAsynchronousFrames(); CFDictionaryRef CreateDecoderSpecification(); CFDictionaryRef CreateDecoderExtensions(); enum class StreamType { Unknown, H264, VP9 }; const StreamType mStreamType; const RefPtr mTaskQueue; const uint32_t mMaxRefFrames; const RefPtr mImageContainer; const RefPtr mKnowsCompositor; const bool mUseSoftwareImages; const Maybe mTrackingId; // Set on reader/decode thread calling Flush() to indicate that output is // not required and so input samples on mTaskQueue need not be processed. Atomic mIsFlushing; std::atomic mCallbackThreadId; // Protects mReorderQueue and mPromise. Monitor mMonitor MOZ_UNANNOTATED; ReorderQueue mReorderQueue; MozMonitoredPromiseHolder mPromise; // Decoded frame will be dropped if its pts is smaller than this // value. It shold be initialized before Input() or after Flush(). So it is // safe to access it in OutputFrame without protecting. Maybe mSeekTargetThreshold; CMVideoFormatDescriptionRef mFormat; VTDecompressionSessionRef mSession; Atomic mIsHardwareAccelerated; PerformanceRecorderMulti mPerformanceRecorder; }; } // namespace mozilla #endif // mozilla_AppleVTDecoder_h