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

Commit 1188a051 authored by Andy Hung's avatar Andy Hung
Browse files

FlacEncoder: Enable float support

Test: MediaCodecTest#testFlacIdentity
Bug: 122264366
Change-Id: Ic692ce0d5dc8358cbd173013c9d4f68b7e45a8ad
parent 9ed79de1
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -23,5 +23,8 @@ cc_library_shared {

    srcs: ["C2SoftFlacEnc.cpp"],

    static_libs: ["libFLAC"],
    static_libs: [
        "libaudioutils",
        "libFLAC",
    ],
}
+36 −12
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#define LOG_TAG "C2SoftFlacEnc"
#include <log/log.h>

#include <audio_utils/primitives.h>
#include <media/stagefright/foundation/MediaDefs.h>

#include <C2PlatformSupport.h>
@@ -72,11 +73,23 @@ public:
                DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
                .withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 4608))
                .build());

        addParameter(
                DefineParam(mPcmEncodingInfo, C2_PARAMKEY_PCM_ENCODING)
                .withDefault(new C2StreamPcmEncodingInfo::input(0u, C2Config::PCM_16))
                .withFields({C2F(mPcmEncodingInfo, value).oneOf({
                     C2Config::PCM_16,
                     // C2Config::PCM_8,
                     C2Config::PCM_FLOAT})
                })
                .withSetter((Setter<decltype(*mPcmEncodingInfo)>::StrictValueWithNoDeps))
                .build());
    }

    uint32_t getSampleRate() const { return mSampleRate->value; }
    uint32_t getChannelCount() const { return mChannelCount->value; }
    uint32_t getBitrate() const { return mBitrate->value; }
    int32_t getPcmEncodingInfo() const { return mPcmEncodingInfo->value; }

private:
    std::shared_ptr<C2StreamFormatConfig::input> mInputFormat;
@@ -87,6 +100,7 @@ private:
    std::shared_ptr<C2StreamChannelCountInfo::input> mChannelCount;
    std::shared_ptr<C2BitrateTuning::output> mBitrate;
    std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize;
    std::shared_ptr<C2StreamPcmEncodingInfo::input> mPcmEncodingInfo;
};
constexpr char COMPONENT_NAME[] = "c2.android.flac.encoder";

@@ -224,12 +238,15 @@ void C2SoftFlacEnc::process(
        mWroteHeader = true;
    }

    uint32_t sampleRate = mIntf->getSampleRate();
    uint32_t channelCount = mIntf->getChannelCount();
    uint64_t outTimeStamp = mProcessedSamples * 1000000ll / sampleRate;
    const uint32_t sampleRate = mIntf->getSampleRate();
    const uint32_t channelCount = mIntf->getChannelCount();
    const bool inputFloat = mIntf->getPcmEncodingInfo() == C2Config::PCM_FLOAT;
    const unsigned sampleSize = inputFloat ? sizeof(float) : sizeof(int16_t);
    const unsigned frameSize = channelCount * sampleSize;
    const uint64_t outTimeStamp = mProcessedSamples * 1000000ll / sampleRate;

    size_t outCapacity = inSize;
    outCapacity += mBlockSize * channelCount * sizeof(int16_t);
    outCapacity += mBlockSize * frameSize;

    C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
    c2_status_t err = pool->fetchLinearBlock(outCapacity, usage, &mOutputBlock);
@@ -250,15 +267,20 @@ void C2SoftFlacEnc::process(
    size_t inPos = 0;
    while (inPos < inSize) {
        const uint8_t *inPtr = rView.data() + inOffset;
        size_t processSize = MIN(kInBlockSize * channelCount * sizeof(int16_t), (inSize - inPos));
        const unsigned nbInputFrames = processSize / (channelCount * sizeof(int16_t));
        const unsigned nbInputSamples = processSize / sizeof(int16_t);
        const int16_t *pcm16 = reinterpret_cast<const int16_t *>(inPtr + inPos);
        ALOGV("about to encode %zu bytes", processSize);
        const size_t processSize = MIN(kInBlockSize * frameSize, (inSize - inPos));
        const unsigned nbInputFrames = processSize / frameSize;
        const unsigned nbInputSamples = processSize / sampleSize;

        ALOGV("about to encode %zu bytes", processSize);
        if (inputFloat) {
            const float * const pcmFloat = reinterpret_cast<const float *>(inPtr + inPos);
            memcpy_to_q8_23_from_float_with_clamp(mInputBufferPcm32, pcmFloat, nbInputSamples);
        } else {
            const int16_t * const pcm16 = reinterpret_cast<const int16_t *>(inPtr + inPos);
            for (unsigned i = 0; i < nbInputSamples; i++) {
                mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
            }
        }

        FLAC__bool ok = FLAC__stream_encoder_process_interleaved(
                mFlacStreamEncoder, mInputBufferPcm32, nbInputFrames);
@@ -342,10 +364,12 @@ status_t C2SoftFlacEnc::configureEncoder() {
        return UNKNOWN_ERROR;
    }

    const bool inputFloat = mIntf->getPcmEncodingInfo() == C2Config::PCM_FLOAT;
    const int bitsPerSample = inputFloat ? 24 : 16;
    FLAC__bool ok = true;
    ok = ok && FLAC__stream_encoder_set_channels(mFlacStreamEncoder, mIntf->getChannelCount());
    ok = ok && FLAC__stream_encoder_set_sample_rate(mFlacStreamEncoder, mIntf->getSampleRate());
    ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, 16);
    ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, bitsPerSample);
    ok = ok && FLAC__stream_encoder_set_compression_level(mFlacStreamEncoder, mCompressionLevel);
    ok = ok && FLAC__stream_encoder_set_verify(mFlacStreamEncoder, false);
    if (!ok) {
+4 −1
Original line number Diff line number Diff line
@@ -28,7 +28,10 @@ cc_library_shared {
    ],

    header_libs: ["libbase_headers"],
    static_libs: ["libFLAC"],
    static_libs: [
        "libaudioutils",
        "libFLAC",
    ],

    name: "libstagefright_soft_flacenc",
    vendor_available: true,
+45 −15
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@
#include <utils/Log.h>

#include "SoftFlacEncoder.h"

#include <audio_utils/primitives.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaDefs.h>

@@ -75,7 +75,9 @@ SoftFlacEncoder::SoftFlacEncoder(
    }

    if (!mSignalledError) { // no use allocating input buffer if we had an error above
        mInputBufferPcm32 = (FLAC__int32*) malloc(sizeof(FLAC__int32) * 2 * kMaxNumSamplesPerFrame);
        // 2x the pcm16 samples can exist with the same size as pcmFloat samples.
        mInputBufferPcm32 = (FLAC__int32*) malloc(
                sizeof(FLAC__int32) * kNumSamplesPerFrame * kMaxChannels * 2);
        if (mInputBufferPcm32 == NULL) {
            ALOGE("SoftFlacEncoder::SoftFlacEncoder(name=%s) error allocating internal input buffer", name);
            mSignalledError = true;
@@ -115,14 +117,14 @@ void SoftFlacEncoder::initPorts() {
    // configure input port of the encoder
    def.nPortIndex = 0;
    def.eDir = OMX_DirInput;
    def.nBufferCountMin = kNumBuffers;// TODO verify that 1 is enough
    def.nBufferCountMin = kNumBuffers;
    def.nBufferCountActual = def.nBufferCountMin;
    def.nBufferSize = kMaxInputBufferSize;
    def.bEnabled = OMX_TRUE;
    def.bPopulated = OMX_FALSE;
    def.eDomain = OMX_PortDomainAudio;
    def.bBuffersContiguous = OMX_FALSE;
    def.nBufferAlignment = 2;
    def.nBufferAlignment = sizeof(float);

    def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
    def.format.audio.pNativeRender = NULL;
@@ -134,7 +136,7 @@ void SoftFlacEncoder::initPorts() {
    // configure output port of the encoder
    def.nPortIndex = 1;
    def.eDir = OMX_DirOutput;
    def.nBufferCountMin = kNumBuffers;// TODO verify that 1 is enough
    def.nBufferCountMin = kNumBuffers;
    def.nBufferCountActual = def.nBufferCountMin;
    def.nBufferSize = kMaxOutputBufferSize;
    def.bEnabled = OMX_TRUE;
@@ -193,10 +195,10 @@ OMX_ERRORTYPE SoftFlacEncoder::internalGetParameter(
                return OMX_ErrorUndefined;
            }

            pcmParams->eNumData = OMX_NumericalDataSigned;
            pcmParams->eNumData = mNumericalData;
            pcmParams->eEndian = OMX_EndianBig;
            pcmParams->bInterleaved = OMX_TRUE;
            pcmParams->nBitPerSample = 16;
            pcmParams->nBitPerSample = mBitsPerSample;
            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
            pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
@@ -270,12 +272,26 @@ OMX_ERRORTYPE SoftFlacEncoder::internalSetParameter(
                return OMX_ErrorUndefined;
            }

            if (pcmParams->nChannels < 1 || pcmParams->nChannels > 2) {
            if (pcmParams->nChannels < 1 || pcmParams->nChannels > kMaxChannels) {
                return OMX_ErrorUndefined;
            }

            mNumChannels = pcmParams->nChannels;
            mSampleRate = pcmParams->nSamplingRate;

            if (pcmParams->eNumData == OMX_NumericalDataFloat && pcmParams->nBitPerSample == 32) {
                mNumericalData = OMX_NumericalDataFloat;
                mBitsPerSample = 32;
            } else if (pcmParams->eNumData == OMX_NumericalDataSigned
                     && pcmParams->nBitPerSample == 16) {
                mNumericalData = OMX_NumericalDataSigned;
                mBitsPerSample = 16;
            } else {
                ALOGE("%s: invalid eNumData %d, nBitsPerSample %d",
                        __func__, pcmParams->eNumData, pcmParams->nBitPerSample);
                return OMX_ErrorUndefined;
            }

            ALOGV("will encode %d channels at %dHz", mNumChannels, mSampleRate);

            return configureEncoder();
@@ -356,6 +372,10 @@ void SoftFlacEncoder::onQueueFilled(OMX_U32 portIndex) {
    List<BufferInfo *> &inQueue = getPortQueue(0);
    List<BufferInfo *> &outQueue = getPortQueue(1);

    const bool inputFloat = mNumericalData == OMX_NumericalDataFloat;
    const size_t sampleSize = inputFloat ? sizeof(float) : sizeof(int16_t);
    const size_t frameSize = sampleSize * mNumChannels;

    FLAC__bool ok = true;

    while ((!inQueue.empty() || mSawInputEOS) && !outQueue.empty() && !mSentOutputEOS) {
@@ -381,14 +401,22 @@ void SoftFlacEncoder::onQueueFilled(OMX_U32 portIndex) {
            mEncoderReturnedNbBytes = 0;
            mCurrentInputTimeStamp = inHeader->nTimeStamp;

            const unsigned nbInputFrames = inHeader->nFilledLen / (2 * mNumChannels);
            const unsigned nbInputSamples = inHeader->nFilledLen / 2;
            const OMX_S16 * const pcm16 = reinterpret_cast<OMX_S16 *>(inHeader->pBuffer);
            const unsigned nbInputFrames = inHeader->nFilledLen / frameSize;
            const unsigned nbInputSamples = inHeader->nFilledLen / sampleSize;

            CHECK_LE(nbInputSamples, 2 * kMaxNumSamplesPerFrame);
            for (unsigned i=0 ; i < nbInputSamples ; i++) {
            if (inputFloat) {
                CHECK_LE(nbInputSamples, kNumSamplesPerFrame * kMaxChannels);
                const float * const pcmFloat = reinterpret_cast<float *>(inHeader->pBuffer);
                 memcpy_to_q8_23_from_float_with_clamp(
                         mInputBufferPcm32, pcmFloat, nbInputSamples);
            } else {
                // note nbInputSamples may be 2x as large for pcm16 data.
                CHECK_LE(nbInputSamples, kNumSamplesPerFrame * kMaxChannels * 2);
                const int16_t * const pcm16 = reinterpret_cast<int16_t *>(inHeader->pBuffer);
                for (unsigned i = 0; i < nbInputSamples; ++i) {
                    mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
                }
            }
            ALOGV(" about to encode %u samples per channel", nbInputFrames);
            ok = FLAC__stream_encoder_process_interleaved(
                            mFlacStreamEncoder,
@@ -526,10 +554,12 @@ OMX_ERRORTYPE SoftFlacEncoder::configureEncoder() {
        return OMX_ErrorInvalidState;
    }

    const bool inputFloat = mNumericalData == OMX_NumericalDataFloat;
    const int codecBitsPerSample = inputFloat ? 24 : 16;
    FLAC__bool ok = true;
    ok = ok && FLAC__stream_encoder_set_channels(mFlacStreamEncoder, mNumChannels);
    ok = ok && FLAC__stream_encoder_set_sample_rate(mFlacStreamEncoder, mSampleRate);
    ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, 16);
    ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, codecBitsPerSample);
    ok = ok && FLAC__stream_encoder_set_compression_level(mFlacStreamEncoder,
            (unsigned)mCompressionLevel);
    ok = ok && FLAC__stream_encoder_set_verify(mFlacStreamEncoder, false);
+6 −2
Original line number Diff line number Diff line
@@ -45,8 +45,10 @@ protected:

private:
    const unsigned int kNumBuffers = 2;
    const unsigned int kMaxNumSamplesPerFrame = 1152;
    const unsigned int kMaxInputBufferSize = kMaxNumSamplesPerFrame * sizeof(int16_t) * 2;
    static constexpr unsigned int kMaxChannels = 2;
    static constexpr unsigned int kNumSamplesPerFrame = 1152;
    static constexpr unsigned int kMaxInputBufferSize =
            kNumSamplesPerFrame * kMaxChannels * sizeof(float);
    const unsigned int kMaxOutputBufferSize = 65536;    //TODO check if this can be reduced

    bool mSignalledError;
@@ -54,6 +56,8 @@ private:
    OMX_U32 mNumChannels;
    OMX_U32 mSampleRate;
    OMX_U32 mCompressionLevel;
    OMX_NUMERICALDATATYPE mNumericalData = OMX_NumericalDataSigned;
    OMX_U32 mBitsPerSample = 16;

    // should the data received by the callback be written to the output port
    bool        mEncoderWriteData;