diff options
-rw-r--r-- | cmds/bootanimation/Android.mk | 4 | ||||
-rw-r--r-- | cmds/bootanimation/BootAnimation.cpp | 15 | ||||
-rw-r--r-- | cmds/bootanimation/audioplay.cpp | 152 | ||||
-rw-r--r-- | cmds/bootanimation/audioplay.h | 8 |
4 files changed, 111 insertions, 68 deletions
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk index 3cf13d908632..3a92b9e74144 100644 --- a/cmds/bootanimation/Android.mk +++ b/cmds/bootanimation/Android.mk @@ -36,8 +36,4 @@ ifdef TARGET_32_BIT_SURFACEFLINGER LOCAL_32_BIT_ONLY := true endif -# get asserts to work -APP_OPTIM := debug -LOCAL_CFLAGS += -UNDEBUG - include $(BUILD_EXECUTABLE) diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 4098772bba12..ebcc9ff0451f 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -588,7 +588,7 @@ bool BootAnimation::preloadZip(Animation& animation) return false; } - bool hasAudio = false; + Animation::Part* partWithAudio = NULL; ZipEntryRO entry; char name[ANIM_ENTRY_NAME_MAX]; while ((entry = zip->nextEntry(cookie)) != NULL) { @@ -612,10 +612,10 @@ bool BootAnimation::preloadZip(Animation& animation) if (map) { Animation::Part& part(animation.parts.editItemAt(j)); if (leaf == "audio.wav") { - hasAudio = true; // a part may have at most one audio file part.audioData = (uint8_t *)map->getDataPtr(); part.audioLength = map->getDataLength(); + partWithAudio = ∂ } else if (leaf == "trim.txt") { part.trimData.setTo((char const*)map->getDataPtr(), map->getDataLength()); @@ -666,9 +666,11 @@ bool BootAnimation::preloadZip(Animation& animation) } // Create and initialize audioplay if there is a wav file in any of the animations. - if (hasAudio) { + if (partWithAudio != NULL) { ALOGD("found audio.wav, creating playback engine"); - audioplay::create(); + if (!audioplay::create(partWithAudio->audioData, partWithAudio->audioLength)) { + return false; + } } zip->endIteration(cookie); @@ -904,7 +906,10 @@ BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn) mLoadedFiles.add(animation->fileName); parseAnimationDesc(*animation); - preloadZip(*animation); + if (!preloadZip(*animation)) { + return NULL; + } + mLoadedFiles.remove(fn); return animation; diff --git a/cmds/bootanimation/audioplay.cpp b/cmds/bootanimation/audioplay.cpp index e20ef0c7c6cc..8a5c2c6d229c 100644 --- a/cmds/bootanimation/audioplay.cpp +++ b/cmds/bootanimation/audioplay.cpp @@ -21,7 +21,6 @@ #define CHATTY ALOGD -#include <assert.h> #include <string.h> #include <utils/Log.h> @@ -80,8 +79,6 @@ struct ChunkFormat { void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) { (void)bq; (void)context; - assert(bq == bqPlayerBufferQueue); - assert(NULL == context); audioplay::setPlaying(false); } @@ -90,39 +87,56 @@ bool hasPlayer() { } // create the engine and output mix objects -void createEngine() { +bool createEngine() { SLresult result; // create engine result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ALOGE("slCreateEngine failed with result %d", result); + return false; + } (void)result; // realize the engine result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl engine Realize failed with result %d", result); + return false; + } (void)result; // get the engine interface, which is needed in order to create other objects result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl engine GetInterface failed with result %d", result); + return false; + } (void)result; // create output mix, with environmental reverb specified as a non-required interface const SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB}; const SLboolean req[1] = {SL_BOOLEAN_FALSE}; result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids, req); - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl engine CreateOutputMix failed with result %d", result); + return false; + } (void)result; // realize the output mix result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl outputMix Realize failed with result %d", result); + return false; + } (void)result; + + return true; } // create buffer queue audio player -void createBufferQueueAudioPlayer(const ChunkFormat* chunkFormat) { +bool createBufferQueueAudioPlayer(const ChunkFormat* chunkFormat) { SLresult result; // configure audio source @@ -148,83 +162,89 @@ void createBufferQueueAudioPlayer(const ChunkFormat* chunkFormat) { const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req); - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl CreateAudioPlayer failed with result %d", result); + return false; + } (void)result; // realize the player result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE); - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl player Realize failed with result %d", result); + return false; + } (void)result; // get the play interface result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay); - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl player GetInterface failed with result %d", result); + return false; + } (void)result; // get the buffer queue interface result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, &bqPlayerBufferQueue); - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl playberBufferQueue GetInterface failed with result %d", result); + return false; + } (void)result; // register callback on the buffer queue result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL); - assert(SL_RESULT_SUCCESS == result); - (void)result; - -#if 0 // mute/solo is not supported for sources that are known to be mono, as this is - // get the mute/solo interface - result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_MUTESOLO, &bqPlayerMuteSolo); - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl bqPlayerBufferQueue RegisterCallback failed with result %d", result); + return false; + } (void)result; -#endif // get the volume interface result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume); - assert(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl volume GetInterface failed with result %d", result); + return false; + } (void)result; // set the player's state to playing audioplay::setPlaying(true); CHATTY("Created buffer queue player: %p", bqPlayerBufferQueue); + return true; } -} // namespace - -void create() { - createEngine(); -} - -bool playClip(const uint8_t* buf, int size) { - // Parse the WAV header - nextBuffer = buf; - nextSize = size; - const RiffWaveHeader* wavHeader = (const RiffWaveHeader*)buf; - if (nextSize < sizeof(*wavHeader) || (wavHeader->riff_id != ID_RIFF) || +bool parseClipBuf(const uint8_t* clipBuf, int clipBufSize, const ChunkFormat** oChunkFormat, + const uint8_t** oSoundBuf, unsigned* oSoundBufSize) { + *oSoundBuf = clipBuf; + *oSoundBufSize = clipBufSize; + *oChunkFormat = NULL; + const RiffWaveHeader* wavHeader = (const RiffWaveHeader*)*oSoundBuf; + if (*oSoundBufSize < sizeof(*wavHeader) || (wavHeader->riff_id != ID_RIFF) || (wavHeader->wave_id != ID_WAVE)) { ALOGE("Error: audio file is not a riff/wave file\n"); return false; } - nextBuffer += sizeof(*wavHeader); - nextSize -= sizeof(*wavHeader); + *oSoundBuf += sizeof(*wavHeader); + *oSoundBufSize -= sizeof(*wavHeader); - const ChunkFormat* chunkFormat = nullptr; while (true) { - const ChunkHeader* chunkHeader = (const ChunkHeader*)nextBuffer; - if (nextSize < sizeof(*chunkHeader)) { + const ChunkHeader* chunkHeader = (const ChunkHeader*)*oSoundBuf; + if (*oSoundBufSize < sizeof(*chunkHeader)) { ALOGE("EOF reading chunk headers"); return false; } - nextBuffer += sizeof(*chunkHeader); - nextSize -= sizeof(*chunkHeader); + *oSoundBuf += sizeof(*chunkHeader); + *oSoundBufSize -= sizeof(*chunkHeader); bool endLoop = false; switch (chunkHeader->id) { case ID_FMT: - chunkFormat = (const ChunkFormat*)nextBuffer; - nextBuffer += chunkHeader->sz; - nextSize -= chunkHeader->sz; + *oChunkFormat = (const ChunkFormat*)*oSoundBuf; + *oSoundBuf += chunkHeader->sz; + *oSoundBufSize -= chunkHeader->sz; break; case ID_DATA: /* Stop looking for chunks */ @@ -232,27 +252,49 @@ bool playClip(const uint8_t* buf, int size) { break; default: /* Unknown chunk, skip bytes */ - nextBuffer += chunkHeader->sz; - nextSize -= chunkHeader->sz; + *oSoundBuf += chunkHeader->sz; + *oSoundBufSize -= chunkHeader->sz; } if (endLoop) { break; } } - if (!chunkFormat) { + if (*oChunkFormat == NULL) { ALOGE("format not found in WAV file"); return false; } + return true; +} - // If this is the first clip, create the buffer based on this WAV's header. - // We assume all future clips with be in the same format. - if (bqPlayerBufferQueue == nullptr) { - createBufferQueueAudioPlayer(chunkFormat); +} // namespace + +bool create(const uint8_t* exampleClipBuf, int exampleClipBufSize) { + if (!createEngine()) { + return false; } - assert(bqPlayerBufferQueue != nullptr); - assert(buf != nullptr); + // Parse the example clip. + const ChunkFormat* chunkFormat; + const uint8_t* soundBuf; + unsigned soundBufSize; + if (!parseClipBuf(exampleClipBuf, exampleClipBufSize, &chunkFormat, &soundBuf, &soundBufSize)) { + return false; + } + + // Initialize the BufferQueue based on this clip's format. + if (!createBufferQueueAudioPlayer(chunkFormat)) { + return false; + } + return true; +} + +bool playClip(const uint8_t* buf, int size) { + // Parse the WAV header + const ChunkFormat* chunkFormat; + if (!parseClipBuf(buf, size, &chunkFormat, &nextBuffer, &nextSize)) { + return false; + } if (!hasPlayer()) { ALOGD("cannot play clip %p without a player", buf); @@ -285,8 +327,6 @@ void setPlaying(bool isPlaying) { // set the player's state result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, isPlaying ? SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_STOPPED); - assert(SL_RESULT_SUCCESS == result); - (void)result; } } diff --git a/cmds/bootanimation/audioplay.h b/cmds/bootanimation/audioplay.h index bdc0a1c84b6e..0e5705af0ad0 100644 --- a/cmds/bootanimation/audioplay.h +++ b/cmds/bootanimation/audioplay.h @@ -22,10 +22,12 @@ namespace audioplay { -void create(); +// Initializes the engine with an example of the type of WAV clip to play. +// All buffers passed to playClip are assumed to be in the same format. +bool create(const uint8_t* exampleClipBuf, int exampleClipBufSize); -// Play a WAV pointed to by buf. All clips are assumed to be in the same format. -// playClip should not be called while a clip is still playing. +// Plays a WAV contained in buf. +// Should not be called while a clip is still playing. bool playClip(const uint8_t* buf, int size); void setPlaying(bool isPlaying); void destroy(); |