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 |