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