MediaChangeMonitor.h (6858B)
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_H264Converter_h 8 #define mozilla_H264Converter_h 9 10 #include "PDMFactory.h" 11 #include "PlatformDecoderModule.h" 12 #include "mozilla/Maybe.h" 13 #include "mozilla/UniquePtr.h" 14 15 namespace mozilla { 16 17 DDLoggedTypeDeclNameAndBase(MediaChangeMonitor, MediaDataDecoder); 18 19 // MediaChangeMonitor is a MediaDataDecoder wrapper used to ensure that 20 // only one type of content is fed to the underlying MediaDataDecoder. 21 // The MediaChangeMonitor allows playback of content where some out of band 22 // extra data (such as SPS NAL for H264 content) may not be provided in the 23 // init segment (e.g. AVC3 or Annex B) MediaChangeMonitor will monitor the 24 // input data, and will delay creation of the MediaDataDecoder until such out 25 // of band have been extracted should the underlying decoder required it. 26 27 class MediaChangeMonitor final 28 : public MediaDataDecoder, 29 public DecoderDoctorLifeLogger<MediaChangeMonitor> { 30 public: 31 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaChangeMonitor, final); 32 33 static RefPtr<PlatformDecoderModule::CreateDecoderPromise> Create( 34 PDMFactory* aPDMFactory, const CreateDecoderParams& aParams); 35 36 RefPtr<InitPromise> Init() override; 37 RefPtr<DecodePromise> Decode(MediaRawData* aSample) override; 38 RefPtr<DecodePromise> Drain() override; 39 RefPtr<FlushPromise> Flush() override; 40 RefPtr<ShutdownPromise> Shutdown() override; 41 bool IsHardwareAccelerated(nsACString& aFailureReason) const override; 42 nsCString GetDescriptionName() const override { 43 if (RefPtr<MediaDataDecoder> decoder = GetDecoderOnNonOwnerThread()) { 44 return decoder->GetDescriptionName(); 45 } 46 return "MediaChangeMonitor decoder (pending)"_ns; 47 } 48 nsCString GetProcessName() const override { 49 if (RefPtr<MediaDataDecoder> decoder = GetDecoderOnNonOwnerThread()) { 50 return decoder->GetProcessName(); 51 } 52 return "MediaChangeMonitor"_ns; 53 } 54 nsCString GetCodecName() const override { 55 if (RefPtr<MediaDataDecoder> decoder = GetDecoderOnNonOwnerThread()) { 56 return decoder->GetCodecName(); 57 } 58 return "MediaChangeMonitor"_ns; 59 } 60 void SetSeekThreshold(const media::TimeUnit& aTime) override; 61 bool SupportDecoderRecycling() const override { 62 if (RefPtr<MediaDataDecoder> decoder = GetDecoderOnNonOwnerThread()) { 63 return decoder->SupportDecoderRecycling(); 64 } 65 return false; 66 } 67 bool ShouldDecoderAlwaysBeRecycled() const override { 68 if (RefPtr<MediaDataDecoder> decoder = GetDecoderOnNonOwnerThread()) { 69 return decoder->ShouldDecoderAlwaysBeRecycled(); 70 } 71 return false; 72 } 73 74 ConversionRequired NeedsConversion() const override { 75 if (RefPtr<MediaDataDecoder> decoder = GetDecoderOnNonOwnerThread()) { 76 return decoder->NeedsConversion(); 77 } 78 // Default so no conversion is performed. 79 return ConversionRequired::kNeedNone; 80 } 81 82 Maybe<PropertyValue> GetDecodeProperty(PropertyName aName) const override { 83 if (RefPtr<MediaDataDecoder> decoder = GetDecoderOnNonOwnerThread()) { 84 return decoder->GetDecodeProperty(aName); 85 } 86 return MediaDataDecoder::GetDecodeProperty(aName); 87 } 88 89 class CodecChangeMonitor { 90 public: 91 virtual bool CanBeInstantiated() const = 0; 92 virtual MediaResult CheckForChange(MediaRawData* aSample) = 0; 93 virtual const TrackInfo& Config() const = 0; 94 virtual MediaResult PrepareSample( 95 MediaDataDecoder::ConversionRequired aConversion, MediaRawData* aSample, 96 bool aNeedKeyFrame) = 0; 97 virtual bool IsHardwareAccelerated(nsACString& aFailureReason) const { 98 return false; 99 } 100 virtual void Flush() {}; 101 virtual ~CodecChangeMonitor() = default; 102 }; 103 104 private: 105 MediaChangeMonitor(PDMFactory* aPDMFactory, 106 UniquePtr<CodecChangeMonitor>&& aCodecChangeMonitor, 107 MediaDataDecoder* aDecoder, 108 const CreateDecoderParams& aParams); 109 virtual ~MediaChangeMonitor(); 110 111 void AssertOnThread() const { 112 // mThread may not be set if Init hasn't been called first. 113 MOZ_ASSERT(!mThread || mThread->IsOnCurrentThread()); 114 } 115 116 // This is used for getting decoder debug info on other threads. Thread-safe. 117 MediaDataDecoder* GetDecoderOnNonOwnerThread() const; 118 119 bool CanRecycleDecoder() const; 120 121 typedef MozPromise<bool, MediaResult, true /* exclusive */> 122 CreateDecoderPromise; 123 // Will create the required MediaDataDecoder if need AVCC and we have a SPS 124 // NAL. Returns NS_ERROR_FAILURE if error is permanent and can't be recovered 125 // and will set mError accordingly. 126 RefPtr<CreateDecoderPromise> CreateDecoder(); 127 MediaResult CreateDecoderAndInit(MediaRawData* aSample); 128 MediaResult CheckForChange(MediaRawData* aSample); 129 130 void DecodeFirstSample(MediaRawData* aSample); 131 void DrainThenFlushDecoder(MediaRawData* aPendingSample); 132 void FlushThenShutdownDecoder(MediaRawData* aPendingSample); 133 RefPtr<ShutdownPromise> ShutdownDecoder(); 134 135 UniquePtr<CodecChangeMonitor> mChangeMonitor; 136 RefPtr<PDMFactory> mPDMFactory; 137 UniquePtr<TrackInfo> mCurrentConfig; 138 nsCOMPtr<nsISerialEventTarget> mThread; 139 RefPtr<MediaDataDecoder> mDecoder; 140 MozPromiseRequestHolder<CreateDecoderPromise> mDecoderRequest; 141 MozPromiseRequestHolder<InitPromise> mInitPromiseRequest; 142 MozPromiseHolder<InitPromise> mInitPromise; 143 MozPromiseRequestHolder<DecodePromise> mDecodePromiseRequest; 144 MozPromiseHolder<DecodePromise> mDecodePromise; 145 MozPromiseRequestHolder<FlushPromise> mFlushRequest; 146 MediaDataDecoder::DecodedData mPendingFrames; 147 MozPromiseRequestHolder<DecodePromise> mDrainRequest; 148 MozPromiseRequestHolder<ShutdownPromise> mShutdownRequest; 149 RefPtr<ShutdownPromise> mShutdownPromise; 150 MozPromiseHolder<FlushPromise> mFlushPromise; 151 152 bool mNeedKeyframe = true; 153 Maybe<bool> mCanRecycleDecoder; 154 Maybe<MediaDataDecoder::ConversionRequired> mConversionRequired; 155 bool mDecoderInitialized = false; 156 const CreateDecoderParamsForAsync mParams; 157 // Keep any seek threshold set for after decoder creation and initialization. 158 Maybe<media::TimeUnit> mPendingSeekThreshold; 159 160 // This lock is used for mDecoder specifically, but it doens't need to be used 161 // for every places accessing mDecoder which is mostly on the owner thread. 162 // However, when requesting decoder debug info, it can happen on other 163 // threads, so we need this mutex to avoid the data race of 164 // creating/destroying decoder and accessing decoder's debug info. 165 mutable Mutex MOZ_ANNOTATED mMutex{"MediaChangeMonitor"}; 166 }; 167 168 } // namespace mozilla 169 170 #endif // mozilla_H264Converter_h