Fixes delay when playing first sound in BootAnimation
audioplay is initialized with an example of the type of clip it
will play.
Also remove asserts and debug compile settings from BootAnimation.
BUG:24800792
Change-Id: Icb78489417aee0549c340c746b25e57ccdb3427e
diff --git a/cmds/bootanimation/audioplay.cpp b/cmds/bootanimation/audioplay.cpp
index e20ef0c..8a5c2c6 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 @@
void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) {
(void)bq;
(void)context;
- assert(bq == bqPlayerBufferQueue);
- assert(NULL == context);
audioplay::setPlaying(false);
}
@@ -90,39 +87,56 @@
}
// 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 @@
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);
+ if (result != SL_RESULT_SUCCESS) {
+ ALOGE("sl bqPlayerBufferQueue RegisterCallback failed with result %d", result);
+ return false;
+ }
(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);
- (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 @@
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 @@
// set the player's state
result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay,
isPlaying ? SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_STOPPED);
- assert(SL_RESULT_SUCCESS == result);
- (void)result;
}
}