| 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.h" | 9 #include "base/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.h" | 12 #include "base/time.h" |
| 13 #include "build/build_config.h" | 13 #include "build/build_config.h" |
| 14 #include "media/audio/audio_silence_detector.h" | 14 #include "media/audio/audio_silence_detector.h" |
| 15 #include "media/audio/audio_util.h" | 15 #include "media/audio/audio_util.h" |
| 16 #include "media/audio/shared_memory_util.h" | 16 #include "media/audio/shared_memory_util.h" |
| 17 #include "media/base/scoped_histogram_timer.h" |
| 17 | 18 |
| 18 using base::Time; | 19 using base::Time; |
| 19 using base::TimeDelta; | 20 using base::TimeDelta; |
| 20 | 21 |
| 21 namespace media { | 22 namespace media { |
| 22 | 23 |
| 23 // Amount of contiguous time where all audio is silent before considering the | 24 // Amount of contiguous time where all audio is silent before considering the |
| 24 // stream to have transitioned and EventHandler::OnAudible() should be called. | 25 // stream to have transitioned and EventHandler::OnAudible() should be called. |
| 25 static const int kQuestionableSilencePeriodMillis = 50; | 26 static const int kQuestionableSilencePeriodMillis = 50; |
| 26 | 27 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 &AudioOutputController::DoClose, this), closed_task); | 97 &AudioOutputController::DoClose, this), closed_task); |
| 97 } | 98 } |
| 98 | 99 |
| 99 void AudioOutputController::SetVolume(double volume) { | 100 void AudioOutputController::SetVolume(double volume) { |
| 100 message_loop_->PostTask(FROM_HERE, base::Bind( | 101 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 101 &AudioOutputController::DoSetVolume, this, volume)); | 102 &AudioOutputController::DoSetVolume, this, volume)); |
| 102 } | 103 } |
| 103 | 104 |
| 104 void AudioOutputController::DoCreate(bool is_for_device_change) { | 105 void AudioOutputController::DoCreate(bool is_for_device_change) { |
| 105 DCHECK(message_loop_->BelongsToCurrentThread()); | 106 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 107 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.CreateTime"); |
| 106 | 108 |
| 107 // Close() can be called before DoCreate() is executed. | 109 // Close() can be called before DoCreate() is executed. |
| 108 if (state_ == kClosed) | 110 if (state_ == kClosed) |
| 109 return; | 111 return; |
| 110 | 112 |
| 111 DoStopCloseAndClearStream(); // Calls RemoveOutputDeviceChangeListener(). | 113 DoStopCloseAndClearStream(); // Calls RemoveOutputDeviceChangeListener(). |
| 112 DCHECK_EQ(kEmpty, state_); | 114 DCHECK_EQ(kEmpty, state_); |
| 113 | 115 |
| 114 stream_ = diverting_to_stream_ ? diverting_to_stream_ : | 116 stream_ = diverting_to_stream_ ? diverting_to_stream_ : |
| 115 audio_manager_->MakeAudioOutputStreamProxy(params_); | 117 audio_manager_->MakeAudioOutputStreamProxy(params_); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 DCHECK(!weak_this_.HasWeakPtrs()); | 164 DCHECK(!weak_this_.HasWeakPtrs()); |
| 163 message_loop_->PostDelayedTask( | 165 message_loop_->PostDelayedTask( |
| 164 FROM_HERE, | 166 FROM_HERE, |
| 165 base::Bind(&AudioOutputController::PollAndStartIfDataReady, | 167 base::Bind(&AudioOutputController::PollAndStartIfDataReady, |
| 166 weak_this_.GetWeakPtr()), | 168 weak_this_.GetWeakPtr()), |
| 167 TimeDelta::FromMilliseconds(kPollPauseInMilliseconds)); | 169 TimeDelta::FromMilliseconds(kPollPauseInMilliseconds)); |
| 168 } | 170 } |
| 169 | 171 |
| 170 void AudioOutputController::PollAndStartIfDataReady() { | 172 void AudioOutputController::PollAndStartIfDataReady() { |
| 171 DCHECK(message_loop_->BelongsToCurrentThread()); | 173 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 174 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PlayTime"); |
| 172 | 175 |
| 173 DCHECK_EQ(kStarting, state_); | 176 DCHECK_EQ(kStarting, state_); |
| 174 | 177 |
| 175 // If we are ready to start the stream, start it. | 178 // If we are ready to start the stream, start it. |
| 176 if (--number_polling_attempts_left_ == 0 || | 179 if (--number_polling_attempts_left_ == 0 || |
| 177 sync_reader_->DataReady()) { | 180 sync_reader_->DataReady()) { |
| 178 StartStream(); | 181 StartStream(); |
| 179 } else { | 182 } else { |
| 180 message_loop_->PostDelayedTask( | 183 message_loop_->PostDelayedTask( |
| 181 FROM_HERE, | 184 FROM_HERE, |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 stream_->Stop(); | 219 stream_->Stop(); |
| 217 DisallowEntryToOnMoreIOData(); | 220 DisallowEntryToOnMoreIOData(); |
| 218 silence_detector_->Stop(true); | 221 silence_detector_->Stop(true); |
| 219 silence_detector_.reset(); | 222 silence_detector_.reset(); |
| 220 state_ = kPaused; | 223 state_ = kPaused; |
| 221 } | 224 } |
| 222 } | 225 } |
| 223 | 226 |
| 224 void AudioOutputController::DoPause() { | 227 void AudioOutputController::DoPause() { |
| 225 DCHECK(message_loop_->BelongsToCurrentThread()); | 228 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 229 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PauseTime"); |
| 226 | 230 |
| 227 StopStream(); | 231 StopStream(); |
| 228 | 232 |
| 229 if (state_ != kPaused) | 233 if (state_ != kPaused) |
| 230 return; | 234 return; |
| 231 | 235 |
| 232 // Send a special pause mark to the low-latency audio thread. | 236 // Send a special pause mark to the low-latency audio thread. |
| 233 sync_reader_->UpdatePendingBytes(kPauseMark); | 237 sync_reader_->UpdatePendingBytes(kPauseMark); |
| 234 | 238 |
| 235 handler_->OnPaused(); | 239 handler_->OnPaused(); |
| 236 } | 240 } |
| 237 | 241 |
| 238 void AudioOutputController::DoClose() { | 242 void AudioOutputController::DoClose() { |
| 239 DCHECK(message_loop_->BelongsToCurrentThread()); | 243 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 244 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.CloseTime"); |
| 240 | 245 |
| 241 if (state_ != kClosed) { | 246 if (state_ != kClosed) { |
| 242 DoStopCloseAndClearStream(); | 247 DoStopCloseAndClearStream(); |
| 243 sync_reader_->Close(); | 248 sync_reader_->Close(); |
| 244 state_ = kClosed; | 249 state_ = kClosed; |
| 245 } | 250 } |
| 246 } | 251 } |
| 247 | 252 |
| 248 void AudioOutputController::DoSetVolume(double volume) { | 253 void AudioOutputController::DoSetVolume(double volume) { |
| 249 DCHECK(message_loop_->BelongsToCurrentThread()); | 254 DCHECK(message_loop_->BelongsToCurrentThread()); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 if (stream_ == diverting_to_stream_) | 361 if (stream_ == diverting_to_stream_) |
| 357 diverting_to_stream_ = NULL; | 362 diverting_to_stream_ = NULL; |
| 358 stream_ = NULL; | 363 stream_ = NULL; |
| 359 } | 364 } |
| 360 | 365 |
| 361 state_ = kEmpty; | 366 state_ = kEmpty; |
| 362 } | 367 } |
| 363 | 368 |
| 364 void AudioOutputController::OnDeviceChange() { | 369 void AudioOutputController::OnDeviceChange() { |
| 365 DCHECK(message_loop_->BelongsToCurrentThread()); | 370 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 371 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.DeviceChangeTime"); |
| 366 | 372 |
| 367 // TODO(dalecurtis): Notify the renderer side that a device change has | 373 // TODO(dalecurtis): Notify the renderer side that a device change has |
| 368 // occurred. Currently querying the hardware information here will lead to | 374 // occurred. Currently querying the hardware information here will lead to |
| 369 // crashes on OSX. See http://crbug.com/158170. | 375 // crashes on OSX. See http://crbug.com/158170. |
| 370 | 376 |
| 371 // Recreate the stream (DoCreate() will first shut down an existing stream). | 377 // Recreate the stream (DoCreate() will first shut down an existing stream). |
| 372 // Exit if we ran into an error. | 378 // Exit if we ran into an error. |
| 373 const State original_state = state_; | 379 const State original_state = state_; |
| 374 DoCreate(true); | 380 DoCreate(true); |
| 375 if (!stream_ || state_ == kError) | 381 if (!stream_ || state_ == kError) |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 436 DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_)); | 442 DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_)); |
| 437 base::AtomicRefCountInc(&num_allowed_io_); | 443 base::AtomicRefCountInc(&num_allowed_io_); |
| 438 } | 444 } |
| 439 | 445 |
| 440 void AudioOutputController::DisallowEntryToOnMoreIOData() { | 446 void AudioOutputController::DisallowEntryToOnMoreIOData() { |
| 441 const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_); | 447 const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_); |
| 442 DCHECK(is_zero); | 448 DCHECK(is_zero); |
| 443 } | 449 } |
| 444 | 450 |
| 445 } // namespace media | 451 } // namespace media |
| OLD | NEW |