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

Side by Side Diff: media/audio/audio_output_resampler.cc

Issue 11410012: Collapse AudioRendererMixer and OnMoreDataResampler into AudioTransform. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rename. Comments. Created 8 years, 1 month 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/audio/audio_output_resampler.h ('k') | media/base/audio_converter.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
11 #include "base/message_loop.h" 11 #include "base/message_loop.h"
12 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
13 #include "base/time.h" 13 #include "base/time.h"
14 #include "media/audio/audio_io.h" 14 #include "media/audio/audio_io.h"
15 #include "media/audio/audio_output_dispatcher_impl.h" 15 #include "media/audio/audio_output_dispatcher_impl.h"
16 #include "media/audio/audio_output_proxy.h" 16 #include "media/audio/audio_output_proxy.h"
17 #include "media/audio/audio_util.h" 17 #include "media/audio/audio_util.h"
18 #include "media/audio/sample_rates.h" 18 #include "media/audio/sample_rates.h"
19 #include "media/base/audio_pull_fifo.h" 19 #include "media/base/audio_converter.h"
20 #include "media/base/channel_mixer.h"
21 #include "media/base/limits.h" 20 #include "media/base/limits.h"
22 #include "media/base/media_switches.h" 21 #include "media/base/media_switches.h"
23 #include "media/base/multi_channel_resampler.h"
24 22
25 namespace media { 23 namespace media {
26 24
27 class OnMoreDataResampler : public AudioOutputStream::AudioSourceCallback { 25 class OnMoreDataConverter
26 : public AudioOutputStream::AudioSourceCallback,
27 public AudioConverter::InputCallback {
28 public: 28 public:
29 OnMoreDataResampler(double io_ratio, 29 OnMoreDataConverter(const AudioParameters& input_params,
30 const AudioParameters& input_params,
31 const AudioParameters& output_params); 30 const AudioParameters& output_params);
32 virtual ~OnMoreDataResampler(); 31 virtual ~OnMoreDataConverter();
33 32
34 // AudioSourceCallback interface. 33 // AudioSourceCallback interface.
35 virtual int OnMoreData(AudioBus* dest, 34 virtual int OnMoreData(AudioBus* dest,
36 AudioBuffersState buffers_state) OVERRIDE; 35 AudioBuffersState buffers_state) OVERRIDE;
37 virtual int OnMoreIOData(AudioBus* source, 36 virtual int OnMoreIOData(AudioBus* source,
38 AudioBus* dest, 37 AudioBus* dest,
39 AudioBuffersState buffers_state) OVERRIDE; 38 AudioBuffersState buffers_state) OVERRIDE;
40 virtual void OnError(AudioOutputStream* stream, int code) OVERRIDE; 39 virtual void OnError(AudioOutputStream* stream, int code) OVERRIDE;
41 virtual void WaitTillDataReady() OVERRIDE; 40 virtual void WaitTillDataReady() OVERRIDE;
42 41
43 // Sets |source_callback_|. If this is not a new object, then Stop() must be 42 // Sets |source_callback_|. If this is not a new object, then Stop() must be
44 // called before Start(). 43 // called before Start().
45 void Start(AudioOutputStream::AudioSourceCallback* callback); 44 void Start(AudioOutputStream::AudioSourceCallback* callback);
46 45
47 // Clears |source_callback_| and flushes the resampler. 46 // Clears |source_callback_| and flushes the resampler.
48 void Stop(); 47 void Stop();
49 48
50 private: 49 private:
51 // Called by MultiChannelResampler when more data is necessary. 50 // AudioConverter::InputCallback implementation.
52 void ProvideInput(AudioBus* audio_bus); 51 virtual double ProvideInput(AudioBus* audio_bus,
53 52 base::TimeDelta buffer_delay) OVERRIDE;
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 53
61 // Ratio of input bytes to output bytes used to correct playback delay with 54 // Ratio of input bytes to output bytes used to correct playback delay with
62 // regard to buffering and resampling. 55 // regard to buffering and resampling.
63 double io_ratio_; 56 double io_ratio_;
64 57
65 // Source callback and associated lock. 58 // Source callback and associated lock.
66 base::Lock source_lock_; 59 base::Lock source_lock_;
67 AudioOutputStream::AudioSourceCallback* source_callback_; 60 AudioOutputStream::AudioSourceCallback* source_callback_;
68 61
62 // |source| passed to OnMoreIOData() which should be passed downstream.
63 AudioBus* source_bus_;
64
69 // Last AudioBuffersState object received via OnMoreData(), used to correct 65 // Last AudioBuffersState object received via OnMoreData(), used to correct
70 // playback delay by ProvideInput() and passed on to |source_callback_|. 66 // playback delay by ProvideInput() and passed on to |source_callback_|.
71 AudioBuffersState current_buffers_state_; 67 AudioBuffersState current_buffers_state_;
72 68
73 // Total number of bytes (in terms of output parameters) stored in resampler 69 const int input_bytes_per_second_;
74 // or FIFO buffers which have not been sent to the audio device.
75 int outstanding_audio_bytes_;
76 70
77 // Used to buffer data between the client and the output device in cases where 71 // Handles resampling, buffering, and channel mixing between input and output
78 // the client buffer size is not the same as the output device buffer size. 72 // parameters.
79 // Bound to SourceCallback_Locked() so must only be used when |source_lock_| 73 AudioConverter audio_converter_;
80 // has already been acquired.
81 scoped_ptr<AudioPullFifo> audio_fifo_;
82 74
83 // Handles resampling. 75 DISALLOW_COPY_AND_ASSIGN(OnMoreDataConverter);
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 }; 76 };
100 77
101 // Record UMA statistics for hardware output configuration. 78 // Record UMA statistics for hardware output configuration.
102 static void RecordStats(const AudioParameters& output_params) { 79 static void RecordStats(const AudioParameters& output_params) {
103 UMA_HISTOGRAM_ENUMERATION( 80 UMA_HISTOGRAM_ENUMERATION(
104 "Media.HardwareAudioBitsPerChannel", output_params.bits_per_sample(), 81 "Media.HardwareAudioBitsPerChannel", output_params.bits_per_sample(),
105 limits::kMaxBitsPerSample); 82 limits::kMaxBitsPerSample);
106 UMA_HISTOGRAM_ENUMERATION( 83 UMA_HISTOGRAM_ENUMERATION(
107 "Media.HardwareAudioChannelLayout", output_params.channel_layout(), 84 "Media.HardwareAudioChannelLayout", output_params.channel_layout(),
108 CHANNEL_LAYOUT_MAX); 85 CHANNEL_LAYOUT_MAX);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 AudioParameters::AUDIO_PCM_LINEAR, input_params.channel_layout(), 140 AudioParameters::AUDIO_PCM_LINEAR, input_params.channel_layout(),
164 input_params.sample_rate(), input_params.bits_per_sample(), 141 input_params.sample_rate(), input_params.bits_per_sample(),
165 frames_per_buffer); 142 frames_per_buffer);
166 } 143 }
167 144
168 AudioOutputResampler::AudioOutputResampler(AudioManager* audio_manager, 145 AudioOutputResampler::AudioOutputResampler(AudioManager* audio_manager,
169 const AudioParameters& input_params, 146 const AudioParameters& input_params,
170 const AudioParameters& output_params, 147 const AudioParameters& output_params,
171 const base::TimeDelta& close_delay) 148 const base::TimeDelta& close_delay)
172 : AudioOutputDispatcher(audio_manager, input_params), 149 : AudioOutputDispatcher(audio_manager, input_params),
173 io_ratio_(1),
174 close_delay_(close_delay), 150 close_delay_(close_delay),
175 output_params_(output_params), 151 output_params_(output_params),
176 streams_opened_(false) { 152 streams_opened_(false) {
177 DCHECK(input_params.IsValid()); 153 DCHECK(input_params.IsValid());
178 DCHECK(output_params.IsValid()); 154 DCHECK(output_params.IsValid());
179 DCHECK_EQ(output_params_.format(), AudioParameters::AUDIO_PCM_LOW_LATENCY); 155 DCHECK_EQ(output_params_.format(), AudioParameters::AUDIO_PCM_LOW_LATENCY);
180 156
181 // Record UMA statistics for the hardware configuration. 157 // Record UMA statistics for the hardware configuration.
182 RecordStats(output_params); 158 RecordStats(output_params);
183 159
184 Initialize(); 160 Initialize();
185 } 161 }
186 162
187 AudioOutputResampler::~AudioOutputResampler() { 163 AudioOutputResampler::~AudioOutputResampler() {
188 DCHECK(callbacks_.empty()); 164 DCHECK(callbacks_.empty());
189 } 165 }
190 166
191 void AudioOutputResampler::Initialize() { 167 void AudioOutputResampler::Initialize() {
192 DCHECK(!streams_opened_); 168 DCHECK(!streams_opened_);
193 DCHECK(callbacks_.empty()); 169 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( 170 dispatcher_ = new AudioOutputDispatcherImpl(
226 audio_manager_, output_params_, close_delay_); 171 audio_manager_, output_params_, close_delay_);
227 } 172 }
228 173
229 bool AudioOutputResampler::OpenStream() { 174 bool AudioOutputResampler::OpenStream() {
230 DCHECK_EQ(MessageLoop::current(), message_loop_); 175 DCHECK_EQ(MessageLoop::current(), message_loop_);
231 176
232 if (dispatcher_->OpenStream()) { 177 if (dispatcher_->OpenStream()) {
233 // Only record the UMA statistic if we didn't fallback during construction 178 // Only record the UMA statistic if we didn't fallback during construction
234 // and only for the first stream we open. 179 // and only for the first stream we open.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 212
268 // Retry, if this fails, there's nothing left to do but report the error back. 213 // Retry, if this fails, there's nothing left to do but report the error back.
269 return dispatcher_->OpenStream(); 214 return dispatcher_->OpenStream();
270 } 215 }
271 216
272 bool AudioOutputResampler::StartStream( 217 bool AudioOutputResampler::StartStream(
273 AudioOutputStream::AudioSourceCallback* callback, 218 AudioOutputStream::AudioSourceCallback* callback,
274 AudioOutputProxy* stream_proxy) { 219 AudioOutputProxy* stream_proxy) {
275 DCHECK_EQ(MessageLoop::current(), message_loop_); 220 DCHECK_EQ(MessageLoop::current(), message_loop_);
276 221
277 OnMoreDataResampler* resampler_callback = NULL; 222 OnMoreDataConverter* resampler_callback = NULL;
278 CallbackMap::iterator it = callbacks_.find(stream_proxy); 223 CallbackMap::iterator it = callbacks_.find(stream_proxy);
279 if (it == callbacks_.end()) { 224 if (it == callbacks_.end()) {
280 resampler_callback = new OnMoreDataResampler( 225 resampler_callback = new OnMoreDataConverter(params_, output_params_);
281 io_ratio_, params_, output_params_);
282 callbacks_[stream_proxy] = resampler_callback; 226 callbacks_[stream_proxy] = resampler_callback;
283 } else { 227 } else {
284 resampler_callback = it->second; 228 resampler_callback = it->second;
285 } 229 }
286 resampler_callback->Start(callback); 230 resampler_callback->Start(callback);
287 return dispatcher_->StartStream(resampler_callback, stream_proxy); 231 return dispatcher_->StartStream(resampler_callback, stream_proxy);
288 } 232 }
289 233
290 void AudioOutputResampler::StreamVolumeSet(AudioOutputProxy* stream_proxy, 234 void AudioOutputResampler::StreamVolumeSet(AudioOutputProxy* stream_proxy,
291 double volume) { 235 double volume) {
292 DCHECK_EQ(MessageLoop::current(), message_loop_); 236 DCHECK_EQ(MessageLoop::current(), message_loop_);
293 dispatcher_->StreamVolumeSet(stream_proxy, volume); 237 dispatcher_->StreamVolumeSet(stream_proxy, volume);
294 } 238 }
295 239
296 void AudioOutputResampler::StopStream(AudioOutputProxy* stream_proxy) { 240 void AudioOutputResampler::StopStream(AudioOutputProxy* stream_proxy) {
297 DCHECK_EQ(MessageLoop::current(), message_loop_); 241 DCHECK_EQ(MessageLoop::current(), message_loop_);
298 dispatcher_->StopStream(stream_proxy); 242 dispatcher_->StopStream(stream_proxy);
299 243
300 // Now that StopStream() has completed the underlying physical stream should 244 // Now that StopStream() has completed the underlying physical stream should
301 // be stopped and no longer calling OnMoreData(), making it safe to Stop() the 245 // be stopped and no longer calling OnMoreData(), making it safe to Stop() the
302 // OnMoreDataResampler. 246 // OnMoreDataConverter.
303 CallbackMap::iterator it = callbacks_.find(stream_proxy); 247 CallbackMap::iterator it = callbacks_.find(stream_proxy);
304 if (it != callbacks_.end()) 248 if (it != callbacks_.end())
305 it->second->Stop(); 249 it->second->Stop();
306 } 250 }
307 251
308 void AudioOutputResampler::CloseStream(AudioOutputProxy* stream_proxy) { 252 void AudioOutputResampler::CloseStream(AudioOutputProxy* stream_proxy) {
309 DCHECK_EQ(MessageLoop::current(), message_loop_); 253 DCHECK_EQ(MessageLoop::current(), message_loop_);
310 dispatcher_->CloseStream(stream_proxy); 254 dispatcher_->CloseStream(stream_proxy);
311 255
312 // We assume that StopStream() is always called prior to CloseStream(), so 256 // We assume that StopStream() is always called prior to CloseStream(), so
313 // that it is safe to delete the OnMoreDataResampler here. 257 // that it is safe to delete the OnMoreDataConverter here.
314 CallbackMap::iterator it = callbacks_.find(stream_proxy); 258 CallbackMap::iterator it = callbacks_.find(stream_proxy);
315 if (it != callbacks_.end()) { 259 if (it != callbacks_.end()) {
316 delete it->second; 260 delete it->second;
317 callbacks_.erase(it); 261 callbacks_.erase(it);
318 } 262 }
319 } 263 }
320 264
321 void AudioOutputResampler::Shutdown() { 265 void AudioOutputResampler::Shutdown() {
322 DCHECK_EQ(MessageLoop::current(), message_loop_); 266 DCHECK_EQ(MessageLoop::current(), message_loop_);
323 267
324 // No AudioOutputProxy objects should hold a reference to us when we get 268 // No AudioOutputProxy objects should hold a reference to us when we get
325 // to this stage. 269 // to this stage.
326 DCHECK(HasOneRef()) << "Only the AudioManager should hold a reference"; 270 DCHECK(HasOneRef()) << "Only the AudioManager should hold a reference";
327 271
328 dispatcher_->Shutdown(); 272 dispatcher_->Shutdown();
329 DCHECK(callbacks_.empty()); 273 DCHECK(callbacks_.empty());
330 } 274 }
331 275
332 OnMoreDataResampler::OnMoreDataResampler( 276 OnMoreDataConverter::OnMoreDataConverter(const AudioParameters& input_params,
333 double io_ratio, const AudioParameters& input_params, 277 const AudioParameters& output_params)
334 const AudioParameters& output_params) 278 : source_callback_(NULL),
335 : io_ratio_(io_ratio), 279 source_bus_(NULL),
336 source_callback_(NULL), 280 input_bytes_per_second_(input_params.GetBytesPerSecond()),
337 outstanding_audio_bytes_(0), 281 audio_converter_(input_params, output_params, false) {
338 output_bytes_per_frame_(output_params.GetBytesPerFrame()), 282 io_ratio_ =
339 input_bytes_per_frame_(input_params.GetBytesPerFrame()), 283 static_cast<double>(input_params.GetBytesPerSecond()) /
340 downmix_early_(false) { 284 output_params.GetBytesPerSecond();
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 } 285 }
395 286
396 OnMoreDataResampler::~OnMoreDataResampler() {} 287 OnMoreDataConverter::~OnMoreDataConverter() {}
397 288
398 void OnMoreDataResampler::Start( 289 void OnMoreDataConverter::Start(
399 AudioOutputStream::AudioSourceCallback* callback) { 290 AudioOutputStream::AudioSourceCallback* callback) {
400 base::AutoLock auto_lock(source_lock_); 291 base::AutoLock auto_lock(source_lock_);
401 DCHECK(!source_callback_); 292 DCHECK(!source_callback_);
402 source_callback_ = callback; 293 source_callback_ = callback;
294
295 // While AudioConverter can handle multiple inputs, we're using it only with
296 // a single input currently. Eventually this may be the basis for a browser
297 // side mixer.
298 audio_converter_.AddInput(this);
403 } 299 }
404 300
405 void OnMoreDataResampler::Stop() { 301 void OnMoreDataConverter::Stop() {
406 base::AutoLock auto_lock(source_lock_); 302 base::AutoLock auto_lock(source_lock_);
407 source_callback_ = NULL; 303 source_callback_ = NULL;
408 outstanding_audio_bytes_ = 0; 304 audio_converter_.RemoveInput(this);
409 if (audio_fifo_)
410 audio_fifo_->Clear();
411 if (resampler_)
412 resampler_->Flush();
413 } 305 }
414 306
415 int OnMoreDataResampler::OnMoreData(AudioBus* dest, 307 int OnMoreDataConverter::OnMoreData(AudioBus* dest,
416 AudioBuffersState buffers_state) { 308 AudioBuffersState buffers_state) {
417 return OnMoreIOData(NULL, dest, buffers_state); 309 return OnMoreIOData(NULL, dest, buffers_state);
418 } 310 }
419 311
420 int OnMoreDataResampler::OnMoreIOData(AudioBus* source, 312 int OnMoreDataConverter::OnMoreIOData(AudioBus* source,
421 AudioBus* dest, 313 AudioBus* dest,
422 AudioBuffersState buffers_state) { 314 AudioBuffersState buffers_state) {
423 base::AutoLock auto_lock(source_lock_); 315 base::AutoLock auto_lock(source_lock_);
424 // While we waited for |source_lock_| the callback might have been cleared. 316 // While we waited for |source_lock_| the callback might have been cleared.
425 if (!source_callback_) { 317 if (!source_callback_) {
426 dest->Zero(); 318 dest->Zero();
427 return dest->frames(); 319 return dest->frames();
428 } 320 }
429 321
322 source_bus_ = source;
430 current_buffers_state_ = buffers_state; 323 current_buffers_state_ = buffers_state;
324 audio_converter_.Convert(dest);
431 325
432 bool needs_mixing = channel_mixer_ && !downmix_early_; 326 // Always return the full number of frames requested, ProvideInput_Locked()
433 AudioBus* temp_dest = needs_mixing ? unmixed_audio_.get() : dest; 327 // will pad with silence if it wasn't able to acquire enough data.
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(); 328 return dest->frames();
465 } 329 }
466 330
467 void OnMoreDataResampler::SourceCallback_Locked(AudioBus* dest) { 331 double OnMoreDataConverter::ProvideInput(AudioBus* dest,
468 SourceIOCallback_Locked(NULL, dest); 332 base::TimeDelta buffer_delay) {
333 source_lock_.AssertAcquired();
334
335 // Adjust playback delay to include |buffer_delay|.
336 // TODO(dalecurtis): Stop passing bytes around, it doesn't make sense since
337 // AudioBus is just float data. Use TimeDelta instead.
338 AudioBuffersState new_buffers_state;
339 new_buffers_state.pending_bytes =
340 io_ratio_ * (current_buffers_state_.total_bytes() +
341 buffer_delay.InSecondsF() * input_bytes_per_second_);
342
343 // Retrieve data from the original callback.
344 int frames = source_callback_->OnMoreIOData(
345 source_bus_, dest, new_buffers_state);
346
347 // |source_bus_| should only be provided once.
348 // TODO(dalecurtis, crogers): This is not a complete fix. If ProvideInput()
349 // is called multiple times, we need to do something more clever here.
350 source_bus_ = NULL;
351
352 // Zero any unfilled frames if anything was filled, otherwise we'll just
353 // return a volume of zero and let AudioConverter drop the output.
354 if (frames > 0 && frames < dest->frames())
355 dest->ZeroFramesPartial(frames, dest->frames() - frames);
356
357 // TODO(dalecurtis): Return the correct volume here.
358 return frames > 0 ? 1 : 0;
469 } 359 }
470 360
471 void OnMoreDataResampler::SourceIOCallback_Locked(AudioBus* source, 361 void OnMoreDataConverter::OnError(AudioOutputStream* stream, int code) {
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
502 void OnMoreDataResampler::ProvideInput(AudioBus* audio_bus) {
503 audio_fifo_->Consume(audio_bus, audio_bus->frames());
504 }
505
506 void OnMoreDataResampler::OnError(AudioOutputStream* stream, int code) {
507 base::AutoLock auto_lock(source_lock_); 362 base::AutoLock auto_lock(source_lock_);
508 if (source_callback_) 363 if (source_callback_)
509 source_callback_->OnError(stream, code); 364 source_callback_->OnError(stream, code);
510 } 365 }
511 366
512 void OnMoreDataResampler::WaitTillDataReady() { 367 void OnMoreDataConverter::WaitTillDataReady() {
513 base::AutoLock auto_lock(source_lock_); 368 base::AutoLock auto_lock(source_lock_);
514 if (source_callback_ && !outstanding_audio_bytes_) 369 if (source_callback_)
515 source_callback_->WaitTillDataReady(); 370 source_callback_->WaitTillDataReady();
516 } 371 }
517 372
518 } // namespace media 373 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/audio_output_resampler.h ('k') | media/base/audio_converter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698