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 26namespace android { 27 28template<class T> 29static 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 37SoftRaw::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 52SoftRaw::~SoftRaw() { 53} 54 55void 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 = 32 * 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 = 32 * 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 96status_t SoftRaw::initDecoder() { 97 return OK; 98} 99 100OMX_ERRORTYPE SoftRaw::internalGetParameter( 101 OMX_INDEXTYPE index, OMX_PTR params) { 102 switch (index) { 103 case OMX_IndexParamAudioPcm: 104 { 105 OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 106 (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 107 108 if (!isValidOMXParam(pcmParams)) { 109 return OMX_ErrorBadParameter; 110 } 111 112 if (pcmParams->nPortIndex != 0 && pcmParams->nPortIndex != 1) { 113 return OMX_ErrorUndefined; 114 } 115 116 pcmParams->eNumData = (OMX_NUMERICALDATATYPE)mNumericalData; 117 pcmParams->eEndian = OMX_EndianBig; 118 pcmParams->bInterleaved = OMX_TRUE; 119 pcmParams->nBitPerSample = mBitsPerSample; 120 pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear; 121 pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF; 122 pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF; 123 124 pcmParams->nChannels = mChannelCount; 125 pcmParams->nSamplingRate = mSampleRate; 126 127 return OMX_ErrorNone; 128 } 129 130 default: 131 return SimpleSoftOMXComponent::internalGetParameter(index, params); 132 } 133} 134 135OMX_ERRORTYPE SoftRaw::internalSetParameter( 136 OMX_INDEXTYPE index, const OMX_PTR params) { 137 switch (index) { 138 case OMX_IndexParamStandardComponentRole: 139 { 140 const OMX_PARAM_COMPONENTROLETYPE *roleParams = 141 (const OMX_PARAM_COMPONENTROLETYPE *)params; 142 143 if (!isValidOMXParam(roleParams)) { 144 return OMX_ErrorBadParameter; 145 } 146 147 if (strncmp((const char *)roleParams->cRole, 148 "audio_decoder.raw", 149 OMX_MAX_STRINGNAME_SIZE - 1)) { 150 return OMX_ErrorUndefined; 151 } 152 153 return OMX_ErrorNone; 154 } 155 156 case OMX_IndexParamAudioPcm: 157 { 158 const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 159 (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 160 161 if (!isValidOMXParam(pcmParams)) { 162 return OMX_ErrorBadParameter; 163 } 164 165 if (pcmParams->nPortIndex != 0) { 166 return OMX_ErrorUndefined; 167 } 168 169 mChannelCount = pcmParams->nChannels; 170 mSampleRate = pcmParams->nSamplingRate; 171 mNumericalData = pcmParams->eNumData; 172 mBitsPerSample = pcmParams->nBitPerSample; 173 174 return OMX_ErrorNone; 175 } 176 177 default: 178 { 179 OMX_ERRORTYPE err = SimpleSoftOMXComponent::internalSetParameter( 180 index, params); 181 // In case inPort->mDef.nBufferSize changed, the output buffer size 182 // should match the input buffer size. 183 PortInfo *inPort = editPortInfo(0); 184 PortInfo *outPort = editPortInfo(1); 185 outPort->mDef.nBufferSize = inPort->mDef.nBufferSize; 186 return err; 187 } 188 } 189} 190 191void SoftRaw::onQueueFilled(OMX_U32 /* portIndex */) { 192 if (mSignalledError) { 193 return; 194 } 195 196 List<BufferInfo *> &inQueue = getPortQueue(0); 197 List<BufferInfo *> &outQueue = getPortQueue(1); 198 199 while (!inQueue.empty() && !outQueue.empty()) { 200 BufferInfo *inInfo = *inQueue.begin(); 201 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 202 203 BufferInfo *outInfo = *outQueue.begin(); 204 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 205 206 CHECK_GE(outHeader->nAllocLen, inHeader->nFilledLen); 207 memcpy(outHeader->pBuffer, 208 inHeader->pBuffer + inHeader->nOffset, 209 inHeader->nFilledLen); 210 211 outHeader->nFlags = inHeader->nFlags; 212 outHeader->nOffset = 0; 213 outHeader->nFilledLen = inHeader->nFilledLen; 214 outHeader->nTimeStamp = inHeader->nTimeStamp; 215 216 bool sawEOS = (inHeader->nFlags & OMX_BUFFERFLAG_EOS) != 0; 217 218 inQueue.erase(inQueue.begin()); 219 inInfo->mOwnedByUs = false; 220 notifyEmptyBufferDone(inHeader); 221 222 outQueue.erase(outQueue.begin()); 223 outInfo->mOwnedByUs = false; 224 notifyFillBufferDone(outHeader); 225 226 if (sawEOS) { 227 break; 228 } 229 } 230} 231 232} // namespace android 233 234android::SoftOMXComponent *createSoftOMXComponent( 235 const char *name, const OMX_CALLBACKTYPE *callbacks, 236 OMX_PTR appData, OMX_COMPONENTTYPE **component) { 237 return new android::SoftRaw(name, callbacks, appData, component); 238} 239