1 /*
2  * Copyright © 2012 Mozilla Foundation
3  *
4  * This program is made available under an ISC-style license.  See the
5  * accompanying file LICENSE for details.
6  */
7 #undef NDEBUG
8 #include <assert.h>
9 #include <dlfcn.h>
10 #include <stdlib.h>
11 #include <pthread.h>
12 #include <SLES/OpenSLES.h>
13 #include <math.h>
14 #include <time.h>
15 #if defined(__ANDROID__)
16 #include <dlfcn.h>
17 #include <sys/system_properties.h>
18 #include "android/sles_definitions.h"
19 #include <SLES/OpenSLES_Android.h>
20 #include <android/log.h>
21 #include <android/api-level.h>
22 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Cubeb_OpenSL" , ## args)
23 #define ANDROID_VERSION_GINGERBREAD_MR1 10
24 #define ANDROID_VERSION_LOLLIPOP 21
25 #define ANDROID_VERSION_MARSHMALLOW 23
26 #endif
27 #include "cubeb/cubeb.h"
28 #include "cubeb-internal.h"
29 #include "cubeb_resampler.h"
30 #include "cubeb-sles.h"
31 
32 static struct cubeb_ops const opensl_ops;
33 
34 struct cubeb {
35   struct cubeb_ops const * ops;
36   void * lib;
37   void * libmedia;
38   int32_t (* get_output_latency)(uint32_t * latency, int stream_type);
39   SLInterfaceID SL_IID_BUFFERQUEUE;
40   SLInterfaceID SL_IID_PLAY;
41 #if defined(__ANDROID__)
42   SLInterfaceID SL_IID_ANDROIDCONFIGURATION;
43 #endif
44   SLInterfaceID SL_IID_VOLUME;
45   SLObjectItf engObj;
46   SLEngineItf eng;
47   SLObjectItf outmixObj;
48 };
49 
50 #define NELEMS(A) (sizeof(A) / sizeof A[0])
51 #define NBUFS 4
52 #define AUDIO_STREAM_TYPE_MUSIC 3
53 
54 struct cubeb_stream {
55   cubeb * context;
56   pthread_mutex_t mutex;
57   SLObjectItf playerObj;
58   SLPlayItf play;
59   SLBufferQueueItf bufq;
60   SLVolumeItf volume;
61   uint8_t *queuebuf[NBUFS];
62   int queuebuf_idx;
63   long queuebuf_len;
64   long bytespersec;
65   long framesize;
66   long written;
67   int draining;
68   cubeb_stream_type stream_type;
69 
70   cubeb_data_callback data_callback;
71   cubeb_state_callback state_callback;
72   void * user_ptr;
73 
74   cubeb_resampler * resampler;
75   unsigned int inputrate;
76   unsigned int outputrate;
77   unsigned int latency;
78   int64_t lastPosition;
79   int64_t lastPositionTimeStamp;
80   int64_t lastCompensativePosition;
81 };
82 
83 static void
play_callback(SLPlayItf caller,void * user_ptr,SLuint32 event)84 play_callback(SLPlayItf caller, void * user_ptr, SLuint32 event)
85 {
86   cubeb_stream * stm = user_ptr;
87   int draining;
88   assert(stm);
89   switch (event) {
90   case SL_PLAYEVENT_HEADATMARKER:
91     pthread_mutex_lock(&stm->mutex);
92     draining = stm->draining;
93     pthread_mutex_unlock(&stm->mutex);
94     if (draining) {
95       stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
96       (*stm->play)->SetPlayState(stm->play, SL_PLAYSTATE_PAUSED);
97     }
98     break;
99   default:
100     break;
101   }
102 }
103 
104 static void
bufferqueue_callback(SLBufferQueueItf caller,void * user_ptr)105 bufferqueue_callback(SLBufferQueueItf caller, void * user_ptr)
106 {
107   cubeb_stream * stm = user_ptr;
108   assert(stm);
109   SLBufferQueueState state;
110   SLresult res;
111 
112   res = (*stm->bufq)->GetState(stm->bufq, &state);
113   assert(res == SL_RESULT_SUCCESS);
114 
115   if (state.count > 1)
116     return;
117 
118   SLuint32 i;
119   for (i = state.count; i < NBUFS; i++) {
120     uint8_t *buf = stm->queuebuf[stm->queuebuf_idx];
121     long written = 0;
122     pthread_mutex_lock(&stm->mutex);
123     int draining = stm->draining;
124     pthread_mutex_unlock(&stm->mutex);
125 
126     if (!draining) {
127       written = cubeb_resampler_fill(stm->resampler,
128                                      NULL, NULL,
129                                      buf, stm->queuebuf_len / stm->framesize);
130       if (written < 0 || written * stm->framesize > stm->queuebuf_len) {
131         (*stm->play)->SetPlayState(stm->play, SL_PLAYSTATE_PAUSED);
132         return;
133       }
134     }
135 
136     // Keep sending silent data even in draining mode to prevent the audio
137     // back-end from being stopped automatically by OpenSL/ES.
138     memset(buf + written * stm->framesize, 0, stm->queuebuf_len - written * stm->framesize);
139     res = (*stm->bufq)->Enqueue(stm->bufq, buf, stm->queuebuf_len);
140     assert(res == SL_RESULT_SUCCESS);
141     stm->queuebuf_idx = (stm->queuebuf_idx + 1) % NBUFS;
142     if (written > 0) {
143       pthread_mutex_lock(&stm->mutex);
144       stm->written += written;
145       pthread_mutex_unlock(&stm->mutex);
146     }
147 
148     if (!draining && written * stm->framesize < stm->queuebuf_len) {
149       pthread_mutex_lock(&stm->mutex);
150       int64_t written_duration = INT64_C(1000) * stm->written * stm->framesize / stm->bytespersec;
151       stm->draining = 1;
152       pthread_mutex_unlock(&stm->mutex);
153       // Use SL_PLAYEVENT_HEADATMARKER event from slPlayCallback of SLPlayItf
154       // to make sure all the data has been processed.
155       (*stm->play)->SetMarkerPosition(stm->play, (SLmillisecond)written_duration);
156       return;
157     }
158   }
159 }
160 
161 #if defined(__ANDROID__)
162 static SLuint32
convert_stream_type_to_sl_stream(cubeb_stream_type stream_type)163 convert_stream_type_to_sl_stream(cubeb_stream_type stream_type)
164 {
165   switch(stream_type) {
166   case CUBEB_STREAM_TYPE_SYSTEM:
167     return SL_ANDROID_STREAM_SYSTEM;
168   case CUBEB_STREAM_TYPE_MUSIC:
169     return SL_ANDROID_STREAM_MEDIA;
170   case CUBEB_STREAM_TYPE_NOTIFICATION:
171     return SL_ANDROID_STREAM_NOTIFICATION;
172   case CUBEB_STREAM_TYPE_ALARM:
173     return SL_ANDROID_STREAM_ALARM;
174   case CUBEB_STREAM_TYPE_VOICE_CALL:
175     return SL_ANDROID_STREAM_VOICE;
176   case CUBEB_STREAM_TYPE_RING:
177     return SL_ANDROID_STREAM_RING;
178   case CUBEB_STREAM_TYPE_SYSTEM_ENFORCED:
179     return SL_ANDROID_STREAM_SYSTEM_ENFORCED;
180   default:
181     return 0xFFFFFFFF;
182   }
183 }
184 #endif
185 
186 static void opensl_destroy(cubeb * ctx);
187 
188 #if defined(__ANDROID__)
189 
190 // The bionic header file on B2G contains the required
191 // declarations on all releases.
192 #ifndef MOZ_WIDGET_GONK
193 
194 #if (__ANDROID_API__ >= ANDROID_VERSION_LOLLIPOP)
195 typedef int (system_property_get)(const char*, char*);
196 
197 static int
__system_property_get(const char * name,char * value)198 __system_property_get(const char* name, char* value)
199 {
200   void* libc = dlopen("libc.so", RTLD_LAZY);
201   if (!libc) {
202     LOG("Failed to open libc.so");
203     return -1;
204   }
205   system_property_get* func = (system_property_get*)
206                               dlsym(libc, "__system_property_get");
207   int ret = -1;
208   if (func) {
209     ret = func(name, value);
210   }
211   dlclose(libc);
212   return ret;
213 }
214 #endif
215 #endif
216 
217 static int
get_android_version(void)218 get_android_version(void)
219 {
220   char version_string[PROP_VALUE_MAX];
221 
222   memset(version_string, 0, PROP_VALUE_MAX);
223 
224   int len = __system_property_get("ro.build.version.sdk", version_string);
225   if (len <= 0) {
226     LOG("Failed to get Android version!\n");
227     return len;
228   }
229 
230   int version = (int)strtol(version_string, NULL, 10);
231   LOG("%d", version);
232   return version;
233 }
234 #endif
235 
236 /*static*/ int
opensl_init(cubeb ** context,char const * context_name)237 opensl_init(cubeb ** context, char const * context_name)
238 {
239   cubeb * ctx;
240 
241 #if defined(__ANDROID__)
242   int android_version = get_android_version();
243   if (android_version > 0 && android_version <= ANDROID_VERSION_GINGERBREAD_MR1) {
244     // Don't even attempt to run on Gingerbread and lower
245     return CUBEB_ERROR;
246   }
247 #endif
248 
249   *context = NULL;
250 
251   ctx = calloc(1, sizeof(*ctx));
252   assert(ctx);
253 
254   ctx->ops = &opensl_ops;
255 
256   ctx->lib = dlopen("libOpenSLES.so", RTLD_LAZY);
257   ctx->libmedia = dlopen("libmedia.so", RTLD_LAZY);
258   if (!ctx->lib || !ctx->libmedia) {
259     free(ctx);
260     return CUBEB_ERROR;
261   }
262 
263   /* Get the latency, in ms, from AudioFlinger */
264   /* status_t AudioSystem::getOutputLatency(uint32_t* latency,
265    *                                        audio_stream_type_t streamType) */
266   /* First, try the most recent signature. */
267   ctx->get_output_latency =
268     dlsym(ctx->libmedia, "_ZN7android11AudioSystem16getOutputLatencyEPj19audio_stream_type_t");
269   if (!ctx->get_output_latency) {
270     /* in case of failure, try the legacy version. */
271     /* status_t AudioSystem::getOutputLatency(uint32_t* latency,
272      *                                        int streamType) */
273     ctx->get_output_latency =
274       dlsym(ctx->libmedia, "_ZN7android11AudioSystem16getOutputLatencyEPji");
275     if (!ctx->get_output_latency) {
276       opensl_destroy(ctx);
277       return CUBEB_ERROR;
278     }
279   }
280 
281   typedef SLresult (*slCreateEngine_t)(SLObjectItf *,
282                                        SLuint32,
283                                        const SLEngineOption *,
284                                        SLuint32,
285                                        const SLInterfaceID *,
286                                        const SLboolean *);
287   slCreateEngine_t f_slCreateEngine =
288     (slCreateEngine_t)dlsym(ctx->lib, "slCreateEngine");
289   SLInterfaceID SL_IID_ENGINE = *(SLInterfaceID *)dlsym(ctx->lib, "SL_IID_ENGINE");
290   SLInterfaceID SL_IID_OUTPUTMIX = *(SLInterfaceID *)dlsym(ctx->lib, "SL_IID_OUTPUTMIX");
291   ctx->SL_IID_VOLUME = *(SLInterfaceID *)dlsym(ctx->lib, "SL_IID_VOLUME");
292   ctx->SL_IID_BUFFERQUEUE = *(SLInterfaceID *)dlsym(ctx->lib, "SL_IID_BUFFERQUEUE");
293 #if defined(__ANDROID__)
294   ctx->SL_IID_ANDROIDCONFIGURATION = *(SLInterfaceID *)dlsym(ctx->lib, "SL_IID_ANDROIDCONFIGURATION");
295 #endif
296   ctx->SL_IID_PLAY = *(SLInterfaceID *)dlsym(ctx->lib, "SL_IID_PLAY");
297   if (!f_slCreateEngine ||
298       !SL_IID_ENGINE ||
299       !SL_IID_OUTPUTMIX ||
300       !ctx->SL_IID_BUFFERQUEUE ||
301 #if defined(__ANDROID__)
302       !ctx->SL_IID_ANDROIDCONFIGURATION ||
303 #endif
304       !ctx->SL_IID_PLAY) {
305     opensl_destroy(ctx);
306     return CUBEB_ERROR;
307   }
308 
309   const SLEngineOption opt[] = {{SL_ENGINEOPTION_THREADSAFE, SL_BOOLEAN_TRUE}};
310 
311   SLresult res;
312   res = cubeb_get_sles_engine(&ctx->engObj, 1, opt, 0, NULL, NULL);
313 
314   if (res != SL_RESULT_SUCCESS) {
315     opensl_destroy(ctx);
316     return CUBEB_ERROR;
317   }
318 
319   res = cubeb_realize_sles_engine(ctx->engObj);
320   if (res != SL_RESULT_SUCCESS) {
321     opensl_destroy(ctx);
322     return CUBEB_ERROR;
323   }
324 
325   res = (*ctx->engObj)->GetInterface(ctx->engObj, SL_IID_ENGINE, &ctx->eng);
326   if (res != SL_RESULT_SUCCESS) {
327     opensl_destroy(ctx);
328     return CUBEB_ERROR;
329   }
330 
331   const SLInterfaceID idsom[] = {SL_IID_OUTPUTMIX};
332   const SLboolean reqom[] = {SL_BOOLEAN_TRUE};
333   res = (*ctx->eng)->CreateOutputMix(ctx->eng, &ctx->outmixObj, 1, idsom, reqom);
334   if (res != SL_RESULT_SUCCESS) {
335     opensl_destroy(ctx);
336     return CUBEB_ERROR;
337   }
338 
339   res = (*ctx->outmixObj)->Realize(ctx->outmixObj, SL_BOOLEAN_FALSE);
340   if (res != SL_RESULT_SUCCESS) {
341     opensl_destroy(ctx);
342     return CUBEB_ERROR;
343   }
344 
345   *context = ctx;
346 
347   return CUBEB_OK;
348 }
349 
350 static char const *
opensl_get_backend_id(cubeb * ctx)351 opensl_get_backend_id(cubeb * ctx)
352 {
353   return "opensl";
354 }
355 
356 static int
opensl_get_max_channel_count(cubeb * ctx,uint32_t * max_channels)357 opensl_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
358 {
359   assert(ctx && max_channels);
360   /* The android mixer handles up to two channels, see
361      http://androidxref.com/4.2.2_r1/xref/frameworks/av/services/audioflinger/AudioFlinger.h#67 */
362   *max_channels = 2;
363 
364   return CUBEB_OK;
365 }
366 
367 static int
opensl_get_preferred_sample_rate(cubeb * ctx,uint32_t * rate)368 opensl_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
369 {
370   /* https://android.googlesource.com/platform/ndk.git/+/master/docs/opensles/index.html
371    * We don't want to deal with JNI here (and we don't have Java on b2g anyways),
372    * so we just dlopen the library and get the two symbols we need. */
373   int r;
374   void * libmedia;
375   uint32_t (*get_primary_output_samplingrate)();
376   uint32_t (*get_output_samplingrate)(int * samplingRate, int streamType);
377 
378   libmedia = dlopen("libmedia.so", RTLD_LAZY);
379   if (!libmedia) {
380     return CUBEB_ERROR;
381   }
382 
383   /* uint32_t AudioSystem::getPrimaryOutputSamplingRate(void) */
384   get_primary_output_samplingrate =
385     dlsym(libmedia, "_ZN7android11AudioSystem28getPrimaryOutputSamplingRateEv");
386   if (!get_primary_output_samplingrate) {
387     /* fallback to
388      * status_t AudioSystem::getOutputSamplingRate(int* samplingRate, int streamType)
389      * if we cannot find getPrimaryOutputSamplingRate. */
390     get_output_samplingrate =
391       dlsym(libmedia, "_ZN7android11AudioSystem21getOutputSamplingRateEPj19audio_stream_type_t");
392     if (!get_output_samplingrate) {
393       /* Another signature exists, with a int instead of an audio_stream_type_t */
394       get_output_samplingrate =
395         dlsym(libmedia, "_ZN7android11AudioSystem21getOutputSamplingRateEPii");
396       if (!get_output_samplingrate) {
397         dlclose(libmedia);
398         return CUBEB_ERROR;
399       }
400     }
401   }
402 
403   if (get_primary_output_samplingrate) {
404     *rate = get_primary_output_samplingrate();
405   } else {
406     /* We don't really know about the type, here, so we just pass music. */
407     r = get_output_samplingrate((int *) rate, AUDIO_STREAM_TYPE_MUSIC);
408     if (r) {
409       dlclose(libmedia);
410       return CUBEB_ERROR;
411     }
412   }
413 
414   dlclose(libmedia);
415 
416   /* Depending on which method we called above, we can get a zero back, yet have
417    * a non-error return value, especially if the audio system is not
418    * ready/shutting down (i.e. when we can't get our hand on the AudioFlinger
419    * thread). */
420   if (*rate == 0) {
421     return CUBEB_ERROR;
422   }
423 
424   return CUBEB_OK;
425 }
426 
427 static int
opensl_get_min_latency(cubeb * ctx,cubeb_stream_params params,uint32_t * latency_frames)428 opensl_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * latency_frames)
429 {
430   /* https://android.googlesource.com/platform/ndk.git/+/master/docs/opensles/index.html
431    * We don't want to deal with JNI here (and we don't have Java on b2g anyways),
432    * so we just dlopen the library and get the two symbols we need. */
433 
434   int r;
435   void * libmedia;
436   size_t (*get_primary_output_frame_count)(void);
437   int (*get_output_frame_count)(size_t * frameCount, int streamType);
438   uint32_t primary_sampling_rate;
439   size_t primary_buffer_size;
440 
441   r = opensl_get_preferred_sample_rate(ctx, &primary_sampling_rate);
442 
443   if (r) {
444     return CUBEB_ERROR;
445   }
446 
447   libmedia = dlopen("libmedia.so", RTLD_LAZY);
448   if (!libmedia) {
449     return CUBEB_ERROR;
450   }
451 
452   /* JB variant */
453   /* size_t AudioSystem::getPrimaryOutputFrameCount(void) */
454   get_primary_output_frame_count =
455     dlsym(libmedia, "_ZN7android11AudioSystem26getPrimaryOutputFrameCountEv");
456   if (!get_primary_output_frame_count) {
457     /* ICS variant */
458     /* status_t AudioSystem::getOutputFrameCount(int* frameCount, int streamType) */
459     get_output_frame_count =
460       dlsym(libmedia, "_ZN7android11AudioSystem19getOutputFrameCountEPii");
461     if (!get_output_frame_count) {
462       dlclose(libmedia);
463       return CUBEB_ERROR;
464     }
465   }
466 
467   if (get_primary_output_frame_count) {
468     primary_buffer_size = get_primary_output_frame_count();
469   } else {
470     if (get_output_frame_count(&primary_buffer_size, params.stream_type) != 0) {
471       return CUBEB_ERROR;
472     }
473   }
474 
475   /* To get a fast track in Android's mixer, we need to be at the native
476    * samplerate, which is device dependant. Some devices might be able to
477    * resample when playing a fast track, but it's pretty rare. */
478   *latency_frames = NBUFS * primary_buffer_size;
479 
480   dlclose(libmedia);
481 
482   return CUBEB_OK;
483 }
484 
485 static void
opensl_destroy(cubeb * ctx)486 opensl_destroy(cubeb * ctx)
487 {
488   if (ctx->outmixObj)
489     (*ctx->outmixObj)->Destroy(ctx->outmixObj);
490   if (ctx->engObj)
491     cubeb_destroy_sles_engine(&ctx->engObj);
492   dlclose(ctx->lib);
493   dlclose(ctx->libmedia);
494   free(ctx);
495 }
496 
497 static void opensl_stream_destroy(cubeb_stream * stm);
498 
499 static int
opensl_stream_init(cubeb * ctx,cubeb_stream ** stream,char const * stream_name,cubeb_devid input_device,cubeb_stream_params * input_stream_params,cubeb_devid output_device,cubeb_stream_params * output_stream_params,unsigned int latency_frames,cubeb_data_callback data_callback,cubeb_state_callback state_callback,void * user_ptr)500 opensl_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name,
501                    cubeb_devid input_device,
502                    cubeb_stream_params * input_stream_params,
503                    cubeb_devid output_device,
504                    cubeb_stream_params * output_stream_params,
505                    unsigned int latency_frames,
506                    cubeb_data_callback data_callback, cubeb_state_callback state_callback,
507                    void * user_ptr)
508 {
509   cubeb_stream * stm;
510 
511   assert(ctx);
512   assert(!input_stream_params && "not supported");
513   if (input_device || output_device) {
514     /* Device selection not yet implemented. */
515     return CUBEB_ERROR_DEVICE_UNAVAILABLE;
516   }
517 
518   *stream = NULL;
519 
520   SLDataFormat_PCM format;
521 
522   format.formatType = SL_DATAFORMAT_PCM;
523   format.numChannels = output_stream_params->channels;
524   // samplesPerSec is in milliHertz
525   format.samplesPerSec = output_stream_params->rate * 1000;
526   format.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
527   format.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;
528   format.channelMask = output_stream_params->channels == 1 ?
529     SL_SPEAKER_FRONT_CENTER :
530     SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
531 
532   switch (output_stream_params->format) {
533   case CUBEB_SAMPLE_S16LE:
534     format.endianness = SL_BYTEORDER_LITTLEENDIAN;
535     break;
536   case CUBEB_SAMPLE_S16BE:
537     format.endianness = SL_BYTEORDER_BIGENDIAN;
538     break;
539   default:
540     return CUBEB_ERROR_INVALID_FORMAT;
541   }
542 
543   stm = calloc(1, sizeof(*stm));
544   assert(stm);
545 
546   stm->context = ctx;
547   stm->data_callback = data_callback;
548   stm->state_callback = state_callback;
549   stm->user_ptr = user_ptr;
550 
551   stm->inputrate = output_stream_params->rate;
552   stm->latency = latency_frames;
553   stm->stream_type = output_stream_params->stream_type;
554   stm->framesize = output_stream_params->channels * sizeof(int16_t);
555   stm->lastPosition = -1;
556   stm->lastPositionTimeStamp = 0;
557   stm->lastCompensativePosition = -1;
558 
559   int r = pthread_mutex_init(&stm->mutex, NULL);
560   assert(r == 0);
561 
562   SLDataLocator_BufferQueue loc_bufq;
563   loc_bufq.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
564   loc_bufq.numBuffers = NBUFS;
565   SLDataSource source;
566   source.pLocator = &loc_bufq;
567   source.pFormat = &format;
568 
569   SLDataLocator_OutputMix loc_outmix;
570   loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
571   loc_outmix.outputMix = ctx->outmixObj;
572   SLDataSink sink;
573   sink.pLocator = &loc_outmix;
574   sink.pFormat = NULL;
575 
576 #if defined(__ANDROID__)
577   const SLInterfaceID ids[] = {ctx->SL_IID_BUFFERQUEUE,
578                                ctx->SL_IID_VOLUME,
579                                ctx->SL_IID_ANDROIDCONFIGURATION};
580   const SLboolean req[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
581 #else
582   const SLInterfaceID ids[] = {ctx->SL_IID_BUFFERQUEUE, ctx->SL_IID_VOLUME};
583   const SLboolean req[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
584 #endif
585   assert(NELEMS(ids) == NELEMS(req));
586 
587   uint32_t preferred_sampling_rate = stm->inputrate;
588 #if defined(__ANDROID__)
589   if (get_android_version() >= ANDROID_VERSION_MARSHMALLOW) {
590     // Reset preferred samping rate to trigger fallback to native sampling rate.
591     preferred_sampling_rate = 0;
592     if (opensl_get_min_latency(ctx, *output_stream_params, &latency_frames) != CUBEB_OK) {
593       // Default to AudioFlinger's advertised fast track latency of 10ms.
594       latency_frames = 440;
595     }
596     stm->latency = latency_frames;
597   }
598 #endif
599 
600   SLresult res = SL_RESULT_CONTENT_UNSUPPORTED;
601   if (preferred_sampling_rate) {
602     res = (*ctx->eng)->CreateAudioPlayer(ctx->eng, &stm->playerObj, &source,
603                                          &sink, NELEMS(ids), ids, req);
604   }
605 
606   // Sample rate not supported? Try again with primary sample rate!
607   if (res == SL_RESULT_CONTENT_UNSUPPORTED) {
608     if (opensl_get_preferred_sample_rate(ctx, &preferred_sampling_rate)) {
609       opensl_stream_destroy(stm);
610       return CUBEB_ERROR;
611     }
612 
613     format.samplesPerSec = preferred_sampling_rate * 1000;
614     res = (*ctx->eng)->CreateAudioPlayer(ctx->eng, &stm->playerObj,
615                                          &source, &sink, NELEMS(ids), ids, req);
616   }
617 
618   if (res != SL_RESULT_SUCCESS) {
619     opensl_stream_destroy(stm);
620     return CUBEB_ERROR;
621   }
622 
623   stm->outputrate = preferred_sampling_rate;
624   stm->bytespersec = stm->outputrate * stm->framesize;
625   stm->queuebuf_len = stm->framesize * latency_frames / NBUFS;
626   // round up to the next multiple of stm->framesize, if needed.
627   if (stm->queuebuf_len % stm->framesize) {
628     stm->queuebuf_len += stm->framesize - (stm->queuebuf_len % stm->framesize);
629   }
630 
631   cubeb_stream_params params = *output_stream_params;
632   params.rate = preferred_sampling_rate;
633 
634   stm->resampler = cubeb_resampler_create(stm, NULL, &params,
635                                           output_stream_params->rate,
636                                           data_callback,
637                                           user_ptr,
638                                           CUBEB_RESAMPLER_QUALITY_DEFAULT);
639 
640   if (!stm->resampler) {
641     opensl_stream_destroy(stm);
642     return CUBEB_ERROR;
643   }
644 
645   int i;
646   for (i = 0; i < NBUFS; i++) {
647     stm->queuebuf[i] = malloc(stm->queuebuf_len);
648     assert(stm->queuebuf[i]);
649   }
650 
651 #if defined(__ANDROID__)
652   SLuint32 stream_type = convert_stream_type_to_sl_stream(output_stream_params->stream_type);
653   if (stream_type != 0xFFFFFFFF) {
654     SLAndroidConfigurationItf playerConfig;
655     res = (*stm->playerObj)->GetInterface(stm->playerObj,
656                                           ctx->SL_IID_ANDROIDCONFIGURATION, &playerConfig);
657     res = (*playerConfig)->SetConfiguration(playerConfig,
658                                             SL_ANDROID_KEY_STREAM_TYPE, &stream_type, sizeof(SLint32));
659     if (res != SL_RESULT_SUCCESS) {
660       opensl_stream_destroy(stm);
661       return CUBEB_ERROR;
662     }
663   }
664 #endif
665 
666   res = (*stm->playerObj)->Realize(stm->playerObj, SL_BOOLEAN_FALSE);
667   if (res != SL_RESULT_SUCCESS) {
668     opensl_stream_destroy(stm);
669     return CUBEB_ERROR;
670   }
671 
672   res = (*stm->playerObj)->GetInterface(stm->playerObj, ctx->SL_IID_PLAY, &stm->play);
673   if (res != SL_RESULT_SUCCESS) {
674     opensl_stream_destroy(stm);
675     return CUBEB_ERROR;
676   }
677 
678   res = (*stm->playerObj)->GetInterface(stm->playerObj, ctx->SL_IID_BUFFERQUEUE,
679                                         &stm->bufq);
680   if (res != SL_RESULT_SUCCESS) {
681     opensl_stream_destroy(stm);
682     return CUBEB_ERROR;
683   }
684 
685   res = (*stm->playerObj)->GetInterface(stm->playerObj, ctx->SL_IID_VOLUME,
686                                         &stm->volume);
687 
688   if (res != SL_RESULT_SUCCESS) {
689     opensl_stream_destroy(stm);
690     return CUBEB_ERROR;
691   }
692 
693   res = (*stm->play)->RegisterCallback(stm->play, play_callback, stm);
694   if (res != SL_RESULT_SUCCESS) {
695     opensl_stream_destroy(stm);
696     return CUBEB_ERROR;
697   }
698 
699   // Work around wilhelm/AudioTrack badness, bug 1221228
700   (*stm->play)->SetMarkerPosition(stm->play, (SLmillisecond)0);
701 
702   res = (*stm->play)->SetCallbackEventsMask(stm->play, (SLuint32)SL_PLAYEVENT_HEADATMARKER);
703   if (res != SL_RESULT_SUCCESS) {
704     opensl_stream_destroy(stm);
705     return CUBEB_ERROR;
706   }
707 
708   res = (*stm->bufq)->RegisterCallback(stm->bufq, bufferqueue_callback, stm);
709   if (res != SL_RESULT_SUCCESS) {
710     opensl_stream_destroy(stm);
711     return CUBEB_ERROR;
712   }
713 
714   {
715     // Enqueue a silent frame so once the player becomes playing, the frame
716     // will be consumed and kick off the buffer queue callback.
717     // Note the duration of a single frame is less than 1ms. We don't bother
718     // adjusting the playback position.
719     uint8_t *buf = stm->queuebuf[stm->queuebuf_idx++];
720     memset(buf, 0, stm->framesize);
721     res = (*stm->bufq)->Enqueue(stm->bufq, buf, stm->framesize);
722     assert(res == SL_RESULT_SUCCESS);
723   }
724 
725   *stream = stm;
726   return CUBEB_OK;
727 }
728 
729 static void
opensl_stream_destroy(cubeb_stream * stm)730 opensl_stream_destroy(cubeb_stream * stm)
731 {
732   if (stm->playerObj)
733     (*stm->playerObj)->Destroy(stm->playerObj);
734   int i;
735   for (i = 0; i < NBUFS; i++) {
736     free(stm->queuebuf[i]);
737   }
738   pthread_mutex_destroy(&stm->mutex);
739 
740   cubeb_resampler_destroy(stm->resampler);
741 
742   free(stm);
743 }
744 
745 static int
opensl_stream_start(cubeb_stream * stm)746 opensl_stream_start(cubeb_stream * stm)
747 {
748   SLresult res = (*stm->play)->SetPlayState(stm->play, SL_PLAYSTATE_PLAYING);
749   if (res != SL_RESULT_SUCCESS)
750     return CUBEB_ERROR;
751   stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STARTED);
752   return CUBEB_OK;
753 }
754 
755 static int
opensl_stream_stop(cubeb_stream * stm)756 opensl_stream_stop(cubeb_stream * stm)
757 {
758   SLresult res = (*stm->play)->SetPlayState(stm->play, SL_PLAYSTATE_PAUSED);
759   if (res != SL_RESULT_SUCCESS)
760     return CUBEB_ERROR;
761   stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED);
762   return CUBEB_OK;
763 }
764 
765 static int
opensl_stream_get_position(cubeb_stream * stm,uint64_t * position)766 opensl_stream_get_position(cubeb_stream * stm, uint64_t * position)
767 {
768   SLmillisecond msec;
769   uint64_t samplerate;
770   SLresult res;
771   int r;
772   uint32_t mixer_latency;
773   uint32_t compensation_msec = 0;
774 
775   res = (*stm->play)->GetPosition(stm->play, &msec);
776   if (res != SL_RESULT_SUCCESS)
777     return CUBEB_ERROR;
778 
779   struct timespec t;
780   clock_gettime(CLOCK_MONOTONIC, &t);
781   if(stm->lastPosition == msec) {
782     compensation_msec =
783       (t.tv_sec*1000000000LL + t.tv_nsec - stm->lastPositionTimeStamp) / 1000000;
784   } else {
785     stm->lastPositionTimeStamp = t.tv_sec*1000000000LL + t.tv_nsec;
786     stm->lastPosition = msec;
787   }
788 
789   samplerate = stm->inputrate;
790 
791   r = stm->context->get_output_latency(&mixer_latency, stm->stream_type);
792   if (r) {
793     return CUBEB_ERROR;
794   }
795 
796   pthread_mutex_lock(&stm->mutex);
797   int64_t maximum_position = stm->written * (int64_t)stm->inputrate / stm->outputrate;
798   pthread_mutex_unlock(&stm->mutex);
799   assert(maximum_position >= 0);
800 
801   if (msec > mixer_latency) {
802     int64_t unadjusted_position;
803     if (stm->lastCompensativePosition > msec + compensation_msec) {
804       // Over compensation, use lastCompensativePosition.
805       unadjusted_position =
806         samplerate * (stm->lastCompensativePosition - mixer_latency) / 1000;
807     } else {
808       unadjusted_position =
809         samplerate * (msec - mixer_latency + compensation_msec) / 1000;
810       stm->lastCompensativePosition = msec + compensation_msec;
811     }
812     *position = unadjusted_position < maximum_position ?
813       unadjusted_position : maximum_position;
814   } else {
815     *position = 0;
816   }
817   return CUBEB_OK;
818 }
819 
820 int
opensl_stream_get_latency(cubeb_stream * stm,uint32_t * latency)821 opensl_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
822 {
823   int r;
824   uint32_t mixer_latency; // The latency returned by AudioFlinger is in ms.
825 
826   /* audio_stream_type_t is an int, so this is okay. */
827   r = stm->context->get_output_latency(&mixer_latency, stm->stream_type);
828   if (r) {
829     return CUBEB_ERROR;
830   }
831 
832   *latency = stm->latency * stm->inputrate / 1000 + // OpenSL latency
833     mixer_latency * stm->inputrate / 1000; // AudioFlinger latency
834 
835   return CUBEB_OK;
836 }
837 
838 int
opensl_stream_set_volume(cubeb_stream * stm,float volume)839 opensl_stream_set_volume(cubeb_stream * stm, float volume)
840 {
841   SLresult res;
842   SLmillibel max_level, millibels;
843   float unclamped_millibels;
844 
845   res = (*stm->volume)->GetMaxVolumeLevel(stm->volume, &max_level);
846 
847   if (res != SL_RESULT_SUCCESS) {
848     return CUBEB_ERROR;
849   }
850 
851   /* millibels are 100*dB, so the conversion from the volume's linear amplitude
852    * is 100 * 20 * log(volume). However we clamp the resulting value before
853    * passing it to lroundf() in order to prevent it from silently returning an
854    * erroneous value when the unclamped value exceeds the size of a long. */
855   unclamped_millibels = 100.0f * 20.0f * log10f(fmaxf(volume, 0.0f));
856   unclamped_millibels = fmaxf(unclamped_millibels, SL_MILLIBEL_MIN);
857   unclamped_millibels = fminf(unclamped_millibels, max_level);
858 
859   millibels = lroundf(unclamped_millibels);
860 
861   res = (*stm->volume)->SetVolumeLevel(stm->volume, millibels);
862 
863   if (res != SL_RESULT_SUCCESS) {
864     return CUBEB_ERROR;
865   }
866   return CUBEB_OK;
867 }
868 
869 static struct cubeb_ops const opensl_ops = {
870   .init = opensl_init,
871   .get_backend_id = opensl_get_backend_id,
872   .get_max_channel_count = opensl_get_max_channel_count,
873   .get_min_latency = opensl_get_min_latency,
874   .get_preferred_sample_rate = opensl_get_preferred_sample_rate,
875   .enumerate_devices = NULL,
876   .destroy = opensl_destroy,
877   .stream_init = opensl_stream_init,
878   .stream_destroy = opensl_stream_destroy,
879   .stream_start = opensl_stream_start,
880   .stream_stop = opensl_stream_stop,
881   .stream_get_position = opensl_stream_get_position,
882   .stream_get_latency = opensl_stream_get_latency,
883   .stream_set_volume = opensl_stream_set_volume,
884   .stream_set_panning = NULL,
885   .stream_get_current_device = NULL,
886   .stream_device_destroy = NULL,
887   .stream_register_device_changed_callback = NULL,
888   .register_device_collection_changed = NULL
889 };
890