| 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_resampler.h" | 5 #include "media/audio/audio_output_resampler.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| 11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
| 12 #include "base/macros.h" | 12 #include "base/macros.h" |
| 13 #include "base/metrics/histogram_macros.h" | 13 #include "base/metrics/histogram_macros.h" |
| 14 #include "base/metrics/sparse_histogram.h" |
| 14 #include "base/numerics/safe_conversions.h" | 15 #include "base/numerics/safe_conversions.h" |
| 15 #include "base/single_thread_task_runner.h" | 16 #include "base/single_thread_task_runner.h" |
| 16 #include "base/trace_event/trace_event.h" | 17 #include "base/trace_event/trace_event.h" |
| 17 #include "build/build_config.h" | 18 #include "build/build_config.h" |
| 18 #include "media/audio/audio_output_proxy.h" | 19 #include "media/audio/audio_output_proxy.h" |
| 19 #include "media/audio/sample_rates.h" | 20 #include "media/audio/sample_rates.h" |
| 20 #include "media/base/audio_converter.h" | 21 #include "media/base/audio_converter.h" |
| 21 #include "media/base/limits.h" | 22 #include "media/base/limits.h" |
| 22 | 23 |
| 23 namespace media { | 24 namespace media { |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 UMA_HISTOGRAM_ENUMERATION( | 129 UMA_HISTOGRAM_ENUMERATION( |
| 129 "Media.FallbackHardwareAudioSamplesPerSecond", | 130 "Media.FallbackHardwareAudioSamplesPerSecond", |
| 130 asr, kAudioSampleRateMax + 1); | 131 asr, kAudioSampleRateMax + 1); |
| 131 } else { | 132 } else { |
| 132 UMA_HISTOGRAM_COUNTS( | 133 UMA_HISTOGRAM_COUNTS( |
| 133 "Media.FallbackHardwareAudioSamplesPerSecondUnexpected", | 134 "Media.FallbackHardwareAudioSamplesPerSecondUnexpected", |
| 134 output_params.sample_rate()); | 135 output_params.sample_rate()); |
| 135 } | 136 } |
| 136 } | 137 } |
| 137 | 138 |
| 139 // Record UMA statistics for input/output rebuffering. |
| 140 static void RecordRebufferingStats(const AudioParameters& input_params, |
| 141 const AudioParameters& output_params) { |
| 142 const int input_buffer_size = input_params.frames_per_buffer(); |
| 143 const int output_buffer_size = output_params.frames_per_buffer(); |
| 144 DCHECK_NE(0, input_buffer_size); |
| 145 DCHECK_NE(0, output_buffer_size); |
| 146 |
| 147 // Buffer size mismatch; see Media.Audio.Render.BrowserCallbackRegularity |
| 148 // histogram for explanation. |
| 149 int value = 0; |
| 150 if (input_buffer_size >= output_buffer_size) { |
| 151 // 0 if input size is a multiple of output size; otherwise -1. |
| 152 value = (input_buffer_size % output_buffer_size) ? -1 : 0; |
| 153 } else { |
| 154 value = (output_buffer_size / input_buffer_size - 1) * 2; |
| 155 if (output_buffer_size % input_buffer_size) { |
| 156 // One more callback is issued periodically. |
| 157 value += 1; |
| 158 } |
| 159 } |
| 160 |
| 161 const int value_cap = (4096 / 128 - 1) * 2 + 1; |
| 162 if (value > value_cap) |
| 163 value = value_cap; |
| 164 |
| 165 switch (input_params.latency_tag()) { |
| 166 case AudioLatency::LATENCY_EXACT_MS: |
| 167 UMA_HISTOGRAM_SPARSE_SLOWLY( |
| 168 "Media.Audio.Render.BrowserCallbackRegularity.LatencyExactMs", value); |
| 169 return; |
| 170 case AudioLatency::LATENCY_INTERACTIVE: |
| 171 UMA_HISTOGRAM_SPARSE_SLOWLY( |
| 172 "Media.Audio.Render.BrowserCallbackRegularity.LatencyInteractive", |
| 173 value); |
| 174 return; |
| 175 case AudioLatency::LATENCY_RTC: |
| 176 UMA_HISTOGRAM_SPARSE_SLOWLY( |
| 177 "Media.Audio.Render.BrowserCallbackRegularity.LatencyRtc", value); |
| 178 return; |
| 179 case AudioLatency::LATENCY_PLAYBACK: |
| 180 UMA_HISTOGRAM_SPARSE_SLOWLY( |
| 181 "Media.Audio.Render.BrowserCallbackRegularity.LatencyPlayback", |
| 182 value); |
| 183 return; |
| 184 default: |
| 185 DVLOG(1) << "Latency tag is not set"; |
| 186 } |
| 187 } |
| 188 |
| 138 // Converts low latency based |output_params| into high latency appropriate | 189 // Converts low latency based |output_params| into high latency appropriate |
| 139 // output parameters in error situations. | 190 // output parameters in error situations. |
| 140 void AudioOutputResampler::SetupFallbackParams() { | 191 void AudioOutputResampler::SetupFallbackParams() { |
| 141 // Only Windows has a high latency output driver that is not the same as the low | 192 // Only Windows has a high latency output driver that is not the same as the low |
| 142 // latency path. | 193 // latency path. |
| 143 #if defined(OS_WIN) | 194 #if defined(OS_WIN) |
| 144 // Choose AudioParameters appropriate for opening the device in high latency | 195 // Choose AudioParameters appropriate for opening the device in high latency |
| 145 // mode. |kMinLowLatencyFrameSize| is arbitrarily based on Pepper Flash's | 196 // mode. |kMinLowLatencyFrameSize| is arbitrarily based on Pepper Flash's |
| 146 // MAXIMUM frame size for low latency. | 197 // MAXIMUM frame size for low latency. |
| 147 static const int kMinLowLatencyFrameSize = 2048; | 198 static const int kMinLowLatencyFrameSize = 2048; |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 | 398 |
| 348 OnMoreDataConverter::OnMoreDataConverter(const AudioParameters& input_params, | 399 OnMoreDataConverter::OnMoreDataConverter(const AudioParameters& input_params, |
| 349 const AudioParameters& output_params) | 400 const AudioParameters& output_params) |
| 350 : io_ratio_(static_cast<double>(input_params.GetBytesPerSecond()) / | 401 : io_ratio_(static_cast<double>(input_params.GetBytesPerSecond()) / |
| 351 output_params.GetBytesPerSecond()), | 402 output_params.GetBytesPerSecond()), |
| 352 source_callback_(nullptr), | 403 source_callback_(nullptr), |
| 353 input_bytes_per_frame_(input_params.GetBytesPerFrame()), | 404 input_bytes_per_frame_(input_params.GetBytesPerFrame()), |
| 354 audio_converter_(input_params, output_params, false), | 405 audio_converter_(input_params, output_params, false), |
| 355 error_occurred_(false), | 406 error_occurred_(false), |
| 356 input_buffer_size_(input_params.frames_per_buffer()), | 407 input_buffer_size_(input_params.frames_per_buffer()), |
| 357 output_buffer_size_(output_params.frames_per_buffer()) {} | 408 output_buffer_size_(output_params.frames_per_buffer()) { |
| 409 RecordRebufferingStats(input_params, output_params); |
| 410 } |
| 358 | 411 |
| 359 OnMoreDataConverter::~OnMoreDataConverter() { | 412 OnMoreDataConverter::~OnMoreDataConverter() { |
| 360 // Ensure Stop() has been called so we don't end up with an AudioOutputStream | 413 // Ensure Stop() has been called so we don't end up with an AudioOutputStream |
| 361 // calling back into OnMoreData() after destruction. | 414 // calling back into OnMoreData() after destruction. |
| 362 CHECK(!source_callback_); | 415 CHECK(!source_callback_); |
| 363 } | 416 } |
| 364 | 417 |
| 365 void OnMoreDataConverter::Start( | 418 void OnMoreDataConverter::Start( |
| 366 AudioOutputStream::AudioSourceCallback* callback) { | 419 AudioOutputStream::AudioSourceCallback* callback) { |
| 367 CHECK(!source_callback_); | 420 CHECK(!source_callback_); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 dest->ZeroFramesPartial(frames, dest->frames() - frames); | 464 dest->ZeroFramesPartial(frames, dest->frames() - frames); |
| 412 return frames > 0 ? 1 : 0; | 465 return frames > 0 ? 1 : 0; |
| 413 } | 466 } |
| 414 | 467 |
| 415 void OnMoreDataConverter::OnError(AudioOutputStream* stream) { | 468 void OnMoreDataConverter::OnError(AudioOutputStream* stream) { |
| 416 error_occurred_ = true; | 469 error_occurred_ = true; |
| 417 source_callback_->OnError(stream); | 470 source_callback_->OnError(stream); |
| 418 } | 471 } |
| 419 | 472 |
| 420 } // namespace media | 473 } // namespace media |
| OLD | NEW |