OLD | NEW |
---|---|
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/debug/trace_event.h" | 7 #include "base/debug/trace_event.h" |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
9 #include "base/threading/thread_restrictions.h" | 9 #include "base/threading/thread_restrictions.h" |
10 #include "base/time.h" | 10 #include "base/time.h" |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
92 CHECK_EQ(0, stream_id_); | 92 CHECK_EQ(0, stream_id_); |
93 } | 93 } |
94 | 94 |
95 void AudioDevice::Start() { | 95 void AudioDevice::Start() { |
96 DCHECK(callback_) << "Initialize hasn't been called"; | 96 DCHECK(callback_) << "Initialize hasn't been called"; |
97 message_loop()->PostTask(FROM_HERE, | 97 message_loop()->PostTask(FROM_HERE, |
98 base::Bind(&AudioDevice::InitializeOnIOThread, this, audio_parameters_)); | 98 base::Bind(&AudioDevice::InitializeOnIOThread, this, audio_parameters_)); |
99 } | 99 } |
100 | 100 |
101 void AudioDevice::Stop() { | 101 void AudioDevice::Stop() { |
102 audio_thread_.Stop(MessageLoop::current()); | 102 audio_thread_.Stop(MessageLoop::current()); |
scherkus (not reviewing)
2012/02/29 21:10:15
remind me again.. what's the advantage to stopping
tommi (sloooow) - chröme
2012/02/29 21:22:13
The IO thread isn't allowed to join threads.
Howe
| |
103 | 103 |
104 message_loop()->PostTask(FROM_HERE, | 104 message_loop()->PostTask(FROM_HERE, |
105 base::Bind(&AudioDevice::ShutDownOnIOThread, this)); | 105 base::Bind(&AudioDevice::ShutDownOnIOThread, this)); |
106 } | 106 } |
107 | 107 |
108 void AudioDevice::Play() { | 108 void AudioDevice::Play() { |
109 message_loop()->PostTask(FROM_HERE, | 109 message_loop()->PostTask(FROM_HERE, |
110 base::Bind(&AudioDevice::PlayOnIOThread, this)); | 110 base::Bind(&AudioDevice::PlayOnIOThread, this)); |
111 } | 111 } |
112 | 112 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
171 | 171 |
172 // Make sure we don't call shutdown more than once. | 172 // Make sure we don't call shutdown more than once. |
173 if (stream_id_) { | 173 if (stream_id_) { |
174 is_started_ = false; | 174 is_started_ = false; |
175 | 175 |
176 filter_->RemoveDelegate(stream_id_); | 176 filter_->RemoveDelegate(stream_id_); |
177 Send(new AudioHostMsg_CloseStream(stream_id_)); | 177 Send(new AudioHostMsg_CloseStream(stream_id_)); |
178 stream_id_ = 0; | 178 stream_id_ = 0; |
179 } | 179 } |
180 | 180 |
181 // We can run into an issue where ShutDownOnIOThread is called right after | |
182 // OnStreamCreated is called in cases where Start/Stop are called before we | |
183 // get the OnStreamCreated callback. To handle that corner case, we call | |
184 // Stop(). In most cases, the thread will already be stopped. | |
185 audio_thread_.Stop(MessageLoop::current()); | |
scherkus (not reviewing)
2012/02/29 21:10:15
hold the phone...
combined with the change to Wil
tommi (sloooow) - chröme
2012/02/29 21:22:13
We shouldn't do that on the IO thread due to threa
| |
181 audio_callback_.reset(); | 186 audio_callback_.reset(); |
182 } | 187 } |
183 | 188 |
184 void AudioDevice::SetVolumeOnIOThread(double volume) { | 189 void AudioDevice::SetVolumeOnIOThread(double volume) { |
185 DCHECK(message_loop()->BelongsToCurrentThread()); | 190 DCHECK(message_loop()->BelongsToCurrentThread()); |
186 if (stream_id_) | 191 if (stream_id_) |
187 Send(new AudioHostMsg_SetVolume(stream_id_, volume)); | 192 Send(new AudioHostMsg_SetVolume(stream_id_, volume)); |
188 } | 193 } |
189 | 194 |
190 void AudioDevice::OnStateChanged(AudioStreamState state) { | 195 void AudioDevice::OnStateChanged(AudioStreamState state) { |
(...skipping 20 matching lines...) Expand all Loading... | |
211 #endif | 216 #endif |
212 | 217 |
213 // Takes care of the case when Stop() is called before OnStreamCreated(). | 218 // Takes care of the case when Stop() is called before OnStreamCreated(). |
214 if (!stream_id_) { | 219 if (!stream_id_) { |
215 base::SharedMemory::CloseHandle(handle); | 220 base::SharedMemory::CloseHandle(handle); |
216 // Close the socket handler. | 221 // Close the socket handler. |
217 base::SyncSocket socket(socket_handle); | 222 base::SyncSocket socket(socket_handle); |
218 return; | 223 return; |
219 } | 224 } |
220 | 225 |
226 DCHECK(audio_thread_.IsStopped()); | |
221 audio_callback_.reset(new AudioDevice::AudioThreadCallback(audio_parameters_, | 227 audio_callback_.reset(new AudioDevice::AudioThreadCallback(audio_parameters_, |
222 handle, length, callback_)); | 228 handle, length, callback_)); |
223 audio_thread_.Start(audio_callback_.get(), socket_handle, "AudioDevice"); | 229 audio_thread_.Start(audio_callback_.get(), socket_handle, "AudioDevice"); |
224 | 230 |
225 // We handle the case where Play() and/or Pause() may have been called | 231 // We handle the case where Play() and/or Pause() may have been called |
226 // multiple times before OnStreamCreated() gets called. | 232 // multiple times before OnStreamCreated() gets called. |
227 is_started_ = true; | 233 is_started_ = true; |
228 if (play_on_start_) | 234 if (play_on_start_) |
229 PlayOnIOThread(); | 235 PlayOnIOThread(); |
230 } | 236 } |
231 | 237 |
232 void AudioDevice::Send(IPC::Message* message) { | 238 void AudioDevice::Send(IPC::Message* message) { |
233 filter_->Send(message); | 239 filter_->Send(message); |
234 } | 240 } |
235 | 241 |
236 void AudioDevice::WillDestroyCurrentMessageLoop() { | 242 void AudioDevice::WillDestroyCurrentMessageLoop() { |
243 LOG(ERROR) << "IO loop going away before the audio device has been stopped"; | |
244 audio_thread_.Stop(NULL); | |
237 ShutDownOnIOThread(); | 245 ShutDownOnIOThread(); |
238 } | 246 } |
239 | 247 |
240 // AudioDevice::AudioThreadCallback | 248 // AudioDevice::AudioThreadCallback |
241 | 249 |
242 AudioDevice::AudioThreadCallback::AudioThreadCallback( | 250 AudioDevice::AudioThreadCallback::AudioThreadCallback( |
243 const AudioParameters& audio_parameters, | 251 const AudioParameters& audio_parameters, |
244 base::SharedMemoryHandle memory, | 252 base::SharedMemoryHandle memory, |
245 int memory_length, | 253 int memory_length, |
246 media::AudioRendererSink::RenderCallback* render_callback) | 254 media::AudioRendererSink::RenderCallback* render_callback) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
278 // to the browser process as float, so we don't lose precision for | 286 // to the browser process as float, so we don't lose precision for |
279 // audio hardware which has better than 16bit precision. | 287 // audio hardware which has better than 16bit precision. |
280 int16* data = reinterpret_cast<int16*>(shared_memory_.memory()); | 288 int16* data = reinterpret_cast<int16*>(shared_memory_.memory()); |
281 media::InterleaveFloatToInt16(audio_data_, data, | 289 media::InterleaveFloatToInt16(audio_data_, data, |
282 audio_parameters_.samples_per_packet); | 290 audio_parameters_.samples_per_packet); |
283 | 291 |
284 // Let the host know we are done. | 292 // Let the host know we are done. |
285 media::SetActualDataSizeInBytes(&shared_memory_, memory_length_, | 293 media::SetActualDataSizeInBytes(&shared_memory_, memory_length_, |
286 num_frames * audio_parameters_.channels * sizeof(data[0])); | 294 num_frames * audio_parameters_.channels * sizeof(data[0])); |
287 } | 295 } |
OLD | NEW |