Chromium Code Reviews| 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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 102 : ActiveDOMObject(document) | 102 : ActiveDOMObject(document) |
| 103 , m_isStopScheduled(false) | 103 , m_isStopScheduled(false) |
| 104 , m_isCleared(false) | 104 , m_isCleared(false) |
| 105 , m_isInitialized(false) | 105 , m_isInitialized(false) |
| 106 , m_destinationNode(nullptr) | 106 , m_destinationNode(nullptr) |
| 107 , m_isResolvingResumePromises(false) | 107 , m_isResolvingResumePromises(false) |
| 108 , m_automaticPullNodesNeedUpdating(false) | 108 , m_automaticPullNodesNeedUpdating(false) |
| 109 , m_connectionCount(0) | 109 , m_connectionCount(0) |
| 110 , m_didInitializeContextGraphMutex(false) | 110 , m_didInitializeContextGraphMutex(false) |
| 111 , m_audioThread(0) | 111 , m_audioThread(0) |
| 112 , m_lastZombie(nullptr) | |
| 113 , m_lastRemovableZombie(nullptr) | |
| 112 , m_isOfflineContext(false) | 114 , m_isOfflineContext(false) |
| 113 , m_contextState(Suspended) | 115 , m_contextState(Suspended) |
| 114 , m_cachedSampleFrame(0) | 116 , m_cachedSampleFrame(0) |
| 115 { | 117 { |
| 116 m_didInitializeContextGraphMutex = true; | 118 m_didInitializeContextGraphMutex = true; |
| 117 m_destinationNode = DefaultAudioDestinationNode::create(this); | 119 m_destinationNode = DefaultAudioDestinationNode::create(this); |
| 118 | 120 |
| 119 initialize(); | 121 initialize(); |
| 120 #if DEBUG_AUDIONODE_REFERENCES | 122 #if DEBUG_AUDIONODE_REFERENCES |
| 121 fprintf(stderr, "%p: AudioContext::AudioContext() #%u\n", this, AudioContext ::s_hardwareContextCount); | 123 fprintf(stderr, "%p: AudioContext::AudioContext() #%u\n", this, AudioContext ::s_hardwareContextCount); |
| 122 #endif | 124 #endif |
| 123 } | 125 } |
| 124 | 126 |
| 125 // Constructor for offline (non-realtime) rendering. | 127 // Constructor for offline (non-realtime) rendering. |
| 126 AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate) | 128 AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate) |
| 127 : ActiveDOMObject(document) | 129 : ActiveDOMObject(document) |
| 128 , m_isStopScheduled(false) | 130 , m_isStopScheduled(false) |
| 129 , m_isCleared(false) | 131 , m_isCleared(false) |
| 130 , m_isInitialized(false) | 132 , m_isInitialized(false) |
| 131 , m_destinationNode(nullptr) | 133 , m_destinationNode(nullptr) |
| 132 , m_isResolvingResumePromises(false) | 134 , m_isResolvingResumePromises(false) |
| 133 , m_automaticPullNodesNeedUpdating(false) | 135 , m_automaticPullNodesNeedUpdating(false) |
| 134 , m_connectionCount(0) | 136 , m_connectionCount(0) |
| 135 , m_didInitializeContextGraphMutex(false) | 137 , m_didInitializeContextGraphMutex(false) |
| 136 , m_audioThread(0) | 138 , m_audioThread(0) |
| 139 , m_lastZombie(nullptr) | |
| 140 , m_lastRemovableZombie(nullptr) | |
| 137 , m_isOfflineContext(true) | 141 , m_isOfflineContext(true) |
| 138 , m_contextState(Suspended) | 142 , m_contextState(Suspended) |
| 139 , m_cachedSampleFrame(0) | 143 , m_cachedSampleFrame(0) |
| 140 { | 144 { |
| 141 m_didInitializeContextGraphMutex = true; | 145 m_didInitializeContextGraphMutex = true; |
| 142 // Create a new destination for offline rendering. | 146 // Create a new destination for offline rendering. |
| 143 m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampl eRate); | 147 m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampl eRate); |
| 144 if (m_renderTarget.get()) | 148 if (m_renderTarget.get()) |
| 145 m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTa rget.get()); | 149 m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTa rget.get()); |
| 146 | 150 |
| 147 initialize(); | 151 initialize(); |
| 148 } | 152 } |
| 149 | 153 |
| 150 AudioContext::~AudioContext() | 154 AudioContext::~AudioContext() |
| 151 { | 155 { |
| 152 #if DEBUG_AUDIONODE_REFERENCES | 156 #if DEBUG_AUDIONODE_REFERENCES |
| 153 fprintf(stderr, "%p: AudioContext::~AudioContext()\n", this); | 157 fprintf(stderr, "%p: AudioContext::~AudioContext()\n", this); |
| 154 #endif | 158 #endif |
| 155 // 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. | 159 // 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 ASSERT(!m_isInitialized); | 160 ASSERT(!m_isInitialized); |
| 157 ASSERT(!m_referencedNodes.size()); | 161 ASSERT(!m_referencedNodes.size()); |
| 158 ASSERT(!m_finishedNodes.size()); | 162 ASSERT(!m_finishedNodes.size()); |
| 159 ASSERT(!m_automaticPullNodes.size()); | 163 ASSERT(!m_automaticPullNodes.size()); |
| 160 if (m_automaticPullNodesNeedUpdating) | 164 if (m_automaticPullNodesNeedUpdating) |
| 161 m_renderingAutomaticPullNodes.resize(m_automaticPullNodes.size()); | 165 m_renderingAutomaticPullNodes.resize(m_automaticPullNodes.size()); |
| 162 ASSERT(!m_renderingAutomaticPullNodes.size()); | 166 ASSERT(!m_renderingAutomaticPullNodes.size()); |
| 163 ASSERT(!m_suspendResolvers.size()); | 167 ASSERT(!m_suspendResolvers.size()); |
| 164 ASSERT(!m_resumeResolvers.size()); | 168 ASSERT(!m_resumeResolvers.size()); |
| 169 ThreadState::current()->removeMarkingTask(this); | |
|
haraken
2015/02/06 07:57:23
Can we move this to AudioContext::uninitialize()?
tkent
2015/02/09 07:00:50
Yes. It's consistent because we call addMarkingTa
| |
| 165 } | 170 } |
| 166 | 171 |
| 167 void AudioContext::initialize() | 172 void AudioContext::initialize() |
| 168 { | 173 { |
| 169 if (isInitialized()) | 174 if (isInitialized()) |
| 170 return; | 175 return; |
| 171 | 176 |
| 177 ThreadState::current()->addMarkingTask(this); | |
| 172 FFTFrame::initialize(); | 178 FFTFrame::initialize(); |
| 173 m_listener = AudioListener::create(); | 179 m_listener = AudioListener::create(); |
| 174 | 180 |
| 175 if (m_destinationNode.get()) { | 181 if (m_destinationNode.get()) { |
| 176 m_destinationNode->initialize(); | 182 m_destinationNode->initialize(); |
| 177 | 183 |
| 178 if (!isOfflineContext()) { | 184 if (!isOfflineContext()) { |
| 179 // This starts the audio thread. The destination node's provideInput () method will now be called repeatedly to render audio. | 185 // 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". | 186 // 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. | 187 // NOTE: for now default AudioContext does not need an explicit star tRendering() call from JavaScript. |
| (...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 810 if (tryLock()) { | 816 if (tryLock()) { |
| 811 // Update the channel count mode. | 817 // Update the channel count mode. |
| 812 updateChangedChannelCountMode(); | 818 updateChangedChannelCountMode(); |
| 813 | 819 |
| 814 // Take care of AudioNode tasks where the tryLock() failed previously. | 820 // Take care of AudioNode tasks where the tryLock() failed previously. |
| 815 handleDeferredAudioNodeTasks(); | 821 handleDeferredAudioNodeTasks(); |
| 816 | 822 |
| 817 // Dynamically clean up nodes which are no longer needed. | 823 // Dynamically clean up nodes which are no longer needed. |
| 818 derefFinishedSourceNodes(); | 824 derefFinishedSourceNodes(); |
| 819 | 825 |
| 826 m_lastRemovableZombie = m_lastZombie; | |
| 827 | |
| 820 // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutpu ts. | 828 // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutpu ts. |
| 821 handleDirtyAudioSummingJunctions(); | 829 handleDirtyAudioSummingJunctions(); |
| 822 handleDirtyAudioNodeOutputs(); | 830 handleDirtyAudioNodeOutputs(); |
| 823 | 831 |
| 824 updateAutomaticPullNodes(); | 832 updateAutomaticPullNodes(); |
| 825 resolvePromisesForSuspend(); | 833 resolvePromisesForSuspend(); |
| 826 | 834 |
| 827 unlock(); | 835 unlock(); |
| 828 } | 836 } |
| 829 } | 837 } |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1103 m_offlineResolver->resolve(renderedBuffer); | 1111 m_offlineResolver->resolve(renderedBuffer); |
| 1104 } | 1112 } |
| 1105 } | 1113 } |
| 1106 | 1114 |
| 1107 void AudioContext::trace(Visitor* visitor) | 1115 void AudioContext::trace(Visitor* visitor) |
| 1108 { | 1116 { |
| 1109 visitor->trace(m_offlineResolver); | 1117 visitor->trace(m_offlineResolver); |
| 1110 visitor->trace(m_renderTarget); | 1118 visitor->trace(m_renderTarget); |
| 1111 visitor->trace(m_destinationNode); | 1119 visitor->trace(m_destinationNode); |
| 1112 visitor->trace(m_listener); | 1120 visitor->trace(m_listener); |
| 1113 // trace() can be called in AudioContext constructor, and | 1121 visitor->trace(m_referencedNodes); |
| 1114 // m_contextGraphMutex might be unavailable. | |
| 1115 if (m_didInitializeContextGraphMutex) { | |
| 1116 AutoLocker lock(this); | |
| 1117 visitor->trace(m_referencedNodes); | |
| 1118 } else { | |
| 1119 visitor->trace(m_referencedNodes); | |
| 1120 } | |
| 1121 visitor->trace(m_resumeResolvers); | 1122 visitor->trace(m_resumeResolvers); |
| 1122 visitor->trace(m_suspendResolvers); | 1123 visitor->trace(m_suspendResolvers); |
| 1123 visitor->trace(m_liveNodes); | 1124 visitor->trace(m_liveNodes); |
| 1124 visitor->trace(m_liveAudioSummingJunctions); | 1125 visitor->trace(m_liveAudioSummingJunctions); |
| 1125 RefCountedGarbageCollectedEventTargetWithInlineData<AudioContext>::trace(vis itor); | 1126 RefCountedGarbageCollectedEventTargetWithInlineData<AudioContext>::trace(vis itor); |
| 1126 ActiveDOMObject::trace(visitor); | 1127 ActiveDOMObject::trace(visitor); |
| 1127 } | 1128 } |
| 1128 | 1129 |
| 1129 void AudioContext::addChangedChannelCountMode(AudioNode* node) | 1130 void AudioContext::addChangedChannelCountMode(AudioNode* node) |
| 1130 { | 1131 { |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1148 (*k)->updateChannelCountMode(); | 1149 (*k)->updateChannelCountMode(); |
| 1149 | 1150 |
| 1150 m_deferredCountModeChange.clear(); | 1151 m_deferredCountModeChange.clear(); |
| 1151 } | 1152 } |
| 1152 | 1153 |
| 1153 SecurityOrigin* AudioContext::securityOrigin() const | 1154 SecurityOrigin* AudioContext::securityOrigin() const |
| 1154 { | 1155 { |
| 1155 return executionContext()->securityOrigin(); | 1156 return executionContext()->securityOrigin(); |
| 1156 } | 1157 } |
| 1157 | 1158 |
| 1159 void AudioContext::setLastZombie(void* object) | |
| 1160 { | |
| 1161 ASSERT(isGraphOwner()); | |
| 1162 m_lastZombie = object; | |
| 1163 } | |
| 1164 | |
| 1165 void AudioContext::willStartMarking(ThreadState& threadState) | |
|
haraken
2015/02/06 07:57:23
willStartMarking is called not only in the ZombieM
tkent
2015/02/09 07:00:50
It's ok.
There are two purposes of this hook:
* S
| |
| 1166 { | |
| 1167 lock(); | |
|
haraken
2015/02/06 07:57:23
What happens if a GC is triggered during AudioCont
tkent
2015/02/09 07:00:50
It won't happen. This task is registered after th
| |
| 1168 if (!m_lastRemovableZombie) | |
| 1169 return; | |
| 1170 if (m_lastZombie != m_lastRemovableZombie) | |
|
haraken
2015/02/06 07:57:23
I don't quite get what m_lastZombie and m_lastRemo
tkent
2015/02/09 07:00:50
We need to avoid the following scenario:
1. GC ha
| |
| 1171 return; | |
| 1172 threadState.purifyZombies(); | |
| 1173 m_lastZombie = nullptr; | |
| 1174 m_lastRemovableZombie = nullptr; | |
| 1175 } | |
| 1176 | |
| 1177 void AudioContext::didFinishMarking(ThreadState&) | |
| 1178 { | |
| 1179 unlock(); | |
| 1180 } | |
| 1181 | |
| 1158 } // namespace blink | 1182 } // namespace blink |
| 1159 | 1183 |
| 1160 #endif // ENABLE(WEB_AUDIO) | 1184 #endif // ENABLE(WEB_AUDIO) |
| OLD | NEW |