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

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: Comments. 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 d34893fe730206158f6e5d7558637713fef19748..a44366576e87cbab18cd51e9ffdc80507b0814c6 100644
--- a/media/audio/audio_output_resampler.cc
+++ b/media/audio/audio_output_resampler.cc
@@ -9,6 +9,7 @@
#include "base/compiler_specific.h"
#include "base/message_loop.h"
#include "base/metrics/histogram.h"
+#include "base/stringprintf.h"
#include "base/time.h"
#include "media/audio/audio_io.h"
#include "media/audio/audio_output_dispatcher_impl.h"
@@ -25,36 +26,40 @@
namespace media {
-static void RecordStats(const AudioParameters& output_params) {
+// Record UMA statistics for hardware output configuration. |prefix| will be
+// prepended to the statistic name.
+static void RecordStats(const char* prefix,
+ const AudioParameters& output_params) {
UMA_HISTOGRAM_ENUMERATION(
- "Media.HardwareAudioBitsPerChannel", output_params.bits_per_sample(),
- limits::kMaxBitsPerSample);
+ base::StringPrintf("Media.%sHardwareAudioBitsPerChannel", prefix),
+ output_params.bits_per_sample(), limits::kMaxBitsPerSample);
#if defined(OS_WIN)
// TODO(dalecurtis): Since channel mixing is handled by the output device
// right now and not by AudioOutputResampler, we need to query for hardware
// channel information. Remove once AOR handles this, http://crbug.com/138762
UMA_HISTOGRAM_ENUMERATION(
- "Media.HardwareAudioChannelLayout",
+ base::StringPrintf("Media.%sHardwareAudioChannelLayout", prefix),
WASAPIAudioOutputStream::HardwareChannelLayout(), CHANNEL_LAYOUT_MAX);
UMA_HISTOGRAM_ENUMERATION(
- "Media.HardwareAudioChannelCount",
+ base::StringPrintf("Media.%sHardwareAudioChannelCount", prefix),
WASAPIAudioOutputStream::HardwareChannelCount(), limits::kMaxChannels);
#else
UMA_HISTOGRAM_ENUMERATION(
- "Media.HardwareAudioChannelLayout", output_params.channel_layout(),
- CHANNEL_LAYOUT_MAX);
+ base::StringPrintf("Media.%sHardwareAudioChannelLayout", prefix),
+ output_params.channel_layout(), CHANNEL_LAYOUT_MAX);
UMA_HISTOGRAM_ENUMERATION(
- "Media.HardwareAudioChannelCount", output_params.channels(),
- limits::kMaxChannels);
+ base::StringPrintf("Media.%sHardwareAudioChannelCount", prefix),
+ output_params.channels(), limits::kMaxChannels);
#endif
AudioSampleRate asr = media::AsAudioSampleRate(output_params.sample_rate());
if (asr != kUnexpectedAudioSampleRate) {
UMA_HISTOGRAM_ENUMERATION(
- "Media.HardwareAudioSamplesPerSecond", asr, kUnexpectedAudioSampleRate);
+ base::StringPrintf("Media.%sHardwareAudioSamplesPerSecond", prefix),
+ asr, kUnexpectedAudioSampleRate);
} else {
UMA_HISTOGRAM_COUNTS(
- "Media.HardwareAudioSamplesPerSecondUnexpected",
- output_params.sample_rate());
+ base::StringPrintf("Media.%sHardwareAudioSamplesPerSecondUnexpected",
+ prefix), output_params.sample_rate());
}
}
@@ -65,47 +70,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) {
scherkus (not reviewing) 2012/09/12 14:24:47 it it worth DCHECKing that we're in LOW_LATENCY or
DaleCurtis 2012/09/12 14:32:34 No reason it wouldn't work, so I haven't felt the
+ 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))));
}
@@ -116,17 +131,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);
+ RecordStats("Fallback", 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();
}
@@ -200,7 +240,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) {
@@ -232,7 +274,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