Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(291)

Side by Side Diff: Source/modules/webaudio/AudioContext.cpp

Issue 304103002: Remove unnecessary members for tricky lazy initialization in AudioContext. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/modules/webaudio/AudioContext.h ('k') | Source/modules/webaudio/AudioNode.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 audioContext->suspendIfNeeded(); 103 audioContext->suspendIfNeeded();
104 return audioContext.release(); 104 return audioContext.release();
105 } 105 }
106 106
107 // Constructor for rendering to the audio hardware. 107 // Constructor for rendering to the audio hardware.
108 AudioContext::AudioContext(Document* document) 108 AudioContext::AudioContext(Document* document)
109 : ActiveDOMObject(document) 109 : ActiveDOMObject(document)
110 , m_isStopScheduled(false) 110 , m_isStopScheduled(false)
111 , m_isCleared(false) 111 , m_isCleared(false)
112 , m_isInitialized(false) 112 , m_isInitialized(false)
113 , m_isAudioThreadFinished(false)
114 , m_destinationNode(nullptr) 113 , m_destinationNode(nullptr)
115 , m_isDeletionScheduled(false) 114 , m_isDeletionScheduled(false)
116 , m_automaticPullNodesNeedUpdating(false) 115 , m_automaticPullNodesNeedUpdating(false)
117 , m_connectionCount(0) 116 , m_connectionCount(0)
118 , m_audioThread(0) 117 , m_audioThread(0)
119 , m_graphOwnerThread(UndefinedThreadIdentifier) 118 , m_graphOwnerThread(UndefinedThreadIdentifier)
120 , m_isOfflineContext(false) 119 , m_isOfflineContext(false)
121 { 120 {
121 ScriptWrappable::init(this);
122
122 m_destinationNode = DefaultAudioDestinationNode::create(this); 123 m_destinationNode = DefaultAudioDestinationNode::create(this);
123 124
124 constructCommon(); 125 initialize();
125 } 126 }
126 127
127 // Constructor for offline (non-realtime) rendering. 128 // Constructor for offline (non-realtime) rendering.
128 AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate) 129 AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate)
129 : ActiveDOMObject(document) 130 : ActiveDOMObject(document)
130 , m_isStopScheduled(false) 131 , m_isStopScheduled(false)
131 , m_isCleared(false) 132 , m_isCleared(false)
132 , m_isInitialized(false) 133 , m_isInitialized(false)
133 , m_isAudioThreadFinished(false)
134 , m_destinationNode(nullptr) 134 , m_destinationNode(nullptr)
135 , m_automaticPullNodesNeedUpdating(false) 135 , m_automaticPullNodesNeedUpdating(false)
136 , m_connectionCount(0) 136 , m_connectionCount(0)
137 , m_audioThread(0) 137 , m_audioThread(0)
138 , m_graphOwnerThread(UndefinedThreadIdentifier) 138 , m_graphOwnerThread(UndefinedThreadIdentifier)
139 , m_isOfflineContext(true) 139 , m_isOfflineContext(true)
140 { 140 {
141 ScriptWrappable::init(this);
142
141 // Create a new destination for offline rendering. 143 // Create a new destination for offline rendering.
142 m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampl eRate); 144 m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampl eRate);
143 if (m_renderTarget.get()) 145 if (m_renderTarget.get())
144 m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTa rget.get()); 146 m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTa rget.get());
145 147
146 constructCommon();
147 }
148
149 void AudioContext::constructCommon()
150 {
151 ScriptWrappable::init(this);
152
153 FFTFrame::initialize();
154
155 m_listener = AudioListener::create();
156
157 initialize(); 148 initialize();
158 } 149 }
159 150
160 AudioContext::~AudioContext() 151 AudioContext::~AudioContext()
161 { 152 {
162 #if DEBUG_AUDIONODE_REFERENCES 153 #if DEBUG_AUDIONODE_REFERENCES
163 fprintf(stderr, "%p: AudioContext::~AudioContext()\n", this); 154 fprintf(stderr, "%p: AudioContext::~AudioContext()\n", this);
164 #endif 155 #endif
165 // AudioNodes keep a reference to their context, so there should be no way t o be in the destructor if there are still AudioNodes around. 156 // AudioNodes keep a reference to their context, so there should be no way t o be in the destructor if there are still AudioNodes around.
166 ASSERT(!m_isInitialized); 157 ASSERT(!m_isInitialized);
167 ASSERT(!m_nodesToDelete.size()); 158 ASSERT(!m_nodesToDelete.size());
168 ASSERT(!m_referencedNodes.size()); 159 ASSERT(!m_referencedNodes.size());
169 ASSERT(!m_finishedNodes.size()); 160 ASSERT(!m_finishedNodes.size());
170 ASSERT(!m_automaticPullNodes.size()); 161 ASSERT(!m_automaticPullNodes.size());
171 if (m_automaticPullNodesNeedUpdating) 162 if (m_automaticPullNodesNeedUpdating)
172 m_renderingAutomaticPullNodes.resize(m_automaticPullNodes.size()); 163 m_renderingAutomaticPullNodes.resize(m_automaticPullNodes.size());
173 ASSERT(!m_renderingAutomaticPullNodes.size()); 164 ASSERT(!m_renderingAutomaticPullNodes.size());
174 } 165 }
175 166
176 void AudioContext::initialize() 167 void AudioContext::initialize()
177 { 168 {
178 if (!m_isInitialized) { 169 if (isInitialized())
179 // Don't allow the context to initialize a second time after it's alread y been explicitly uninitialized. 170 return;
180 ASSERT(!m_isAudioThreadFinished);
181 if (!m_isAudioThreadFinished) {
182 // Creation of a destination node should not start the audio HW. The
183 // creation of any other AudioNode will initialize the audio HW and start processing
184 if (m_destinationNode.get()) {
185 m_destinationNode->initialize();
186 171
187 if (!isOfflineContext()) { 172 FFTFrame::initialize();
188 // This starts the audio thread. The destination node's prov ideInput() method will now be called repeatedly to render audio. 173 m_listener = AudioListener::create();
189 // Each time provideInput() is called, a portion of the audi o stream is rendered. Let's call this time period a "render quantum".
190 // NOTE: for now default AudioContext does not need an expli cit startRendering() call from JavaScript.
191 // We may want to consider requiring it for symmetry with Of flineAudioContext.
192 m_destinationNode->startRendering();
193 ++s_hardwareContextCount;
194 }
195 174
196 m_isInitialized = true; 175 if (m_destinationNode.get()) {
197 } 176 m_destinationNode->initialize();
177
178 if (!isOfflineContext()) {
179 // 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".
181 // NOTE: for now default AudioContext does not need an explicit star tRendering() call from JavaScript.
182 // We may want to consider requiring it for symmetry with OfflineAud ioContext.
183 m_destinationNode->startRendering();
184 ++s_hardwareContextCount;
198 } 185 }
186
187 m_isInitialized = true;
199 } 188 }
200 } 189 }
201 190
202 void AudioContext::clear() 191 void AudioContext::clear()
203 { 192 {
204 // We have to release our reference to the destination node before the conte xt will ever be deleted since the destination node holds a reference to the cont ext. 193 // We have to release our reference to the destination node before the conte xt will ever be deleted since the destination node holds a reference to the cont ext.
205 if (m_destinationNode) 194 if (m_destinationNode)
206 m_destinationNode.clear(); 195 m_destinationNode.clear();
207 196
208 // Audio thread is dead. Nobody will schedule node deletion action. Let's do it ourselves. 197 // Audio thread is dead. Nobody will schedule node deletion action. Let's do it ourselves.
209 do { 198 do {
210 m_nodesToDelete.appendVector(m_nodesMarkedForDeletion); 199 m_nodesToDelete.appendVector(m_nodesMarkedForDeletion);
211 m_nodesMarkedForDeletion.clear(); 200 m_nodesMarkedForDeletion.clear();
212 deleteMarkedNodes(); 201 deleteMarkedNodes();
213 } while (m_nodesToDelete.size()); 202 } while (m_nodesToDelete.size());
214 203
215 m_isCleared = true; 204 m_isCleared = true;
216 } 205 }
217 206
218 void AudioContext::uninitialize() 207 void AudioContext::uninitialize()
219 { 208 {
220 ASSERT(isMainThread()); 209 ASSERT(isMainThread());
221 210
222 if (!m_isInitialized) 211 if (!isInitialized())
223 return; 212 return;
224 213
225 // This stops the audio thread and all audio rendering. 214 // This stops the audio thread and all audio rendering.
226 m_destinationNode->uninitialize(); 215 m_destinationNode->uninitialize();
227 216
228 // Don't allow the context to initialize a second time after it's already be en explicitly uninitialized.
229 m_isAudioThreadFinished = true;
230
231 if (!isOfflineContext()) { 217 if (!isOfflineContext()) {
232 ASSERT(s_hardwareContextCount); 218 ASSERT(s_hardwareContextCount);
233 --s_hardwareContextCount; 219 --s_hardwareContextCount;
234 } 220 }
235 221
236 // Get rid of the sources which may still be playing. 222 // Get rid of the sources which may still be playing.
237 derefUnfinishedSourceNodes(); 223 derefUnfinishedSourceNodes();
238 224
239 m_isInitialized = false; 225 m_isInitialized = false;
240 } 226 }
241 227
242 bool AudioContext::isInitialized() const
243 {
244 return m_isInitialized;
245 }
246
247 void AudioContext::stopDispatch(void* userData) 228 void AudioContext::stopDispatch(void* userData)
248 { 229 {
249 AudioContext* context = reinterpret_cast<AudioContext*>(userData); 230 AudioContext* context = reinterpret_cast<AudioContext*>(userData);
250 ASSERT(context); 231 ASSERT(context);
251 if (!context) 232 if (!context)
252 return; 233 return;
253 234
254 context->uninitialize(); 235 context->uninitialize();
255 context->clear(); 236 context->clear();
256 } 237 }
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
586 567
587 void AudioContext::notifyNodeFinishedProcessing(AudioNode* node) 568 void AudioContext::notifyNodeFinishedProcessing(AudioNode* node)
588 { 569 {
589 ASSERT(isAudioThread()); 570 ASSERT(isAudioThread());
590 m_finishedNodes.append(node); 571 m_finishedNodes.append(node);
591 } 572 }
592 573
593 void AudioContext::derefFinishedSourceNodes() 574 void AudioContext::derefFinishedSourceNodes()
594 { 575 {
595 ASSERT(isGraphOwner()); 576 ASSERT(isGraphOwner());
596 ASSERT(isAudioThread() || isAudioThreadFinished()); 577 ASSERT(isAudioThread());
597 for (unsigned i = 0; i < m_finishedNodes.size(); i++) 578 for (unsigned i = 0; i < m_finishedNodes.size(); i++)
598 derefNode(m_finishedNodes[i]); 579 derefNode(m_finishedNodes[i]);
599 580
600 m_finishedNodes.clear(); 581 m_finishedNodes.clear();
601 } 582 }
602 583
603 void AudioContext::refNode(AudioNode* node) 584 void AudioContext::refNode(AudioNode* node)
604 { 585 {
605 ASSERT(isMainThread()); 586 ASSERT(isMainThread());
606 AutoLocker locker(this); 587 AutoLocker locker(this);
(...skipping 11 matching lines...) Expand all
618 for (unsigned i = 0; i < m_referencedNodes.size(); ++i) { 599 for (unsigned i = 0; i < m_referencedNodes.size(); ++i) {
619 if (node == m_referencedNodes[i]) { 600 if (node == m_referencedNodes[i]) {
620 m_referencedNodes.remove(i); 601 m_referencedNodes.remove(i);
621 break; 602 break;
622 } 603 }
623 } 604 }
624 } 605 }
625 606
626 void AudioContext::derefUnfinishedSourceNodes() 607 void AudioContext::derefUnfinishedSourceNodes()
627 { 608 {
628 ASSERT(isMainThread() && isAudioThreadFinished()); 609 ASSERT(isMainThread());
629 for (unsigned i = 0; i < m_referencedNodes.size(); ++i) 610 for (unsigned i = 0; i < m_referencedNodes.size(); ++i)
630 m_referencedNodes[i]->deref(AudioNode::RefTypeConnection); 611 m_referencedNodes[i]->deref(AudioNode::RefTypeConnection);
631 612
632 m_referencedNodes.clear(); 613 m_referencedNodes.clear();
633 } 614 }
634 615
635 void AudioContext::lock(bool& mustReleaseLock) 616 void AudioContext::lock(bool& mustReleaseLock)
636 { 617 {
637 // Don't allow regular lock in real-time audio thread. 618 // Don't allow regular lock in real-time audio thread.
638 ASSERT(isMainThread()); 619 ASSERT(isMainThread());
(...skipping 10 matching lines...) Expand all
649 mustReleaseLock = true; 630 mustReleaseLock = true;
650 } 631 }
651 } 632 }
652 633
653 bool AudioContext::tryLock(bool& mustReleaseLock) 634 bool AudioContext::tryLock(bool& mustReleaseLock)
654 { 635 {
655 ThreadIdentifier thisThread = currentThread(); 636 ThreadIdentifier thisThread = currentThread();
656 bool isAudioThread = thisThread == audioThread(); 637 bool isAudioThread = thisThread == audioThread();
657 638
658 // Try to catch cases of using try lock on main thread - it should use regul ar lock. 639 // Try to catch cases of using try lock on main thread - it should use regul ar lock.
659 ASSERT(isAudioThread || isAudioThreadFinished()); 640 ASSERT(isAudioThread);
660 641
661 if (!isAudioThread) { 642 if (!isAudioThread) {
662 // In release build treat tryLock() as lock() (since above ASSERT(isAudi oThread) never fires) - this is the best we can do. 643 // In release build treat tryLock() as lock() (since above ASSERT(isAudi oThread) never fires) - this is the best we can do.
663 lock(mustReleaseLock); 644 lock(mustReleaseLock);
664 return true; 645 return true;
665 } 646 }
666 647
667 bool hasLock; 648 bool hasLock;
668 649
669 if (thisThread == m_graphOwnerThread) { 650 if (thisThread == m_graphOwnerThread) {
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
764 node->finishDeref(AudioNode::RefTypeConnection); 745 node->finishDeref(AudioNode::RefTypeConnection);
765 } 746 }
766 747
767 m_deferredFinishDerefList.clear(); 748 m_deferredFinishDerefList.clear();
768 } 749 }
769 750
770 void AudioContext::markForDeletion(AudioNode* node) 751 void AudioContext::markForDeletion(AudioNode* node)
771 { 752 {
772 ASSERT(isGraphOwner()); 753 ASSERT(isGraphOwner());
773 754
774 if (isAudioThreadFinished()) 755 if (!isInitialized())
775 m_nodesToDelete.append(node); 756 m_nodesToDelete.append(node);
776 else 757 else
777 m_nodesMarkedForDeletion.append(node); 758 m_nodesMarkedForDeletion.append(node);
778 759
779 // This is probably the best time for us to remove the node from automatic p ull list, 760 // This is probably the best time for us to remove the node from automatic p ull list,
780 // since all connections are gone and we hold the graph lock. Then when hand lePostRenderTasks() 761 // since all connections are gone and we hold the graph lock. Then when hand lePostRenderTasks()
781 // gets a chance to schedule the deletion work, updateAutomaticPullNodes() a lso gets a chance to 762 // gets a chance to schedule the deletion work, updateAutomaticPullNodes() a lso gets a chance to
782 // modify m_renderingAutomaticPullNodes. 763 // modify m_renderingAutomaticPullNodes.
783 removeAutomaticPullNode(node); 764 removeAutomaticPullNode(node);
784 } 765 }
785 766
786 void AudioContext::scheduleNodeDeletion() 767 void AudioContext::scheduleNodeDeletion()
787 { 768 {
788 bool isGood = m_isInitialized && isGraphOwner(); 769 bool isGood = isInitialized() && isGraphOwner();
789 ASSERT(isGood); 770 ASSERT(isGood);
790 if (!isGood) 771 if (!isGood)
791 return; 772 return;
792 773
793 // Make sure to call deleteMarkedNodes() on main thread. 774 // Make sure to call deleteMarkedNodes() on main thread.
794 if (m_nodesMarkedForDeletion.size() && !m_isDeletionScheduled) { 775 if (m_nodesMarkedForDeletion.size() && !m_isDeletionScheduled) {
795 m_nodesToDelete.appendVector(m_nodesMarkedForDeletion); 776 m_nodesToDelete.appendVector(m_nodesMarkedForDeletion);
796 m_nodesMarkedForDeletion.clear(); 777 m_nodesMarkedForDeletion.clear();
797 778
798 m_isDeletionScheduled = true; 779 m_isDeletionScheduled = true;
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
974 visitor->trace(m_renderTarget); 955 visitor->trace(m_renderTarget);
975 visitor->trace(m_destinationNode); 956 visitor->trace(m_destinationNode);
976 visitor->trace(m_listener); 957 visitor->trace(m_listener);
977 visitor->trace(m_dirtySummingJunctions); 958 visitor->trace(m_dirtySummingJunctions);
978 EventTargetWithInlineData::trace(visitor); 959 EventTargetWithInlineData::trace(visitor);
979 } 960 }
980 961
981 } // namespace WebCore 962 } // namespace WebCore
982 963
983 #endif // ENABLE(WEB_AUDIO) 964 #endif // ENABLE(WEB_AUDIO)
OLDNEW
« no previous file with comments | « Source/modules/webaudio/AudioContext.h ('k') | Source/modules/webaudio/AudioNode.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698