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 https://mozilla.org/MPL/2.0/. */
7 #include "GraphRunner.h"
9 #include "GraphDriver.h"
10 #include "MediaTrackGraph.h"
11 #include "MediaTrackGraphImpl.h"
12 #include "nsISupportsImpl.h"
13 #include "nsISupportsPriority.h"
16 #include "mozilla/dom/WorkletThread.h"
17 #include "audio_thread_priority.h"
18 #ifdef MOZ_WIDGET_ANDROID
19 # include "AndroidProcess.h"
20 #endif // MOZ_WIDGET_ANDROID
24 GraphRunner::GraphRunner(MediaTrackGraphImpl
* aGraph
,
25 already_AddRefed
<nsIThread
> aThread
)
26 : Runnable("GraphRunner"),
27 mMonitor("GraphRunner::mMonitor"),
29 mThreadState(ThreadState::Wait
),
31 mThread
->Dispatch(do_AddRef(this));
34 GraphRunner::~GraphRunner() {
35 MOZ_ASSERT(mThreadState
== ThreadState::Shutdown
);
39 already_AddRefed
<GraphRunner
> GraphRunner::Create(MediaTrackGraphImpl
* aGraph
) {
40 nsCOMPtr
<nsIThread
> thread
;
41 nsIThreadManager::ThreadCreationOptions options
= {
42 .stackSize
= mozilla::dom::WorkletThread::StackSize()};
43 if (NS_WARN_IF(NS_FAILED(NS_NewNamedThread(
44 "GraphRunner", getter_AddRefs(thread
), nullptr, options
)))) {
47 nsCOMPtr
<nsISupportsPriority
> supportsPriority
= do_QueryInterface(thread
);
48 MOZ_ASSERT(supportsPriority
);
50 supportsPriority
->SetPriority(nsISupportsPriority::PRIORITY_HIGHEST
));
52 return do_AddRef(new GraphRunner(aGraph
, thread
.forget()));
55 void GraphRunner::Shutdown() {
57 MonitorAutoLock
lock(mMonitor
);
58 MOZ_ASSERT(mThreadState
== ThreadState::Wait
);
59 mThreadState
= ThreadState::Shutdown
;
65 auto GraphRunner::OneIteration(GraphTime aStateTime
, GraphTime aIterationEnd
,
66 MixerCallbackReceiver
* aMixerReceiver
)
68 TRACE("GraphRunner::OneIteration");
70 MonitorAutoLock
lock(mMonitor
);
71 MOZ_ASSERT(mThreadState
== ThreadState::Wait
);
73 Some(IterationState(aStateTime
, aIterationEnd
, aMixerReceiver
));
76 if (const auto* audioDriver
=
77 mGraph
->CurrentDriver()->AsAudioCallbackDriver()) {
78 mAudioDriverThreadId
= audioDriver
->ThreadId();
79 } else if (const auto* clockDriver
=
80 mGraph
->CurrentDriver()->AsSystemClockDriver()) {
81 mClockDriverThread
= clockDriver
->Thread();
83 MOZ_CRASH("Unknown GraphDriver");
86 // Signal that mIterationState was updated
87 mThreadState
= ThreadState::Run
;
89 // Wait for mIterationResult to update
92 } while (mThreadState
== ThreadState::Run
);
95 mAudioDriverThreadId
= std::thread::id();
96 mClockDriverThread
= nullptr;
99 mIterationState
= Nothing();
101 IterationResult result
= std::move(mIterationResult
);
102 mIterationResult
= IterationResult();
106 #ifdef MOZ_WIDGET_ANDROID
108 void PromoteRenderingThreadAndroid() {
109 MOZ_LOG(gMediaTrackGraphLog
, LogLevel::Debug
,
110 ("GraphRunner default thread priority: %d",
111 java::sdk::Process::GetThreadPriority(java::sdk::Process::MyTid())));
112 java::sdk::Process::SetThreadPriority(
113 java::sdk::Process::THREAD_PRIORITY_URGENT_AUDIO
);
114 MOZ_LOG(gMediaTrackGraphLog
, LogLevel::Debug
,
115 ("GraphRunner promoted thread priority: %d",
116 java::sdk::Process::GetThreadPriority(java::sdk::Process::MyTid())));
119 #endif // MOZ_WIDGET_ANDROID
121 NS_IMETHODIMP
GraphRunner::Run() {
124 atp_promote_current_thread_to_real_time(0, mGraph
->GraphRate());
127 #ifdef MOZ_WIDGET_ANDROID
128 PromoteRenderingThreadAndroid();
129 #endif // MOZ_WIDGET_ANDROID
131 nsCOMPtr
<nsIThreadInternal
> threadInternal
= do_QueryInterface(mThread
);
132 threadInternal
->SetObserver(mGraph
);
134 MonitorAutoLock
lock(mMonitor
);
136 while (mThreadState
== ThreadState::Wait
) {
137 mMonitor
.Wait(); // Wait for mIterationState to update or for shutdown
139 if (mThreadState
== ThreadState::Shutdown
) {
142 MOZ_DIAGNOSTIC_ASSERT(mIterationState
.isSome());
143 TRACE("GraphRunner::Run");
144 mIterationResult
= mGraph
->OneIterationImpl(
145 mIterationState
->StateTime(), mIterationState
->IterationEnd(),
146 mIterationState
->MixerReceiver());
147 // Signal that mIterationResult was updated
148 mThreadState
= ThreadState::Wait
;
154 atp_demote_current_thread_from_real_time(handle
);
161 bool GraphRunner::OnThread() const { return mThread
->IsOnCurrentThread(); }
164 bool GraphRunner::InDriverIteration(const GraphDriver
* aDriver
) const {
169 if (const auto* audioDriver
= aDriver
->AsAudioCallbackDriver()) {
170 return audioDriver
->ThreadId() == mAudioDriverThreadId
;
173 if (const auto* clockDriver
= aDriver
->AsSystemClockDriver()) {
174 return clockDriver
->Thread() == mClockDriverThread
;
177 MOZ_CRASH("Unknown driver");
181 } // namespace mozilla