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 |