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

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

Issue 11568021: Merge 169553 (Closed) Base URL: svn://svn.chromium.org/chrome/branches/1312/src/
Patch Set: Created 8 years 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_controller.cc ('k') | media/audio/win/waveout_output_win.cc » ('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 "build/build_config.h"
14 #include "media/audio/audio_io.h" 15 #include "media/audio/audio_io.h"
15 #include "media/audio/audio_output_dispatcher_impl.h" 16 #include "media/audio/audio_output_dispatcher_impl.h"
16 #include "media/audio/audio_output_proxy.h" 17 #include "media/audio/audio_output_proxy.h"
17 #include "media/audio/audio_util.h" 18 #include "media/audio/audio_util.h"
18 #include "media/audio/sample_rates.h" 19 #include "media/audio/sample_rates.h"
19 #include "media/base/audio_pull_fifo.h" 20 #include "media/base/audio_pull_fifo.h"
20 #include "media/base/channel_mixer.h" 21 #include "media/base/channel_mixer.h"
21 #include "media/base/limits.h" 22 #include "media/base/limits.h"
22 #include "media/base/media_switches.h" 23 #include "media/base/media_switches.h"
23 #include "media/base/multi_channel_resampler.h" 24 #include "media/base/multi_channel_resampler.h"
24 25
26 #if defined(OS_WIN)
27 #include "media/audio/win/core_audio_util_win.h"
28 #endif
29
25 namespace media { 30 namespace media {
26 31
27 class OnMoreDataResampler : public AudioOutputStream::AudioSourceCallback { 32 class OnMoreDataResampler : public AudioOutputStream::AudioSourceCallback {
28 public: 33 public:
29 OnMoreDataResampler(double io_ratio, 34 OnMoreDataResampler(double io_ratio,
30 const AudioParameters& input_params, 35 const AudioParameters& input_params,
31 const AudioParameters& output_params); 36 const AudioParameters& output_params);
32 virtual ~OnMoreDataResampler(); 37 virtual ~OnMoreDataResampler();
33 38
34 // AudioSourceCallback interface. 39 // AudioSourceCallback interface.
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 scoped_ptr<ChannelMixer> channel_mixer_; 93 scoped_ptr<ChannelMixer> channel_mixer_;
89 scoped_ptr<AudioBus> unmixed_audio_; 94 scoped_ptr<AudioBus> unmixed_audio_;
90 95
91 int output_bytes_per_frame_; 96 int output_bytes_per_frame_;
92 int input_bytes_per_frame_; 97 int input_bytes_per_frame_;
93 98
94 // Since resampling is expensive, figure out if we should downmix channels 99 // Since resampling is expensive, figure out if we should downmix channels
95 // before resampling. 100 // before resampling.
96 bool downmix_early_; 101 bool downmix_early_;
97 102
98 DISALLOW_COPY_AND_ASSIGN(OnMoreDataResampler); 103 // If we're using WaveOut on Windows' we always have to wait for DataReady()
104 // before calling |source_callback_|.
105 bool waveout_wait_hack_;
106
107 DISALLOW_COPY_AND_ASSIGN(OnMoreDataConverter);
99 }; 108 };
100 109
101 // Record UMA statistics for hardware output configuration. 110 // Record UMA statistics for hardware output configuration.
102 static void RecordStats(const AudioParameters& output_params) { 111 static void RecordStats(const AudioParameters& output_params) {
103 UMA_HISTOGRAM_ENUMERATION( 112 UMA_HISTOGRAM_ENUMERATION(
104 "Media.HardwareAudioBitsPerChannel", output_params.bits_per_sample(), 113 "Media.HardwareAudioBitsPerChannel", output_params.bits_per_sample(),
105 limits::kMaxBitsPerSample); 114 limits::kMaxBitsPerSample);
106 UMA_HISTOGRAM_ENUMERATION( 115 UMA_HISTOGRAM_ENUMERATION(
107 "Media.HardwareAudioChannelLayout", output_params.channel_layout(), 116 "Media.HardwareAudioChannelLayout", output_params.channel_layout(),
108 CHANNEL_LAYOUT_MAX); 117 CHANNEL_LAYOUT_MAX);
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 } 339 }
331 340
332 OnMoreDataResampler::OnMoreDataResampler( 341 OnMoreDataResampler::OnMoreDataResampler(
333 double io_ratio, const AudioParameters& input_params, 342 double io_ratio, const AudioParameters& input_params,
334 const AudioParameters& output_params) 343 const AudioParameters& output_params)
335 : io_ratio_(io_ratio), 344 : io_ratio_(io_ratio),
336 source_callback_(NULL), 345 source_callback_(NULL),
337 outstanding_audio_bytes_(0), 346 outstanding_audio_bytes_(0),
338 output_bytes_per_frame_(output_params.GetBytesPerFrame()), 347 output_bytes_per_frame_(output_params.GetBytesPerFrame()),
339 input_bytes_per_frame_(input_params.GetBytesPerFrame()), 348 input_bytes_per_frame_(input_params.GetBytesPerFrame()),
340 downmix_early_(false) { 349 downmix_early_(false),
350 waveout_wait_hack_(false) {
341 // Handle different input and output channel layouts. 351 // Handle different input and output channel layouts.
342 if (input_params.channel_layout() != output_params.channel_layout()) { 352 if (input_params.channel_layout() != output_params.channel_layout()) {
343 DVLOG(1) << "Remixing channel layout from " << input_params.channel_layout() 353 DVLOG(1) << "Remixing channel layout from " << input_params.channel_layout()
344 << " to " << output_params.channel_layout() << "; from " 354 << " to " << output_params.channel_layout() << "; from "
345 << input_params.channels() << " channels to " 355 << input_params.channels() << " channels to "
346 << output_params.channels() << " channels."; 356 << output_params.channels() << " channels.";
347 channel_mixer_.reset(new ChannelMixer( 357 channel_mixer_.reset(new ChannelMixer(
348 input_params.channel_layout(), output_params.channel_layout())); 358 input_params.channel_layout(), output_params.channel_layout()));
349 359
350 // Pare off data as early as we can for efficiency. 360 // Pare off data as early as we can for efficiency.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 input_params.frames_per_buffer() != output_params.frames_per_buffer()) { 394 input_params.frames_per_buffer() != output_params.frames_per_buffer()) {
385 DVLOG(1) << "Rebuffering from " << input_params.frames_per_buffer() 395 DVLOG(1) << "Rebuffering from " << input_params.frames_per_buffer()
386 << " to " << output_params.frames_per_buffer(); 396 << " to " << output_params.frames_per_buffer();
387 audio_fifo_.reset(new AudioPullFifo( 397 audio_fifo_.reset(new AudioPullFifo(
388 downmix_early_ ? output_params.channels() : 398 downmix_early_ ? output_params.channels() :
389 input_params.channels(), 399 input_params.channels(),
390 input_params.frames_per_buffer(), base::Bind( 400 input_params.frames_per_buffer(), base::Bind(
391 &OnMoreDataResampler::SourceCallback_Locked, 401 &OnMoreDataResampler::SourceCallback_Locked,
392 base::Unretained(this)))); 402 base::Unretained(this))));
393 } 403 }
404
405 // TODO(dalecurtis): We should require all render side clients to use a
406 // buffer size that's a multiple of the hardware buffer size scaled by the
407 // request_sample_rate / hw_sample_rate. Doing so ensures each hardware
408 // request for audio data results in only a single render side callback and
409 // would allow us to remove this hack. See http://crbug.com/162207.
410 #if defined(OS_WIN)
411 waveout_wait_hack_ =
412 output_params.format() == AudioParameters::AUDIO_PCM_LINEAR ||
413 !CoreAudioUtil::IsSupported();
414 #endif
394 } 415 }
395 416
396 OnMoreDataResampler::~OnMoreDataResampler() {} 417 OnMoreDataResampler::~OnMoreDataResampler() {}
397 418
398 void OnMoreDataResampler::Start( 419 void OnMoreDataResampler::Start(
399 AudioOutputStream::AudioSourceCallback* callback) { 420 AudioOutputStream::AudioSourceCallback* callback) {
400 base::AutoLock auto_lock(source_lock_); 421 base::AutoLock auto_lock(source_lock_);
401 DCHECK(!source_callback_); 422 DCHECK(!source_callback_);
402 source_callback_ = callback; 423 source_callback_ = callback;
403 } 424 }
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 // Adjust playback delay to include the state of the internal buffers used by 496 // 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 497 // 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. 498 // may be different, we need to scale this value appropriately.
478 AudioBuffersState new_buffers_state; 499 AudioBuffersState new_buffers_state;
479 new_buffers_state.pending_bytes = io_ratio_ * 500 new_buffers_state.pending_bytes = io_ratio_ *
480 (current_buffers_state_.total_bytes() + outstanding_audio_bytes_); 501 (current_buffers_state_.total_bytes() + outstanding_audio_bytes_);
481 502
482 bool needs_downmix = channel_mixer_ && downmix_early_; 503 bool needs_downmix = channel_mixer_ && downmix_early_;
483 AudioBus* temp_dest = needs_downmix ? unmixed_audio_.get() : dest; 504 AudioBus* temp_dest = needs_downmix ? unmixed_audio_.get() : dest;
484 505
506 if (waveout_wait_hack_)
507 source_callback_->WaitTillDataReady();
508
485 // Retrieve data from the original callback. Zero any unfilled frames. 509 // Retrieve data from the original callback. Zero any unfilled frames.
486 int frames = source_callback_->OnMoreIOData( 510 int frames = source_callback_->OnMoreIOData(
487 source, temp_dest, new_buffers_state); 511 source, temp_dest, new_buffers_state);
488 if (frames < temp_dest->frames()) 512 if (frames < temp_dest->frames())
489 temp_dest->ZeroFramesPartial(frames, temp_dest->frames() - frames); 513 temp_dest->ZeroFramesPartial(frames, temp_dest->frames() - frames);
490 514
491 // Scale the number of frames we got back in terms of input bytes to output 515 // Scale the number of frames we got back in terms of input bytes to output
492 // bytes accordingly. 516 // bytes accordingly.
493 outstanding_audio_bytes_ += 517 outstanding_audio_bytes_ +=
494 (temp_dest->frames() * input_bytes_per_frame_) / io_ratio_; 518 (temp_dest->frames() * input_bytes_per_frame_) / io_ratio_;
(...skipping 14 matching lines...) Expand all
509 source_callback_->OnError(stream, code); 533 source_callback_->OnError(stream, code);
510 } 534 }
511 535
512 void OnMoreDataResampler::WaitTillDataReady() { 536 void OnMoreDataResampler::WaitTillDataReady() {
513 base::AutoLock auto_lock(source_lock_); 537 base::AutoLock auto_lock(source_lock_);
514 if (source_callback_ && !outstanding_audio_bytes_) 538 if (source_callback_ && !outstanding_audio_bytes_)
515 source_callback_->WaitTillDataReady(); 539 source_callback_->WaitTillDataReady();
516 } 540 }
517 541
518 } // namespace media 542 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/audio_output_controller.cc ('k') | media/audio/win/waveout_output_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698