OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2010, Google Inc. All rights reserved. | 2 * Copyright (C) 2010, Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 : ActiveDOMObject(document) | 104 : ActiveDOMObject(document) |
105 , m_isStopScheduled(false) | 105 , m_isStopScheduled(false) |
106 , m_isCleared(false) | 106 , m_isCleared(false) |
107 , m_isInitialized(false) | 107 , m_isInitialized(false) |
108 , m_destinationNode(nullptr) | 108 , m_destinationNode(nullptr) |
109 , m_isResolvingResumePromises(false) | 109 , m_isResolvingResumePromises(false) |
110 , m_automaticPullNodesNeedUpdating(false) | 110 , m_automaticPullNodesNeedUpdating(false) |
111 , m_connectionCount(0) | 111 , m_connectionCount(0) |
112 , m_didInitializeContextGraphMutex(false) | 112 , m_didInitializeContextGraphMutex(false) |
113 , m_audioThread(0) | 113 , m_audioThread(0) |
114 , m_lastZombie(nullptr) | |
115 , m_lastRemovableZombie(nullptr) | |
116 , m_isOfflineContext(false) | 114 , m_isOfflineContext(false) |
117 , m_contextState(Suspended) | 115 , m_contextState(Suspended) |
118 , m_cachedSampleFrame(0) | 116 , m_cachedSampleFrame(0) |
119 { | 117 { |
120 m_didInitializeContextGraphMutex = true; | 118 m_didInitializeContextGraphMutex = true; |
121 m_destinationNode = DefaultAudioDestinationNode::create(this); | 119 m_destinationNode = DefaultAudioDestinationNode::create(this); |
122 | 120 |
123 initialize(); | 121 initialize(); |
124 } | 122 } |
125 | 123 |
126 // Constructor for offline (non-realtime) rendering. | 124 // Constructor for offline (non-realtime) rendering. |
127 AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t
numberOfFrames, float sampleRate) | 125 AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t
numberOfFrames, float sampleRate) |
128 : ActiveDOMObject(document) | 126 : ActiveDOMObject(document) |
129 , m_isStopScheduled(false) | 127 , m_isStopScheduled(false) |
130 , m_isCleared(false) | 128 , m_isCleared(false) |
131 , m_isInitialized(false) | 129 , m_isInitialized(false) |
132 , m_destinationNode(nullptr) | 130 , m_destinationNode(nullptr) |
133 , m_isResolvingResumePromises(false) | 131 , m_isResolvingResumePromises(false) |
134 , m_automaticPullNodesNeedUpdating(false) | 132 , m_automaticPullNodesNeedUpdating(false) |
135 , m_connectionCount(0) | 133 , m_connectionCount(0) |
136 , m_didInitializeContextGraphMutex(false) | 134 , m_didInitializeContextGraphMutex(false) |
137 , m_audioThread(0) | 135 , m_audioThread(0) |
138 , m_lastZombie(nullptr) | |
139 , m_lastRemovableZombie(nullptr) | |
140 , m_isOfflineContext(true) | 136 , m_isOfflineContext(true) |
141 , m_contextState(Suspended) | 137 , m_contextState(Suspended) |
142 , m_cachedSampleFrame(0) | 138 , m_cachedSampleFrame(0) |
143 { | 139 { |
144 m_didInitializeContextGraphMutex = true; | 140 m_didInitializeContextGraphMutex = true; |
145 // Create a new destination for offline rendering. | 141 // Create a new destination for offline rendering. |
146 m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampl
eRate); | 142 m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampl
eRate); |
147 if (m_renderTarget.get()) | 143 if (m_renderTarget.get()) |
148 m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTa
rget.get()); | 144 m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTa
rget.get()); |
149 | 145 |
(...skipping 16 matching lines...) Expand all Loading... |
166 ASSERT(!m_suspendResolvers.size()); | 162 ASSERT(!m_suspendResolvers.size()); |
167 ASSERT(!m_isResolvingResumePromises); | 163 ASSERT(!m_isResolvingResumePromises); |
168 ASSERT(!m_resumeResolvers.size()); | 164 ASSERT(!m_resumeResolvers.size()); |
169 } | 165 } |
170 | 166 |
171 void AudioContext::initialize() | 167 void AudioContext::initialize() |
172 { | 168 { |
173 if (isInitialized()) | 169 if (isInitialized()) |
174 return; | 170 return; |
175 | 171 |
176 ThreadState::current()->addMarkingTask(this); | |
177 FFTFrame::initialize(); | 172 FFTFrame::initialize(); |
178 m_listener = AudioListener::create(); | 173 m_listener = AudioListener::create(); |
179 | 174 |
180 if (m_destinationNode.get()) { | 175 if (m_destinationNode.get()) { |
181 m_destinationNode->initialize(); | 176 m_destinationNode->initialize(); |
182 | 177 |
183 if (!isOfflineContext()) { | 178 if (!isOfflineContext()) { |
184 // This starts the audio thread. The destination node's provideInput
() method will now be called repeatedly to render audio. | 179 // This starts the audio thread. The destination node's provideInput
() method will now be called repeatedly to render audio. |
185 // Each time provideInput() is called, a portion of the audio stream
is rendered. Let's call this time period a "render quantum". | 180 // Each time provideInput() is called, a portion of the audio stream
is rendered. Let's call this time period a "render quantum". |
186 // NOTE: for now default AudioContext does not need an explicit star
tRendering() call from JavaScript. | 181 // NOTE: for now default AudioContext does not need an explicit star
tRendering() call from JavaScript. |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 setContextState(Closed); | 232 setContextState(Closed); |
238 | 233 |
239 // Resolve the promise now, if any | 234 // Resolve the promise now, if any |
240 if (m_closeResolver) | 235 if (m_closeResolver) |
241 m_closeResolver->resolve(); | 236 m_closeResolver->resolve(); |
242 | 237 |
243 ASSERT(m_listener); | 238 ASSERT(m_listener); |
244 m_listener->waitForHRTFDatabaseLoaderThreadCompletion(); | 239 m_listener->waitForHRTFDatabaseLoaderThreadCompletion(); |
245 | 240 |
246 clear(); | 241 clear(); |
247 | |
248 ThreadState::current()->removeMarkingTask(this); | |
249 if (m_lastZombie) | |
250 ThreadState::current()->purifyZombies(); | |
251 m_lastZombie = nullptr; | |
252 m_lastRemovableZombie = nullptr; | |
253 } | 242 } |
254 | 243 |
255 void AudioContext::stop() | 244 void AudioContext::stop() |
256 { | 245 { |
257 // Usually ExecutionContext calls stop twice. | 246 // Usually ExecutionContext calls stop twice. |
258 if (m_isStopScheduled) | 247 if (m_isStopScheduled) |
259 return; | 248 return; |
260 m_isStopScheduled = true; | 249 m_isStopScheduled = true; |
261 | 250 |
262 // Don't call uninitialize() immediately here because the ExecutionContext i
s in the middle | 251 // Don't call uninitialize() immediately here because the ExecutionContext i
s in the middle |
(...skipping 726 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
989 if (tryLock()) { | 978 if (tryLock()) { |
990 // Update the channel count mode. | 979 // Update the channel count mode. |
991 updateChangedChannelCountMode(); | 980 updateChangedChannelCountMode(); |
992 | 981 |
993 // Take care of AudioNode tasks where the tryLock() failed previously. | 982 // Take care of AudioNode tasks where the tryLock() failed previously. |
994 handleDeferredAudioNodeTasks(); | 983 handleDeferredAudioNodeTasks(); |
995 | 984 |
996 // Dynamically clean up nodes which are no longer needed. | 985 // Dynamically clean up nodes which are no longer needed. |
997 derefFinishedSourceNodes(); | 986 derefFinishedSourceNodes(); |
998 | 987 |
999 m_lastRemovableZombie = m_lastZombie; | |
1000 | |
1001 // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutpu
ts. | 988 // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutpu
ts. |
1002 handleDirtyAudioSummingJunctions(); | 989 handleDirtyAudioSummingJunctions(); |
1003 handleDirtyAudioNodeOutputs(); | 990 handleDirtyAudioNodeOutputs(); |
1004 | 991 |
1005 updateAutomaticPullNodes(); | 992 updateAutomaticPullNodes(); |
1006 resolvePromisesForSuspend(); | 993 resolvePromisesForSuspend(); |
1007 | 994 |
1008 unlock(); | 995 unlock(); |
1009 } | 996 } |
1010 } | 997 } |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1287 } | 1274 } |
1288 } | 1275 } |
1289 | 1276 |
1290 DEFINE_TRACE(AudioContext) | 1277 DEFINE_TRACE(AudioContext) |
1291 { | 1278 { |
1292 visitor->trace(m_closeResolver); | 1279 visitor->trace(m_closeResolver); |
1293 visitor->trace(m_offlineResolver); | 1280 visitor->trace(m_offlineResolver); |
1294 visitor->trace(m_renderTarget); | 1281 visitor->trace(m_renderTarget); |
1295 visitor->trace(m_destinationNode); | 1282 visitor->trace(m_destinationNode); |
1296 visitor->trace(m_listener); | 1283 visitor->trace(m_listener); |
1297 visitor->trace(m_referencedNodes); | 1284 // trace() can be called in AudioContext constructor, and |
| 1285 // m_contextGraphMutex might be unavailable. |
| 1286 if (m_didInitializeContextGraphMutex) { |
| 1287 AutoLocker lock(this); |
| 1288 visitor->trace(m_referencedNodes); |
| 1289 } else { |
| 1290 visitor->trace(m_referencedNodes); |
| 1291 } |
1298 visitor->trace(m_resumeResolvers); | 1292 visitor->trace(m_resumeResolvers); |
1299 visitor->trace(m_suspendResolvers); | 1293 visitor->trace(m_suspendResolvers); |
1300 visitor->trace(m_liveNodes); | 1294 visitor->trace(m_liveNodes); |
1301 visitor->trace(m_liveAudioSummingJunctions); | 1295 visitor->trace(m_liveAudioSummingJunctions); |
1302 RefCountedGarbageCollectedEventTargetWithInlineData<AudioContext>::trace(vis
itor); | 1296 RefCountedGarbageCollectedEventTargetWithInlineData<AudioContext>::trace(vis
itor); |
1303 ActiveDOMObject::trace(visitor); | 1297 ActiveDOMObject::trace(visitor); |
1304 } | 1298 } |
1305 | 1299 |
1306 void AudioContext::addChangedChannelCountMode(AudioNode* node) | 1300 void AudioContext::addChangedChannelCountMode(AudioNode* node) |
1307 { | 1301 { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1364 | 1358 |
1365 // Stop the audio context. This will stop the destination node from pulling
audio anymore. And | 1359 // Stop the audio context. This will stop the destination node from pulling
audio anymore. And |
1366 // since we have disconnected the destination from the audio graph, and thus
has no references, | 1360 // since we have disconnected the destination from the audio graph, and thus
has no references, |
1367 // the destination node can GCed if JS has no references. stop() will also r
esolve the Promise | 1361 // the destination node can GCed if JS has no references. stop() will also r
esolve the Promise |
1368 // created here. | 1362 // created here. |
1369 stop(); | 1363 stop(); |
1370 | 1364 |
1371 return promise; | 1365 return promise; |
1372 } | 1366 } |
1373 | 1367 |
1374 void AudioContext::setLastZombie(void* object) | |
1375 { | |
1376 ASSERT(isGraphOwner()); | |
1377 m_lastZombie = object; | |
1378 } | |
1379 | |
1380 void AudioContext::willStartMarking(ThreadState& threadState) | |
1381 { | |
1382 lock(); | |
1383 if (!m_lastRemovableZombie) | |
1384 return; | |
1385 if (m_lastZombie != m_lastRemovableZombie) | |
1386 return; | |
1387 threadState.purifyZombies(); | |
1388 m_lastZombie = nullptr; | |
1389 m_lastRemovableZombie = nullptr; | |
1390 } | |
1391 | |
1392 void AudioContext::didFinishMarking(ThreadState&) | |
1393 { | |
1394 unlock(); | |
1395 } | |
1396 | |
1397 } // namespace blink | 1368 } // namespace blink |
1398 | 1369 |
1399 #endif // ENABLE(WEB_AUDIO) | 1370 #endif // ENABLE(WEB_AUDIO) |
OLD | NEW |