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