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

Side by Side Diff: content/renderer/media/audio_device.cc

Issue 9104043: Monitor the IO message loop in the AudioDevice classes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 10 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/media/audio_device.h" 5 #include "content/renderer/media/audio_device.h"
6 6
7 #include "base/bind.h"
8 #include "base/debug/trace_event.h" 7 #include "base/debug/trace_event.h"
9 #include "base/message_loop.h" 8 #include "base/message_loop.h"
10 #include "base/threading/thread_restrictions.h" 9 #include "base/threading/thread_restrictions.h"
11 #include "base/time.h" 10 #include "base/time.h"
12 #include "content/common/child_process.h" 11 #include "content/common/child_process.h"
13 #include "content/common/media/audio_messages.h" 12 #include "content/common/media/audio_messages.h"
14 #include "content/common/view_messages.h" 13 #include "content/common/view_messages.h"
15 #include "content/renderer/render_thread_impl.h" 14 #include "content/renderer/render_thread_impl.h"
16 #include "media/audio/audio_output_controller.h" 15 #include "media/audio/audio_output_controller.h"
17 #include "media/audio/audio_util.h" 16 #include "media/audio/audio_util.h"
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 } 92 }
94 93
95 void AudioDevice::Start() { 94 void AudioDevice::Start() {
96 AudioParameters params; 95 AudioParameters params;
97 params.format = latency_format_; 96 params.format = latency_format_;
98 params.channels = channels_; 97 params.channels = channels_;
99 params.sample_rate = static_cast<int>(sample_rate_); 98 params.sample_rate = static_cast<int>(sample_rate_);
100 params.bits_per_sample = bits_per_sample_; 99 params.bits_per_sample = bits_per_sample_;
101 params.samples_per_packet = buffer_size_; 100 params.samples_per_packet = buffer_size_;
102 101
103 ChildProcess::current()->io_message_loop()->PostTask( 102 loop()->PostTask(FROM_HERE,
104 FROM_HERE,
105 base::Bind(&AudioDevice::InitializeOnIOThread, this, params)); 103 base::Bind(&AudioDevice::InitializeOnIOThread, this, params));
106 } 104 }
107 105
108 void AudioDevice::Stop() { 106 void AudioDevice::Stop() {
109 DCHECK(MessageLoop::current() != ChildProcess::current()->io_message_loop()); 107 DCHECK(!loop()->BelongsToCurrentThread());
110 108
111 // Stop and shutdown the audio thread from the IO thread. 109 // Stop and shutdown the audio thread from the IO thread.
112 // This operation must be synchronous for now since the |callback_| pointer 110 // This operation must be synchronous for now since the |callback_| pointer
113 // isn't ref counted and the object might go out of scope after Stop() 111 // isn't ref counted and the object might go out of scope after Stop()
114 // returns (and FireRenderCallback might dereference a bogus pointer). 112 // returns (and FireRenderCallback might dereference a bogus pointer).
115 // TODO(tommi): Add an Uninitialize() method to AudioRendererSink? 113 // TODO(tommi): Add an Uninitialize() method to AudioRendererSink?
116 base::WaitableEvent done(true, false); 114 base::WaitableEvent done(true, false);
117 ChildProcess::current()->io_message_loop()->PostTask( 115 if (loop()->PostTask(FROM_HERE,
118 FROM_HERE, 116 base::Bind(&AudioDevice::ShutDownOnIOThread, this, &done))) {
119 base::Bind(&AudioDevice::ShutDownOnIOThread, this, &done)); 117 done.Wait();
120 done.Wait(); 118 }
121 } 119 }
122 120
123 void AudioDevice::Play() { 121 void AudioDevice::Play() {
124 ChildProcess::current()->io_message_loop()->PostTask( 122 loop()->PostTask(FROM_HERE,
125 FROM_HERE,
126 base::Bind(&AudioDevice::PlayOnIOThread, this)); 123 base::Bind(&AudioDevice::PlayOnIOThread, this));
127 } 124 }
128 125
129 void AudioDevice::Pause(bool flush) { 126 void AudioDevice::Pause(bool flush) {
130 ChildProcess::current()->io_message_loop()->PostTask( 127 loop()->PostTask(FROM_HERE,
131 FROM_HERE,
132 base::Bind(&AudioDevice::PauseOnIOThread, this, flush)); 128 base::Bind(&AudioDevice::PauseOnIOThread, this, flush));
133 } 129 }
134 130
135 bool AudioDevice::SetVolume(double volume) { 131 bool AudioDevice::SetVolume(double volume) {
136 if (volume < 0 || volume > 1.0) 132 if (volume < 0 || volume > 1.0)
137 return false; 133 return false;
138 134
139 ChildProcess::current()->io_message_loop()->PostTask( 135 if (!loop()->PostTask(FROM_HERE,
140 FROM_HERE, 136 base::Bind(&AudioDevice::SetVolumeOnIOThread, this, volume))) {
141 base::Bind(&AudioDevice::SetVolumeOnIOThread, this, volume)); 137 return false;
138 }
142 139
143 volume_ = volume; 140 volume_ = volume;
144 141
145 return true; 142 return true;
146 } 143 }
147 144
148 void AudioDevice::GetVolume(double* volume) { 145 void AudioDevice::GetVolume(double* volume) {
149 // Return a locally cached version of the current scaling factor. 146 // Return a locally cached version of the current scaling factor.
150 *volume = volume_; 147 *volume = volume_;
151 } 148 }
152 149
153 void AudioDevice::InitializeOnIOThread(const AudioParameters& params) { 150 void AudioDevice::InitializeOnIOThread(const AudioParameters& params) {
154 DCHECK_EQ(MessageLoop::current(), ChildProcess::current()->io_message_loop()); 151 DCHECK(loop()->BelongsToCurrentThread());
155 // Make sure we don't create the stream more than once. 152 // Make sure we don't create the stream more than once.
156 DCHECK_EQ(0, stream_id_); 153 DCHECK_EQ(0, stream_id_);
157 if (stream_id_) 154 if (stream_id_)
158 return; 155 return;
159 156
160 stream_id_ = filter_->AddDelegate(this); 157 stream_id_ = filter_->AddDelegate(this);
161 Send(new AudioHostMsg_CreateStream(stream_id_, params, true)); 158 Send(new AudioHostMsg_CreateStream(stream_id_, params, true));
162 } 159 }
163 160
164 void AudioDevice::PlayOnIOThread() { 161 void AudioDevice::PlayOnIOThread() {
165 DCHECK_EQ(MessageLoop::current(), ChildProcess::current()->io_message_loop()); 162 DCHECK(loop()->BelongsToCurrentThread());
166 if (stream_id_ && is_started_) 163 if (stream_id_ && is_started_)
167 Send(new AudioHostMsg_PlayStream(stream_id_)); 164 Send(new AudioHostMsg_PlayStream(stream_id_));
168 else 165 else
169 play_on_start_ = true; 166 play_on_start_ = true;
170 } 167 }
171 168
172 void AudioDevice::PauseOnIOThread(bool flush) { 169 void AudioDevice::PauseOnIOThread(bool flush) {
173 DCHECK_EQ(MessageLoop::current(), ChildProcess::current()->io_message_loop()); 170 DCHECK(loop()->BelongsToCurrentThread());
174 if (stream_id_ && is_started_) { 171 if (stream_id_ && is_started_) {
175 Send(new AudioHostMsg_PauseStream(stream_id_)); 172 Send(new AudioHostMsg_PauseStream(stream_id_));
176 if (flush) 173 if (flush)
177 Send(new AudioHostMsg_FlushStream(stream_id_)); 174 Send(new AudioHostMsg_FlushStream(stream_id_));
178 } else { 175 } else {
179 // Note that |flush| isn't relevant here since this is the case where 176 // Note that |flush| isn't relevant here since this is the case where
180 // the stream is first starting. 177 // the stream is first starting.
181 play_on_start_ = false; 178 play_on_start_ = false;
182 } 179 }
183 } 180 }
184 181
185 void AudioDevice::ShutDownOnIOThread(base::WaitableEvent* signal) { 182 void AudioDevice::ShutDownOnIOThread(base::WaitableEvent* signal) {
186 DCHECK_EQ(MessageLoop::current(), ChildProcess::current()->io_message_loop()); 183 DCHECK(loop()->BelongsToCurrentThread());
187 184
188 // Make sure we don't call shutdown more than once. 185 // Make sure we don't call shutdown more than once.
189 if (stream_id_) { 186 if (stream_id_) {
190 is_started_ = false; 187 is_started_ = false;
191 188
192 filter_->RemoveDelegate(stream_id_); 189 filter_->RemoveDelegate(stream_id_);
193 Send(new AudioHostMsg_CloseStream(stream_id_)); 190 Send(new AudioHostMsg_CloseStream(stream_id_));
194 stream_id_ = 0; 191 stream_id_ = 0;
195 192
196 ShutDownAudioThread(); 193 ShutDownAudioThread();
197 } 194 }
198 195
199 signal->Signal(); 196 if (signal)
197 signal->Signal();
200 } 198 }
201 199
202 void AudioDevice::SetVolumeOnIOThread(double volume) { 200 void AudioDevice::SetVolumeOnIOThread(double volume) {
203 DCHECK_EQ(MessageLoop::current(), ChildProcess::current()->io_message_loop()); 201 DCHECK(loop()->BelongsToCurrentThread());
204 if (stream_id_) 202 if (stream_id_)
205 Send(new AudioHostMsg_SetVolume(stream_id_, volume)); 203 Send(new AudioHostMsg_SetVolume(stream_id_, volume));
206 } 204 }
207 205
208 void AudioDevice::OnRequestPacket(AudioBuffersState buffers_state) { 206 void AudioDevice::OnRequestPacket(AudioBuffersState buffers_state) {
209 // This method does not apply to the low-latency system. 207 // This method does not apply to the low-latency system.
210 } 208 }
211 209
212 void AudioDevice::OnStateChanged(AudioStreamState state) { 210 void AudioDevice::OnStateChanged(AudioStreamState state) {
213 if (state == kAudioStreamError) { 211 if (state == kAudioStreamError) {
214 DLOG(WARNING) << "AudioDevice::OnStateChanged(kError)"; 212 DLOG(WARNING) << "AudioDevice::OnStateChanged(kError)";
215 callback_->OnError(); 213 callback_->OnError();
216 } 214 }
217 } 215 }
218 216
219 void AudioDevice::OnCreated( 217 void AudioDevice::OnCreated(base::SharedMemoryHandle handle, uint32 length) {
220 base::SharedMemoryHandle handle, uint32 length) {
221 // Not needed in this simple implementation. 218 // Not needed in this simple implementation.
222 } 219 }
223 220
224 void AudioDevice::OnLowLatencyCreated( 221 void AudioDevice::OnLowLatencyCreated(
225 base::SharedMemoryHandle handle, 222 base::SharedMemoryHandle handle,
226 base::SyncSocket::Handle socket_handle, 223 base::SyncSocket::Handle socket_handle,
227 uint32 length) { 224 uint32 length) {
228 DCHECK_EQ(MessageLoop::current(), ChildProcess::current()->io_message_loop()); 225 DCHECK(loop()->BelongsToCurrentThread());
229 DCHECK_GE(length, buffer_size_ * sizeof(int16) * channels_); 226 DCHECK_GE(length, buffer_size_ * sizeof(int16) * channels_);
230 #if defined(OS_WIN) 227 #if defined(OS_WIN)
231 DCHECK(handle); 228 DCHECK(handle);
232 DCHECK(socket_handle); 229 DCHECK(socket_handle);
233 #else 230 #else
234 DCHECK_GE(handle.fd, 0); 231 DCHECK_GE(handle.fd, 0);
235 DCHECK_GE(socket_handle, 0); 232 DCHECK_GE(socket_handle, 0);
236 #endif 233 #endif
237 234
238 // Takes care of the case when Stop() is called before OnLowLatencyCreated(). 235 // Takes care of the case when Stop() is called before OnLowLatencyCreated().
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 // to the browser process as float, so we don't lose precision for 318 // to the browser process as float, so we don't lose precision for
322 // audio hardware which has better than 16bit precision. 319 // audio hardware which has better than 16bit precision.
323 media::InterleaveFloatToInt16(audio_data_, 320 media::InterleaveFloatToInt16(audio_data_,
324 data, 321 data,
325 buffer_size_); 322 buffer_size_);
326 } 323 }
327 return num_frames; 324 return num_frames;
328 } 325 }
329 326
330 void AudioDevice::ShutDownAudioThread() { 327 void AudioDevice::ShutDownAudioThread() {
331 DCHECK_EQ(MessageLoop::current(), ChildProcess::current()->io_message_loop()); 328 DCHECK(loop()->BelongsToCurrentThread());
332 329
333 if (audio_thread_.get()) { 330 if (audio_thread_.get()) {
334 // Close the socket to terminate the main thread function in the 331 // Close the socket to terminate the main thread function in the
335 // audio thread. 332 // audio thread.
336 audio_socket_->Shutdown(); // Stops blocking Receive calls. 333 audio_socket_->Shutdown(); // Stops blocking Receive calls.
337 // TODO(tommi): We must not do this from the IO thread. Fix. 334 // TODO(tommi): We must not do this from the IO thread. Fix.
338 base::ThreadRestrictions::ScopedAllowIO allow_wait; 335 base::ThreadRestrictions::ScopedAllowIO allow_wait;
339 audio_thread_->Join(); 336 audio_thread_->Join();
340 audio_thread_.reset(NULL); 337 audio_thread_.reset(NULL);
341 audio_socket_.reset(); 338 audio_socket_.reset();
342 } 339 }
343 } 340 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698