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