| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/mac/audio_auhal_mac.h" | 5 #include "media/audio/mac/audio_auhal_mac.h" |
| 6 | 6 |
| 7 #include <CoreServices/CoreServices.h> | 7 #include <CoreServices/CoreServices.h> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 // Use a cancellable closure so that if Stop() is called before Start() | 142 // Use a cancellable closure so that if Stop() is called before Start() |
| 143 // actually runs, we can cancel the pending start. | 143 // actually runs, we can cancel the pending start. |
| 144 deferred_start_cb_.Reset( | 144 deferred_start_cb_.Reset( |
| 145 base::Bind(&AUHALStream::Start, base::Unretained(this), callback)); | 145 base::Bind(&AUHALStream::Start, base::Unretained(this), callback)); |
| 146 manager_->GetTaskRunner()->PostDelayedTask( | 146 manager_->GetTaskRunner()->PostDelayedTask( |
| 147 FROM_HERE, deferred_start_cb_.callback(), base::TimeDelta::FromSeconds( | 147 FROM_HERE, deferred_start_cb_.callback(), base::TimeDelta::FromSeconds( |
| 148 AudioManagerMac::kStartDelayInSecsForPowerEvents)); | 148 AudioManagerMac::kStartDelayInSecsForPowerEvents)); |
| 149 return; | 149 return; |
| 150 } | 150 } |
| 151 | 151 |
| 152 ReportAndResetStats(); | |
| 153 | |
| 154 stopped_ = false; | 152 stopped_ = false; |
| 155 audio_fifo_.reset(); | 153 audio_fifo_.reset(); |
| 156 { | 154 { |
| 157 base::AutoLock auto_lock(source_lock_); | 155 base::AutoLock auto_lock(source_lock_); |
| 158 source_ = callback; | 156 source_ = callback; |
| 159 } | 157 } |
| 160 | 158 |
| 161 OSStatus result = AudioOutputUnitStart(audio_unit_); | 159 OSStatus result = AudioOutputUnitStart(audio_unit_); |
| 162 if (result == noErr) | 160 if (result == noErr) |
| 163 return; | 161 return; |
| 164 | 162 |
| 165 Stop(); | 163 Stop(); |
| 166 OSSTATUS_DLOG(ERROR, result) << "AudioOutputUnitStart() failed."; | 164 OSSTATUS_DLOG(ERROR, result) << "AudioOutputUnitStart() failed."; |
| 167 callback->OnError(this); | 165 callback->OnError(this); |
| 168 } | 166 } |
| 169 | 167 |
| 170 void AUHALStream::Stop() { | 168 void AUHALStream::Stop() { |
| 171 DCHECK(thread_checker_.CalledOnValidThread()); | 169 DCHECK(thread_checker_.CalledOnValidThread()); |
| 172 deferred_start_cb_.Cancel(); | 170 deferred_start_cb_.Cancel(); |
| 173 if (stopped_) | 171 if (stopped_) |
| 174 return; | 172 return; |
| 175 | 173 |
| 176 OSStatus result = AudioOutputUnitStop(audio_unit_); | 174 OSStatus result = AudioOutputUnitStop(audio_unit_); |
| 177 OSSTATUS_DLOG_IF(ERROR, result != noErr, result) | 175 OSSTATUS_DLOG_IF(ERROR, result != noErr, result) |
| 178 << "AudioOutputUnitStop() failed."; | 176 << "AudioOutputUnitStop() failed."; |
| 179 if (result != noErr) | 177 if (result != noErr) |
| 180 source_->OnError(this); | 178 source_->OnError(this); |
| 181 | 179 |
| 180 ReportAndResetStats(); |
| 181 |
| 182 base::AutoLock auto_lock(source_lock_); | 182 base::AutoLock auto_lock(source_lock_); |
| 183 source_ = NULL; | 183 source_ = NULL; |
| 184 stopped_ = true; | 184 stopped_ = true; |
| 185 } | 185 } |
| 186 | 186 |
| 187 void AUHALStream::SetVolume(double volume) { | 187 void AUHALStream::SetVolume(double volume) { |
| 188 volume_ = static_cast<float>(volume); | 188 volume_ = static_cast<float>(volume); |
| 189 } | 189 } |
| 190 | 190 |
| 191 void AUHALStream::GetVolume(double* volume) { | 191 void AUHALStream::GetVolume(double* volume) { |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 largest_glitch_frames_ = lost_frames; | 364 largest_glitch_frames_ = lost_frames; |
| 365 ++glitches_detected_; | 365 ++glitches_detected_; |
| 366 } | 366 } |
| 367 } | 367 } |
| 368 | 368 |
| 369 // Store the last sample time for use next time we get called back. | 369 // Store the last sample time for use next time we get called back. |
| 370 last_sample_time_ = timestamp->mSampleTime; | 370 last_sample_time_ = timestamp->mSampleTime; |
| 371 } | 371 } |
| 372 | 372 |
| 373 void AUHALStream::ReportAndResetStats() { | 373 void AUHALStream::ReportAndResetStats() { |
| 374 if (!last_sample_time_) |
| 375 return; // No stats gathered to report. |
| 376 |
| 374 // A value of 0 indicates that we got the buffer size we asked for. | 377 // A value of 0 indicates that we got the buffer size we asked for. |
| 375 UMA_HISTOGRAM_COUNTS("Media.Audio.Render.FramesRequested", | 378 UMA_HISTOGRAM_COUNTS("Media.Audio.Render.FramesRequested", |
| 376 number_of_frames_requested_); | 379 number_of_frames_requested_); |
| 377 // Even if there aren't any glitches, we want to record it to get a feel for | 380 // Even if there aren't any glitches, we want to record it to get a feel for |
| 378 // how often we get no glitches vs the alternative. | 381 // how often we get no glitches vs the alternative. |
| 379 UMA_HISTOGRAM_COUNTS("Media.Audio.Render.Glitches", glitches_detected_); | 382 UMA_HISTOGRAM_CUSTOM_COUNTS("Media.Audio.Render.Glitches", glitches_detected_, |
| 383 0, 999999, 100); |
| 380 | 384 |
| 381 if (glitches_detected_ != 0) { | 385 if (glitches_detected_ != 0) { |
| 382 auto lost_frames_ms = (total_lost_frames_ * 1000) / params_.sample_rate(); | 386 auto lost_frames_ms = (total_lost_frames_ * 1000) / params_.sample_rate(); |
| 383 UMA_HISTOGRAM_COUNTS("Media.Audio.Render.LostFramesInMs", lost_frames_ms); | 387 UMA_HISTOGRAM_COUNTS("Media.Audio.Render.LostFramesInMs", lost_frames_ms); |
| 384 auto largest_glitch_ms = | 388 auto largest_glitch_ms = |
| 385 (largest_glitch_frames_ * 1000) / params_.sample_rate(); | 389 (largest_glitch_frames_ * 1000) / params_.sample_rate(); |
| 386 UMA_HISTOGRAM_COUNTS("Media.Audio.Render.LargestGlitchMs", | 390 UMA_HISTOGRAM_COUNTS("Media.Audio.Render.LargestGlitchMs", |
| 387 largest_glitch_ms); | 391 largest_glitch_ms); |
| 388 DLOG(WARNING) << "Total glitches=" << glitches_detected_ | 392 DLOG(WARNING) << "Total glitches=" << glitches_detected_ |
| 389 << ". Total frames lost=" << total_lost_frames_ << " (" | 393 << ". Total frames lost=" << total_lost_frames_ << " (" |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 533 OSStatus result = AudioUnitUninitialize(audio_unit_); | 537 OSStatus result = AudioUnitUninitialize(audio_unit_); |
| 534 OSSTATUS_DLOG_IF(ERROR, result != noErr, result) | 538 OSSTATUS_DLOG_IF(ERROR, result != noErr, result) |
| 535 << "AudioUnitUninitialize() failed."; | 539 << "AudioUnitUninitialize() failed."; |
| 536 result = AudioComponentInstanceDispose(audio_unit_); | 540 result = AudioComponentInstanceDispose(audio_unit_); |
| 537 OSSTATUS_DLOG_IF(ERROR, result != noErr, result) | 541 OSSTATUS_DLOG_IF(ERROR, result != noErr, result) |
| 538 << "AudioComponentInstanceDispose() failed."; | 542 << "AudioComponentInstanceDispose() failed."; |
| 539 audio_unit_ = 0; | 543 audio_unit_ = 0; |
| 540 } | 544 } |
| 541 | 545 |
| 542 } // namespace media | 546 } // namespace media |
| OLD | NEW |