Chromium Code Reviews| 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(volume >= 0 && volume <= 1.0); | |
|
scherkus (not reviewing)
2012/03/20 13:49:41
nit: if you split these DCHECKs into DCHECK_GE() a
henrika (OOO until Aug 14)
2012/03/21 10:16:04
Nice. Thanks.
| |
| 188 | |
| 189 if (state_ != kCreated && state_ != kRecording) | |
| 190 return; | |
| 191 | |
| 192 // Only ask for the maximum volume at first call and use cached value | |
| 193 // for remaining function calls. | |
| 194 if (!max_volume_) { | |
| 195 max_volume_ = stream_->GetMaxVolume(); | |
| 196 } | |
| 197 | |
| 198 if (max_volume_ == 0.0) { | |
| 199 DLOG(WARNING) << "Failed to access input volume control"; | |
| 200 return; | |
| 201 } | |
| 202 | |
| 203 // Set the stream volume and scale to a range matched to the platform. | |
| 204 stream_->SetVolume(max_volume_ * volume); | |
| 205 } | |
| 206 | |
| 207 void AudioInputController::DoSetAutomaticGainControl(bool enabled) { | |
| 208 DCHECK(message_loop_->BelongsToCurrentThread()); | |
| 209 | |
| 210 if (state_ != kCreated) | |
| 211 return; | |
| 212 | |
| 213 stream_->SetAutomaticGainControl(enabled); | |
| 214 } | |
| 215 | |
| 174 void AudioInputController::DoReportNoDataError() { | 216 void AudioInputController::DoReportNoDataError() { |
| 175 DCHECK(creator_loop_->BelongsToCurrentThread()); | 217 DCHECK(creator_loop_->BelongsToCurrentThread()); |
| 176 | 218 |
| 177 // Error notifications should be sent on the audio-manager thread. | 219 // Error notifications should be sent on the audio-manager thread. |
| 178 int code = 0; | 220 int code = 0; |
| 179 message_loop_->PostTask(FROM_HERE, base::Bind( | 221 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 180 &AudioInputController::DoReportError, this, code)); | 222 &AudioInputController::DoReportError, this, code)); |
| 181 } | 223 } |
| 182 | 224 |
| 183 void AudioInputController::DoResetNoDataTimer() { | 225 void AudioInputController::DoResetNoDataTimer() { |
| 184 DCHECK(creator_loop_->BelongsToCurrentThread()); | 226 DCHECK(creator_loop_->BelongsToCurrentThread()); |
| 185 no_data_timer_.Reset(); | 227 no_data_timer_.Reset(); |
| 186 } | 228 } |
| 187 | 229 |
| 188 void AudioInputController::OnData(AudioInputStream* stream, const uint8* data, | 230 void AudioInputController::OnData(AudioInputStream* stream, const uint8* data, |
| 189 uint32 size, uint32 hardware_delay_bytes) { | 231 uint32 size, uint32 hardware_delay_bytes, |
| 232 double volume) { | |
| 190 { | 233 { |
| 191 base::AutoLock auto_lock(lock_); | 234 base::AutoLock auto_lock(lock_); |
| 192 if (state_ != kRecording) | 235 if (state_ != kRecording) |
| 193 return; | 236 return; |
| 194 } | 237 } |
| 195 | 238 |
| 196 creator_loop_->PostTask(FROM_HERE, base::Bind( | 239 creator_loop_->PostTask(FROM_HERE, base::Bind( |
| 197 &AudioInputController::DoResetNoDataTimer, this)); | 240 &AudioInputController::DoResetNoDataTimer, this)); |
| 198 | 241 |
| 199 // Use SyncSocket if we are in a low-latency mode. | 242 // Use SyncSocket if we are in a low-latency mode. |
| 200 if (LowLatencyMode()) { | 243 if (LowLatencyMode()) { |
| 201 sync_writer_->Write(data, size); | 244 sync_writer_->Write(data, size, volume); |
| 202 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); | 245 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); |
| 203 return; | 246 return; |
| 204 } | 247 } |
| 205 | 248 |
| 206 handler_->OnData(this, data, size); | 249 handler_->OnData(this, data, size); |
| 207 } | 250 } |
| 208 | 251 |
| 209 void AudioInputController::OnClose(AudioInputStream* stream) { | 252 void AudioInputController::OnClose(AudioInputStream* stream) { |
| 210 DVLOG(1) << "AudioInputController::OnClose()"; | 253 DVLOG(1) << "AudioInputController::OnClose()"; |
| 211 // TODO(satish): Sometimes the device driver closes the input stream without | 254 // TODO(satish): Sometimes the device driver closes the input stream without |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 229 stream_->Close(); | 272 stream_->Close(); |
| 230 stream_ = NULL; | 273 stream_ = NULL; |
| 231 } | 274 } |
| 232 | 275 |
| 233 // Should be last in the method, do not touch "this" from here on. | 276 // Should be last in the method, do not touch "this" from here on. |
| 234 if (done != NULL) | 277 if (done != NULL) |
| 235 done->Signal(); | 278 done->Signal(); |
| 236 } | 279 } |
| 237 | 280 |
| 238 } // namespace media | 281 } // namespace media |
| OLD | NEW |