| 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/threading/platform_thread.h" | 10 #include "base/threading/platform_thread.h" |
| 11 #include "base/time.h" | 11 #include "base/time.h" |
| 12 #include "build/build_config.h" | 12 #include "build/build_config.h" |
| 13 #include "media/audio/audio_silence_detector.h" | 13 #include "media/audio/audio_silence_detector.h" |
| 14 #include "media/audio/audio_util.h" | 14 #include "media/audio/audio_util.h" |
| 15 #include "media/audio/shared_memory_util.h" | 15 #include "media/audio/shared_memory_util.h" |
| 16 #include "media/base/scoped_uma_timer.h" |
| 16 | 17 |
| 17 using base::Time; | 18 using base::Time; |
| 18 using base::TimeDelta; | 19 using base::TimeDelta; |
| 19 | 20 |
| 20 namespace media { | 21 namespace media { |
| 21 | 22 |
| 22 // Amount of contiguous time where all audio is silent before considering the | 23 // Amount of contiguous time where all audio is silent before considering the |
| 23 // stream to have transitioned and EventHandler::OnAudible() should be called. | 24 // stream to have transitioned and EventHandler::OnAudible() should be called. |
| 24 static const int kQuestionableSilencePeriodMillis = 50; | 25 static const int kQuestionableSilencePeriodMillis = 50; |
| 25 | 26 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 &AudioOutputController::DoClose, this), closed_task); | 96 &AudioOutputController::DoClose, this), closed_task); |
| 96 } | 97 } |
| 97 | 98 |
| 98 void AudioOutputController::SetVolume(double volume) { | 99 void AudioOutputController::SetVolume(double volume) { |
| 99 message_loop_->PostTask(FROM_HERE, base::Bind( | 100 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 100 &AudioOutputController::DoSetVolume, this, volume)); | 101 &AudioOutputController::DoSetVolume, this, volume)); |
| 101 } | 102 } |
| 102 | 103 |
| 103 void AudioOutputController::DoCreate(bool is_for_device_change) { | 104 void AudioOutputController::DoCreate(bool is_for_device_change) { |
| 104 DCHECK(message_loop_->BelongsToCurrentThread()); | 105 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 106 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.CreateTime"); |
| 105 | 107 |
| 106 // Close() can be called before DoCreate() is executed. | 108 // Close() can be called before DoCreate() is executed. |
| 107 if (state_ == kClosed) | 109 if (state_ == kClosed) |
| 108 return; | 110 return; |
| 109 | 111 |
| 110 DoStopCloseAndClearStream(); // Calls RemoveOutputDeviceChangeListener(). | 112 DoStopCloseAndClearStream(); // Calls RemoveOutputDeviceChangeListener(). |
| 111 DCHECK_EQ(kEmpty, state_); | 113 DCHECK_EQ(kEmpty, state_); |
| 112 | 114 |
| 113 stream_ = diverting_to_stream_ ? diverting_to_stream_ : | 115 stream_ = diverting_to_stream_ ? diverting_to_stream_ : |
| 114 audio_manager_->MakeAudioOutputStreamProxy(params_); | 116 audio_manager_->MakeAudioOutputStreamProxy(params_); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 DCHECK(!weak_this_.HasWeakPtrs()); | 163 DCHECK(!weak_this_.HasWeakPtrs()); |
| 162 message_loop_->PostDelayedTask( | 164 message_loop_->PostDelayedTask( |
| 163 FROM_HERE, | 165 FROM_HERE, |
| 164 base::Bind(&AudioOutputController::PollAndStartIfDataReady, | 166 base::Bind(&AudioOutputController::PollAndStartIfDataReady, |
| 165 weak_this_.GetWeakPtr()), | 167 weak_this_.GetWeakPtr()), |
| 166 TimeDelta::FromMilliseconds(kPollPauseInMilliseconds)); | 168 TimeDelta::FromMilliseconds(kPollPauseInMilliseconds)); |
| 167 } | 169 } |
| 168 | 170 |
| 169 void AudioOutputController::PollAndStartIfDataReady() { | 171 void AudioOutputController::PollAndStartIfDataReady() { |
| 170 DCHECK(message_loop_->BelongsToCurrentThread()); | 172 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 173 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PlayTime"); |
| 171 | 174 |
| 172 DCHECK_EQ(kStarting, state_); | 175 DCHECK_EQ(kStarting, state_); |
| 173 | 176 |
| 174 // If we are ready to start the stream, start it. | 177 // If we are ready to start the stream, start it. |
| 175 if (--number_polling_attempts_left_ == 0 || | 178 if (--number_polling_attempts_left_ == 0 || |
| 176 sync_reader_->DataReady()) { | 179 sync_reader_->DataReady()) { |
| 177 StartStream(); | 180 StartStream(); |
| 178 } else { | 181 } else { |
| 179 message_loop_->PostDelayedTask( | 182 message_loop_->PostDelayedTask( |
| 180 FROM_HERE, | 183 FROM_HERE, |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 stream_->Stop(); | 218 stream_->Stop(); |
| 216 DisallowEntryToOnMoreIOData(); | 219 DisallowEntryToOnMoreIOData(); |
| 217 silence_detector_->Stop(true); | 220 silence_detector_->Stop(true); |
| 218 silence_detector_.reset(); | 221 silence_detector_.reset(); |
| 219 state_ = kPaused; | 222 state_ = kPaused; |
| 220 } | 223 } |
| 221 } | 224 } |
| 222 | 225 |
| 223 void AudioOutputController::DoPause() { | 226 void AudioOutputController::DoPause() { |
| 224 DCHECK(message_loop_->BelongsToCurrentThread()); | 227 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 228 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PauseTime"); |
| 225 | 229 |
| 226 StopStream(); | 230 StopStream(); |
| 227 | 231 |
| 228 if (state_ != kPaused) | 232 if (state_ != kPaused) |
| 229 return; | 233 return; |
| 230 | 234 |
| 231 // Send a special pause mark to the low-latency audio thread. | 235 // Send a special pause mark to the low-latency audio thread. |
| 232 sync_reader_->UpdatePendingBytes(kPauseMark); | 236 sync_reader_->UpdatePendingBytes(kPauseMark); |
| 233 | 237 |
| 234 handler_->OnPaused(); | 238 handler_->OnPaused(); |
| 235 } | 239 } |
| 236 | 240 |
| 237 void AudioOutputController::DoClose() { | 241 void AudioOutputController::DoClose() { |
| 238 DCHECK(message_loop_->BelongsToCurrentThread()); | 242 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 243 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.CloseTime"); |
| 239 | 244 |
| 240 if (state_ != kClosed) { | 245 if (state_ != kClosed) { |
| 241 DoStopCloseAndClearStream(); | 246 DoStopCloseAndClearStream(); |
| 242 sync_reader_->Close(); | 247 sync_reader_->Close(); |
| 243 state_ = kClosed; | 248 state_ = kClosed; |
| 244 } | 249 } |
| 245 } | 250 } |
| 246 | 251 |
| 247 void AudioOutputController::DoSetVolume(double volume) { | 252 void AudioOutputController::DoSetVolume(double volume) { |
| 248 DCHECK(message_loop_->BelongsToCurrentThread()); | 253 DCHECK(message_loop_->BelongsToCurrentThread()); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 if (stream_ == diverting_to_stream_) | 339 if (stream_ == diverting_to_stream_) |
| 335 diverting_to_stream_ = NULL; | 340 diverting_to_stream_ = NULL; |
| 336 stream_ = NULL; | 341 stream_ = NULL; |
| 337 } | 342 } |
| 338 | 343 |
| 339 state_ = kEmpty; | 344 state_ = kEmpty; |
| 340 } | 345 } |
| 341 | 346 |
| 342 void AudioOutputController::OnDeviceChange() { | 347 void AudioOutputController::OnDeviceChange() { |
| 343 DCHECK(message_loop_->BelongsToCurrentThread()); | 348 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 349 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.DeviceChangeTime"); |
| 344 | 350 |
| 345 // TODO(dalecurtis): Notify the renderer side that a device change has | 351 // TODO(dalecurtis): Notify the renderer side that a device change has |
| 346 // occurred. Currently querying the hardware information here will lead to | 352 // occurred. Currently querying the hardware information here will lead to |
| 347 // crashes on OSX. See http://crbug.com/158170. | 353 // crashes on OSX. See http://crbug.com/158170. |
| 348 | 354 |
| 349 // Recreate the stream (DoCreate() will first shut down an existing stream). | 355 // Recreate the stream (DoCreate() will first shut down an existing stream). |
| 350 // Exit if we ran into an error. | 356 // Exit if we ran into an error. |
| 351 const State original_state = state_; | 357 const State original_state = state_; |
| 352 DoCreate(true); | 358 DoCreate(true); |
| 353 if (!stream_ || state_ == kError) | 359 if (!stream_ || state_ == kError) |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_)); | 420 DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_)); |
| 415 base::AtomicRefCountInc(&num_allowed_io_); | 421 base::AtomicRefCountInc(&num_allowed_io_); |
| 416 } | 422 } |
| 417 | 423 |
| 418 void AudioOutputController::DisallowEntryToOnMoreIOData() { | 424 void AudioOutputController::DisallowEntryToOnMoreIOData() { |
| 419 const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_); | 425 const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_); |
| 420 DCHECK(is_zero); | 426 DCHECK(is_zero); |
| 421 } | 427 } |
| 422 | 428 |
| 423 } // namespace media | 429 } // namespace media |
| OLD | NEW |