Backed out changeset 06f41c22f3a6 (bug 1888460) for causing linux xpcshell failures...
[gecko.git] / dom / media / ReaderProxy.cpp
blobc824863f40bb8016244cd4b5c4d997739d7aba13
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/. */
7 #include "mozilla/CDMProxy.h"
8 #include "mozilla/MozPromise.h"
9 #include "MediaFormatReader.h"
10 #include "ReaderProxy.h"
11 #include "TimeUnits.h"
13 namespace mozilla {
15 ReaderProxy::ReaderProxy(AbstractThread* aOwnerThread,
16 MediaFormatReader* aReader)
17 : mOwnerThread(aOwnerThread),
18 mReader(aReader),
19 mWatchManager(this, aReader->OwnerThread()),
20 mDuration(aReader->OwnerThread(), media::NullableTimeUnit(),
21 "ReaderProxy::mDuration (Mirror)") {
22 // Must support either heuristic buffering or WaitForData().
23 MOZ_ASSERT(mReader->UseBufferingHeuristics() ||
24 mReader->IsWaitForDataSupported());
27 ReaderProxy::~ReaderProxy() = default;
29 media::TimeUnit ReaderProxy::StartTime() const {
30 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
31 return mStartTime.ref();
34 RefPtr<ReaderProxy::MetadataPromise> ReaderProxy::ReadMetadata() {
35 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
36 MOZ_ASSERT(!mShutdown);
37 return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
38 &MediaFormatReader::AsyncReadMetadata)
39 ->Then(mOwnerThread, __func__, this, &ReaderProxy::OnMetadataRead,
40 &ReaderProxy::OnMetadataNotRead);
43 RefPtr<ReaderProxy::AudioDataPromise> ReaderProxy::OnAudioDataRequestCompleted(
44 RefPtr<AudioData> aAudio) {
45 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
47 if (aAudio->AdjustForStartTime(StartTime())) {
48 return AudioDataPromise::CreateAndResolve(aAudio.forget(), __func__);
50 return AudioDataPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_OVERFLOW_ERR,
51 __func__);
54 RefPtr<ReaderProxy::AudioDataPromise> ReaderProxy::OnAudioDataRequestFailed(
55 const MediaResult& aError) {
56 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
57 return AudioDataPromise::CreateAndReject(aError, __func__);
60 RefPtr<ReaderProxy::AudioDataPromise> ReaderProxy::RequestAudioData() {
61 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
62 MOZ_ASSERT(!mShutdown);
64 return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
65 &MediaFormatReader::RequestAudioData)
66 ->Then(mOwnerThread, __func__, this,
67 &ReaderProxy::OnAudioDataRequestCompleted,
68 &ReaderProxy::OnAudioDataRequestFailed);
71 RefPtr<ReaderProxy::VideoDataPromise> ReaderProxy::RequestVideoData(
72 const media::TimeUnit& aTimeThreshold, bool aRequestNextVideoKeyFrame) {
73 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
74 MOZ_ASSERT(!mShutdown);
76 const auto threshold = aTimeThreshold > media::TimeUnit::Zero()
77 ? aTimeThreshold + StartTime()
78 : aTimeThreshold;
80 auto startTime = StartTime();
81 return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
82 &MediaFormatReader::RequestVideoData, threshold,
83 aRequestNextVideoKeyFrame)
84 ->Then(
85 mOwnerThread, __func__,
86 [startTime](RefPtr<VideoData> aVideo) {
87 return aVideo->AdjustForStartTime(startTime)
88 ? VideoDataPromise::CreateAndResolve(aVideo.forget(),
89 __func__)
90 : VideoDataPromise::CreateAndReject(
91 NS_ERROR_DOM_MEDIA_OVERFLOW_ERR, __func__);
93 [](const MediaResult& aError) {
94 return VideoDataPromise::CreateAndReject(aError, __func__);
95 });
98 RefPtr<ReaderProxy::SeekPromise> ReaderProxy::Seek(const SeekTarget& aTarget) {
99 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
100 return SeekInternal(aTarget);
103 RefPtr<ReaderProxy::SeekPromise> ReaderProxy::SeekInternal(
104 const SeekTarget& aTarget) {
105 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
106 SeekTarget adjustedTarget = aTarget;
107 adjustedTarget.SetTime(adjustedTarget.GetTime() + StartTime());
108 return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
109 &MediaFormatReader::Seek, std::move(adjustedTarget));
112 RefPtr<ReaderProxy::WaitForDataPromise> ReaderProxy::WaitForData(
113 MediaData::Type aType) {
114 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
115 MOZ_ASSERT(mReader->IsWaitForDataSupported());
116 return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
117 &MediaFormatReader::WaitForData, aType);
120 void ReaderProxy::ReleaseResources() {
121 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
122 nsCOMPtr<nsIRunnable> r =
123 NewRunnableMethod("MediaFormatReader::ReleaseResources", mReader,
124 &MediaFormatReader::ReleaseResources);
125 nsresult rv = mReader->OwnerThread()->Dispatch(r.forget());
126 MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
127 Unused << rv;
130 void ReaderProxy::ResetDecode(TrackSet aTracks) {
131 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
132 nsCOMPtr<nsIRunnable> r =
133 NewRunnableMethod<TrackSet>("MediaFormatReader::ResetDecode", mReader,
134 &MediaFormatReader::ResetDecode, aTracks);
135 nsresult rv = mReader->OwnerThread()->Dispatch(r.forget());
136 MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
137 Unused << rv;
140 RefPtr<ShutdownPromise> ReaderProxy::Shutdown() {
141 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
142 mShutdown = true;
143 RefPtr<ReaderProxy> self = this;
144 return InvokeAsync(mReader->OwnerThread(), __func__, [self]() {
145 self->mDuration.DisconnectIfConnected();
146 self->mWatchManager.Shutdown();
147 return self->mReader->Shutdown();
151 RefPtr<ReaderProxy::MetadataPromise> ReaderProxy::OnMetadataRead(
152 MetadataHolder&& aMetadata) {
153 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
154 if (mShutdown) {
155 return MetadataPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_ABORT_ERR,
156 __func__);
159 if (mStartTime.isNothing()) {
160 mStartTime.emplace(aMetadata.mInfo->mStartTime);
162 return MetadataPromise::CreateAndResolve(std::move(aMetadata), __func__);
165 RefPtr<ReaderProxy::MetadataPromise> ReaderProxy::OnMetadataNotRead(
166 const MediaResult& aError) {
167 return MetadataPromise::CreateAndReject(aError, __func__);
170 void ReaderProxy::SetVideoBlankDecode(bool aIsBlankDecode) {
171 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
172 nsCOMPtr<nsIRunnable> r = NewRunnableMethod<bool>(
173 "MediaFormatReader::SetVideoNullDecode", mReader,
174 &MediaFormatReader::SetVideoNullDecode, aIsBlankDecode);
175 nsresult rv = mReader->OwnerThread()->Dispatch(r.forget());
176 MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
177 Unused << rv;
180 void ReaderProxy::UpdateDuration() {
181 MOZ_ASSERT(mReader->OwnerThread()->IsCurrentThreadIn());
182 mReader->UpdateDuration(mDuration.Ref().ref());
185 void ReaderProxy::SetCanonicalDuration(
186 Canonical<media::NullableTimeUnit>& aCanonical) {
187 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
188 nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
189 "ReaderProxy::SetCanonicalDuration", [this, self = RefPtr(this)]() {
190 mWatchManager.Watch(mDuration, &ReaderProxy::UpdateDuration);
192 mReader->OwnerThread()->DispatchStateChange(r.forget());
193 aCanonical.ConnectMirror(&mDuration);
196 void ReaderProxy::UpdateMediaEngineId(uint64_t aMediaEngineId) {
197 MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
198 nsCOMPtr<nsIRunnable> r = NewRunnableMethod<uint64_t>(
199 "MediaFormatReader::UpdateMediaEngineId", mReader,
200 &MediaFormatReader::UpdateMediaEngineId, aMediaEngineId);
201 nsresult rv = mReader->OwnerThread()->Dispatch(r.forget());
202 MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
203 Unused << rv;
206 RefPtr<SetCDMPromise> ReaderProxy::SetCDMProxy(CDMProxy* aProxy) {
207 return InvokeAsync<RefPtr<CDMProxy>>(mReader->OwnerThread(), mReader.get(),
208 __func__,
209 &MediaFormatReader::SetCDMProxy, aProxy);
212 } // namespace mozilla