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