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 |