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

Commit d30bcef9 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "libstagefright: Aggregate buffers in audio source"

parents db9233bc b556f5df
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ struct AudioSource : public MediaSource, public MediaBufferObserver {
            MediaBuffer **buffer, const ReadOptions *options = NULL);

    status_t dataCallback(const AudioRecord::Buffer& buffer);
    virtual void onEvent(int event, void* info);
    virtual void signalBufferReturned(MediaBuffer *buffer);

protected:
@@ -60,7 +61,9 @@ protected:

private:
    enum {
        kMaxBufferSize = 2048,
        //This max buffer size is derived from aggregation of audio
        //buffers for max duration 80 msec with 48K sampling rate.
        kMaxBufferSize = 30720,

        // After the initial mute, we raise the volume linearly
        // over kAutoRampDurationUs.
@@ -75,6 +78,11 @@ private:
    Condition mFrameAvailableCondition;
    Condition mFrameEncodingCompletionCondition;

    AudioRecord::Buffer mTempBuf;
    uint32_t mPrevPosition;
    uint32_t mAllocBytes;
    int32_t mAudioSessionId;
    AudioRecord::transfer_type mTransferMode;
    sp<AudioRecord> mRecord;
    status_t mInitCheck;
    bool mStarted;
@@ -91,7 +99,6 @@ private:
    int64_t mAutoRampStartUs;

    List<MediaBuffer * > mBuffersReceived;

    void trackMaxAmplitude(int16_t *data, int nSamples);

    // This is used to raise the volume from mute to the
+138 −20
Original line number Diff line number Diff line
@@ -31,23 +31,12 @@
#include <cutils/properties.h>
#include <system/audio.h>

#define AUDIO_RECORD_DEFAULT_BUFFER_DURATION 20
namespace android {

static void AudioRecordCallbackFunction(int event, void *user, void *info) {
    AudioSource *source = (AudioSource *) user;
    switch (event) {
        case AudioRecord::EVENT_MORE_DATA: {
            source->dataCallback(*((AudioRecord::Buffer *) info));
            break;
        }
        case AudioRecord::EVENT_OVERRUN: {
            ALOGW("AudioRecord reported overrun!");
            break;
        }
        default:
            // does nothing
            break;
    }
    source->onEvent(event, info);
}

AudioSource::AudioSource(
@@ -80,6 +69,60 @@ AudioSource::AudioSource(
            bufCount++;
        }

        mTempBuf.size = 0;
        mTempBuf.frameCount = 0;
        mTempBuf.i16 = (short*)NULL;
        mPrevPosition = 0;
        mAudioSessionId = -1;
        mAllocBytes = 0;
        mTransferMode = AudioRecord::TRANSFER_CALLBACK;

        //decide whether to use callback or event pos callback
        //use position marker only for PCM 16 bit and mono or stereo capture
        //and if input source is camera
        if((mFormat == AUDIO_FORMAT_PCM_16_BIT) &&
            ((channelCount == 1) || (channelCount == 2)) &&
            (inputSource == AUDIO_SOURCE_CAMCORDER)) {

            //Need audioSession Id in the extended audio record constructor
            //where the transfer mode can be specified
            mAudioSessionId = AudioSystem::newAudioUniqueId();
            AudioSystem::acquireAudioSessionId(mAudioSessionId, -1);

            mRecord = new AudioRecord(
                        inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT,
                        audio_channel_in_mask_from_count(channelCount),
                        (size_t) (bufCount * frameCount),
                        AudioRecordCallbackFunction,
                        this,
                        frameCount /*notificationFrames*/,
                        mAudioSessionId,
                        AudioRecord::TRANSFER_SYNC,
                        AUDIO_INPUT_FLAG_NONE);

            int buffDuration = AUDIO_RECORD_DEFAULT_BUFFER_DURATION;
            char propValue[PROPERTY_VALUE_MAX];
            if (property_get("audio.record.buffer.duration", propValue, NULL)) {
                if (atoi(propValue) < AUDIO_RECORD_DEFAULT_BUFFER_DURATION)
                    buffDuration = AUDIO_RECORD_DEFAULT_BUFFER_DURATION;
                else
                    buffDuration = atoi(propValue);
            }
            else
                buffDuration = AUDIO_RECORD_DEFAULT_BUFFER_DURATION;

            //set to update position after frames worth of buffduration time for 16 bits
            mAllocBytes = ((sizeof(uint8_t) * frameCount * 2 * channelCount));
            ALOGI("AudioSource in TRANSFER_SYNC with duration %d ms", buffDuration);
            mTempBuf.i16 = (short*) malloc(mAllocBytes);
            if (mTempBuf.i16 == NULL) {
                mAllocBytes = 0;
                mInitCheck = NO_MEMORY;
            }
            mTransferMode = AudioRecord::TRANSFER_SYNC;
            mRecord->setPositionUpdatePeriod((sampleRate * buffDuration)/1000);
        } else {
            //Sound recorder and VOIP use cases does NOT use aggregation
            mRecord = new AudioRecord(
                        inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT,
                        audio_channel_in_mask_from_count(channelCount),
@@ -87,7 +130,12 @@ AudioSource::AudioSource(
                        AudioRecordCallbackFunction,
                        this,
                        frameCount /*notificationFrames*/);
            ALOGI("AudioSource in TRANSFER_CALLBACK");
            mTransferMode = AudioRecord::TRANSFER_CALLBACK;
        }

        mInitCheck = mRecord->initCheck();

        mAutoRampStartUs = kAutoRampStartUs;
        uint32_t playbackLatencyMs = 0;
        if (AudioSystem::getOutputLatency(&playbackLatencyMs,
@@ -100,6 +148,7 @@ AudioSource::AudioSource(
    } else {
        mInitCheck = status;
    }
    ALOGV("mInitCheck %d", mInitCheck);
}

AudioSource::AudioSource( audio_source_t inputSource, const sp<MetaData>& meta )
@@ -137,6 +186,14 @@ AudioSource::AudioSource( audio_source_t inputSource, const sp<MetaData>& meta )
                AudioRecordCallbackFunction,
                this);
    mInitCheck = mRecord->initCheck();
    mTempBuf.size = 0;
    mTempBuf.frameCount = 0;
    mTempBuf.i16 = (short*)NULL;
    mPrevPosition = 0;
    mAudioSessionId = -1;
    mAllocBytes = 0;
    mTransferMode = AudioRecord::TRANSFER_CALLBACK;

}

AudioSource::~AudioSource() {
@@ -223,6 +280,16 @@ status_t AudioSource::reset() {
    waitOutstandingEncodingFrames_l();
    releaseQueuedFrames_l();

    if (mTransferMode == AudioRecord::TRANSFER_SYNC) {
        if(mAudioSessionId != -1)
            AudioSystem::releaseAudioSessionId(mAudioSessionId, -1);

        mAudioSessionId = -1;
        if(mTempBuf.i16) {
            free(mTempBuf.i16);
            mTempBuf.i16 = (short*)NULL;
        }
    }
    return OK;
}

@@ -408,6 +475,57 @@ status_t AudioSource::dataCallback(const AudioRecord::Buffer& audioBuffer) {
    return OK;
}

void AudioSource::onEvent(int event, void* info) {

    switch (event) {
        case AudioRecord::EVENT_MORE_DATA: {
            dataCallback(*((AudioRecord::Buffer *) info));
            break;
        }
        case AudioRecord::EVENT_NEW_POS: {
            uint32_t position = 0;
            mRecord->getPosition(&position);
            size_t framestoRead = position - mPrevPosition;
            size_t bytestoRead = (framestoRead * 2 * mRecord->channelCount());
            if(bytestoRead <=0 || bytestoRead > mAllocBytes) {
                //try to read only max
                ALOGI("greater than allocated size in callback, adjusting size");
                bytestoRead =  mAllocBytes;
                framestoRead = (mAllocBytes / (2 * mRecord->channelCount()));
            }

            if(mTempBuf.i16 && framestoRead > 0) {
                //read only if you have valid data
                size_t bytesRead = mRecord->read(mTempBuf.i16, framestoRead);
                size_t framesRead = 0;
                ALOGV("event_new_pos, new pos %d, frames to read %d\n", \
                        position, framestoRead);
                ALOGV("bytes read = %d \n", bytesRead);
                if(bytesRead > 0){
                    framesRead = (bytesRead / (2 * mRecord->channelCount()));
                    mPrevPosition += framesRead;
                    mTempBuf.size = bytesRead;
                    mTempBuf.frameCount = framesRead;
                    dataCallback(mTempBuf);
                } else {
                    ALOGE("EVENT_NEW_POS did not return any data");
                }
            } else {
                ALOGE("Init error");
            }
            break;
        }
        case AudioRecord::EVENT_OVERRUN: {
            ALOGW("AudioRecord reported overrun!");
            break;
        }
        default:
            // does nothing
            break;
    }
    return;
}

void AudioSource::queueInputBuffer_l(MediaBuffer *buffer, int64_t timeUs) {
    if (mRecPaused) {
        if (!mBuffersReceived.empty()) {