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 "content/renderer/media/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" |
11 #include "media/audio/audio_manager_base.h" | 11 #include "media/audio/audio_manager_base.h" |
12 #include "media/audio/audio_util.h" | 12 #include "media/audio/audio_util.h" |
13 | 13 |
| 14 namespace media { |
| 15 |
| 16 AudioInputDevice::CaptureCallback::~CaptureCallback() {} |
| 17 AudioInputDevice::CaptureEventHandler::~CaptureEventHandler() {} |
| 18 |
14 // Takes care of invoking the capture callback on the audio thread. | 19 // Takes care of invoking the capture callback on the audio thread. |
15 // An instance of this class is created for each capture stream in | 20 // An instance of this class is created for each capture stream in |
16 // OnLowLatencyCreated(). | 21 // OnLowLatencyCreated(). |
17 class AudioInputDevice::AudioThreadCallback | 22 class AudioInputDevice::AudioThreadCallback |
18 : public AudioDeviceThread::Callback { | 23 : public AudioDeviceThread::Callback { |
19 public: | 24 public: |
20 AudioThreadCallback(const media::AudioParameters& audio_parameters, | 25 AudioThreadCallback(const AudioParameters& audio_parameters, |
21 base::SharedMemoryHandle memory, | 26 base::SharedMemoryHandle memory, |
22 int memory_length, | 27 int memory_length, |
23 CaptureCallback* capture_callback); | 28 CaptureCallback* capture_callback); |
24 virtual ~AudioThreadCallback(); | 29 virtual ~AudioThreadCallback(); |
25 | 30 |
26 virtual void MapSharedMemory() OVERRIDE; | 31 virtual void MapSharedMemory() OVERRIDE; |
27 | 32 |
28 // Called whenever we receive notifications about pending data. | 33 // Called whenever we receive notifications about pending data. |
29 virtual void Process(int pending_data) OVERRIDE; | 34 virtual void Process(int pending_data) OVERRIDE; |
30 | 35 |
31 private: | 36 private: |
32 CaptureCallback* capture_callback_; | 37 CaptureCallback* capture_callback_; |
33 DISALLOW_COPY_AND_ASSIGN(AudioThreadCallback); | 38 DISALLOW_COPY_AND_ASSIGN(AudioThreadCallback); |
34 }; | 39 }; |
35 | 40 |
36 AudioInputDevice::AudioInputDevice( | 41 AudioInputDevice::AudioInputDevice( |
37 media::AudioInputIPC* ipc, | 42 AudioInputIPC* ipc, |
38 const scoped_refptr<base::MessageLoopProxy>& io_loop) | 43 const scoped_refptr<base::MessageLoopProxy>& io_loop) |
39 : ScopedLoopObserver(io_loop), | 44 : ScopedLoopObserver(io_loop), |
40 callback_(NULL), | 45 callback_(NULL), |
41 event_handler_(NULL), | 46 event_handler_(NULL), |
42 ipc_(ipc), | 47 ipc_(ipc), |
43 stream_id_(0), | 48 stream_id_(0), |
44 session_id_(0), | 49 session_id_(0), |
45 pending_device_ready_(false), | 50 pending_device_ready_(false), |
46 agc_is_enabled_(false) { | 51 agc_is_enabled_(false) { |
47 CHECK(ipc_); | 52 CHECK(ipc_); |
48 } | 53 } |
49 | 54 |
50 void AudioInputDevice::Initialize(const media::AudioParameters& params, | 55 void AudioInputDevice::Initialize(const AudioParameters& params, |
51 CaptureCallback* callback, | 56 CaptureCallback* callback, |
52 CaptureEventHandler* event_handler) { | 57 CaptureEventHandler* event_handler) { |
53 DCHECK(!callback_); | 58 DCHECK(!callback_); |
54 DCHECK(!event_handler_); | 59 DCHECK(!event_handler_); |
55 audio_parameters_ = params; | 60 audio_parameters_ = params; |
56 callback_ = callback; | 61 callback_ = callback; |
57 event_handler_ = event_handler; | 62 event_handler_ = event_handler; |
58 } | 63 } |
59 | 64 |
60 void AudioInputDevice::SetDevice(int session_id) { | 65 void AudioInputDevice::SetDevice(int session_id) { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
130 | 135 |
131 MessageLoop::current()->PostTask(FROM_HERE, | 136 MessageLoop::current()->PostTask(FROM_HERE, |
132 base::Bind(&AudioInputDevice::StartOnIOThread, this)); | 137 base::Bind(&AudioInputDevice::StartOnIOThread, this)); |
133 } | 138 } |
134 | 139 |
135 void AudioInputDevice::OnVolume(double volume) { | 140 void AudioInputDevice::OnVolume(double volume) { |
136 NOTIMPLEMENTED(); | 141 NOTIMPLEMENTED(); |
137 } | 142 } |
138 | 143 |
139 void AudioInputDevice::OnStateChanged( | 144 void AudioInputDevice::OnStateChanged( |
140 media::AudioInputIPCDelegate::State state) { | 145 AudioInputIPCDelegate::State state) { |
141 DCHECK(message_loop()->BelongsToCurrentThread()); | 146 DCHECK(message_loop()->BelongsToCurrentThread()); |
142 | 147 |
143 // Do nothing if the stream has been closed. | 148 // Do nothing if the stream has been closed. |
144 if (!stream_id_) | 149 if (!stream_id_) |
145 return; | 150 return; |
146 | 151 |
147 switch (state) { | 152 switch (state) { |
148 case media::AudioInputIPCDelegate::kStopped: | 153 case AudioInputIPCDelegate::kStopped: |
149 // TODO(xians): Should we just call ShutDownOnIOThread here instead? | 154 // TODO(xians): Should we just call ShutDownOnIOThread here instead? |
150 ipc_->RemoveDelegate(stream_id_); | 155 ipc_->RemoveDelegate(stream_id_); |
151 | 156 |
152 audio_thread_.Stop(MessageLoop::current()); | 157 audio_thread_.Stop(MessageLoop::current()); |
153 audio_callback_.reset(); | 158 audio_callback_.reset(); |
154 | 159 |
155 if (event_handler_) | 160 if (event_handler_) |
156 event_handler_->OnDeviceStopped(); | 161 event_handler_->OnDeviceStopped(); |
157 | 162 |
158 stream_id_ = 0; | 163 stream_id_ = 0; |
159 pending_device_ready_ = false; | 164 pending_device_ready_ = false; |
160 break; | 165 break; |
161 case media::AudioInputIPCDelegate::kRecording: | 166 case AudioInputIPCDelegate::kRecording: |
162 NOTIMPLEMENTED(); | 167 NOTIMPLEMENTED(); |
163 break; | 168 break; |
164 case media::AudioInputIPCDelegate::kError: | 169 case AudioInputIPCDelegate::kError: |
165 DLOG(WARNING) << "AudioInputDevice::OnStateChanged(kError)"; | 170 DLOG(WARNING) << "AudioInputDevice::OnStateChanged(kError)"; |
166 // Don't dereference the callback object if the audio thread | 171 // Don't dereference the callback object if the audio thread |
167 // is stopped or stopping. That could mean that the callback | 172 // is stopped or stopping. That could mean that the callback |
168 // object has been deleted. | 173 // object has been deleted. |
169 // TODO(tommi): Add an explicit contract for clearing the callback | 174 // TODO(tommi): Add an explicit contract for clearing the callback |
170 // object. Possibly require calling Initialize again or provide | 175 // object. Possibly require calling Initialize again or provide |
171 // a callback object via Start() and clear it in Stop(). | 176 // a callback object via Start() and clear it in Stop(). |
172 if (!audio_thread_.IsStopped()) | 177 if (!audio_thread_.IsStopped()) |
173 callback_->OnCaptureError(); | 178 callback_->OnCaptureError(); |
174 break; | 179 break; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 DCHECK_EQ(0, stream_id_); | 223 DCHECK_EQ(0, stream_id_); |
219 if (stream_id_) | 224 if (stream_id_) |
220 return; | 225 return; |
221 | 226 |
222 stream_id_ = ipc_->AddDelegate(this); | 227 stream_id_ = ipc_->AddDelegate(this); |
223 // If |session_id_| is not specified, it will directly create the stream; | 228 // If |session_id_| is not specified, it will directly create the stream; |
224 // otherwise it will send a AudioInputHostMsg_StartDevice msg to the browser | 229 // otherwise it will send a AudioInputHostMsg_StartDevice msg to the browser |
225 // and create the stream when getting a OnDeviceReady() callback. | 230 // and create the stream when getting a OnDeviceReady() callback. |
226 if (!session_id_) { | 231 if (!session_id_) { |
227 ipc_->CreateStream(stream_id_, audio_parameters_, | 232 ipc_->CreateStream(stream_id_, audio_parameters_, |
228 media::AudioManagerBase::kDefaultDeviceId, agc_is_enabled_); | 233 AudioManagerBase::kDefaultDeviceId, agc_is_enabled_); |
229 } else { | 234 } else { |
230 ipc_->StartDevice(stream_id_, session_id_); | 235 ipc_->StartDevice(stream_id_, session_id_); |
231 pending_device_ready_ = true; | 236 pending_device_ready_ = true; |
232 } | 237 } |
233 } | 238 } |
234 | 239 |
235 void AudioInputDevice::SetSessionIdOnIOThread(int session_id) { | 240 void AudioInputDevice::SetSessionIdOnIOThread(int session_id) { |
236 DCHECK(message_loop()->BelongsToCurrentThread()); | 241 DCHECK(message_loop()->BelongsToCurrentThread()); |
237 session_id_ = session_id; | 242 session_id_ = session_id; |
238 } | 243 } |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 agc_is_enabled_ = enabled; | 292 agc_is_enabled_ = enabled; |
288 } | 293 } |
289 | 294 |
290 void AudioInputDevice::WillDestroyCurrentMessageLoop() { | 295 void AudioInputDevice::WillDestroyCurrentMessageLoop() { |
291 LOG(ERROR) << "IO loop going away before the input device has been stopped"; | 296 LOG(ERROR) << "IO loop going away before the input device has been stopped"; |
292 ShutDownOnIOThread(); | 297 ShutDownOnIOThread(); |
293 } | 298 } |
294 | 299 |
295 // AudioInputDevice::AudioThreadCallback | 300 // AudioInputDevice::AudioThreadCallback |
296 AudioInputDevice::AudioThreadCallback::AudioThreadCallback( | 301 AudioInputDevice::AudioThreadCallback::AudioThreadCallback( |
297 const media::AudioParameters& audio_parameters, | 302 const AudioParameters& audio_parameters, |
298 base::SharedMemoryHandle memory, | 303 base::SharedMemoryHandle memory, |
299 int memory_length, | 304 int memory_length, |
300 CaptureCallback* capture_callback) | 305 CaptureCallback* capture_callback) |
301 : AudioDeviceThread::Callback(audio_parameters, memory, memory_length), | 306 : AudioDeviceThread::Callback(audio_parameters, memory, memory_length), |
302 capture_callback_(capture_callback) { | 307 capture_callback_(capture_callback) { |
303 } | 308 } |
304 | 309 |
305 AudioInputDevice::AudioThreadCallback::~AudioThreadCallback() { | 310 AudioInputDevice::AudioThreadCallback::~AudioThreadCallback() { |
306 } | 311 } |
307 | 312 |
308 void AudioInputDevice::AudioThreadCallback::MapSharedMemory() { | 313 void AudioInputDevice::AudioThreadCallback::MapSharedMemory() { |
309 shared_memory_.Map(memory_length_); | 314 shared_memory_.Map(memory_length_); |
310 } | 315 } |
311 | 316 |
312 void AudioInputDevice::AudioThreadCallback::Process(int pending_data) { | 317 void AudioInputDevice::AudioThreadCallback::Process(int pending_data) { |
313 // The shared memory represents parameters, size of the data buffer and the | 318 // The shared memory represents parameters, size of the data buffer and the |
314 // actual data buffer containing audio data. Map the memory into this | 319 // actual data buffer containing audio data. Map the memory into this |
315 // structure and parse out parameters and the data area. | 320 // structure and parse out parameters and the data area. |
316 media::AudioInputBuffer* buffer = | 321 AudioInputBuffer* buffer = |
317 reinterpret_cast<media::AudioInputBuffer*>(shared_memory_.memory()); | 322 reinterpret_cast<AudioInputBuffer*>(shared_memory_.memory()); |
318 DCHECK_EQ(buffer->params.size, | 323 DCHECK_EQ(buffer->params.size, |
319 memory_length_ - sizeof(media::AudioInputBufferParameters)); | 324 memory_length_ - sizeof(AudioInputBufferParameters)); |
320 double volume = buffer->params.volume; | 325 double volume = buffer->params.volume; |
321 | 326 |
322 int audio_delay_milliseconds = pending_data / bytes_per_ms_; | 327 int audio_delay_milliseconds = pending_data / bytes_per_ms_; |
323 int16* memory = reinterpret_cast<int16*>(&buffer->audio[0]); | 328 int16* memory = reinterpret_cast<int16*>(&buffer->audio[0]); |
324 const size_t number_of_frames = audio_parameters_.frames_per_buffer(); | 329 const size_t number_of_frames = audio_parameters_.frames_per_buffer(); |
325 const int bytes_per_sample = sizeof(memory[0]); | 330 const int bytes_per_sample = sizeof(memory[0]); |
326 | 331 |
327 // Deinterleave each channel and convert to 32-bit floating-point | 332 // Deinterleave each channel and convert to 32-bit floating-point |
328 // with nominal range -1.0 -> +1.0. | 333 // with nominal range -1.0 -> +1.0. |
329 for (int channel_index = 0; channel_index < audio_parameters_.channels(); | 334 for (int channel_index = 0; channel_index < audio_parameters_.channels(); |
330 ++channel_index) { | 335 ++channel_index) { |
331 media::DeinterleaveAudioChannel(memory, | 336 DeinterleaveAudioChannel(memory, |
332 audio_data_[channel_index], | 337 audio_data_[channel_index], |
333 audio_parameters_.channels(), | 338 audio_parameters_.channels(), |
334 channel_index, | 339 channel_index, |
335 bytes_per_sample, | 340 bytes_per_sample, |
336 number_of_frames); | 341 number_of_frames); |
337 } | 342 } |
338 | 343 |
339 // Deliver captured data to the client in floating point format | 344 // Deliver captured data to the client in floating point format |
340 // and update the audio-delay measurement. | 345 // and update the audio-delay measurement. |
341 capture_callback_->Capture(audio_data_, number_of_frames, | 346 capture_callback_->Capture(audio_data_, number_of_frames, |
342 audio_delay_milliseconds, volume); | 347 audio_delay_milliseconds, volume); |
343 } | 348 } |
| 349 |
| 350 } // namespace media |
OLD | NEW |