Chromium Code Reviews| Index: media/audio/audio_output_controller.cc |
| diff --git a/media/audio/audio_output_controller.cc b/media/audio/audio_output_controller.cc |
| index 4f008c993db98b3527199fb0d6f0fa5b925c0407..435e68695ac156bd2fd5adeed9047d9919f7c68e 100644 |
| --- a/media/audio/audio_output_controller.cc |
| +++ b/media/audio/audio_output_controller.cc |
| @@ -57,7 +57,7 @@ AudioOutputController::AudioOutputController( |
| params.sample_rate(), |
| TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMillis)), |
| #endif |
| - number_polling_attempts_left_(0) { |
| + wedge_detected_(false) { |
| DCHECK(audio_manager); |
| DCHECK(handler_); |
| DCHECK(sync_reader_); |
| @@ -132,6 +132,7 @@ void AudioOutputController::SwitchOutputDevice( |
| void AudioOutputController::DoCreate(bool is_for_device_change) { |
| DCHECK(message_loop_->BelongsToCurrentThread()); |
| SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.CreateTime"); |
| + TRACE_EVENT0("audio", "AudioOutputController::DoCreate"); |
| // Close() can be called before DoCreate() is executed. |
| if (state_ == kClosed) |
| @@ -176,6 +177,7 @@ void AudioOutputController::DoCreate(bool is_for_device_change) { |
| void AudioOutputController::DoPlay() { |
| DCHECK(message_loop_->BelongsToCurrentThread()); |
| SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PlayTime"); |
| + TRACE_EVENT0("audio", "AudioOutputController::DoPlay"); |
| // We can start from created or paused state. |
| if (state_ != kCreated && state_ != kPaused) |
| @@ -196,7 +198,22 @@ void AudioOutputController::DoPlay() { |
| power_poll_callback_.callback().Run(); |
| #endif |
| - // We start the AudioOutputStream lazily. |
| + // For UMA tracking purposes, start the wedge detection timer. This allows us |
| + // to record statistics about the number of wedged playbacks in the field. |
| + // |
| + // WedgeCheck() will look to see if |wedge_detected_| is still true after the |
| + // timeout expires. Care must be taken to ensure the wedge check delay is |
| + // large enough that the value isn't queried while OnMoreDataIO() is setting |
| + // it. Currently, all buffers are less than 42ms, so anything larger is fine. |
|
scherkus (not reviewing)
2013/11/04 19:05:12
isn't the important # here how long it takes betwe
DaleCurtis
2013/11/04 21:11:37
Ah, yeah, you're right. The PlayTime UMA values sh
|
| + // |
| + // Timer self-manages its lifetime and WedgeCheck() will only fire if the |
|
scherkus (not reviewing)
2013/11/04 19:05:12
nit on comment accuracy: WedgeCheck() always runs,
DaleCurtis
2013/11/04 21:11:37
Done.
|
| + // state is still kPlaying. Additional Start() calls will invalidate the |
| + // previous timer. |
| + wedge_timer_.Start( |
| + FROM_HERE, TimeDelta::FromSeconds(1), this, |
| + &AudioOutputController::WedgeCheck); |
| + wedge_detected_ = true; |
|
scherkus (not reviewing)
2013/11/04 19:05:12
how about on_more_data_io_called_, since that's wh
DaleCurtis
2013/11/04 21:11:37
Done.
|
| + |
| AllowEntryToOnMoreIOData(); |
| stream_->Start(this); |
| @@ -233,6 +250,7 @@ void AudioOutputController::StopStream() { |
| void AudioOutputController::DoPause() { |
| DCHECK(message_loop_->BelongsToCurrentThread()); |
| SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PauseTime"); |
| + TRACE_EVENT0("audio", "AudioOutputController::DoPause"); |
| StopStream(); |
| @@ -255,6 +273,7 @@ void AudioOutputController::DoPause() { |
| void AudioOutputController::DoClose() { |
| DCHECK(message_loop_->BelongsToCurrentThread()); |
| SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.CloseTime"); |
| + TRACE_EVENT0("audio", "AudioOutputController::DoClose"); |
| if (state_ != kClosed) { |
| DoStopCloseAndClearStream(); |
| @@ -320,6 +339,11 @@ int AudioOutputController::OnMoreIOData(AudioBus* source, |
| DisallowEntryToOnMoreIOData(); |
| TRACE_EVENT0("audio", "AudioOutputController::OnMoreIOData"); |
| + // Indicate that we haven't wedged (at least not indefinitely, WedgeCheck() |
| + // may have already fired if OnMoreIOData() took an abnormal amount of time). |
| + if (wedge_detected_) |
|
scherkus (not reviewing)
2013/11/04 19:05:12
you don't need this if statement
DaleCurtis
2013/11/04 21:11:37
I was trying to avoid setting it if it's already s
|
| + wedge_detected_ = false; |
|
scherkus (not reviewing)
2013/11/04 19:05:12
IIRC OnMoreIOData() runs on a different thread vs.
DaleCurtis
2013/11/04 21:11:37
Correct, hence the comment above. It seemed overk
|
| + |
| sync_reader_->Read(source, dest); |
| const int frames = dest->frames(); |
| @@ -363,6 +387,7 @@ void AudioOutputController::DoStopCloseAndClearStream() { |
| void AudioOutputController::OnDeviceChange() { |
| DCHECK(message_loop_->BelongsToCurrentThread()); |
| SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.DeviceChangeTime"); |
| + TRACE_EVENT0("audio", "AudioOutputController::OnDeviceChange"); |
| // TODO(dalecurtis): Notify the renderer side that a device change has |
| // occurred. Currently querying the hardware information here will lead to |
| @@ -441,4 +466,14 @@ void AudioOutputController::DisallowEntryToOnMoreIOData() { |
| DCHECK(is_zero); |
| } |
| +void AudioOutputController::WedgeCheck() { |
| + DCHECK(message_loop_->BelongsToCurrentThread()); |
| + |
| + // If we should be playing and we haven't, that's a wedge. |
| + if (state_ == kPlaying) { |
| + UMA_HISTOGRAM_BOOLEAN( |
| + "Media.AudioOutputControllerWedgeDetected", wedge_detected_); |
|
jar (doing other things)
2013/11/04 07:03:43
This seems to use a histogram as a counter. With
DaleCurtis
2013/11/04 18:57:32
I'm confused with what you mean by == and !=. |we
|
| + } |
| +} |
| + |
| } // namespace media |