12f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi/*
22f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi * Copyright (C) 2012 The Android Open Source Project
32f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi *
42f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
52f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi * you may not use this file except in compliance with the License.
62f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi * You may obtain a copy of the License at
72f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi *
82f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
92f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi *
102f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
112f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
122f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi * See the License for the specific language governing permissions and
142f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi * limitations under the License.
152f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi */
162f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
172f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi//#define LOG_NDEBUG 0
182f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi#define LOG_TAG "SoftFlacEncoder"
192f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi#include <utils/Log.h>
202f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
212f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi#include "SoftFlacEncoder.h"
222f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
232f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi#include <media/stagefright/foundation/ADebug.h>
242f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi#include <media/stagefright/MediaDefs.h>
252f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
262f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi#define FLAC_COMPRESSION_LEVEL_MIN     0
272f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi#define FLAC_COMPRESSION_LEVEL_DEFAULT 5
282f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi#define FLAC_COMPRESSION_LEVEL_MAX     8
292f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
3084333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#if LOG_NDEBUG
3184333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#define UNUSED_UNLESS_VERBOSE(x) (void)(x)
3284333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#else
3384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#define UNUSED_UNLESS_VERBOSE(x)
3484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#endif
3584333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber
362f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivinamespace android {
372f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
382f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivitemplate<class T>
392f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivistatic void InitOMXParams(T *params) {
402f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    params->nSize = sizeof(T);
412f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    params->nVersion.s.nVersionMajor = 1;
422f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    params->nVersion.s.nVersionMinor = 0;
432f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    params->nVersion.s.nRevision = 0;
442f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    params->nVersion.s.nStep = 0;
452f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi}
462f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
472f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel TriviSoftFlacEncoder::SoftFlacEncoder(
482f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        const char *name,
492f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        const OMX_CALLBACKTYPE *callbacks,
502f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        OMX_PTR appData,
512f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        OMX_COMPONENTTYPE **component)
522f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    : SimpleSoftOMXComponent(name, callbacks, appData, component),
532f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi      mSignalledError(false),
542f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi      mNumChannels(1),
552f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi      mSampleRate(44100),
562f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi      mCompressionLevel(FLAC_COMPRESSION_LEVEL_DEFAULT),
572f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi      mEncoderWriteData(false),
582f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi      mEncoderReturnedEncodedData(false),
592f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi      mEncoderReturnedNbBytes(0),
602f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi      mInputBufferPcm32(NULL)
612f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi#ifdef WRITE_FLAC_HEADER_IN_FIRST_BUFFER
622f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi      , mHeaderOffset(0)
632f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi      , mWroteHeader(false)
642f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi#endif
652f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi{
662f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    ALOGV("SoftFlacEncoder::SoftFlacEncoder(name=%s)", name);
672f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    initPorts();
682f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
692f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    mFlacStreamEncoder = FLAC__stream_encoder_new();
702f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    if (mFlacStreamEncoder == NULL) {
712f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        ALOGE("SoftFlacEncoder::SoftFlacEncoder(name=%s) error instantiating FLAC encoder", name);
722f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        mSignalledError = true;
732f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    }
742f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
752f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    if (!mSignalledError) { // no use allocating input buffer if we had an error above
762f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        mInputBufferPcm32 = (FLAC__int32*) malloc(sizeof(FLAC__int32) * 2 * kMaxNumSamplesPerFrame);
772f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        if (mInputBufferPcm32 == NULL) {
782f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            ALOGE("SoftFlacEncoder::SoftFlacEncoder(name=%s) error allocating internal input buffer", name);
792f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            mSignalledError = true;
802f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        }
812f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    }
822f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi}
832f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
842f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel TriviSoftFlacEncoder::~SoftFlacEncoder() {
852f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    ALOGV("SoftFlacEncoder::~SoftFlacEncoder()");
862f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    if (mFlacStreamEncoder != NULL) {
872f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        FLAC__stream_encoder_delete(mFlacStreamEncoder);
882f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        mFlacStreamEncoder = NULL;
892f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    }
902f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    free(mInputBufferPcm32);
912f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    mInputBufferPcm32 = NULL;
922f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi}
932f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
942f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel TriviOMX_ERRORTYPE SoftFlacEncoder::initCheck() const {
952f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    if (mSignalledError) {
962f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        if (mFlacStreamEncoder == NULL) {
972f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            ALOGE("initCheck() failed due to NULL encoder");
982f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        } else if (mInputBufferPcm32 == NULL) {
992f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            ALOGE("initCheck() failed due to error allocating internal input buffer");
1002f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        }
1012f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        return OMX_ErrorUndefined;
1022f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    } else {
1032f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        return SimpleSoftOMXComponent::initCheck();
1042f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    }
1052f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi}
1062f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
1072f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivivoid SoftFlacEncoder::initPorts() {
1082f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    ALOGV("SoftFlacEncoder::initPorts()");
1092f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
1102f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    OMX_PARAM_PORTDEFINITIONTYPE def;
1112f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    InitOMXParams(&def);
1122f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
1132f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    // configure input port of the encoder
1142f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.nPortIndex = 0;
1152f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.eDir = OMX_DirInput;
1162f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.nBufferCountMin = kNumBuffers;// TODO verify that 1 is enough
1172f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.nBufferCountActual = def.nBufferCountMin;
118eb8709e3c65b59e85b882b5ca8710068708671beAndreas Huber    def.nBufferSize = kMaxInputBufferSize;
1192f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.bEnabled = OMX_TRUE;
1202f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.bPopulated = OMX_FALSE;
1212f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.eDomain = OMX_PortDomainAudio;
1222f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.bBuffersContiguous = OMX_FALSE;
1232f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.nBufferAlignment = 2;
1242f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
1252f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
1262f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.format.audio.pNativeRender = NULL;
1272f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
1282f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
1292f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
1302f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    addPort(def);
1312f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
1322f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    // configure output port of the encoder
1332f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.nPortIndex = 1;
1342f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.eDir = OMX_DirOutput;
1352f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.nBufferCountMin = kNumBuffers;// TODO verify that 1 is enough
1362f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.nBufferCountActual = def.nBufferCountMin;
1372f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.nBufferSize = kMaxOutputBufferSize;
1382f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.bEnabled = OMX_TRUE;
1392f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.bPopulated = OMX_FALSE;
1402f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.eDomain = OMX_PortDomainAudio;
1412f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.bBuffersContiguous = OMX_FALSE;
1422f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.nBufferAlignment = 1;
1432f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
1442f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.format.audio.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_AUDIO_FLAC);
1452f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.format.audio.pNativeRender = NULL;
1462f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
1472f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    def.format.audio.eEncoding = OMX_AUDIO_CodingFLAC;
1482f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
1492f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    addPort(def);
1502f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi}
1512f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
1522f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel TriviOMX_ERRORTYPE SoftFlacEncoder::internalGetParameter(
1532f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        OMX_INDEXTYPE index, OMX_PTR params) {
1542f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    ALOGV("SoftFlacEncoder::internalGetParameter(index=0x%x)", index);
1552f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
1562f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    switch (index) {
1572f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        case OMX_IndexParamAudioPcm:
1582f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        {
1592f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
1602f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
1612f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
1622f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            if (pcmParams->nPortIndex > 1) {
1632f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                return OMX_ErrorUndefined;
1642f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            }
1652f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
1662f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            pcmParams->eNumData = OMX_NumericalDataSigned;
1672f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            pcmParams->eEndian = OMX_EndianBig;
1682f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            pcmParams->bInterleaved = OMX_TRUE;
1692f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            pcmParams->nBitPerSample = 16;
1702f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
1712f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
1722f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
1732f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
1742f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            pcmParams->nChannels = mNumChannels;
1752f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            pcmParams->nSamplingRate = mSampleRate;
1762f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
1772f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            return OMX_ErrorNone;
1782f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        }
1792f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
1802f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        case OMX_IndexParamAudioFlac:
1812f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        {
1822f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            OMX_AUDIO_PARAM_FLACTYPE *flacParams = (OMX_AUDIO_PARAM_FLACTYPE *)params;
1832f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            flacParams->nCompressionLevel = mCompressionLevel;
1842f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            flacParams->nChannels = mNumChannels;
1852f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            flacParams->nSampleRate = mSampleRate;
1862f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            return OMX_ErrorNone;
1872f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        }
1882f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
1892f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        default:
1902f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            return SimpleSoftOMXComponent::internalGetParameter(index, params);
1912f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    }
1922f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi}
1932f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
1942f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel TriviOMX_ERRORTYPE SoftFlacEncoder::internalSetParameter(
1952f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        OMX_INDEXTYPE index, const OMX_PTR params) {
1962f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    switch (index) {
1972f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        case OMX_IndexParamAudioPcm:
1982f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        {
1992f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            ALOGV("SoftFlacEncoder::internalSetParameter(OMX_IndexParamAudioPcm)");
2002f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
2012f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
2022f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            if (pcmParams->nPortIndex != 0 && pcmParams->nPortIndex != 1) {
2032f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                ALOGE("SoftFlacEncoder::internalSetParameter() Error #1");
2042f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                return OMX_ErrorUndefined;
2052f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            }
2062f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
2072f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            if (pcmParams->nChannels < 1 || pcmParams->nChannels > 2) {
2082f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                return OMX_ErrorUndefined;
2092f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            }
2102f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
2112f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            mNumChannels = pcmParams->nChannels;
2122f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            mSampleRate = pcmParams->nSamplingRate;
21366fe2e9ee30bcb4161bc487ec63d2ae4a05f4051Glenn Kasten            ALOGV("will encode %d channels at %dHz", mNumChannels, mSampleRate);
2142f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
2152f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            return configureEncoder();
2162f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        }
2172f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
2182f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        case OMX_IndexParamStandardComponentRole:
2192f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        {
2202f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            ALOGV("SoftFlacEncoder::internalSetParameter(OMX_IndexParamStandardComponentRole)");
2212f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
2222f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                (const OMX_PARAM_COMPONENTROLETYPE *)params;
2232f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
2242f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            if (strncmp((const char *)roleParams->cRole,
2252f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                    "audio_encoder.flac",
2262f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                    OMX_MAX_STRINGNAME_SIZE - 1)) {
2272f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                ALOGE("SoftFlacEncoder::internalSetParameter(OMX_IndexParamStandardComponentRole)"
2282f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                        "error");
2292f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                return OMX_ErrorUndefined;
2302f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            }
2312f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
2322f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            return OMX_ErrorNone;
2332f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        }
2342f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
2352f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        case OMX_IndexParamAudioFlac:
2362f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        {
2372f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            // used only for setting the compression level
2382f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            OMX_AUDIO_PARAM_FLACTYPE *flacParams = (OMX_AUDIO_PARAM_FLACTYPE *)params;
2392f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            mCompressionLevel = flacParams->nCompressionLevel; // range clamping done inside encoder
2402f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            return OMX_ErrorNone;
2412f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        }
2422f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
243eb8709e3c65b59e85b882b5ca8710068708671beAndreas Huber        case OMX_IndexParamPortDefinition:
244eb8709e3c65b59e85b882b5ca8710068708671beAndreas Huber        {
245eb8709e3c65b59e85b882b5ca8710068708671beAndreas Huber            OMX_PARAM_PORTDEFINITIONTYPE *defParams =
246eb8709e3c65b59e85b882b5ca8710068708671beAndreas Huber                (OMX_PARAM_PORTDEFINITIONTYPE *)params;
247eb8709e3c65b59e85b882b5ca8710068708671beAndreas Huber
248eb8709e3c65b59e85b882b5ca8710068708671beAndreas Huber            if (defParams->nPortIndex == 0) {
249eb8709e3c65b59e85b882b5ca8710068708671beAndreas Huber                if (defParams->nBufferSize > kMaxInputBufferSize) {
250b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross                    ALOGE("Input buffer size must be at most %d bytes",
251eb8709e3c65b59e85b882b5ca8710068708671beAndreas Huber                        kMaxInputBufferSize);
252eb8709e3c65b59e85b882b5ca8710068708671beAndreas Huber                    return OMX_ErrorUnsupportedSetting;
253eb8709e3c65b59e85b882b5ca8710068708671beAndreas Huber                }
254eb8709e3c65b59e85b882b5ca8710068708671beAndreas Huber            }
255eb8709e3c65b59e85b882b5ca8710068708671beAndreas Huber
256eb8709e3c65b59e85b882b5ca8710068708671beAndreas Huber            // fall through
257eb8709e3c65b59e85b882b5ca8710068708671beAndreas Huber        }
258eb8709e3c65b59e85b882b5ca8710068708671beAndreas Huber
2592f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        default:
2602f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            ALOGV("SoftFlacEncoder::internalSetParameter(default)");
2612f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            return SimpleSoftOMXComponent::internalSetParameter(index, params);
2622f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    }
2632f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi}
2642f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
2652f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivivoid SoftFlacEncoder::onQueueFilled(OMX_U32 portIndex) {
26684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber    UNUSED_UNLESS_VERBOSE(portIndex);
26766fe2e9ee30bcb4161bc487ec63d2ae4a05f4051Glenn Kasten    ALOGV("SoftFlacEncoder::onQueueFilled(portIndex=%d)", portIndex);
2682f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
2692f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    if (mSignalledError) {
2702f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        return;
2712f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    }
2722f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
2732f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    List<BufferInfo *> &inQueue = getPortQueue(0);
2742f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    List<BufferInfo *> &outQueue = getPortQueue(1);
2752f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
2762f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    while (!inQueue.empty() && !outQueue.empty()) {
2772f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        BufferInfo *inInfo = *inQueue.begin();
2782f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
2792f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
2802f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        BufferInfo *outInfo = *outQueue.begin();
2812f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
2822f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
2832f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
2842f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            inQueue.erase(inQueue.begin());
2852f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            inInfo->mOwnedByUs = false;
2862f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            notifyEmptyBufferDone(inHeader);
2872f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
2882f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            outHeader->nFilledLen = 0;
2892f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
2902f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
2912f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            outQueue.erase(outQueue.begin());
2922f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            outInfo->mOwnedByUs = false;
2932f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            notifyFillBufferDone(outHeader);
2942f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
2952f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            return;
2962f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        }
2972f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
298eb8709e3c65b59e85b882b5ca8710068708671beAndreas Huber        if (inHeader->nFilledLen > kMaxInputBufferSize) {
29966fe2e9ee30bcb4161bc487ec63d2ae4a05f4051Glenn Kasten            ALOGE("input buffer too large (%d).", inHeader->nFilledLen);
3002f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            mSignalledError = true;
3012f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
3022f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            return;
3032f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        }
3042f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
3052f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        assert(mNumChannels != 0);
3062f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        mEncoderWriteData = true;
3072f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        mEncoderReturnedEncodedData = false;
3082f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        mEncoderReturnedNbBytes = 0;
3092f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        mCurrentInputTimeStamp = inHeader->nTimeStamp;
3102f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
3112f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        const unsigned nbInputFrames = inHeader->nFilledLen / (2 * mNumChannels);
3122f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        const unsigned nbInputSamples = inHeader->nFilledLen / 2;
3132f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        const OMX_S16 * const pcm16 = reinterpret_cast<OMX_S16 *>(inHeader->pBuffer);
3142f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
315eb8709e3c65b59e85b882b5ca8710068708671beAndreas Huber        CHECK_LE(nbInputSamples, 2 * kMaxNumSamplesPerFrame);
3162f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        for (unsigned i=0 ; i < nbInputSamples ; i++) {
3172f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
3182f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        }
3192f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        ALOGV(" about to encode %u samples per channel", nbInputFrames);
3202f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        FLAC__bool ok = FLAC__stream_encoder_process_interleaved(
3212f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                        mFlacStreamEncoder,
3222f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                        mInputBufferPcm32,
3232f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                        nbInputFrames /*samples per channel*/ );
3242f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
3252f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        if (ok) {
3262f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            if (mEncoderReturnedEncodedData && (mEncoderReturnedNbBytes != 0)) {
3272f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                ALOGV(" dequeueing buffer on output port after writing data");
3282f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                outInfo->mOwnedByUs = false;
3292f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                outQueue.erase(outQueue.begin());
3302f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                outInfo = NULL;
3312f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                notifyFillBufferDone(outHeader);
3322f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                outHeader = NULL;
3332f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                mEncoderReturnedEncodedData = false;
3342f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            } else {
3352f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                ALOGV(" encoder process_interleaved returned without data to write");
3362f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            }
3372f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        } else {
3382f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            ALOGE(" error encountered during encoding");
3392f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            mSignalledError = true;
3402f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
3412f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            return;
3422f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        }
3432f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
3442f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        inInfo->mOwnedByUs = false;
3452f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        inQueue.erase(inQueue.begin());
3462f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        inInfo = NULL;
3472f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        notifyEmptyBufferDone(inHeader);
3482f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        inHeader = NULL;
3492f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    }
3502f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi}
3512f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
3522f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel TriviFLAC__StreamEncoderWriteStatus SoftFlacEncoder::onEncodedFlacAvailable(
3532f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            const FLAC__byte buffer[],
35484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber            size_t bytes, unsigned samples,
35584333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber            unsigned current_frame) {
35684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber    UNUSED_UNLESS_VERBOSE(current_frame);
357b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross    ALOGV("SoftFlacEncoder::onEncodedFlacAvailable(bytes=%zu, samples=%u, curr_frame=%u)",
3582f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            bytes, samples, current_frame);
3592f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
3602f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi#ifdef WRITE_FLAC_HEADER_IN_FIRST_BUFFER
3612f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    if (samples == 0) {
362b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross        ALOGI(" saving %zu bytes of header", bytes);
3632f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        memcpy(mHeader + mHeaderOffset, buffer, bytes);
3642f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        mHeaderOffset += bytes;// will contain header size when finished receiving header
3652f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
3662f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    }
3672f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
3682f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi#endif
3692f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
3702f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    if ((samples == 0) || !mEncoderWriteData) {
3712f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        // called by the encoder because there's header data to save, but it's not the role
3722f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        // of this component (unless WRITE_FLAC_HEADER_IN_FIRST_BUFFER is defined)
373b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross        ALOGV("ignoring %zu bytes of header data (samples=%d)", bytes, samples);
3742f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
3752f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    }
3762f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
3772f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    List<BufferInfo *> &outQueue = getPortQueue(1);
3782f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    CHECK(!outQueue.empty());
3792f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    BufferInfo *outInfo = *outQueue.begin();
3802f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
3812f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
3822f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi#ifdef WRITE_FLAC_HEADER_IN_FIRST_BUFFER
3832f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    if (!mWroteHeader) {
3842f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        ALOGI(" writing %d bytes of header on output port", mHeaderOffset);
3852f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        memcpy(outHeader->pBuffer + outHeader->nOffset + outHeader->nFilledLen,
3862f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                mHeader, mHeaderOffset);
3872f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        outHeader->nFilledLen += mHeaderOffset;
3882f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        outHeader->nOffset    += mHeaderOffset;
3892f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        mWroteHeader = true;
3902f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    }
3912f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi#endif
3922f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
3932f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    // write encoded data
394b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross    ALOGV(" writing %zu bytes of encoded data on output port", bytes);
3952f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    if (bytes > outHeader->nAllocLen - outHeader->nOffset - outHeader->nFilledLen) {
396b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross        ALOGE(" not enough space left to write encoded data, dropping %zu bytes", bytes);
3972f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        // a fatal error would stop the encoding
3982f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
3992f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    }
4002f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    memcpy(outHeader->pBuffer + outHeader->nOffset, buffer, bytes);
4012f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
4022f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    outHeader->nTimeStamp = mCurrentInputTimeStamp;
4032f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    outHeader->nOffset = 0;
4042f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    outHeader->nFilledLen += bytes;
4052f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    outHeader->nFlags = 0;
4062f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
4072f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    mEncoderReturnedEncodedData = true;
4082f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    mEncoderReturnedNbBytes += bytes;
4092f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
4102f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
4112f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi}
4122f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
4132f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
4142f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel TriviOMX_ERRORTYPE SoftFlacEncoder::configureEncoder() {
41566fe2e9ee30bcb4161bc487ec63d2ae4a05f4051Glenn Kasten    ALOGV("SoftFlacEncoder::configureEncoder() numChannel=%d, sampleRate=%d",
4162f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            mNumChannels, mSampleRate);
4172f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
4182f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    if (mSignalledError || (mFlacStreamEncoder == NULL)) {
4192f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        ALOGE("can't configure encoder: no encoder or invalid state");
4202f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        return OMX_ErrorInvalidState;
4212f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    }
4222f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
4232f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    FLAC__bool ok = true;
4242f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    FLAC__StreamEncoderInitStatus initStatus = FLAC__STREAM_ENCODER_INIT_STATUS_OK;
4252f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    ok = ok && FLAC__stream_encoder_set_channels(mFlacStreamEncoder, mNumChannels);
4262f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    ok = ok && FLAC__stream_encoder_set_sample_rate(mFlacStreamEncoder, mSampleRate);
4272f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, 16);
4282f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    ok = ok && FLAC__stream_encoder_set_compression_level(mFlacStreamEncoder,
4292f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            (unsigned)mCompressionLevel);
4302f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    ok = ok && FLAC__stream_encoder_set_verify(mFlacStreamEncoder, false);
4312f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    if (!ok) { goto return_result; }
4322f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
4332f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    ok &= FLAC__STREAM_ENCODER_INIT_STATUS_OK ==
4342f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            FLAC__stream_encoder_init_stream(mFlacStreamEncoder,
4352f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                    flacEncoderWriteCallback    /*write_callback*/,
4362f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                    NULL /*seek_callback*/,
4372f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                    NULL /*tell_callback*/,
4382f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                    NULL /*metadata_callback*/,
4392f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi                    (void *) this /*client_data*/);
4402f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
4412f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivireturn_result:
4422f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    if (ok) {
4432f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        ALOGV("encoder successfully configured");
4442f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        return OMX_ErrorNone;
4452f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    } else {
4462f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        ALOGE("unknown error when configuring encoder");
4472f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        return OMX_ErrorUndefined;
4482f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    }
4492f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi}
4502f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
4512f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
4522f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi// static
4532f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel TriviFLAC__StreamEncoderWriteStatus SoftFlacEncoder::flacEncoderWriteCallback(
45484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber            const FLAC__StreamEncoder * /* encoder */,
45584333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber            const FLAC__byte buffer[],
45684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber            size_t bytes,
45784333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber            unsigned samples,
45884333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber            unsigned current_frame,
45984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber            void *client_data) {
4602f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    return ((SoftFlacEncoder*) client_data)->onEncodedFlacAvailable(
4612f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi            buffer, bytes, samples, current_frame);
4622f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi}
4632f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
4642f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi}  // namespace android
4652f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
4662f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
4672f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Triviandroid::SoftOMXComponent *createSoftOMXComponent(
4682f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        const char *name, const OMX_CALLBACKTYPE *callbacks,
4692f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
4702f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi    return new android::SoftFlacEncoder(name, callbacks, appData, component);
4712f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi}
4722f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi
473