| 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_->PostTask(FROM_HERE, base::Bind( | 107 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 107 &AudioInputController::DoClose, this, closed_task)); | 108 &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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 } | 175 } |
| 165 | 176 |
| 166 closed_task.Run(); | 177 closed_task.Run(); |
| 167 } | 178 } |
| 168 | 179 |
| 169 void AudioInputController::DoReportError(int code) { | 180 void AudioInputController::DoReportError(int code) { |
| 170 DCHECK(message_loop_->BelongsToCurrentThread()); | 181 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 171 handler_->OnError(this, code); | 182 handler_->OnError(this, code); |
| 172 } | 183 } |
| 173 | 184 |
| 185 void AudioInputController::DoSetVolume(double volume) { |
| 186 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 187 DCHECK_GE(volume, 0); |
| 188 DCHECK_LE(volume, 1.0); |
| 189 |
| 190 if (state_ != kCreated && state_ != kRecording) |
| 191 return; |
| 192 |
| 193 // Only ask for the maximum volume at first call and use cached value |
| 194 // for remaining function calls. |
| 195 if (!max_volume_) { |
| 196 max_volume_ = stream_->GetMaxVolume(); |
| 197 } |
| 198 |
| 199 if (max_volume_ == 0.0) { |
| 200 DLOG(WARNING) << "Failed to access input volume control"; |
| 201 return; |
| 202 } |
| 203 |
| 204 // Set the stream volume and scale to a range matched to the platform. |
| 205 stream_->SetVolume(max_volume_ * volume); |
| 206 } |
| 207 |
| 208 void AudioInputController::DoSetAutomaticGainControl(bool enabled) { |
| 209 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 210 DCHECK_NE(state_, kRecording); |
| 211 |
| 212 // Ensure that the AGC state only can be modified before streaming starts. |
| 213 if (state_ != kCreated || state_ == kRecording) |
| 214 return; |
| 215 |
| 216 stream_->SetAutomaticGainControl(enabled); |
| 217 } |
| 218 |
| 174 void AudioInputController::DoReportNoDataError() { | 219 void AudioInputController::DoReportNoDataError() { |
| 175 DCHECK(creator_loop_->BelongsToCurrentThread()); | 220 DCHECK(creator_loop_->BelongsToCurrentThread()); |
| 176 | 221 |
| 177 // Error notifications should be sent on the audio-manager thread. | 222 // Error notifications should be sent on the audio-manager thread. |
| 178 int code = 0; | 223 int code = 0; |
| 179 message_loop_->PostTask(FROM_HERE, base::Bind( | 224 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 180 &AudioInputController::DoReportError, this, code)); | 225 &AudioInputController::DoReportError, this, code)); |
| 181 } | 226 } |
| 182 | 227 |
| 183 void AudioInputController::DoResetNoDataTimer() { | 228 void AudioInputController::DoResetNoDataTimer() { |
| 184 DCHECK(creator_loop_->BelongsToCurrentThread()); | 229 DCHECK(creator_loop_->BelongsToCurrentThread()); |
| 185 no_data_timer_.Reset(); | 230 no_data_timer_.Reset(); |
| 186 } | 231 } |
| 187 | 232 |
| 188 void AudioInputController::OnData(AudioInputStream* stream, const uint8* data, | 233 void AudioInputController::OnData(AudioInputStream* stream, const uint8* data, |
| 189 uint32 size, uint32 hardware_delay_bytes) { | 234 uint32 size, uint32 hardware_delay_bytes, |
| 235 double volume) { |
| 190 { | 236 { |
| 191 base::AutoLock auto_lock(lock_); | 237 base::AutoLock auto_lock(lock_); |
| 192 if (state_ != kRecording) | 238 if (state_ != kRecording) |
| 193 return; | 239 return; |
| 194 } | 240 } |
| 195 | 241 |
| 196 creator_loop_->PostTask(FROM_HERE, base::Bind( | 242 creator_loop_->PostTask(FROM_HERE, base::Bind( |
| 197 &AudioInputController::DoResetNoDataTimer, this)); | 243 &AudioInputController::DoResetNoDataTimer, this)); |
| 198 | 244 |
| 199 // Use SyncSocket if we are in a low-latency mode. | 245 // Use SyncSocket if we are in a low-latency mode. |
| 200 if (LowLatencyMode()) { | 246 if (LowLatencyMode()) { |
| 201 sync_writer_->Write(data, size); | 247 sync_writer_->Write(data, size, volume); |
| 202 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); | 248 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); |
| 203 return; | 249 return; |
| 204 } | 250 } |
| 205 | 251 |
| 206 handler_->OnData(this, data, size); | 252 handler_->OnData(this, data, size); |
| 207 } | 253 } |
| 208 | 254 |
| 209 void AudioInputController::OnClose(AudioInputStream* stream) { | 255 void AudioInputController::OnClose(AudioInputStream* stream) { |
| 210 DVLOG(1) << "AudioInputController::OnClose()"; | 256 DVLOG(1) << "AudioInputController::OnClose()"; |
| 211 // TODO(satish): Sometimes the device driver closes the input stream without | 257 // TODO(satish): Sometimes the device driver closes the input stream without |
| (...skipping 17 matching lines...) Expand all Loading... |
| 229 stream_->Close(); | 275 stream_->Close(); |
| 230 stream_ = NULL; | 276 stream_ = NULL; |
| 231 } | 277 } |
| 232 | 278 |
| 233 // Should be last in the method, do not touch "this" from here on. | 279 // Should be last in the method, do not touch "this" from here on. |
| 234 if (done != NULL) | 280 if (done != NULL) |
| 235 done->Signal(); | 281 done->Signal(); |
| 236 } | 282 } |
| 237 | 283 |
| 238 } // namespace media | 284 } // namespace media |
| OLD | NEW |