Home | History | Annotate | Download | only in dec
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 //#define LOG_NDEBUG 0
     18 #define LOG_TAG "SoftFlacDecoder"
     19 #include <utils/Log.h>
     20 
     21 #include "SoftFlacDecoder.h"
     22 #include <OMX_AudioExt.h>
     23 #include <OMX_IndexExt.h>
     24 
     25 #include <cutils/properties.h>
     26 #include <media/stagefright/foundation/ADebug.h>
     27 #include <media/stagefright/MediaErrors.h>
     28 #include <utils/misc.h>
     29 
     30 namespace android {
     31 
     32 template<class T>
     33 static void InitOMXParams(T *params) {
     34     params->nSize = sizeof(T);
     35     params->nVersion.s.nVersionMajor = 1;
     36     params->nVersion.s.nVersionMinor = 0;
     37     params->nVersion.s.nRevision = 0;
     38     params->nVersion.s.nStep = 0;
     39 }
     40 
     41 SoftFlacDecoder::SoftFlacDecoder(
     42         const char *name,
     43         const OMX_CALLBACKTYPE *callbacks,
     44         OMX_PTR appData,
     45         OMX_COMPONENTTYPE **component)
     46     : SimpleSoftOMXComponent(name, callbacks, appData, component),
     47       mFLACDecoder(NULL),
     48       mInputBufferCount(0),
     49       mHasStreamInfo(false),
     50       mSignalledError(false),
     51       mSawInputEOS(false),
     52       mFinishedDecoder(false),
     53       mOutputPortSettingsChange(NONE) {
     54     ALOGV("ctor:");
     55     memset(&mStreamInfo, 0, sizeof(mStreamInfo));
     56     initPorts();
     57     initDecoder();
     58 }
     59 
     60 SoftFlacDecoder::~SoftFlacDecoder() {
     61     ALOGV("dtor:");
     62     delete mFLACDecoder;
     63 }
     64 
     65 void SoftFlacDecoder::initPorts() {
     66     ALOGV("initPorts:");
     67     OMX_PARAM_PORTDEFINITIONTYPE def;
     68     InitOMXParams(&def);
     69 
     70     def.nPortIndex = 0;
     71     def.eDir = OMX_DirInput;
     72     def.nBufferCountMin = kNumInputBuffers;
     73     def.nBufferCountActual = def.nBufferCountMin;
     74     def.nBufferSize = 32768;
     75     def.bEnabled = OMX_TRUE;
     76     def.bPopulated = OMX_FALSE;
     77     def.eDomain = OMX_PortDomainAudio;
     78     def.bBuffersContiguous = OMX_FALSE;
     79     def.nBufferAlignment = 1;
     80 
     81     def.format.audio.cMIMEType = const_cast<char *>("audio/flac");
     82     def.format.audio.pNativeRender = NULL;
     83     def.format.audio.bFlagErrorConcealment = OMX_FALSE;
     84     def.format.audio.eEncoding = OMX_AUDIO_CodingFLAC;
     85 
     86     addPort(def);
     87 
     88     def.nPortIndex = 1;
     89     def.eDir = OMX_DirOutput;
     90     def.nBufferCountMin = kNumOutputBuffers;
     91     def.nBufferCountActual = def.nBufferCountMin;
     92     def.nBufferSize = 4096 * FLACDecoder::kMaxChannels;
     93     def.bEnabled = OMX_TRUE;
     94     def.bPopulated = OMX_FALSE;
     95     def.eDomain = OMX_PortDomainAudio;
     96     def.bBuffersContiguous = OMX_FALSE;
     97     def.nBufferAlignment = 2;
     98 
     99     def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
    100     def.format.audio.pNativeRender = NULL;
    101     def.format.audio.bFlagErrorConcealment = OMX_FALSE;
    102     def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
    103 
    104     addPort(def);
    105 }
    106 
    107 void SoftFlacDecoder::initDecoder() {
    108     ALOGV("initDecoder:");
    109     mFLACDecoder = FLACDecoder::Create();
    110     if (mFLACDecoder == NULL) {
    111         ALOGE("initDecoder: failed to create FLACDecoder");
    112         mSignalledError = true;
    113     }
    114 }
    115 
    116 OMX_ERRORTYPE SoftFlacDecoder::initCheck() const {
    117     if (mSignalledError) {
    118         if (mFLACDecoder == NULL) {
    119             ALOGE("initCheck: failed due to NULL encoder");
    120             return OMX_ErrorDynamicResourcesUnavailable;
    121         }
    122         return OMX_ErrorUndefined;
    123     }
    124 
    125     return SimpleSoftOMXComponent::initCheck();
    126 }
    127 
    128 OMX_ERRORTYPE SoftFlacDecoder::internalGetParameter(
    129         OMX_INDEXTYPE index, OMX_PTR params) {
    130     ALOGV("internalGetParameter: index(%x)", index);
    131     switch ((OMX_U32)index) {
    132         case OMX_IndexParamAudioPortFormat:
    133         {
    134             OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
    135                 (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
    136 
    137             if (!isValidOMXParam(formatParams)) {
    138                 return OMX_ErrorBadParameter;
    139             }
    140 
    141             if (formatParams->nPortIndex > 1) {
    142                 return OMX_ErrorUndefined;
    143             }
    144 
    145             if (formatParams->nIndex > 0) {
    146                 return OMX_ErrorNoMore;
    147             }
    148 
    149             formatParams->eEncoding =
    150                 (formatParams->nPortIndex == 0)
    151                     ? OMX_AUDIO_CodingFLAC : OMX_AUDIO_CodingPCM;
    152 
    153             return OMX_ErrorNone;
    154         }
    155         case OMX_IndexParamAudioFlac:
    156         {
    157             OMX_AUDIO_PARAM_FLACTYPE *flacParams =
    158                 (OMX_AUDIO_PARAM_FLACTYPE *)params;
    159 
    160             if (!isValidOMXParam(flacParams)) {
    161                 ALOGE("internalGetParameter(OMX_IndexParamAudioFlac): invalid omx params");
    162                 return OMX_ErrorBadParameter;
    163             }
    164 
    165             if (flacParams->nPortIndex != 0) {
    166                 ALOGE("internalGetParameter(OMX_IndexParamAudioFlac): bad port index");
    167                 return OMX_ErrorBadPortIndex;
    168             }
    169 
    170             flacParams->nCompressionLevel = 0;
    171 
    172             if (isConfigured()) {
    173                 flacParams->nChannels = mStreamInfo.channels;
    174                 flacParams->nSampleRate = mStreamInfo.sample_rate;
    175             } else {
    176                 flacParams->nChannels = 1;
    177                 flacParams->nSampleRate = 44100;
    178             }
    179 
    180             return OMX_ErrorNone;
    181         }
    182 
    183         case OMX_IndexParamAudioPcm:
    184         {
    185             OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
    186                 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
    187 
    188             if (!isValidOMXParam(pcmParams)) {
    189                 ALOGE("internalGetParameter(OMX_IndexParamAudioPcm): invalid omx params");
    190                 return OMX_ErrorBadParameter;
    191             }
    192 
    193             if (pcmParams->nPortIndex != 1) {
    194                 ALOGE("internalGetParameter(OMX_IndexParamAudioPcm): bad port index");
    195                 return OMX_ErrorBadPortIndex;
    196             }
    197 
    198             pcmParams->eNumData = OMX_NumericalDataSigned;
    199             pcmParams->eEndian = OMX_EndianBig;
    200             pcmParams->bInterleaved = OMX_TRUE;
    201             pcmParams->nBitPerSample = 16;
    202             pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
    203             pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
    204             pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
    205             pcmParams->eChannelMapping[2] = OMX_AUDIO_ChannelCF;
    206             pcmParams->eChannelMapping[3] = OMX_AUDIO_ChannelLFE;
    207             pcmParams->eChannelMapping[4] = OMX_AUDIO_ChannelLS;
    208             pcmParams->eChannelMapping[5] = OMX_AUDIO_ChannelRS;
    209 
    210             if (isConfigured()) {
    211                 pcmParams->nChannels = mStreamInfo.channels;
    212                 pcmParams->nSamplingRate = mStreamInfo.sample_rate;
    213             } else {
    214                 pcmParams->nChannels = 1;
    215                 pcmParams->nSamplingRate = 44100;
    216             }
    217 
    218             return OMX_ErrorNone;
    219         }
    220 
    221         default:
    222             return SimpleSoftOMXComponent::internalGetParameter(index, params);
    223     }
    224 }
    225 
    226 OMX_ERRORTYPE SoftFlacDecoder::internalSetParameter(
    227         OMX_INDEXTYPE index, const OMX_PTR params) {
    228     ALOGV("internalSetParameter: index(%x)", (int)index);
    229     switch ((int)index) {
    230         case OMX_IndexParamStandardComponentRole:
    231         {
    232             const OMX_PARAM_COMPONENTROLETYPE *roleParams =
    233                 (const OMX_PARAM_COMPONENTROLETYPE *)params;
    234 
    235             if (!isValidOMXParam(roleParams)) {
    236                 return OMX_ErrorBadParameter;
    237             }
    238 
    239             if (strncmp((const char *)roleParams->cRole,
    240                         "audio_decoder.flac",
    241                         OMX_MAX_STRINGNAME_SIZE - 1) != 0) {
    242                 return OMX_ErrorInvalidComponentName;
    243             }
    244 
    245             return OMX_ErrorNone;
    246         }
    247 
    248         case OMX_IndexParamAudioPortFormat:
    249         {
    250             const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
    251                 (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
    252 
    253             if (!isValidOMXParam(formatParams)) {
    254                 return OMX_ErrorBadParameter;
    255             }
    256 
    257             if (formatParams->nPortIndex > 1) {
    258                 return OMX_ErrorUndefined;
    259             }
    260 
    261             if ((formatParams->nPortIndex == 0
    262                         && formatParams->eEncoding != OMX_AUDIO_CodingFLAC)
    263                 || (formatParams->nPortIndex == 1
    264                         && formatParams->eEncoding != OMX_AUDIO_CodingPCM)) {
    265                 return OMX_ErrorUndefined;
    266             }
    267 
    268             return OMX_ErrorNone;
    269         }
    270 
    271         case OMX_IndexParamAudioPcm:
    272         {
    273             const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
    274                 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
    275 
    276             if (!isValidOMXParam(pcmParams)) {
    277                 return OMX_ErrorBadParameter;
    278             }
    279 
    280             if (pcmParams->nPortIndex != 1) {
    281                 return OMX_ErrorBadPortIndex;
    282             }
    283 
    284             return OMX_ErrorNone;
    285         }
    286 
    287         default:
    288             return SimpleSoftOMXComponent::internalSetParameter(index, params);
    289     }
    290 }
    291 
    292 bool SoftFlacDecoder::isConfigured() const {
    293     return mHasStreamInfo;
    294 }
    295 
    296 void SoftFlacDecoder::onQueueFilled(OMX_U32 /* portIndex */) {
    297     if (mSignalledError || mOutputPortSettingsChange != NONE) {
    298         return;
    299     }
    300 
    301     List<BufferInfo *> &inQueue = getPortQueue(0);
    302     List<BufferInfo *> &outQueue = getPortQueue(1);
    303 
    304     ALOGV("onQueueFilled %d/%d:", inQueue.empty(), outQueue.empty());
    305     while ((!inQueue.empty() || mSawInputEOS) && !outQueue.empty() && !mFinishedDecoder) {
    306         BufferInfo *outInfo = *outQueue.begin();
    307         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
    308         short *outBuffer = reinterpret_cast<short *>(outHeader->pBuffer + outHeader->nOffset);
    309         size_t outBufferSize = outHeader->nAllocLen - outHeader->nOffset;
    310         int64_t timeStamp = 0;
    311 
    312         if (!inQueue.empty()) {
    313             BufferInfo *inInfo = *inQueue.begin();
    314             OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
    315             uint8_t* inBuffer = inHeader->pBuffer + inHeader->nOffset;
    316             uint32_t inBufferLength = inHeader->nFilledLen;
    317             ALOGV("input: %u bytes", inBufferLength);
    318             if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
    319                 ALOGV("saw EOS");
    320                 mSawInputEOS = true;
    321                 if (mInputBufferCount == 0 && inHeader->nFilledLen == 0) {
    322                     // first buffer was empty and EOS: signal EOS on output and return
    323                     ALOGV("empty first EOS");
    324                     outHeader->nFilledLen = 0;
    325                     outHeader->nTimeStamp = inHeader->nTimeStamp;
    326                     outHeader->nFlags = OMX_BUFFERFLAG_EOS;
    327                     outInfo->mOwnedByUs = false;
    328                     outQueue.erase(outQueue.begin());
    329                     notifyFillBufferDone(outHeader);
    330                     mFinishedDecoder = true;
    331                     inInfo->mOwnedByUs = false;
    332                     inQueue.erase(inQueue.begin());
    333                     notifyEmptyBufferDone(inHeader);
    334                     return;
    335                 }
    336             }
    337 
    338             if (mInputBufferCount == 0 && !(inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
    339                 ALOGE("onQueueFilled: first buffer should have OMX_BUFFERFLAG_CODECCONFIG set");
    340                 inHeader->nFlags |= OMX_BUFFERFLAG_CODECCONFIG;
    341             }
    342             if ((inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) != 0) {
    343                 ALOGV("received config buffer of size %u", inBufferLength);
    344                 status_t decoderErr = mFLACDecoder->parseMetadata(inBuffer, inBufferLength);
    345                 mInputBufferCount++;
    346 
    347                 if (decoderErr != OK && decoderErr != WOULD_BLOCK) {
    348                     ALOGE("onQueueFilled: FLACDecoder parseMetaData returns error %d", decoderErr);
    349                     mSignalledError = true;
    350                     notify(OMX_EventError, OMX_ErrorStreamCorrupt, decoderErr, NULL);
    351                     return;
    352                 }
    353 
    354                 inInfo->mOwnedByUs = false;
    355                 inQueue.erase(inQueue.begin());
    356                 notifyEmptyBufferDone(inHeader);
    357 
    358                 if (decoderErr == WOULD_BLOCK) {
    359                     continue;
    360                 }
    361                 mStreamInfo = mFLACDecoder->getStreamInfo();
    362                 mHasStreamInfo = true;
    363 
    364                 // Only send out port settings changed event if both sample rate
    365                 // and numChannels are valid.
    366                 if (mStreamInfo.sample_rate && mStreamInfo.channels) {
    367                     ALOGD("onQueueFilled: initially configuring decoder: %d Hz, %d channels",
    368                         mStreamInfo.sample_rate, mStreamInfo.channels);
    369 
    370                     notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
    371                     mOutputPortSettingsChange = AWAITING_DISABLED;
    372                 }
    373                 return;
    374             }
    375 
    376             status_t decoderErr = mFLACDecoder->decodeOneFrame(
    377                     inBuffer, inBufferLength, outBuffer, &outBufferSize);
    378             if (decoderErr != OK) {
    379                 ALOGE("onQueueFilled: FLACDecoder decodeOneFrame returns error %d", decoderErr);
    380                 mSignalledError = true;
    381                 notify(OMX_EventError, OMX_ErrorStreamCorrupt, decoderErr, NULL);
    382                 return;
    383             }
    384 
    385             mInputBufferCount++;
    386             timeStamp = inHeader->nTimeStamp;
    387             inInfo->mOwnedByUs = false;
    388             inQueue.erase(inQueue.begin());
    389             notifyEmptyBufferDone(inHeader);
    390 
    391             if (outBufferSize == 0) {
    392                 ALOGV("no output, trying again");
    393                 continue;
    394             }
    395         } else if (mSawInputEOS) {
    396             status_t decoderErr = mFLACDecoder->decodeOneFrame(NULL, 0, outBuffer, &outBufferSize);
    397             mFinishedDecoder = true;
    398             if (decoderErr != OK) {
    399                 ALOGE("onQueueFilled: FLACDecoder finish returns error %d", decoderErr);
    400                 mSignalledError = true;
    401                 notify(OMX_EventError, OMX_ErrorStreamCorrupt, decoderErr, NULL);
    402                 return;
    403             }
    404             outHeader->nFlags = OMX_BUFFERFLAG_EOS;
    405         } else {
    406             // no more input buffers at this time, loop and see if there is more output
    407             continue;
    408         }
    409 
    410         outHeader->nFilledLen = outBufferSize;
    411         outHeader->nTimeStamp = timeStamp;
    412 
    413         outInfo->mOwnedByUs = false;
    414         outQueue.erase(outQueue.begin());
    415         notifyFillBufferDone(outHeader);
    416     }
    417 }
    418 
    419 void SoftFlacDecoder::onPortFlushCompleted(OMX_U32 portIndex) {
    420     ALOGV("onPortFlushCompleted: portIndex(%u)", portIndex);
    421     if (portIndex == 0) {
    422         drainDecoder();
    423     }
    424 }
    425 
    426 void SoftFlacDecoder::drainDecoder() {
    427     mFLACDecoder->flush();
    428     mSawInputEOS = false;
    429     mFinishedDecoder = false;
    430 }
    431 
    432 void SoftFlacDecoder::onReset() {
    433     ALOGV("onReset");
    434     drainDecoder();
    435 
    436     memset(&mStreamInfo, 0, sizeof(mStreamInfo));
    437     mHasStreamInfo = false;
    438     mInputBufferCount = 0;
    439     mSignalledError = false;
    440     mOutputPortSettingsChange = NONE;
    441 }
    442 
    443 void SoftFlacDecoder::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
    444     ALOGV("onPortEnableCompleted: portIndex(%u), enabled(%d)", portIndex, enabled);
    445     if (portIndex != 1) {
    446         return;
    447     }
    448 
    449     switch (mOutputPortSettingsChange) {
    450         case NONE:
    451             break;
    452 
    453         case AWAITING_DISABLED:
    454         {
    455             CHECK(!enabled);
    456             mOutputPortSettingsChange = AWAITING_ENABLED;
    457             PortInfo *info = editPortInfo(1 /* portIndex */);
    458             if (!info->mDef.bEnabled) {
    459                 info->mDef.nBufferSize = mStreamInfo.max_blocksize * mStreamInfo.channels * 2;
    460             }
    461             break;
    462         }
    463 
    464         default:
    465         {
    466             CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
    467             CHECK(enabled);
    468             mOutputPortSettingsChange = NONE;
    469             break;
    470         }
    471     }
    472 }
    473 
    474 }  // namespace android
    475 
    476 android::SoftOMXComponent *createSoftOMXComponent(
    477         const char *name, const OMX_CALLBACKTYPE *callbacks,
    478         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
    479     ALOGV("createSoftOMXComponent: flac decoder");
    480     return new android::SoftFlacDecoder(name, callbacks, appData, component);
    481 }
    482