Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1e23c3d6 authored by Geoffrey Pitsch's avatar Geoffrey Pitsch Committed by android-build-merger
Browse files

Merge \"Fixes delay when playing first sound in BootAnimation\" into nyc-mr1-dev

am: ebfa6df9

Change-Id: Id8b55b666ddd21f5ad767635ff68c2e82edfa2f8
parents 352eac67 ebfa6df9
Loading
Loading
Loading
Loading
+0 −4
Original line number Original line Diff line number Diff line
@@ -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)
+10 −5
Original line number Original line Diff line number Diff line
@@ -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) {
@@ -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());
@@ -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);
@@ -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;
+96 −56
Original line number Original line Diff line number Diff line
@@ -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>
@@ -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);
}
}


@@ -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
@@ -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 */
@@ -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);
@@ -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;
    }
    }


}
}
+5 −3
Original line number Original line Diff line number Diff line
@@ -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();