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

Commit ebfa6df9 authored by Geoffrey Pitsch's avatar Geoffrey Pitsch Committed by Android (Google) Code Review
Browse files

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

parents cc6e8c46 a91a2d73
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -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)
+10 −5
Original line number Diff line number Diff line
@@ -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;
+96 −56
Original line number Diff line number Diff line
@@ -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;
}

} // namespace

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

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