🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

941 lines
31 KiB

  1. /*
  2. * Copyright (C) 2011 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /* This is an OpenAL backend for Android using the native audio APIs based on
  17. * OpenSL ES 1.0.1. It is based on source code for the native-audio sample app
  18. * bundled with NDK.
  19. */
  20. #include "config.h"
  21. #include "backends/opensl.h"
  22. #include <stdlib.h>
  23. #include <jni.h>
  24. #include <new>
  25. #include <thread>
  26. #include <functional>
  27. #include "alMain.h"
  28. #include "alu.h"
  29. #include "ringbuffer.h"
  30. #include "threads.h"
  31. #include "compat.h"
  32. #include <SLES/OpenSLES.h>
  33. #include <SLES/OpenSLES_Android.h>
  34. #include <SLES/OpenSLES_AndroidConfiguration.h>
  35. namespace {
  36. /* Helper macros */
  37. #define EXTRACT_VCALL_ARGS(...) __VA_ARGS__))
  38. #define VCALL(obj, func) ((*(obj))->func((obj), EXTRACT_VCALL_ARGS
  39. #define VCALL0(obj, func) ((*(obj))->func((obj) EXTRACT_VCALL_ARGS
  40. constexpr ALCchar opensl_device[] = "OpenSL";
  41. SLuint32 GetChannelMask(DevFmtChannels chans)
  42. {
  43. switch(chans)
  44. {
  45. case DevFmtMono: return SL_SPEAKER_FRONT_CENTER;
  46. case DevFmtStereo: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT;
  47. case DevFmtQuad: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
  48. SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT;
  49. case DevFmtX51: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
  50. SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
  51. SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;
  52. case DevFmtX51Rear: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
  53. SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
  54. SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT;
  55. case DevFmtX61: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
  56. SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
  57. SL_SPEAKER_BACK_CENTER|
  58. SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;
  59. case DevFmtX71: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
  60. SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
  61. SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT|
  62. SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;
  63. case DevFmtAmbi3D:
  64. break;
  65. }
  66. return 0;
  67. }
  68. #ifdef SL_DATAFORMAT_PCM_EX
  69. SLuint32 GetTypeRepresentation(DevFmtType type)
  70. {
  71. switch(type)
  72. {
  73. case DevFmtUByte:
  74. case DevFmtUShort:
  75. case DevFmtUInt:
  76. return SL_PCM_REPRESENTATION_UNSIGNED_INT;
  77. case DevFmtByte:
  78. case DevFmtShort:
  79. case DevFmtInt:
  80. return SL_PCM_REPRESENTATION_SIGNED_INT;
  81. case DevFmtFloat:
  82. return SL_PCM_REPRESENTATION_FLOAT;
  83. }
  84. return 0;
  85. }
  86. #endif
  87. const char *res_str(SLresult result)
  88. {
  89. switch(result)
  90. {
  91. case SL_RESULT_SUCCESS: return "Success";
  92. case SL_RESULT_PRECONDITIONS_VIOLATED: return "Preconditions violated";
  93. case SL_RESULT_PARAMETER_INVALID: return "Parameter invalid";
  94. case SL_RESULT_MEMORY_FAILURE: return "Memory failure";
  95. case SL_RESULT_RESOURCE_ERROR: return "Resource error";
  96. case SL_RESULT_RESOURCE_LOST: return "Resource lost";
  97. case SL_RESULT_IO_ERROR: return "I/O error";
  98. case SL_RESULT_BUFFER_INSUFFICIENT: return "Buffer insufficient";
  99. case SL_RESULT_CONTENT_CORRUPTED: return "Content corrupted";
  100. case SL_RESULT_CONTENT_UNSUPPORTED: return "Content unsupported";
  101. case SL_RESULT_CONTENT_NOT_FOUND: return "Content not found";
  102. case SL_RESULT_PERMISSION_DENIED: return "Permission denied";
  103. case SL_RESULT_FEATURE_UNSUPPORTED: return "Feature unsupported";
  104. case SL_RESULT_INTERNAL_ERROR: return "Internal error";
  105. case SL_RESULT_UNKNOWN_ERROR: return "Unknown error";
  106. case SL_RESULT_OPERATION_ABORTED: return "Operation aborted";
  107. case SL_RESULT_CONTROL_LOST: return "Control lost";
  108. #ifdef SL_RESULT_READONLY
  109. case SL_RESULT_READONLY: return "ReadOnly";
  110. #endif
  111. #ifdef SL_RESULT_ENGINEOPTION_UNSUPPORTED
  112. case SL_RESULT_ENGINEOPTION_UNSUPPORTED: return "Engine option unsupported";
  113. #endif
  114. #ifdef SL_RESULT_SOURCE_SINK_INCOMPATIBLE
  115. case SL_RESULT_SOURCE_SINK_INCOMPATIBLE: return "Source/Sink incompatible";
  116. #endif
  117. }
  118. return "Unknown error code";
  119. }
  120. #define PRINTERR(x, s) do { \
  121. if(UNLIKELY((x) != SL_RESULT_SUCCESS)) \
  122. ERR("%s: %s\n", (s), res_str((x))); \
  123. } while(0)
  124. struct OpenSLPlayback final : public BackendBase {
  125. OpenSLPlayback(ALCdevice *device) noexcept : BackendBase{device} { }
  126. ~OpenSLPlayback() override;
  127. static void processC(SLAndroidSimpleBufferQueueItf bq, void *context);
  128. void process(SLAndroidSimpleBufferQueueItf bq);
  129. int mixerProc();
  130. ALCenum open(const ALCchar *name) override;
  131. ALCboolean reset() override;
  132. ALCboolean start() override;
  133. void stop() override;
  134. ClockLatency getClockLatency() override;
  135. /* engine interfaces */
  136. SLObjectItf mEngineObj{nullptr};
  137. SLEngineItf mEngine{nullptr};
  138. /* output mix interfaces */
  139. SLObjectItf mOutputMix{nullptr};
  140. /* buffer queue player interfaces */
  141. SLObjectItf mBufferQueueObj{nullptr};
  142. RingBufferPtr mRing{nullptr};
  143. al::semaphore mSem;
  144. ALsizei mFrameSize{0};
  145. std::atomic<bool> mKillNow{true};
  146. std::thread mThread;
  147. static constexpr inline const char *CurrentPrefix() noexcept { return "OpenSLPlayback::"; }
  148. DEF_NEWDEL(OpenSLPlayback)
  149. };
  150. OpenSLPlayback::~OpenSLPlayback()
  151. {
  152. if(mBufferQueueObj)
  153. VCALL0(mBufferQueueObj,Destroy)();
  154. mBufferQueueObj = nullptr;
  155. if(mOutputMix)
  156. VCALL0(mOutputMix,Destroy)();
  157. mOutputMix = nullptr;
  158. if(mEngineObj)
  159. VCALL0(mEngineObj,Destroy)();
  160. mEngineObj = nullptr;
  161. mEngine = nullptr;
  162. }
  163. /* this callback handler is called every time a buffer finishes playing */
  164. void OpenSLPlayback::processC(SLAndroidSimpleBufferQueueItf bq, void *context)
  165. { static_cast<OpenSLPlayback*>(context)->process(bq); }
  166. void OpenSLPlayback::process(SLAndroidSimpleBufferQueueItf UNUSED(bq))
  167. {
  168. /* A note on the ringbuffer usage: The buffer queue seems to hold on to the
  169. * pointer passed to the Enqueue method, rather than copying the audio.
  170. * Consequently, the ringbuffer contains the audio that is currently queued
  171. * and waiting to play. This process() callback is called when a buffer is
  172. * finished, so we simply move the read pointer up to indicate the space is
  173. * available for writing again, and wake up the mixer thread to mix and
  174. * queue more audio.
  175. */
  176. mRing->readAdvance(1);
  177. mSem.post();
  178. }
  179. int OpenSLPlayback::mixerProc()
  180. {
  181. SetRTPriority();
  182. althrd_setname(MIXER_THREAD_NAME);
  183. SLPlayItf player;
  184. SLAndroidSimpleBufferQueueItf bufferQueue;
  185. SLresult result{VCALL(mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
  186. &bufferQueue)};
  187. PRINTERR(result, "bufferQueue->GetInterface SL_IID_ANDROIDSIMPLEBUFFERQUEUE");
  188. if(SL_RESULT_SUCCESS == result)
  189. {
  190. result = VCALL(mBufferQueueObj,GetInterface)(SL_IID_PLAY, &player);
  191. PRINTERR(result, "bufferQueue->GetInterface SL_IID_PLAY");
  192. }
  193. lock();
  194. if(SL_RESULT_SUCCESS != result)
  195. aluHandleDisconnect(mDevice, "Failed to get playback buffer: 0x%08x", result);
  196. while(SL_RESULT_SUCCESS == result && !mKillNow.load(std::memory_order_acquire) &&
  197. mDevice->Connected.load(std::memory_order_acquire))
  198. {
  199. if(mRing->writeSpace() == 0)
  200. {
  201. SLuint32 state{0};
  202. result = VCALL(player,GetPlayState)(&state);
  203. PRINTERR(result, "player->GetPlayState");
  204. if(SL_RESULT_SUCCESS == result && state != SL_PLAYSTATE_PLAYING)
  205. {
  206. result = VCALL(player,SetPlayState)(SL_PLAYSTATE_PLAYING);
  207. PRINTERR(result, "player->SetPlayState");
  208. }
  209. if(SL_RESULT_SUCCESS != result)
  210. {
  211. aluHandleDisconnect(mDevice, "Failed to start platback: 0x%08x", result);
  212. break;
  213. }
  214. if(mRing->writeSpace() == 0)
  215. {
  216. unlock();
  217. mSem.wait();
  218. lock();
  219. continue;
  220. }
  221. }
  222. auto data = mRing->getWriteVector();
  223. aluMixData(mDevice, data.first.buf, data.first.len*mDevice->UpdateSize);
  224. if(data.second.len > 0)
  225. aluMixData(mDevice, data.second.buf, data.second.len*mDevice->UpdateSize);
  226. size_t todo{data.first.len + data.second.len};
  227. mRing->writeAdvance(todo);
  228. for(size_t i{0};i < todo;i++)
  229. {
  230. if(!data.first.len)
  231. {
  232. data.first = data.second;
  233. data.second.buf = nullptr;
  234. data.second.len = 0;
  235. }
  236. result = VCALL(bufferQueue,Enqueue)(data.first.buf, mDevice->UpdateSize*mFrameSize);
  237. PRINTERR(result, "bufferQueue->Enqueue");
  238. if(SL_RESULT_SUCCESS != result)
  239. {
  240. aluHandleDisconnect(mDevice, "Failed to queue audio: 0x%08x", result);
  241. break;
  242. }
  243. data.first.len--;
  244. data.first.buf += mDevice->UpdateSize*mFrameSize;
  245. }
  246. }
  247. unlock();
  248. return 0;
  249. }
  250. ALCenum OpenSLPlayback::open(const ALCchar *name)
  251. {
  252. if(!name)
  253. name = opensl_device;
  254. else if(strcmp(name, opensl_device) != 0)
  255. return ALC_INVALID_VALUE;
  256. // create engine
  257. SLresult result{slCreateEngine(&mEngineObj, 0, nullptr, 0, nullptr, nullptr)};
  258. PRINTERR(result, "slCreateEngine");
  259. if(SL_RESULT_SUCCESS == result)
  260. {
  261. result = VCALL(mEngineObj,Realize)(SL_BOOLEAN_FALSE);
  262. PRINTERR(result, "engine->Realize");
  263. }
  264. if(SL_RESULT_SUCCESS == result)
  265. {
  266. result = VCALL(mEngineObj,GetInterface)(SL_IID_ENGINE, &mEngine);
  267. PRINTERR(result, "engine->GetInterface");
  268. }
  269. if(SL_RESULT_SUCCESS == result)
  270. {
  271. result = VCALL(mEngine,CreateOutputMix)(&mOutputMix, 0, nullptr, nullptr);
  272. PRINTERR(result, "engine->CreateOutputMix");
  273. }
  274. if(SL_RESULT_SUCCESS == result)
  275. {
  276. result = VCALL(mOutputMix,Realize)(SL_BOOLEAN_FALSE);
  277. PRINTERR(result, "outputMix->Realize");
  278. }
  279. if(SL_RESULT_SUCCESS != result)
  280. {
  281. if(mOutputMix)
  282. VCALL0(mOutputMix,Destroy)();
  283. mOutputMix = nullptr;
  284. if(mEngineObj)
  285. VCALL0(mEngineObj,Destroy)();
  286. mEngineObj = nullptr;
  287. mEngine = nullptr;
  288. return ALC_INVALID_VALUE;
  289. }
  290. mDevice->DeviceName = name;
  291. return ALC_NO_ERROR;
  292. }
  293. ALCboolean OpenSLPlayback::reset()
  294. {
  295. SLDataLocator_AndroidSimpleBufferQueue loc_bufq;
  296. SLDataLocator_OutputMix loc_outmix;
  297. SLDataSource audioSrc;
  298. SLDataSink audioSnk;
  299. SLInterfaceID ids[2];
  300. SLboolean reqs[2];
  301. SLresult result;
  302. if(mBufferQueueObj)
  303. VCALL0(mBufferQueueObj,Destroy)();
  304. mBufferQueueObj = nullptr;
  305. mRing = nullptr;
  306. #if 0
  307. if(!(mDevice->Flags&DEVICE_FREQUENCY_REQUEST))
  308. {
  309. /* FIXME: Disabled until I figure out how to get the Context needed for
  310. * the getSystemService call.
  311. */
  312. JNIEnv *env = Android_GetJNIEnv();
  313. jobject jctx = Android_GetContext();
  314. /* Get necessary stuff for using java.lang.Integer,
  315. * android.content.Context, and android.media.AudioManager.
  316. */
  317. jclass int_cls = JCALL(env,FindClass)("java/lang/Integer");
  318. jmethodID int_parseint = JCALL(env,GetStaticMethodID)(int_cls,
  319. "parseInt", "(Ljava/lang/String;)I"
  320. );
  321. TRACE("Integer: %p, parseInt: %p\n", int_cls, int_parseint);
  322. jclass ctx_cls = JCALL(env,FindClass)("android/content/Context");
  323. jfieldID ctx_audsvc = JCALL(env,GetStaticFieldID)(ctx_cls,
  324. "AUDIO_SERVICE", "Ljava/lang/String;"
  325. );
  326. jmethodID ctx_getSysSvc = JCALL(env,GetMethodID)(ctx_cls,
  327. "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;"
  328. );
  329. TRACE("Context: %p, AUDIO_SERVICE: %p, getSystemService: %p\n",
  330. ctx_cls, ctx_audsvc, ctx_getSysSvc);
  331. jclass audmgr_cls = JCALL(env,FindClass)("android/media/AudioManager");
  332. jfieldID audmgr_prop_out_srate = JCALL(env,GetStaticFieldID)(audmgr_cls,
  333. "PROPERTY_OUTPUT_SAMPLE_RATE", "Ljava/lang/String;"
  334. );
  335. jmethodID audmgr_getproperty = JCALL(env,GetMethodID)(audmgr_cls,
  336. "getProperty", "(Ljava/lang/String;)Ljava/lang/String;"
  337. );
  338. TRACE("AudioManager: %p, PROPERTY_OUTPUT_SAMPLE_RATE: %p, getProperty: %p\n",
  339. audmgr_cls, audmgr_prop_out_srate, audmgr_getproperty);
  340. const char *strchars;
  341. jstring strobj;
  342. /* Now make the calls. */
  343. //AudioManager audMgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
  344. strobj = JCALL(env,GetStaticObjectField)(ctx_cls, ctx_audsvc);
  345. jobject audMgr = JCALL(env,CallObjectMethod)(jctx, ctx_getSysSvc, strobj);
  346. strchars = JCALL(env,GetStringUTFChars)(strobj, nullptr);
  347. TRACE("Context.getSystemService(%s) = %p\n", strchars, audMgr);
  348. JCALL(env,ReleaseStringUTFChars)(strobj, strchars);
  349. //String srateStr = audMgr.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
  350. strobj = JCALL(env,GetStaticObjectField)(audmgr_cls, audmgr_prop_out_srate);
  351. jstring srateStr = JCALL(env,CallObjectMethod)(audMgr, audmgr_getproperty, strobj);
  352. strchars = JCALL(env,GetStringUTFChars)(strobj, nullptr);
  353. TRACE("audMgr.getProperty(%s) = %p\n", strchars, srateStr);
  354. JCALL(env,ReleaseStringUTFChars)(strobj, strchars);
  355. //int sampleRate = Integer.parseInt(srateStr);
  356. sampleRate = JCALL(env,CallStaticIntMethod)(int_cls, int_parseint, srateStr);
  357. strchars = JCALL(env,GetStringUTFChars)(srateStr, nullptr);
  358. TRACE("Got system sample rate %uhz (%s)\n", sampleRate, strchars);
  359. JCALL(env,ReleaseStringUTFChars)(srateStr, strchars);
  360. if(!sampleRate) sampleRate = device->Frequency;
  361. else sampleRate = maxu(sampleRate, MIN_OUTPUT_RATE);
  362. }
  363. #endif
  364. mDevice->FmtChans = DevFmtStereo;
  365. mDevice->FmtType = DevFmtShort;
  366. SetDefaultWFXChannelOrder(mDevice);
  367. mFrameSize = mDevice->frameSizeFromFmt();
  368. loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
  369. loc_bufq.numBuffers = mDevice->BufferSize / mDevice->UpdateSize;
  370. #ifdef SL_DATAFORMAT_PCM_EX
  371. SLDataFormat_PCM_EX format_pcm;
  372. format_pcm.formatType = SL_DATAFORMAT_PCM_EX;
  373. format_pcm.numChannels = mDevice->channelsFromFmt();
  374. format_pcm.sampleRate = mDevice->Frequency * 1000;
  375. format_pcm.bitsPerSample = mDevice->bytesFromFmt() * 8;
  376. format_pcm.containerSize = format_pcm.bitsPerSample;
  377. format_pcm.channelMask = GetChannelMask(mDevice->FmtChans);
  378. format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN :
  379. SL_BYTEORDER_BIGENDIAN;
  380. format_pcm.representation = GetTypeRepresentation(mDevice->FmtType);
  381. #else
  382. SLDataFormat_PCM format_pcm;
  383. format_pcm.formatType = SL_DATAFORMAT_PCM;
  384. format_pcm.numChannels = mDevice->channelsFromFmt();
  385. format_pcm.samplesPerSec = mDevice->Frequency * 1000;
  386. format_pcm.bitsPerSample = mDevice->bytesFromFmt() * 8;
  387. format_pcm.containerSize = format_pcm.bitsPerSample;
  388. format_pcm.channelMask = GetChannelMask(mDevice->FmtChans);
  389. format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN :
  390. SL_BYTEORDER_BIGENDIAN;
  391. #endif
  392. audioSrc.pLocator = &loc_bufq;
  393. audioSrc.pFormat = &format_pcm;
  394. loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
  395. loc_outmix.outputMix = mOutputMix;
  396. audioSnk.pLocator = &loc_outmix;
  397. audioSnk.pFormat = nullptr;
  398. ids[0] = SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
  399. reqs[0] = SL_BOOLEAN_TRUE;
  400. ids[1] = SL_IID_ANDROIDCONFIGURATION;
  401. reqs[1] = SL_BOOLEAN_FALSE;
  402. result = VCALL(mEngine,CreateAudioPlayer)(&mBufferQueueObj, &audioSrc, &audioSnk, COUNTOF(ids),
  403. ids, reqs);
  404. PRINTERR(result, "engine->CreateAudioPlayer");
  405. if(SL_RESULT_SUCCESS == result)
  406. {
  407. /* Set the stream type to "media" (games, music, etc), if possible. */
  408. SLAndroidConfigurationItf config;
  409. result = VCALL(mBufferQueueObj,GetInterface)(SL_IID_ANDROIDCONFIGURATION, &config);
  410. PRINTERR(result, "bufferQueue->GetInterface SL_IID_ANDROIDCONFIGURATION");
  411. if(SL_RESULT_SUCCESS == result)
  412. {
  413. SLint32 streamType = SL_ANDROID_STREAM_MEDIA;
  414. result = VCALL(config,SetConfiguration)(SL_ANDROID_KEY_STREAM_TYPE, &streamType,
  415. sizeof(streamType));
  416. PRINTERR(result, "config->SetConfiguration");
  417. }
  418. /* Clear any error since this was optional. */
  419. result = SL_RESULT_SUCCESS;
  420. }
  421. if(SL_RESULT_SUCCESS == result)
  422. {
  423. result = VCALL(mBufferQueueObj,Realize)(SL_BOOLEAN_FALSE);
  424. PRINTERR(result, "bufferQueue->Realize");
  425. }
  426. if(SL_RESULT_SUCCESS == result)
  427. {
  428. const ALuint num_updates{mDevice->BufferSize / mDevice->UpdateSize};
  429. try {
  430. mRing = CreateRingBuffer(num_updates, mFrameSize*mDevice->UpdateSize, true);
  431. }
  432. catch(std::exception& e) {
  433. ERR("Failed allocating ring buffer %ux%ux%u: %s\n", mDevice->UpdateSize,
  434. num_updates, mFrameSize, e.what());
  435. result = SL_RESULT_MEMORY_FAILURE;
  436. }
  437. }
  438. if(SL_RESULT_SUCCESS != result)
  439. {
  440. if(mBufferQueueObj)
  441. VCALL0(mBufferQueueObj,Destroy)();
  442. mBufferQueueObj = nullptr;
  443. return ALC_FALSE;
  444. }
  445. return ALC_TRUE;
  446. }
  447. ALCboolean OpenSLPlayback::start()
  448. {
  449. mRing->reset();
  450. SLAndroidSimpleBufferQueueItf bufferQueue;
  451. SLresult result{VCALL(mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
  452. &bufferQueue)};
  453. PRINTERR(result, "bufferQueue->GetInterface");
  454. if(SL_RESULT_SUCCESS != result)
  455. return ALC_FALSE;
  456. result = VCALL(bufferQueue,RegisterCallback)(&OpenSLPlayback::processC, this);
  457. PRINTERR(result, "bufferQueue->RegisterCallback");
  458. if(SL_RESULT_SUCCESS != result) return ALC_FALSE;
  459. try {
  460. mKillNow.store(false, std::memory_order_release);
  461. mThread = std::thread(std::mem_fn(&OpenSLPlayback::mixerProc), this);
  462. return ALC_TRUE;
  463. }
  464. catch(std::exception& e) {
  465. ERR("Could not create playback thread: %s\n", e.what());
  466. }
  467. catch(...) {
  468. }
  469. return ALC_FALSE;
  470. }
  471. void OpenSLPlayback::stop()
  472. {
  473. if(mKillNow.exchange(true, std::memory_order_acq_rel) || !mThread.joinable())
  474. return;
  475. mSem.post();
  476. mThread.join();
  477. SLPlayItf player;
  478. SLresult result{VCALL(mBufferQueueObj,GetInterface)(SL_IID_PLAY, &player)};
  479. PRINTERR(result, "bufferQueue->GetInterface");
  480. if(SL_RESULT_SUCCESS == result)
  481. {
  482. result = VCALL(player,SetPlayState)(SL_PLAYSTATE_STOPPED);
  483. PRINTERR(result, "player->SetPlayState");
  484. }
  485. SLAndroidSimpleBufferQueueItf bufferQueue;
  486. result = VCALL(mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bufferQueue);
  487. PRINTERR(result, "bufferQueue->GetInterface");
  488. if(SL_RESULT_SUCCESS == result)
  489. {
  490. result = VCALL0(bufferQueue,Clear)();
  491. PRINTERR(result, "bufferQueue->Clear");
  492. }
  493. if(SL_RESULT_SUCCESS == result)
  494. {
  495. result = VCALL(bufferQueue,RegisterCallback)(nullptr, nullptr);
  496. PRINTERR(result, "bufferQueue->RegisterCallback");
  497. }
  498. if(SL_RESULT_SUCCESS == result)
  499. {
  500. SLAndroidSimpleBufferQueueState state;
  501. do {
  502. std::this_thread::yield();
  503. result = VCALL(bufferQueue,GetState)(&state);
  504. } while(SL_RESULT_SUCCESS == result && state.count > 0);
  505. PRINTERR(result, "bufferQueue->GetState");
  506. }
  507. }
  508. ClockLatency OpenSLPlayback::getClockLatency()
  509. {
  510. ClockLatency ret;
  511. lock();
  512. ret.ClockTime = GetDeviceClockTime(mDevice);
  513. ret.Latency = std::chrono::seconds{mRing->readSpace() * mDevice->UpdateSize};
  514. ret.Latency /= mDevice->Frequency;
  515. unlock();
  516. return ret;
  517. }
  518. struct OpenSLCapture final : public BackendBase {
  519. OpenSLCapture(ALCdevice *device) noexcept : BackendBase{device} { }
  520. ~OpenSLCapture() override;
  521. static void processC(SLAndroidSimpleBufferQueueItf bq, void *context);
  522. void process(SLAndroidSimpleBufferQueueItf bq);
  523. ALCenum open(const ALCchar *name) override;
  524. ALCboolean start() override;
  525. void stop() override;
  526. ALCenum captureSamples(void *buffer, ALCuint samples) override;
  527. ALCuint availableSamples() override;
  528. /* engine interfaces */
  529. SLObjectItf mEngineObj{nullptr};
  530. SLEngineItf mEngine;
  531. /* recording interfaces */
  532. SLObjectItf mRecordObj{nullptr};
  533. RingBufferPtr mRing{nullptr};
  534. ALCuint mSplOffset{0u};
  535. ALsizei mFrameSize{0};
  536. static constexpr inline const char *CurrentPrefix() noexcept { return "OpenSLCapture::"; }
  537. DEF_NEWDEL(OpenSLCapture)
  538. };
  539. OpenSLCapture::~OpenSLCapture()
  540. {
  541. if(mRecordObj)
  542. VCALL0(mRecordObj,Destroy)();
  543. mRecordObj = nullptr;
  544. if(mEngineObj)
  545. VCALL0(mEngineObj,Destroy)();
  546. mEngineObj = nullptr;
  547. mEngine = nullptr;
  548. }
  549. void OpenSLCapture::processC(SLAndroidSimpleBufferQueueItf bq, void *context)
  550. { static_cast<OpenSLCapture*>(context)->process(bq); }
  551. void OpenSLCapture::process(SLAndroidSimpleBufferQueueItf UNUSED(bq))
  552. {
  553. /* A new chunk has been written into the ring buffer, advance it. */
  554. mRing->writeAdvance(1);
  555. }
  556. ALCenum OpenSLCapture::open(const ALCchar* name)
  557. {
  558. if(!name)
  559. name = opensl_device;
  560. else if(strcmp(name, opensl_device) != 0)
  561. return ALC_INVALID_VALUE;
  562. SLresult result{slCreateEngine(&mEngineObj, 0, nullptr, 0, nullptr, nullptr)};
  563. PRINTERR(result, "slCreateEngine");
  564. if(SL_RESULT_SUCCESS == result)
  565. {
  566. result = VCALL(mEngineObj,Realize)(SL_BOOLEAN_FALSE);
  567. PRINTERR(result, "engine->Realize");
  568. }
  569. if(SL_RESULT_SUCCESS == result)
  570. {
  571. result = VCALL(mEngineObj,GetInterface)(SL_IID_ENGINE, &mEngine);
  572. PRINTERR(result, "engine->GetInterface");
  573. }
  574. if(SL_RESULT_SUCCESS == result)
  575. {
  576. mFrameSize = mDevice->frameSizeFromFmt();
  577. /* Ensure the total length is at least 100ms */
  578. ALsizei length{maxi(mDevice->BufferSize, mDevice->Frequency/10)};
  579. /* Ensure the per-chunk length is at least 10ms, and no more than 50ms. */
  580. ALsizei update_len{clampi(mDevice->BufferSize/3, mDevice->Frequency/100,
  581. mDevice->Frequency/100*5)};
  582. ALsizei num_updates{(length+update_len-1) / update_len};
  583. try {
  584. mRing = CreateRingBuffer(num_updates, update_len*mFrameSize, false);
  585. mDevice->UpdateSize = update_len;
  586. mDevice->BufferSize = mRing->writeSpace() * update_len;
  587. }
  588. catch(std::exception& e) {
  589. ERR("Failed to allocate ring buffer: %s\n", e.what());
  590. result = SL_RESULT_MEMORY_FAILURE;
  591. }
  592. }
  593. if(SL_RESULT_SUCCESS == result)
  594. {
  595. const SLInterfaceID ids[2] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION };
  596. const SLboolean reqs[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_FALSE };
  597. SLDataLocator_IODevice loc_dev{};
  598. loc_dev.locatorType = SL_DATALOCATOR_IODEVICE;
  599. loc_dev.deviceType = SL_IODEVICE_AUDIOINPUT;
  600. loc_dev.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT;
  601. loc_dev.device = nullptr;
  602. SLDataSource audioSrc{};
  603. audioSrc.pLocator = &loc_dev;
  604. audioSrc.pFormat = nullptr;
  605. SLDataLocator_AndroidSimpleBufferQueue loc_bq{};
  606. loc_bq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
  607. loc_bq.numBuffers = mDevice->BufferSize / mDevice->UpdateSize;
  608. #ifdef SL_DATAFORMAT_PCM_EX
  609. SLDataFormat_PCM_EX format_pcm{};
  610. format_pcm.formatType = SL_DATAFORMAT_PCM_EX;
  611. format_pcm.numChannels = mDevice->channelsFromFmt();
  612. format_pcm.sampleRate = mDevice->Frequency * 1000;
  613. format_pcm.bitsPerSample = mDevice->bytesFromFmt() * 8;
  614. format_pcm.containerSize = format_pcm.bitsPerSample;
  615. format_pcm.channelMask = GetChannelMask(mDevice->FmtChans);
  616. format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN : SL_BYTEORDER_BIGENDIAN;
  617. format_pcm.representation = GetTypeRepresentation(mDevice->FmtType);
  618. #else
  619. SLDataFormat_PCM format_pcm{};
  620. format_pcm.formatType = SL_DATAFORMAT_PCM;
  621. format_pcm.numChannels = mDevice->channelsFromFmt();
  622. format_pcm.samplesPerSec = mDevice->Frequency * 1000;
  623. format_pcm.bitsPerSample = mDevice->bytesFromFmt() * 8;
  624. format_pcm.containerSize = format_pcm.bitsPerSample;
  625. format_pcm.channelMask = GetChannelMask(mDevice->FmtChans);
  626. format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN : SL_BYTEORDER_BIGENDIAN;
  627. #endif
  628. SLDataSink audioSnk{};
  629. audioSnk.pLocator = &loc_bq;
  630. audioSnk.pFormat = &format_pcm;
  631. result = VCALL(mEngine,CreateAudioRecorder)(&mRecordObj, &audioSrc, &audioSnk,
  632. COUNTOF(ids), ids, reqs);
  633. PRINTERR(result, "engine->CreateAudioRecorder");
  634. }
  635. if(SL_RESULT_SUCCESS == result)
  636. {
  637. /* Set the record preset to "generic", if possible. */
  638. SLAndroidConfigurationItf config;
  639. result = VCALL(mRecordObj,GetInterface)(SL_IID_ANDROIDCONFIGURATION, &config);
  640. PRINTERR(result, "recordObj->GetInterface SL_IID_ANDROIDCONFIGURATION");
  641. if(SL_RESULT_SUCCESS == result)
  642. {
  643. SLuint32 preset = SL_ANDROID_RECORDING_PRESET_GENERIC;
  644. result = VCALL(config,SetConfiguration)(SL_ANDROID_KEY_RECORDING_PRESET, &preset,
  645. sizeof(preset));
  646. PRINTERR(result, "config->SetConfiguration");
  647. }
  648. /* Clear any error since this was optional. */
  649. result = SL_RESULT_SUCCESS;
  650. }
  651. if(SL_RESULT_SUCCESS == result)
  652. {
  653. result = VCALL(mRecordObj,Realize)(SL_BOOLEAN_FALSE);
  654. PRINTERR(result, "recordObj->Realize");
  655. }
  656. SLAndroidSimpleBufferQueueItf bufferQueue;
  657. if(SL_RESULT_SUCCESS == result)
  658. {
  659. result = VCALL(mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bufferQueue);
  660. PRINTERR(result, "recordObj->GetInterface");
  661. }
  662. if(SL_RESULT_SUCCESS == result)
  663. {
  664. result = VCALL(bufferQueue,RegisterCallback)(&OpenSLCapture::processC, this);
  665. PRINTERR(result, "bufferQueue->RegisterCallback");
  666. }
  667. if(SL_RESULT_SUCCESS == result)
  668. {
  669. const ALuint chunk_size{mDevice->UpdateSize * mFrameSize};
  670. auto data = mRing->getWriteVector();
  671. for(size_t i{0u};i < data.first.len && SL_RESULT_SUCCESS == result;i++)
  672. {
  673. result = VCALL(bufferQueue,Enqueue)(data.first.buf + chunk_size*i, chunk_size);
  674. PRINTERR(result, "bufferQueue->Enqueue");
  675. }
  676. for(size_t i{0u};i < data.second.len && SL_RESULT_SUCCESS == result;i++)
  677. {
  678. result = VCALL(bufferQueue,Enqueue)(data.second.buf + chunk_size*i, chunk_size);
  679. PRINTERR(result, "bufferQueue->Enqueue");
  680. }
  681. }
  682. if(SL_RESULT_SUCCESS != result)
  683. {
  684. if(mRecordObj)
  685. VCALL0(mRecordObj,Destroy)();
  686. mRecordObj = nullptr;
  687. if(mEngineObj)
  688. VCALL0(mEngineObj,Destroy)();
  689. mEngineObj = nullptr;
  690. mEngine = nullptr;
  691. return ALC_INVALID_VALUE;
  692. }
  693. mDevice->DeviceName = name;
  694. return ALC_NO_ERROR;
  695. }
  696. ALCboolean OpenSLCapture::start()
  697. {
  698. SLRecordItf record;
  699. SLresult result{VCALL(mRecordObj,GetInterface)(SL_IID_RECORD, &record)};
  700. PRINTERR(result, "recordObj->GetInterface");
  701. if(SL_RESULT_SUCCESS == result)
  702. {
  703. result = VCALL(record,SetRecordState)(SL_RECORDSTATE_RECORDING);
  704. PRINTERR(result, "record->SetRecordState");
  705. }
  706. if(SL_RESULT_SUCCESS != result)
  707. {
  708. aluHandleDisconnect(mDevice, "Failed to start capture: 0x%08x", result);
  709. return ALC_FALSE;
  710. }
  711. return ALC_TRUE;
  712. }
  713. void OpenSLCapture::stop()
  714. {
  715. SLRecordItf record;
  716. SLresult result{VCALL(mRecordObj,GetInterface)(SL_IID_RECORD, &record)};
  717. PRINTERR(result, "recordObj->GetInterface");
  718. if(SL_RESULT_SUCCESS == result)
  719. {
  720. result = VCALL(record,SetRecordState)(SL_RECORDSTATE_PAUSED);
  721. PRINTERR(result, "record->SetRecordState");
  722. }
  723. }
  724. ALCenum OpenSLCapture::captureSamples(void* buffer, ALCuint samples)
  725. {
  726. ALsizei chunk_size = mDevice->UpdateSize * mFrameSize;
  727. SLAndroidSimpleBufferQueueItf bufferQueue;
  728. SLresult result;
  729. ALCuint i;
  730. result = VCALL(mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bufferQueue);
  731. PRINTERR(result, "recordObj->GetInterface");
  732. /* Read the desired samples from the ring buffer then advance its read
  733. * pointer.
  734. */
  735. auto data = mRing->getReadVector();
  736. for(i = 0;i < samples;)
  737. {
  738. ALCuint rem{minu(samples - i, mDevice->UpdateSize - mSplOffset)};
  739. memcpy((ALCbyte*)buffer + i*mFrameSize, data.first.buf + mSplOffset*mFrameSize,
  740. rem * mFrameSize);
  741. mSplOffset += rem;
  742. if(mSplOffset == mDevice->UpdateSize)
  743. {
  744. /* Finished a chunk, reset the offset and advance the read pointer. */
  745. mSplOffset = 0;
  746. mRing->readAdvance(1);
  747. result = VCALL(bufferQueue,Enqueue)(data.first.buf, chunk_size);
  748. PRINTERR(result, "bufferQueue->Enqueue");
  749. if(SL_RESULT_SUCCESS != result) break;
  750. data.first.len--;
  751. if(!data.first.len)
  752. data.first = data.second;
  753. else
  754. data.first.buf += chunk_size;
  755. }
  756. i += rem;
  757. }
  758. if(SL_RESULT_SUCCESS != result)
  759. {
  760. aluHandleDisconnect(mDevice, "Failed to update capture buffer: 0x%08x", result);
  761. return ALC_INVALID_DEVICE;
  762. }
  763. return ALC_NO_ERROR;
  764. }
  765. ALCuint OpenSLCapture::availableSamples()
  766. { return mRing->readSpace()*mDevice->UpdateSize - mSplOffset; }
  767. } // namespace
  768. bool OSLBackendFactory::init() { return true; }
  769. bool OSLBackendFactory::querySupport(BackendType type)
  770. { return (type == BackendType::Playback || type == BackendType::Capture); }
  771. void OSLBackendFactory::probe(DevProbe type, std::string *outnames)
  772. {
  773. switch(type)
  774. {
  775. case DevProbe::Playback:
  776. case DevProbe::Capture:
  777. /* Includes null char. */
  778. outnames->append(opensl_device, sizeof(opensl_device));
  779. break;
  780. }
  781. }
  782. BackendPtr OSLBackendFactory::createBackend(ALCdevice *device, BackendType type)
  783. {
  784. if(type == BackendType::Playback)
  785. return BackendPtr{new OpenSLPlayback{device}};
  786. if(type == BackendType::Capture)
  787. return BackendPtr{new OpenSLCapture{device}};
  788. return nullptr;
  789. }
  790. BackendFactory &OSLBackendFactory::getFactory()
  791. {
  792. static OSLBackendFactory factory{};
  793. return factory;
  794. }