OLD | NEW |
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 |
(...skipping 10 matching lines...) Expand all Loading... |
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 ALLOW_THIS_IN_INITIALIZER_LIST(no_data_timer_(FROM_HERE, | 26 ALLOW_THIS_IN_INITIALIZER_LIST(no_data_timer_(FROM_HERE, |
27 base::TimeDelta::FromSeconds(kTimerResetInterval), | 27 base::TimeDelta::FromSeconds(kTimerResetInterval), |
28 this, | 28 this, |
29 &AudioInputController::DoReportNoDataError)), | 29 &AudioInputController::DoReportNoDataError)), |
30 state_(kEmpty), | 30 state_(kEmpty), |
31 sync_writer_(sync_writer) { | 31 sync_writer_(sync_writer), |
| 32 max_volume_(0.0) { |
32 DCHECK(creator_loop_); | 33 DCHECK(creator_loop_); |
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 } |
38 | 39 |
39 // static | 40 // static |
40 scoped_refptr<AudioInputController> AudioInputController::Create( | 41 scoped_refptr<AudioInputController> AudioInputController::Create( |
41 AudioManager* audio_manager, | 42 AudioManager* audio_manager, |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 message_loop_->PostTask(FROM_HERE, base::Bind( | 101 message_loop_->PostTask(FROM_HERE, base::Bind( |
101 &AudioInputController::DoRecord, this)); | 102 &AudioInputController::DoRecord, this)); |
102 } | 103 } |
103 | 104 |
104 void AudioInputController::Close(const base::Closure& closed_task) { | 105 void AudioInputController::Close(const base::Closure& closed_task) { |
105 DCHECK(!closed_task.is_null()); | 106 DCHECK(!closed_task.is_null()); |
106 message_loop_->PostTaskAndReply( | 107 message_loop_->PostTaskAndReply( |
107 FROM_HERE, base::Bind(&AudioInputController::DoClose, this), closed_task); | 108 FROM_HERE, base::Bind(&AudioInputController::DoClose, this), closed_task); |
108 } | 109 } |
109 | 110 |
| 111 void AudioInputController::SetVolume(double volume) { |
| 112 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 113 &AudioInputController::DoSetVolume, this, volume)); |
| 114 } |
| 115 |
| 116 void AudioInputController::SetAutomaticGainControl(bool enabled) { |
| 117 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 118 &AudioInputController::DoSetAutomaticGainControl, this, enabled)); |
| 119 } |
| 120 |
110 void AudioInputController::DoCreate(AudioManager* audio_manager, | 121 void AudioInputController::DoCreate(AudioManager* audio_manager, |
111 const AudioParameters& params, | 122 const AudioParameters& params, |
112 const std::string& device_id) { | 123 const std::string& device_id) { |
113 DCHECK(message_loop_->BelongsToCurrentThread()); | 124 DCHECK(message_loop_->BelongsToCurrentThread()); |
114 | 125 |
115 stream_ = audio_manager->MakeAudioInputStream(params, device_id); | 126 stream_ = audio_manager->MakeAudioInputStream(params, device_id); |
116 | 127 |
117 if (!stream_) { | 128 if (!stream_) { |
118 // TODO(satish): Define error types. | 129 // TODO(satish): Define error types. |
119 handler_->OnError(this, 0); | 130 handler_->OnError(this, 0); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 | 173 |
163 state_ = kClosed; | 174 state_ = kClosed; |
164 } | 175 } |
165 } | 176 } |
166 | 177 |
167 void AudioInputController::DoReportError(int code) { | 178 void AudioInputController::DoReportError(int code) { |
168 DCHECK(message_loop_->BelongsToCurrentThread()); | 179 DCHECK(message_loop_->BelongsToCurrentThread()); |
169 handler_->OnError(this, code); | 180 handler_->OnError(this, code); |
170 } | 181 } |
171 | 182 |
| 183 void AudioInputController::DoSetVolume(double volume) { |
| 184 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 185 DCHECK_GE(volume, 0); |
| 186 DCHECK_LE(volume, 1.0); |
| 187 |
| 188 if (state_ != kCreated && state_ != kRecording) |
| 189 return; |
| 190 |
| 191 // Only ask for the maximum volume at first call and use cached value |
| 192 // for remaining function calls. |
| 193 if (!max_volume_) { |
| 194 max_volume_ = stream_->GetMaxVolume(); |
| 195 } |
| 196 |
| 197 if (max_volume_ == 0.0) { |
| 198 DLOG(WARNING) << "Failed to access input volume control"; |
| 199 return; |
| 200 } |
| 201 |
| 202 // Set the stream volume and scale to a range matched to the platform. |
| 203 stream_->SetVolume(max_volume_ * volume); |
| 204 } |
| 205 |
| 206 void AudioInputController::DoSetAutomaticGainControl(bool enabled) { |
| 207 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 208 DCHECK_NE(state_, kRecording); |
| 209 |
| 210 // Ensure that the AGC state only can be modified before streaming starts. |
| 211 if (state_ != kCreated || state_ == kRecording) |
| 212 return; |
| 213 |
| 214 stream_->SetAutomaticGainControl(enabled); |
| 215 } |
| 216 |
172 void AudioInputController::DoReportNoDataError() { | 217 void AudioInputController::DoReportNoDataError() { |
173 DCHECK(creator_loop_->BelongsToCurrentThread()); | 218 DCHECK(creator_loop_->BelongsToCurrentThread()); |
174 | 219 |
175 // Error notifications should be sent on the audio-manager thread. | 220 // Error notifications should be sent on the audio-manager thread. |
176 int code = 0; | 221 int code = 0; |
177 message_loop_->PostTask(FROM_HERE, base::Bind( | 222 message_loop_->PostTask(FROM_HERE, base::Bind( |
178 &AudioInputController::DoReportError, this, code)); | 223 &AudioInputController::DoReportError, this, code)); |
179 } | 224 } |
180 | 225 |
181 void AudioInputController::DoResetNoDataTimer() { | 226 void AudioInputController::DoResetNoDataTimer() { |
182 DCHECK(creator_loop_->BelongsToCurrentThread()); | 227 DCHECK(creator_loop_->BelongsToCurrentThread()); |
183 no_data_timer_.Reset(); | 228 no_data_timer_.Reset(); |
184 } | 229 } |
185 | 230 |
186 void AudioInputController::OnData(AudioInputStream* stream, const uint8* data, | 231 void AudioInputController::OnData(AudioInputStream* stream, const uint8* data, |
187 uint32 size, uint32 hardware_delay_bytes) { | 232 uint32 size, uint32 hardware_delay_bytes, |
| 233 double volume) { |
188 { | 234 { |
189 base::AutoLock auto_lock(lock_); | 235 base::AutoLock auto_lock(lock_); |
190 if (state_ != kRecording) | 236 if (state_ != kRecording) |
191 return; | 237 return; |
192 } | 238 } |
193 | 239 |
194 creator_loop_->PostTask(FROM_HERE, base::Bind( | 240 creator_loop_->PostTask(FROM_HERE, base::Bind( |
195 &AudioInputController::DoResetNoDataTimer, this)); | 241 &AudioInputController::DoResetNoDataTimer, this)); |
196 | 242 |
197 // Use SyncSocket if we are in a low-latency mode. | 243 // Use SyncSocket if we are in a low-latency mode. |
198 if (LowLatencyMode()) { | 244 if (LowLatencyMode()) { |
199 sync_writer_->Write(data, size); | 245 sync_writer_->Write(data, size, volume); |
200 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); | 246 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); |
201 return; | 247 return; |
202 } | 248 } |
203 | 249 |
204 handler_->OnData(this, data, size); | 250 handler_->OnData(this, data, size); |
205 } | 251 } |
206 | 252 |
207 void AudioInputController::OnClose(AudioInputStream* stream) { | 253 void AudioInputController::OnClose(AudioInputStream* stream) { |
208 DVLOG(1) << "AudioInputController::OnClose()"; | 254 DVLOG(1) << "AudioInputController::OnClose()"; |
209 // TODO(satish): Sometimes the device driver closes the input stream without | 255 // TODO(satish): Sometimes the device driver closes the input stream without |
(...skipping 17 matching lines...) Expand all Loading... |
227 stream_->Close(); | 273 stream_->Close(); |
228 stream_ = NULL; | 274 stream_ = NULL; |
229 } | 275 } |
230 | 276 |
231 // Should be last in the method, do not touch "this" from here on. | 277 // Should be last in the method, do not touch "this" from here on. |
232 if (done != NULL) | 278 if (done != NULL) |
233 done->Signal(); | 279 done->Signal(); |
234 } | 280 } |
235 | 281 |
236 } // namespace media | 282 } // namespace media |
OLD | NEW |