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 |