Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(335)

Side by Side Diff: media/audio/audio_input_device.cc

Issue 12440027: Do not pass the string device_id via IPC message to create an audio input stream (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: addressed Per's comments. Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/audio/audio_input_device.h ('k') | media/audio/audio_input_ipc.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "base/bind.h" 7 #include "base/bind.h"
8 #include "base/message_loop.h" 8 #include "base/message_loop.h"
9 #include "base/threading/thread_restrictions.h" 9 #include "base/threading/thread_restrictions.h"
10 #include "base/time.h" 10 #include "base/time.h"
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 CaptureCallback* capture_callback_; 42 CaptureCallback* capture_callback_;
43 scoped_ptr<AudioBus> audio_bus_; 43 scoped_ptr<AudioBus> audio_bus_;
44 DISALLOW_COPY_AND_ASSIGN(AudioThreadCallback); 44 DISALLOW_COPY_AND_ASSIGN(AudioThreadCallback);
45 }; 45 };
46 46
47 AudioInputDevice::AudioInputDevice( 47 AudioInputDevice::AudioInputDevice(
48 AudioInputIPC* ipc, 48 AudioInputIPC* ipc,
49 const scoped_refptr<base::MessageLoopProxy>& io_loop) 49 const scoped_refptr<base::MessageLoopProxy>& io_loop)
50 : ScopedLoopObserver(io_loop), 50 : ScopedLoopObserver(io_loop),
51 callback_(NULL), 51 callback_(NULL),
52 event_handler_(NULL),
53 ipc_(ipc), 52 ipc_(ipc),
54 stream_id_(0), 53 stream_id_(0),
55 session_id_(0), 54 session_id_(0),
56 pending_device_ready_(false),
57 agc_is_enabled_(false) { 55 agc_is_enabled_(false) {
58 CHECK(ipc_); 56 CHECK(ipc_);
59 } 57 }
60 58
61 void AudioInputDevice::Initialize(const AudioParameters& params, 59 void AudioInputDevice::Initialize(const AudioParameters& params,
62 CaptureCallback* callback, 60 CaptureCallback* callback,
63 CaptureEventHandler* event_handler) { 61 int session_id) {
64 DCHECK(!callback_); 62 DCHECK(!callback_);
65 DCHECK(!event_handler_); 63 DCHECK_EQ(0, session_id_);
66 audio_parameters_ = params; 64 audio_parameters_ = params;
67 callback_ = callback; 65 callback_ = callback;
68 event_handler_ = event_handler; 66 session_id_ = session_id;
69 }
70
71 void AudioInputDevice::SetDevice(int session_id) {
72 DVLOG(1) << "SetDevice (session_id=" << session_id << ")";
73 message_loop()->PostTask(FROM_HERE,
74 base::Bind(&AudioInputDevice::SetSessionIdOnIOThread, this, session_id));
75 } 67 }
76 68
77 void AudioInputDevice::Start() { 69 void AudioInputDevice::Start() {
78 DVLOG(1) << "Start()"; 70 DVLOG(1) << "Start()";
79 message_loop()->PostTask(FROM_HERE, 71 message_loop()->PostTask(FROM_HERE,
80 base::Bind(&AudioInputDevice::InitializeOnIOThread, this)); 72 base::Bind(&AudioInputDevice::InitializeOnIOThread, this));
81 } 73 }
82 74
83 void AudioInputDevice::Stop() { 75 void AudioInputDevice::Stop() {
84 DVLOG(1) << "Stop()"; 76 DVLOG(1) << "Stop()";
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 return; 149 return;
158 150
159 switch (state) { 151 switch (state) {
160 case AudioInputIPCDelegate::kStopped: 152 case AudioInputIPCDelegate::kStopped:
161 // TODO(xians): Should we just call ShutDownOnIOThread here instead? 153 // TODO(xians): Should we just call ShutDownOnIOThread here instead?
162 ipc_->RemoveDelegate(stream_id_); 154 ipc_->RemoveDelegate(stream_id_);
163 155
164 audio_thread_.Stop(MessageLoop::current()); 156 audio_thread_.Stop(MessageLoop::current());
165 audio_callback_.reset(); 157 audio_callback_.reset();
166 158
167 if (event_handler_)
168 event_handler_->OnDeviceStopped();
169
170 stream_id_ = 0; 159 stream_id_ = 0;
171 pending_device_ready_ = false;
172 break; 160 break;
173 case AudioInputIPCDelegate::kRecording: 161 case AudioInputIPCDelegate::kRecording:
174 NOTIMPLEMENTED(); 162 NOTIMPLEMENTED();
175 break; 163 break;
176 case AudioInputIPCDelegate::kError: 164 case AudioInputIPCDelegate::kError:
177 DLOG(WARNING) << "AudioInputDevice::OnStateChanged(kError)"; 165 DLOG(WARNING) << "AudioInputDevice::OnStateChanged(kError)";
178 // Don't dereference the callback object if the audio thread 166 // Don't dereference the callback object if the audio thread
179 // is stopped or stopping. That could mean that the callback 167 // is stopped or stopping. That could mean that the callback
180 // object has been deleted. 168 // object has been deleted.
181 // TODO(tommi): Add an explicit contract for clearing the callback 169 // TODO(tommi): Add an explicit contract for clearing the callback
182 // object. Possibly require calling Initialize again or provide 170 // object. Possibly require calling Initialize again or provide
183 // a callback object via Start() and clear it in Stop(). 171 // a callback object via Start() and clear it in Stop().
184 if (!audio_thread_.IsStopped()) 172 if (!audio_thread_.IsStopped())
185 callback_->OnCaptureError(); 173 callback_->OnCaptureError();
186 break; 174 break;
187 default: 175 default:
188 NOTREACHED(); 176 NOTREACHED();
189 break; 177 break;
190 } 178 }
191 } 179 }
192 180
193 void AudioInputDevice::OnDeviceReady(const std::string& device_id) {
194 DCHECK(message_loop()->BelongsToCurrentThread());
195 DVLOG(1) << "OnDeviceReady (device_id=" << device_id << ")";
196
197 // Takes care of the case when Stop() is called before OnDeviceReady().
198 if (!pending_device_ready_)
199 return;
200
201 // If AudioInputDeviceManager returns an empty string, it means no device
202 // is ready for start.
203 if (device_id.empty()) {
204 ipc_->RemoveDelegate(stream_id_);
205 stream_id_ = 0;
206 } else {
207 ipc_->CreateStream(stream_id_, audio_parameters_, device_id,
208 agc_is_enabled_, kRequestedSharedMemoryCount);
209 }
210
211 pending_device_ready_ = false;
212 // Notify the client that the device has been started.
213 if (event_handler_)
214 event_handler_->OnDeviceStarted(device_id);
215 }
216
217 void AudioInputDevice::OnIPCClosed() { 181 void AudioInputDevice::OnIPCClosed() {
218 ipc_ = NULL; 182 ipc_ = NULL;
219 } 183 }
220 184
221 AudioInputDevice::~AudioInputDevice() { 185 AudioInputDevice::~AudioInputDevice() {
222 // TODO(henrika): The current design requires that the user calls 186 // TODO(henrika): The current design requires that the user calls
223 // Stop before deleting this class. 187 // Stop before deleting this class.
224 CHECK_EQ(0, stream_id_); 188 CHECK_EQ(0, stream_id_);
225 } 189 }
226 190
227 void AudioInputDevice::InitializeOnIOThread() { 191 void AudioInputDevice::InitializeOnIOThread() {
228 DCHECK(message_loop()->BelongsToCurrentThread()); 192 DCHECK(message_loop()->BelongsToCurrentThread());
229 // Make sure we don't call Start() more than once. 193 // Make sure we don't call Start() more than once.
230 DCHECK_EQ(0, stream_id_); 194 DCHECK_EQ(0, stream_id_);
231 if (stream_id_) 195 if (stream_id_)
232 return; 196 return;
233 197
198 if (session_id_ <= 0) {
199 DLOG(WARNING) << "Invalid session id for the input stream " << session_id_;
200 return;
201 }
202
234 stream_id_ = ipc_->AddDelegate(this); 203 stream_id_ = ipc_->AddDelegate(this);
235 // If |session_id_| is not specified, it will directly create the stream; 204 ipc_->CreateStream(stream_id_, session_id_, audio_parameters_,
236 // otherwise it will send a AudioInputHostMsg_StartDevice msg to the browser 205 agc_is_enabled_, kRequestedSharedMemoryCount);
237 // and create the stream when getting a OnDeviceReady() callback.
238 if (!session_id_) {
239 ipc_->CreateStream(stream_id_, audio_parameters_,
240 AudioManagerBase::kDefaultDeviceId, agc_is_enabled_,
241 kRequestedSharedMemoryCount);
242 } else {
243 ipc_->StartDevice(stream_id_, session_id_);
244 pending_device_ready_ = true;
245 }
246 }
247
248 void AudioInputDevice::SetSessionIdOnIOThread(int session_id) {
249 DCHECK(message_loop()->BelongsToCurrentThread());
250 session_id_ = session_id;
251 } 206 }
252 207
253 void AudioInputDevice::StartOnIOThread() { 208 void AudioInputDevice::StartOnIOThread() {
254 DCHECK(message_loop()->BelongsToCurrentThread()); 209 DCHECK(message_loop()->BelongsToCurrentThread());
255 if (stream_id_) 210 if (stream_id_)
256 ipc_->RecordStream(stream_id_); 211 ipc_->RecordStream(stream_id_);
257 } 212 }
258 213
259 void AudioInputDevice::ShutDownOnIOThread() { 214 void AudioInputDevice::ShutDownOnIOThread() {
260 DCHECK(message_loop()->BelongsToCurrentThread()); 215 DCHECK(message_loop()->BelongsToCurrentThread());
261 // NOTE: |completion| may be NULL. 216 // NOTE: |completion| may be NULL.
262 // Make sure we don't call shutdown more than once. 217 // Make sure we don't call shutdown more than once.
263 if (stream_id_) { 218 if (stream_id_) {
264 if (ipc_) { 219 if (ipc_) {
265 ipc_->CloseStream(stream_id_); 220 ipc_->CloseStream(stream_id_);
266 ipc_->RemoveDelegate(stream_id_); 221 ipc_->RemoveDelegate(stream_id_);
267 } 222 }
268 223
269 stream_id_ = 0; 224 stream_id_ = 0;
270 session_id_ = 0;
271 pending_device_ready_ = false;
272 agc_is_enabled_ = false; 225 agc_is_enabled_ = false;
273 } 226 }
274 227
275 // We can run into an issue where ShutDownOnIOThread is called right after 228 // We can run into an issue where ShutDownOnIOThread is called right after
276 // OnStreamCreated is called in cases where Start/Stop are called before we 229 // OnStreamCreated is called in cases where Start/Stop are called before we
277 // get the OnStreamCreated callback. To handle that corner case, we call 230 // get the OnStreamCreated callback. To handle that corner case, we call
278 // Stop(). In most cases, the thread will already be stopped. 231 // Stop(). In most cases, the thread will already be stopped.
279 // Another situation is when the IO thread goes away before Stop() is called 232 // Another situation is when the IO thread goes away before Stop() is called
280 // in which case, we cannot use the message loop to close the thread handle 233 // in which case, we cannot use the message loop to close the thread handle
281 // and can't not rely on the main thread existing either. 234 // and can't not rely on the main thread existing either.
282 base::ThreadRestrictions::ScopedAllowIO allow_io; 235 base::ThreadRestrictions::ScopedAllowIO allow_io;
283 audio_thread_.Stop(NULL); 236 audio_thread_.Stop(NULL);
284 audio_callback_.reset(); 237 audio_callback_.reset();
238 session_id_ = 0;
285 } 239 }
286 240
287 void AudioInputDevice::SetVolumeOnIOThread(double volume) { 241 void AudioInputDevice::SetVolumeOnIOThread(double volume) {
288 DCHECK(message_loop()->BelongsToCurrentThread()); 242 DCHECK(message_loop()->BelongsToCurrentThread());
289 if (stream_id_) 243 if (stream_id_)
290 ipc_->SetVolume(stream_id_, volume); 244 ipc_->SetVolume(stream_id_, volume);
291 } 245 }
292 246
293 void AudioInputDevice::SetAutomaticGainControlOnIOThread(bool enabled) { 247 void AudioInputDevice::SetAutomaticGainControlOnIOThread(bool enabled) {
294 DCHECK(message_loop()->BelongsToCurrentThread()); 248 DCHECK(message_loop()->BelongsToCurrentThread());
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 // with nominal range -1.0 -> +1.0. 304 // with nominal range -1.0 -> +1.0.
351 audio_bus_->FromInterleaved(memory, audio_bus_->frames(), bytes_per_sample); 305 audio_bus_->FromInterleaved(memory, audio_bus_->frames(), bytes_per_sample);
352 306
353 // Deliver captured data to the client in floating point format 307 // Deliver captured data to the client in floating point format
354 // and update the audio-delay measurement. 308 // and update the audio-delay measurement.
355 capture_callback_->Capture(audio_bus_.get(), 309 capture_callback_->Capture(audio_bus_.get(),
356 audio_delay_milliseconds, volume); 310 audio_delay_milliseconds, volume);
357 } 311 }
358 312
359 } // namespace media 313 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/audio_input_device.h ('k') | media/audio/audio_input_ipc.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698