RemoteMediaDataDecoder.cpp (8424B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 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 #include "RemoteMediaDataDecoder.h" 7 8 #include "RemoteDecoderChild.h" 9 #include "RemoteMediaManagerChild.h" 10 11 namespace mozilla { 12 13 #ifdef LOG 14 # undef LOG 15 #endif // LOG 16 #define LOG(arg, ...) \ 17 DDMOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, "::%s: " arg, __func__, \ 18 ##__VA_ARGS__) 19 20 RemoteMediaDataDecoder::RemoteMediaDataDecoder(RemoteDecoderChild* aChild) 21 : mChild(aChild), 22 mDescription("RemoteMediaDataDecoder"_ns), 23 mProcessName("unknown"_ns), 24 mCodecName("unknown"_ns), 25 mIsHardwareAccelerated(false), 26 mConversion(ConversionRequired::kNeedNone), 27 mShouldDecoderAlwaysBeRecycled(false) { 28 LOG("%p is created", this); 29 } 30 31 RemoteMediaDataDecoder::~RemoteMediaDataDecoder() { 32 if (mChild) { 33 // Shutdown didn't get called. This can happen if the creation of the 34 // decoder got interrupted while pending. 35 nsCOMPtr<nsISerialEventTarget> thread = 36 RemoteMediaManagerChild::GetManagerThread(); 37 MOZ_ASSERT(thread); 38 thread->Dispatch(NS_NewRunnableFunction( 39 "RemoteMediaDataDecoderShutdown", [child = std::move(mChild), thread] { 40 child->Shutdown()->Then( 41 thread, __func__, 42 [child](const ShutdownPromise::ResolveOrRejectValue& aValue) { 43 child->DestroyIPDL(); 44 }); 45 })); 46 } 47 LOG("%p is released", this); 48 } 49 50 RefPtr<MediaDataDecoder::InitPromise> RemoteMediaDataDecoder::Init() { 51 auto managerThread = RemoteMediaManagerChild::GetManagerThread(); 52 if (!managerThread) { 53 return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED, __func__); 54 } 55 RefPtr<RemoteMediaDataDecoder> self = this; 56 return InvokeAsync(managerThread, __func__, 57 [self]() { return self->mChild->Init(); }) 58 ->Then( 59 managerThread, __func__, 60 [self, this](TrackType aTrack) { 61 MutexAutoLock lock(mMutex); 62 // If shutdown has started in the meantime shutdown promise may 63 // be resloved before this task. In this case mChild will be null 64 // and the init promise has to be canceled. 65 if (!mChild) { 66 return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED, 67 __func__); 68 } 69 mDescription = mChild->GetDescriptionName(); 70 mProcessName = mChild->GetProcessName(); 71 mCodecName = mChild->GetCodecName(); 72 mIsHardwareAccelerated = 73 mChild->IsHardwareAccelerated(mHardwareAcceleratedReason); 74 mConversion = mChild->NeedsConversion(); 75 mDecodeProperties = mChild->GetDecodeProperties(); 76 mShouldDecoderAlwaysBeRecycled = 77 mChild->ShouldDecoderAlwaysBeRecycled(); 78 LOG("%p RemoteDecoderChild has been initialized - description: %s, " 79 "process: %s, codec: %s", 80 this, mDescription.get(), mProcessName.get(), mCodecName.get()); 81 return InitPromise::CreateAndResolve(aTrack, __func__); 82 }, 83 [self](const MediaResult& aError) { 84 return InitPromise::CreateAndReject(aError, __func__); 85 }); 86 } 87 88 RefPtr<MediaDataDecoder::DecodePromise> RemoteMediaDataDecoder::Decode( 89 MediaRawData* aSample) { 90 auto managerThread = RemoteMediaManagerChild::GetManagerThread(); 91 if (!managerThread) { 92 return DecodePromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED, 93 __func__); 94 } 95 RefPtr<RemoteMediaDataDecoder> self = this; 96 RefPtr<MediaRawData> sample = aSample; 97 return InvokeAsync(managerThread, __func__, [self, sample]() { 98 return self->mChild->Decode(nsTArray<RefPtr<MediaRawData>>{sample}); 99 }); 100 } 101 102 RefPtr<MediaDataDecoder::DecodePromise> RemoteMediaDataDecoder::DecodeBatch( 103 nsTArray<RefPtr<MediaRawData>>&& aSamples) { 104 auto managerThread = RemoteMediaManagerChild::GetManagerThread(); 105 if (!managerThread) { 106 return DecodePromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED, 107 __func__); 108 } 109 RefPtr<RemoteMediaDataDecoder> self = this; 110 return InvokeAsync(managerThread, __func__, 111 [self, samples = std::move(aSamples)]() { 112 return self->mChild->Decode(samples); 113 }); 114 } 115 116 RefPtr<MediaDataDecoder::FlushPromise> RemoteMediaDataDecoder::Flush() { 117 auto managerThread = RemoteMediaManagerChild::GetManagerThread(); 118 if (!managerThread) { 119 return FlushPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED, __func__); 120 } 121 RefPtr<RemoteMediaDataDecoder> self = this; 122 return InvokeAsync(managerThread, __func__, 123 [self]() { return self->mChild->Flush(); }); 124 } 125 126 RefPtr<MediaDataDecoder::DecodePromise> RemoteMediaDataDecoder::Drain() { 127 auto managerThread = RemoteMediaManagerChild::GetManagerThread(); 128 if (!managerThread) { 129 return DecodePromise::CreateAndReject(NS_ERROR_DOM_MEDIA_CANCELED, 130 __func__); 131 } 132 RefPtr<RemoteMediaDataDecoder> self = this; 133 return InvokeAsync(managerThread, __func__, 134 [self]() { return self->mChild->Drain(); }); 135 } 136 137 RefPtr<ShutdownPromise> RemoteMediaDataDecoder::Shutdown() { 138 auto managerThread = RemoteMediaManagerChild::GetManagerThread(); 139 if (!managerThread) { 140 return ShutdownPromise::CreateAndResolve(true, __func__); 141 } 142 RefPtr<RemoteMediaDataDecoder> self = this; 143 return InvokeAsync(managerThread, __func__, [self]() { 144 auto managerThread = RemoteMediaManagerChild::GetManagerThread(); 145 if (!managerThread) { 146 return ShutdownPromise::CreateAndResolve(true, __func__); 147 } 148 149 RefPtr<ShutdownPromise> p = self->mChild->Shutdown(); 150 151 // We're about to be destroyed and drop our ref to 152 // *DecoderChild. Make sure we put a ref into the 153 // task queue for the *DecoderChild thread to keep 154 // it alive until we send the delete message. 155 p->Then(managerThread, __func__, 156 [child = std::move(self->mChild)]( 157 const ShutdownPromise::ResolveOrRejectValue& aValue) { 158 MOZ_ASSERT(aValue.IsResolve()); 159 child->DestroyIPDL(); 160 return ShutdownPromise::CreateAndResolveOrReject(aValue, 161 __func__); 162 }); 163 return p; 164 }); 165 } 166 167 bool RemoteMediaDataDecoder::IsHardwareAccelerated( 168 nsACString& aFailureReason) const { 169 MutexAutoLock lock(mMutex); 170 aFailureReason = mHardwareAcceleratedReason; 171 return mIsHardwareAccelerated; 172 } 173 174 void RemoteMediaDataDecoder::SetSeekThreshold(const media::TimeUnit& aTime) { 175 auto managerThread = RemoteMediaManagerChild::GetManagerThread(); 176 if (!managerThread) { 177 return; 178 } 179 RefPtr<RemoteMediaDataDecoder> self = this; 180 media::TimeUnit time = aTime; 181 managerThread->Dispatch( 182 NS_NewRunnableFunction("dom::RemoteMediaDataDecoder::SetSeekThreshold", 183 [=]() { 184 MOZ_ASSERT(self->mChild); 185 self->mChild->SetSeekThreshold(time); 186 }), 187 NS_DISPATCH_NORMAL); 188 } 189 190 MediaDataDecoder::ConversionRequired RemoteMediaDataDecoder::NeedsConversion() 191 const { 192 MutexAutoLock lock(mMutex); 193 return mConversion; 194 } 195 196 Maybe<MediaDataDecoder::PropertyValue> 197 RemoteMediaDataDecoder::GetDecodeProperty( 198 MediaDataDecoder::PropertyName aName) const { 199 MutexAutoLock lock(mMutex); 200 return mDecodeProperties[aName]; 201 } 202 203 nsCString RemoteMediaDataDecoder::GetDescriptionName() const { 204 MutexAutoLock lock(mMutex); 205 return mDescription; 206 } 207 208 nsCString RemoteMediaDataDecoder::GetProcessName() const { 209 MutexAutoLock lock(mMutex); 210 return mProcessName; 211 } 212 213 nsCString RemoteMediaDataDecoder::GetCodecName() const { 214 MutexAutoLock lock(mMutex); 215 return mCodecName; 216 } 217 218 bool RemoteMediaDataDecoder::ShouldDecoderAlwaysBeRecycled() const { 219 MutexAutoLock lock(mMutex); 220 return mShouldDecoderAlwaysBeRecycled; 221 } 222 223 #undef LOG 224 225 } // namespace mozilla