Chromium Code Reviews| Index: media/audio/mac/audio_low_latency_input_mac.cc |
| diff --git a/media/audio/mac/audio_low_latency_input_mac.cc b/media/audio/mac/audio_low_latency_input_mac.cc |
| index b945d7ff445af864d4cfc6d0af32bc07577b6046..5eb91ee953922a0f05e23d9f33639675fdc1a952 100644 |
| --- a/media/audio/mac/audio_low_latency_input_mac.cc |
| +++ b/media/audio/mac/audio_low_latency_input_mac.cc |
| @@ -127,6 +127,7 @@ AUAudioInputStream::AUAudioInputStream(AudioManagerMac* manager, |
| AudioDeviceID audio_device_id) |
| : manager_(manager), |
| number_of_frames_(input_params.frames_per_buffer()), |
| + number_of_frames_requested_(0), |
| io_buffer_frame_size_(0), |
| sink_(nullptr), |
| audio_unit_(0), |
| @@ -140,7 +141,12 @@ AUAudioInputStream::AUAudioInputStream(AudioManagerMac* manager, |
| start_was_deferred_(false), |
| buffer_size_was_changed_(false), |
| audio_unit_render_has_worked_(false), |
| - device_listener_is_active_(false) { |
| + device_listener_is_active_(false), |
| + last_sample_time_(0.0), |
| + last_number_of_frames_(0), |
| + total_lost_frames_(0), |
| + largest_glitch_frames_(0), |
| + glitches_detected_(0) { |
| DCHECK(manager_); |
| // Set up the desired (output) format specified by the client. |
| @@ -183,6 +189,7 @@ AUAudioInputStream::AUAudioInputStream(AudioManagerMac* manager, |
| AUAudioInputStream::~AUAudioInputStream() { |
| DVLOG(1) << "~dtor"; |
| DCHECK(!device_listener_is_active_); |
| + ReportAndResetStats(); |
| } |
| // Obtain and open the AUHAL AudioOutputUnit for recording. |
| @@ -463,6 +470,7 @@ void AUAudioInputStream::Stop() { |
| DCHECK_EQ(result, noErr); |
| SetInputCallbackIsActive(false); |
| + ReportAndResetStats(); |
| sink_ = nullptr; |
| fifo_.Clear(); |
| io_buffer_frame_size_ = 0; |
| @@ -760,6 +768,15 @@ OSStatus AUAudioInputStream::OnDataIsAvailable( |
| OSStatus AUAudioInputStream::Provide(UInt32 number_of_frames, |
| AudioBufferList* io_data, |
| const AudioTimeStamp* time_stamp) { |
| + UpdateCaptureTimestamp(time_stamp); |
| + last_number_of_frames_ = number_of_frames; |
| + |
| + // TODO(grunell): We'll only care about the first buffer size change, any |
| + // further changes will be ignored. This is in line with output side stats. |
| + // It would be nice to have all changes reflected in UMA stats. |
| + if (number_of_frames != number_of_frames_ && number_of_frames_requested_ == 0) |
| + number_of_frames_requested_ = number_of_frames; |
| + |
| // Update the capture latency. |
| double capture_latency_frames = GetCaptureLatency(time_stamp); |
| @@ -1147,4 +1164,61 @@ void AUAudioInputStream::AddDevicePropertyChangesToUMA(bool startup_failed) { |
| device_property_changes_map_.clear(); |
| } |
| +void AUAudioInputStream::UpdateCaptureTimestamp( |
| + const AudioTimeStamp* timestamp) { |
| + if ((timestamp->mFlags & kAudioTimeStampSampleTimeValid) == 0) |
| + return; |
| + |
| + if (last_sample_time_) { |
| + DCHECK_NE(0U, last_number_of_frames_); |
| + UInt32 diff = |
| + static_cast<UInt32>(timestamp->mSampleTime - last_sample_time_); |
| + if (diff != last_number_of_frames_) { |
| + DCHECK_GT(diff, last_number_of_frames_); |
| + // We were given samples post what we expected. Update the glitch count |
| + // etc. and keep a record of the largest glitch. |
| + auto lost_frames = diff - last_number_of_frames_; |
| + total_lost_frames_ += lost_frames; |
| + if (lost_frames > largest_glitch_frames_) |
| + largest_glitch_frames_ = lost_frames; |
| + ++glitches_detected_; |
| + } |
| + } |
| + |
| + // Store the last sample time for use next time we get called back. |
| + last_sample_time_ = timestamp->mSampleTime; |
| +} |
| + |
| +void AUAudioInputStream::ReportAndResetStats() { |
| + if (last_sample_time_ == 0) |
| + return; // No stats gathered to report. |
| + |
| + // A value of 0 indicates that we got the buffer size we asked for. |
| + UMA_HISTOGRAM_COUNTS("Media.Audio.Capture.FramesRequested", |
| + number_of_frames_requested_); |
|
Mark P
2016/02/26 17:10:55
Is the standard COUNTS histogram the right range?
tommi (sloooow) - chröme
2016/02/26 17:27:43
These are audio "frames". There will be tens of t
Mark P
2016/02/26 18:37:19
Ah, thanks for the explanation. This seems alrigh
Henrik Grunell
2016/02/29 17:48:48
Actually, this is number of frames requested per c
|
| + // Even if there aren't any glitches, we want to record it to get a feel for |
| + // how often we get no glitches vs the alternative. |
| + UMA_HISTOGRAM_CUSTOM_COUNTS("Media.Audio.Capture.Glitches", |
| + glitches_detected_, 0, 999999, 100); |
|
Mark P
2016/02/26 17:10:55
With these parameters, the histogram looks basical
tommi (sloooow) - chröme
2016/02/26 17:27:43
This doubles the bucket count though - or am I mis
Mark P
2016/02/26 18:37:19
Ah, I see, you're using twice as many buckets as t
Henrik Grunell
2016/02/29 17:48:48
Tommi, do you have the rationale for this? (Since
|
| + |
| + if (glitches_detected_ != 0) { |
| + auto lost_frames_ms = (total_lost_frames_ * 1000) / format_.mSampleRate; |
| + UMA_HISTOGRAM_COUNTS("Media.Audio.Capture.LostFramesInMs", lost_frames_ms); |
|
Mark P
2016/02/26 17:10:55
Either use one of the standard UMA times histogram
Henrik Grunell
2016/02/29 17:48:48
Changed to LONG_TIMES and below to CUSTOM_TIMES wi
|
| + auto largest_glitch_ms = |
| + (largest_glitch_frames_ * 1000) / format_.mSampleRate; |
| + UMA_HISTOGRAM_COUNTS("Media.Audio.Capture.LargestGlitchMs", |
| + largest_glitch_ms); |
| + DLOG(WARNING) << "Total glitches=" << glitches_detected_ |
| + << ". Total frames lost=" << total_lost_frames_ << " (" |
| + << lost_frames_ms; |
| + } |
| + |
| + number_of_frames_requested_ = 0; |
| + glitches_detected_ = 0; |
| + last_sample_time_ = 0; |
| + last_number_of_frames_ = 0; |
| + total_lost_frames_ = 0; |
| + largest_glitch_frames_ = 0; |
| +} |
| + |
| } // namespace media |