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

Side by Side Diff: media/audio/android/opensles_input.cc

Issue 23296008: Adding audio unit tests for Android (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: First round Created 7 years, 3 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
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/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());
tommi (sloooow) - chröme 2013/08/29 09:56:27 nice to have the thread checker in here.
henrika (OOO until Aug 14) 2013/08/29 11:59:07 Thanks. It was a really smart guy who suggested it
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_) 80 if (started_)
tommi (sloooow) - chröme 2013/08/29 09:56:27 this needs to be checked under the lock
henrika (OOO until Aug 14) 2013/08/29 11:59:07 Done.
74 return; 81 return;
75 82 {
76 // Enable the flags before streaming. 83 base::AutoLock lock(lock_);
77 callback_ = callback; 84 // Enable the flags before streaming.
78 active_queue_ = 0; 85 callback_ = callback;
79 started_ = true; 86 active_queue_ = 0;
87 started_ = true;
88 }
80 89
81 SLresult err = SL_RESULT_UNKNOWN_ERROR; 90 SLresult err = SL_RESULT_UNKNOWN_ERROR;
82 // Enqueues |kNumOfQueuesInBuffer| zero buffers to get the ball rolling. 91 // Enqueues |kNumOfQueuesInBuffer| zero buffers to get the ball rolling.
83 for (int i = 0; i < kNumOfQueuesInBuffer; ++i) { 92 for (int i = 0; i < kNumOfQueuesInBuffer; ++i) {
84 err = (*simple_buffer_queue_)->Enqueue( 93 err = (*simple_buffer_queue_)->Enqueue(
tommi (sloooow) - chröme 2013/08/29 09:56:27 As is, it looks to me that you need to hold the lo
henrika (OOO until Aug 14) 2013/08/29 11:59:07 I find it difficult to guarantee that the worker t
85 simple_buffer_queue_, 94 simple_buffer_queue_,
86 audio_data_[i], 95 audio_data_[i],
87 buffer_size_bytes_); 96 buffer_size_bytes_);
88 if (SL_RESULT_SUCCESS != err) { 97 if (SL_RESULT_SUCCESS != err) {
89 HandleError(err); 98 HandleError(err);
90 return; 99 return;
91 } 100 }
92 } 101 }
93 102
94 // Start the recording by setting the state to |SL_RECORDSTATE_RECORDING|. 103 // Start the recording by setting the state to |SL_RECORDSTATE_RECORDING|.
95 err = (*recorder_)->SetRecordState(recorder_, SL_RECORDSTATE_RECORDING); 104 err = (*recorder_)->SetRecordState(recorder_, SL_RECORDSTATE_RECORDING);
96 if (SL_RESULT_SUCCESS != err) 105 if (SL_RESULT_SUCCESS != err)
97 HandleError(err); 106 HandleError(err);
98 } 107 }
99 108
100 void OpenSLESInputStream::Stop() { 109 void OpenSLESInputStream::Stop() {
110 DVLOG(2) << "OpenSLESInputStream::Stop()";
111 DCHECK(thread_checker_.CalledOnValidThread());
101 if (!started_) 112 if (!started_)
tommi (sloooow) - chröme 2013/08/29 09:56:27 need to hold lock.
henrika (OOO until Aug 14) 2013/08/29 11:59:07 Done.
102 return; 113 return;
103 114
104 // Stop recording by setting the record state to |SL_RECORDSTATE_STOPPED|. 115 // Stop recording by setting the record state to |SL_RECORDSTATE_STOPPED|.
105 LOG_ON_FAILURE_AND_RETURN( 116 LOG_ON_FAILURE_AND_RETURN(
106 (*recorder_)->SetRecordState(recorder_, 117 (*recorder_)->SetRecordState(recorder_,
107 SL_RECORDSTATE_STOPPED)); 118 SL_RECORDSTATE_STOPPED));
119 {
120 base::AutoLock lock(lock_);
108 121
109 // Clear the buffer queue to get rid of old data when resuming recording. 122 // Clear the buffer queue to get rid of old data when resuming recording.
110 LOG_ON_FAILURE_AND_RETURN( 123 LOG_ON_FAILURE_AND_RETURN(
111 (*simple_buffer_queue_)->Clear(simple_buffer_queue_)); 124 (*simple_buffer_queue_)->Clear(simple_buffer_queue_));
112 125
113 started_ = false; 126 started_ = false;
127 }
114 } 128 }
115 129
116 void OpenSLESInputStream::Close() { 130 void OpenSLESInputStream::Close() {
131 DVLOG(2) << "OpenSLESInputStream::Close()";
132 DCHECK(thread_checker_.CalledOnValidThread());
117 // Stop the stream if it is still recording. 133 // Stop the stream if it is still recording.
118 Stop(); 134 Stop();
135 {
136 base::AutoLock lock(lock_);
137 if (callback_) {
138 callback_->OnClose(this);
139 callback_ = NULL;
140 }
141 }
119 142
120 // Explicitly free the player objects and invalidate their associated 143 // Explicitly free the player objects and invalidate their associated
121 // interfaces. They have to be done in the correct order. 144 // interfaces. They have to be done in the correct order.
122 recorder_object_.Reset(); 145 recorder_object_.Reset();
123 engine_object_.Reset(); 146 engine_object_.Reset();
tommi (sloooow) - chröme 2013/08/29 09:56:27 If I understand things correctly, resetting the en
henrika (OOO until Aug 14) 2013/08/29 11:59:07 Good point, thanks. Analyzed how things are create
124 simple_buffer_queue_ = NULL; 147 {
148 base::AutoLock lock(lock_);
149 simple_buffer_queue_ = NULL;
tommi (sloooow) - chröme 2013/08/29 09:56:27 here you actually do grab the lock before changing
henrika (OOO until Aug 14) 2013/08/29 11:59:07 Done.
150 }
125 recorder_ = NULL; 151 recorder_ = NULL;
126 152
127 ReleaseAudioBuffer(); 153 ReleaseAudioBuffer();
128 154
129 audio_manager_->ReleaseInputStream(this); 155 audio_manager_->ReleaseInputStream(this);
130 } 156 }
131 157
132 double OpenSLESInputStream::GetMaxVolume() { 158 double OpenSLESInputStream::GetMaxVolume() {
133 NOTIMPLEMENTED(); 159 NOTIMPLEMENTED();
134 return 0.0; 160 return 0.0;
(...skipping 11 matching lines...) Expand all
146 void OpenSLESInputStream::SetAutomaticGainControl(bool enabled) { 172 void OpenSLESInputStream::SetAutomaticGainControl(bool enabled) {
147 NOTIMPLEMENTED(); 173 NOTIMPLEMENTED();
148 } 174 }
149 175
150 bool OpenSLESInputStream::GetAutomaticGainControl() { 176 bool OpenSLESInputStream::GetAutomaticGainControl() {
151 NOTIMPLEMENTED(); 177 NOTIMPLEMENTED();
152 return false; 178 return false;
153 } 179 }
154 180
155 bool OpenSLESInputStream::CreateRecorder() { 181 bool OpenSLESInputStream::CreateRecorder() {
182 DCHECK(thread_checker_.CalledOnValidThread());
tommi (sloooow) - chröme 2013/08/29 09:56:27 We should also dcheck that all interface and objec
henrika (OOO until Aug 14) 2013/08/29 11:59:07 Done.
156 // Initializes the engine object with specific option. After working with the 183 // Initializes the engine object with specific option. After working with the
157 // object, we need to free the object and its resources. 184 // object, we need to free the object and its resources.
158 SLEngineOption option[] = { 185 SLEngineOption option[] = {
159 { SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE) } 186 { SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE) }
160 }; 187 };
161 LOG_ON_FAILURE_AND_RETURN(slCreateEngine(engine_object_.Receive(), 188 LOG_ON_FAILURE_AND_RETURN(slCreateEngine(engine_object_.Receive(),
162 1, 189 1,
163 option, 190 option,
164 0, 191 0,
165 NULL, 192 NULL,
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 } 285 }
259 286
260 void OpenSLESInputStream::SimpleBufferQueueCallback( 287 void OpenSLESInputStream::SimpleBufferQueueCallback(
261 SLAndroidSimpleBufferQueueItf buffer_queue, void* instance) { 288 SLAndroidSimpleBufferQueueItf buffer_queue, void* instance) {
262 OpenSLESInputStream* stream = 289 OpenSLESInputStream* stream =
263 reinterpret_cast<OpenSLESInputStream*>(instance); 290 reinterpret_cast<OpenSLESInputStream*>(instance);
264 stream->ReadBufferQueue(); 291 stream->ReadBufferQueue();
265 } 292 }
266 293
267 void OpenSLESInputStream::ReadBufferQueue() { 294 void OpenSLESInputStream::ReadBufferQueue() {
295 base::AutoLock lock(lock_);
268 if (!started_) 296 if (!started_)
269 return; 297 return;
270 298
271 // TODO(xians): Get an accurate delay estimation. 299 // TODO(xians): Get an accurate delay estimation.
272 callback_->OnData(this, 300 callback_->OnData(this,
273 audio_data_[active_queue_], 301 audio_data_[active_queue_],
274 buffer_size_bytes_, 302 buffer_size_bytes_,
275 buffer_size_bytes_, 303 buffer_size_bytes_,
276 0.0); 304 0.0);
277 305
278 // Done with this buffer. Send it to device for recording. 306 // Done with this buffer. Send it to device for recording.
279 SLresult err = (*simple_buffer_queue_)->Enqueue( 307 SLresult err = (*simple_buffer_queue_)->Enqueue(
280 simple_buffer_queue_, 308 simple_buffer_queue_,
281 audio_data_[active_queue_], 309 audio_data_[active_queue_],
282 buffer_size_bytes_); 310 buffer_size_bytes_);
283 if (SL_RESULT_SUCCESS != err) 311 if (SL_RESULT_SUCCESS != err)
284 HandleError(err); 312 HandleError(err);
285 313
286 active_queue_ = (active_queue_ + 1) % kNumOfQueuesInBuffer; 314 active_queue_ = (active_queue_ + 1) % kNumOfQueuesInBuffer;
287 } 315 }
288 316
289 void OpenSLESInputStream::SetupAudioBuffer() { 317 void OpenSLESInputStream::SetupAudioBuffer() {
318 DCHECK(thread_checker_.CalledOnValidThread());
290 DCHECK(!audio_data_[0]); 319 DCHECK(!audio_data_[0]);
291 for (int i = 0; i < kNumOfQueuesInBuffer; ++i) { 320 for (int i = 0; i < kNumOfQueuesInBuffer; ++i) {
292 audio_data_[i] = new uint8[buffer_size_bytes_]; 321 audio_data_[i] = new uint8[buffer_size_bytes_];
293 } 322 }
294 } 323 }
295 324
296 void OpenSLESInputStream::ReleaseAudioBuffer() { 325 void OpenSLESInputStream::ReleaseAudioBuffer() {
326 DCHECK(thread_checker_.CalledOnValidThread());
297 if (audio_data_[0]) { 327 if (audio_data_[0]) {
298 for (int i = 0; i < kNumOfQueuesInBuffer; ++i) { 328 for (int i = 0; i < kNumOfQueuesInBuffer; ++i) {
299 delete [] audio_data_[i]; 329 delete [] audio_data_[i];
300 audio_data_[i] = NULL; 330 audio_data_[i] = NULL;
301 } 331 }
302 } 332 }
303 } 333 }
304 334
305 void OpenSLESInputStream::HandleError(SLresult error) { 335 void OpenSLESInputStream::HandleError(SLresult error) {
306 DLOG(FATAL) << "OpenSLES Input error " << error; 336 DLOG(FATAL) << "OpenSLES Input error " << error;
307 if (callback_) 337 if (callback_)
308 callback_->OnError(this); 338 callback_->OnError(this);
309 } 339 }
310 340
311 } // namespace media 341 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698