• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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