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 |