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

Side by Side Diff: media/base/audio_renderer_mixer.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/base/audio_renderer_mixer.h ('k') | media/base/audio_renderer_mixer_input.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/base/audio_renderer_mixer.h" 5 #include "media/base/audio_renderer_mixer.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/logging.h" 9 #include "base/logging.h"
10 #include "media/audio/audio_util.h"
11 #include "media/base/limits.h"
12 #include "media/base/vector_math.h"
13 10
14 namespace media { 11 namespace media {
15 12
16 AudioRendererMixer::AudioRendererMixer( 13 AudioRendererMixer::AudioRendererMixer(
17 const AudioParameters& input_params, const AudioParameters& output_params, 14 const AudioParameters& input_params, const AudioParameters& output_params,
18 const scoped_refptr<AudioRendererSink>& sink) 15 const scoped_refptr<AudioRendererSink>& sink)
19 : audio_sink_(sink), 16 : audio_sink_(sink),
20 current_audio_delay_milliseconds_(0), 17 audio_converter_(input_params, output_params, true) {
21 io_ratio_(1),
22 input_ms_per_frame_(
23 static_cast<double>(base::Time::kMillisecondsPerSecond) /
24 input_params.sample_rate()) {
25 DCHECK(input_params.IsValid());
26 DCHECK(output_params.IsValid());
27
28 // Channel mixing is handled by the browser side currently.
29 DCHECK_EQ(input_params.channels(), output_params.channels());
30
31 // Only resample if necessary since it's expensive.
32 if (input_params.sample_rate() != output_params.sample_rate()) {
33 io_ratio_ = input_params.sample_rate() /
34 static_cast<double>(output_params.sample_rate());
35 resampler_.reset(new MultiChannelResampler(
36 output_params.channels(), io_ratio_,
37 base::Bind(&AudioRendererMixer::ProvideInput, base::Unretained(this))));
38 }
39
40 audio_sink_->Initialize(output_params, this); 18 audio_sink_->Initialize(output_params, this);
41 audio_sink_->Start(); 19 audio_sink_->Start();
42 } 20 }
43 21
44 AudioRendererMixer::~AudioRendererMixer() { 22 AudioRendererMixer::~AudioRendererMixer() {
45 // AudioRendererSinks must be stopped before being destructed. 23 // AudioRendererSinks must be stopped before being destructed.
46 audio_sink_->Stop(); 24 audio_sink_->Stop();
47 25
48 // Ensures that all mixer inputs have stopped themselves prior to destruction 26 // Ensures that all mixer inputs have stopped themselves prior to destruction
49 // and have called RemoveMixerInput(). 27 // and have called RemoveMixerInput().
50 DCHECK_EQ(mixer_inputs_.size(), 0U); 28 DCHECK_EQ(mixer_inputs_.size(), 0U);
51 } 29 }
52 30
53 void AudioRendererMixer::AddMixerInput( 31 void AudioRendererMixer::AddMixerInput(
54 const scoped_refptr<AudioRendererMixerInput>& input) { 32 const scoped_refptr<AudioRendererMixerInput>& input) {
55 base::AutoLock auto_lock(mixer_inputs_lock_); 33 base::AutoLock auto_lock(mixer_inputs_lock_);
56 mixer_inputs_.insert(input); 34 mixer_inputs_.push_back(input);
35 audio_converter_.AddInput(input);
57 } 36 }
58 37
59 void AudioRendererMixer::RemoveMixerInput( 38 void AudioRendererMixer::RemoveMixerInput(
60 const scoped_refptr<AudioRendererMixerInput>& input) { 39 const scoped_refptr<AudioRendererMixerInput>& input) {
61 base::AutoLock auto_lock(mixer_inputs_lock_); 40 base::AutoLock auto_lock(mixer_inputs_lock_);
62 mixer_inputs_.erase(input); 41 audio_converter_.RemoveInput(input);
42 mixer_inputs_.remove(input);
63 } 43 }
64 44
65 int AudioRendererMixer::Render(AudioBus* audio_bus, 45 int AudioRendererMixer::Render(AudioBus* audio_bus,
66 int audio_delay_milliseconds) { 46 int audio_delay_milliseconds) {
67 current_audio_delay_milliseconds_ = audio_delay_milliseconds / io_ratio_; 47 base::AutoLock auto_lock(mixer_inputs_lock_);
68 48
69 if (resampler_.get()) 49 // Set the delay information for each mixer input.
70 resampler_->Resample(audio_bus, audio_bus->frames()); 50 for (AudioRendererMixerInputSet::iterator it = mixer_inputs_.begin();
71 else 51 it != mixer_inputs_.end(); ++it) {
72 ProvideInput(audio_bus); 52 (*it)->set_audio_delay_milliseconds(audio_delay_milliseconds);
53 }
73 54
74 // Always return the full number of frames requested, ProvideInput() will pad 55 audio_converter_.Convert(audio_bus);
75 // with silence if it wasn't able to acquire enough data.
76 return audio_bus->frames(); 56 return audio_bus->frames();
77 } 57 }
78 58
79 void AudioRendererMixer::ProvideInput(AudioBus* audio_bus) {
80 base::AutoLock auto_lock(mixer_inputs_lock_);
81
82 // Allocate staging area for each mixer input's audio data on first call. We
83 // won't know how much to allocate until here because of resampling. Ensure
84 // our intermediate AudioBus is sized exactly as the original. Resize should
85 // only happen once due to the way the resampler works.
86 if (!mixer_input_audio_bus_.get() ||
87 mixer_input_audio_bus_->frames() != audio_bus->frames()) {
88 mixer_input_audio_bus_ =
89 AudioBus::Create(audio_bus->channels(), audio_bus->frames());
90 }
91
92 // Sanity check our inputs.
93 DCHECK_EQ(audio_bus->frames(), mixer_input_audio_bus_->frames());
94 DCHECK_EQ(audio_bus->channels(), mixer_input_audio_bus_->channels());
95
96 // Zero |audio_bus| so we're mixing into a clean buffer and return silence if
97 // we couldn't get enough data from our inputs.
98 audio_bus->Zero();
99
100 // Have each mixer render its data into an output buffer then mix the result.
101 for (AudioRendererMixerInputSet::iterator it = mixer_inputs_.begin();
102 it != mixer_inputs_.end(); ++it) {
103 const scoped_refptr<AudioRendererMixerInput>& input = *it;
104
105 double volume;
106 input->GetVolume(&volume);
107
108 // Nothing to do if the input isn't playing.
109 if (!input->playing())
110 continue;
111
112 int frames_filled = input->callback()->Render(
113 mixer_input_audio_bus_.get(), current_audio_delay_milliseconds_);
114 if (frames_filled == 0)
115 continue;
116
117 // Volume adjust and mix each mixer input into |audio_bus| after rendering.
118 for (int i = 0; i < audio_bus->channels(); ++i) {
119 vector_math::FMAC(
120 mixer_input_audio_bus_->channel(i), volume, frames_filled,
121 audio_bus->channel(i));
122 }
123 }
124
125 // Update the delay estimate.
126 current_audio_delay_milliseconds_ +=
127 audio_bus->frames() * input_ms_per_frame_;
128 }
129
130 void AudioRendererMixer::OnRenderError() { 59 void AudioRendererMixer::OnRenderError() {
131 base::AutoLock auto_lock(mixer_inputs_lock_); 60 base::AutoLock auto_lock(mixer_inputs_lock_);
132 61
133 // Call each mixer input and signal an error. 62 // Call each mixer input and signal an error.
134 for (AudioRendererMixerInputSet::iterator it = mixer_inputs_.begin(); 63 for (AudioRendererMixerInputSet::iterator it = mixer_inputs_.begin();
135 it != mixer_inputs_.end(); ++it) { 64 it != mixer_inputs_.end(); ++it) {
136 (*it)->callback()->OnRenderError(); 65 (*it)->OnRenderError();
137 } 66 }
138 } 67 }
139 68
140 } // namespace media 69 } // namespace media
OLDNEW
« no previous file with comments | « media/base/audio_renderer_mixer.h ('k') | media/base/audio_renderer_mixer_input.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698