1 /* ------------------------------------------------------------------ 2 * Copyright (C) 1998-2009 PacketVideo 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 13 * express or implied. 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * ------------------------------------------------------------------- 17 */ 18 19 #include "omx_amrenc_component.h" 20 21 #if PROXY_INTERFACE 22 #include "omx_proxy_interface.h" 23 #endif 24 25 26 27 // This function is called by OMX_GetHandle and it creates an instance of the amr component AO 28 OMX_ERRORTYPE AmrEncOmxComponentFactory(OMX_OUT OMX_HANDLETYPE* pHandle, OMX_IN OMX_PTR pAppData, OMX_PTR pProxy, OMX_STRING aOmxLibName, OMX_PTR &aOmxLib, OMX_PTR aOsclUuid, OMX_U32 &aRefCount) 29 { 30 OSCL_UNUSED_ARG(aOmxLibName); 31 OSCL_UNUSED_ARG(aOmxLib); 32 OSCL_UNUSED_ARG(aOsclUuid); 33 OSCL_UNUSED_ARG(aRefCount); 34 35 OmxComponentAmrEncoderAO* pOpenmaxAOType; 36 OMX_ERRORTYPE Status; 37 38 // move InitAmrOmxComponentFields content to actual constructor 39 40 pOpenmaxAOType = (OmxComponentAmrEncoderAO*) OSCL_NEW(OmxComponentAmrEncoderAO, ()); 41 42 if (NULL == pOpenmaxAOType) 43 { 44 return OMX_ErrorInsufficientResources; 45 } 46 47 //Call the construct component to initialize OMX types 48 Status = pOpenmaxAOType->ConstructComponent(pAppData, pProxy); 49 50 *pHandle = pOpenmaxAOType->GetOmxHandle(); 51 52 return Status; 53 /////////////////////////////////////////////////////////////////////////////////////// 54 } 55 56 // This function is called by OMX_FreeHandle when component AO needs to be destroyed 57 OMX_ERRORTYPE AmrEncOmxComponentDestructor(OMX_IN OMX_HANDLETYPE pHandle, OMX_PTR &aOmxLib, OMX_PTR aOsclUuid, OMX_U32 &aRefCount) 58 { 59 OSCL_UNUSED_ARG(aOmxLib); 60 OSCL_UNUSED_ARG(aOsclUuid); 61 OSCL_UNUSED_ARG(aRefCount); 62 63 // get pointer to component AO 64 OmxComponentAmrEncoderAO* pOpenmaxAOType = (OmxComponentAmrEncoderAO*)((OMX_COMPONENTTYPE*)pHandle)->pComponentPrivate; 65 66 // clean up encoder, OMX component stuff 67 pOpenmaxAOType->DestroyComponent(); 68 69 // destroy the AO class 70 OSCL_DELETE(pOpenmaxAOType); 71 72 return OMX_ErrorNone; 73 } 74 75 #if DYNAMIC_LOAD_OMX_AMRENC_COMPONENT 76 class AmrEncOmxSharedLibraryInterface: public OsclSharedLibraryInterface, 77 public OmxSharedLibraryInterface 78 79 { 80 public: 81 OsclAny *QueryOmxComponentInterface(const OsclUuid& aOmxTypeId, const OsclUuid& aInterfaceId) 82 { 83 if (PV_OMX_AMRENC_UUID == aOmxTypeId) 84 { 85 if (PV_OMX_CREATE_INTERFACE == aInterfaceId) 86 { 87 return ((OsclAny*)(&AmrEncOmxComponentFactory)); 88 } 89 else if (PV_OMX_DESTROY_INTERFACE == aInterfaceId) 90 { 91 return ((OsclAny*)(&AmrEncOmxComponentDestructor)); 92 } 93 } 94 return NULL; 95 }; 96 97 OsclAny *SharedLibraryLookup(const OsclUuid& aInterfaceId) 98 { 99 if (aInterfaceId == PV_OMX_SHARED_INTERFACE) 100 { 101 return OSCL_STATIC_CAST(OmxSharedLibraryInterface*, this); 102 } 103 return NULL; 104 }; 105 106 AmrEncOmxSharedLibraryInterface() {}; 107 }; 108 109 // function to obtain the interface object from the shared library 110 extern "C" 111 { 112 OSCL_EXPORT_REF OsclAny* PVGetInterface() 113 { 114 return (OsclAny*) OSCL_NEW(AmrEncOmxSharedLibraryInterface, ()); 115 } 116 117 OSCL_EXPORT_REF void PVReleaseInterface(OsclSharedLibraryInterface* aInstance) 118 { 119 AmrEncOmxSharedLibraryInterface* module = (AmrEncOmxSharedLibraryInterface*)aInstance; 120 OSCL_DELETE(module); 121 } 122 } 123 124 #endif 125 126 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 127 128 OMX_ERRORTYPE OmxComponentAmrEncoderAO::ConstructComponent(OMX_PTR pAppData, OMX_PTR pProxy) 129 { 130 ComponentPortType* pInPort, *pOutPort; 131 OMX_ERRORTYPE Status; 132 133 iNumPorts = 2; 134 iCompressedFormatPortNum = OMX_PORT_OUTPUTPORT_INDEX; 135 iOmxComponent.nSize = sizeof(OMX_COMPONENTTYPE); 136 iOmxComponent.pComponentPrivate = (OMX_PTR) this; // pComponentPrivate points to THIS component AO class 137 ipComponentProxy = pProxy; 138 iOmxComponent.pApplicationPrivate = pAppData; // init the App data 139 140 141 #if PROXY_INTERFACE 142 iPVCapabilityFlags.iIsOMXComponentMultiThreaded = OMX_TRUE; 143 144 iOmxComponent.SendCommand = OmxComponentAmrEncoderAO::BaseComponentProxySendCommand; 145 iOmxComponent.GetParameter = OmxComponentAmrEncoderAO::BaseComponentProxyGetParameter; 146 iOmxComponent.SetParameter = OmxComponentAmrEncoderAO::BaseComponentProxySetParameter; 147 iOmxComponent.GetConfig = OmxComponentAmrEncoderAO::BaseComponentProxyGetConfig; 148 iOmxComponent.SetConfig = OmxComponentAmrEncoderAO::BaseComponentProxySetConfig; 149 iOmxComponent.GetExtensionIndex = OmxComponentAmrEncoderAO::BaseComponentProxyGetExtensionIndex; 150 iOmxComponent.GetState = OmxComponentAmrEncoderAO::BaseComponentProxyGetState; 151 iOmxComponent.UseBuffer = OmxComponentAmrEncoderAO::BaseComponentProxyUseBuffer; 152 iOmxComponent.AllocateBuffer = OmxComponentAmrEncoderAO::BaseComponentProxyAllocateBuffer; 153 iOmxComponent.FreeBuffer = OmxComponentAmrEncoderAO::BaseComponentProxyFreeBuffer; 154 iOmxComponent.EmptyThisBuffer = OmxComponentAmrEncoderAO::BaseComponentProxyEmptyThisBuffer; 155 iOmxComponent.FillThisBuffer = OmxComponentAmrEncoderAO::BaseComponentProxyFillThisBuffer; 156 157 #else 158 iPVCapabilityFlags.iIsOMXComponentMultiThreaded = OMX_FALSE; 159 160 iOmxComponent.SendCommand = OmxComponentAmrEncoderAO::BaseComponentSendCommand; 161 iOmxComponent.GetParameter = OmxComponentAmrEncoderAO::BaseComponentGetParameter; 162 iOmxComponent.SetParameter = OmxComponentAmrEncoderAO::BaseComponentSetParameter; 163 iOmxComponent.GetConfig = OmxComponentAmrEncoderAO::BaseComponentGetConfig; 164 iOmxComponent.SetConfig = OmxComponentAmrEncoderAO::BaseComponentSetConfig; 165 iOmxComponent.GetExtensionIndex = OmxComponentAmrEncoderAO::BaseComponentGetExtensionIndex; 166 iOmxComponent.GetState = OmxComponentAmrEncoderAO::BaseComponentGetState; 167 iOmxComponent.UseBuffer = OmxComponentAmrEncoderAO::BaseComponentUseBuffer; 168 iOmxComponent.AllocateBuffer = OmxComponentAmrEncoderAO::BaseComponentAllocateBuffer; 169 iOmxComponent.FreeBuffer = OmxComponentAmrEncoderAO::BaseComponentFreeBuffer; 170 iOmxComponent.EmptyThisBuffer = OmxComponentAmrEncoderAO::BaseComponentEmptyThisBuffer; 171 iOmxComponent.FillThisBuffer = OmxComponentAmrEncoderAO::BaseComponentFillThisBuffer; 172 #endif 173 174 iOmxComponent.SetCallbacks = OmxComponentAmrEncoderAO::BaseComponentSetCallbacks; 175 iOmxComponent.nVersion.s.nVersionMajor = SPECVERSIONMAJOR; 176 iOmxComponent.nVersion.s.nVersionMinor = SPECVERSIONMINOR; 177 iOmxComponent.nVersion.s.nRevision = SPECREVISION; 178 iOmxComponent.nVersion.s.nStep = SPECSTEP; 179 180 // PV capability 181 iPVCapabilityFlags.iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE; 182 iPVCapabilityFlags.iOMXComponentSupportsExternalOutputBufferAlloc = OMX_TRUE; 183 iPVCapabilityFlags.iOMXComponentSupportsMovableInputBuffers = OMX_TRUE; 184 iPVCapabilityFlags.iOMXComponentSupportsPartialFrames = OMX_TRUE; 185 iPVCapabilityFlags.iOMXComponentUsesNALStartCodes = OMX_FALSE; 186 iPVCapabilityFlags.iOMXComponentCanHandleIncompleteFrames = OMX_TRUE; 187 iPVCapabilityFlags.iOMXComponentUsesFullAVCFrames = OMX_FALSE; 188 189 if (ipAppPriv) 190 { 191 oscl_free(ipAppPriv); 192 ipAppPriv = NULL; 193 } 194 195 ipAppPriv = (ComponentPrivateType*) oscl_malloc(sizeof(ComponentPrivateType)); 196 if (NULL == ipAppPriv) 197 { 198 return OMX_ErrorInsufficientResources; 199 } 200 201 //Construct base class now 202 Status = ConstructBaseComponent(pAppData); 203 204 if (OMX_ErrorNone != Status) 205 { 206 return Status; 207 } 208 209 /** Domain specific section for the ports */ 210 /* Input port is raw/pcm for AMR encoder */ 211 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nPortIndex = OMX_PORT_INPUTPORT_INDEX; 212 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.eDomain = OMX_PortDomainAudio; 213 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.cMIMEType = (OMX_STRING)"raw"; 214 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.pNativeRender = 0; 215 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.bFlagErrorConcealment = OMX_FALSE; 216 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 217 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.eDir = OMX_DirInput; 218 //Set to a default value, will change later during setparameter call 219 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferCountActual = NUMBER_INPUT_BUFFER_AMR_ENC; 220 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferCountMin = 1; 221 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize = INPUT_BUFFER_SIZE_AMR_ENC; 222 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE; 223 ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE; 224 225 226 /* Output port is amr format for AMR encoder */ 227 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 228 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.eDomain = OMX_PortDomainAudio; 229 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.cMIMEType = (OMX_STRING)"audio/mpeg"; 230 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.pNativeRender = 0; 231 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.bFlagErrorConcealment = OMX_FALSE; 232 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.format.audio.eEncoding = OMX_AUDIO_CodingAMR; 233 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.eDir = OMX_DirOutput; 234 //Set to a default value, will change later during setparameter call 235 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountActual = NUMBER_OUTPUT_BUFFER_AMR_ENC; 236 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferCountMin = 1; 237 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.nBufferSize = OUTPUT_BUFFER_SIZE_AMR_ENC; 238 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bEnabled = OMX_TRUE; 239 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->PortParam.bPopulated = OMX_FALSE; 240 241 //Default values for PCM input audio param port 242 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.nPortIndex = OMX_PORT_INPUTPORT_INDEX; 243 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.nChannels = 1; 244 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.eNumData = OMX_NumericalDataSigned; 245 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.bInterleaved = OMX_TRUE; 246 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.nBitPerSample = 16; 247 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.nSamplingRate = 8000; 248 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.ePCMMode = OMX_AUDIO_PCMModeLinear; 249 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.eChannelMapping[0] = OMX_AUDIO_ChannelLF; 250 ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode.eChannelMapping[1] = OMX_AUDIO_ChannelRF; 251 252 //Default values for AMR output audio param port 253 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioAmrParam.nPortIndex = OMX_PORT_OUTPUTPORT_INDEX; 254 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioAmrParam.nChannels = 1; 255 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioAmrParam.nBitRate = 0; 256 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioAmrParam.eAMRBandMode = OMX_AUDIO_AMRBandModeNB7; //AMRNB Mode 7 = 12200 bps 257 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioAmrParam.eAMRDTXMode = OMX_AUDIO_AMRDTXModeOnVAD1; 258 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioAmrParam.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; //PVMF_AMR_IETF 259 260 iPortTypesParam.nPorts = 2; 261 iPortTypesParam.nStartPortNumber = 0; 262 263 pInPort = (ComponentPortType*) ipPorts[OMX_PORT_INPUTPORT_INDEX]; 264 pOutPort = (ComponentPortType*) ipPorts[OMX_PORT_OUTPUTPORT_INDEX]; 265 266 SetHeader(&pInPort->AudioParam, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); 267 pInPort->AudioParam.nPortIndex = 0; 268 pInPort->AudioParam.nIndex = 0; 269 pInPort->AudioParam.eEncoding = OMX_AUDIO_CodingPCM; 270 271 SetHeader(&pOutPort->AudioParam, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); 272 pOutPort->AudioParam.nPortIndex = 1; 273 pOutPort->AudioParam.nIndex = 0; 274 pOutPort->AudioParam.eEncoding = OMX_AUDIO_CodingAMR; 275 276 oscl_strncpy((OMX_STRING)iComponentRole, (OMX_STRING)"audio_encoder.amrnb", OMX_MAX_STRINGNAME_SIZE); 277 278 iInputBufferRemainingBytes = 0; 279 280 if (ipAmrEnc) 281 { 282 OSCL_DELETE(ipAmrEnc); 283 ipAmrEnc = NULL; 284 } 285 286 ipAmrEnc = OSCL_NEW(OmxAmrEncoder, ()); 287 if (NULL == ipAmrEnc) 288 { 289 return OMX_ErrorInsufficientResources; 290 } 291 292 293 294 #if PROXY_INTERFACE 295 296 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSendCommand = BaseComponentSendCommand; 297 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetParameter = BaseComponentGetParameter; 298 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSetParameter = BaseComponentSetParameter; 299 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetConfig = BaseComponentGetConfig; 300 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentSetConfig = BaseComponentSetConfig; 301 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetExtensionIndex = BaseComponentGetExtensionIndex; 302 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentGetState = BaseComponentGetState; 303 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentUseBuffer = BaseComponentUseBuffer; 304 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentAllocateBuffer = BaseComponentAllocateBuffer; 305 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentFreeBuffer = BaseComponentFreeBuffer; 306 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentEmptyThisBuffer = BaseComponentEmptyThisBuffer; 307 ((ProxyApplication_OMX*)ipComponentProxy)->ComponentFillThisBuffer = BaseComponentFillThisBuffer; 308 309 #endif 310 return OMX_ErrorNone; 311 } 312 313 314 /** This function is called by the omx core when the component 315 * is disposed by the IL client with a call to FreeHandle(). 316 * \param Component, the component to be disposed 317 */ 318 319 OMX_ERRORTYPE OmxComponentAmrEncoderAO::DestroyComponent() 320 { 321 if (iIsInit != OMX_FALSE) 322 { 323 ComponentDeInit(); 324 } 325 326 //Destroy the base class now 327 DestroyBaseComponent(); 328 329 if (ipAmrEnc) 330 { 331 OSCL_DELETE(ipAmrEnc); 332 ipAmrEnc = NULL; 333 } 334 335 if (ipAppPriv) 336 { 337 ipAppPriv->CompHandle = NULL; 338 339 oscl_free(ipAppPriv); 340 ipAppPriv = NULL; 341 } 342 343 return OMX_ErrorNone; 344 } 345 346 347 348 /* This routine will extract the input timestamp from the input buffer */ 349 void OmxComponentAmrEncoderAO::SyncWithInputTimestamp() 350 { 351 // this is called when new input buffer is received 352 // and checked against internally kept (Current) timestamp 353 // TODO: 354 // If there is unprocessed data from previous buffer - need to adjust timestamp - but 355 // timestamp adjustment should only be done once (if multiple PCM input buffers are received - prior to doing further processing) 356 357 358 } 359 360 361 void OmxComponentAmrEncoderAO::ProcessData() 362 { 363 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ProcessData IN")); 364 365 QueueType* pInputQueue = ipPorts[OMX_PORT_INPUTPORT_INDEX]->pBufferQueue; 366 QueueType* pOutputQueue = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->pBufferQueue; 367 368 ComponentPortType* pInPort = (ComponentPortType*) ipPorts[OMX_PORT_INPUTPORT_INDEX]; 369 ComponentPortType* pOutPort = ipPorts[OMX_PORT_OUTPUTPORT_INDEX]; 370 OMX_COMPONENTTYPE* pHandle = &iOmxComponent; 371 372 OMX_U8* pOutBuffer; 373 OMX_U32 OutputLength; 374 OMX_S32 EncodeReturn; 375 OMX_U32 RemainderInputBytes = 0; 376 OMX_TICKS OutputTimeStamp; 377 378 OMX_U32 TempInputBufferSize = (2 * sizeof(uint8) * (ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize)); 379 380 OMX_U32 AllocNumberOutputFrames; 381 OMX_U32 ExtraInputBytes = 0; 382 383 if ((!iIsInputBufferEnded) || iEndofStream) 384 { 385 //Check whether prev output bufer has been released or not 386 if (OMX_TRUE == iNewOutBufRequired) 387 { 388 //Check whether a new output buffer is available or not 389 if (0 == (GetQueueNumElem(pOutputQueue))) 390 { 391 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ProcessData OUT output buffer unavailable")); 392 return; 393 } 394 395 ipOutputBuffer = (OMX_BUFFERHEADERTYPE*) DeQueue(pOutputQueue); 396 397 OSCL_ASSERT(NULL != ipOutputBuffer); 398 if (NULL == ipOutputBuffer) 399 { 400 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "OmxComponentAmrEncoderAO : ProcessData ERROR - OUT buffer cannot be dequeued")); 401 402 return; 403 } 404 405 ipOutputBuffer->nFilledLen = 0; 406 iNewOutBufRequired = OMX_FALSE; 407 408 //At the first frame count, detrermine the output parameters 409 if (0 == iFrameCount) 410 { 411 //How many frames can be accomodated in the output buffer 412 AllocNumberOutputFrames = ipOutputBuffer->nAllocLen / MAX_AMR_FRAME_SIZE; 413 iActualNumberOutputFrames = omx_min(AllocNumberOutputFrames, iMaxNumberOutputFrames); 414 415 /* Keep the minimum of the two: 416 -frames accomodated and 417 -maximum frames defined by component */ 418 iOutputFrameLength = iActualNumberOutputFrames * MAX_AMR_FRAME_SIZE; 419 } 420 } 421 422 /* Code for the marking buffer. Takes care of the OMX_CommandMarkBuffer 423 * command and hMarkTargetComponent as given by the specifications 424 */ 425 if (ipMark != NULL) 426 { 427 ipOutputBuffer->hMarkTargetComponent = ipMark->hMarkTargetComponent; 428 ipOutputBuffer->pMarkData = ipMark->pMarkData; 429 ipMark = NULL; 430 } 431 432 if (ipTargetComponent != NULL) 433 { 434 ipOutputBuffer->hMarkTargetComponent = ipTargetComponent; 435 ipOutputBuffer->pMarkData = iTargetMarkData; 436 ipTargetComponent = NULL; 437 438 } 439 //Mark buffer code ends here 440 441 442 if ((iTempInputBufferLength > 0) && 443 ((iInputCurrLength + iTempInputBufferLength) <= TempInputBufferSize)) 444 { 445 oscl_memcpy(&ipTempInputBuffer[iTempInputBufferLength], ipFrameDecodeBuffer, iInputCurrLength); 446 iInputCurrLength += iTempInputBufferLength; 447 iTempInputBufferLength = 0; 448 ipFrameDecodeBuffer = ipTempInputBuffer; 449 } 450 451 452 //If the number of output buffers to be produced from the current iInputCurrLength 453 //are more than our requirement, send only the required data for encoding 454 if (iInputCurrLength / iInputFrameLength > iActualNumberOutputFrames) 455 { 456 ExtraInputBytes = iInputCurrLength - (iInputFrameLength * iActualNumberOutputFrames); 457 iInputCurrLength -= ExtraInputBytes; 458 } 459 else 460 { 461 /* Before sending the input buffer to the encoder, ensure that the data is multiple 462 * of one amr input frame length*/ 463 RemainderInputBytes = iInputCurrLength % iInputFrameLength; 464 iInputCurrLength -= RemainderInputBytes; 465 } 466 467 468 pOutBuffer = &ipOutputBuffer->pBuffer[ipOutputBuffer->nFilledLen]; 469 OutputLength = 0; 470 471 EncodeReturn = ipAmrEnc->AmrEncodeFrame(pOutBuffer, 472 &OutputLength, 473 ipFrameDecodeBuffer, 474 iInputCurrLength, 475 iCurrentTimestamp, 476 &OutputTimeStamp); 477 478 479 //Attach the timestamp to the output buffer only when we have fetched the new output buffer 480 //If we are reusing the same output buffer again, no need to modify the previous timestamp, as it should be of the first frame in that buffer 481 482 if (0 == ipOutputBuffer->nFilledLen) 483 { 484 ipOutputBuffer->nTimeStamp = OutputTimeStamp; 485 } 486 487 488 ipOutputBuffer->nFilledLen += OutputLength; 489 //offset not required in our case, set it to zero 490 ipOutputBuffer->nOffset = 0; 491 492 //It has to be incremented atleast one time, so that 'equality with zero' checks added above hold true only once 493 iFrameCount++; 494 495 496 /* If EOS flag has come from the client & there are no more 497 * input buffers to decode, send the callback to the client 498 */ 499 if (OMX_TRUE == iEndofStream) 500 { 501 if ((0 == iInputCurrLength) || (OMX_TRUE != EncodeReturn)) 502 { 503 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ProcessData EOS callback send")); 504 505 (*(ipCallbacks->EventHandler)) 506 (pHandle, 507 iCallbackData, 508 OMX_EventBufferFlag, 509 1, 510 OMX_BUFFERFLAG_EOS, 511 NULL); 512 513 iEndofStream = OMX_FALSE; 514 515 ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_EOS; 516 517 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 518 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ProcessData OUT")); 519 520 return; 521 } 522 } 523 524 525 if (OMX_TRUE == EncodeReturn) 526 { 527 //Do not return the input buffer in case it has more than one frame data to encode 528 if (ExtraInputBytes > 0) 529 { 530 ipFrameDecodeBuffer += iInputCurrLength; 531 iInputCurrLength = ExtraInputBytes; 532 } 533 else 534 { 535 536 /* If there are some remainder bytes out of the last buffer, copy into a temp buffer 537 * to be used in next decode cycle and return the existing input buffer*/ 538 if (RemainderInputBytes > 0) 539 { 540 oscl_memmove(ipTempInputBuffer, &ipFrameDecodeBuffer[iInputCurrLength], RemainderInputBytes); 541 iTempInputBufferLength = RemainderInputBytes; 542 } 543 544 //Input bytes consumed now, return the buffer 545 ipInputBuffer->nFilledLen = 0; 546 ReturnInputBuffer(ipInputBuffer, pInPort); 547 iIsInputBufferEnded = OMX_TRUE; 548 iInputCurrLength = 0; 549 550 } 551 } 552 //In case of error, discard the bitstream and report data corruption error via callback 553 else 554 { 555 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ProcessData ErrorStreamCorrupt callback send")); 556 557 ipInputBuffer->nFilledLen = 0; 558 ReturnInputBuffer(ipInputBuffer, pInPort); 559 iIsInputBufferEnded = OMX_TRUE; 560 iInputCurrLength = 0; 561 562 563 (*(ipCallbacks->EventHandler)) 564 (pHandle, 565 iCallbackData, 566 OMX_EventError, 567 OMX_ErrorStreamCorrupt, 568 0, 569 NULL); 570 } 571 572 573 /* Send the output buffer back when it has the following conditions as true: 574 1) Output buffer contain desired number of frames, calculated above 575 2) Output buffer can no longer hold the desired number of frames that 576 we will encode in next encode call 577 */ 578 if ((ipOutputBuffer->nFilledLen >= iOutputFrameLength) 579 || (ipOutputBuffer->nAllocLen - ipOutputBuffer->nFilledLen) < iOutputFrameLength) 580 { 581 //Attach the end of frame flag while sending out the output buffer 582 ipOutputBuffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; 583 ReturnOutputBuffer(ipOutputBuffer, pOutPort); 584 } 585 586 587 /* If there is some more processing left with current buffers, re-schedule the AO 588 * Do not go for more than one round of processing at a time. 589 * This may block the AO longer than required. 590 */ 591 if (((ipInputBuffer->nFilledLen != 0) || (GetQueueNumElem(pInputQueue) > 0)) 592 && ((GetQueueNumElem(pOutputQueue) > 0) || (OMX_FALSE == iNewOutBufRequired))) 593 { 594 RunIfNotReady(); 595 } 596 } 597 598 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ProcessData OUT")); 599 return; 600 } 601 602 603 //Not implemented & supported in case of base profile components 604 605 void OmxComponentAmrEncoderAO::ComponentGetRolesOfComponent(OMX_STRING* aRoleString) 606 { 607 *aRoleString = (OMX_STRING)"audio_encoder.amr"; 608 } 609 610 611 //Component constructor 612 OmxComponentAmrEncoderAO::OmxComponentAmrEncoderAO() 613 { 614 ipAmrEnc = NULL; 615 iInputFrameLength = 0; 616 iOutputFrameLength = 0; 617 iActualNumberOutputFrames = 0; 618 iMaxNumberOutputFrames = 0; 619 620 if (!IsAdded()) 621 { 622 AddToScheduler(); 623 } 624 625 iCurrentTimestamp = 0; 626 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : constructed")); 627 } 628 629 630 //Active object destructor 631 OmxComponentAmrEncoderAO::~OmxComponentAmrEncoderAO() 632 { 633 if (IsAdded()) 634 { 635 RemoveFromScheduler(); 636 } 637 638 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : destructed")); 639 } 640 641 642 /** The Initialization function 643 */ 644 OMX_ERRORTYPE OmxComponentAmrEncoderAO::ComponentInit() 645 { 646 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ComponentInit IN")); 647 648 OMX_BOOL Status = OMX_TRUE; 649 650 if (OMX_TRUE == iIsInit) 651 { 652 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ComponentInit error incorrect operation")); 653 return OMX_ErrorIncorrectStateOperation; 654 } 655 iIsInit = OMX_TRUE; 656 657 //amr encoder lib init 658 if (!iCodecReady) 659 { 660 Status = ipAmrEnc->AmrEncInit(ipPorts[OMX_PORT_INPUTPORT_INDEX]->AudioPcmMode, 661 ipPorts[OMX_PORT_OUTPUTPORT_INDEX]->AudioAmrParam, 662 &iInputFrameLength, &iMaxNumberOutputFrames); 663 664 iCodecReady = OMX_TRUE; 665 } 666 667 iInputCurrLength = 0; 668 669 //Used in dynamic port reconfiguration 670 iFrameCount = 0; 671 672 if (OMX_TRUE == Status) 673 { 674 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ComponentInit OUT")); 675 return OMX_ErrorNone; 676 } 677 else 678 { 679 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : Error ComponentInit, OUT")); 680 return OMX_ErrorInvalidComponent; 681 } 682 } 683 684 685 686 /** This function is called upon a transition to the idle or invalid state. 687 * Also it is called by the ComponentDestructor() function 688 */ 689 OMX_ERRORTYPE OmxComponentAmrEncoderAO::ComponentDeInit() 690 { 691 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ComponentDeInit IN")); 692 693 iIsInit = OMX_FALSE; 694 695 if (iCodecReady) 696 { 697 ipAmrEnc->AmrEncDeinit(); 698 iCodecReady = OMX_FALSE; 699 } 700 701 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "OmxComponentAmrEncoderAO : ComponentDeInit OUT")); 702 703 return OMX_ErrorNone; 704 705 } 706 707 708 /* A component specific routine called from BufferMgmtWithoutMarker */ 709 void OmxComponentAmrEncoderAO::ProcessInBufferFlag() 710 { 711 iIsInputBufferEnded = OMX_FALSE; 712 } 713