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