SoftFlacEncoder.cpp revision 84333e0475bc911adc16417f4ca327c975cf6c36
15a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines/*
25a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines * Copyright (C) 2012 The Android Open Source Project
35a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines *
45a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines * Licensed under the Apache License, Version 2.0 (the "License");
55a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines * you may not use this file except in compliance with the License.
65a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines * You may obtain a copy of the License at
75a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines *
85a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines *      http://www.apache.org/licenses/LICENSE-2.0
95a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines *
105a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines * Unless required by applicable law or agreed to in writing, software
115a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines * distributed under the License is distributed on an "AS IS" BASIS,
125a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines * See the License for the specific language governing permissions and
145a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines * limitations under the License.
155a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines */
165a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
175a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines//#define LOG_NDEBUG 0
185a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines#define LOG_TAG "SoftFlacEncoder"
195a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines#include <utils/Log.h>
205a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
215a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines#include "SoftFlacEncoder.h"
225a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
235a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines#include <media/stagefright/foundation/ADebug.h>
245a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines#include <media/stagefright/MediaDefs.h>
255a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
265a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines#define FLAC_COMPRESSION_LEVEL_MIN     0
275a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines#define FLAC_COMPRESSION_LEVEL_DEFAULT 5
28e3af53b643677c40d228ffd3624cf259f4dc68edTim Murray#define FLAC_COMPRESSION_LEVEL_MAX     8
295a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
30e3af53b643677c40d228ffd3624cf259f4dc68edTim Murray#if LOG_NDEBUG
31e3af53b643677c40d228ffd3624cf259f4dc68edTim Murray#define UNUSED_UNLESS_VERBOSE(x) (void)(x)
32e3af53b643677c40d228ffd3624cf259f4dc68edTim Murray#else
335a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines#define UNUSED_UNLESS_VERBOSE(x)
345a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines#endif
355a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
365a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hinesnamespace android {
375a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
385a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hinestemplate<class T>
395a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hinesstatic void InitOMXParams(T *params) {
405a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    params->nSize = sizeof(T);
415a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    params->nVersion.s.nVersionMajor = 1;
425a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    params->nVersion.s.nVersionMinor = 0;
435a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    params->nVersion.s.nRevision = 0;
445a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    params->nVersion.s.nStep = 0;
455a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines}
46ddceab9a001f07a3395226c5e06e3b420720af0fJason Sams
47ddceab9a001f07a3395226c5e06e3b420720af0fJason SamsSoftFlacEncoder::SoftFlacEncoder(
485a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        const char *name,
495a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        const OMX_CALLBACKTYPE *callbacks,
505a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        OMX_PTR appData,
515a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        OMX_COMPONENTTYPE **component)
525a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    : SimpleSoftOMXComponent(name, callbacks, appData, component),
535a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines      mSignalledError(false),
545a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines      mNumChannels(1),
555a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines      mSampleRate(44100),
565a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines      mCompressionLevel(FLAC_COMPRESSION_LEVEL_DEFAULT),
575a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines      mEncoderWriteData(false),
585a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines      mEncoderReturnedEncodedData(false),
595a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines      mEncoderReturnedNbBytes(0),
605a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines      mInputBufferPcm32(NULL)
6161656a7c6fc13421679d0a1cdf8b5b861e286892Jason Sams#ifdef WRITE_FLAC_HEADER_IN_FIRST_BUFFER
6261656a7c6fc13421679d0a1cdf8b5b861e286892Jason Sams      , mHeaderOffset(0)
6361656a7c6fc13421679d0a1cdf8b5b861e286892Jason Sams      , mWroteHeader(false)
6461656a7c6fc13421679d0a1cdf8b5b861e286892Jason Sams#endif
6561656a7c6fc13421679d0a1cdf8b5b861e286892Jason Sams{
665a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    ALOGV("SoftFlacEncoder::SoftFlacEncoder(name=%s)", name);
675a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    initPorts();
685a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
695a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    mFlacStreamEncoder = FLAC__stream_encoder_new();
703ff0fe77fdba8ad4a920dc27157d8c1786bb3661Jason Sams    if (mFlacStreamEncoder == NULL) {
715a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        ALOGE("SoftFlacEncoder::SoftFlacEncoder(name=%s) error instantiating FLAC encoder", name);
725a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        mSignalledError = true;
735a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    }
745a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
755a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    if (!mSignalledError) { // no use allocating input buffer if we had an error above
765a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        mInputBufferPcm32 = (FLAC__int32*) malloc(sizeof(FLAC__int32) * 2 * kMaxNumSamplesPerFrame);
775a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        if (mInputBufferPcm32 == NULL) {
785a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            ALOGE("SoftFlacEncoder::SoftFlacEncoder(name=%s) error allocating internal input buffer", name);
795a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            mSignalledError = true;
805a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        }
815a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    }
825a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines}
835a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
845a47020542c52af3e879c1cd67674ca979ff0a18Stephen HinesSoftFlacEncoder::~SoftFlacEncoder() {
855a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    ALOGV("SoftFlacEncoder::~SoftFlacEncoder()");
865a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    if (mFlacStreamEncoder != NULL) {
875a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        FLAC__stream_encoder_delete(mFlacStreamEncoder);
885a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        mFlacStreamEncoder = NULL;
895a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    }
905a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    free(mInputBufferPcm32);
915a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    mInputBufferPcm32 = NULL;
925a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines}
935a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
945a47020542c52af3e879c1cd67674ca979ff0a18Stephen HinesOMX_ERRORTYPE SoftFlacEncoder::initCheck() const {
955a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    if (mSignalledError) {
965a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        if (mFlacStreamEncoder == NULL) {
975a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            ALOGE("initCheck() failed due to NULL encoder");
985a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        } else if (mInputBufferPcm32 == NULL) {
995a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            ALOGE("initCheck() failed due to error allocating internal input buffer");
1005a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        }
1015a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        return OMX_ErrorUndefined;
1025a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    } else {
1035a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        return SimpleSoftOMXComponent::initCheck();
1045a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    }
1055a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines}
1065a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
1075a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hinesvoid SoftFlacEncoder::initPorts() {
1085a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    ALOGV("SoftFlacEncoder::initPorts()");
1095a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
1105a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    OMX_PARAM_PORTDEFINITIONTYPE def;
1115a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    InitOMXParams(&def);
1125a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
1135a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    // configure input port of the encoder
1145a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.nPortIndex = 0;
1155a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.eDir = OMX_DirInput;
1165a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.nBufferCountMin = kNumBuffers;// TODO verify that 1 is enough
1175a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.nBufferCountActual = def.nBufferCountMin;
1185a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.nBufferSize = kMaxInputBufferSize;
1195a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.bEnabled = OMX_TRUE;
1205a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.bPopulated = OMX_FALSE;
1215a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.eDomain = OMX_PortDomainAudio;
1225a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.bBuffersContiguous = OMX_FALSE;
1235a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.nBufferAlignment = 2;
1245a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
1255a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
1265a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.format.audio.pNativeRender = NULL;
1275a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
1285a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
1295a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
1305a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    addPort(def);
1315a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
1323ff0fe77fdba8ad4a920dc27157d8c1786bb3661Jason Sams    // configure output port of the encoder
1335a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.nPortIndex = 1;
1345a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.eDir = OMX_DirOutput;
1355a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.nBufferCountMin = kNumBuffers;// TODO verify that 1 is enough
1365a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.nBufferCountActual = def.nBufferCountMin;
1375a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.nBufferSize = kMaxOutputBufferSize;
1385a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.bEnabled = OMX_TRUE;
1395a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.bPopulated = OMX_FALSE;
1405a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.eDomain = OMX_PortDomainAudio;
1415a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.bBuffersContiguous = OMX_FALSE;
1425a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.nBufferAlignment = 1;
1435a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
1445a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.format.audio.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_AUDIO_FLAC);
1455a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.format.audio.pNativeRender = NULL;
1465a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
1475a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    def.format.audio.eEncoding = OMX_AUDIO_CodingFLAC;
1485a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
1495a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    addPort(def);
1505a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines}
1515a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
152e3af53b643677c40d228ffd3624cf259f4dc68edTim MurrayOMX_ERRORTYPE SoftFlacEncoder::internalGetParameter(
1535a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        OMX_INDEXTYPE index, OMX_PTR params) {
154e3af53b643677c40d228ffd3624cf259f4dc68edTim Murray    ALOGV("SoftFlacEncoder::internalGetParameter(index=0x%x)", index);
155e3af53b643677c40d228ffd3624cf259f4dc68edTim Murray
156e3af53b643677c40d228ffd3624cf259f4dc68edTim Murray    switch (index) {
1575a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        case OMX_IndexParamAudioPcm:
1585a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        {
1595a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
1605a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
1615a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
1625a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            if (pcmParams->nPortIndex > 1) {
1635a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines                return OMX_ErrorUndefined;
1645a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            }
1655a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
1665a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            pcmParams->eNumData = OMX_NumericalDataSigned;
1675a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            pcmParams->eEndian = OMX_EndianBig;
1685a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            pcmParams->bInterleaved = OMX_TRUE;
1695a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            pcmParams->nBitPerSample = 16;
1705a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
1715a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
1725a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
1735a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
1745a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            pcmParams->nChannels = mNumChannels;
1755a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            pcmParams->nSamplingRate = mSampleRate;
1765a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
1775a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            return OMX_ErrorNone;
1785a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        }
1795a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
1805a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        case OMX_IndexParamAudioFlac:
1815a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        {
1825a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            OMX_AUDIO_PARAM_FLACTYPE *flacParams = (OMX_AUDIO_PARAM_FLACTYPE *)params;
1835a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            flacParams->nCompressionLevel = mCompressionLevel;
1845a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            flacParams->nChannels = mNumChannels;
1855a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            flacParams->nSampleRate = mSampleRate;
1865a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            return OMX_ErrorNone;
1875a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        }
188e3af53b643677c40d228ffd3624cf259f4dc68edTim Murray
1895a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        default:
190e3af53b643677c40d228ffd3624cf259f4dc68edTim Murray            return SimpleSoftOMXComponent::internalGetParameter(index, params);
191e3af53b643677c40d228ffd3624cf259f4dc68edTim Murray    }
192e3af53b643677c40d228ffd3624cf259f4dc68edTim Murray}
1935a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
1945a47020542c52af3e879c1cd67674ca979ff0a18Stephen HinesOMX_ERRORTYPE SoftFlacEncoder::internalSetParameter(
1955a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        OMX_INDEXTYPE index, const OMX_PTR params) {
1965a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    switch (index) {
1975a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        case OMX_IndexParamAudioPcm:
1985a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        {
1995a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            ALOGV("SoftFlacEncoder::internalSetParameter(OMX_IndexParamAudioPcm)");
2005a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
2015a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
2025a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            if (pcmParams->nPortIndex != 0 && pcmParams->nPortIndex != 1) {
2035a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines                ALOGE("SoftFlacEncoder::internalSetParameter() Error #1");
2045a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines                return OMX_ErrorUndefined;
2055a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            }
2065a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
2075a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            if (pcmParams->nChannels < 1 || pcmParams->nChannels > 2) {
2085a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines                return OMX_ErrorUndefined;
2095a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            }
2105a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
2115a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            mNumChannels = pcmParams->nChannels;
2125a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            mSampleRate = pcmParams->nSamplingRate;
2135a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            ALOGV("will encode %ld channels at %ldHz", mNumChannels, mSampleRate);
2145a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
2155a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            return configureEncoder();
2165a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        }
2175a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
2185a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        case OMX_IndexParamStandardComponentRole:
2195a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        {
2205a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            ALOGV("SoftFlacEncoder::internalSetParameter(OMX_IndexParamStandardComponentRole)");
2215a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
2225a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines                (const OMX_PARAM_COMPONENTROLETYPE *)params;
2235a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
2245a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            if (strncmp((const char *)roleParams->cRole,
2255a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines                    "audio_encoder.flac",
2265a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines                    OMX_MAX_STRINGNAME_SIZE - 1)) {
2275a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines                ALOGE("SoftFlacEncoder::internalSetParameter(OMX_IndexParamStandardComponentRole)"
2285a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines                        "error");
2295a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines                return OMX_ErrorUndefined;
230e3af53b643677c40d228ffd3624cf259f4dc68edTim Murray            }
2315a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
232e3af53b643677c40d228ffd3624cf259f4dc68edTim Murray            return OMX_ErrorNone;
233e3af53b643677c40d228ffd3624cf259f4dc68edTim Murray        }
234e3af53b643677c40d228ffd3624cf259f4dc68edTim Murray
2355a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        case OMX_IndexParamAudioFlac:
2365a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        {
2375a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            // used only for setting the compression level
2385a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            OMX_AUDIO_PARAM_FLACTYPE *flacParams = (OMX_AUDIO_PARAM_FLACTYPE *)params;
2395a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            mCompressionLevel = flacParams->nCompressionLevel; // range clamping done inside encoder
2405a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            return OMX_ErrorNone;
2415a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        }
2425a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
2435a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        case OMX_IndexParamPortDefinition:
2445a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        {
2455a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            OMX_PARAM_PORTDEFINITIONTYPE *defParams =
2465a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines                (OMX_PARAM_PORTDEFINITIONTYPE *)params;
2475a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
2485a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            if (defParams->nPortIndex == 0) {
2495a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines                if (defParams->nBufferSize > kMaxInputBufferSize) {
2505a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines                    ALOGE("Input buffer size must be at most %zu bytes",
2515a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines                        kMaxInputBufferSize);
2523ff0fe77fdba8ad4a920dc27157d8c1786bb3661Jason Sams                    return OMX_ErrorUnsupportedSetting;
2535a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines                }
2545a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            }
2555a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
2565a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            // fall through
2575a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        }
2585a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
2595a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        default:
2605a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            ALOGV("SoftFlacEncoder::internalSetParameter(default)");
2615a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            return SimpleSoftOMXComponent::internalSetParameter(index, params);
2625a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    }
2635a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines}
2645a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
2655a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hinesvoid SoftFlacEncoder::onQueueFilled(OMX_U32 portIndex) {
2665a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    UNUSED_UNLESS_VERBOSE(portIndex);
2675a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    ALOGV("SoftFlacEncoder::onQueueFilled(portIndex=%ld)", portIndex);
2685a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
2695a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    if (mSignalledError) {
2705a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        return;
2715a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    }
2725a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
2735a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    List<BufferInfo *> &inQueue = getPortQueue(0);
2745a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    List<BufferInfo *> &outQueue = getPortQueue(1);
2755a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
2765a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines    while (!inQueue.empty() && !outQueue.empty()) {
2775a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        BufferInfo *inInfo = *inQueue.begin();
2785a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
2795a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
2805a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        BufferInfo *outInfo = *outQueue.begin();
2815a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
2825a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
2835a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
2845a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            inQueue.erase(inQueue.begin());
2855a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines            inInfo->mOwnedByUs = false;
2863ff0fe77fdba8ad4a920dc27157d8c1786bb3661Jason Sams            notifyEmptyBufferDone(inHeader);
2875a47020542c52af3e879c1cd67674ca979ff0a18Stephen Hines
288            outHeader->nFilledLen = 0;
289            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
290
291            outQueue.erase(outQueue.begin());
292            outInfo->mOwnedByUs = false;
293            notifyFillBufferDone(outHeader);
294
295            return;
296        }
297
298        if (inHeader->nFilledLen > kMaxInputBufferSize) {
299            ALOGE("input buffer too large (%ld).", inHeader->nFilledLen);
300            mSignalledError = true;
301            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
302            return;
303        }
304
305        assert(mNumChannels != 0);
306        mEncoderWriteData = true;
307        mEncoderReturnedEncodedData = false;
308        mEncoderReturnedNbBytes = 0;
309        mCurrentInputTimeStamp = inHeader->nTimeStamp;
310
311        const unsigned nbInputFrames = inHeader->nFilledLen / (2 * mNumChannels);
312        const unsigned nbInputSamples = inHeader->nFilledLen / 2;
313        const OMX_S16 * const pcm16 = reinterpret_cast<OMX_S16 *>(inHeader->pBuffer);
314
315        CHECK_LE(nbInputSamples, 2 * kMaxNumSamplesPerFrame);
316        for (unsigned i=0 ; i < nbInputSamples ; i++) {
317            mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
318        }
319        ALOGV(" about to encode %u samples per channel", nbInputFrames);
320        FLAC__bool ok = FLAC__stream_encoder_process_interleaved(
321                        mFlacStreamEncoder,
322                        mInputBufferPcm32,
323                        nbInputFrames /*samples per channel*/ );
324
325        if (ok) {
326            if (mEncoderReturnedEncodedData && (mEncoderReturnedNbBytes != 0)) {
327                ALOGV(" dequeueing buffer on output port after writing data");
328                outInfo->mOwnedByUs = false;
329                outQueue.erase(outQueue.begin());
330                outInfo = NULL;
331                notifyFillBufferDone(outHeader);
332                outHeader = NULL;
333                mEncoderReturnedEncodedData = false;
334            } else {
335                ALOGV(" encoder process_interleaved returned without data to write");
336            }
337        } else {
338            ALOGE(" error encountered during encoding");
339            mSignalledError = true;
340            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
341            return;
342        }
343
344        inInfo->mOwnedByUs = false;
345        inQueue.erase(inQueue.begin());
346        inInfo = NULL;
347        notifyEmptyBufferDone(inHeader);
348        inHeader = NULL;
349    }
350}
351
352FLAC__StreamEncoderWriteStatus SoftFlacEncoder::onEncodedFlacAvailable(
353            const FLAC__byte buffer[],
354            size_t bytes, unsigned samples,
355            unsigned current_frame) {
356    UNUSED_UNLESS_VERBOSE(current_frame);
357    ALOGV("SoftFlacEncoder::onEncodedFlacAvailable(bytes=%d, samples=%d, curr_frame=%d)",
358            bytes, samples, current_frame);
359
360#ifdef WRITE_FLAC_HEADER_IN_FIRST_BUFFER
361    if (samples == 0) {
362        ALOGI(" saving %d bytes of header", bytes);
363        memcpy(mHeader + mHeaderOffset, buffer, bytes);
364        mHeaderOffset += bytes;// will contain header size when finished receiving header
365        return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
366    }
367
368#endif
369
370    if ((samples == 0) || !mEncoderWriteData) {
371        // called by the encoder because there's header data to save, but it's not the role
372        // of this component (unless WRITE_FLAC_HEADER_IN_FIRST_BUFFER is defined)
373        ALOGV("ignoring %d bytes of header data (samples=%d)", bytes, samples);
374        return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
375    }
376
377    List<BufferInfo *> &outQueue = getPortQueue(1);
378    CHECK(!outQueue.empty());
379    BufferInfo *outInfo = *outQueue.begin();
380    OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
381
382#ifdef WRITE_FLAC_HEADER_IN_FIRST_BUFFER
383    if (!mWroteHeader) {
384        ALOGI(" writing %d bytes of header on output port", mHeaderOffset);
385        memcpy(outHeader->pBuffer + outHeader->nOffset + outHeader->nFilledLen,
386                mHeader, mHeaderOffset);
387        outHeader->nFilledLen += mHeaderOffset;
388        outHeader->nOffset    += mHeaderOffset;
389        mWroteHeader = true;
390    }
391#endif
392
393    // write encoded data
394    ALOGV(" writing %d bytes of encoded data on output port", bytes);
395    if (bytes > outHeader->nAllocLen - outHeader->nOffset - outHeader->nFilledLen) {
396        ALOGE(" not enough space left to write encoded data, dropping %u bytes", bytes);
397        // a fatal error would stop the encoding
398        return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
399    }
400    memcpy(outHeader->pBuffer + outHeader->nOffset, buffer, bytes);
401
402    outHeader->nTimeStamp = mCurrentInputTimeStamp;
403    outHeader->nOffset = 0;
404    outHeader->nFilledLen += bytes;
405    outHeader->nFlags = 0;
406
407    mEncoderReturnedEncodedData = true;
408    mEncoderReturnedNbBytes += bytes;
409
410    return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
411}
412
413
414OMX_ERRORTYPE SoftFlacEncoder::configureEncoder() {
415    ALOGV("SoftFlacEncoder::configureEncoder() numChannel=%ld, sampleRate=%ld",
416            mNumChannels, mSampleRate);
417
418    if (mSignalledError || (mFlacStreamEncoder == NULL)) {
419        ALOGE("can't configure encoder: no encoder or invalid state");
420        return OMX_ErrorInvalidState;
421    }
422
423    FLAC__bool ok = true;
424    FLAC__StreamEncoderInitStatus initStatus = FLAC__STREAM_ENCODER_INIT_STATUS_OK;
425    ok = ok && FLAC__stream_encoder_set_channels(mFlacStreamEncoder, mNumChannels);
426    ok = ok && FLAC__stream_encoder_set_sample_rate(mFlacStreamEncoder, mSampleRate);
427    ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, 16);
428    ok = ok && FLAC__stream_encoder_set_compression_level(mFlacStreamEncoder,
429            (unsigned)mCompressionLevel);
430    ok = ok && FLAC__stream_encoder_set_verify(mFlacStreamEncoder, false);
431    if (!ok) { goto return_result; }
432
433    ok &= FLAC__STREAM_ENCODER_INIT_STATUS_OK ==
434            FLAC__stream_encoder_init_stream(mFlacStreamEncoder,
435                    flacEncoderWriteCallback    /*write_callback*/,
436                    NULL /*seek_callback*/,
437                    NULL /*tell_callback*/,
438                    NULL /*metadata_callback*/,
439                    (void *) this /*client_data*/);
440
441return_result:
442    if (ok) {
443        ALOGV("encoder successfully configured");
444        return OMX_ErrorNone;
445    } else {
446        ALOGE("unknown error when configuring encoder");
447        return OMX_ErrorUndefined;
448    }
449}
450
451
452// static
453FLAC__StreamEncoderWriteStatus SoftFlacEncoder::flacEncoderWriteCallback(
454            const FLAC__StreamEncoder * /* encoder */,
455            const FLAC__byte buffer[],
456            size_t bytes,
457            unsigned samples,
458            unsigned current_frame,
459            void *client_data) {
460    return ((SoftFlacEncoder*) client_data)->onEncodedFlacAvailable(
461            buffer, bytes, samples, current_frame);
462}
463
464}  // namespace android
465
466
467android::SoftOMXComponent *createSoftOMXComponent(
468        const char *name, const OMX_CALLBACKTYPE *callbacks,
469        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
470    return new android::SoftFlacEncoder(name, callbacks, appData, component);
471}
472
473