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 "audio_thread_priority.h"
17 #ifdef MOZ_WIDGET_ANDROID
18 # include "AndroidProcess.h"
19 #endif // MOZ_WIDGET_ANDROID
23 GraphRunner::GraphRunner(MediaTrackGraphImpl
* aGraph
,
24 already_AddRefed
<nsIThread
> aThread
)
25 : Runnable("GraphRunner"),
26 mMonitor("GraphRunner::mMonitor"),
28 mThreadState(ThreadState::Wait
),
30 mThread
->Dispatch(do_AddRef(this));
33 GraphRunner::~GraphRunner() {
34 MOZ_ASSERT(mThreadState
== ThreadState::Shutdown
);
38 already_AddRefed
<GraphRunner
> GraphRunner::Create(MediaTrackGraphImpl
* aGraph
) {
39 nsCOMPtr
<nsIThread
> thread
;
40 if (NS_WARN_IF(NS_FAILED(
41 NS_NewNamedThread("GraphRunner", getter_AddRefs(thread
))))) {
44 nsCOMPtr
<nsISupportsPriority
> supportsPriority
= do_QueryInterface(thread
);
45 MOZ_ASSERT(supportsPriority
);
47 supportsPriority
->SetPriority(nsISupportsPriority::PRIORITY_HIGHEST
));
49 return do_AddRef(new GraphRunner(aGraph
, thread
.forget()));
52 void GraphRunner::Shutdown() {
54 MonitorAutoLock
lock(mMonitor
);
55 MOZ_ASSERT(mThreadState
== ThreadState::Wait
);
56 mThreadState
= ThreadState::Shutdown
;
62 auto GraphRunner::OneIteration(GraphTime aStateTime
, GraphTime aIterationEnd
,
63 AudioMixer
* aMixer
) -> IterationResult
{
64 TRACE("GraphRunner::OneIteration");
66 MonitorAutoLock
lock(mMonitor
);
67 MOZ_ASSERT(mThreadState
== ThreadState::Wait
);
68 mIterationState
= Some(IterationState(aStateTime
, aIterationEnd
, aMixer
));
71 if (const auto* audioDriver
=
72 mGraph
->CurrentDriver()->AsAudioCallbackDriver()) {
73 mAudioDriverThreadId
= audioDriver
->ThreadId();
74 } else if (const auto* clockDriver
=
75 mGraph
->CurrentDriver()->AsSystemClockDriver()) {
76 mClockDriverThread
= clockDriver
->Thread();
78 MOZ_CRASH("Unknown GraphDriver");
81 // Signal that mIterationState was updated
82 mThreadState
= ThreadState::Run
;
84 // Wait for mIterationResult to update
87 } while (mThreadState
== ThreadState::Run
);
90 mAudioDriverThreadId
= std::thread::id();
91 mClockDriverThread
= nullptr;
94 mIterationState
= Nothing();
96 IterationResult result
= std::move(mIterationResult
);
97 mIterationResult
= IterationResult();
101 #ifdef MOZ_WIDGET_ANDROID
103 void PromoteRenderingThreadAndroid() {
104 MOZ_LOG(gMediaTrackGraphLog
, LogLevel::Debug
,
105 ("GraphRunner default thread priority: %d",
106 java::sdk::Process::GetThreadPriority(java::sdk::Process::MyTid())));
107 java::sdk::Process::SetThreadPriority(
108 java::sdk::Process::THREAD_PRIORITY_URGENT_AUDIO
);
109 MOZ_LOG(gMediaTrackGraphLog
, LogLevel::Debug
,
110 ("GraphRunner promoted thread priority: %d",
111 java::sdk::Process::GetThreadPriority(java::sdk::Process::MyTid())));
114 #endif // MOZ_WIDGET_ANDROID
116 NS_IMETHODIMP
GraphRunner::Run() {
119 atp_promote_current_thread_to_real_time(0, mGraph
->GraphRate());
122 #ifdef MOZ_WIDGET_ANDROID
123 PromoteRenderingThreadAndroid();
124 #endif // MOZ_WIDGET_ANDROID
126 nsCOMPtr
<nsIThreadInternal
> threadInternal
= do_QueryInterface(mThread
);
127 threadInternal
->SetObserver(mGraph
);
129 MonitorAutoLock
lock(mMonitor
);
131 while (mThreadState
== ThreadState::Wait
) {
132 mMonitor
.Wait(); // Wait for mIterationState to update or for shutdown
134 if (mThreadState
== ThreadState::Shutdown
) {
137 MOZ_DIAGNOSTIC_ASSERT(mIterationState
.isSome());
138 TRACE("GraphRunner::Run");
139 mIterationResult
= mGraph
->OneIterationImpl(mIterationState
->StateTime(),
140 mIterationState
->IterationEnd(),
141 mIterationState
->Mixer());
142 // Signal that mIterationResult was updated
143 mThreadState
= ThreadState::Wait
;
149 atp_demote_current_thread_from_real_time(handle
);
156 bool GraphRunner::OnThread() const { return mThread
->IsOnCurrentThread(); }
159 bool GraphRunner::InDriverIteration(const GraphDriver
* aDriver
) const {
164 if (const auto* audioDriver
= aDriver
->AsAudioCallbackDriver()) {
165 return audioDriver
->ThreadId() == mAudioDriverThreadId
;
168 if (const auto* clockDriver
= aDriver
->AsSystemClockDriver()) {
169 return clockDriver
->Thread() == mClockDriverThread
;
172 MOZ_CRASH("Unknown driver");
176 } // namespace mozilla