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