| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800 |
- /*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /* This is an OpenAL backend for Android using the native audio APIs based on OpenSL ES 1.0.1.
- * It is based on source code for the native-audio sample app bundled with NDK.
- */
- #include <stdlib.h>
- #include <time.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include <dlfcn.h>
- #include "alMain.h"
- #include "AL/al.h"
- #include "AL/alc.h"
- #include <pthread.h>
- #include <sched.h>
- #include <sys/prctl.h>
- #include <jni.h>
- #define LOG_NDEBUG 0
- #define LOG_TAG "OpenAL_SLES"
- #if 1
- #define LOGV(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
- #else
- #define LOGV(...)
- #endif
- // for native audio
- #include <SLES/OpenSLES.h>
- #include <SLES/OpenSLES_Android.h>
- #include "apportable_openal_funcs.h"
- #define MAKE_SYM_POINTER(sym) static typeof(sym) * p##sym = NULL
- MAKE_SYM_POINTER(SL_IID_ENGINE);
- MAKE_SYM_POINTER(SL_IID_ANDROIDSIMPLEBUFFERQUEUE);
- MAKE_SYM_POINTER(SL_IID_PLAY);
- MAKE_SYM_POINTER(SL_IID_BUFFERQUEUE);
- MAKE_SYM_POINTER(slCreateEngine);
- // engine interfaces
- static SLObjectItf engineObject = NULL;
- static SLEngineItf engineEngine;
- // output mix interfaces
- static SLObjectItf outputMixObject = NULL;
- // JNI stuff so we can get the runtime OS version number
- static JavaVM* javaVM = NULL;
- static int alc_opensles_get_android_api()
- {
- jclass androidVersionClass = NULL;
- jfieldID androidSdkIntField = NULL;
- int androidApiLevel = 0;
- JNIEnv* env = NULL;
-
- (*javaVM)->GetEnv(javaVM, (void**)&env, JNI_VERSION_1_4);
- androidVersionClass = (*env)->FindClass(env, "android/os/Build$VERSION");
- if (androidVersionClass)
- {
- androidSdkIntField = (*env)->GetStaticFieldID(env, androidVersionClass, "SDK_INT", "I");
- if (androidSdkIntField != NULL)
- {
- androidApiLevel = (int)((*env)->GetStaticIntField(env, androidVersionClass, androidSdkIntField));
- }
- (*env)->DeleteLocalRef(env, androidVersionClass);
- }
- LOGV("API:%d", androidApiLevel);
- return androidApiLevel;
- }
- static char *androidModel = NULL;
- static char *alc_opensles_get_android_model()
- {
- if (!androidModel) {
- jclass androidBuildClass = NULL;
- jfieldID androidModelField = NULL;
- jstring androidModelString = NULL;
- int androidApiLevel = 0;
- JNIEnv* env = NULL;
-
- (*javaVM)->GetEnv(javaVM, (void**)&env, JNI_VERSION_1_4);
- (*env)->PushLocalFrame(env, 5);
- androidBuildClass = (*env)->FindClass(env, "android/os/Build");
- if (androidBuildClass)
- {
- androidModelField = (*env)->GetStaticFieldID(env, androidBuildClass, "MODEL", "Ljava/lang/String;");
- androidModelString = (*env)->GetStaticObjectField(env, androidBuildClass, androidModelField);
- const char *unichars = (*env)->GetStringUTFChars(env, androidModelString, NULL);
- if (!(*env)->ExceptionOccurred(env))
- {
- jsize sz = (*env)->GetStringLength(env, androidModelString);
- androidModel = malloc(sz+1);
- if (androidModel) {
- strncpy(androidModel, unichars, sz);
- androidModel[sz] = '\0';
- }
- }
- (*env)->ReleaseStringUTFChars(env, androidModelString, unichars);
- }
- (*env)->PopLocalFrame(env, NULL);
- }
- LOGV("Model:%s", androidModel);
- return androidModel;
- }
- static long timespecdiff(struct timespec *starttime, struct timespec *finishtime)
- {
- long msec;
- msec=(finishtime->tv_sec-starttime->tv_sec)*1000;
- msec+=(finishtime->tv_nsec-starttime->tv_nsec)/1000000;
- return msec;
- }
- // Cannot be a constant because we need to tweak differently depending on OS version.
- static size_t bufferCount = 8;
- static size_t bufferSize = (1024*4);
- static size_t defaultBufferSize = (1024*4);
- static size_t premixCount = 3;
- #define bufferSizeMax (1024*4)
- typedef enum {
- OUTPUT_BUFFER_STATE_UNKNOWN,
- OUTPUT_BUFFER_STATE_FREE,
- OUTPUT_BUFFER_STATE_MIXED,
- OUTPUT_BUFFER_STATE_ENQUEUED,
- } outputBuffer_state_t;
- typedef struct outputBuffer_s {
- pthread_mutex_t mutex;
- pthread_cond_t cond;
- outputBuffer_state_t state;
- char buffer[bufferSizeMax];
- } outputBuffer_t;
- // Will dynamically create the number of buffers (array elements) based on OS version.
- typedef struct {
- pthread_t playbackThread;
- char threadShouldRun;
- char threadIsReady;
- char lastBufferEnqueued;
- char lastBufferMixed;
- outputBuffer_t *outputBuffers;
- // buffer queue player interfaces
- SLObjectItf bqPlayerObject;
- SLPlayItf bqPlayerPlay;
- SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;
- } opesles_data_t;
- #define MAX_DEVICES 3
- static ALCdevice *deviceList[MAX_DEVICES] = {NULL};
- static pthread_mutex_t deviceListMutex = PTHREAD_MUTEX_INITIALIZER;
- typedef void (*deviceListFn)(ALCdevice *);
- static void devlist_add(ALCdevice *pDevice) {
- int i;
- pthread_mutex_lock(&(deviceListMutex));
- for (i = 0; i < MAX_DEVICES; i++) {
- if (deviceList[i] == pDevice) {
- break;
- } else if (deviceList[i] == NULL) {
- deviceList[i] = pDevice;
- break;
- }
- }
- pthread_mutex_unlock(&(deviceListMutex));
- }
- static void devlist_remove(ALCdevice *pDevice) {
- int i;
- pthread_mutex_lock(&(deviceListMutex));
- for (i = 0; i < MAX_DEVICES; i++) {
- if (deviceList[i] == pDevice) {
- deviceList[i] = NULL;
- }
- }
- pthread_mutex_unlock(&(deviceListMutex));
- }
- static void devlist_process(deviceListFn mapFunction) {
- int i;
- pthread_mutex_lock(&(deviceListMutex));
- for (i = 0; i < MAX_DEVICES; i++) {
- if (deviceList[i]) {
- pthread_mutex_unlock(&(deviceListMutex));
- mapFunction(deviceList[i]);
- pthread_mutex_lock(&(deviceListMutex));
- }
- }
- pthread_mutex_unlock(&(deviceListMutex));
- }
- static void *playback_function(void * context) {
- LOGV("playback_function started");
- outputBuffer_t *buffer = NULL;
- SLresult result;
- struct timespec ts;
- assert(NULL != context);
- ALCdevice *pDevice = (ALCdevice *) context;
- opesles_data_t *devState = (opesles_data_t *) pDevice->ExtraData;
- unsigned int bufferIndex = devState->lastBufferMixed;
- ALint frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
- // Show a sensible name for the thread in debug tools
- prctl(PR_SET_NAME, (unsigned long)"OpenAL/sl/m", 0, 0, 0);
- while (1) {
- if (devState->threadShouldRun == 0) {
- return NULL;
- }
- bufferIndex = (++bufferIndex) % bufferCount;
- buffer = &(devState->outputBuffers[bufferIndex]);
- pthread_mutex_lock(&(buffer->mutex));
- while (1) {
- if (devState->threadShouldRun == 0) {
- pthread_mutex_unlock(&(buffer->mutex));
- return NULL;
- }
- // This is a little hacky, but here we avoid mixing too much data
- if (buffer->state == OUTPUT_BUFFER_STATE_FREE) {
- int i = (bufferIndex - premixCount) % bufferCount;
- outputBuffer_t *buffer1 = &(devState->outputBuffers[i]);
- if (buffer1->state == OUTPUT_BUFFER_STATE_ENQUEUED ||
- buffer1->state == OUTPUT_BUFFER_STATE_FREE) {
- break;
- }
- }
- // No buffer available, wait for a buffer to become available
- // or until playback is stopped/suspended
- clock_gettime(CLOCK_REALTIME, &ts);
- ts.tv_nsec += 5000000;
- pthread_cond_timedwait(&(buffer->cond), &(buffer->mutex), &ts);
- }
- devState->threadIsReady = 1;
- aluMixData(pDevice, buffer->buffer, bufferSize/frameSize);
- buffer->state = OUTPUT_BUFFER_STATE_MIXED;
- pthread_cond_signal(&(buffer->cond));
- pthread_mutex_unlock(&(buffer->mutex));
- devState->lastBufferMixed = bufferIndex;
- }
- }
- SLresult alc_opensles_init_extradata(ALCdevice *pDevice)
- {
- opesles_data_t *devState = NULL;
- int i;
- devState = malloc(sizeof(opesles_data_t));
- if (!devState) {
- return SL_RESULT_MEMORY_FAILURE;
- }
- bzero(devState, sizeof(opesles_data_t));
- devState->outputBuffers = (outputBuffer_t*) malloc(sizeof(outputBuffer_t)*bufferCount);
- if (!devState->outputBuffers) {
- free(devState);
- return SL_RESULT_MEMORY_FAILURE;
- }
- pDevice->ExtraData = devState;
- bzero(devState->outputBuffers, sizeof(outputBuffer_t)*bufferCount);
- devState->lastBufferEnqueued = -1;
- devState->lastBufferMixed = -1;
- for (i = 0; i < bufferCount; i++) {
- if (pthread_mutex_init(&(devState->outputBuffers[i].mutex), (pthread_mutexattr_t*) NULL) != 0) {
- LOGV("Error on init of mutex");
- free(devState->outputBuffers);
- free(devState);
- return SL_RESULT_UNKNOWN_ERROR;
- }
- if (pthread_cond_init(&(devState->outputBuffers[i].cond), (pthread_condattr_t*) NULL) != 0) {
- LOGV("Error on init of cond");
- free(devState->outputBuffers);
- free(devState);
- return SL_RESULT_UNKNOWN_ERROR;
- }
- devState->outputBuffers[i].state = OUTPUT_BUFFER_STATE_FREE;
- }
- // For the Android suspend/resume functionaly, keep track of all device contexts
- devlist_add(pDevice);
- return SL_RESULT_SUCCESS;
- }
- static void start_playback(ALCdevice *pDevice) {
- opesles_data_t *devState = NULL;
- int i;
- if (pDevice->ExtraData == NULL) {
- alc_opensles_init_extradata(pDevice);
- devState = pDevice->ExtraData;
- assert(devState != NULL);
- } else {
- devState = (opesles_data_t *) pDevice->ExtraData;
- }
- if (devState->threadShouldRun == 1) {
- // Gratuitous resume
- return;
- }
- // start/restart playback thread
- devState->threadShouldRun = 1;
- pthread_attr_t playbackThreadAttr;
- pthread_attr_init(&playbackThreadAttr);
- struct sched_param playbackThreadParam;
- playbackThreadParam.sched_priority = sched_get_priority_max(SCHED_RR);
- pthread_attr_setschedpolicy(&playbackThreadAttr, SCHED_RR);
- pthread_attr_setschedparam(&playbackThreadAttr, &playbackThreadParam);
- pthread_create(&(devState->playbackThread), &playbackThreadAttr, playback_function, (void *) pDevice);
- while (devState->threadShouldRun && (0 == devState->threadIsReady))
- {
- sched_yield();
- }
- }
- static void stop_playback(ALCdevice *pDevice) {
- opesles_data_t *devState = (opesles_data_t *) pDevice->ExtraData;
- devState->threadShouldRun = 0;
- pthread_join(devState->playbackThread, NULL);
- return;
- }
- // this callback handler is called every time a buffer finishes playing
- static void opensles_callback(SLAndroidSimpleBufferQueueItf bq, void *context)
- {
- ALCdevice *pDevice = (ALCdevice *) context;
- opesles_data_t *devState = (opesles_data_t *) pDevice->ExtraData;
- unsigned int bufferIndex = devState->lastBufferEnqueued;
- unsigned int i;
- struct timespec ts;
- int rc;
- SLresult result;
- outputBuffer_t *buffer = NULL;
- bufferIndex = (++bufferIndex) % bufferCount;
- buffer = &(devState->outputBuffers[bufferIndex]);
- pthread_mutex_lock(&(buffer->mutex));
- // We will block until 'next' buffer has mixed audio, but first flag oldest equeued buffer as free
- for (i = 1; i <= bufferCount; i++) {
- unsigned int j = (devState->lastBufferEnqueued+i) % bufferCount;
- outputBuffer_t *bufferFree = &(devState->outputBuffers[j]);
- if (bufferFree->state == OUTPUT_BUFFER_STATE_ENQUEUED) {
- bufferFree->state = OUTPUT_BUFFER_STATE_FREE;
- break;
- }
- }
- while (buffer->state != OUTPUT_BUFFER_STATE_MIXED) {
- clock_gettime(CLOCK_REALTIME, &ts);
- ts.tv_nsec += 100000;
- rc = pthread_cond_timedwait(&(buffer->cond), &(buffer->mutex), &ts);
- if (rc != 0) {
- if (devState->threadShouldRun == 0) {
- // we are probably suspended
- pthread_mutex_unlock(&(buffer->mutex));
- return;
- }
- }
- }
- if (devState->bqPlayerBufferQueue) {
- result = (*devState->bqPlayerBufferQueue)->Enqueue(devState->bqPlayerBufferQueue, buffer->buffer, bufferSize);
- if (SL_RESULT_SUCCESS == result) {
- buffer->state = OUTPUT_BUFFER_STATE_ENQUEUED;
- devState->lastBufferEnqueued = bufferIndex;
- pthread_cond_signal(&(buffer->cond));
- } else {
- bufferIndex--;
- }
- }
- pthread_mutex_unlock(&(buffer->mutex));
- }
- static const ALCchar opensles_device[] = "OpenSL ES";
- // Apportable extensions
- SLresult alc_opensles_create_native_audio_engine()
- {
- if (engineObject)
- return SL_RESULT_SUCCESS;
- SLresult result;
- // create engine
- result = pslCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
- assert(SL_RESULT_SUCCESS == result);
- // realize the engine
- result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
- assert(SL_RESULT_SUCCESS == result);
- // get the engine interface, which is needed in order to create other objects
- result = (*engineObject)->GetInterface(engineObject, *pSL_IID_ENGINE, &engineEngine);
- assert(SL_RESULT_SUCCESS == result);
- // create output mix
- result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL);
- assert(SL_RESULT_SUCCESS == result);
- // realize the output mix
- result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
- assert(SL_RESULT_SUCCESS == result);
- return result;
- }
- // Backend functions, in same order as type BackendFuncs
- static ALCboolean opensles_open_playback(ALCdevice *pDevice, const ALCchar *deviceName)
- {
- LOGV("opensles_open_playback pDevice=%p, deviceName=%s", pDevice, deviceName);
- // Check if probe has linked the opensl symbols
- if (pslCreateEngine == NULL) {
- alc_opensles_probe(DEVICE_PROBE);
- if (pslCreateEngine == NULL) {
- return ALC_FALSE;
- }
- }
- if (pDevice->ExtraData == NULL) {
- alc_opensles_init_extradata(pDevice);
- }
- // create the engine and output mix objects
- alc_opensles_create_native_audio_engine();
- return ALC_TRUE;
- }
- static void opensles_close_playback(ALCdevice *pDevice)
- {
- LOGV("opensles_close_playback pDevice=%p", pDevice);
- opesles_data_t *devState = (opesles_data_t *) pDevice->ExtraData;
- // shut down the native audio system
- // destroy buffer queue audio player object, and invalidate all associated interfaces
- if (devState->bqPlayerObject != NULL) {
- (*devState->bqPlayerObject)->Destroy(devState->bqPlayerObject);
- devState->bqPlayerObject = NULL;
- devState->bqPlayerPlay = NULL;
- devState->bqPlayerBufferQueue = NULL;
- }
- devlist_remove(pDevice);
- }
- static ALCboolean opensles_reset_playback(ALCdevice *pDevice)
- {
- if (pDevice == NULL) {
- LOGE("Received a NULL ALCdevice! Returning ALC_FALSE from opensles_reset_playback");
- return ALC_FALSE;
- }
- LOGV("opensles_reset_playback pDevice=%p", pDevice);
- opesles_data_t *devState;
- unsigned bits = BytesFromDevFmt(pDevice->FmtType) * 8;
- unsigned channels = ChannelsFromDevFmt(pDevice->FmtChans);
- unsigned samples = pDevice->UpdateSize;
- unsigned size = samples * channels * bits / 8;
- SLuint32 sampling_rate = pDevice->Frequency * 1000;
- SLresult result;
- LOGV("bits=%u, channels=%u, samples=%u, size=%u, freq=%u", bits, channels, samples, size, pDevice->Frequency);
- if (pDevice->Frequency <= 22050) {
- bufferSize = defaultBufferSize / 2;
- }
- devState = (opesles_data_t *) pDevice->ExtraData;
- // create buffer queue audio player
- // configure audio source
- SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
- // SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, 2, SL_SAMPLINGRATE_44_1,
- SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, 2, sampling_rate,
- SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
- SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT, SL_BYTEORDER_LITTLEENDIAN};
- SLDataSource audioSrc = {&loc_bufq, &format_pcm};
- // configure audio sink
- SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
- SLDataSink audioSnk = {&loc_outmix, NULL};
- // create audio player
- LOGV("create audio player");
- const SLInterfaceID ids[1] = {*pSL_IID_ANDROIDSIMPLEBUFFERQUEUE};
- const SLboolean req[1] = {SL_BOOLEAN_TRUE};
- result = (*engineEngine)->CreateAudioPlayer(engineEngine, &devState->bqPlayerObject, &audioSrc, &audioSnk,
- 1, ids, req);
- if ((result != SL_RESULT_SUCCESS) || (devState->bqPlayerObject == NULL)) {
- //RELEASE_LOG("create audio player is null or errored: %lx", result);
- return ALC_FALSE;
- }
- // realize the player
- result = (*devState->bqPlayerObject)->Realize(devState->bqPlayerObject, SL_BOOLEAN_FALSE);
- assert(SL_RESULT_SUCCESS == result);
- // get the play interface
- result = (*devState->bqPlayerObject)->GetInterface(devState->bqPlayerObject, *pSL_IID_PLAY, &devState->bqPlayerPlay);
- assert(SL_RESULT_SUCCESS == result);
- // get the buffer queue interface
- result = (*devState->bqPlayerObject)->GetInterface(devState->bqPlayerObject, *pSL_IID_BUFFERQUEUE,
- &devState->bqPlayerBufferQueue);
- if ((result != SL_RESULT_SUCCESS) || (devState->bqPlayerBufferQueue == NULL)) {
- //RELEASE_LOG("get the buffer queue interface is null or errored: %lx", result);
- return ALC_FALSE;
- }
- // register callback on the buffer queue
- result = (*devState->bqPlayerBufferQueue)->RegisterCallback(devState->bqPlayerBufferQueue, opensles_callback, (void *) pDevice);
- assert(SL_RESULT_SUCCESS == result);
- // playback_lock = createThreadLock();
- start_playback(pDevice);
- // set the player's state to playing
- result = (*devState->bqPlayerPlay)->SetPlayState(devState->bqPlayerPlay, SL_PLAYSTATE_PLAYING);
- assert(SL_RESULT_SUCCESS == result);
- // enqueue the first buffer to kick off the callbacks
- result = (*devState->bqPlayerBufferQueue)->Enqueue(devState->bqPlayerBufferQueue, "\0", 1);
- assert(SL_RESULT_SUCCESS == result);
- SetDefaultWFXChannelOrder(pDevice);
- devlist_add(pDevice);
- return ALC_TRUE;
- }
- static void opensles_stop_playback(ALCdevice *pDevice)
- {
- LOGV("opensles_stop_playback device=%p", pDevice);
- stop_playback(pDevice);
- }
- static ALCboolean opensles_open_capture(ALCdevice *pDevice, const ALCchar *deviceName)
- {
- LOGV("opensles_open_capture device=%p, deviceName=%s", pDevice, deviceName);
- return ALC_FALSE;
- }
- static void opensles_close_capture(ALCdevice *pDevice)
- {
- LOGV("opensles_closed_capture device=%p", pDevice);
- }
- static void opensles_start_capture(ALCdevice *pDevice)
- {
- LOGV("opensles_start_capture device=%p", pDevice);
- }
- static void opensles_stop_capture(ALCdevice *pDevice)
- {
- LOGV("opensles_stop_capture device=%p", pDevice);
- }
- static void opensles_capture_samples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
- {
- LOGV("opensles_capture_samples device=%p, pBuffer=%p, lSamples=%u", pDevice, pBuffer, lSamples);
- }
- static ALCuint opensles_available_samples(ALCdevice *pDevice)
- {
- LOGV("opensles_available_samples device=%p", pDevice);
- return 0;
- }
- // table of backend function pointers
- BackendFuncs opensles_funcs = {
- opensles_open_playback,
- opensles_close_playback,
- opensles_reset_playback,
- opensles_stop_playback,
- opensles_open_capture,
- opensles_close_capture,
- opensles_start_capture,
- opensles_stop_capture,
- opensles_capture_samples,
- opensles_available_samples
- };
- // global entry points called from XYZZY
-
- static void suspend_device(ALCdevice *pDevice) {
- SLresult result;
- if (pDevice) {
- opesles_data_t *devState = (opesles_data_t *) pDevice->ExtraData;
- if (devState->bqPlayerPlay) {
- result = (*devState->bqPlayerPlay)->SetPlayState(devState->bqPlayerPlay, SL_PLAYSTATE_PAUSED);
- if ((SL_RESULT_SUCCESS == result) && (devState->bqPlayerBufferQueue)) {
- result = (*devState->bqPlayerBufferQueue)->Clear(devState->bqPlayerBufferQueue);
- assert(SL_RESULT_SUCCESS == result);
- }
- }
- stop_playback(pDevice);
- }
- }
- static void resume_device(ALCdevice *pDevice) {
- SLresult result;
- if (pDevice) {
- opesles_data_t *devState = (opesles_data_t *) pDevice->ExtraData;
- if (devState->bqPlayerPlay) {
- result = (*devState->bqPlayerPlay)->SetPlayState(devState->bqPlayerPlay, SL_PLAYSTATE_PLAYING);
- // Pump some blank data into the buffer to stimulate the callback
- if ((SL_RESULT_SUCCESS == result) && (devState->bqPlayerBufferQueue)) {
- result = (*devState->bqPlayerBufferQueue)->Enqueue(devState->bqPlayerBufferQueue, "\0", 1);
- assert(SL_RESULT_SUCCESS == result);
- }
- }
- start_playback(pDevice);
- }
- }
- void alc_opensles_suspend()
- {
- devlist_process(&suspend_device);
- }
-
- void alc_opensles_resume()
- {
- devlist_process(&resume_device);
- }
- static void alc_opensles_set_java_vm(JavaVM *vm)
- {
- // Called once and only once from JNI_OnLoad
- javaVM = vm;
- int i;
- char *android_model;
- char *low_buffer_models[] = {
- "GT-I9300",
- "GT-I9305",
- "SHV-E210",
- "SGH-T999",
- "SGH-I747",
- "SGH-N064",
- "SC-06D",
- "SGH-N035",
- "SC-03E",
- "SCH-R530",
- "SCH-I535",
- "SPH-L710",
- "GT-I9308",
- "SCH-I939",
- "Kindle Fire",
- NULL};
- if(NULL != javaVM)
- {
- int android_os_version = alc_opensles_get_android_api();
- // If running on 4.1 (Jellybean) or later, use 8 buffers to avoid breakup/stuttering.
- if(android_os_version >= 16)
- {
- premixCount = 5;
- }
- // Else, use 4 buffers to reduce latency
- else
- {
- premixCount = 1;
- }
- android_model = alc_opensles_get_android_model();
- for (i = 0; low_buffer_models[i] != NULL; i++) {
- if (strncmp(android_model, low_buffer_models[i], strlen(low_buffer_models[i])) == 0) {
- LOGV("Using less buffering");
- defaultBufferSize = 1024;
- bufferSize = 1024;
- premixCount = 1;
- break;
- }
- }
- }
- }
- void alc_opensles_init(BackendFuncs *func_list)
- {
- LOGV("alc_opensles_init");
- struct stat statinfo;
- if (stat("/system/lib/libOpenSLES.so", &statinfo) != 0) {
- return;
- }
- *func_list = opensles_funcs;
- // We need the JavaVM for JNI so we can detect the OS version number at runtime.
- // This is because we need to use different bufferCount values for Android 4.1 vs. pre-4.1.
- // This must be set at constructor time before JNI_OnLoad is invoked.
- apportableOpenALFuncs.alc_android_set_java_vm = alc_opensles_set_java_vm;
- }
- void alc_opensles_deinit(void)
- {
- LOGV("alc_opensles_deinit");
- // destroy output mix object, and invalidate all associated interfaces
- if (outputMixObject != NULL) {
- (*outputMixObject)->Destroy(outputMixObject);
- outputMixObject = NULL;
- }
- // destroy engine object, and invalidate all associated interfaces
- if (engineObject != NULL) {
- (*engineObject)->Destroy(engineObject);
- engineObject = NULL;
- engineEngine = NULL;
- }
- }
- void alc_opensles_probe(int type)
- {
- char *error;
- struct stat statinfo;
- if (stat("/system/lib/libOpenSLES.so", &statinfo) != 0) {
- LOGV("alc_opensles_probe OpenSLES support not found.");
- return;
- }
- dlerror(); // Clear dl errors
- void *dlHandle = dlopen("/system/lib/libOpenSLES.so", RTLD_NOW | RTLD_GLOBAL);
- if (!dlHandle || (error = (typeof(error))dlerror()) != NULL) {
- LOGV("OpenSLES could not be loaded.");
- return;
- }
- #define LOAD_SYM_POINTER(sym) \
- do { \
- p##sym = dlsym(dlHandle, #sym); \
- if((error=(typeof(error))dlerror()) != NULL) { \
- LOGV("alc_opensles_probe could not load %s, error: %s", #sym, error); \
- dlclose(dlHandle); \
- return; \
- } \
- } while(0)
- LOAD_SYM_POINTER(slCreateEngine);
- LOAD_SYM_POINTER(SL_IID_ENGINE);
- LOAD_SYM_POINTER(SL_IID_ANDROIDSIMPLEBUFFERQUEUE);
- LOAD_SYM_POINTER(SL_IID_PLAY);
- LOAD_SYM_POINTER(SL_IID_BUFFERQUEUE);
- apportableOpenALFuncs.alc_android_suspend = alc_opensles_suspend;
- apportableOpenALFuncs.alc_android_resume = alc_opensles_resume;
- switch (type) {
- case DEVICE_PROBE:
- LOGV("alc_opensles_probe DEVICE_PROBE");
- AppendDeviceList(opensles_device);
- break;
- case ALL_DEVICE_PROBE:
- LOGV("alc_opensles_probe ALL_DEVICE_PROBE");
- AppendAllDeviceList(opensles_device);
- break;
- default:
- LOGV("alc_opensles_probe type=%d", type);
- break;
- }
- }
|