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

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

Issue 9702019: Adds Analog Gain Control (AGC) to the WebRTC client. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased Created 8 years, 9 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
« no previous file with comments | « media/audio/audio_input_controller.h ('k') | media/audio/audio_input_controller_unittest.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_input_controller.h" 5 #include "media/audio/audio_input_controller.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/threading/thread_restrictions.h" 8 #include "base/threading/thread_restrictions.h"
9 #include "media/base/limits.h" 9 #include "media/base/limits.h"
10 10
11 namespace { 11 namespace {
12 const int kMaxInputChannels = 2; 12 const int kMaxInputChannels = 2;
13 const int kTimerResetInterval = 1; // One second. 13 const int kTimerResetInterval = 1; // One second.
14 } 14 }
15 15
16 namespace media { 16 namespace media {
17 17
18 // static 18 // static
19 AudioInputController::Factory* AudioInputController::factory_ = NULL; 19 AudioInputController::Factory* AudioInputController::factory_ = NULL;
20 20
21 AudioInputController::AudioInputController(EventHandler* handler, 21 AudioInputController::AudioInputController(EventHandler* handler,
22 SyncWriter* sync_writer) 22 SyncWriter* sync_writer)
23 : creator_loop_(base::MessageLoopProxy::current()), 23 : creator_loop_(base::MessageLoopProxy::current()),
24 handler_(handler), 24 handler_(handler),
25 stream_(NULL), 25 stream_(NULL),
26 state_(kEmpty), 26 state_(kEmpty),
27 sync_writer_(sync_writer) { 27 sync_writer_(sync_writer),
28 max_volume_(0.0) {
28 DCHECK(creator_loop_); 29 DCHECK(creator_loop_);
29 no_data_timer_.reset(new base::DelayTimer<AudioInputController>(FROM_HERE, 30 no_data_timer_.reset(new base::DelayTimer<AudioInputController>(FROM_HERE,
30 base::TimeDelta::FromSeconds(kTimerResetInterval), 31 base::TimeDelta::FromSeconds(kTimerResetInterval),
31 this, 32 this,
32 &AudioInputController::DoReportNoDataError)); 33 &AudioInputController::DoReportNoDataError));
33 } 34 }
34 35
35 AudioInputController::~AudioInputController() { 36 AudioInputController::~AudioInputController() {
36 DCHECK(kClosed == state_ || kCreated == state_ || kEmpty == state_); 37 DCHECK(kClosed == state_ || kCreated == state_ || kEmpty == state_);
37 } 38 }
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 DCHECK(!closed_task.is_null()); 106 DCHECK(!closed_task.is_null());
106 DCHECK(creator_loop_->BelongsToCurrentThread()); 107 DCHECK(creator_loop_->BelongsToCurrentThread());
107 // See crbug.com/119783: Deleting the timer now to avoid disaster if 108 // See crbug.com/119783: Deleting the timer now to avoid disaster if
108 // AudioInputController is destructed on a thread other than the creator 109 // AudioInputController is destructed on a thread other than the creator
109 // thread. 110 // thread.
110 no_data_timer_.reset(); 111 no_data_timer_.reset();
111 message_loop_->PostTaskAndReply( 112 message_loop_->PostTaskAndReply(
112 FROM_HERE, base::Bind(&AudioInputController::DoClose, this), closed_task); 113 FROM_HERE, base::Bind(&AudioInputController::DoClose, this), closed_task);
113 } 114 }
114 115
116 void AudioInputController::SetVolume(double volume) {
117 message_loop_->PostTask(FROM_HERE, base::Bind(
118 &AudioInputController::DoSetVolume, this, volume));
119 }
120
121 void AudioInputController::SetAutomaticGainControl(bool enabled) {
122 message_loop_->PostTask(FROM_HERE, base::Bind(
123 &AudioInputController::DoSetAutomaticGainControl, this, enabled));
124 }
125
115 void AudioInputController::DoCreate(AudioManager* audio_manager, 126 void AudioInputController::DoCreate(AudioManager* audio_manager,
116 const AudioParameters& params, 127 const AudioParameters& params,
117 const std::string& device_id) { 128 const std::string& device_id) {
118 DCHECK(message_loop_->BelongsToCurrentThread()); 129 DCHECK(message_loop_->BelongsToCurrentThread());
119 130
120 stream_ = audio_manager->MakeAudioInputStream(params, device_id); 131 stream_ = audio_manager->MakeAudioInputStream(params, device_id);
121 132
122 if (!stream_) { 133 if (!stream_) {
123 // TODO(satish): Define error types. 134 // TODO(satish): Define error types.
124 handler_->OnError(this, 0); 135 handler_->OnError(this, 0);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 178
168 state_ = kClosed; 179 state_ = kClosed;
169 } 180 }
170 } 181 }
171 182
172 void AudioInputController::DoReportError(int code) { 183 void AudioInputController::DoReportError(int code) {
173 DCHECK(message_loop_->BelongsToCurrentThread()); 184 DCHECK(message_loop_->BelongsToCurrentThread());
174 handler_->OnError(this, code); 185 handler_->OnError(this, code);
175 } 186 }
176 187
188 void AudioInputController::DoSetVolume(double volume) {
189 DCHECK(message_loop_->BelongsToCurrentThread());
190 DCHECK_GE(volume, 0);
191 DCHECK_LE(volume, 1.0);
192
193 if (state_ != kCreated && state_ != kRecording)
194 return;
195
196 // Only ask for the maximum volume at first call and use cached value
197 // for remaining function calls.
198 if (!max_volume_) {
199 max_volume_ = stream_->GetMaxVolume();
200 }
201
202 if (max_volume_ == 0.0) {
203 DLOG(WARNING) << "Failed to access input volume control";
204 return;
205 }
206
207 // Set the stream volume and scale to a range matched to the platform.
208 stream_->SetVolume(max_volume_ * volume);
209 }
210
211 void AudioInputController::DoSetAutomaticGainControl(bool enabled) {
212 DCHECK(message_loop_->BelongsToCurrentThread());
213 DCHECK_NE(state_, kRecording);
214
215 // Ensure that the AGC state only can be modified before streaming starts.
216 if (state_ != kCreated || state_ == kRecording)
217 return;
218
219 stream_->SetAutomaticGainControl(enabled);
220 }
221
177 void AudioInputController::DoReportNoDataError() { 222 void AudioInputController::DoReportNoDataError() {
178 DCHECK(creator_loop_->BelongsToCurrentThread()); 223 DCHECK(creator_loop_->BelongsToCurrentThread());
179 224
180 // Error notifications should be sent on the audio-manager thread. 225 // Error notifications should be sent on the audio-manager thread.
181 int code = 0; 226 int code = 0;
182 message_loop_->PostTask(FROM_HERE, base::Bind( 227 message_loop_->PostTask(FROM_HERE, base::Bind(
183 &AudioInputController::DoReportError, this, code)); 228 &AudioInputController::DoReportError, this, code));
184 } 229 }
185 230
186 void AudioInputController::DoResetNoDataTimer() { 231 void AudioInputController::DoResetNoDataTimer() {
187 DCHECK(creator_loop_->BelongsToCurrentThread()); 232 DCHECK(creator_loop_->BelongsToCurrentThread());
188 if (no_data_timer_.get()) 233 if (no_data_timer_.get())
189 no_data_timer_->Reset(); 234 no_data_timer_->Reset();
190 } 235 }
191 236
192 void AudioInputController::OnData(AudioInputStream* stream, const uint8* data, 237 void AudioInputController::OnData(AudioInputStream* stream, const uint8* data,
193 uint32 size, uint32 hardware_delay_bytes) { 238 uint32 size, uint32 hardware_delay_bytes,
239 double volume) {
194 { 240 {
195 base::AutoLock auto_lock(lock_); 241 base::AutoLock auto_lock(lock_);
196 if (state_ != kRecording) 242 if (state_ != kRecording)
197 return; 243 return;
198 } 244 }
199 245
200 creator_loop_->PostTask(FROM_HERE, base::Bind( 246 creator_loop_->PostTask(FROM_HERE, base::Bind(
201 &AudioInputController::DoResetNoDataTimer, this)); 247 &AudioInputController::DoResetNoDataTimer, this));
202 248
203 // Use SyncSocket if we are in a low-latency mode. 249 // Use SyncSocket if we are in a low-latency mode.
204 if (LowLatencyMode()) { 250 if (LowLatencyMode()) {
205 sync_writer_->Write(data, size); 251 sync_writer_->Write(data, size, volume);
206 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); 252 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes);
207 return; 253 return;
208 } 254 }
209 255
210 handler_->OnData(this, data, size); 256 handler_->OnData(this, data, size);
211 } 257 }
212 258
213 void AudioInputController::OnClose(AudioInputStream* stream) { 259 void AudioInputController::OnClose(AudioInputStream* stream) {
214 DVLOG(1) << "AudioInputController::OnClose()"; 260 DVLOG(1) << "AudioInputController::OnClose()";
215 // TODO(satish): Sometimes the device driver closes the input stream without 261 // TODO(satish): Sometimes the device driver closes the input stream without
(...skipping 17 matching lines...) Expand all
233 stream_->Close(); 279 stream_->Close();
234 stream_ = NULL; 280 stream_ = NULL;
235 } 281 }
236 282
237 // Should be last in the method, do not touch "this" from here on. 283 // Should be last in the method, do not touch "this" from here on.
238 if (done != NULL) 284 if (done != NULL)
239 done->Signal(); 285 done->Signal();
240 } 286 }
241 287
242 } // namespace media 288 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/audio_input_controller.h ('k') | media/audio/audio_input_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698