ReaderProxy.cpp (8375B)
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 7 #include "ReaderProxy.h" 8 9 #include "MediaFormatReader.h" 10 #include "TimeUnits.h" 11 #include "mozilla/CDMProxy.h" 12 #include "mozilla/MozPromise.h" 13 14 namespace mozilla { 15 16 ReaderProxy::ReaderProxy(AbstractThread* aOwnerThread, 17 MediaFormatReader* aReader) 18 : mOwnerThread(aOwnerThread), 19 mReader(aReader), 20 mWatchManager(this, aReader->OwnerThread()), 21 mDuration(aReader->OwnerThread(), media::NullableTimeUnit(), 22 "ReaderProxy::mDuration (Mirror)") { 23 // Must support either heuristic buffering or WaitForData(). 24 MOZ_ASSERT(mReader->UseBufferingHeuristics() || 25 mReader->IsWaitForDataSupported()); 26 } 27 28 ReaderProxy::~ReaderProxy() = default; 29 30 media::TimeUnit ReaderProxy::StartTime() const { 31 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); 32 return mStartTime.ref(); 33 } 34 35 RefPtr<ReaderProxy::MetadataPromise> ReaderProxy::ReadMetadata() { 36 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); 37 MOZ_ASSERT(!mShutdown); 38 return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__, 39 &MediaFormatReader::AsyncReadMetadata) 40 ->Then(mOwnerThread, __func__, this, &ReaderProxy::OnMetadataRead, 41 &ReaderProxy::OnMetadataNotRead); 42 } 43 44 RefPtr<ReaderProxy::AudioDataPromise> ReaderProxy::OnAudioDataRequestCompleted( 45 RefPtr<AudioData> aAudio) { 46 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); 47 48 if (aAudio->AdjustForStartTime(StartTime())) { 49 return AudioDataPromise::CreateAndResolve(aAudio.forget(), __func__); 50 } 51 return AudioDataPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_OVERFLOW_ERR, 52 __func__); 53 } 54 55 RefPtr<ReaderProxy::AudioDataPromise> ReaderProxy::OnAudioDataRequestFailed( 56 const MediaResult& aError) { 57 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); 58 return AudioDataPromise::CreateAndReject(aError, __func__); 59 } 60 61 RefPtr<ReaderProxy::AudioDataPromise> ReaderProxy::RequestAudioData() { 62 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); 63 MOZ_ASSERT(!mShutdown); 64 65 return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__, 66 &MediaFormatReader::RequestAudioData) 67 ->Then(mOwnerThread, __func__, this, 68 &ReaderProxy::OnAudioDataRequestCompleted, 69 &ReaderProxy::OnAudioDataRequestFailed); 70 } 71 72 RefPtr<ReaderProxy::VideoDataPromise> ReaderProxy::RequestVideoData( 73 const media::TimeUnit& aTimeThreshold, bool aRequestNextVideoKeyFrame) { 74 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); 75 MOZ_ASSERT(!mShutdown); 76 77 const auto threshold = aTimeThreshold > media::TimeUnit::Zero() 78 ? aTimeThreshold + StartTime() 79 : aTimeThreshold; 80 81 auto startTime = StartTime(); 82 return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__, 83 &MediaFormatReader::RequestVideoData, threshold, 84 aRequestNextVideoKeyFrame) 85 ->Then( 86 mOwnerThread, __func__, 87 [startTime](RefPtr<VideoData> aVideo) { 88 return aVideo->AdjustForStartTime(startTime) 89 ? VideoDataPromise::CreateAndResolve(aVideo.forget(), 90 __func__) 91 : VideoDataPromise::CreateAndReject( 92 NS_ERROR_DOM_MEDIA_OVERFLOW_ERR, __func__); 93 }, 94 [](const MediaResult& aError) { 95 return VideoDataPromise::CreateAndReject(aError, __func__); 96 }); 97 } 98 99 RefPtr<ReaderProxy::SeekPromise> ReaderProxy::Seek(const SeekTarget& aTarget) { 100 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); 101 return SeekInternal(aTarget); 102 } 103 104 RefPtr<ReaderProxy::SeekPromise> ReaderProxy::SeekInternal( 105 const SeekTarget& aTarget) { 106 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); 107 SeekTarget adjustedTarget = aTarget; 108 adjustedTarget.SetTime(adjustedTarget.GetTime() + StartTime()); 109 return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__, 110 &MediaFormatReader::Seek, std::move(adjustedTarget)); 111 } 112 113 RefPtr<ReaderProxy::WaitForDataPromise> ReaderProxy::WaitForData( 114 MediaData::Type aType) { 115 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); 116 MOZ_ASSERT(mReader->IsWaitForDataSupported()); 117 return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__, 118 &MediaFormatReader::WaitForData, aType); 119 } 120 121 void ReaderProxy::ReleaseResources() { 122 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); 123 nsCOMPtr<nsIRunnable> r = 124 NewRunnableMethod("MediaFormatReader::ReleaseResources", mReader, 125 &MediaFormatReader::ReleaseResources); 126 nsresult rv = mReader->OwnerThread()->Dispatch(r.forget()); 127 MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); 128 (void)rv; 129 } 130 131 void ReaderProxy::ResetDecode(TrackSet aTracks) { 132 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); 133 nsCOMPtr<nsIRunnable> r = 134 NewRunnableMethod<TrackSet>("MediaFormatReader::ResetDecode", mReader, 135 &MediaFormatReader::ResetDecode, aTracks); 136 nsresult rv = mReader->OwnerThread()->Dispatch(r.forget()); 137 MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); 138 (void)rv; 139 } 140 141 RefPtr<ShutdownPromise> ReaderProxy::Shutdown() { 142 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); 143 mShutdown = true; 144 RefPtr<ReaderProxy> self = this; 145 return InvokeAsync(mReader->OwnerThread(), __func__, [self]() { 146 self->mDuration.DisconnectIfConnected(); 147 self->mWatchManager.Shutdown(); 148 return self->mReader->Shutdown(); 149 }); 150 } 151 152 RefPtr<ReaderProxy::MetadataPromise> ReaderProxy::OnMetadataRead( 153 MetadataHolder&& aMetadata) { 154 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); 155 if (mShutdown) { 156 return MetadataPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_ABORT_ERR, 157 __func__); 158 } 159 160 if (mStartTime.isNothing()) { 161 mStartTime.emplace(aMetadata.mInfo->mStartTime); 162 } 163 return MetadataPromise::CreateAndResolve(std::move(aMetadata), __func__); 164 } 165 166 RefPtr<ReaderProxy::MetadataPromise> ReaderProxy::OnMetadataNotRead( 167 const MediaResult& aError) { 168 return MetadataPromise::CreateAndReject(aError, __func__); 169 } 170 171 void ReaderProxy::SetVideoBlankDecode(bool aIsBlankDecode) { 172 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); 173 nsCOMPtr<nsIRunnable> r = NewRunnableMethod<bool>( 174 "MediaFormatReader::SetVideoNullDecode", mReader, 175 &MediaFormatReader::SetVideoNullDecode, aIsBlankDecode); 176 nsresult rv = mReader->OwnerThread()->Dispatch(r.forget()); 177 MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); 178 (void)rv; 179 } 180 181 void ReaderProxy::UpdateDuration() { 182 MOZ_ASSERT(mReader->OwnerThread()->IsCurrentThreadIn()); 183 mReader->UpdateDuration(mDuration.Ref().ref()); 184 } 185 186 void ReaderProxy::SetCanonicalDuration( 187 Canonical<media::NullableTimeUnit>& aCanonical) { 188 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); 189 nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( 190 "ReaderProxy::SetCanonicalDuration", [this, self = RefPtr(this)]() { 191 mWatchManager.Watch(mDuration, &ReaderProxy::UpdateDuration); 192 }); 193 mReader->OwnerThread()->DispatchStateChange(r.forget()); 194 aCanonical.ConnectMirror(&mDuration); 195 } 196 197 void ReaderProxy::UpdateMediaEngineId(uint64_t aMediaEngineId) { 198 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); 199 nsCOMPtr<nsIRunnable> r = NewRunnableMethod<uint64_t>( 200 "MediaFormatReader::UpdateMediaEngineId", mReader, 201 &MediaFormatReader::UpdateMediaEngineId, aMediaEngineId); 202 nsresult rv = mReader->OwnerThread()->Dispatch(r.forget()); 203 MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); 204 (void)rv; 205 } 206 207 RefPtr<SetCDMPromise> ReaderProxy::SetCDMProxy(CDMProxy* aProxy) { 208 return InvokeAsync<RefPtr<CDMProxy>>(mReader->OwnerThread(), mReader.get(), 209 __func__, 210 &MediaFormatReader::SetCDMProxy, aProxy); 211 } 212 213 void ReaderProxy::SetEncryptedCustomIdent() { 214 mReader->SetEncryptedCustomIdent(); 215 } 216 217 bool ReaderProxy::IsEncryptedCustomIdent() const { 218 return mReader->IsEncryptedCustomIdent(); 219 } 220 221 } // namespace mozilla