audio_output_resampler.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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 3// found in the LICENSE file. 4 5#include "media/audio/audio_output_resampler.h" 6 7#include "base/bind.h" 8#include "base/bind_helpers.h" 9#include "base/command_line.h" 10#include "base/compiler_specific.h" 11#include "base/message_loop.h" 12#include "base/metrics/histogram.h" 13#include "base/time.h" 14#include "media/audio/audio_io.h" 15#include "media/audio/audio_output_dispatcher_impl.h" 16#include "media/audio/audio_output_proxy.h" 17#include "media/audio/audio_util.h" 18#include "media/audio/sample_rates.h" 19#include "media/base/audio_pull_fifo.h" 20#include "media/base/channel_mixer.h" 21#include "media/base/limits.h" 22#include "media/base/media_switches.h" 23#include "media/base/multi_channel_resampler.h" 24 25namespace media { 26 27class OnMoreDataResampler : public AudioOutputStream::AudioSourceCallback { 28 public: 29 OnMoreDataResampler(double io_ratio, 30 const AudioParameters& input_params, 31 const AudioParameters& output_params); 32 virtual ~OnMoreDataResampler(); 33 34 // AudioSourceCallback interface. 35 virtual int OnMoreData(AudioBus* dest, 36 AudioBuffersState buffers_state) OVERRIDE; 37 virtual int OnMoreIOData(AudioBus* source, 38 AudioBus* dest, 39 AudioBuffersState buffers_state) OVERRIDE; 40 virtual void OnError(AudioOutputStream* stream, int code) OVERRIDE; 41 virtual void WaitTillDataReady() OVERRIDE; 42 43 // Sets |source_callback_|. If this is not a new object, then Stop() must be 44 // called before Start(). 45 void Start(AudioOutputStream::AudioSourceCallback* callback); 46 47 // Clears |source_callback_| and flushes the resampler. 48 void Stop(); 49 50 private: 51 // Called by MultiChannelResampler when more data is necessary. 52 void ProvideInput(AudioBus* audio_bus); 53 54 // Called by AudioPullFifo when more data is necessary. Requires 55 // |source_lock_| to have been acquired. 56 void SourceCallback_Locked(AudioBus* audio_bus); 57 58 // Passes through |source| to the |source_callback_| OnMoreIOData() call. 59 void SourceIOCallback_Locked(AudioBus* source, AudioBus* dest); 60 61 // Ratio of input bytes to output bytes used to correct playback delay with 62 // regard to buffering and resampling. 63 double io_ratio_; 64 65 // Source callback and associated lock. 66 base::Lock source_lock_; 67 AudioOutputStream::AudioSourceCallback* source_callback_; 68 69 // Last AudioBuffersState object received via OnMoreData(), used to correct 70 // playback delay by ProvideInput() and passed on to |source_callback_|. 71 AudioBuffersState current_buffers_state_; 72 73 // Total number of bytes (in terms of output parameters) stored in resampler 74 // or FIFO buffers which have not been sent to the audio device. 75 int outstanding_audio_bytes_; 76 77 // Used to buffer data between the client and the output device in cases where 78 // the client buffer size is not the same as the output device buffer size. 79 // Bound to SourceCallback_Locked() so must only be used when |source_lock_| 80 // has already been acquired. 81 scoped_ptr<AudioPullFifo> audio_fifo_; 82 83 // Handles resampling. 84 scoped_ptr<MultiChannelResampler> resampler_; 85 86 // Handles channel transforms. |unmixed_audio_| is a temporary destination 87 // for audio data before it goes into the channel mixer. 88 scoped_ptr<ChannelMixer> channel_mixer_; 89 scoped_ptr<AudioBus> unmixed_audio_; 90 91 int output_bytes_per_frame_; 92 int input_bytes_per_frame_; 93 94 // Since resampling is expensive, figure out if we should downmix channels 95 // before resampling. 96 bool downmix_early_; 97 98 DISALLOW_COPY_AND_ASSIGN(OnMoreDataResampler); 99}; 100 101// Record UMA statistics for hardware output configuration. 102static void RecordStats(const AudioParameters& output_params) { 103 UMA_HISTOGRAM_ENUMERATION( 104 "Media.HardwareAudioBitsPerChannel", output_params.bits_per_sample(), 105 limits::kMaxBitsPerSample); 106 UMA_HISTOGRAM_ENUMERATION( 107 "Media.HardwareAudioChannelLayout", output_params.channel_layout(), 108 CHANNEL_LAYOUT_MAX); 109 UMA_HISTOGRAM_ENUMERATION( 110 "Media.HardwareAudioChannelCount", output_params.channels(), 111 limits::kMaxChannels); 112 113 AudioSampleRate asr = media::AsAudioSampleRate(output_params.sample_rate()); 114 if (asr != kUnexpectedAudioSampleRate) { 115 UMA_HISTOGRAM_ENUMERATION( 116 "Media.HardwareAudioSamplesPerSecond", asr, kUnexpectedAudioSampleRate); 117 } else { 118 UMA_HISTOGRAM_COUNTS( 119 "Media.HardwareAudioSamplesPerSecondUnexpected", 120 output_params.sample_rate()); 121 } 122} 123 124// Record UMA statistics for hardware output configuration after fallback. 125static void RecordFallbackStats(const AudioParameters& output_params) { 126 UMA_HISTOGRAM_BOOLEAN("Media.FallbackToHighLatencyAudioPath", true); 127 UMA_HISTOGRAM_ENUMERATION( 128 "Media.FallbackHardwareAudioBitsPerChannel", 129 output_params.bits_per_sample(), limits::kMaxBitsPerSample); 130 UMA_HISTOGRAM_ENUMERATION( 131 "Media.FallbackHardwareAudioChannelLayout", 132 output_params.channel_layout(), CHANNEL_LAYOUT_MAX); 133 UMA_HISTOGRAM_ENUMERATION( 134 "Media.FallbackHardwareAudioChannelCount", 135 output_params.channels(), limits::kMaxChannels); 136 137 AudioSampleRate asr = media::AsAudioSampleRate(output_params.sample_rate()); 138 if (asr != kUnexpectedAudioSampleRate) { 139 UMA_HISTOGRAM_ENUMERATION( 140 "Media.FallbackHardwareAudioSamplesPerSecond", 141 asr, kUnexpectedAudioSampleRate); 142 } else { 143 UMA_HISTOGRAM_COUNTS( 144 "Media.FallbackHardwareAudioSamplesPerSecondUnexpected", 145 output_params.sample_rate()); 146 } 147} 148 149// Converts low latency based |output_params| into high latency appropriate 150// output parameters in error situations. 151static AudioParameters SetupFallbackParams( 152 const AudioParameters& input_params, const AudioParameters& output_params) { 153 // Choose AudioParameters appropriate for opening the device in high latency 154 // mode. |kMinLowLatencyFrameSize| is arbitrarily based on Pepper Flash's 155 // MAXIMUM frame size for low latency. 156 static const int kMinLowLatencyFrameSize = 2048; 157 int frames_per_buffer = std::min( 158 std::max(input_params.frames_per_buffer(), kMinLowLatencyFrameSize), 159 static_cast<int>( 160 GetHighLatencyOutputBufferSize(input_params.sample_rate()))); 161 162 return AudioParameters( 163 AudioParameters::AUDIO_PCM_LINEAR, input_params.channel_layout(), 164 input_params.sample_rate(), input_params.bits_per_sample(), 165 frames_per_buffer); 166} 167 168AudioOutputResampler::AudioOutputResampler(AudioManager* audio_manager, 169 const AudioParameters& input_params, 170 const AudioParameters& output_params, 171 const base::TimeDelta& close_delay) 172 : AudioOutputDispatcher(audio_manager, input_params), 173 io_ratio_(1), 174 close_delay_(close_delay), 175 output_params_(output_params), 176 streams_opened_(false) { 177 DCHECK(input_params.IsValid()); 178 DCHECK(output_params.IsValid()); 179 DCHECK_EQ(output_params_.format(), AudioParameters::AUDIO_PCM_LOW_LATENCY); 180 181 // Record UMA statistics for the hardware configuration. 182 RecordStats(output_params); 183 184 Initialize(); 185} 186 187AudioOutputResampler::~AudioOutputResampler() { 188 DCHECK(callbacks_.empty()); 189} 190 191void AudioOutputResampler::Initialize() { 192 DCHECK(!streams_opened_); 193 DCHECK(callbacks_.empty()); 194 195 io_ratio_ = 1; 196 197 // Only resample or rebuffer if the input parameters don't match the output 198 // parameters to avoid any unnecessary work. 199 if (params_.channels() != output_params_.channels() || 200 params_.sample_rate() != output_params_.sample_rate() || 201 params_.bits_per_sample() != output_params_.bits_per_sample() || 202 params_.frames_per_buffer() != output_params_.frames_per_buffer()) { 203 if (params_.sample_rate() != output_params_.sample_rate()) { 204 double io_sample_rate_ratio = params_.sample_rate() / 205 static_cast<double>(output_params_.sample_rate()); 206 // Include the I/O resampling ratio in our global I/O ratio. 207 io_ratio_ *= io_sample_rate_ratio; 208 } 209 210 // Include bits per channel differences. 211 io_ratio_ *= static_cast<double>(params_.bits_per_sample()) / 212 output_params_.bits_per_sample(); 213 214 // Include channel count differences. 215 io_ratio_ *= static_cast<double>(params_.channels()) / 216 output_params_.channels(); 217 218 DVLOG(1) << "I/O ratio is " << io_ratio_; 219 } else { 220 DVLOG(1) << "Input and output params are the same; in pass-through mode."; 221 } 222 223 // TODO(dalecurtis): All this code should be merged into AudioOutputMixer once 224 // we've stabilized the issues there. 225 dispatcher_ = new AudioOutputDispatcherImpl( 226 audio_manager_, output_params_, close_delay_); 227} 228 229bool AudioOutputResampler::OpenStream() { 230 DCHECK_EQ(MessageLoop::current(), message_loop_); 231 232 if (dispatcher_->OpenStream()) { 233 // Only record the UMA statistic if we didn't fallback during construction 234 // and only for the first stream we open. 235 if (!streams_opened_ && 236 output_params_.format() == AudioParameters::AUDIO_PCM_LOW_LATENCY) { 237 UMA_HISTOGRAM_BOOLEAN("Media.FallbackToHighLatencyAudioPath", false); 238 } 239 streams_opened_ = true; 240 return true; 241 } 242 243 // If we've already tried to open the stream in high latency mode or we've 244 // successfully opened a stream previously, there's nothing more to be done. 245 if (output_params_.format() == AudioParameters::AUDIO_PCM_LINEAR || 246 streams_opened_ || !callbacks_.empty()) { 247 return false; 248 } 249 250 DCHECK_EQ(output_params_.format(), AudioParameters::AUDIO_PCM_LOW_LATENCY); 251 252 if (CommandLine::ForCurrentProcess()->HasSwitch( 253 switches::kDisableAudioFallback)) { 254 LOG(ERROR) << "Open failed and automatic fallback to high latency audio " 255 << "path is disabled, aborting."; 256 return false; 257 } 258 259 DLOG(ERROR) << "Unable to open audio device in low latency mode. Falling " 260 << "back to high latency audio output."; 261 262 // Record UMA statistics about the hardware which triggered the failure so 263 // we can debug and triage later. 264 RecordFallbackStats(output_params_); 265 output_params_ = SetupFallbackParams(params_, output_params_); 266 Initialize(); 267 268 // Retry, if this fails, there's nothing left to do but report the error back. 269 return dispatcher_->OpenStream(); 270} 271 272bool AudioOutputResampler::StartStream( 273 AudioOutputStream::AudioSourceCallback* callback, 274 AudioOutputProxy* stream_proxy) { 275 DCHECK_EQ(MessageLoop::current(), message_loop_); 276 277 OnMoreDataResampler* resampler_callback = NULL; 278 CallbackMap::iterator it = callbacks_.find(stream_proxy); 279 if (it == callbacks_.end()) { 280 resampler_callback = new OnMoreDataResampler( 281 io_ratio_, params_, output_params_); 282 callbacks_[stream_proxy] = resampler_callback; 283 } else { 284 resampler_callback = it->second; 285 } 286 resampler_callback->Start(callback); 287 return dispatcher_->StartStream(resampler_callback, stream_proxy); 288} 289 290void AudioOutputResampler::StreamVolumeSet(AudioOutputProxy* stream_proxy, 291 double volume) { 292 DCHECK_EQ(MessageLoop::current(), message_loop_); 293 dispatcher_->StreamVolumeSet(stream_proxy, volume); 294} 295 296void AudioOutputResampler::StopStream(AudioOutputProxy* stream_proxy) { 297 DCHECK_EQ(MessageLoop::current(), message_loop_); 298 dispatcher_->StopStream(stream_proxy); 299 300 // Now that StopStream() has completed the underlying physical stream should 301 // be stopped and no longer calling OnMoreData(), making it safe to Stop() the 302 // OnMoreDataResampler. 303 CallbackMap::iterator it = callbacks_.find(stream_proxy); 304 if (it != callbacks_.end()) 305 it->second->Stop(); 306} 307 308void AudioOutputResampler::CloseStream(AudioOutputProxy* stream_proxy) { 309 DCHECK_EQ(MessageLoop::current(), message_loop_); 310 dispatcher_->CloseStream(stream_proxy); 311 312 // We assume that StopStream() is always called prior to CloseStream(), so 313 // that it is safe to delete the OnMoreDataResampler here. 314 CallbackMap::iterator it = callbacks_.find(stream_proxy); 315 if (it != callbacks_.end()) { 316 delete it->second; 317 callbacks_.erase(it); 318 } 319} 320 321void AudioOutputResampler::Shutdown() { 322 DCHECK_EQ(MessageLoop::current(), message_loop_); 323 324 // No AudioOutputProxy objects should hold a reference to us when we get 325 // to this stage. 326 DCHECK(HasOneRef()) << "Only the AudioManager should hold a reference"; 327 328 dispatcher_->Shutdown(); 329 DCHECK(callbacks_.empty()); 330} 331 332OnMoreDataResampler::OnMoreDataResampler( 333 double io_ratio, const AudioParameters& input_params, 334 const AudioParameters& output_params) 335 : io_ratio_(io_ratio), 336 source_callback_(NULL), 337 outstanding_audio_bytes_(0), 338 output_bytes_per_frame_(output_params.GetBytesPerFrame()), 339 input_bytes_per_frame_(input_params.GetBytesPerFrame()), 340 downmix_early_(false) { 341 // Handle different input and output channel layouts. 342 if (input_params.channel_layout() != output_params.channel_layout()) { 343 DVLOG(1) << "Remixing channel layout from " << input_params.channel_layout() 344 << " to " << output_params.channel_layout() << "; from " 345 << input_params.channels() << " channels to " 346 << output_params.channels() << " channels."; 347 channel_mixer_.reset(new ChannelMixer( 348 input_params.channel_layout(), output_params.channel_layout())); 349 350 // Pare off data as early as we can for efficiency. 351 downmix_early_ = input_params.channels() > output_params.channels(); 352 if (downmix_early_) { 353 DVLOG(1) << "Remixing channel layout prior to resampling."; 354 // If we're downmixing early we need a temporary AudioBus which matches 355 // the the input channel count and input frame size since we're passing 356 // |unmixed_audio_| directly to the |source_callback_|. 357 unmixed_audio_ = AudioBus::Create(input_params); 358 } else { 359 // Instead, if we're not downmixing early we need a temporary AudioBus 360 // which matches the input channel count but uses the output frame size 361 // since we'll mix into the AudioBus from the output stream. 362 unmixed_audio_ = AudioBus::Create( 363 input_params.channels(), output_params.frames_per_buffer()); 364 } 365 } 366 367 // Only resample if necessary since it's expensive. 368 if (input_params.sample_rate() != output_params.sample_rate()) { 369 DVLOG(1) << "Resampling from " << input_params.sample_rate() << " to " 370 << output_params.sample_rate(); 371 double io_sample_rate_ratio = input_params.sample_rate() / 372 static_cast<double>(output_params.sample_rate()); 373 resampler_.reset(new MultiChannelResampler( 374 downmix_early_ ? output_params.channels() : 375 input_params.channels(), 376 io_sample_rate_ratio, base::Bind( 377 &OnMoreDataResampler::ProvideInput, base::Unretained(this)))); 378 } 379 380 // Since the resampler / output device may want a different buffer size than 381 // the caller asked for, we need to use a FIFO to ensure that both sides 382 // read in chunk sizes they're configured for. 383 if (input_params.sample_rate() != output_params.sample_rate() || 384 input_params.frames_per_buffer() != output_params.frames_per_buffer()) { 385 DVLOG(1) << "Rebuffering from " << input_params.frames_per_buffer() 386 << " to " << output_params.frames_per_buffer(); 387 audio_fifo_.reset(new AudioPullFifo( 388 downmix_early_ ? output_params.channels() : 389 input_params.channels(), 390 input_params.frames_per_buffer(), base::Bind( 391 &OnMoreDataResampler::SourceCallback_Locked, 392 base::Unretained(this)))); 393 } 394} 395 396OnMoreDataResampler::~OnMoreDataResampler() {} 397 398void OnMoreDataResampler::Start( 399 AudioOutputStream::AudioSourceCallback* callback) { 400 base::AutoLock auto_lock(source_lock_); 401 DCHECK(!source_callback_); 402 source_callback_ = callback; 403} 404 405void OnMoreDataResampler::Stop() { 406 base::AutoLock auto_lock(source_lock_); 407 source_callback_ = NULL; 408 outstanding_audio_bytes_ = 0; 409 if (audio_fifo_) 410 audio_fifo_->Clear(); 411 if (resampler_) 412 resampler_->Flush(); 413} 414 415int OnMoreDataResampler::OnMoreData(AudioBus* dest, 416 AudioBuffersState buffers_state) { 417 return OnMoreIOData(NULL, dest, buffers_state); 418} 419 420int OnMoreDataResampler::OnMoreIOData(AudioBus* source, 421 AudioBus* dest, 422 AudioBuffersState buffers_state) { 423 base::AutoLock auto_lock(source_lock_); 424 // While we waited for |source_lock_| the callback might have been cleared. 425 if (!source_callback_) { 426 dest->Zero(); 427 return dest->frames(); 428 } 429 430 current_buffers_state_ = buffers_state; 431 432 bool needs_mixing = channel_mixer_ && !downmix_early_; 433 AudioBus* temp_dest = needs_mixing ? unmixed_audio_.get() : dest; 434 435 if (!resampler_ && !audio_fifo_) { 436 // We have no internal buffers, so clear any outstanding audio data. 437 outstanding_audio_bytes_ = 0; 438 SourceIOCallback_Locked(source, temp_dest); 439 } else { 440 if (resampler_) 441 resampler_->Resample(temp_dest, temp_dest->frames()); 442 else 443 ProvideInput(temp_dest); 444 445 // Calculate how much data is left in the internal FIFO and resampler. 446 outstanding_audio_bytes_ -= temp_dest->frames() * output_bytes_per_frame_; 447 } 448 449 if (needs_mixing) { 450 DCHECK_EQ(temp_dest->frames(), dest->frames()); 451 channel_mixer_->Transform(temp_dest, dest); 452 } 453 454 // Due to rounding errors while multiplying against |io_ratio_|, 455 // |outstanding_audio_bytes_| might (rarely) slip below zero. 456 if (outstanding_audio_bytes_ < 0) { 457 DLOG(ERROR) << "Outstanding audio bytes went negative! Value: " 458 << outstanding_audio_bytes_; 459 outstanding_audio_bytes_ = 0; 460 } 461 462 // Always return the full number of frames requested, ProvideInput() will pad 463 // with silence if it wasn't able to acquire enough data. 464 return dest->frames(); 465} 466 467void OnMoreDataResampler::SourceCallback_Locked(AudioBus* dest) { 468 SourceIOCallback_Locked(NULL, dest); 469} 470 471void OnMoreDataResampler::SourceIOCallback_Locked(AudioBus* source, 472 AudioBus* dest) { 473 source_lock_.AssertAcquired(); 474 475 // Adjust playback delay to include the state of the internal buffers used by 476 // the resampler and/or the FIFO. Since the sample rate and bits per channel 477 // may be different, we need to scale this value appropriately. 478 AudioBuffersState new_buffers_state; 479 new_buffers_state.pending_bytes = io_ratio_ * 480 (current_buffers_state_.total_bytes() + outstanding_audio_bytes_); 481 482 bool needs_downmix = channel_mixer_ && downmix_early_; 483 AudioBus* temp_dest = needs_downmix ? unmixed_audio_.get() : dest; 484 485 // Retrieve data from the original callback. Zero any unfilled frames. 486 int frames = source_callback_->OnMoreIOData( 487 source, temp_dest, new_buffers_state); 488 if (frames < temp_dest->frames()) 489 temp_dest->ZeroFramesPartial(frames, temp_dest->frames() - frames); 490 491 // Scale the number of frames we got back in terms of input bytes to output 492 // bytes accordingly. 493 outstanding_audio_bytes_ += 494 (temp_dest->frames() * input_bytes_per_frame_) / io_ratio_; 495 496 if (needs_downmix) { 497 DCHECK_EQ(temp_dest->frames(), dest->frames()); 498 channel_mixer_->Transform(temp_dest, dest); 499 } 500} 501 502void OnMoreDataResampler::ProvideInput(AudioBus* audio_bus) { 503 audio_fifo_->Consume(audio_bus, audio_bus->frames()); 504} 505 506void OnMoreDataResampler::OnError(AudioOutputStream* stream, int code) { 507 base::AutoLock auto_lock(source_lock_); 508 if (source_callback_) 509 source_callback_->OnError(stream, code); 510} 511 512void OnMoreDataResampler::WaitTillDataReady() { 513 base::AutoLock auto_lock(source_lock_); 514 if (source_callback_ && !outstanding_audio_bytes_) 515 source_callback_->WaitTillDataReady(); 516} 517 518} // namespace media 519