ijksdl_aout_android_opensles.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. /*****************************************************************************
  2. * ijksdl_aout_android_opensles.c
  3. *****************************************************************************
  4. *
  5. * Copyright (c) 2013 Bilibili
  6. * copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
  7. *
  8. * This file is part of ijkPlayer.
  9. *
  10. * ijkPlayer is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Lesser General Public
  12. * License as published by the Free Software Foundation; either
  13. * version 2.1 of the License, or (at your option) any later version.
  14. *
  15. * ijkPlayer is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with ijkPlayer; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. */
  24. #include <stdbool.h>
  25. #include <assert.h>
  26. #include <math.h>
  27. #include <inttypes.h>
  28. #include <jni.h>
  29. #include <SLES/OpenSLES.h>
  30. #include <SLES/OpenSLES_Android.h>
  31. #include "../ijksdl_inc_internal.h"
  32. #include "../ijksdl_thread.h"
  33. #include "../ijksdl_aout_internal.h"
  34. #include "ijksdl_android_jni.h"
  35. #include "android_audiotrack.h"
  36. #ifdef SDLTRACE
  37. #undef SDLTRACE
  38. #define SDLTRACE(...)
  39. //#define SDLTRACE ALOGW
  40. #endif
  41. #define OPENSLES_BUFFERS 255 /* maximum number of buffers */
  42. #define OPENSLES_BUFLEN 10 /* ms */
  43. static SDL_Class g_opensles_class = {
  44. .name = "OpenSLES",
  45. };
  46. typedef struct SDL_Aout_Opaque {
  47. SDL_cond *wakeup_cond;
  48. SDL_mutex *wakeup_mutex;
  49. SDL_Thread *audio_tid;
  50. SDL_Thread _audio_tid;
  51. SDL_AudioSpec spec;
  52. SLDataFormat_PCM format_pcm;
  53. int bytes_per_frame;
  54. int milli_per_buffer;
  55. int frames_per_buffer;
  56. int bytes_per_buffer;
  57. SLObjectItf slObject;
  58. SLEngineItf slEngine;
  59. SLObjectItf slOutputMixObject;
  60. SLObjectItf slPlayerObject;
  61. SLAndroidSimpleBufferQueueItf slBufferQueueItf;
  62. SLVolumeItf slVolumeItf;
  63. SLPlayItf slPlayItf;
  64. volatile bool need_set_volume;
  65. volatile float left_volume;
  66. volatile float right_volume;
  67. volatile bool abort_request;
  68. volatile bool pause_on;
  69. volatile bool need_flush;
  70. volatile bool is_running;
  71. uint8_t *buffer;
  72. size_t buffer_capacity;
  73. } SDL_Aout_Opaque;
  74. #define CHECK_OPENSL_ERROR(ret__, ...) \
  75. do { \
  76. if ((ret__) != SL_RESULT_SUCCESS) \
  77. { \
  78. ALOGE(__VA_ARGS__); \
  79. goto fail; \
  80. } \
  81. } while (0)
  82. #define CHECK_COND_ERROR(cond__, ...) \
  83. do { \
  84. if (!(cond__)) \
  85. { \
  86. ALOGE(__VA_ARGS__); \
  87. goto fail; \
  88. } \
  89. } while (0)
  90. static inline SLmillibel android_amplification_to_sles(float volumeLevel) {
  91. // FIXME use the FX Framework conversions
  92. if (volumeLevel < 0.00000001)
  93. return SL_MILLIBEL_MIN;
  94. SLmillibel mb = lroundf(2000.f * log10f(volumeLevel));
  95. if (mb < SL_MILLIBEL_MIN)
  96. mb = SL_MILLIBEL_MIN;
  97. else if (mb > 0)
  98. mb = 0; /* maximum supported level could be higher: GetMaxVolumeLevel */
  99. return mb;
  100. }
  101. static int aout_thread_n(SDL_Aout *aout)
  102. {
  103. SDL_Aout_Opaque *opaque = aout->opaque;
  104. SLPlayItf slPlayItf = opaque->slPlayItf;
  105. SLAndroidSimpleBufferQueueItf slBufferQueueItf = opaque->slBufferQueueItf;
  106. SLVolumeItf slVolumeItf = opaque->slVolumeItf;
  107. SDL_AudioCallback audio_cblk = opaque->spec.callback;
  108. void *userdata = opaque->spec.userdata;
  109. uint8_t *next_buffer = NULL;
  110. int next_buffer_index = 0;
  111. size_t bytes_per_buffer = opaque->bytes_per_buffer;
  112. SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
  113. if (!opaque->abort_request && !opaque->pause_on)
  114. (*slPlayItf)->SetPlayState(slPlayItf, SL_PLAYSTATE_PLAYING);
  115. while (!opaque->abort_request) {
  116. SLAndroidSimpleBufferQueueState slState = {0};
  117. SLresult slRet = (*slBufferQueueItf)->GetState(slBufferQueueItf, &slState);
  118. if (slRet != SL_RESULT_SUCCESS) {
  119. ALOGE("%s: slBufferQueueItf->GetState() failed\n", __func__);
  120. SDL_UnlockMutex(opaque->wakeup_mutex);
  121. }
  122. SDL_LockMutex(opaque->wakeup_mutex);
  123. if (!opaque->abort_request && (opaque->pause_on || slState.count >= OPENSLES_BUFFERS)) {
  124. while (!opaque->abort_request && (opaque->pause_on || slState.count >= OPENSLES_BUFFERS)) {
  125. if (!opaque->pause_on) {
  126. (*slPlayItf)->SetPlayState(slPlayItf, SL_PLAYSTATE_PLAYING);
  127. }
  128. SDL_CondWaitTimeout(opaque->wakeup_cond, opaque->wakeup_mutex, 1000);
  129. SLresult slRet = (*slBufferQueueItf)->GetState(slBufferQueueItf, &slState);
  130. if (slRet != SL_RESULT_SUCCESS) {
  131. ALOGE("%s: slBufferQueueItf->GetState() failed\n", __func__);
  132. SDL_UnlockMutex(opaque->wakeup_mutex);
  133. }
  134. if (opaque->pause_on)
  135. (*slPlayItf)->SetPlayState(slPlayItf, SL_PLAYSTATE_PAUSED);
  136. }
  137. if (!opaque->abort_request && !opaque->pause_on) {
  138. (*slPlayItf)->SetPlayState(slPlayItf, SL_PLAYSTATE_PLAYING);
  139. }
  140. }
  141. if (opaque->need_flush) {
  142. opaque->need_flush = 0;
  143. (*slBufferQueueItf)->Clear(slBufferQueueItf);
  144. }
  145. #if 0
  146. if (opaque->need_set_volume) {
  147. opaque->need_set_volume = 0;
  148. // FIXME: set volume here
  149. }
  150. #endif
  151. if (opaque->need_set_volume) {
  152. opaque->need_set_volume = 0;
  153. SLmillibel level = android_amplification_to_sles((opaque->left_volume + opaque->right_volume) / 2);
  154. ALOGI("slVolumeItf->SetVolumeLevel((%f, %f) -> %d)\n", opaque->left_volume, opaque->right_volume, (int)level);
  155. slRet = (*slVolumeItf)->SetVolumeLevel(slVolumeItf, level);
  156. if (slRet != SL_RESULT_SUCCESS) {
  157. ALOGE("slVolumeItf->SetVolumeLevel failed %d\n", (int)slRet);
  158. // just ignore error
  159. }
  160. }
  161. SDL_UnlockMutex(opaque->wakeup_mutex);
  162. next_buffer = opaque->buffer + next_buffer_index * bytes_per_buffer;
  163. next_buffer_index = (next_buffer_index + 1) % OPENSLES_BUFFERS;
  164. audio_cblk(userdata, next_buffer, bytes_per_buffer);
  165. if (opaque->need_flush) {
  166. (*slBufferQueueItf)->Clear(slBufferQueueItf);
  167. opaque->need_flush = false;
  168. }
  169. if (opaque->need_flush) {
  170. ALOGE("flush");
  171. opaque->need_flush = 0;
  172. (*slBufferQueueItf)->Clear(slBufferQueueItf);
  173. } else {
  174. slRet = (*slBufferQueueItf)->Enqueue(slBufferQueueItf, next_buffer, bytes_per_buffer);
  175. if (slRet == SL_RESULT_SUCCESS) {
  176. // do nothing
  177. } else if (slRet == SL_RESULT_BUFFER_INSUFFICIENT) {
  178. // don't retry, just pass through
  179. ALOGE("SL_RESULT_BUFFER_INSUFFICIENT\n");
  180. } else {
  181. ALOGE("slBufferQueueItf->Enqueue() = %d\n", (int)slRet);
  182. break;
  183. }
  184. }
  185. // TODO: 1 if callback return -1 or 0
  186. }
  187. return 0;
  188. }
  189. static int aout_thread(void *arg)
  190. {
  191. return aout_thread_n(arg);
  192. }
  193. static void aout_opensles_callback(SLAndroidSimpleBufferQueueItf caller, void *pContext)
  194. {
  195. SDLTRACE("%s\n", __func__);
  196. SDL_Aout *aout = pContext;
  197. SDL_Aout_Opaque *opaque = aout->opaque;
  198. if (opaque) {
  199. SDL_LockMutex(opaque->wakeup_mutex);
  200. opaque->is_running = true;
  201. SDL_CondSignal(opaque->wakeup_cond);
  202. SDL_UnlockMutex(opaque->wakeup_mutex);
  203. }
  204. }
  205. static void aout_close_audio(SDL_Aout *aout)
  206. {
  207. SDLTRACE("aout_close_audio()\n");
  208. SDL_Aout_Opaque *opaque = aout->opaque;
  209. if (!opaque)
  210. return;
  211. SDL_LockMutex(opaque->wakeup_mutex);
  212. opaque->abort_request = true;
  213. SDL_CondSignal(opaque->wakeup_cond);
  214. SDL_UnlockMutex(opaque->wakeup_mutex);
  215. SDL_WaitThread(opaque->audio_tid, NULL);
  216. opaque->audio_tid = NULL;
  217. if (opaque->slPlayItf)
  218. (*opaque->slPlayItf)->SetPlayState(opaque->slPlayItf, SL_PLAYSTATE_STOPPED);
  219. if (opaque->slBufferQueueItf)
  220. (*opaque->slBufferQueueItf)->Clear(opaque->slBufferQueueItf);
  221. if (opaque->slBufferQueueItf)
  222. opaque->slBufferQueueItf = NULL;
  223. if (opaque->slVolumeItf)
  224. opaque->slVolumeItf = NULL;
  225. if (opaque->slPlayItf)
  226. opaque->slPlayItf = NULL;
  227. if (opaque->slPlayerObject) {
  228. (*opaque->slPlayerObject)->Destroy(opaque->slPlayerObject);
  229. opaque->slPlayerObject = NULL;
  230. }
  231. freep((void **)&opaque->buffer);
  232. }
  233. static void aout_free_l(SDL_Aout *aout)
  234. {
  235. SDLTRACE("%s\n", __func__);
  236. if (!aout)
  237. return;
  238. aout_close_audio(aout);
  239. SDL_Aout_Opaque *opaque = aout->opaque;
  240. if (opaque->slOutputMixObject) {
  241. (*opaque->slOutputMixObject)->Destroy(opaque->slOutputMixObject);
  242. opaque->slOutputMixObject = NULL;
  243. }
  244. opaque->slEngine = NULL;
  245. if (opaque->slObject) {
  246. (*opaque->slObject)->Destroy(opaque->slObject);
  247. opaque->slObject = NULL;
  248. }
  249. SDL_DestroyCondP(&opaque->wakeup_cond);
  250. SDL_DestroyMutexP(&opaque->wakeup_mutex);
  251. SDL_Aout_FreeInternal(aout);
  252. }
  253. static int aout_open_audio(SDL_Aout *aout, const SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
  254. {
  255. SDLTRACE("%s\n", __func__);
  256. assert(desired);
  257. SDLTRACE("aout_open_audio()\n");
  258. SDL_Aout_Opaque *opaque = aout->opaque;
  259. SLEngineItf slEngine = opaque->slEngine;
  260. SLDataFormat_PCM *format_pcm = &opaque->format_pcm;
  261. int ret = 0;
  262. opaque->spec = *desired;
  263. // config audio src
  264. SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {
  265. SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
  266. OPENSLES_BUFFERS
  267. };
  268. int native_sample_rate = audiotrack_get_native_output_sample_rate(NULL);
  269. ALOGI("OpenSL-ES: native sample rate %d Hz\n", native_sample_rate);
  270. CHECK_COND_ERROR((desired->format == AUDIO_S16SYS), "%s: not AUDIO_S16SYS", __func__);
  271. CHECK_COND_ERROR((desired->channels == 2 || desired->channels == 1), "%s: not 1,2 channel", __func__);
  272. CHECK_COND_ERROR((desired->freq >= 8000 && desired->freq <= 48000), "%s: unsupport freq %d Hz", __func__, desired->freq);
  273. if (SDL_Android_GetApiLevel() < IJK_API_21_LOLLIPOP &&
  274. native_sample_rate > 0 &&
  275. desired->freq < native_sample_rate) {
  276. // Don't try to play back a sample rate higher than the native one,
  277. // since OpenSL ES will try to use the fast path, which AudioFlinger
  278. // will reject (fast path can't do resampling), and will end up with
  279. // too small buffers for the resampling. See http://b.android.com/59453
  280. // for details. This bug is still present in 4.4. If it is fixed later
  281. // this workaround could be made conditional.
  282. //
  283. // by VLC/android_opensles.c
  284. ALOGW("OpenSL-ES: force resample %lu to native sample rate %d\n",
  285. (unsigned long) format_pcm->samplesPerSec / 1000,
  286. (int) native_sample_rate);
  287. format_pcm->samplesPerSec = native_sample_rate * 1000;
  288. }
  289. format_pcm->formatType = SL_DATAFORMAT_PCM;
  290. format_pcm->numChannels = desired->channels;
  291. format_pcm->samplesPerSec = desired->freq * 1000; // milli Hz
  292. // format_pcm->numChannels = 2;
  293. // format_pcm->samplesPerSec = SL_SAMPLINGRATE_44_1;
  294. format_pcm->bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
  295. format_pcm->containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;
  296. switch (desired->channels) {
  297. case 2:
  298. format_pcm->channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
  299. break;
  300. case 1:
  301. format_pcm->channelMask = SL_SPEAKER_FRONT_CENTER;
  302. break;
  303. default:
  304. ALOGE("%s, invalid channel %d", __func__, desired->channels);
  305. goto fail;
  306. }
  307. format_pcm->endianness = SL_BYTEORDER_LITTLEENDIAN;
  308. SLDataSource audio_source = {&loc_bufq, format_pcm};
  309. // config audio sink
  310. SLDataLocator_OutputMix loc_outmix = {
  311. SL_DATALOCATOR_OUTPUTMIX,
  312. opaque->slOutputMixObject
  313. };
  314. SLDataSink audio_sink = {&loc_outmix, NULL};
  315. SLObjectItf slPlayerObject = NULL;
  316. const SLInterfaceID ids2[] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_VOLUME, SL_IID_PLAY };
  317. static const SLboolean req2[] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
  318. ret = (*slEngine)->CreateAudioPlayer(slEngine, &slPlayerObject, &audio_source,
  319. &audio_sink, sizeof(ids2) / sizeof(*ids2),
  320. ids2, req2);
  321. CHECK_OPENSL_ERROR(ret, "%s: slEngine->CreateAudioPlayer() failed", __func__);
  322. opaque->slPlayerObject = slPlayerObject;
  323. ret = (*slPlayerObject)->Realize(slPlayerObject, SL_BOOLEAN_FALSE);
  324. CHECK_OPENSL_ERROR(ret, "%s: slPlayerObject->Realize() failed", __func__);
  325. ret = (*slPlayerObject)->GetInterface(slPlayerObject, SL_IID_PLAY, &opaque->slPlayItf);
  326. CHECK_OPENSL_ERROR(ret, "%s: slPlayerObject->GetInterface(SL_IID_PLAY) failed", __func__);
  327. ret = (*slPlayerObject)->GetInterface(slPlayerObject, SL_IID_VOLUME, &opaque->slVolumeItf);
  328. CHECK_OPENSL_ERROR(ret, "%s: slPlayerObject->GetInterface(SL_IID_VOLUME) failed", __func__);
  329. ret = (*slPlayerObject)->GetInterface(slPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &opaque->slBufferQueueItf);
  330. CHECK_OPENSL_ERROR(ret, "%s: slPlayerObject->GetInterface(SL_IID_ANDROIDSIMPLEBUFFERQUEUE) failed", __func__);
  331. ret = (*opaque->slBufferQueueItf)->RegisterCallback(opaque->slBufferQueueItf, aout_opensles_callback, (void*)aout);
  332. CHECK_OPENSL_ERROR(ret, "%s: slBufferQueueItf->RegisterCallback() failed", __func__);
  333. // set the player's state to playing
  334. // ret = (*opaque->slPlayItf)->SetPlayState(opaque->slPlayItf, SL_PLAYSTATE_PLAYING);
  335. // CHECK_OPENSL_ERROR(ret, "%s: slBufferQueueItf->slPlayItf() failed", __func__);
  336. opaque->bytes_per_frame = format_pcm->numChannels * format_pcm->bitsPerSample / 8;
  337. opaque->milli_per_buffer = OPENSLES_BUFLEN;
  338. opaque->frames_per_buffer = opaque->milli_per_buffer * format_pcm->samplesPerSec / 1000000; // samplesPerSec is in milli
  339. opaque->bytes_per_buffer = opaque->bytes_per_frame * opaque->frames_per_buffer;
  340. opaque->buffer_capacity = OPENSLES_BUFFERS * opaque->bytes_per_buffer;
  341. ALOGI("OpenSL-ES: bytes_per_frame = %d bytes\n", (int)opaque->bytes_per_frame);
  342. ALOGI("OpenSL-ES: milli_per_buffer = %d ms\n", (int)opaque->milli_per_buffer);
  343. ALOGI("OpenSL-ES: frame_per_buffer = %d frames\n", (int)opaque->frames_per_buffer);
  344. ALOGI("OpenSL-ES: bytes_per_buffer = %d bytes\n", (int)opaque->bytes_per_buffer);
  345. ALOGI("OpenSL-ES: buffer_capacity = %d bytes\n", (int)opaque->buffer_capacity);
  346. opaque->buffer = malloc(opaque->buffer_capacity);
  347. CHECK_COND_ERROR(opaque->buffer, "%s: failed to alloc buffer %d\n", __func__, (int)opaque->buffer_capacity);
  348. // (*opaque->slPlayItf)->SetPositionUpdatePeriod(opaque->slPlayItf, 1000);
  349. // enqueue empty buffer to start play
  350. memset(opaque->buffer, 0, opaque->buffer_capacity);
  351. for(int i = 0; i < OPENSLES_BUFFERS; ++i) {
  352. ret = (*opaque->slBufferQueueItf)->Enqueue(opaque->slBufferQueueItf, opaque->buffer + i * opaque->bytes_per_buffer, opaque->bytes_per_buffer);
  353. CHECK_OPENSL_ERROR(ret, "%s: slBufferQueueItf->Enqueue(000...) failed", __func__);
  354. }
  355. opaque->pause_on = 1;
  356. opaque->abort_request = 0;
  357. opaque->audio_tid = SDL_CreateThreadEx(&opaque->_audio_tid, aout_thread, aout, "ff_aout_opensles");
  358. CHECK_COND_ERROR(opaque->audio_tid, "%s: failed to SDL_CreateThreadEx", __func__);
  359. if (obtained) {
  360. *obtained = *desired;
  361. obtained->size = opaque->buffer_capacity;
  362. obtained->freq = format_pcm->samplesPerSec / 1000;
  363. }
  364. return opaque->buffer_capacity;
  365. fail:
  366. aout_close_audio(aout);
  367. return -1;
  368. }
  369. static void aout_pause_audio(SDL_Aout *aout, int pause_on)
  370. {
  371. SDL_Aout_Opaque *opaque = aout->opaque;
  372. SDL_LockMutex(opaque->wakeup_mutex);
  373. SDLTRACE("aout_pause_audio(%d)", pause_on);
  374. opaque->pause_on = pause_on;
  375. if (!pause_on)
  376. SDL_CondSignal(opaque->wakeup_cond);
  377. SDL_UnlockMutex(opaque->wakeup_mutex);
  378. }
  379. static void aout_flush_audio(SDL_Aout *aout)
  380. {
  381. SDL_Aout_Opaque *opaque = aout->opaque;
  382. SDL_LockMutex(opaque->wakeup_mutex);
  383. SDLTRACE("aout_flush_audio()");
  384. opaque->need_flush = 1;
  385. SDL_CondSignal(opaque->wakeup_cond);
  386. SDL_UnlockMutex(opaque->wakeup_mutex);
  387. }
  388. static void aout_set_volume(SDL_Aout *aout, float left_volume, float right_volume)
  389. {
  390. SDL_Aout_Opaque *opaque = aout->opaque;
  391. SDL_LockMutex(opaque->wakeup_mutex);
  392. ALOGI("aout_set_volume(%f, %f)", left_volume, right_volume);
  393. opaque->left_volume = left_volume;
  394. opaque->right_volume = right_volume;
  395. opaque->need_set_volume = 1;
  396. SDL_CondSignal(opaque->wakeup_cond);
  397. SDL_UnlockMutex(opaque->wakeup_mutex);
  398. }
  399. static double aout_get_latency_seconds(SDL_Aout *aout)
  400. {
  401. SDL_Aout_Opaque *opaque = aout->opaque;
  402. SLAndroidSimpleBufferQueueState state = {0};
  403. SLresult slRet = (*opaque->slBufferQueueItf)->GetState(opaque->slBufferQueueItf, &state);
  404. if (slRet != SL_RESULT_SUCCESS) {
  405. ALOGE("%s failed\n", __func__);
  406. return ((double)opaque->milli_per_buffer) * OPENSLES_BUFFERS / 1000;
  407. }
  408. // assume there is always a buffer in coping
  409. double latency = ((double)opaque->milli_per_buffer) * state.count / 1000;
  410. return latency;
  411. }
  412. SDL_Aout *SDL_AoutAndroid_CreateForOpenSLES()
  413. {
  414. SDLTRACE("%s\n", __func__);
  415. SDL_Aout *aout = SDL_Aout_CreateInternal(sizeof(SDL_Aout_Opaque));
  416. if (!aout)
  417. return NULL;
  418. SDL_Aout_Opaque *opaque = aout->opaque;
  419. opaque->wakeup_cond = SDL_CreateCond();
  420. opaque->wakeup_mutex = SDL_CreateMutex();
  421. int ret = 0;
  422. SLObjectItf slObject = NULL;
  423. ret = slCreateEngine(&slObject, 0, NULL, 0, NULL, NULL);
  424. CHECK_OPENSL_ERROR(ret, "%s: slCreateEngine() failed", __func__);
  425. opaque->slObject = slObject;
  426. ret = (*slObject)->Realize(slObject, SL_BOOLEAN_FALSE);
  427. CHECK_OPENSL_ERROR(ret, "%s: slObject->Realize() failed", __func__);
  428. SLEngineItf slEngine = NULL;
  429. ret = (*slObject)->GetInterface(slObject, SL_IID_ENGINE, &slEngine);
  430. CHECK_OPENSL_ERROR(ret, "%s: slObject->GetInterface() failed", __func__);
  431. opaque->slEngine = slEngine;
  432. SLObjectItf slOutputMixObject = NULL;
  433. const SLInterfaceID ids1[] = {SL_IID_VOLUME};
  434. const SLboolean req1[] = {SL_BOOLEAN_FALSE};
  435. ret = (*slEngine)->CreateOutputMix(slEngine, &slOutputMixObject, 1, ids1, req1);
  436. CHECK_OPENSL_ERROR(ret, "%s: slEngine->CreateOutputMix() failed", __func__);
  437. opaque->slOutputMixObject = slOutputMixObject;
  438. ret = (*slOutputMixObject)->Realize(slOutputMixObject, SL_BOOLEAN_FALSE);
  439. CHECK_OPENSL_ERROR(ret, "%s: slOutputMixObject->Realize() failed", __func__);
  440. aout->free_l = aout_free_l;
  441. aout->opaque_class = &g_opensles_class;
  442. aout->open_audio = aout_open_audio;
  443. aout->pause_audio = aout_pause_audio;
  444. aout->flush_audio = aout_flush_audio;
  445. aout->close_audio = aout_close_audio;
  446. aout->set_volume = aout_set_volume;
  447. aout->func_get_latency_seconds = aout_get_latency_seconds;
  448. return aout;
  449. fail:
  450. aout_free_l(aout);
  451. return NULL;
  452. }
  453. bool SDL_AoutAndroid_IsObjectOfOpenSLES(SDL_Aout *aout)
  454. {
  455. if (aout)
  456. return false;
  457. return aout->opaque_class == &g_opensles_class;
  458. }