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

Side by Side Diff: media/base/audio_renderer_mixer.cc

Issue 10698066: Switch to pcm_low_latency and enable resampling. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Comments! Remove RefCount. Squash ARMM changes. Created 8 years, 5 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 unified diff | Download patch | Annotate | Revision Log
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/base/audio_renderer_mixer.h" 5 #include "media/base/audio_renderer_mixer.h"
6 6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
7 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "media/audio/audio_util.h"
11 #include "media/base/limits.h"
8 12
9 namespace media { 13 namespace media {
10 14
11 AudioRendererMixer::AudioRendererMixer( 15 AudioRendererMixer::AudioRendererMixer(
12 const AudioParameters& params, const scoped_refptr<AudioRendererSink>& sink) 16 const AudioParameters& input_params, const AudioParameters& output_params,
13 : audio_parameters_(params), 17 const scoped_refptr<AudioRendererSink>& sink)
14 audio_sink_(sink) { 18 : audio_sink_(sink),
15 // TODO(dalecurtis): Once we have resampling we'll need to pass on a different 19 current_audio_delay_milliseconds_(0) {
16 // set of AudioParameters than the ones we're given. 20 // Sanity check sample rates.
17 audio_sink_->Initialize(audio_parameters_, this); 21 DCHECK_LE(input_params.sample_rate(), limits::kMaxSampleRate);
22 DCHECK_GE(input_params.sample_rate(), limits::kMinSampleRate);
23 DCHECK_LE(output_params.sample_rate(), limits::kMaxSampleRate);
24 DCHECK_GE(output_params.sample_rate(), limits::kMinSampleRate);
25
26 // Only resample if necessary since it's expensive.
27 if (input_params.sample_rate() != output_params.sample_rate()) {
28 resampler_.reset(new MultiChannelResampler(
29 output_params.channels(),
30 input_params.sample_rate() / static_cast<double>(
31 output_params.sample_rate()),
32 base::Bind(&AudioRendererMixer::ProvideInput, base::Unretained(this))));
33 }
34
35 audio_sink_->Initialize(output_params, this);
18 audio_sink_->Start(); 36 audio_sink_->Start();
19 } 37 }
20 38
21 AudioRendererMixer::~AudioRendererMixer() { 39 AudioRendererMixer::~AudioRendererMixer() {
22 // AudioRendererSinks must be stopped before being destructed. 40 // AudioRendererSinks must be stopped before being destructed.
23 audio_sink_->Stop(); 41 audio_sink_->Stop();
24 42
43 // Clean up |mixer_input_audio_data_|.
44 for (size_t i = 0; i < mixer_input_audio_data_.size(); ++i)
45 delete [] mixer_input_audio_data_[i];
46 mixer_input_audio_data_.clear();
47
25 // Ensures that all mixer inputs have stopped themselves prior to destruction 48 // Ensures that all mixer inputs have stopped themselves prior to destruction
26 // and have called RemoveMixerInput(). 49 // and have called RemoveMixerInput().
27 DCHECK_EQ(mixer_inputs_.size(), 0U); 50 DCHECK_EQ(mixer_inputs_.size(), 0U);
28 } 51 }
29 52
30 void AudioRendererMixer::AddMixerInput( 53 void AudioRendererMixer::AddMixerInput(
31 const scoped_refptr<AudioRendererMixerInput>& input) { 54 const scoped_refptr<AudioRendererMixerInput>& input) {
32 base::AutoLock auto_lock(mixer_inputs_lock_); 55 base::AutoLock auto_lock(mixer_inputs_lock_);
33 mixer_inputs_.insert(input); 56 mixer_inputs_.insert(input);
34 } 57 }
35 58
36 void AudioRendererMixer::RemoveMixerInput( 59 void AudioRendererMixer::RemoveMixerInput(
37 const scoped_refptr<AudioRendererMixerInput>& input) { 60 const scoped_refptr<AudioRendererMixerInput>& input) {
38 base::AutoLock auto_lock(mixer_inputs_lock_); 61 base::AutoLock auto_lock(mixer_inputs_lock_);
39 mixer_inputs_.erase(input); 62 mixer_inputs_.erase(input);
40 } 63 }
41 64
42 int AudioRendererMixer::Render(const std::vector<float*>& audio_data, 65 int AudioRendererMixer::Render(const std::vector<float*>& audio_data,
43 int number_of_frames, 66 int number_of_frames,
44 int audio_delay_milliseconds) { 67 int audio_delay_milliseconds) {
68 current_audio_delay_milliseconds_ = audio_delay_milliseconds;
69
70 if (resampler_.get())
71 resampler_->Resample(audio_data, number_of_frames);
72 else
73 ProvideInput(audio_data, number_of_frames);
74
75 // Always return the full number of frames requested, ProvideInput() will pad
76 // with silence if it wasn't able to acquire enough data.
77 return number_of_frames;
78 }
79
80 void AudioRendererMixer::ProvideInput(const std::vector<float*>& audio_data,
81 int number_of_frames) {
45 base::AutoLock auto_lock(mixer_inputs_lock_); 82 base::AutoLock auto_lock(mixer_inputs_lock_);
46 83
84 // Allocate staging area for each mixer input's audio data on first call. We
85 // won't know how much to allocate until here because of resampling.
86 if (mixer_input_audio_data_.size() == 0) {
87 // TODO(dalecurtis): If we switch to AVX/SSE optimization, we'll need to
88 // allocate these on 32-byte boundaries and ensure they're sized % 32 bytes.
89 mixer_input_audio_data_.reserve(audio_data.size());
90 for (size_t i = 0; i < audio_data.size(); ++i)
91 mixer_input_audio_data_.push_back(new float[number_of_frames]);
92 mixer_input_audio_data_size_ = number_of_frames;
93 }
94
95 // Sanity check our inputs.
96 DCHECK_LE(number_of_frames, mixer_input_audio_data_size_);
97 DCHECK_EQ(audio_data.size(), mixer_input_audio_data_.size());
98
47 // Zero |audio_data| so we're mixing into a clean buffer and return silence if 99 // Zero |audio_data| so we're mixing into a clean buffer and return silence if
48 // we couldn't get enough data from our inputs. 100 // we couldn't get enough data from our inputs.
49 for (int i = 0; i < audio_parameters_.channels(); ++i) 101 for (size_t i = 0; i < audio_data.size(); ++i)
50 memset(audio_data[i], 0, number_of_frames * sizeof(*audio_data[i])); 102 memset(audio_data[i], 0, number_of_frames * sizeof(*audio_data[i]));
51 103
52 // Have each mixer render its data into an output buffer then mix the result. 104 // Have each mixer render its data into an output buffer then mix the result.
53 for (AudioRendererMixerInputSet::iterator it = mixer_inputs_.begin(); 105 for (AudioRendererMixerInputSet::iterator it = mixer_inputs_.begin();
54 it != mixer_inputs_.end(); ++it) { 106 it != mixer_inputs_.end(); ++it) {
55 const scoped_refptr<AudioRendererMixerInput>& input = *it; 107 const scoped_refptr<AudioRendererMixerInput>& input = *it;
56 108
57 double volume; 109 double volume;
58 input->GetVolume(&volume); 110 input->GetVolume(&volume);
59 111
60 // Nothing to do if the input isn't playing or the volume is zero. 112 // Nothing to do if the input isn't playing.
61 if (!input->playing() || volume == 0.0f) 113 if (!input->playing())
62 continue; 114 continue;
63 115
64 const std::vector<float*>& mixer_input_audio_data = input->audio_data();
65
66 int frames_filled = input->callback()->Render( 116 int frames_filled = input->callback()->Render(
67 mixer_input_audio_data, number_of_frames, audio_delay_milliseconds); 117 mixer_input_audio_data_, number_of_frames,
118 current_audio_delay_milliseconds_);
68 if (frames_filled == 0) 119 if (frames_filled == 0)
69 continue; 120 continue;
70 121
71 // TODO(dalecurtis): Resample audio data.
72
73 // Volume adjust and mix each mixer input into |audio_data| after rendering. 122 // Volume adjust and mix each mixer input into |audio_data| after rendering.
74 // TODO(dalecurtis): Optimize with NEON/SSE/AVX vector_fmac from FFmpeg. 123 // TODO(dalecurtis): Optimize with NEON/SSE/AVX vector_fmac from FFmpeg.
75 for (int j = 0; j < audio_parameters_.channels(); ++j) { 124 for (size_t j = 0; j < audio_data.size(); ++j) {
76 float* dest = audio_data[j]; 125 float* dest = audio_data[j];
77 float* source = mixer_input_audio_data[j]; 126 float* source = mixer_input_audio_data_[j];
78 for (int k = 0; k < frames_filled; ++k) 127 for (int k = 0; k < frames_filled; ++k)
79 dest[k] += source[k] * static_cast<float>(volume); 128 dest[k] += source[k] * static_cast<float>(volume);
80 } 129 }
81 130
82 // No need to clamp values as InterleaveFloatToInt() will take care of this 131 // No need to clamp values as InterleaveFloatToInt() will take care of this
83 // for us later when data is transferred to the browser process. 132 // for us later when data is transferred to the browser process.
84 } 133 }
85
86 // Always return the full number of frames requested, padded with silence if
87 // we couldn't get enough data.
88 return number_of_frames;
89 } 134 }
90 135
91 void AudioRendererMixer::OnRenderError() { 136 void AudioRendererMixer::OnRenderError() {
92 base::AutoLock auto_lock(mixer_inputs_lock_); 137 base::AutoLock auto_lock(mixer_inputs_lock_);
93 138
94 // Call each mixer input and signal an error. 139 // Call each mixer input and signal an error.
95 for (AudioRendererMixerInputSet::iterator it = mixer_inputs_.begin(); 140 for (AudioRendererMixerInputSet::iterator it = mixer_inputs_.begin();
96 it != mixer_inputs_.end(); ++it) { 141 it != mixer_inputs_.end(); ++it) {
97 (*it)->callback()->OnRenderError(); 142 (*it)->callback()->OnRenderError();
98 } 143 }
99 } 144 }
100 145
101 } // namespace media 146 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698