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_device.h" | 5 #include "media/audio/audio_input_device.h" | 
| 6 | 6 | 
| 7 #include <stdint.h> | 7 #include <stdint.h> | 
| 8 #include <utility> | 8 #include <utility> | 
| 9 | 9 | 
| 10 #include "base/bind.h" | 10 #include "base/bind.h" | 
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 87 DVLOG(1) << "Start()"; | 87 DVLOG(1) << "Start()"; | 
| 88 task_runner()->PostTask(FROM_HERE, | 88 task_runner()->PostTask(FROM_HERE, | 
| 89 base::Bind(&AudioInputDevice::StartUpOnIOThread, this)); | 89 base::Bind(&AudioInputDevice::StartUpOnIOThread, this)); | 
| 90 } | 90 } | 
| 91 | 91 | 
| 92 void AudioInputDevice::Stop() { | 92 void AudioInputDevice::Stop() { | 
| 93 DVLOG(1) << "Stop()"; | 93 DVLOG(1) << "Stop()"; | 
| 94 | 94 | 
| 95 { | 95 { | 
| 96 base::AutoLock auto_lock(audio_thread_lock_); | 96 base::AutoLock auto_lock(audio_thread_lock_); | 
| 97 audio_thread_.Stop(base::MessageLoop::current()); | 97 audio_thread_.reset(); | 
| 98 stopping_hack_ = true; | 98 stopping_hack_ = true; | 
| 99 } | 99 } | 
| 100 | 100 | 
| 101 task_runner()->PostTask(FROM_HERE, | 101 task_runner()->PostTask(FROM_HERE, | 
| 102 base::Bind(&AudioInputDevice::ShutDownOnIOThread, this)); | 102 base::Bind(&AudioInputDevice::ShutDownOnIOThread, this)); | 
| 103 } | 103 } | 
| 104 | 104 | 
| 105 void AudioInputDevice::SetVolume(double volume) { | 105 void AudioInputDevice::SetVolume(double volume) { | 
| 106 if (volume < 0 || volume > 1.0) { | 106 if (volume < 0 || volume > 1.0) { | 
| 107 DLOG(ERROR) << "Invalid volume value specified"; | 107 DLOG(ERROR) << "Invalid volume value specified"; | 
| (...skipping 28 matching lines...) Expand all Loading... | |
| 136 if (state_ != CREATING_STREAM) | 136 if (state_ != CREATING_STREAM) | 
| 137 return; | 137 return; | 
| 138 | 138 | 
| 139 base::AutoLock auto_lock(audio_thread_lock_); | 139 base::AutoLock auto_lock(audio_thread_lock_); | 
| 140 // TODO(miu): See TODO in OnStreamCreated method for AudioOutputDevice. | 140 // TODO(miu): See TODO in OnStreamCreated method for AudioOutputDevice. | 
| 141 // Interface changes need to be made; likely, after AudioInputDevice is merged | 141 // Interface changes need to be made; likely, after AudioInputDevice is merged | 
| 142 // into AudioOutputDevice (http://crbug.com/179597). | 142 // into AudioOutputDevice (http://crbug.com/179597). | 
| 143 if (stopping_hack_) | 143 if (stopping_hack_) | 
| 144 return; | 144 return; | 
| 145 | 145 | 
| 146 DCHECK(audio_thread_.IsStopped()); | 146 DCHECK(!audio_callback_); | 
| 147 DCHECK(!audio_thread_); | |
| 147 audio_callback_.reset(new AudioInputDevice::AudioThreadCallback( | 148 audio_callback_.reset(new AudioInputDevice::AudioThreadCallback( | 
| 148 audio_parameters_, handle, length, total_segments, callback_)); | 149 audio_parameters_, handle, length, total_segments, callback_)); | 
| 149 audio_thread_.Start( | 150 audio_thread_.reset(new AudioDeviceThread(audio_callback_.get(), | 
| 150 audio_callback_.get(), socket_handle, "AudioInputDevice", true); | 151 socket_handle, "AudioInputDevice")); | 
| 151 | 152 | 
| 152 state_ = RECORDING; | 153 state_ = RECORDING; | 
| 153 ipc_->RecordStream(); | 154 ipc_->RecordStream(); | 
| 154 } | 155 } | 
| 155 | 156 | 
| 156 void AudioInputDevice::OnVolume(double volume) { | 157 void AudioInputDevice::OnVolume(double volume) { | 
| 157 NOTIMPLEMENTED(); | 158 NOTIMPLEMENTED(); | 
| 158 } | 159 } | 
| 159 | 160 | 
| 160 void AudioInputDevice::OnStateChanged( | 161 void AudioInputDevice::OnStateChanged( | 
| (...skipping 14 matching lines...) Expand all Loading... | |
| 175 NOTIMPLEMENTED(); | 176 NOTIMPLEMENTED(); | 
| 176 break; | 177 break; | 
| 177 case AUDIO_INPUT_IPC_DELEGATE_STATE_ERROR: | 178 case AUDIO_INPUT_IPC_DELEGATE_STATE_ERROR: | 
| 178 DLOG(WARNING) << "AudioInputDevice::OnStateChanged(ERROR)"; | 179 DLOG(WARNING) << "AudioInputDevice::OnStateChanged(ERROR)"; | 
| 179 // Don't dereference the callback object if the audio thread | 180 // Don't dereference the callback object if the audio thread | 
| 180 // is stopped or stopping. That could mean that the callback | 181 // is stopped or stopping. That could mean that the callback | 
| 181 // object has been deleted. | 182 // object has been deleted. | 
| 182 // TODO(tommi): Add an explicit contract for clearing the callback | 183 // TODO(tommi): Add an explicit contract for clearing the callback | 
| 183 // object. Possibly require calling Initialize again or provide | 184 // object. Possibly require calling Initialize again or provide | 
| 184 // a callback object via Start() and clear it in Stop(). | 185 // a callback object via Start() and clear it in Stop(). | 
| 185 if (!audio_thread_.IsStopped()) | 186 { | 
| 186 callback_->OnCaptureError( | 187 base::AutoLock auto_lock_(audio_thread_lock_); | 
| 
 
tommi (sloooow) - chröme
2016/06/16 22:19:22
auto_lock
 
 | |
| 187 "AudioInputDevice::OnStateChanged - audio thread still running"); | 188 if (audio_thread_) { | 
| 189 callback_->OnCaptureError( | |
| 190 "AudioInputDevice::OnStateChanged - audio thread still running"); | |
| 191 } | |
| 192 } | |
| 188 break; | 193 break; | 
| 189 default: | 194 default: | 
| 190 NOTREACHED(); | 195 NOTREACHED(); | 
| 191 break; | 196 break; | 
| 192 } | 197 } | 
| 193 } | 198 } | 
| 194 | 199 | 
| 195 void AudioInputDevice::OnIPCClosed() { | 200 void AudioInputDevice::OnIPCClosed() { | 
| 196 DCHECK(task_runner()->BelongsToCurrentThread()); | 201 DCHECK(task_runner()->BelongsToCurrentThread()); | 
| 197 state_ = IPC_CLOSED; | 202 state_ = IPC_CLOSED; | 
| 198 ipc_.reset(); | 203 ipc_.reset(); | 
| 199 } | 204 } | 
| 200 | 205 | 
| 201 AudioInputDevice::~AudioInputDevice() { | 206 AudioInputDevice::~AudioInputDevice() {} | 
| 202 // TODO(henrika): The current design requires that the user calls | |
| 203 // Stop before deleting this class. | |
| 204 DCHECK(audio_thread_.IsStopped()); | |
| 205 } | |
| 206 | 207 | 
| 207 void AudioInputDevice::StartUpOnIOThread() { | 208 void AudioInputDevice::StartUpOnIOThread() { | 
| 208 DCHECK(task_runner()->BelongsToCurrentThread()); | 209 DCHECK(task_runner()->BelongsToCurrentThread()); | 
| 209 | 210 | 
| 210 // Make sure we don't call Start() more than once. | 211 // Make sure we don't call Start() more than once. | 
| 211 if (state_ != IDLE) | 212 if (state_ != IDLE) | 
| 212 return; | 213 return; | 
| 213 | 214 | 
| 214 if (session_id_ <= 0) { | 215 if (session_id_ <= 0) { | 
| 215 DLOG(WARNING) << "Invalid session id for the input stream " << session_id_; | 216 DLOG(WARNING) << "Invalid session id for the input stream " << session_id_; | 
| (...skipping 18 matching lines...) Expand all Loading... | |
| 234 // We can run into an issue where ShutDownOnIOThread is called right after | 235 // We can run into an issue where ShutDownOnIOThread is called right after | 
| 235 // OnStreamCreated is called in cases where Start/Stop are called before we | 236 // OnStreamCreated is called in cases where Start/Stop are called before we | 
| 236 // get the OnStreamCreated callback. To handle that corner case, we call | 237 // get the OnStreamCreated callback. To handle that corner case, we call | 
| 237 // Stop(). In most cases, the thread will already be stopped. | 238 // Stop(). In most cases, the thread will already be stopped. | 
| 238 // | 239 // | 
| 239 // Another situation is when the IO thread goes away before Stop() is called | 240 // Another situation is when the IO thread goes away before Stop() is called | 
| 240 // in which case, we cannot use the message loop to close the thread handle | 241 // in which case, we cannot use the message loop to close the thread handle | 
| 241 // and can't not rely on the main thread existing either. | 242 // and can't not rely on the main thread existing either. | 
| 242 base::AutoLock auto_lock_(audio_thread_lock_); | 243 base::AutoLock auto_lock_(audio_thread_lock_); | 
| 243 base::ThreadRestrictions::ScopedAllowIO allow_io; | 244 base::ThreadRestrictions::ScopedAllowIO allow_io; | 
| 244 audio_thread_.Stop(NULL); | 245 audio_thread_.reset(); | 
| 245 audio_callback_.reset(); | 246 audio_callback_.reset(); | 
| 246 stopping_hack_ = false; | 247 stopping_hack_ = false; | 
| 247 } | 248 } | 
| 248 | 249 | 
| 249 void AudioInputDevice::SetVolumeOnIOThread(double volume) { | 250 void AudioInputDevice::SetVolumeOnIOThread(double volume) { | 
| 250 DCHECK(task_runner()->BelongsToCurrentThread()); | 251 DCHECK(task_runner()->BelongsToCurrentThread()); | 
| 251 if (state_ >= CREATING_STREAM) | 252 if (state_ >= CREATING_STREAM) | 
| 252 ipc_->SetVolume(volume); | 253 ipc_->SetVolume(volume); | 
| 253 } | 254 } | 
| 254 | 255 | 
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 340 capture_callback_->Capture( | 341 capture_callback_->Capture( | 
| 341 audio_bus, | 342 audio_bus, | 
| 342 buffer->params.hardware_delay_bytes / bytes_per_ms_, // Delay in ms | 343 buffer->params.hardware_delay_bytes / bytes_per_ms_, // Delay in ms | 
| 343 buffer->params.volume, buffer->params.key_pressed); | 344 buffer->params.volume, buffer->params.key_pressed); | 
| 344 | 345 | 
| 345 if (++current_segment_id_ >= total_segments_) | 346 if (++current_segment_id_ >= total_segments_) | 
| 346 current_segment_id_ = 0; | 347 current_segment_id_ = 0; | 
| 347 } | 348 } | 
| 348 | 349 | 
| 349 } // namespace media | 350 } // namespace media | 
| OLD | NEW |