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

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

Issue 9655023: Adding input and output audio backend to Android. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebased && addressed qinmin's comments Created 8 years, 8 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "media/audio/android/opensles_input.h"
6
7 #include "base/logging.h"
8 #include "media/audio/android/audio_manager_android.h"
9
10 OpenSLESInputStream::OpenSLESInputStream(AudioManagerAndroid* audio_manager,
11 const AudioParameters& params)
12 : audio_manager_(audio_manager),
13 callback_(NULL),
14 recorder_(NULL),
15 simple_buffer_queue_(NULL),
16 active_queue_(0),
17 buffer_size_bytes_(0),
18 started_(false) {
19 format_.formatType = SL_DATAFORMAT_PCM;
20 format_.numChannels = static_cast<SLuint32>(params.channels());
21 // Provides sampling rate in milliHertz to OpenSLES.
22 format_.samplesPerSec = static_cast<SLuint32>(params.sample_rate() * 1000);
23 format_.bitsPerSample = params.bits_per_sample();
24 format_.containerSize = params.bits_per_sample();
25 format_.channelMask = SL_SPEAKER_FRONT_CENTER;
26 format_.endianness = SL_BYTEORDER_LITTLEENDIAN;
27
28 buffer_size_bytes_ = params.GetBytesPerBuffer();
29
30 for (int i = 0; i < kNumOfQueuesInBuffer; ++i) {
qinmin 2012/04/02 13:28:54 I still prefer you put this into the Open() functi
no longer working on chromium 2012/04/02 15:17:38 Done.
31 audio_data_[i] = new uint8[buffer_size_bytes_];
32 }
33 }
34
35 OpenSLESInputStream::~OpenSLESInputStream() {
36 DCHECK(!recorder_object_.Get());
37 DCHECK(!engine_object_.Get());
38 DCHECK(!recorder_);
39 DCHECK(!simple_buffer_queue_);
40 for (int i = 0; i < kNumOfQueuesInBuffer; ++i)
41 delete [] audio_data_[i];
42 }
43
44 bool OpenSLESInputStream::Open() {
45 if (engine_object_.Get())
46 return false;
47
48 return CreateRecorder();
49 }
50
51 void OpenSLESInputStream::Start(AudioInputCallback* callback) {
52 DCHECK(callback);
53 DCHECK(recorder_);
54 DCHECK(simple_buffer_queue_);
55 if (started_)
56 return;
57
58 // Enable the flags before streaming.
59 callback_ = callback;
60 active_queue_ = 0;
61 started_ = true;
62
63 SLresult err = SL_RESULT_UNKNOWN_ERROR;
64 // Enqueues |kNumOfQueuesInBuffer| zero buffers to get the ball rolling.
65 for (int i = 0; i < kNumOfQueuesInBuffer - 1; ++i) {
66 err = (*simple_buffer_queue_)->Enqueue(
67 simple_buffer_queue_,
68 audio_data_[i],
69 buffer_size_bytes_);
70 if (SL_RESULT_SUCCESS != err) {
71 HandleError(err);
72 return;
73 }
74 }
75
76 // Start the recording by setting the state to |SL_RECORDSTATE_RECORDING|.
77 err = (*recorder_)->SetRecordState(recorder_, SL_RECORDSTATE_RECORDING);
78 DCHECK_EQ(SL_RESULT_SUCCESS, err);
79 if (SL_RESULT_SUCCESS != err)
80 HandleError(err);
81 }
82
83 void OpenSLESInputStream::Stop() {
84 if (!started_)
85 return;
86
87 // Stop recording by setting the record state to |SL_RECORDSTATE_STOPPED|.
88 SLresult err = (*recorder_)->SetRecordState(recorder_,
89 SL_RECORDSTATE_STOPPED);
90 DLOG_IF(WARNING, SL_RESULT_SUCCESS != err) << "SetRecordState() failed to "
91 << "set the state to stop";
92
93 // Clear the buffer queue to get rid of old data when resuming recording.
94 err = (*simple_buffer_queue_)->Clear(simple_buffer_queue_);
95 DLOG_IF(WARNING, SL_RESULT_SUCCESS != err) << "Clear() failed to clear "
96 << "the buffer queue";
97
98 started_ = false;
99 }
100
101 void OpenSLESInputStream::Close() {
102 // Stop the stream if it is still recording.
103 Stop();
104
105 // Explicitly free the player objects and invalidate their associated
106 // interfaces. They have to be done in the correct order.
107 recorder_object_.Reset();
108 engine_object_.Reset();
109 simple_buffer_queue_ = NULL;
110 recorder_ = NULL;
111
112 audio_manager_->ReleaseInputStream(this);
113 }
114
115 double OpenSLESInputStream::GetMaxVolume() {
116 NOTIMPLEMENTED();
117 return 0.0;
118 }
119
120 void OpenSLESInputStream::SetVolume(double volume) {
121 NOTIMPLEMENTED();
122 }
123
124 double OpenSLESInputStream::GetVolume() {
125 NOTIMPLEMENTED();
126 return 0.0;
127 }
128
129 void OpenSLESInputStream::SetAutomaticGainControl(bool enabled) {
130 NOTIMPLEMENTED();
131 }
132
133 bool OpenSLESInputStream::GetAutomaticGainControl() {
134 NOTIMPLEMENTED();
135 return false;
136 }
137
138 bool OpenSLESInputStream::CreateRecorder() {
139 // Initializes the engine object with specific option. After working with the
140 // object, we need to free the object and its resources.
141 SLEngineOption option[] = {
142 { SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE) }
143 };
144 SLresult err = slCreateEngine(engine_object_.Receive(),
145 1,
146 option,
147 0,
148 NULL,
149 NULL);
150 DCHECK_EQ(SL_RESULT_SUCCESS, err);
151 if (SL_RESULT_SUCCESS != err)
152 return false;
153
154 // Realize the SL engine object in synchronous mode.
155 err = engine_object_->Realize(engine_object_.Get(), SL_BOOLEAN_FALSE);
156 DCHECK_EQ(SL_RESULT_SUCCESS, err);
157 if (SL_RESULT_SUCCESS != err)
158 return false;
159
160 // Get the SL engine interface which is implicit.
161 SLEngineItf engine;
162 err = engine_object_->GetInterface(
163 engine_object_.Get(), SL_IID_ENGINE, &engine);
164 DCHECK_EQ(SL_RESULT_SUCCESS, err);
165 if (SL_RESULT_SUCCESS != err)
166 return false;
167
168 // Audio source configuration.
169 SLDataLocator_IODevice mic_locator = {
170 SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT,
171 SL_DEFAULTDEVICEID_AUDIOINPUT, NULL
172 };
173 SLDataSource audio_source = { &mic_locator, NULL };
174
175 // Audio sink configuration.
176 SLDataLocator_AndroidSimpleBufferQueue buffer_queue = {
177 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, // Locator type.
178 static_cast<SLuint32>(kNumOfQueuesInBuffer) // Number of buffers.
179 };
180 SLDataSink audio_sink = { &buffer_queue, &format_ };
181
182 // Create an audio recorder.
183 const SLuint32 number_of_interfaces = 1;
184 const SLInterfaceID interface_id[number_of_interfaces] = {
185 SL_IID_ANDROIDSIMPLEBUFFERQUEUE
186 };
187 const SLboolean interface_required[number_of_interfaces] = {
188 SL_BOOLEAN_TRUE
189 };
190 err = (*engine)->CreateAudioRecorder(engine,
191 recorder_object_.Receive(),
192 &audio_source,
193 &audio_sink,
194 number_of_interfaces,
195 interface_id,
196 interface_required);
197 DCHECK_EQ(SL_RESULT_SUCCESS, err);
198 if (SL_RESULT_SUCCESS != err) {
199 DLOG(ERROR) << "CreateAudioRecorder failed with error code " << err;
200 return false;
201 }
202
203 // Realize the recorder object in synchronous mode.
204 err = recorder_object_->Realize(recorder_object_.Get(), SL_BOOLEAN_FALSE);
205 DCHECK_EQ(SL_RESULT_SUCCESS, err);
206 if (SL_RESULT_SUCCESS != err) {
207 DLOG(ERROR) << "Recprder Realize() failed with error code " << err;
208 return false;
209 }
210
211 // Get an implicit recorder interface.
212 err = recorder_object_->GetInterface(recorder_object_.Get(),
213 SL_IID_RECORD,
214 &recorder_);
215 DCHECK_EQ(SL_RESULT_SUCCESS, err);
216 if (SL_RESULT_SUCCESS != err)
217 return false;
218
219 // Get the simple buffer queue interface.
220 err = recorder_object_->GetInterface(recorder_object_.Get(),
221 SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
222 &simple_buffer_queue_);
223 DCHECK_EQ(SL_RESULT_SUCCESS, err);
224 if (SL_RESULT_SUCCESS != err)
225 return false;
226
227 // Register the input callback for the simple buffer queue.
228 // This callback will be called when receiving new data from the device.
229 err = (*simple_buffer_queue_)->RegisterCallback(simple_buffer_queue_,
230 SimpleBufferQueueCallback,
231 this);
232 DCHECK_EQ(SL_RESULT_SUCCESS, err);
233
234 return (SL_RESULT_SUCCESS == err);
235 }
236
237 void OpenSLESInputStream::SimpleBufferQueueCallback(
238 SLAndroidSimpleBufferQueueItf buffer_queue, void* instance) {
239 OpenSLESInputStream* stream =
240 reinterpret_cast<OpenSLESInputStream*>(instance);
241 stream->ReadBufferQueue();
242 }
243
244 void OpenSLESInputStream::ReadBufferQueue() {
245 if (!started_)
246 return;
247
248 // Get the enqueued buffer from the soundcard.
249 SLresult err = (*simple_buffer_queue_)->Enqueue(
250 simple_buffer_queue_,
251 audio_data_[active_queue_],
252 buffer_size_bytes_);
253 if (SL_RESULT_SUCCESS != err)
254 HandleError(err);
255
256 // TODO(xians): Get an accurate delay estimation.
257 callback_->OnData(this,
258 audio_data_[active_queue_],
259 buffer_size_bytes_,
260 buffer_size_bytes_,
261 0.0);
262
263 active_queue_ = ++active_queue_ % kNumOfQueuesInBuffer;
264 }
265
266 void OpenSLESInputStream::HandleError(SLresult error) {
267 DLOG(FATAL) << "OpenSLES error " << error;
268 if (callback_)
269 callback_->OnError(this, error);
270 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698