Home | History | Annotate | Download | only in raw
      1 /*
      2  * Copyright (C) 2012 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 "SoftRaw"
     19 #include <utils/Log.h>
     20 
     21 #include "SoftRaw.h"
     22 
     23 #include <media/stagefright/foundation/ADebug.h>
     24 #include <media/stagefright/foundation/hexdump.h>
     25 
     26 namespace android {
     27 
     28 template<class T>
     29 static void InitOMXParams(T *params) {
     30     params->nSize = sizeof(T);
     31     params->nVersion.s.nVersionMajor = 1;
     32     params->nVersion.s.nVersionMinor = 0;
     33     params->nVersion.s.nRevision = 0;
     34     params->nVersion.s.nStep = 0;
     35 }
     36 
     37 SoftRaw::SoftRaw(
     38         const char *name,
     39         const OMX_CALLBACKTYPE *callbacks,
     40         OMX_PTR appData,
     41         OMX_COMPONENTTYPE **component)
     42     : SimpleSoftOMXComponent(name, callbacks, appData, component),
     43       mSignalledError(false),
     44       mChannelCount(2),
     45       mSampleRate(44100),
     46       mNumericalData(OMX_NumericalDataSigned),
     47       mBitsPerSample(16) {
     48     initPorts();
     49     CHECK_EQ(initDecoder(), (status_t)OK);
     50 }
     51 
     52 SoftRaw::~SoftRaw() {
     53 }
     54 
     55 void SoftRaw::initPorts() {
     56     OMX_PARAM_PORTDEFINITIONTYPE def;
     57     InitOMXParams(&def);
     58 
     59     def.nPortIndex = 0;
     60     def.eDir = OMX_DirInput;
     61     def.nBufferCountMin = kNumBuffers;
     62     def.nBufferCountActual = def.nBufferCountMin;
     63     def.nBufferSize = 64 * 1024;
     64     def.bEnabled = OMX_TRUE;
     65     def.bPopulated = OMX_FALSE;
     66     def.eDomain = OMX_PortDomainAudio;
     67     def.bBuffersContiguous = OMX_FALSE;
     68     def.nBufferAlignment = 1;
     69 
     70     def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
     71     def.format.audio.pNativeRender = NULL;
     72     def.format.audio.bFlagErrorConcealment = OMX_FALSE;
     73     def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
     74 
     75     addPort(def);
     76 
     77     def.nPortIndex = 1;
     78     def.eDir = OMX_DirOutput;
     79     def.nBufferCountMin = kNumBuffers;
     80     def.nBufferCountActual = def.nBufferCountMin;
     81     def.nBufferSize = 64 * 1024;
     82     def.bEnabled = OMX_TRUE;
     83     def.bPopulated = OMX_FALSE;
     84     def.eDomain = OMX_PortDomainAudio;
     85     def.bBuffersContiguous = OMX_FALSE;
     86     def.nBufferAlignment = 2;
     87 
     88     def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
     89     def.format.audio.pNativeRender = NULL;
     90     def.format.audio.bFlagErrorConcealment = OMX_FALSE;
     91     def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
     92 
     93     addPort(def);
     94 }
     95 
     96 status_t SoftRaw::initDecoder() {
     97     return OK;
     98 }
     99 
    100 OMX_ERRORTYPE SoftRaw::internalGetParameter(
    101         OMX_INDEXTYPE index, OMX_PTR params) {
    102     switch (index) {
    103         case OMX_IndexParamAudioPortFormat:
    104         {
    105             OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
    106                 (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
    107 
    108             if (!isValidOMXParam(formatParams)) {
    109                 return OMX_ErrorBadParameter;
    110             }
    111 
    112             if (formatParams->nPortIndex > 1) {
    113                 return OMX_ErrorUndefined;
    114             }
    115 
    116             if (formatParams->nIndex > 0) {
    117                 return OMX_ErrorNoMore;
    118             }
    119 
    120             formatParams->eEncoding = OMX_AUDIO_CodingPCM;
    121 
    122             return OMX_ErrorNone;
    123         }
    124 
    125         case OMX_IndexParamAudioPcm:
    126         {
    127             OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
    128                 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
    129 
    130             if (!isValidOMXParam(pcmParams)) {
    131                 return OMX_ErrorBadParameter;
    132             }
    133 
    134             if (pcmParams->nPortIndex != 0 && pcmParams->nPortIndex != 1) {
    135                 return OMX_ErrorUndefined;
    136             }
    137 
    138             pcmParams->eNumData = (OMX_NUMERICALDATATYPE)mNumericalData;
    139             pcmParams->eEndian = OMX_EndianBig;
    140             pcmParams->bInterleaved = OMX_TRUE;
    141             pcmParams->nBitPerSample = mBitsPerSample;
    142             pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
    143             pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
    144             pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
    145 
    146             pcmParams->nChannels = mChannelCount;
    147             pcmParams->nSamplingRate = mSampleRate;
    148 
    149             return OMX_ErrorNone;
    150         }
    151 
    152         default:
    153             return SimpleSoftOMXComponent::internalGetParameter(index, params);
    154     }
    155 }
    156 
    157 OMX_ERRORTYPE SoftRaw::internalSetParameter(
    158         OMX_INDEXTYPE index, const OMX_PTR params) {
    159     switch (index) {
    160         case OMX_IndexParamStandardComponentRole:
    161         {
    162             const OMX_PARAM_COMPONENTROLETYPE *roleParams =
    163                 (const OMX_PARAM_COMPONENTROLETYPE *)params;
    164 
    165             if (!isValidOMXParam(roleParams)) {
    166                 return OMX_ErrorBadParameter;
    167             }
    168 
    169             if (strncmp((const char *)roleParams->cRole,
    170                         "audio_decoder.raw",
    171                         OMX_MAX_STRINGNAME_SIZE - 1)) {
    172                 return OMX_ErrorUndefined;
    173             }
    174 
    175             return OMX_ErrorNone;
    176         }
    177 
    178         case OMX_IndexParamAudioPortFormat:
    179         {
    180             const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
    181                 (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
    182 
    183             if (!isValidOMXParam(formatParams)) {
    184                 return OMX_ErrorBadParameter;
    185             }
    186 
    187             if (formatParams->nPortIndex > 1) {
    188                 return OMX_ErrorUndefined;
    189             }
    190 
    191             if (formatParams->eEncoding != OMX_AUDIO_CodingPCM) {
    192                 return OMX_ErrorUndefined;
    193             }
    194 
    195             return OMX_ErrorNone;
    196         }
    197 
    198         case OMX_IndexParamAudioPcm:
    199         {
    200             const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
    201                 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
    202 
    203             if (!isValidOMXParam(pcmParams)) {
    204                 return OMX_ErrorBadParameter;
    205             }
    206 
    207             if (pcmParams->nPortIndex != 0) {
    208                 return OMX_ErrorUndefined;
    209             }
    210 
    211             mChannelCount = pcmParams->nChannels;
    212             mSampleRate = pcmParams->nSamplingRate;
    213             mNumericalData = pcmParams->eNumData;
    214             mBitsPerSample = pcmParams->nBitPerSample;
    215 
    216             return OMX_ErrorNone;
    217         }
    218 
    219         default:
    220         {
    221             OMX_ERRORTYPE err = SimpleSoftOMXComponent::internalSetParameter(
    222                     index, params);
    223             // In case inPort->mDef.nBufferSize changed, the output buffer size
    224             // should match the input buffer size.
    225             PortInfo *inPort = editPortInfo(0);
    226             PortInfo *outPort = editPortInfo(1);
    227             outPort->mDef.nBufferSize = inPort->mDef.nBufferSize;
    228             return err;
    229         }
    230     }
    231 }
    232 
    233 void SoftRaw::onQueueFilled(OMX_U32 /* portIndex */) {
    234     if (mSignalledError) {
    235         return;
    236     }
    237 
    238     List<BufferInfo *> &inQueue = getPortQueue(0);
    239     List<BufferInfo *> &outQueue = getPortQueue(1);
    240 
    241     while (!inQueue.empty() && !outQueue.empty()) {
    242         BufferInfo *inInfo = *inQueue.begin();
    243         OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
    244 
    245         BufferInfo *outInfo = *outQueue.begin();
    246         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
    247 
    248         CHECK_GE(outHeader->nAllocLen, inHeader->nFilledLen);
    249         memcpy(outHeader->pBuffer,
    250                inHeader->pBuffer + inHeader->nOffset,
    251                inHeader->nFilledLen);
    252 
    253         outHeader->nFlags = inHeader->nFlags;
    254         outHeader->nOffset = 0;
    255         outHeader->nFilledLen = inHeader->nFilledLen;
    256         outHeader->nTimeStamp = inHeader->nTimeStamp;
    257 
    258         bool sawEOS = (inHeader->nFlags & OMX_BUFFERFLAG_EOS) != 0;
    259 
    260         inQueue.erase(inQueue.begin());
    261         inInfo->mOwnedByUs = false;
    262         notifyEmptyBufferDone(inHeader);
    263 
    264         outQueue.erase(outQueue.begin());
    265         outInfo->mOwnedByUs = false;
    266         notifyFillBufferDone(outHeader);
    267 
    268         if (sawEOS) {
    269             break;
    270         }
    271     }
    272 }
    273 
    274 }  // namespace android
    275 
    276 android::SoftOMXComponent *createSoftOMXComponent(
    277         const char *name, const OMX_CALLBACKTYPE *callbacks,
    278         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
    279     return new android::SoftRaw(name, callbacks, appData, component);
    280 }
    281