Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(833)

Unified Diff: media/audio/audio_output_resampler.cc

Issue 10909151: Automatically fall back to non-low latency on open() failure. (Closed) Base URL: http://git.chromium.org/chromium/src.git@resampler2
Patch Set: Rebase. Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/audio/audio_output_resampler.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/audio/audio_output_resampler.cc
diff --git a/media/audio/audio_output_resampler.cc b/media/audio/audio_output_resampler.cc
index c52d340491ef9c09c7ce52e3cf8a3a89c64a9307..ae3af591ae0ae93444bc39693c28c2c5f390a39e 100644
--- a/media/audio/audio_output_resampler.cc
+++ b/media/audio/audio_output_resampler.cc
@@ -21,6 +21,7 @@
namespace media {
+// Record UMA statistics for hardware output configuration.
static void RecordStats(const AudioParameters& output_params) {
UMA_HISTOGRAM_ENUMERATION(
"Media.HardwareAudioBitsPerChannel", output_params.bits_per_sample(),
@@ -43,6 +44,30 @@ static void RecordStats(const AudioParameters& output_params) {
}
}
+// Record UMA statistics for hardware output configuration after fallback.
+static void RecordFallbackStats(const AudioParameters& output_params) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Media.FallbackHardwareAudioBitsPerChannel",
+ output_params.bits_per_sample(), limits::kMaxBitsPerSample);
+ UMA_HISTOGRAM_ENUMERATION(
+ "Media.FallbackHardwareAudioChannelLayout",
+ output_params.channel_layout(), CHANNEL_LAYOUT_MAX);
+ UMA_HISTOGRAM_ENUMERATION(
+ "Media.FallbackHardwareAudioChannelCount",
+ output_params.channels(), limits::kMaxChannels);
Chris Rogers 2012/09/12 18:45:45 Any chance we can record the buffer-size - frames_
+
+ AudioSampleRate asr = media::AsAudioSampleRate(output_params.sample_rate());
+ if (asr != kUnexpectedAudioSampleRate) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Media.FallbackHardwareAudioSamplesPerSecond",
+ asr, kUnexpectedAudioSampleRate);
+ } else {
+ UMA_HISTOGRAM_COUNTS(
+ "Media.FallbackHardwareAudioSamplesPerSecondUnexpected",
+ output_params.sample_rate());
+ }
+}
+
AudioOutputResampler::AudioOutputResampler(AudioManager* audio_manager,
const AudioParameters& input_params,
const AudioParameters& output_params,
@@ -50,47 +75,57 @@ AudioOutputResampler::AudioOutputResampler(AudioManager* audio_manager,
: AudioOutputDispatcher(audio_manager, input_params),
source_callback_(NULL),
io_ratio_(1),
- input_bytes_per_frame_(input_params.GetBytesPerFrame()),
- output_bytes_per_frame_(output_params.GetBytesPerFrame()),
- outstanding_audio_bytes_(0) {
+ close_delay_(close_delay),
+ outstanding_audio_bytes_(0),
+ output_params_(output_params) {
+ Initialize();
+ // Record UMA statistics for the hardware configuration.
+ RecordStats(output_params_);
+}
+
+AudioOutputResampler::~AudioOutputResampler() {}
+
+void AudioOutputResampler::Initialize() {
+ io_ratio_ = 1;
+
// TODO(dalecurtis): Add channel remixing. http://crbug.com/138762
- DCHECK_EQ(input_params.channels(), output_params.channels());
+ DCHECK_EQ(params_.channels(), output_params_.channels());
// Only resample or rebuffer if the input parameters don't match the output
// parameters to avoid any unnecessary work.
- if (input_params.channels() != output_params.channels() ||
- input_params.sample_rate() != output_params.sample_rate() ||
- input_params.bits_per_sample() != output_params.bits_per_sample() ||
- input_params.frames_per_buffer() != output_params.frames_per_buffer()) {
+ if (params_.channels() != output_params_.channels() ||
+ params_.sample_rate() != output_params_.sample_rate() ||
+ params_.bits_per_sample() != output_params_.bits_per_sample() ||
+ params_.frames_per_buffer() != output_params_.frames_per_buffer()) {
// Only resample if necessary since it's expensive.
- if (input_params.sample_rate() != output_params.sample_rate()) {
- DVLOG(1) << "Resampling from " << input_params.sample_rate() << " to "
- << output_params.sample_rate();
- double io_sample_rate_ratio = input_params.sample_rate() /
- static_cast<double>(output_params.sample_rate());
+ if (params_.sample_rate() != output_params_.sample_rate()) {
+ DVLOG(1) << "Resampling from " << params_.sample_rate() << " to "
+ << output_params_.sample_rate();
+ double io_sample_rate_ratio = params_.sample_rate() /
+ static_cast<double>(output_params_.sample_rate());
// Include the I/O resampling ratio in our global I/O ratio.
io_ratio_ *= io_sample_rate_ratio;
resampler_.reset(new MultiChannelResampler(
- output_params.channels(), io_sample_rate_ratio, base::Bind(
+ output_params_.channels(), io_sample_rate_ratio, base::Bind(
&AudioOutputResampler::ProvideInput, base::Unretained(this))));
}
// Include bits per channel differences.
- io_ratio_ *= static_cast<double>(input_params.bits_per_sample()) /
- output_params.bits_per_sample();
+ io_ratio_ *= static_cast<double>(params_.bits_per_sample()) /
+ output_params_.bits_per_sample();
// Include channel count differences.
- io_ratio_ *= static_cast<double>(input_params.channels()) /
- output_params.channels();
+ io_ratio_ *= static_cast<double>(params_.channels()) /
+ output_params_.channels();
// Since the resampler / output device may want a different buffer size than
// the caller asked for, we need to use a FIFO to ensure that both sides
// read in chunk sizes they're configured for.
- if (input_params.sample_rate() != output_params.sample_rate() ||
- input_params.frames_per_buffer() != output_params.frames_per_buffer()) {
- DVLOG(1) << "Rebuffering from " << input_params.frames_per_buffer()
- << " to " << output_params.frames_per_buffer();
+ if (params_.sample_rate() != output_params_.sample_rate() ||
+ params_.frames_per_buffer() != output_params_.frames_per_buffer()) {
+ DVLOG(1) << "Rebuffering from " << params_.frames_per_buffer()
+ << " to " << output_params_.frames_per_buffer();
audio_fifo_.reset(new AudioPullFifo(
- input_params.channels(), input_params.frames_per_buffer(), base::Bind(
+ params_.channels(), params_.frames_per_buffer(), base::Bind(
&AudioOutputResampler::SourceCallback_Locked,
base::Unretained(this))));
}
@@ -101,17 +136,42 @@ AudioOutputResampler::AudioOutputResampler(AudioManager* audio_manager,
// TODO(dalecurtis): All this code should be merged into AudioOutputMixer once
// we've stabilized the issues there.
dispatcher_ = new AudioOutputDispatcherImpl(
- audio_manager, output_params, close_delay);
-
- // Record UMA statistics for the hardware configuration.
- RecordStats(output_params);
+ audio_manager_, output_params_, close_delay_);
}
-AudioOutputResampler::~AudioOutputResampler() {}
-
bool AudioOutputResampler::OpenStream() {
- // TODO(dalecurtis): Automatically revert to high latency path if OpenStream()
- // fails; use default high latency output values + rebuffering / resampling.
+ if (dispatcher_->OpenStream()) {
+ UMA_HISTOGRAM_BOOLEAN("Media.FallbackToHighLatencyAudioPath", false);
+ return true;
+ }
+
+ // If we've already tried to open the stream in high latency mode, there's
+ // nothing more to be done.
+ if (output_params_.format() == AudioParameters::AUDIO_PCM_LINEAR)
+ return false;
+
+ DLOG(ERROR) << "Unable to open audio device in low latency mode. Falling "
+ << "back to high latency audio output.";
+
+ // Record UMA statistics about the hardware which triggered the failure so we
+ // can debug and triage later.
+ UMA_HISTOGRAM_BOOLEAN("Media.FallbackToHighLatencyAudioPath", true);
+ RecordFallbackStats(output_params_);
+
+ // Open failed! Attempt to open the output device in high latency mode using
+ // a new high latency appropriate buffer size. |kMinLowLatencyFrameSize| is
+ // arbitrarily based on Pepper Flash's MAXIMUM frame size for low latency.
+ static const int kMinLowLatencyFrameSize = 2048;
+ int frames_per_buffer = std::max(
+ std::min(params_.frames_per_buffer(), kMinLowLatencyFrameSize),
+ static_cast<int>(GetHighLatencyOutputBufferSize(params_.sample_rate())));
+
+ output_params_ = AudioParameters(
+ AudioParameters::AUDIO_PCM_LINEAR, params_.channel_layout(),
+ params_.sample_rate(), params_.bits_per_sample(), frames_per_buffer);
+ Initialize();
+
+ // Retry, if this fails, there's nothing left to do but report the error back.
return dispatcher_->OpenStream();
}
@@ -185,7 +245,9 @@ int AudioOutputResampler::OnMoreIOData(AudioBus* source,
ProvideInput(dest);
// Calculate how much data is left in the internal FIFO and resampler buffers.
- outstanding_audio_bytes_ -= dest->frames() * output_bytes_per_frame_;
+ outstanding_audio_bytes_ -=
+ dest->frames() * output_params_.GetBytesPerFrame();
+
// Due to rounding errors while multiplying against |io_ratio_|,
// |outstanding_audio_bytes_| might (rarely) slip below zero.
if (outstanding_audio_bytes_ < 0) {
@@ -217,7 +279,7 @@ void AudioOutputResampler::SourceCallback_Locked(AudioBus* audio_bus) {
// Scale the number of frames we got back in terms of input bytes to output
// bytes accordingly.
outstanding_audio_bytes_ +=
- (audio_bus->frames() * input_bytes_per_frame_) / io_ratio_;
+ (audio_bus->frames() * params_.GetBytesPerFrame()) / io_ratio_;
}
void AudioOutputResampler::ProvideInput(AudioBus* audio_bus) {
« no previous file with comments | « media/audio/audio_output_resampler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698