FreeRDP
rdpsnd/client/opensles/opensl_io.c
1 /*
2 opensl_io.c:
3 Android OpenSL input/output module
4 Copyright (c) 2012, Victor Lazzarini
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9  * Redistributions of source code must retain the above copyright
10  notice, this list of conditions and the following disclaimer.
11  * Redistributions in binary form must reproduce the above copyright
12  notice, this list of conditions and the following disclaimer in the
13  documentation and/or other materials provided with the distribution.
14  * Neither the name of the <organization> nor the
15  names of its contributors may be used to endorse or promote products
16  derived from this software without specific prior written permission.
17 
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
22 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 
30 #include <winpr/assert.h>
31 
32 #include "rdpsnd_main.h"
33 #include "opensl_io.h"
34 #define CONV16BIT 32768
35 #define CONVMYFLT (1. / 32768.)
36 
37 static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context);
38 
39 // creates the OpenSL ES audio engine
40 static SLresult openSLCreateEngine(OPENSL_STREAM* p)
41 {
42  SLresult result;
43  // create engine
44  result = slCreateEngine(&(p->engineObject), 0, NULL, 0, NULL, NULL);
45  DEBUG_SND("engineObject=%p", (void*)p->engineObject);
46 
47  if (result != SL_RESULT_SUCCESS)
48  goto engine_end;
49 
50  // realize the engine
51  result = (*p->engineObject)->Realize(p->engineObject, SL_BOOLEAN_FALSE);
52  DEBUG_SND("Realize=%" PRIu32 "", result);
53 
54  if (result != SL_RESULT_SUCCESS)
55  goto engine_end;
56 
57  // get the engine interface, which is needed in order to create other objects
58  result = (*p->engineObject)->GetInterface(p->engineObject, SL_IID_ENGINE, &(p->engineEngine));
59  DEBUG_SND("engineEngine=%p", (void*)p->engineEngine);
60 
61  if (result != SL_RESULT_SUCCESS)
62  goto engine_end;
63 
64 engine_end:
65  return result;
66 }
67 
68 // opens the OpenSL ES device for output
69 static SLresult openSLPlayOpen(OPENSL_STREAM* p)
70 {
71  SLresult result;
72  SLuint32 sr = p->sr;
73  SLuint32 channels = p->outchannels;
74  WINPR_ASSERT(p->engineObject);
75  WINPR_ASSERT(p->engineEngine);
76 
77  if (channels)
78  {
79  // configure audio source
80  SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
81  p->queuesize };
82 
83  switch (sr)
84  {
85  case 8000:
86  sr = SL_SAMPLINGRATE_8;
87  break;
88 
89  case 11025:
90  sr = SL_SAMPLINGRATE_11_025;
91  break;
92 
93  case 16000:
94  sr = SL_SAMPLINGRATE_16;
95  break;
96 
97  case 22050:
98  sr = SL_SAMPLINGRATE_22_05;
99  break;
100 
101  case 24000:
102  sr = SL_SAMPLINGRATE_24;
103  break;
104 
105  case 32000:
106  sr = SL_SAMPLINGRATE_32;
107  break;
108 
109  case 44100:
110  sr = SL_SAMPLINGRATE_44_1;
111  break;
112 
113  case 48000:
114  sr = SL_SAMPLINGRATE_48;
115  break;
116 
117  case 64000:
118  sr = SL_SAMPLINGRATE_64;
119  break;
120 
121  case 88200:
122  sr = SL_SAMPLINGRATE_88_2;
123  break;
124 
125  case 96000:
126  sr = SL_SAMPLINGRATE_96;
127  break;
128 
129  case 192000:
130  sr = SL_SAMPLINGRATE_192;
131  break;
132 
133  default:
134  return -1;
135  }
136 
137  const SLInterfaceID ids[] = { SL_IID_VOLUME };
138  const SLboolean req[] = { SL_BOOLEAN_FALSE };
139  result = (*p->engineEngine)
140  ->CreateOutputMix(p->engineEngine, &(p->outputMixObject), 1, ids, req);
141  DEBUG_SND("engineEngine=%p", (void*)p->engineEngine);
142  WINPR_ASSERT(!result);
143 
144  if (result != SL_RESULT_SUCCESS)
145  goto end_openaudio;
146 
147  // realize the output mix
148  result = (*p->outputMixObject)->Realize(p->outputMixObject, SL_BOOLEAN_FALSE);
149  DEBUG_SND("Realize=%" PRIu32 "", result);
150  WINPR_ASSERT(!result);
151 
152  if (result != SL_RESULT_SUCCESS)
153  goto end_openaudio;
154 
155  int speakers;
156 
157  if (channels > 1)
158  speakers = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
159  else
160  speakers = SL_SPEAKER_FRONT_CENTER;
161 
162  SLDataFormat_PCM format_pcm = { SL_DATAFORMAT_PCM,
163  channels,
164  sr,
165  SL_PCMSAMPLEFORMAT_FIXED_16,
166  SL_PCMSAMPLEFORMAT_FIXED_16,
167  speakers,
168  SL_BYTEORDER_LITTLEENDIAN };
169  SLDataSource audioSrc = { &loc_bufq, &format_pcm };
170  // configure audio sink
171  SLDataLocator_OutputMix loc_outmix = { SL_DATALOCATOR_OUTPUTMIX, p->outputMixObject };
172  SLDataSink audioSnk = { &loc_outmix, NULL };
173  // create audio player
174  const SLInterfaceID ids1[] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_VOLUME };
175  const SLboolean req1[] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
176  result = (*p->engineEngine)
177  ->CreateAudioPlayer(p->engineEngine, &(p->bqPlayerObject), &audioSrc,
178  &audioSnk, 2, ids1, req1);
179  DEBUG_SND("bqPlayerObject=%p", (void*)p->bqPlayerObject);
180  WINPR_ASSERT(!result);
181 
182  if (result != SL_RESULT_SUCCESS)
183  goto end_openaudio;
184 
185  // realize the player
186  result = (*p->bqPlayerObject)->Realize(p->bqPlayerObject, SL_BOOLEAN_FALSE);
187  DEBUG_SND("Realize=%" PRIu32 "", result);
188  WINPR_ASSERT(!result);
189 
190  if (result != SL_RESULT_SUCCESS)
191  goto end_openaudio;
192 
193  // get the play interface
194  result =
195  (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject, SL_IID_PLAY, &(p->bqPlayerPlay));
196  DEBUG_SND("bqPlayerPlay=%p", (void*)p->bqPlayerPlay);
197  WINPR_ASSERT(!result);
198 
199  if (result != SL_RESULT_SUCCESS)
200  goto end_openaudio;
201 
202  // get the volume interface
203  result = (*p->bqPlayerObject)
204  ->GetInterface(p->bqPlayerObject, SL_IID_VOLUME, &(p->bqPlayerVolume));
205  DEBUG_SND("bqPlayerVolume=%p", (void*)p->bqPlayerVolume);
206  WINPR_ASSERT(!result);
207 
208  if (result != SL_RESULT_SUCCESS)
209  goto end_openaudio;
210 
211  // get the buffer queue interface
212  result = (*p->bqPlayerObject)
213  ->GetInterface(p->bqPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
214  &(p->bqPlayerBufferQueue));
215  DEBUG_SND("bqPlayerBufferQueue=%p", (void*)p->bqPlayerBufferQueue);
216  WINPR_ASSERT(!result);
217 
218  if (result != SL_RESULT_SUCCESS)
219  goto end_openaudio;
220 
221  // register callback on the buffer queue
222  result = (*p->bqPlayerBufferQueue)
223  ->RegisterCallback(p->bqPlayerBufferQueue, bqPlayerCallback, p);
224  DEBUG_SND("bqPlayerCallback=%p", (void*)p->bqPlayerCallback);
225  WINPR_ASSERT(!result);
226 
227  if (result != SL_RESULT_SUCCESS)
228  goto end_openaudio;
229 
230  // set the player's state to playing
231  result = (*p->bqPlayerPlay)->SetPlayState(p->bqPlayerPlay, SL_PLAYSTATE_PLAYING);
232  DEBUG_SND("SetPlayState=%" PRIu32 "", result);
233  WINPR_ASSERT(!result);
234  end_openaudio:
235  WINPR_ASSERT(!result);
236  return result;
237  }
238 
239  return SL_RESULT_SUCCESS;
240 }
241 
242 // close the OpenSL IO and destroy the audio engine
243 static void openSLDestroyEngine(OPENSL_STREAM* p)
244 {
245  // destroy buffer queue audio player object, and invalidate all associated interfaces
246  if (p->bqPlayerObject != NULL)
247  {
248  (*p->bqPlayerObject)->Destroy(p->bqPlayerObject);
249  p->bqPlayerObject = NULL;
250  p->bqPlayerVolume = NULL;
251  p->bqPlayerPlay = NULL;
252  p->bqPlayerBufferQueue = NULL;
253  p->bqPlayerEffectSend = NULL;
254  }
255 
256  // destroy output mix object, and invalidate all associated interfaces
257  if (p->outputMixObject != NULL)
258  {
259  (*p->outputMixObject)->Destroy(p->outputMixObject);
260  p->outputMixObject = NULL;
261  }
262 
263  // destroy engine object, and invalidate all associated interfaces
264  if (p->engineObject != NULL)
265  {
266  (*p->engineObject)->Destroy(p->engineObject);
267  p->engineObject = NULL;
268  p->engineEngine = NULL;
269  }
270 }
271 
272 // open the android audio device for and/or output
273 OPENSL_STREAM* android_OpenAudioDevice(int sr, int outchannels, int bufferframes)
274 {
275  OPENSL_STREAM* p;
276  p = (OPENSL_STREAM*)calloc(1, sizeof(OPENSL_STREAM));
277 
278  if (!p)
279  return NULL;
280 
281  p->queuesize = bufferframes;
282  p->outchannels = outchannels;
283  p->sr = sr;
284 
285  if (openSLCreateEngine(p) != SL_RESULT_SUCCESS)
286  {
287  android_CloseAudioDevice(p);
288  return NULL;
289  }
290 
291  if (openSLPlayOpen(p) != SL_RESULT_SUCCESS)
292  {
293  android_CloseAudioDevice(p);
294  return NULL;
295  }
296 
297  p->queue = Queue_New(TRUE, -1, -1);
298 
299  if (!p->queue)
300  {
301  android_CloseAudioDevice(p);
302  return NULL;
303  }
304 
305  return p;
306 }
307 
308 // close the android audio device
309 void android_CloseAudioDevice(OPENSL_STREAM* p)
310 {
311  if (p == NULL)
312  return;
313 
314  openSLDestroyEngine(p);
315 
316  if (p->queue)
317  Queue_Free(p->queue);
318 
319  free(p);
320 }
321 
322 // this callback handler is called every time a buffer finishes playing
323 static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context)
324 {
325  OPENSL_STREAM* p = (OPENSL_STREAM*)context;
326  WINPR_ASSERT(p);
327  WINPR_ASSERT(p->queue);
328  void* data = Queue_Dequeue(p->queue);
329  free(data);
330 }
331 
332 // puts a buffer of size samples to the device
333 int android_AudioOut(OPENSL_STREAM* p, const short* buffer, int size)
334 {
335  HANDLE ev;
336  WINPR_ASSERT(p);
337  WINPR_ASSERT(buffer);
338  WINPR_ASSERT(size > 0);
339 
340  ev = Queue_Event(p->queue);
341  /* Assure, that the queue is not full. */
342  if (p->queuesize <= Queue_Count(p->queue) && WaitForSingleObject(ev, INFINITE) == WAIT_FAILED)
343  {
344  DEBUG_SND("WaitForSingleObject failed!");
345  return -1;
346  }
347 
348  void* data = calloc(size, sizeof(short));
349 
350  if (!data)
351  {
352  DEBUG_SND("unable to allocate a buffer");
353  return -1;
354  }
355 
356  memcpy(data, buffer, size * sizeof(short));
357  Queue_Enqueue(p->queue, data);
358  (*p->bqPlayerBufferQueue)->Enqueue(p->bqPlayerBufferQueue, data, sizeof(short) * size);
359  return size;
360 }
361 
362 int android_GetOutputMute(OPENSL_STREAM* p)
363 {
364  SLboolean mute;
365  WINPR_ASSERT(p);
366  WINPR_ASSERT(p->bqPlayerVolume);
367  SLresult rc = (*p->bqPlayerVolume)->GetMute(p->bqPlayerVolume, &mute);
368 
369  if (SL_RESULT_SUCCESS != rc)
370  return SL_BOOLEAN_FALSE;
371 
372  return mute;
373 }
374 
375 BOOL android_SetOutputMute(OPENSL_STREAM* p, BOOL _mute)
376 {
377  SLboolean mute = _mute;
378  WINPR_ASSERT(p);
379  WINPR_ASSERT(p->bqPlayerVolume);
380  SLresult rc = (*p->bqPlayerVolume)->SetMute(p->bqPlayerVolume, mute);
381 
382  if (SL_RESULT_SUCCESS != rc)
383  return FALSE;
384 
385  return TRUE;
386 }
387 
388 int android_GetOutputVolume(OPENSL_STREAM* p)
389 {
390  SLmillibel level;
391  WINPR_ASSERT(p);
392  WINPR_ASSERT(p->bqPlayerVolume);
393  SLresult rc = (*p->bqPlayerVolume)->GetVolumeLevel(p->bqPlayerVolume, &level);
394 
395  if (SL_RESULT_SUCCESS != rc)
396  return 0;
397 
398  return level;
399 }
400 
401 int android_GetOutputVolumeMax(OPENSL_STREAM* p)
402 {
403  SLmillibel level;
404  WINPR_ASSERT(p);
405  WINPR_ASSERT(p->bqPlayerVolume);
406  SLresult rc = (*p->bqPlayerVolume)->GetMaxVolumeLevel(p->bqPlayerVolume, &level);
407 
408  if (SL_RESULT_SUCCESS != rc)
409  return 0;
410 
411  return level;
412 }
413 
414 BOOL android_SetOutputVolume(OPENSL_STREAM* p, int level)
415 {
416  SLresult rc = (*p->bqPlayerVolume)->SetVolumeLevel(p->bqPlayerVolume, level);
417 
418  if (SL_RESULT_SUCCESS != rc)
419  return FALSE;
420 
421  return TRUE;
422 }