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
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)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
AmrEncOmxComponentDestructor(OMX_IN OMX_HANDLETYPE pHandle,OMX_PTR & aOmxLib,OMX_PTR aOsclUuid,OMX_U32 & aRefCount)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:
QueryOmxComponentInterface(const OsclUuid & aOmxTypeId,const OsclUuid & aInterfaceId)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
SharedLibraryLookup(const OsclUuid & aInterfaceId)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
AmrEncOmxSharedLibraryInterface()106 AmrEncOmxSharedLibraryInterface() {};
107 };
108
109 // function to obtain the interface object from the shared library
110 extern "C"
111 {
PVGetInterface()112 OSCL_EXPORT_REF OsclAny* PVGetInterface()
113 {
114 return (OsclAny*) OSCL_NEW(AmrEncOmxSharedLibraryInterface, ());
115 }
116
PVReleaseInterface(OsclSharedLibraryInterface * aInstance)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
ConstructComponent(OMX_PTR pAppData,OMX_PTR pProxy)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
DestroyComponent()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 */
SyncWithInputTimestamp()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
ProcessData()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
ComponentGetRolesOfComponent(OMX_STRING * aRoleString)605 void OmxComponentAmrEncoderAO::ComponentGetRolesOfComponent(OMX_STRING* aRoleString)
606 {
607 *aRoleString = (OMX_STRING)"audio_encoder.amr";
608 }
609
610
611 //Component constructor
OmxComponentAmrEncoderAO()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
~OmxComponentAmrEncoderAO()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 */
ComponentInit()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 */
ComponentDeInit()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 */
ProcessInBufferFlag()709 void OmxComponentAmrEncoderAO::ProcessInBufferFlag()
710 {
711 iIsInputBufferEnded = OMX_FALSE;
712 }
713