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/android/opensles_input.h" | 5 #include "media/audio/android/opensles_input.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "media/audio/android/audio_manager_android.h" | 8 #include "media/audio/android/audio_manager_android.h" |
9 | 9 |
10 #define LOG_ON_FAILURE_AND_RETURN(op, ...) \ | 10 #define LOG_ON_FAILURE_AND_RETURN(op, ...) \ |
11 do { \ | 11 do { \ |
12 SLresult err = (op); \ | 12 SLresult err = (op); \ |
13 if (err != SL_RESULT_SUCCESS) { \ | 13 if (err != SL_RESULT_SUCCESS) { \ |
14 DLOG(ERROR) << #op << " failed: " << err; \ | 14 DLOG(ERROR) << #op << " failed: " << err; \ |
15 return __VA_ARGS__; \ | 15 return __VA_ARGS__; \ |
16 } \ | 16 } \ |
17 } while (0) | 17 } while (0) |
18 | 18 |
19 namespace media { | 19 namespace media { |
20 | 20 |
21 OpenSLESInputStream::OpenSLESInputStream(AudioManagerAndroid* audio_manager, | 21 OpenSLESInputStream::OpenSLESInputStream(AudioManagerAndroid* audio_manager, |
22 const AudioParameters& params) | 22 const AudioParameters& params) |
23 : audio_manager_(audio_manager), | 23 : audio_manager_(audio_manager), |
24 callback_(NULL), | 24 callback_(NULL), |
25 recorder_(NULL), | 25 recorder_(NULL), |
26 simple_buffer_queue_(NULL), | 26 simple_buffer_queue_(NULL), |
27 active_queue_(0), | 27 active_queue_(0), |
28 buffer_size_bytes_(0), | 28 buffer_size_bytes_(0), |
29 started_(false) { | 29 started_(false) { |
30 DVLOG(2) << "OpenSLESInputStream::OpenSLESInputStream()"; | |
30 format_.formatType = SL_DATAFORMAT_PCM; | 31 format_.formatType = SL_DATAFORMAT_PCM; |
31 format_.numChannels = static_cast<SLuint32>(params.channels()); | 32 format_.numChannels = static_cast<SLuint32>(params.channels()); |
32 // Provides sampling rate in milliHertz to OpenSLES. | 33 // Provides sampling rate in milliHertz to OpenSLES. |
33 format_.samplesPerSec = static_cast<SLuint32>(params.sample_rate() * 1000); | 34 format_.samplesPerSec = static_cast<SLuint32>(params.sample_rate() * 1000); |
34 format_.bitsPerSample = params.bits_per_sample(); | 35 format_.bitsPerSample = params.bits_per_sample(); |
35 format_.containerSize = params.bits_per_sample(); | 36 format_.containerSize = params.bits_per_sample(); |
36 format_.endianness = SL_BYTEORDER_LITTLEENDIAN; | 37 format_.endianness = SL_BYTEORDER_LITTLEENDIAN; |
37 if (format_.numChannels == 1) | 38 if (format_.numChannels == 1) |
38 format_.channelMask = SL_SPEAKER_FRONT_CENTER; | 39 format_.channelMask = SL_SPEAKER_FRONT_CENTER; |
39 else if (format_.numChannels == 2) | 40 else if (format_.numChannels == 2) |
40 format_.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; | 41 format_.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; |
41 else | 42 else |
42 NOTREACHED() << "Unsupported number of channels: " << format_.numChannels; | 43 NOTREACHED() << "Unsupported number of channels: " << format_.numChannels; |
43 | 44 |
44 buffer_size_bytes_ = params.GetBytesPerBuffer(); | 45 buffer_size_bytes_ = params.GetBytesPerBuffer(); |
45 | 46 |
46 memset(&audio_data_, 0, sizeof(audio_data_)); | 47 memset(&audio_data_, 0, sizeof(audio_data_)); |
47 } | 48 } |
48 | 49 |
49 OpenSLESInputStream::~OpenSLESInputStream() { | 50 OpenSLESInputStream::~OpenSLESInputStream() { |
51 DVLOG(2) << "OpenSLESInputStream::~OpenSLESInputStream()"; | |
52 DCHECK(thread_checker_.CalledOnValidThread()); | |
50 DCHECK(!recorder_object_.Get()); | 53 DCHECK(!recorder_object_.Get()); |
51 DCHECK(!engine_object_.Get()); | 54 DCHECK(!engine_object_.Get()); |
52 DCHECK(!recorder_); | 55 DCHECK(!recorder_); |
53 DCHECK(!simple_buffer_queue_); | 56 DCHECK(!simple_buffer_queue_); |
54 DCHECK(!audio_data_[0]); | 57 DCHECK(!audio_data_[0]); |
55 } | 58 } |
56 | 59 |
57 bool OpenSLESInputStream::Open() { | 60 bool OpenSLESInputStream::Open() { |
61 DVLOG(2) << "OpenSLESInputStream::Open()"; | |
62 DCHECK(thread_checker_.CalledOnValidThread()); | |
58 if (engine_object_.Get()) | 63 if (engine_object_.Get()) |
59 return false; | 64 return false; |
60 | 65 |
61 if (!CreateRecorder()) | 66 if (!CreateRecorder()) |
62 return false; | 67 return false; |
63 | 68 |
64 SetupAudioBuffer(); | 69 SetupAudioBuffer(); |
65 | 70 |
66 return true; | 71 return true; |
67 } | 72 } |
68 | 73 |
69 void OpenSLESInputStream::Start(AudioInputCallback* callback) { | 74 void OpenSLESInputStream::Start(AudioInputCallback* callback) { |
75 DVLOG(2) << "OpenSLESInputStream::Start()"; | |
76 DCHECK(thread_checker_.CalledOnValidThread()); | |
70 DCHECK(callback); | 77 DCHECK(callback); |
71 DCHECK(recorder_); | 78 DCHECK(recorder_); |
72 DCHECK(simple_buffer_queue_); | 79 DCHECK(simple_buffer_queue_); |
73 if (started_) | |
74 return; | |
75 | |
76 // Enable the flags before streaming. | |
77 callback_ = callback; | |
78 active_queue_ = 0; | |
79 started_ = true; | |
80 | 80 |
81 SLresult err = SL_RESULT_UNKNOWN_ERROR; | 81 SLresult err = SL_RESULT_UNKNOWN_ERROR; |
82 // Enqueues |kNumOfQueuesInBuffer| zero buffers to get the ball rolling. | 82 { |
83 for (int i = 0; i < kNumOfQueuesInBuffer; ++i) { | 83 base::AutoLock lock(lock_); |
84 err = (*simple_buffer_queue_)->Enqueue( | 84 if (started_) |
wjia(left Chromium)
2013/08/29 14:21:55
No need to guard this check since this is the only
| |
85 simple_buffer_queue_, | |
86 audio_data_[i], | |
87 buffer_size_bytes_); | |
88 if (SL_RESULT_SUCCESS != err) { | |
89 HandleError(err); | |
90 return; | 85 return; |
86 | |
87 // Enable the flags before streaming. | |
88 callback_ = callback; | |
89 active_queue_ = 0; | |
90 started_ = true; | |
91 | |
92 // Enqueues |kNumOfQueuesInBuffer| zero buffers to get the ball rolling. | |
93 for (int i = 0; i < kNumOfQueuesInBuffer; ++i) { | |
94 err = (*simple_buffer_queue_)->Enqueue( | |
95 simple_buffer_queue_, | |
96 audio_data_[i], | |
97 buffer_size_bytes_); | |
98 if (SL_RESULT_SUCCESS != err) { | |
99 HandleError(err); | |
100 return; | |
101 } | |
91 } | 102 } |
92 } | 103 } |
93 | 104 |
94 // Start the recording by setting the state to |SL_RECORDSTATE_RECORDING|. | 105 // Start the recording by setting the state to |SL_RECORDSTATE_RECORDING|. |
95 err = (*recorder_)->SetRecordState(recorder_, SL_RECORDSTATE_RECORDING); | 106 err = (*recorder_)->SetRecordState(recorder_, SL_RECORDSTATE_RECORDING); |
96 if (SL_RESULT_SUCCESS != err) | 107 if (SL_RESULT_SUCCESS != err) |
97 HandleError(err); | 108 HandleError(err); |
98 } | 109 } |
99 | 110 |
100 void OpenSLESInputStream::Stop() { | 111 void OpenSLESInputStream::Stop() { |
101 if (!started_) | 112 DVLOG(2) << "OpenSLESInputStream::Stop()"; |
102 return; | 113 DCHECK(thread_checker_.CalledOnValidThread()); |
114 { | |
115 base::AutoLock lock(lock_); | |
116 if (!started_) | |
wjia(left Chromium)
2013/08/29 14:21:55
ditto.
| |
117 return; | |
118 } | |
103 | 119 |
104 // Stop recording by setting the record state to |SL_RECORDSTATE_STOPPED|. | 120 // Stop recording by setting the record state to |SL_RECORDSTATE_STOPPED|. |
105 LOG_ON_FAILURE_AND_RETURN( | 121 LOG_ON_FAILURE_AND_RETURN( |
106 (*recorder_)->SetRecordState(recorder_, | 122 (*recorder_)->SetRecordState(recorder_, |
107 SL_RECORDSTATE_STOPPED)); | 123 SL_RECORDSTATE_STOPPED)); |
124 { | |
125 base::AutoLock lock(lock_); | |
108 | 126 |
109 // Clear the buffer queue to get rid of old data when resuming recording. | 127 // Clear the buffer queue to get rid of old data when resuming recording. |
110 LOG_ON_FAILURE_AND_RETURN( | 128 LOG_ON_FAILURE_AND_RETURN( |
111 (*simple_buffer_queue_)->Clear(simple_buffer_queue_)); | 129 (*simple_buffer_queue_)->Clear(simple_buffer_queue_)); |
112 | 130 |
113 started_ = false; | 131 started_ = false; |
132 } | |
114 } | 133 } |
115 | 134 |
116 void OpenSLESInputStream::Close() { | 135 void OpenSLESInputStream::Close() { |
136 DVLOG(2) << "OpenSLESInputStream::Close()"; | |
137 DCHECK(thread_checker_.CalledOnValidThread()); | |
138 | |
117 // Stop the stream if it is still recording. | 139 // Stop the stream if it is still recording. |
118 Stop(); | 140 Stop(); |
wjia(left Chromium)
2013/08/29 14:21:55
|lock_| is not needed after this point, since |sta
| |
119 | 141 |
120 // Explicitly free the player objects and invalidate their associated | 142 { |
121 // interfaces. They have to be done in the correct order. | 143 base::AutoLock lock(lock_); |
144 if (callback_) { | |
145 callback_->OnClose(this); | |
146 callback_ = NULL; | |
147 } | |
148 } | |
149 | |
150 // Destroy the buffer queue recorder object and invalidate all associated | |
151 // interfaces. | |
122 recorder_object_.Reset(); | 152 recorder_object_.Reset(); |
123 engine_object_.Reset(); | 153 { |
124 simple_buffer_queue_ = NULL; | 154 base::AutoLock lock(lock_); |
155 simple_buffer_queue_ = NULL; | |
156 } | |
125 recorder_ = NULL; | 157 recorder_ = NULL; |
126 | 158 |
127 ReleaseAudioBuffer(); | 159 // Destroy the engine object. We don't store any associated interface for |
160 // this object. | |
161 engine_object_.Reset(); | |
162 { | |
163 base::AutoLock lock(lock_); | |
164 ReleaseAudioBuffer(); | |
165 } | |
128 | 166 |
129 audio_manager_->ReleaseInputStream(this); | 167 audio_manager_->ReleaseInputStream(this); |
130 } | 168 } |
131 | 169 |
132 double OpenSLESInputStream::GetMaxVolume() { | 170 double OpenSLESInputStream::GetMaxVolume() { |
133 NOTIMPLEMENTED(); | 171 NOTIMPLEMENTED(); |
134 return 0.0; | 172 return 0.0; |
135 } | 173 } |
136 | 174 |
137 void OpenSLESInputStream::SetVolume(double volume) { | 175 void OpenSLESInputStream::SetVolume(double volume) { |
138 NOTIMPLEMENTED(); | 176 NOTIMPLEMENTED(); |
139 } | 177 } |
140 | 178 |
141 double OpenSLESInputStream::GetVolume() { | 179 double OpenSLESInputStream::GetVolume() { |
142 NOTIMPLEMENTED(); | 180 NOTIMPLEMENTED(); |
143 return 0.0; | 181 return 0.0; |
144 } | 182 } |
145 | 183 |
146 void OpenSLESInputStream::SetAutomaticGainControl(bool enabled) { | 184 void OpenSLESInputStream::SetAutomaticGainControl(bool enabled) { |
147 NOTIMPLEMENTED(); | 185 NOTIMPLEMENTED(); |
148 } | 186 } |
149 | 187 |
150 bool OpenSLESInputStream::GetAutomaticGainControl() { | 188 bool OpenSLESInputStream::GetAutomaticGainControl() { |
151 NOTIMPLEMENTED(); | 189 NOTIMPLEMENTED(); |
152 return false; | 190 return false; |
153 } | 191 } |
154 | 192 |
155 bool OpenSLESInputStream::CreateRecorder() { | 193 bool OpenSLESInputStream::CreateRecorder() { |
194 DCHECK(thread_checker_.CalledOnValidThread()); | |
195 DCHECK(!engine_object_.Get()); | |
196 DCHECK(!recorder_object_.Get()); | |
197 DCHECK(!recorder_); | |
198 DCHECK(!simple_buffer_queue_); | |
199 | |
156 // Initializes the engine object with specific option. After working with the | 200 // Initializes the engine object with specific option. After working with the |
157 // object, we need to free the object and its resources. | 201 // object, we need to free the object and its resources. |
158 SLEngineOption option[] = { | 202 SLEngineOption option[] = { |
159 { SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE) } | 203 { SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE) } |
160 }; | 204 }; |
161 LOG_ON_FAILURE_AND_RETURN(slCreateEngine(engine_object_.Receive(), | 205 LOG_ON_FAILURE_AND_RETURN(slCreateEngine(engine_object_.Receive(), |
162 1, | 206 1, |
163 option, | 207 option, |
164 0, | 208 0, |
165 NULL, | 209 NULL, |
(...skipping 28 matching lines...) Expand all Loading... | |
194 | 238 |
195 // Create an audio recorder. | 239 // Create an audio recorder. |
196 const SLInterfaceID interface_id[] = { | 240 const SLInterfaceID interface_id[] = { |
197 SL_IID_ANDROIDSIMPLEBUFFERQUEUE, | 241 SL_IID_ANDROIDSIMPLEBUFFERQUEUE, |
198 SL_IID_ANDROIDCONFIGURATION | 242 SL_IID_ANDROIDCONFIGURATION |
199 }; | 243 }; |
200 const SLboolean interface_required[] = { | 244 const SLboolean interface_required[] = { |
201 SL_BOOLEAN_TRUE, | 245 SL_BOOLEAN_TRUE, |
202 SL_BOOLEAN_TRUE | 246 SL_BOOLEAN_TRUE |
203 }; | 247 }; |
248 | |
204 // Create AudioRecorder and specify SL_IID_ANDROIDCONFIGURATION. | 249 // Create AudioRecorder and specify SL_IID_ANDROIDCONFIGURATION. |
205 LOG_ON_FAILURE_AND_RETURN( | 250 LOG_ON_FAILURE_AND_RETURN( |
206 (*engine)->CreateAudioRecorder(engine, | 251 (*engine)->CreateAudioRecorder(engine, |
207 recorder_object_.Receive(), | 252 recorder_object_.Receive(), |
208 &audio_source, | 253 &audio_source, |
209 &audio_sink, | 254 &audio_sink, |
210 arraysize(interface_id), | 255 arraysize(interface_id), |
211 interface_id, | 256 interface_id, |
212 interface_required), | 257 interface_required), |
213 false); | 258 false); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
258 } | 303 } |
259 | 304 |
260 void OpenSLESInputStream::SimpleBufferQueueCallback( | 305 void OpenSLESInputStream::SimpleBufferQueueCallback( |
261 SLAndroidSimpleBufferQueueItf buffer_queue, void* instance) { | 306 SLAndroidSimpleBufferQueueItf buffer_queue, void* instance) { |
262 OpenSLESInputStream* stream = | 307 OpenSLESInputStream* stream = |
263 reinterpret_cast<OpenSLESInputStream*>(instance); | 308 reinterpret_cast<OpenSLESInputStream*>(instance); |
264 stream->ReadBufferQueue(); | 309 stream->ReadBufferQueue(); |
265 } | 310 } |
266 | 311 |
267 void OpenSLESInputStream::ReadBufferQueue() { | 312 void OpenSLESInputStream::ReadBufferQueue() { |
313 base::AutoLock lock(lock_); | |
268 if (!started_) | 314 if (!started_) |
269 return; | 315 return; |
270 | 316 |
271 // TODO(xians): Get an accurate delay estimation. | 317 // TODO(xians): Get an accurate delay estimation. |
272 callback_->OnData(this, | 318 callback_->OnData(this, |
273 audio_data_[active_queue_], | 319 audio_data_[active_queue_], |
274 buffer_size_bytes_, | 320 buffer_size_bytes_, |
275 buffer_size_bytes_, | 321 buffer_size_bytes_, |
276 0.0); | 322 0.0); |
277 | 323 |
278 // Done with this buffer. Send it to device for recording. | 324 // Done with this buffer. Send it to device for recording. |
279 SLresult err = (*simple_buffer_queue_)->Enqueue( | 325 SLresult err = (*simple_buffer_queue_)->Enqueue( |
280 simple_buffer_queue_, | 326 simple_buffer_queue_, |
281 audio_data_[active_queue_], | 327 audio_data_[active_queue_], |
282 buffer_size_bytes_); | 328 buffer_size_bytes_); |
283 if (SL_RESULT_SUCCESS != err) | 329 if (SL_RESULT_SUCCESS != err) |
284 HandleError(err); | 330 HandleError(err); |
285 | 331 |
286 active_queue_ = (active_queue_ + 1) % kNumOfQueuesInBuffer; | 332 active_queue_ = (active_queue_ + 1) % kNumOfQueuesInBuffer; |
287 } | 333 } |
288 | 334 |
289 void OpenSLESInputStream::SetupAudioBuffer() { | 335 void OpenSLESInputStream::SetupAudioBuffer() { |
336 DCHECK(thread_checker_.CalledOnValidThread()); | |
290 DCHECK(!audio_data_[0]); | 337 DCHECK(!audio_data_[0]); |
291 for (int i = 0; i < kNumOfQueuesInBuffer; ++i) { | 338 for (int i = 0; i < kNumOfQueuesInBuffer; ++i) { |
292 audio_data_[i] = new uint8[buffer_size_bytes_]; | 339 audio_data_[i] = new uint8[buffer_size_bytes_]; |
293 } | 340 } |
294 } | 341 } |
295 | 342 |
296 void OpenSLESInputStream::ReleaseAudioBuffer() { | 343 void OpenSLESInputStream::ReleaseAudioBuffer() { |
344 DCHECK(thread_checker_.CalledOnValidThread()); | |
297 if (audio_data_[0]) { | 345 if (audio_data_[0]) { |
298 for (int i = 0; i < kNumOfQueuesInBuffer; ++i) { | 346 for (int i = 0; i < kNumOfQueuesInBuffer; ++i) { |
299 delete [] audio_data_[i]; | 347 delete [] audio_data_[i]; |
300 audio_data_[i] = NULL; | 348 audio_data_[i] = NULL; |
301 } | 349 } |
302 } | 350 } |
303 } | 351 } |
304 | 352 |
305 void OpenSLESInputStream::HandleError(SLresult error) { | 353 void OpenSLESInputStream::HandleError(SLresult error) { |
wjia(left Chromium)
2013/08/29 14:21:55
This function should be called HandleErrorWithLock
| |
306 DLOG(FATAL) << "OpenSLES Input error " << error; | 354 DLOG(FATAL) << "OpenSLES Input error " << error; |
307 if (callback_) | 355 if (callback_) |
308 callback_->OnError(this); | 356 callback_->OnError(this); |
309 } | 357 } |
310 | 358 |
311 } // namespace media | 359 } // namespace media |
OLD | NEW |