Home | History | Annotate | Download | only in libaudiojni
      1 /*
      2  * Copyright (C) 2015 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 
     17 //#define LOG_NDEBUG 0
     18 #define LOG_TAG "OpenSL-ES-Test-B-1-1-Buffer-Queue"
     19 
     20 #include "sl-utils.h"
     21 
     22 /*
     23  * See https://www.khronos.org/registry/sles/specs/OpenSL_ES_Specification_1.0.1.pdf
     24  * Appendix B.1.1 sample code.
     25  *
     26  * Minor edits made to conform to Android coding style.
     27  *
     28  * Correction to code: SL_IID_VOLUME is now made optional for the mixer.
     29  * It isn't supported on the standard Android mixer, but it is supported on the player.
     30  */
     31 
     32 #define MAX_NUMBER_INTERFACES 3
     33 
     34 /* Local storage for Audio data in 16 bit words */
     35 #define AUDIO_DATA_STORAGE_SIZE 4096
     36 
     37 #define AUDIO_DATA_SEGMENTS 8
     38 
     39 /* Audio data buffer size in 16 bit words. 8 data segments are used in
     40    this simple example */
     41 #define AUDIO_DATA_BUFFER_SIZE (AUDIO_DATA_STORAGE_SIZE / AUDIO_DATA_SEGMENTS)
     42 
     43 /* Structure for passing information to callback function */
     44 typedef struct  {
     45     SLPlayItf playItf;
     46     SLint16  *pDataBase; // Base address of local audio data storage
     47     SLint16  *pData;     // Current address of local audio data storage
     48     SLuint32  size;
     49 } CallbackCntxt;
     50 
     51 /* Local storage for Audio data */
     52 static SLint16 pcmData[AUDIO_DATA_STORAGE_SIZE];
     53 
     54 /* Callback for Buffer Queue events */
     55 static void BufferQueueCallback(
     56         SLBufferQueueItf queueItf,
     57         void *pContext)
     58 {
     59     SLresult res;
     60     CallbackCntxt *pCntxt = (CallbackCntxt*)pContext;
     61     if (pCntxt->pData < (pCntxt->pDataBase + pCntxt->size)) {
     62         res = (*queueItf)->Enqueue(queueItf, (void *)pCntxt->pData,
     63                 sizeof(SLint16) * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */
     64         ALOGE_IF(res != SL_RESULT_SUCCESS, "error: %s", android::getSLErrStr(res));
     65         /* Increase data pointer by buffer size */
     66         pCntxt->pData += AUDIO_DATA_BUFFER_SIZE;
     67     }
     68 }
     69 
     70 /* Play some music from a buffer queue */
     71 static void TestPlayMusicBufferQueue(SLObjectItf sl)
     72 {
     73     SLEngineItf EngineItf;
     74 
     75     SLresult res;
     76 
     77     SLDataSource audioSource;
     78     SLDataLocator_BufferQueue bufferQueue;
     79     SLDataFormat_PCM pcm;
     80 
     81     SLDataSink audioSink;
     82     SLDataLocator_OutputMix locator_outputmix;
     83 
     84     SLObjectItf player;
     85     SLPlayItf playItf;
     86     SLBufferQueueItf bufferQueueItf;
     87     SLBufferQueueState state;
     88 
     89     SLObjectItf OutputMix;
     90     SLVolumeItf volumeItf;
     91 
     92     int i;
     93 
     94     SLboolean required[MAX_NUMBER_INTERFACES];
     95     SLInterfaceID iidArray[MAX_NUMBER_INTERFACES];
     96 
     97     /* Callback context for the buffer queue callback function */
     98     CallbackCntxt cntxt;
     99 
    100     /* Get the SL Engine Interface which is implicit */
    101     res = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void *)&EngineItf);
    102     CheckErr(res);
    103 
    104     /* Initialize arrays required[] and iidArray[] */
    105     for (i = 0; i < MAX_NUMBER_INTERFACES; i++) {
    106         required[i] = SL_BOOLEAN_FALSE;
    107         iidArray[i] = SL_IID_NULL;
    108     }
    109 
    110     // Set arrays required[] and iidArray[] for VOLUME interface
    111     required[0] = SL_BOOLEAN_FALSE; // ANDROID: we don't require this interface
    112     iidArray[0] = SL_IID_VOLUME;
    113 
    114 #if 0
    115     const unsigned interfaces = 1;
    116 #else
    117 
    118     /* FIXME: Android doesn't properly support optional interfaces (required == false).
    119     [3.1.6] When an application requests explicit interfaces during object creation,
    120     it can flag any interface as required. If an implementation is unable to satisfy
    121     the request for an interface that is not flagged as required (i.e. it is not required),
    122     this will not cause the object to fail creation. On the other hand, if the interface
    123     is flagged as required and the implementation is unable to satisfy the request
    124     for the interface, the object will not be created.
    125     */
    126     const unsigned interfaces = 0;
    127 #endif
    128     // Create Output Mix object to be used by player
    129     res = (*EngineItf)->CreateOutputMix(EngineItf, &OutputMix, interfaces,
    130             iidArray, required);
    131     CheckErr(res);
    132 
    133     // Realizing the Output Mix object in synchronous mode.
    134     res = (*OutputMix)->Realize(OutputMix, SL_BOOLEAN_FALSE);
    135     CheckErr(res);
    136 
    137     volumeItf = NULL; // ANDROID: Volume interface on mix object may not be supported
    138     res = (*OutputMix)->GetInterface(OutputMix, SL_IID_VOLUME,
    139             (void *)&volumeItf);
    140 
    141     /* Setup the data source structure for the buffer queue */
    142     bufferQueue.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
    143     bufferQueue.numBuffers = 4; /* Four buffers in our buffer queue */
    144 
    145     /* Setup the format of the content in the buffer queue */
    146     pcm.formatType = SL_DATAFORMAT_PCM;
    147     pcm.numChannels = 2;
    148     pcm.samplesPerSec = SL_SAMPLINGRATE_44_1;
    149     pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
    150     pcm.containerSize = 16;
    151     pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
    152     pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
    153     audioSource.pFormat = (void *)&pcm;
    154     audioSource.pLocator = (void *)&bufferQueue;
    155 
    156     /* Setup the data sink structure */
    157     locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
    158     locator_outputmix.outputMix = OutputMix;
    159     audioSink.pLocator = (void *)&locator_outputmix;
    160     audioSink.pFormat = NULL;
    161 
    162     /* Initialize the context for Buffer queue callbacks */
    163     cntxt.pDataBase = pcmData;
    164     cntxt.pData = cntxt.pDataBase;
    165     cntxt.size = sizeof(pcmData) / sizeof(pcmData[0]); // ANDROID: Bug
    166 
    167     /* Set arrays required[] and iidArray[] for SEEK interface
    168        (PlayItf is implicit) */
    169     required[0] = SL_BOOLEAN_TRUE;
    170     iidArray[0] = SL_IID_BUFFERQUEUE;
    171 
    172     /* Create the music player */
    173 
    174     res = (*EngineItf)->CreateAudioPlayer(EngineItf, &player,
    175             &audioSource, &audioSink, 1, iidArray, required);
    176     CheckErr(res);
    177 
    178     /* Realizing the player in synchronous mode. */
    179     res = (*player)->Realize(player, SL_BOOLEAN_FALSE);
    180     CheckErr(res);
    181 
    182     /* Get seek and play interfaces */
    183     res = (*player)->GetInterface(player, SL_IID_PLAY, (void *)&playItf);
    184     CheckErr(res);
    185     res = (*player)->GetInterface(player, SL_IID_BUFFERQUEUE,
    186             (void *)&bufferQueueItf);
    187     CheckErr(res);
    188 
    189     /* Setup to receive buffer queue event callbacks */
    190     res = (*bufferQueueItf)->RegisterCallback(bufferQueueItf,
    191             BufferQueueCallback, &cntxt /* BUG, was NULL */);
    192     CheckErr(res);
    193 
    194     /* Before we start set volume to -3dB (-300mB) */
    195     if (volumeItf != NULL) { // ANDROID: Volume interface may not be supported.
    196         res = (*volumeItf)->SetVolumeLevel(volumeItf, -300);
    197         CheckErr(res);
    198     }
    199 
    200     /* Enqueue a few buffers to get the ball rolling */
    201     res = (*bufferQueueItf)->Enqueue(bufferQueueItf, cntxt.pData,
    202             sizeof(SLint16) * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */
    203     CheckErr(res);
    204     cntxt.pData += AUDIO_DATA_BUFFER_SIZE;
    205     res = (*bufferQueueItf)->Enqueue(bufferQueueItf, cntxt.pData,
    206             sizeof(SLint16) * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */
    207     CheckErr(res);
    208     cntxt.pData += AUDIO_DATA_BUFFER_SIZE;
    209     res = (*bufferQueueItf)->Enqueue(bufferQueueItf, cntxt.pData,
    210             sizeof(SLint16) * AUDIO_DATA_BUFFER_SIZE); /* Size given in bytes. */
    211     CheckErr(res);
    212     cntxt.pData += AUDIO_DATA_BUFFER_SIZE;
    213 
    214     /* Play the PCM samples using a buffer queue */
    215     res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING);
    216     CheckErr(res);
    217 
    218     /* Wait until the PCM data is done playing, the buffer queue callback
    219        will continue to queue buffers until the entire PCM data has been
    220        played. This is indicated by waiting for the count member of the
    221        SLBufferQueueState to go to zero.
    222      */
    223     res = (*bufferQueueItf)->GetState(bufferQueueItf, &state);
    224     CheckErr(res);
    225 
    226     while (state.count) {
    227         usleep(5 * 1000 /* usec */); // ANDROID: avoid busy waiting
    228         (*bufferQueueItf)->GetState(bufferQueueItf, &state);
    229     }
    230 
    231     /* Make sure player is stopped */
    232     res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
    233     CheckErr(res);
    234 
    235     /* Destroy the player */
    236     (*player)->Destroy(player);
    237 
    238     /* Destroy Output Mix object */
    239     (*OutputMix)->Destroy(OutputMix);
    240 }
    241 
    242 extern "C" void Java_android_media_cts_AudioNativeTest_nativeAppendixBBufferQueue(
    243         JNIEnv * /* env */, jclass /* clazz */)
    244 {
    245     SLObjectItf engineObject = android::OpenSLEngine();
    246     LOG_ALWAYS_FATAL_IF(engineObject == NULL, "cannot open OpenSL ES engine");
    247 
    248     TestPlayMusicBufferQueue(engineObject);
    249     android::CloseSLEngine(engineObject);
    250 }
    251