Home | History | Annotate | Download | only in bootanimation
      1 /*
      2  * Copyright (C) 2016 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 
     18 // cribbed from samples/native-audio
     19 
     20 #include "audioplay.h"
     21 
     22 #define CHATTY ALOGD
     23 #define LOG_TAG "audioplay"
     24 
     25 #include <string.h>
     26 
     27 #include <utils/Log.h>
     28 
     29 // for native audio
     30 #include <SLES/OpenSLES.h>
     31 #include <SLES/OpenSLES_Android.h>
     32 
     33 namespace audioplay {
     34 namespace {
     35 
     36 // engine interfaces
     37 static SLObjectItf engineObject = NULL;
     38 static SLEngineItf engineEngine;
     39 
     40 // output mix interfaces
     41 static SLObjectItf outputMixObject = NULL;
     42 
     43 // buffer queue player interfaces
     44 static SLObjectItf bqPlayerObject = NULL;
     45 static SLPlayItf bqPlayerPlay;
     46 static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;
     47 static SLMuteSoloItf bqPlayerMuteSolo;
     48 static SLVolumeItf bqPlayerVolume;
     49 
     50 // pointer and size of the next player buffer to enqueue, and number of remaining buffers
     51 static const uint8_t* nextBuffer;
     52 static unsigned nextSize;
     53 
     54 static const uint32_t ID_RIFF = 0x46464952;
     55 static const uint32_t ID_WAVE = 0x45564157;
     56 static const uint32_t ID_FMT  = 0x20746d66;
     57 static const uint32_t ID_DATA = 0x61746164;
     58 
     59 struct RiffWaveHeader {
     60     uint32_t riff_id;
     61     uint32_t riff_sz;
     62     uint32_t wave_id;
     63 };
     64 
     65 struct ChunkHeader {
     66     uint32_t id;
     67     uint32_t sz;
     68 };
     69 
     70 struct ChunkFormat {
     71     uint16_t audio_format;
     72     uint16_t num_channels;
     73     uint32_t sample_rate;
     74     uint32_t byte_rate;
     75     uint16_t block_align;
     76     uint16_t bits_per_sample;
     77 };
     78 
     79 // this callback handler is called every time a buffer finishes playing
     80 void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) {
     81     (void)bq;
     82     (void)context;
     83     audioplay::setPlaying(false);
     84 }
     85 
     86 bool hasPlayer() {
     87     return (engineObject != NULL && bqPlayerObject != NULL);
     88 }
     89 
     90 // create the engine and output mix objects
     91 bool createEngine() {
     92     SLresult result;
     93 
     94     // create engine
     95     result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
     96     if (result != SL_RESULT_SUCCESS) {
     97         ALOGE("slCreateEngine failed with result %d", result);
     98         return false;
     99     }
    100     (void)result;
    101 
    102     // realize the engine
    103     result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
    104     if (result != SL_RESULT_SUCCESS) {
    105         ALOGE("sl engine Realize failed with result %d", result);
    106         return false;
    107     }
    108     (void)result;
    109 
    110     // get the engine interface, which is needed in order to create other objects
    111     result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
    112     if (result != SL_RESULT_SUCCESS) {
    113         ALOGE("sl engine GetInterface failed with result %d", result);
    114         return false;
    115     }
    116     (void)result;
    117 
    118     // create output mix
    119     result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL);
    120     if (result != SL_RESULT_SUCCESS) {
    121         ALOGE("sl engine CreateOutputMix failed with result %d", result);
    122         return false;
    123     }
    124     (void)result;
    125 
    126     // realize the output mix
    127     result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
    128     if (result != SL_RESULT_SUCCESS) {
    129         ALOGE("sl outputMix Realize failed with result %d", result);
    130         return false;
    131     }
    132     (void)result;
    133 
    134     return true;
    135 }
    136 
    137 // create buffer queue audio player
    138 bool createBufferQueueAudioPlayer(const ChunkFormat* chunkFormat) {
    139     SLresult result;
    140 
    141     // configure audio source
    142     SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 1};
    143 
    144     // Determine channelMask from num_channels
    145     SLuint32 channelMask;
    146     switch (chunkFormat->num_channels) {
    147         case 1:
    148             channelMask = SL_SPEAKER_FRONT_CENTER;
    149             break;
    150         case 2:
    151             channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
    152             break;
    153         default:
    154             // Default of 0 will derive mask from num_channels and log a warning.
    155             channelMask = 0;
    156     }
    157 
    158     SLDataFormat_PCM format_pcm = {
    159         SL_DATAFORMAT_PCM,
    160         chunkFormat->num_channels,
    161         chunkFormat->sample_rate * 1000,  // convert to milliHz
    162         chunkFormat->bits_per_sample,
    163         16,
    164         channelMask,
    165         SL_BYTEORDER_LITTLEENDIAN
    166     };
    167     SLDataSource audioSrc = {&loc_bufq, &format_pcm};
    168 
    169     // configure audio sink
    170     SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
    171     SLDataSink audioSnk = {&loc_outmix, NULL};
    172 
    173     // create audio player
    174     const SLInterfaceID ids[3] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME, SL_IID_ANDROIDCONFIGURATION};
    175     const SLboolean req[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
    176     result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk,
    177             3, ids, req);
    178     if (result != SL_RESULT_SUCCESS) {
    179         ALOGE("sl CreateAudioPlayer failed with result %d", result);
    180         return false;
    181     }
    182     (void)result;
    183 
    184     // Use the System stream for boot sound playback.
    185     SLAndroidConfigurationItf playerConfig;
    186     result = (*bqPlayerObject)->GetInterface(bqPlayerObject,
    187         SL_IID_ANDROIDCONFIGURATION, &playerConfig);
    188     if (result != SL_RESULT_SUCCESS) {
    189         ALOGE("config GetInterface failed with result %d", result);
    190         return false;
    191     }
    192     SLint32 streamType = SL_ANDROID_STREAM_SYSTEM;
    193     result = (*playerConfig)->SetConfiguration(playerConfig,
    194         SL_ANDROID_KEY_STREAM_TYPE, &streamType, sizeof(SLint32));
    195     if (result != SL_RESULT_SUCCESS) {
    196         ALOGE("SetConfiguration failed with result %d", result);
    197         return false;
    198     }
    199     // use normal performance mode as low latency is not needed. This is not mandatory so
    200     // do not bail if we fail
    201     SLuint32 performanceMode = SL_ANDROID_PERFORMANCE_NONE;
    202     result = (*playerConfig)->SetConfiguration(
    203            playerConfig, SL_ANDROID_KEY_PERFORMANCE_MODE, &performanceMode, sizeof(SLuint32));
    204     ALOGW_IF(result != SL_RESULT_SUCCESS,
    205             "could not set performance mode on player, error %d", result);
    206     (void)result;
    207 
    208     // realize the player
    209     result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
    210     if (result != SL_RESULT_SUCCESS) {
    211         ALOGE("sl player Realize failed with result %d", result);
    212         return false;
    213     }
    214     (void)result;
    215 
    216     // get the play interface
    217     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
    218     if (result != SL_RESULT_SUCCESS) {
    219         ALOGE("sl player GetInterface failed with result %d", result);
    220         return false;
    221     }
    222     (void)result;
    223 
    224     // get the buffer queue interface
    225     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE,
    226             &bqPlayerBufferQueue);
    227     if (result != SL_RESULT_SUCCESS) {
    228         ALOGE("sl playberBufferQueue GetInterface failed with result %d", result);
    229         return false;
    230     }
    231     (void)result;
    232 
    233     // register callback on the buffer queue
    234     result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL);
    235     if (result != SL_RESULT_SUCCESS) {
    236         ALOGE("sl bqPlayerBufferQueue RegisterCallback failed with result %d", result);
    237         return false;
    238     }
    239     (void)result;
    240 
    241     // get the volume interface
    242     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume);
    243     if (result != SL_RESULT_SUCCESS) {
    244         ALOGE("sl volume GetInterface failed with result %d", result);
    245         return false;
    246     }
    247     (void)result;
    248 
    249     // set the player's state to playing
    250     audioplay::setPlaying(true);
    251     CHATTY("Created buffer queue player: %p", bqPlayerBufferQueue);
    252     return true;
    253 }
    254 
    255 bool parseClipBuf(const uint8_t* clipBuf, int clipBufSize, const ChunkFormat** oChunkFormat,
    256                   const uint8_t** oSoundBuf, unsigned* oSoundBufSize) {
    257     *oSoundBuf = clipBuf;
    258     *oSoundBufSize = clipBufSize;
    259     *oChunkFormat = NULL;
    260     const RiffWaveHeader* wavHeader = (const RiffWaveHeader*)*oSoundBuf;
    261     if (*oSoundBufSize < sizeof(*wavHeader) || (wavHeader->riff_id != ID_RIFF) ||
    262         (wavHeader->wave_id != ID_WAVE)) {
    263         ALOGE("Error: audio file is not a riff/wave file\n");
    264         return false;
    265     }
    266     *oSoundBuf += sizeof(*wavHeader);
    267     *oSoundBufSize -= sizeof(*wavHeader);
    268 
    269     while (true) {
    270         const ChunkHeader* chunkHeader = (const ChunkHeader*)*oSoundBuf;
    271         if (*oSoundBufSize < sizeof(*chunkHeader)) {
    272             ALOGE("EOF reading chunk headers");
    273             return false;
    274         }
    275 
    276         *oSoundBuf += sizeof(*chunkHeader);
    277         *oSoundBufSize -= sizeof(*chunkHeader);
    278 
    279         bool endLoop = false;
    280         switch (chunkHeader->id) {
    281             case ID_FMT:
    282                 *oChunkFormat = (const ChunkFormat*)*oSoundBuf;
    283                 *oSoundBuf += chunkHeader->sz;
    284                 *oSoundBufSize -= chunkHeader->sz;
    285                 break;
    286             case ID_DATA:
    287                 /* Stop looking for chunks */
    288                 *oSoundBufSize = chunkHeader->sz;
    289                 endLoop = true;
    290                 break;
    291             default:
    292                 /* Unknown chunk, skip bytes */
    293                 *oSoundBuf += chunkHeader->sz;
    294                 *oSoundBufSize -= chunkHeader->sz;
    295         }
    296         if (endLoop) {
    297             break;
    298         }
    299     }
    300 
    301     if (*oChunkFormat == NULL) {
    302         ALOGE("format not found in WAV file");
    303         return false;
    304     }
    305     return true;
    306 }
    307 
    308 } // namespace
    309 
    310 bool create(const uint8_t* exampleClipBuf, int exampleClipBufSize) {
    311     if (!createEngine()) {
    312         return false;
    313     }
    314 
    315     // Parse the example clip.
    316     const ChunkFormat* chunkFormat;
    317     const uint8_t* soundBuf;
    318     unsigned soundBufSize;
    319     if (!parseClipBuf(exampleClipBuf, exampleClipBufSize, &chunkFormat, &soundBuf, &soundBufSize)) {
    320         return false;
    321     }
    322 
    323     // Initialize the BufferQueue based on this clip's format.
    324     if (!createBufferQueueAudioPlayer(chunkFormat)) {
    325         return false;
    326     }
    327     return true;
    328 }
    329 
    330 bool playClip(const uint8_t* buf, int size) {
    331     // Parse the WAV header
    332     const ChunkFormat* chunkFormat;
    333     if (!parseClipBuf(buf, size, &chunkFormat, &nextBuffer, &nextSize)) {
    334         return false;
    335     }
    336 
    337     if (!hasPlayer()) {
    338         ALOGD("cannot play clip %p without a player", buf);
    339         return false;
    340     }
    341 
    342     CHATTY("playClip on player %p: buf=%p size=%d nextSize %d",
    343            bqPlayerBufferQueue, buf, size, nextSize);
    344 
    345     if (nextSize > 0) {
    346         // here we only enqueue one buffer because it is a long clip,
    347         // but for streaming playback we would typically enqueue at least 2 buffers to start
    348         SLresult result;
    349         result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize);
    350         if (SL_RESULT_SUCCESS != result) {
    351             return false;
    352         }
    353         audioplay::setPlaying(true);
    354     }
    355 
    356     return true;
    357 }
    358 
    359 // set the playing state for the buffer queue audio player
    360 void setPlaying(bool isPlaying) {
    361     if (!hasPlayer()) return;
    362 
    363     SLresult result;
    364 
    365     if (NULL != bqPlayerPlay) {
    366         // set the player's state
    367         result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay,
    368             isPlaying ? SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_STOPPED);
    369     }
    370 
    371 }
    372 
    373 void destroy() {
    374     // destroy buffer queue audio player object, and invalidate all associated interfaces
    375     if (bqPlayerObject != NULL) {
    376         CHATTY("destroying audio player");
    377         (*bqPlayerObject)->Destroy(bqPlayerObject);
    378         bqPlayerObject = NULL;
    379         bqPlayerPlay = NULL;
    380         bqPlayerBufferQueue = NULL;
    381         bqPlayerMuteSolo = NULL;
    382         bqPlayerVolume = NULL;
    383     }
    384 
    385     // destroy output mix object, and invalidate all associated interfaces
    386     if (outputMixObject != NULL) {
    387         (*outputMixObject)->Destroy(outputMixObject);
    388         outputMixObject = NULL;
    389     }
    390 
    391     // destroy engine object, and invalidate all associated interfaces
    392     if (engineObject != NULL) {
    393         CHATTY("destroying audio engine");
    394         (*engineObject)->Destroy(engineObject);
    395         engineObject = NULL;
    396         engineEngine = NULL;
    397     }
    398 }
    399 
    400 }  // namespace audioplay
    401