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

Commit b00edc38 authored by jiabin's avatar jiabin
Browse files

Add format conversion in AudioRecord.

In audio flinger, it is required that the client's format matches the
hardware format to get fast mode. However, format conversion is not a
time consuming operation. In that case, adding format conversion in
AudioRecord can help the client get fast mode if only format is
different from the hardware one. This can help improve latency.

Test: atest AudioRecordTest, capture audio in fast/non-fast mode
Bug: 79156275
Bug: 188843084
Change-Id: I1baaa9a6054bb84412c31a159c6d25ee498822cf
parent f9b5b733
Loading
Loading
Loading
Loading
+28 −8
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <android-base/macros.h>
#include <sys/resource.h>

#include <audio_utils/format.h>
#include <audiomanager/AudioManager.h>
#include <audiomanager/IAudioManager.h>
#include <binder/Binder.h>
@@ -858,6 +859,10 @@ status_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch)
    mRoutedDeviceId = output.selectedDeviceId;
    mSessionId = output.sessionId;
    mSampleRate = output.sampleRate;
    mServerConfig = output.serverConfig;
    mServerFrameSize = audio_bytes_per_frame(
            audio_channel_count_from_in_mask(mServerConfig.channel_mask), mServerConfig.format);
    mServerSampleSize = audio_bytes_per_sample(mServerConfig.format);

    if (output.cblk == 0) {
        ALOGE("%s(%d): Could not get control block", __func__, mPortId);
@@ -921,6 +926,10 @@ status_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch)
                mNotificationFramesReq, output.notificationFrameCount, output.frameCount);
    }
    mNotificationFramesAct = (uint32_t)output.notificationFrameCount;
    if (mServerConfig.format != mFormat && mCbf != nullptr) {
        mFormatConversionBufRaw = std::make_unique<uint8_t[]>(mNotificationFramesAct * mFrameSize);
        mFormatConversionBuffer.raw = mFormatConversionBufRaw.get();
    }

    //mInput != input includes the case where mInput == AUDIO_IO_HANDLE_NONE for first creation
    if (mDeviceCallback != 0) {
@@ -947,7 +956,7 @@ status_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch)
    }

    // update proxy
    mProxy = new AudioRecordClientProxy(cblk, buffers, mFrameCount, mFrameSize);
    mProxy = new AudioRecordClientProxy(cblk, buffers, mFrameCount, mServerFrameSize);
    mProxy->setEpoch(epoch);
    mProxy->setMinimum(mNotificationFramesAct);

@@ -1077,7 +1086,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, const struct timespec *r
    } while ((status == DEAD_OBJECT) && (tryCounter-- > 0));

    audioBuffer->frameCount = buffer.mFrameCount;
    audioBuffer->size = buffer.mFrameCount * mFrameSize;
    audioBuffer->size = buffer.mFrameCount * mServerFrameSize;
    audioBuffer->raw = buffer.mRaw;
    audioBuffer->sequence = oldSequence;
    if (nonContig != NULL) {
@@ -1090,7 +1099,7 @@ void AudioRecord::releaseBuffer(const Buffer* audioBuffer)
{
    // FIXME add error checking on mode, by adding an internal version

    size_t stepCount = audioBuffer->size / mFrameSize;
    size_t stepCount = audioBuffer->frameCount;
    if (stepCount == 0) {
        return;
    }
@@ -1152,8 +1161,9 @@ ssize_t AudioRecord::read(void* buffer, size_t userSize, bool blocking)
            return ssize_t(err);
        }

        size_t bytesRead = audioBuffer.size;
        memcpy(buffer, audioBuffer.i8, bytesRead);
        size_t bytesRead = audioBuffer.frameCount * mFrameSize;
        memcpy_by_audio_format(buffer, mFormat, audioBuffer.raw, mServerConfig.format,
                               audioBuffer.size / mServerSampleSize);
        buffer = ((char *) buffer) + bytesRead;
        userSize -= bytesRead;
        read += bytesRead;
@@ -1350,9 +1360,19 @@ nsecs_t AudioRecord::processAudioBuffer()
            }
        }

        size_t reqSize = audioBuffer.size;
        mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
        size_t readSize = audioBuffer.size;
        Buffer* buffer = &audioBuffer;
        if (mServerConfig.format != mFormat) {
            buffer = &mFormatConversionBuffer;
            buffer->frameCount = audioBuffer.frameCount;
            buffer->size = buffer->frameCount * mFrameSize;
            buffer->sequence = audioBuffer.sequence;
            memcpy_by_audio_format(buffer->raw, mFormat, audioBuffer.raw,
                                   mServerConfig.format, audioBuffer.size / mServerSampleSize);
        }

        size_t reqSize = buffer->size;
        mCbf(EVENT_MORE_DATA, mUserData, buffer);
        size_t readSize = buffer->size;

        // Validate on returned size
        if (ssize_t(readSize) < 0 || readSize > reqSize) {
+4 −0
Original line number Diff line number Diff line
@@ -195,6 +195,8 @@ IAudioFlinger::CreateRecordOutput::toAidl() const {
    aidl.buffers = VALUE_OR_RETURN(legacy2aidl_NullableIMemory_SharedFileRegion(buffers));
    aidl.portId = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(portId));
    aidl.audioRecord = audioRecord;
    aidl.serverConfig = VALUE_OR_RETURN(
            legacy2aidl_audio_config_base_t_AudioConfigBase(serverConfig, true /*isInput*/));
    return aidl;
}

@@ -215,6 +217,8 @@ IAudioFlinger::CreateRecordOutput::fromAidl(
    legacy.buffers = VALUE_OR_RETURN(aidl2legacy_NullableSharedFileRegion_IMemory(aidl.buffers));
    legacy.portId = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_port_handle_t(aidl.portId));
    legacy.audioRecord = aidl.audioRecord;
    legacy.serverConfig = VALUE_OR_RETURN(
            aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.serverConfig, true /*isInput*/));
    return legacy;
}

+2 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.media;

import android.media.AudioConfigBase;
import android.media.IAudioRecord;
import android.media.SharedFileRegion;

@@ -43,4 +44,5 @@ parcelable CreateRecordResponse {
    int portId;
    /** The newly created record. */
    @nullable IAudioRecord audioRecord;
    AudioConfigBase serverConfig;
}
+7 −0
Original line number Diff line number Diff line
@@ -760,6 +760,13 @@ private:
    bool                    mTimestampRetrogradePositionReported = false; // reduce log spam
    bool                    mTimestampRetrogradeTimeReported = false;     // reduce log spam

    // Format conversion. Maybe needed for adding fast tracks whose format is different from server.
    audio_config_base_t     mServerConfig;
    size_t                  mServerFrameSize;
    size_t                  mServerSampleSize;
    std::unique_ptr<uint8_t[]> mFormatConversionBufRaw;
    Buffer                  mFormatConversionBuffer;

private:
    class DeathNotifier : public IBinder::DeathRecipient {
    public:
+1 −0
Original line number Diff line number Diff line
@@ -166,6 +166,7 @@ public:
        sp<IMemory> buffers;
        audio_port_handle_t portId;
        sp<media::IAudioRecord> audioRecord;
        audio_config_base_t serverConfig;

        ConversionResult<media::CreateRecordResponse> toAidl() const;
        static ConversionResult<CreateRecordOutput>
Loading