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 "media/audio/audio_output_controller.h" | 5 #include "media/audio/audio_output_controller.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/debug/trace_event.h" | 8 #include "base/debug/trace_event.h" |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
11 #include "base/threading/platform_thread.h" | 11 #include "base/threading/platform_thread.h" |
12 #include "base/time/time.h" | 12 #include "base/time/time.h" |
13 #include "build/build_config.h" | 13 #include "build/build_config.h" |
14 #include "media/audio/audio_util.h" | 14 #include "media/audio/audio_util.h" |
15 #include "media/audio/shared_memory_util.h" | |
16 #include "media/base/scoped_histogram_timer.h" | 15 #include "media/base/scoped_histogram_timer.h" |
17 | 16 |
18 using base::Time; | 17 using base::Time; |
19 using base::TimeDelta; | 18 using base::TimeDelta; |
20 | 19 |
21 namespace media { | 20 namespace media { |
22 | 21 |
23 // Time constant for AudioPowerMonitor. See AudioPowerMonitor ctor comments for | 22 // Time constant for AudioPowerMonitor. See AudioPowerMonitor ctor comments for |
24 // semantics. This value was arbitrarily chosen, but seems to work well. | 23 // semantics. This value was arbitrarily chosen, but seems to work well. |
25 static const int kPowerMeasurementTimeConstantMillis = 10; | 24 static const int kPowerMeasurementTimeConstantMillis = 10; |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 | 204 |
206 void AudioOutputController::DoPause() { | 205 void AudioOutputController::DoPause() { |
207 DCHECK(message_loop_->BelongsToCurrentThread()); | 206 DCHECK(message_loop_->BelongsToCurrentThread()); |
208 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PauseTime"); | 207 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PauseTime"); |
209 | 208 |
210 StopStream(); | 209 StopStream(); |
211 | 210 |
212 if (state_ != kPaused) | 211 if (state_ != kPaused) |
213 return; | 212 return; |
214 | 213 |
215 // Send a special pause mark to the low-latency audio thread. | 214 // Let the renderer know we've stopped. Necessary to let PPAPI clients know |
216 sync_reader_->UpdatePendingBytes(kPauseMark); | 215 // audio has been shutdown. TODO(dalecurtis): This stinks. PPAPI should have |
| 216 // a better way to know when it should exit PPB_Audio_Shared::Run(). |
| 217 sync_reader_->UpdatePendingBytes(-1); |
217 | 218 |
218 // Paused means silence follows. | 219 // Paused means silence follows. |
219 handler_->OnPowerMeasured(AudioPowerMonitor::zero_power(), false); | 220 handler_->OnPowerMeasured(AudioPowerMonitor::zero_power(), false); |
220 | 221 |
221 handler_->OnPaused(); | 222 handler_->OnPaused(); |
222 } | 223 } |
223 | 224 |
224 void AudioOutputController::DoClose() { | 225 void AudioOutputController::DoClose() { |
225 DCHECK(message_loop_->BelongsToCurrentThread()); | 226 DCHECK(message_loop_->BelongsToCurrentThread()); |
226 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.CloseTime"); | 227 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.CloseTime"); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 AudioBuffersState buffers_state) { | 261 AudioBuffersState buffers_state) { |
261 return OnMoreIOData(NULL, dest, buffers_state); | 262 return OnMoreIOData(NULL, dest, buffers_state); |
262 } | 263 } |
263 | 264 |
264 int AudioOutputController::OnMoreIOData(AudioBus* source, | 265 int AudioOutputController::OnMoreIOData(AudioBus* source, |
265 AudioBus* dest, | 266 AudioBus* dest, |
266 AudioBuffersState buffers_state) { | 267 AudioBuffersState buffers_state) { |
267 DisallowEntryToOnMoreIOData(); | 268 DisallowEntryToOnMoreIOData(); |
268 TRACE_EVENT0("audio", "AudioOutputController::OnMoreIOData"); | 269 TRACE_EVENT0("audio", "AudioOutputController::OnMoreIOData"); |
269 | 270 |
270 // The OS level audio APIs on Linux and Windows all have problems requesting | 271 sync_reader_->Read(source, dest); |
271 // data on a fixed interval. Sometimes they will issue calls back to back | |
272 // which can cause glitching, so wait until the renderer is ready. | |
273 // | |
274 // We also need to wait when diverting since the virtual stream will call this | |
275 // multiple times without waiting. | |
276 // | |
277 // NEVER wait on OSX unless a virtual stream is connected, otherwise we can | |
278 // end up hanging the entire OS. | |
279 // | |
280 // See many bugs for context behind this decision: http://crbug.com/170498, | |
281 // http://crbug.com/171651, http://crbug.com/174985, and more. | |
282 #if defined(OS_WIN) || defined(OS_LINUX) | |
283 const bool kShouldBlock = true; | |
284 #else | |
285 const bool kShouldBlock = diverting_to_stream_ != NULL; | |
286 #endif | |
287 | 272 |
288 const int frames = sync_reader_->Read(kShouldBlock, source, dest); | 273 const int frames = dest->frames(); |
289 DCHECK_LE(0, frames); | |
290 sync_reader_->UpdatePendingBytes( | 274 sync_reader_->UpdatePendingBytes( |
291 buffers_state.total_bytes() + frames * params_.GetBytesPerFrame()); | 275 buffers_state.total_bytes() + frames * params_.GetBytesPerFrame()); |
292 | 276 |
293 power_monitor_.Scan(*dest, frames); | 277 power_monitor_.Scan(*dest, frames); |
294 | 278 |
295 AllowEntryToOnMoreIOData(); | 279 AllowEntryToOnMoreIOData(); |
296 return frames; | 280 return frames; |
297 } | 281 } |
298 | 282 |
299 void AudioOutputController::OnError(AudioOutputStream* stream) { | 283 void AudioOutputController::OnError(AudioOutputStream* stream) { |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_)); | 381 DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_)); |
398 base::AtomicRefCountInc(&num_allowed_io_); | 382 base::AtomicRefCountInc(&num_allowed_io_); |
399 } | 383 } |
400 | 384 |
401 void AudioOutputController::DisallowEntryToOnMoreIOData() { | 385 void AudioOutputController::DisallowEntryToOnMoreIOData() { |
402 const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_); | 386 const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_); |
403 DCHECK(is_zero); | 387 DCHECK(is_zero); |
404 } | 388 } |
405 | 389 |
406 } // namespace media | 390 } // namespace media |
OLD | NEW |