• 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 #include "pvmf_omx_enc_node.h"
19 #include "pvlogger.h"
20 #include "oscl_error_codes.h"
21 #include "pvmf_omx_enc_port.h"
22 #include "pv_mime_string_utils.h"
23 #include "oscl_snprintf.h"
24 #include "pvmf_media_cmd.h"
25 #include "pvmf_media_msg_format_ids.h"
26 #include "pvmi_kvp_util.h"
27 
28 #ifdef _DEBUG
29 #include <stdio.h>
30 #endif
31 
32 #include "OMX_Core.h"
33 #include "pvmf_omx_enc_callbacks.h"     //used for thin AO in encoder's callbacks
34 #include "pv_omxcore.h"
35 
36 #define CONFIG_SIZE_AND_VERSION(param)                  \
37     param.nSize=sizeof(param);                          \
38     param.nVersion.s.nVersionMajor = SPECVERSIONMAJOR;  \
39     param.nVersion.s.nVersionMinor = SPECVERSIONMINOR;  \
40     param.nVersion.s.nRevision = SPECREVISION;          \
41     param.nVersion.s.nStep = SPECSTEP;
42 
43 
44 #define CHECK_OMX_ERR_AND_RETURN(Err, str)                              \
45     if (Err != OMX_ErrorNone)                                           \
46     {                                                                   \
47         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, str)); \
48     }
49 
50 
51 #define PVOMXENC_EXTRA_YUVBUFFER_POOLNUM 3
52 #define PVOMXENC_MEDIADATA_POOLNUM (PVOMXENCMAXNUMDPBFRAMESPLUS1 + PVOMXENC_EXTRA_YUVBUFFER_POOLNUM)
53 #define PVOMXENC_MEDIADATA_CHUNKSIZE 128
54 
55 
56 const uint32 DEFAULT_VOL_HEADER_LENGTH = 28;
57 const uint8 DEFAULT_VOL_HEADER[DEFAULT_VOL_HEADER_LENGTH] =
58 {
59     0x00, 0x00, 0x01, 0xB0, 0x08, 0x00, 0x00, 0x01,
60     0xB5, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
61     0x01, 0x20, 0x00, 0x84, 0x40, 0xFA, 0x28, 0x2C,
62     0x20, 0x90, 0xA2, 0x1F
63 };
64 
65 
66 #ifdef _TEST_AE_ERROR_HANDLING
67 const uint32 FAIL_NODE_CMD_START = 2;
68 const uint32 FAIL_NODE_CMD_STOP = 3;
69 const uint32 FAIL_NODE_CMD_FLUSH = 4;
70 const uint32 FAIL_NODE_CMD_PAUSE = 5;
71 const uint32 FAIL_NODE_CMD_RELEASE_PORT = 7;
72 #endif
73 
74 #define PVMF_OMXENC_NUM_METADATA_VALUES 6
75 
76 // Constant character strings for metadata keys
77 static const char PVOMXENCMETADATA_CODECINFO_VIDEO_FORMAT_KEY[] = "codec-info/video/format";
78 static const char PVOMXENCMETADATA_CODECINFO_VIDEO_WIDTH_KEY[] = "codec-info/video/width";
79 static const char PVOMXENCMETADATA_CODECINFO_VIDEO_HEIGHT_KEY[] = "codec-info/video/height";
80 static const char PVOMXENCMETADATA_CODECINFO_VIDEO_PROFILE_KEY[] = "codec-info/video/profile";
81 static const char PVOMXENCMETADATA_CODECINFO_VIDEO_LEVEL_KEY[] = "codec-info/video/level";
82 static const char PVOMXENCMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY[] = "codec-info/video/avgbitrate";//(bits per sec)
83 
84 
85 static const char PVOMXENCMETADATA_SEMICOLON[] = ";";
86 
87 static const char LOG_ID_AUDIO_AMRNB[]  = "Audio_AMRNB";
88 static const char LOG_ID_AUDIO_AMRWB[]  = "Audio_AMRWB";
89 static const char LOG_ID_AUDIO_AAC[]  = "Audio_AAC";
90 static const char LOG_ID_VIDEO_H263[] = "Video_H263";
91 static const char LOG_ID_VIDEO_M4V[] =  "Video_M4V";
92 static const char LOG_ID_VIDEO_AVC[] =  "Video_AVC";
93 static const char LOG_ID_UNKNOWN[] = "TypeNotSetYet";
94 
95 // OMX CALLBACKS
96 // 1) AO OMX component running in the same thread as the OMX node
97 //  In this case, the callbacks can be called directly from the component
98 //  The callback: OMX Component->CallbackEventHandler->EventHandlerProcessing
99 //  The callback can perform do RunIfNotReady
100 
101 // 2) Multithreaded component
102 //  In this case, the callback is made using the threadsafe callback (TSCB) AO
103 //  Component thread : OMX Component->CallbackEventHandler->TSCB(ReceiveEvent) => event is queued
104 //  Node thread      : dequeue event => TSCB(ProcessEvent)->ProcessCallbackEventHandler->EventHandlerProcessing
105 
106 
107 
108 // callback for Event Handler - in multithreaded case, event is queued to be processed later
109 //  in AO case, event is processed immediately by calling EventHandlerProcessing
CallbackEventHandlerEnc(OMX_OUT OMX_HANDLETYPE aComponent,OMX_OUT OMX_PTR aAppData,OMX_OUT OMX_EVENTTYPE aEvent,OMX_OUT OMX_U32 aData1,OMX_OUT OMX_U32 aData2,OMX_OUT OMX_PTR aEventData)110 OMX_ERRORTYPE CallbackEventHandlerEnc(OMX_OUT OMX_HANDLETYPE aComponent,
111                                       OMX_OUT OMX_PTR aAppData,
112                                       OMX_OUT OMX_EVENTTYPE aEvent,
113                                       OMX_OUT OMX_U32 aData1,
114                                       OMX_OUT OMX_U32 aData2,
115                                       OMX_OUT OMX_PTR aEventData)
116 {
117 
118     PVMFOMXEncNode *Node = (PVMFOMXEncNode *) aAppData;
119 
120     if (Node->IsComponentMultiThreaded())
121     {
122         // allocate the memory for the callback event specific data
123         //EventHandlerSpecificData* ED = (EventHandlerSpecificData*) oscl_malloc(sizeof (EventHandlerSpecificData));
124         EventHandlerSpecificData* ED = (EventHandlerSpecificData*) Node->iThreadSafeHandlerEventHandler->iMemoryPool->allocate(sizeof(EventHandlerSpecificData));
125 
126         // pack the relevant data into the structure
127         ED->hComponent = aComponent;
128         ED->pAppData = aAppData;
129         ED->eEvent = aEvent;
130         ED->nData1 = aData1;
131         ED->nData2 = aData2;
132         ED->pEventData = aEventData;
133 
134         // convert the pointer into OsclAny ptr
135         OsclAny* P = (OsclAny*) ED;
136 
137 
138         // CALL the generic callback AO API:
139         Node->iThreadSafeHandlerEventHandler->ReceiveEvent(P);
140 
141         return OMX_ErrorNone;
142     }
143     else
144     {
145 
146         OMX_ERRORTYPE status;
147         status = Node->EventHandlerProcessing(aComponent, aAppData, aEvent, aData1, aData2, aEventData);
148         return status;
149     }
150 
151 }
152 
153 
154 // callback for EmptyBufferDone - in multithreaded case, event is queued to be processed later
155 //  in AO case, event is processed immediately by calling EmptyBufferDoneProcessing
CallbackEmptyBufferDoneEnc(OMX_OUT OMX_HANDLETYPE aComponent,OMX_OUT OMX_PTR aAppData,OMX_OUT OMX_BUFFERHEADERTYPE * aBuffer)156 OMX_ERRORTYPE CallbackEmptyBufferDoneEnc(OMX_OUT OMX_HANDLETYPE aComponent,
157         OMX_OUT OMX_PTR aAppData,
158         OMX_OUT OMX_BUFFERHEADERTYPE* aBuffer)
159 {
160 
161     PVMFOMXEncNode *Node = (PVMFOMXEncNode *) aAppData;
162     if (Node->IsComponentMultiThreaded())
163     {
164 
165         // allocate the memory for the callback event specific data
166         //EmptyBufferDoneSpecificData* ED = (EmptyBufferDoneSpecificData*) oscl_malloc(sizeof (EmptyBufferDoneSpecificData));
167         EmptyBufferDoneSpecificData* ED = (EmptyBufferDoneSpecificData*) Node->iThreadSafeHandlerEmptyBufferDone->iMemoryPool->allocate(sizeof(EmptyBufferDoneSpecificData));
168 
169         // pack the relevant data into the structure
170         ED->hComponent = aComponent;
171         ED->pAppData = aAppData;
172         ED->pBuffer = aBuffer;
173 
174         // convert the pointer into OsclAny ptr
175         OsclAny* P = (OsclAny*) ED;
176 
177         // CALL the generic callback AO API:
178         Node->iThreadSafeHandlerEmptyBufferDone->ReceiveEvent(P);
179 
180         return OMX_ErrorNone;
181     }
182     else
183     {
184         OMX_ERRORTYPE status;
185         status = Node->EmptyBufferDoneProcessing(aComponent, aAppData, aBuffer);
186         return status;
187     }
188 
189 }
190 
191 // callback for FillBufferDone - in multithreaded case, event is queued to be processed later
192 //  in AO case, event is processed immediately by calling FillBufferDoneProcessing
CallbackFillBufferDoneEnc(OMX_OUT OMX_HANDLETYPE aComponent,OMX_OUT OMX_PTR aAppData,OMX_OUT OMX_BUFFERHEADERTYPE * aBuffer)193 OMX_ERRORTYPE CallbackFillBufferDoneEnc(OMX_OUT OMX_HANDLETYPE aComponent,
194                                         OMX_OUT OMX_PTR aAppData,
195                                         OMX_OUT OMX_BUFFERHEADERTYPE* aBuffer)
196 {
197     PVMFOMXEncNode *Node = (PVMFOMXEncNode *) aAppData;
198     if (Node->IsComponentMultiThreaded())
199     {
200 
201         // allocate the memory for the callback event specific data
202         //FillBufferDoneSpecificData* ED = (FillBufferDoneSpecificData*) oscl_malloc(sizeof (FillBufferDoneSpecificData));
203         FillBufferDoneSpecificData* ED = (FillBufferDoneSpecificData*) Node->iThreadSafeHandlerFillBufferDone->iMemoryPool->allocate(sizeof(FillBufferDoneSpecificData));
204 
205         // pack the relevant data into the structure
206         ED->hComponent = aComponent;
207         ED->pAppData = aAppData;
208         ED->pBuffer = aBuffer;
209 
210         // convert the pointer into OsclAny ptr
211         OsclAny* P = (OsclAny*) ED;
212 
213         // CALL the generic callback AO API:
214         Node->iThreadSafeHandlerFillBufferDone->ReceiveEvent(P);
215 
216         return OMX_ErrorNone;
217     }
218     else
219     {
220         OMX_ERRORTYPE status;
221         status = Node->FillBufferDoneProcessing(aComponent, aAppData, aBuffer);
222         return status;
223     }
224 
225 }
226 
227 // Callback processing in multithreaded case - dequeued event - call EventHandlerProcessing
ProcessCallbackEventHandler_MultiThreaded(OsclAny * P)228 OsclReturnCode PVMFOMXEncNode::ProcessCallbackEventHandler_MultiThreaded(OsclAny* P)
229 {
230 
231     // re-cast the pointer
232 
233     EventHandlerSpecificData* ED = (EventHandlerSpecificData*) P;
234 
235     OMX_HANDLETYPE aComponent = ED->hComponent;
236     OMX_PTR aAppData = ED->pAppData;
237     OMX_EVENTTYPE aEvent = ED->eEvent;
238     OMX_U32 aData1 = ED->nData1;
239     OMX_U32 aData2 = ED->nData2;
240     OMX_PTR aEventData = ED->pEventData;
241 
242 
243     EventHandlerProcessing(aComponent, aAppData, aEvent, aData1, aData2, aEventData);
244 
245 
246     // release the allocated memory when no longer needed
247 
248     iThreadSafeHandlerEventHandler->iMemoryPool->deallocate(ED);
249     ED = NULL;
250 
251     return OsclSuccess;
252 }
253 
254 
255 
256 // Callback processing in multithreaded case - dequeued event - call EmptyBufferDoneProcessing
ProcessCallbackEmptyBufferDone_MultiThreaded(OsclAny * P)257 OsclReturnCode PVMFOMXEncNode::ProcessCallbackEmptyBufferDone_MultiThreaded(OsclAny* P)
258 {
259 
260 
261     // re-cast the pointer
262     EmptyBufferDoneSpecificData* ED = (EmptyBufferDoneSpecificData*) P;
263 
264     OMX_HANDLETYPE aComponent = ED->hComponent;
265     OMX_PTR aAppData = ED->pAppData;
266     OMX_BUFFERHEADERTYPE* aBuffer = ED->pBuffer;
267 
268     EmptyBufferDoneProcessing(aComponent, aAppData, aBuffer);
269 
270     // release the allocated memory when no longer needed
271 
272     iThreadSafeHandlerEmptyBufferDone->iMemoryPool->deallocate(ED);
273     ED = NULL;
274 
275     return OsclSuccess;
276 }
277 
278 
279 // Callback processing in multithreaded case - dequeued event - call FillBufferDoneProcessing
ProcessCallbackFillBufferDone_MultiThreaded(OsclAny * P)280 OsclReturnCode PVMFOMXEncNode::ProcessCallbackFillBufferDone_MultiThreaded(OsclAny* P)
281 {
282 
283     // re-cast the pointer
284     FillBufferDoneSpecificData* ED = (FillBufferDoneSpecificData*) P;
285 
286     OMX_HANDLETYPE aComponent = ED->hComponent;
287     OMX_PTR aAppData = ED->pAppData;
288     OMX_BUFFERHEADERTYPE* aBuffer = ED->pBuffer;
289 
290 
291     FillBufferDoneProcessing(aComponent, aAppData, aBuffer);
292 
293 
294     // release the allocated memory when no longer needed
295 
296     iThreadSafeHandlerFillBufferDone->iMemoryPool->deallocate(ED);
297     ED = NULL;
298 
299     return OsclSuccess;
300 }
301 /////////////////////////////////////////////////////////////////////////////
302 // Class Destructor
303 /////////////////////////////////////////////////////////////////////////////
~PVMFOMXEncNode()304 PVMFOMXEncNode::~PVMFOMXEncNode()
305 {
306     LogDiagnostics();
307 
308     //Clearup encoder
309     DeleteOMXEncoder();
310 
311     // Cleanup callback AOs and Mempools
312     if (iThreadSafeHandlerEventHandler)
313     {
314         OSCL_DELETE(iThreadSafeHandlerEventHandler);
315         iThreadSafeHandlerEventHandler = NULL;
316     }
317     if (iThreadSafeHandlerEmptyBufferDone)
318     {
319         OSCL_DELETE(iThreadSafeHandlerEmptyBufferDone);
320         iThreadSafeHandlerEmptyBufferDone = NULL;
321     }
322     if (iThreadSafeHandlerFillBufferDone)
323     {
324         OSCL_DELETE(iThreadSafeHandlerFillBufferDone);
325         iThreadSafeHandlerFillBufferDone = NULL;
326     }
327 
328     if (iMediaDataMemPool)
329     {
330         iMediaDataMemPool->removeRef();
331         iMediaDataMemPool = NULL;
332     }
333 
334     if (iOutBufMemoryPool)
335     {
336         iOutBufMemoryPool->removeRef();
337         iOutBufMemoryPool = NULL;
338     }
339     if (iInBufMemoryPool)
340     {
341         iInBufMemoryPool->removeRef();
342         iInBufMemoryPool = NULL;
343     }
344 
345     if (in_ctrl_struct_ptr)
346     {
347         oscl_free(in_ctrl_struct_ptr);
348         in_ctrl_struct_ptr = NULL;
349     }
350 
351     if (in_buff_hdr_ptr)
352     {
353         oscl_free(in_buff_hdr_ptr);
354         in_buff_hdr_ptr = NULL;
355     }
356 
357     if (out_ctrl_struct_ptr)
358     {
359         oscl_free(out_ctrl_struct_ptr);
360         out_ctrl_struct_ptr = NULL;
361     }
362 
363     if (out_buff_hdr_ptr)
364     {
365         oscl_free(out_buff_hdr_ptr);
366         out_buff_hdr_ptr = NULL;
367     }
368 
369     //Thread logoff
370     if (IsAdded())
371     {
372         RemoveFromScheduler();
373         iIsAdded = false;
374     }
375 
376     //Cleanup allocated interfaces
377 
378     //Cleanup allocated ports
379     ReleaseAllPorts();
380 
381     //Cleanup commands
382     //The command queues are self-deleting, but we want to
383     //notify the observer of unprocessed commands.
384     while (!iCurrentCommand.empty())
385     {
386         CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFFailure);
387     }
388     while (!iInputCommands.empty())
389     {
390         CommandComplete(iInputCommands, iInputCommands.front(), PVMFFailure);
391     }
392 
393     if (iNALSizeArray != NULL)
394     {
395         oscl_free(iNALSizeArray);
396     }
397 
398     if (iNALPtrArray != NULL)
399     {
400         oscl_free(iNALPtrArray);
401     }
402 
403     //Release Input buffer
404     iDataIn.Unbind();
405 
406 }
407 
408 /////////////////////////////////////////////////////////////////////////////
409 // Add AO to the scheduler
410 /////////////////////////////////////////////////////////////////////////////
ThreadLogon()411 PVMFStatus PVMFOMXEncNode::ThreadLogon()
412 {
413     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFOMXEncNode:ThreadLogon"));
414 
415     switch (iInterfaceState)
416     {
417         case EPVMFNodeCreated:
418             if (!IsAdded())
419             {
420                 AddToScheduler();
421                 iIsAdded = true;
422             }
423 
424             SetState(EPVMFNodeIdle);
425             return PVMFSuccess;
426             // break;   This break statement was removed to avoid compiler warning for Unreachable Code
427         default:
428             return PVMFErrInvalidState;
429             // break;   This break statement was removed to avoid compiler warning for Unreachable Code
430     }
431 }
432 
433 /////////////////////////////////////////////////////////////////////////////
434 // Remove AO from the scheduler
435 /////////////////////////////////////////////////////////////////////////////
ThreadLogoff()436 PVMFStatus PVMFOMXEncNode::ThreadLogoff()
437 {
438     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFOMXEncNode-%s::ThreadLogoff", iNodeTypeId));
439 
440     switch (iInterfaceState)
441     {
442         case EPVMFNodeIdle:
443             if (IsAdded())
444             {
445                 RemoveFromScheduler();
446                 iIsAdded = false;
447             }
448             iLogger = NULL;
449             SetState(EPVMFNodeCreated);
450             return PVMFSuccess;
451             // break;   This break statement was removed to avoid compiler warning for Unreachable Code
452 
453         default:
454             return PVMFErrInvalidState;
455             // break;   This break statement was removed to avoid compiler warning for Unreachable Code
456     }
457 }
458 
459 /////////////////////////////////////////////////////////////////////////////
GetCapability(PVMFNodeCapability & aNodeCapability)460 PVMFStatus PVMFOMXEncNode::GetCapability(PVMFNodeCapability& aNodeCapability)
461 {
462     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::GetCapability() called", iNodeTypeId));
463 
464     aNodeCapability = iCapability;
465     return PVMFSuccess;
466 }
467 
468 /////////////////////////////////////////////////////////////////////////////
GetPorts(const PVMFPortFilter * aFilter)469 PVMFPortIter* PVMFOMXEncNode::GetPorts(const PVMFPortFilter* aFilter)
470 {
471     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::GetPorts() %s called", iNodeTypeId));
472 
473     OSCL_UNUSED_ARG(aFilter);
474 
475     return NULL;
476 }
477 
478 /////////////////////////////////////////////////////////////////////////////
QueueCommandL(PVMFOMXEncNodeCommand & aCmd)479 PVMFCommandId PVMFOMXEncNode::QueueCommandL(PVMFOMXEncNodeCommand& aCmd)
480 {
481     PVMFCommandId id;
482 
483     id = iInputCommands.AddL(aCmd);
484 
485     if (iInputCommands.size() == 1)
486     {
487         //wakeup the AO all the rest of input commands will reschedule the AO in Run
488         RunIfNotReady();
489     }
490     return id;
491 }
492 
493 /////////////////////////////////////////////////////////////////////////////
QueryUUID(PVMFSessionId s,const PvmfMimeString & aMimeType,Oscl_Vector<PVUuid,PVMFOMXEncNodeAllocator> & aUuids,bool aExactUuidsOnly,const OsclAny * aContext)494 PVMFCommandId PVMFOMXEncNode::QueryUUID(PVMFSessionId s, const PvmfMimeString& aMimeType,
495                                         Oscl_Vector<PVUuid, PVMFOMXEncNodeAllocator>& aUuids,
496                                         bool aExactUuidsOnly,
497                                         const OsclAny* aContext)
498 {
499     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::QueryUUID() called", iNodeTypeId));
500     PVMFOMXEncNodeCommand cmd;
501     cmd.PVMFOMXEncNodeCommandBase::Construct(s, PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_QUERYUUID, aMimeType, aUuids, aExactUuidsOnly, aContext);
502     return QueueCommandL(cmd);
503 }
504 
505 /////////////////////////////////////////////////////////////////////////////
QueryInterface(PVMFSessionId s,const PVUuid & aUuid,PVInterface * & aInterfacePtr,const OsclAny * aContext)506 PVMFCommandId PVMFOMXEncNode::QueryInterface(PVMFSessionId s, const PVUuid& aUuid,
507         PVInterface*& aInterfacePtr,
508         const OsclAny* aContext)
509 {
510     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::QueryInterface() called", iNodeTypeId));
511     PVMFOMXEncNodeCommand cmd;
512     cmd.PVMFOMXEncNodeCommandBase::Construct(s, PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_QUERYINTERFACE, aUuid, aInterfacePtr, aContext);
513     return QueueCommandL(cmd);
514 }
515 
516 /////////////////////////////////////////////////////////////////////////////
RequestPort(PVMFSessionId s,int32 aPortTag,const PvmfMimeString * aPortConfig,const OsclAny * aContext)517 PVMFCommandId PVMFOMXEncNode::RequestPort(PVMFSessionId s, int32 aPortTag, const PvmfMimeString* aPortConfig, const OsclAny* aContext)
518 {
519     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::RequestPort() called", iNodeTypeId));
520     PVMFOMXEncNodeCommand cmd;
521 
522     // IMPORTANT NOTE - ENGINE IS SENDING THE MIME TYPE FOR THE ENCODER INPUT/OUTPUT FORMAT THRU THE PORT PARAMETER
523     cmd.PVMFOMXEncNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_REQUESTPORT, aPortTag, aPortConfig, aContext);
524     return QueueCommandL(cmd);
525 
526 }
527 
528 /////////////////////////////////////////////////////////////////////////////
ReleasePort(PVMFSessionId s,PVMFPortInterface & aPort,const OsclAny * aContext)529 PVMFStatus PVMFOMXEncNode::ReleasePort(PVMFSessionId s, PVMFPortInterface& aPort, const OsclAny* aContext)
530 {
531     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::ReleasePort() called", iNodeTypeId));
532     PVMFOMXEncNodeCommand cmd;
533     cmd.PVMFOMXEncNodeCommandBase::Construct(s, PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_RELEASEPORT, aPort, aContext);
534     return QueueCommandL(cmd);
535 }
536 
537 /////////////////////////////////////////////////////////////////////////////
Init(PVMFSessionId s,const OsclAny * aContext)538 PVMFCommandId PVMFOMXEncNode::Init(PVMFSessionId s, const OsclAny* aContext)
539 {
540     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::Init() called", iNodeTypeId));
541     PVMFOMXEncNodeCommand cmd;
542     cmd.PVMFOMXEncNodeCommandBase::Construct(s, PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_INIT, aContext);
543     return QueueCommandL(cmd);
544 }
545 
546 /////////////////////////////////////////////////////////////////////////////
Prepare(PVMFSessionId s,const OsclAny * aContext)547 PVMFCommandId PVMFOMXEncNode::Prepare(PVMFSessionId s, const OsclAny* aContext)
548 {
549     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::Prepare() called", iNodeTypeId));
550     PVMFOMXEncNodeCommand cmd;
551     cmd.PVMFOMXEncNodeCommandBase::Construct(s, PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_PREPARE, aContext);
552     return QueueCommandL(cmd);
553 }
554 
555 /////////////////////////////////////////////////////////////////////////////
Start(PVMFSessionId s,const OsclAny * aContext)556 PVMFCommandId PVMFOMXEncNode::Start(PVMFSessionId s, const OsclAny* aContext)
557 {
558     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::Start() called", iNodeTypeId));
559     PVMFOMXEncNodeCommand cmd;
560     cmd.PVMFOMXEncNodeCommandBase::Construct(s, PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_START, aContext);
561     return QueueCommandL(cmd);
562 }
563 
564 /////////////////////////////////////////////////////////////////////////////
Stop(PVMFSessionId s,const OsclAny * aContext)565 PVMFCommandId PVMFOMXEncNode::Stop(PVMFSessionId s, const OsclAny* aContext)
566 {
567     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::Stop() called", iNodeTypeId));
568     PVMFOMXEncNodeCommand cmd;
569     cmd.PVMFOMXEncNodeCommandBase::Construct(s, PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_STOP, aContext);
570     return QueueCommandL(cmd);
571 }
572 
573 /////////////////////////////////////////////////////////////////////////////
Flush(PVMFSessionId s,const OsclAny * aContext)574 PVMFCommandId PVMFOMXEncNode::Flush(PVMFSessionId s, const OsclAny* aContext)
575 {
576     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::Flush() called", iNodeTypeId));
577     PVMFOMXEncNodeCommand cmd;
578     cmd.PVMFOMXEncNodeCommandBase::Construct(s, PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_FLUSH, aContext);
579     return QueueCommandL(cmd);
580 }
581 
582 /////////////////////////////////////////////////////////////////////////////
Pause(PVMFSessionId s,const OsclAny * aContext)583 PVMFCommandId PVMFOMXEncNode::Pause(PVMFSessionId s, const OsclAny* aContext)
584 {
585     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::Pause() called", iNodeTypeId));
586     PVMFOMXEncNodeCommand cmd;
587     cmd.PVMFOMXEncNodeCommandBase::Construct(s, PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_PAUSE, aContext);
588     return QueueCommandL(cmd);
589 }
590 
591 /////////////////////////////////////////////////////////////////////////////
Reset(PVMFSessionId s,const OsclAny * aContext)592 PVMFCommandId PVMFOMXEncNode::Reset(PVMFSessionId s, const OsclAny* aContext)
593 {
594     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::Reset() called", iNodeTypeId));
595     PVMFOMXEncNodeCommand cmd;
596     cmd.PVMFOMXEncNodeCommandBase::Construct(s, PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_RESET, aContext);
597     return QueueCommandL(cmd);
598 }
599 
600 /////////////////////////////////////////////////////////////////////////////
CancelAllCommands(PVMFSessionId s,const OsclAny * aContext)601 PVMFCommandId PVMFOMXEncNode::CancelAllCommands(PVMFSessionId s, const OsclAny* aContext)
602 {
603     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::CancelAllCommands() called", iNodeTypeId));
604     PVMFOMXEncNodeCommand cmd;
605     cmd.PVMFOMXEncNodeCommandBase::Construct(s, PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_CANCELALL, aContext);
606     return QueueCommandL(cmd);
607 }
608 
609 /////////////////////////////////////////////////////////////////////////////
CancelCommand(PVMFSessionId s,PVMFCommandId aCmdId,const OsclAny * aContext)610 PVMFCommandId PVMFOMXEncNode::CancelCommand(PVMFSessionId s, PVMFCommandId aCmdId, const OsclAny* aContext)
611 {
612     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::CancelCommand() called", iNodeTypeId));
613     PVMFOMXEncNodeCommand cmd;
614     cmd.PVMFOMXEncNodeCommandBase::Construct(s, PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_CANCELCMD, aCmdId, aContext);
615     return QueueCommandL(cmd);
616 }
617 
618 
619 
620 
621 
622 /////////////////////
623 // Private Section //
624 /////////////////////
625 
626 /////////////////////////////////////////////////////////////////////////////
627 // Class Constructor
628 /////////////////////////////////////////////////////////////////////////////
PVMFOMXEncNode(int32 aPriority)629 PVMFOMXEncNode::PVMFOMXEncNode(int32 aPriority) :
630         OsclActiveObject(aPriority, "PVMFOMXEncNode"),
631         iInPort(NULL),
632         iOutPort(NULL),
633         iOutBufMemoryPool(NULL),
634         iMediaDataMemPool(NULL),
635         iOMXComponentOutputBufferSize(0),
636         iOutputAllocSize(0),
637         iNumOutstandingOutputBuffers(0),
638         iNumOutstandingInputBuffers(0),
639         iProcessingState(EPVMFOMXEncNodeProcessingState_Idle),
640         iOMXEncoder(NULL),
641         iSendBOS(false),
642         iStreamID(0),
643         iBOSTimestamp(0),
644         iSeqNum(0),
645         iSeqNum_In(0),
646         iIsAdded(true),
647         iLogger(NULL),
648         iDataPathLogger(NULL),
649         iClockLogger(NULL),
650         iExtensionRefCount(0),
651         iEndOfDataReached(false),
652         iEndOfDataTimestamp(0),
653         iDiagnosticsLogger(NULL),
654         iDiagnosticsLogged(false),
655         iAvgBitrateValue(0),
656         iResetInProgress(false),
657         iResetMsgSent(false),
658         iStopInResetMsgSent(false),
659         bIsQCOMOmxComp(false)
660 {
661     iInterfaceState = EPVMFNodeCreated;
662 
663 
664     // Allocate memory for VOL header
665     uint refCounterSize = oscl_mem_aligned_size(sizeof(OsclRefCounterDA));
666     uint VolHdrSize = refCounterSize + DEFAULT_VOL_HEADER_LENGTH;
667     uint8 *memBufferVOLHeader = NULL;
668 
669     uint ParamSetSize = refCounterSize + DEFAULT_PARAMS_SET_LENGTH;
670     uint8 *memBufferParamSet = NULL;
671 
672 
673     int32 err;
674     OSCL_TRY(err,
675 
676              //Create the input command queue.  Use a reserve to avoid lots of
677              //dynamic memory allocation.
678              iInputCommands.Construct(PVMF_OMXENC_NODE_COMMAND_ID_START, PVMF_OMXENC_NODE_COMMAND_VECTOR_RESERVE);
679 
680              //Create the "current command" queue.  It will only contain one
681              //command at a time, so use a reserve of 1.
682              iCurrentCommand.Construct(0, 1);
683 
684              //Set the node capability data.
685              //This node can support an unlimited number of ports.
686              iCapability.iCanSupportMultipleInputPorts = false;
687              iCapability.iCanSupportMultipleOutputPorts = false;
688              iCapability.iHasMaxNumberOfPorts = true;
689              iCapability.iMaxNumberOfPorts = 2;
690 
691              // video output
692              iCapability.iOutputFormatCapability.push_back(PVMF_MIME_H264_VIDEO_MP4);
693              iCapability.iOutputFormatCapability.push_back(PVMF_MIME_H264_VIDEO_RAW);
694              //iCapability.iOutputFormatCapability.push_back(PVMF_MIME_H264_VIDEO);
695              iCapability.iOutputFormatCapability.push_back(PVMF_MIME_M4V);
696              iCapability.iOutputFormatCapability.push_back(PVMF_MIME_H2631998);
697              iCapability.iOutputFormatCapability.push_back(PVMF_MIME_H2632000);
698              //iCapability.iOutputFormatCapability.push_back(PVMF_MIME_WMV);
699              // audio output
700              iCapability.iOutputFormatCapability.push_back(PVMF_MIME_AMR_IETF);
701              iCapability.iOutputFormatCapability.push_back(PVMF_MIME_AMRWB_IETF);
702              iCapability.iOutputFormatCapability.push_back(PVMF_MIME_AMR_IF2);
703              iCapability.iOutputFormatCapability.push_back(PVMF_MIME_ADTS);
704              iCapability.iOutputFormatCapability.push_back(PVMF_MIME_ADIF);
705              iCapability.iOutputFormatCapability.push_back(PVMF_MIME_MPEG4_AUDIO);
706 
707              // video input
708              iCapability.iInputFormatCapability.push_back(PVMF_MIME_YUV420);
709              iCapability.iInputFormatCapability.push_back(PVMF_MIME_YUV422);
710              iCapability.iInputFormatCapability.push_back(PVMF_MIME_RGB24);
711              iCapability.iInputFormatCapability.push_back(PVMF_MIME_RGB12);
712 
713              // audio input
714              iCapability.iInputFormatCapability.push_back(PVMF_MIME_PCM16);
715 
716 
717 
718              iAvailableMetadataKeys.reserve(PVMF_OMXENC_NUM_METADATA_VALUES);
719              iAvailableMetadataKeys.clear();
720 
721              // for VOL header
722              memBufferVOLHeader = (uint8*)iAlloc.allocate(VolHdrSize);
723              if (!memBufferVOLHeader)
724 {
725     OSCL_LEAVE(PVMFErrNoMemory);
726     }
727 
728     memBufferParamSet = (uint8*) iAlloc.allocate(ParamSetSize);
729     if (!memBufferParamSet)
730 {
731     OSCL_LEAVE(PVMFErrNoMemory);
732     }
733 
734             );
735 
736     // Save default VOL header
737     oscl_memset(memBufferVOLHeader, 0, DEFAULT_VOL_HEADER_LENGTH);
738     OsclMemoryFragment volHeader;
739     OsclRefCounter* refCounterVOLHeader = new(memBufferVOLHeader) OsclRefCounterDA(memBufferVOLHeader,
740             (OsclDestructDealloc*)&iAlloc);
741     memBufferVOLHeader += refCounterSize;
742     volHeader.ptr = memBufferVOLHeader;
743     oscl_memcpy(volHeader.ptr, (OsclAny*)DEFAULT_VOL_HEADER, DEFAULT_VOL_HEADER_LENGTH);
744     volHeader.len = DEFAULT_VOL_HEADER_LENGTH;
745     iVolHeader = OsclRefCounterMemFrag(volHeader, refCounterVOLHeader, DEFAULT_VOL_HEADER_LENGTH);
746 
747 
748     // construct SPS&PPS placeholder
749     oscl_memset(memBufferParamSet, 0, DEFAULT_PARAMS_SET_LENGTH);
750     OsclMemoryFragment paramSet;
751     OsclRefCounter* refCounterParamSet = new(memBufferParamSet) OsclRefCounterDA(memBufferParamSet,
752             (OsclDestructDealloc*)&iAlloc);
753     memBufferParamSet += refCounterSize;
754     paramSet.ptr = memBufferParamSet;
755     paramSet.len = DEFAULT_PARAMS_SET_LENGTH;
756 
757     iParamSet = OsclRefCounterMemFrag(paramSet, refCounterParamSet, DEFAULT_PARAMS_SET_LENGTH);
758 
759     // initialize length and number of sps/ppss
760     iParamSet.getMemFrag().len = 0;
761     iNumPPSs = 0;
762     iNumSPSs = 0;
763     iSpsPpsSequenceOver = false;
764     iFirstNAL = false; //set this to false so that mp4 can proceed without a problem.
765     // in case of AVC, this flag will be set after spspps
766 
767     iNALSizeArray = NULL;
768     iNALPtrArray = NULL;
769     iNALSizeArrayMaxElems = 0;
770     iNumNALs = 0;
771     iFirstNALStartCodeSize = 0;
772 
773     iThreadSafeHandlerEventHandler = NULL;
774     iThreadSafeHandlerEmptyBufferDone = NULL;
775     iThreadSafeHandlerFillBufferDone = NULL;
776 
777     iInBufMemoryPool = NULL;
778     iOutBufMemoryPool = NULL;
779 
780     in_ctrl_struct_ptr = NULL;
781     in_buff_hdr_ptr = NULL;
782     out_ctrl_struct_ptr = NULL;
783     out_buff_hdr_ptr = NULL;
784 
785     // init to some value
786     iOMXComponentOutputBufferSize = 0;
787     iNumOutputBuffers = 0;
788     iOMXComponentInputBufferSize = 0;
789     iNumInputBuffers = 0;
790 
791     iDoNotSendOutputBuffersDownstreamFlag = false;
792     iDoNotSaveInputBuffersFlag = false;
793 
794 
795     iOutputBuffersFreed = true;// buffers have not been created yet, so they can be considered freed
796     iInputBuffersFreed = true;
797 
798     // dynamic port reconfig init vars
799     iSecondPortReportedChange = false;
800     iDynamicReconfigInProgress = false;
801 
802     // EOS flag init
803     iIsEOSSentToComponent = false;
804     iIsEOSReceivedFromComponent = false;
805 
806     // init state of component
807     iCurrentEncoderState = OMX_StateInvalid;
808 
809     iTimeStampOut = 0;
810     iTimeStampPrevious = 0;
811     iBufferLenOut = 0;
812     iBufferLenPrevious = 0;
813     iEndOfFrameFlagPrevious = 0;
814     iKeyFrameFlagPrevious = 0;
815     iEndOfNALFlagPrevious = 0;
816 
817 
818     iEndOfFrameFlagOut = 0;
819     iKeyFrameFlagOut = 0;
820     iEndOfNALFlagOut = 0;
821 
822     // counts output frames (for logging)
823     iFrameCounter = 0;
824     iInFormat = PVMF_MIME_FORMAT_UNKNOWN;
825     iOutFormat = PVMF_MIME_FORMAT_UNKNOWN;
826 
827     // zero out encoder param structure
828 
829     oscl_memset(&iVideoInputFormat, 0, sizeof(iVideoInputFormat));
830 
831     // set default values
832     iVideoInputFormat.iVideoFormat = EI_YUV420;
833     iVideoInputFormat.iFrameWidth = DEFAULT_FRAME_WIDTH;
834     iVideoInputFormat.iFrameHeight = DEFAULT_FRAME_HEIGHT;
835     iVideoInputFormat.iFrameRate = (float)DEFAULT_FRAME_RATE;
836     iVideoInputFormat.iFrameOrientation = 0;
837 
838     oscl_memset(&iVideoEncodeParam, 0, sizeof(iVideoEncodeParam));
839 
840     iVideoEncodeParam.iEncodeID = 0;
841     iVideoEncodeParam.iNumLayer = 1;
842     iVideoEncodeParam.iFrameWidth[0] = DEFAULT_FRAME_WIDTH;
843     iVideoEncodeParam.iFrameHeight[0] = DEFAULT_FRAME_HEIGHT;
844     iVideoEncodeParam.iBitRate[0] = DEFAULT_BITRATE;
845     iVideoEncodeParam.iFrameRate[0] = (float)DEFAULT_FRAME_RATE;
846     iVideoEncodeParam.iFrameQuality = 10;
847     iVideoEncodeParam.iSceneDetection = false;
848     iVideoEncodeParam.iRVLCEnable = false;
849     iVideoEncodeParam.iIFrameInterval = DEFAULT_I_FRAME_INTERVAL;
850     iVideoEncodeParam.iBufferDelay = (float)0.2;
851     iVideoEncodeParam.iShortHeader = false;
852     iVideoEncodeParam.iDataPartitioning = false;
853     iVideoEncodeParam.iResyncMarker = true;
854 
855     // set the default rate control type to variable bit rate control
856     // since it has better performance
857     iVideoEncodeParam.iRateControlType = PVMFVEN_RATE_CONTROL_VBR;
858     iVideoEncodeParam.iIquant[0] = 15;
859     iVideoEncodeParam.iPquant[0] = 12;
860     iVideoEncodeParam.iBquant[0] = 12;
861     iVideoEncodeParam.iSearchRange = 16;
862     iVideoEncodeParam.iMV8x8 = false;
863     iVideoEncodeParam.iMVHalfPel = true;
864     iVideoEncodeParam.iPacketSize = 256;
865     iVideoEncodeParam.iNoCurrentSkip = false;
866     iVideoEncodeParam.iNoFrameSkip = false;
867     iVideoEncodeParam.iClipDuration = 0;
868     iVideoEncodeParam.iProfileLevel = EI_CORE_LEVEL2;
869     /////////////////AVC SPECIFIC///////////////////////////
870     iVideoEncodeParam.iEncMode = EI_ENCMODE_RECORDER;
871     iVideoEncodeParam.iAVCProfile = EI_PROFILE_BASELINE;
872     iVideoEncodeParam.iAVCLevel = EI_LEVEL_11;
873 
874 
875     oscl_memset(&iAudioInputFormat, 0, sizeof(iAudioInputFormat));
876     // Currently, set according to AMR values
877     iAudioInputFormat.iInputInterleaveMode = EINTERLEAVE_LR;
878     iAudioInputFormat.iInputBitsPerSample = 16;
879     iAudioInputFormat.iInputNumChannels = 1;
880     iAudioInputFormat.iInputSamplingRate = 8000;
881 
882     oscl_memset(&iAudioEncodeParam, 0, sizeof(iAudioEncodeParam));
883 
884     iAudioEncodeParam.iMaxNumOutputFramesPerBuffer = MAX_NUM_AMR_FRAMES_PER_BUFFER;
885     iAudioEncodeParam.iAMRBitrate = GSM_AMR_12_2;
886     iAudioEncodeParam.iOutputBitrate = 24000;
887     iAudioEncodeParam.iOutputNumChannels = iAudioInputFormat.iInputNumChannels;
888     iAudioEncodeParam.iOutputSamplingRate = iAudioInputFormat.iInputSamplingRate;
889 
890 
891 #ifdef _TEST_AE_ERROR_HANDLING
892     iErrorHandlingInit = false;
893     iErrorHandlingEncodeCount = 0;
894     iCountFrames = 0;
895     iErrorDataPathStall = 0;
896     iErrorNodeCmd = 0;
897     iErrorConfigHeader = false;
898     iErrorEncodeFlag = 0;
899 #endif
900 
901     sendYuvFsi = true;
902 
903     iNodeTypeId = LOG_ID_UNKNOWN;
904     iLogger = PVLogger::GetLoggerObject("PVMFOMXEncNode");
905     iRunlLogger = PVLogger::GetLoggerObject("Run.PVMFOMXEncNode");
906     iDataPathLogger = PVLogger::GetLoggerObject("datapath");
907     iClockLogger = PVLogger::GetLoggerObject("clock");
908     iDiagnosticsLogger = PVLogger::GetLoggerObject("pvplayerdiagnostics.encnode.OMXEncnode");
909 }
910 
911 /////////////////////////////////////////////////////////////////////////////
912 // Local Run Routine
913 /////////////////////////////////////////////////////////////////////////////
Run()914 void PVMFOMXEncNode::Run()
915 {
916     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::Run() In", iNodeTypeId));
917 
918     // if reset is in progress, call DoReset again until Reset Msg is sent
919     if ((iResetInProgress == true) &&
920             (iResetMsgSent == false) &&
921             (iCurrentCommand.size() > 0) &&
922             (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_RESET)
923        )
924     {
925         DoReset(iCurrentCommand.front());
926         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVMFOMXEncNode-%s::Run() - Calling DoReset", iNodeTypeId));
927         return; // don't do anything else
928     }
929     //Check for NODE commands...
930     if (!iInputCommands.empty())
931     {
932         if (ProcessCommand(iInputCommands.front()))
933         {
934             if (iInterfaceState != EPVMFNodeCreated
935                     && (!iInputCommands.empty() || (iInPort && (iInPort->IncomingMsgQueueSize() > 0)) ||
936                         (iDataIn.GetRep() != NULL)))
937             {
938                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVMFOMXEncNode-%s::Run() - rescheduling after process command", iNodeTypeId));
939                 RunIfNotReady();
940             }
941             return;
942         }
943 
944         if (!iInputCommands.empty())
945         {
946             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVMFOMXEncNode-%s::Run() - rescheduling to process more commands", iNodeTypeId));
947             RunIfNotReady();
948         }
949     }
950     else
951     {
952         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVMFOMXEncNode-%s::Run() - Input commands empty", iNodeTypeId));
953     }
954 
955     if (((iCurrentCommand.size() == 0) && (iInterfaceState != EPVMFNodeStarted)) ||
956             ((iCurrentCommand.size() > 0) && (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_START) && (iInterfaceState != EPVMFNodeStarted)))
957     {
958         // rescheduling because of input data will be handled in Command Processing Part
959         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVMFOMXEncNode-%s::Run() - Node not in Started state yet", iNodeTypeId));
960         return;
961     }
962 
963 
964     // Process port activity, push out all outgoing messages
965     if (iOutPort)
966     {
967         while (iOutPort->OutgoingMsgQueueSize())
968         {
969             // if port is busy it is going to wakeup from port ready event
970             if (!ProcessOutgoingMsg(iOutPort))
971             {
972                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVMFOMXEncNode-%s::Run() - Outgoing Port Busy, cannot send more msgs", iNodeTypeId));
973                 break;
974             }
975         }
976     }
977     int loopCount = 0;
978 #if (PVLOGGER_INST_LEVEL >= PVLOGMSG_INST_REL)
979     uint32 startticks = OsclTickCount::TickCount();
980     uint32 starttime = OsclTickCount::TicksToMsec(startticks);
981 #endif
982     do // Try to consume all the data from the Input port
983     {
984         // Process port activity if there is no input data that is being processed
985         // Do not accept any input if EOS needs to be sent out
986         if (iInPort && (iInPort->IncomingMsgQueueSize() > 0) && (iDataIn.GetRep() == NULL) && !iEndOfDataReached)
987         {
988             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVMFOMXEncNode-%s::Run() - Getting more input", iNodeTypeId));
989             if (!ProcessIncomingMsg(iInPort))
990             {
991                 //Re-schedule to come back.
992                 RunIfNotReady();
993                 return;
994             }
995         }
996 
997         if (iSendBOS)
998         {
999             SendBeginOfMediaStreamCommand();
1000         }
1001 
1002         // If in init or ready to encode state, process data in the input port if there is input available and input buffers are present
1003         // (note: at EOS, iDataIn will not be available)
1004         if ((iDataIn.GetRep() != NULL) ||
1005                 ((iNumOutstandingOutputBuffers < iNumOutputBuffers) &&
1006                  (iProcessingState == EPVMFOMXEncNodeProcessingState_ReadyToEncode) &&
1007                  (iResetMsgSent == false)) ||
1008                 ((iDynamicReconfigInProgress == true) && (iResetMsgSent == false))
1009            )
1010         {
1011             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1012                             (0, "PVMFOMXEncNode-%s::Run() - Calling HandleProcessingState", iNodeTypeId));
1013 
1014             // input data is available, that means there is data to be encoded
1015             if (HandleProcessingState() != PVMFSuccess)
1016             {
1017                 // If HandleProcessingState does not return Success, we must wait for an event
1018                 // no point in  rescheduling
1019                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1020                                 (0, "PVMFOMXEncNode-%s::Run() - HandleProcessingState did not return Success", iNodeTypeId));
1021                 return;
1022             }
1023         }
1024         loopCount++;
1025     }
1026     while (iInPort &&
1027             (((iInPort->IncomingMsgQueueSize() > 0) || (iDataIn.GetRep() != NULL)) && (iNumOutstandingInputBuffers < iNumInputBuffers))
1028             && (!iEndOfDataReached)
1029             && (iResetMsgSent == false)
1030           );
1031 #if (PVLOGGER_INST_LEVEL >= PVLOGMSG_INST_REL)
1032     uint32 endticks = OsclTickCount::TickCount();
1033     uint32 endtime = OsclTickCount::TicksToMsec(endticks);
1034     uint32 timeinloop;
1035     timeinloop  = (endtime - starttime);
1036     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iRunlLogger, PVLOGMSG_INFO,
1037                     (0, "PVMFOMXEncNode-%s::Run() - LoopCount = %d, Time spent in loop(in ms) = %d, iNumOutstandingInputBuffers = %d, iNumOutstandingOutputBuffers = %d ", iNodeTypeId,
1038                      loopCount, timeinloop, iNumOutstandingInputBuffers, iNumOutstandingOutputBuffers));
1039 #endif
1040     // EOS processing:
1041     // first send an empty buffer to OMX component and mark the EOS flag
1042     // wait for the OMX component to send async event to indicate that it has reached this EOS buffer
1043     // then, create and send the EOS message downstream
1044 
1045     if (iEndOfDataReached && !iDynamicReconfigInProgress)
1046     {
1047 
1048         // if EOS was not sent yet and we have an available input buffer, send EOS buffer to component
1049         if (!iIsEOSSentToComponent && (iNumOutstandingInputBuffers < iNumInputBuffers))
1050         {
1051             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1052                             (0, "PVMFOMXEncNode-%s::Run() - Sending EOS marked buffer To Component ", iNodeTypeId));
1053 
1054             iIsEOSSentToComponent = true;
1055 
1056 
1057             // if the component is not yet initialized or if it's in the middle of port reconfig,
1058             // don't send EOS buffer to component. It does not care. Just set the flag as if we received
1059             // EOS from the component to enable sending EOS downstream
1060             if (iProcessingState != EPVMFOMXEncNodeProcessingState_ReadyToEncode)
1061             {
1062 
1063                 iIsEOSReceivedFromComponent = true;
1064             }
1065             else if (!SendEOSBufferToOMXComponent())
1066             {
1067                 // for some reason, Component can't receive the EOS buffer
1068                 // it could be that it is not initialized yet (because EOS could be the first msg). In this case,
1069                 // send the EOS downstream anyway
1070                 iIsEOSReceivedFromComponent = true;
1071             }
1072         }
1073 
1074         // DV: we must wait for event (acknowledgment from component)
1075         // before sending EOS downstream. This is because OMX Component will send
1076         // the EOS event only after processing remaining buffers
1077 
1078         if (iIsEOSReceivedFromComponent)
1079         {
1080 
1081             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1082                             (0, "PVMFOMXEncNode-%s::Run() - Received EOS from component, Sending EOS msg downstream ", iNodeTypeId));
1083 
1084             if (iOutPort && iOutPort->IsOutgoingQueueBusy())
1085             {
1086                 // note: we already tried to empty the outgoing q. If it's still busy,
1087                 // it means that output port is busy. Just return and wait for the port to become free.
1088                 // this will wake up the node and it will send out a msg from the q etc.
1089                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1090                                 (0, "PVMFOMXEncNode-%s::Run() - - EOS cannot be sent downstream, outgoing queue busy - wait", iNodeTypeId));
1091                 return;
1092             }
1093 
1094             if (SendEndOfTrackCommand()) // this will only q the EOS
1095             {
1096                 // EOS send downstream OK, so reset the flag
1097                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1098                                 (0, "PVMFOMXEncNode-%s::Run() - EOS was queued to be sent downstream", iNodeTypeId));
1099 
1100                 iEndOfDataReached = false; // to resume normal processing, reset the flags
1101                 iIsEOSSentToComponent = false;
1102                 iIsEOSReceivedFromComponent = false;
1103 
1104                 RunIfNotReady(); // Run again to send out the EOS msg from the outgoing q, and resume
1105                 // normal processing
1106 
1107                 // END OF STREAM EVENT reported by the downstream node.
1108                 //ReportInfoEvent(PVMFInfoEndOfData);
1109             }
1110         }
1111         else
1112         {
1113             // keep sending output buffers, it's possible that the component needs to flush output
1114             //  data at the end
1115             while (iNumOutstandingOutputBuffers < iNumOutputBuffers)
1116             {
1117                 if (!SendOutputBufferToOMXComponent())
1118                     break;
1119             }
1120         }
1121 
1122     }
1123 
1124 
1125     //Check for flash command complition...
1126     if (iInPort && iOutPort && (iCurrentCommand.size() > 0) &&
1127             (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_FLUSH) &&
1128             (iInPort->IncomingMsgQueueSize() == 0) &&
1129             (iOutPort->OutgoingMsgQueueSize() == 0) &&
1130             (iDataIn.GetRep() == NULL) &&
1131             (iNumOutstandingOutputBuffers == iNumOutputBuffers) && // all output buffers are with the component or outstanding
1132             (iNumOutstandingInputBuffers == 0) // all input buffers were processed and returned. These 2 conditions mean the component is idle
1133        )
1134     {
1135         //flush command is almost completed
1136         //Debug check-- all the port queues should be empty at this point.
1137         OMX_ERRORTYPE err = OMX_ErrorNone;
1138         OMX_STATETYPE sState = OMX_StateInvalid;
1139 
1140         OSCL_ASSERT(iInPort->IncomingMsgQueueSize() == 0 && iOutPort->OutgoingMsgQueueSize() == 0);
1141 
1142         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVMFOMXEncNode-%s::Run() - Flush pending", iNodeTypeId));
1143 
1144         // now, drive the state of the omx component to IDLE - wait for the callback from the component and send cmd complete from there
1145         iDataIn.Unbind();
1146         iPreviousMediaData.Unbind(); // make sure nothing is holding this data
1147         if ((iOutFormat == PVMF_MIME_H264_VIDEO_MP4) || (iOutFormat == PVMF_MIME_H264_VIDEO_RAW))
1148         {
1149             // prepare for next start
1150             iFirstNAL = true;
1151         }
1152 
1153         // Clear the data flags
1154 
1155         iEndOfDataReached = false;
1156         iIsEOSSentToComponent = false;
1157         iIsEOSReceivedFromComponent = false;
1158 
1159 
1160         iDoNotSendOutputBuffersDownstreamFlag = true; // stop sending output buffers downstream
1161         iDoNotSaveInputBuffersFlag = true;
1162 
1163 
1164         //Get state of OpenMAX encoder
1165         err = OMX_GetState(iOMXEncoder, &sState);
1166         if (err != OMX_ErrorNone)
1167         {
1168             //Error condition report
1169             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
1170                             (0, "PVMFOMXEncNode-%s::Run(): Flush pending - Can't get State of encoder!", iNodeTypeId));
1171 
1172             sState = OMX_StateInvalid;
1173         }
1174 
1175         if ((sState == OMX_StateExecuting) || (sState == OMX_StatePause))
1176         {
1177             /* Change state to OMX_StateIdle from OMX_StateExecuting or OMX_StatePause. */
1178 
1179             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1180                             (0, "PVMFOMXEncNode-%s::Run(): Flush pending:  Changing Component State Executing->Idle or Pause->Idle", iNodeTypeId));
1181 
1182             err = OMX_SendCommand(iOMXEncoder, OMX_CommandStateSet, OMX_StateIdle, NULL);
1183             if (err != OMX_ErrorNone)
1184             {
1185                 //Error condition report
1186                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
1187                                 (0, "PVMFOMXEncNode-%s::Run(): Flush pending : Can't send StateSet command to encoder!", iNodeTypeId));
1188 
1189                 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFErrInvalidState);
1190                 return;
1191             }
1192 
1193             // prevent the node from sending more buffers etc.
1194             // if port reconfiguration is in process, let the state remain one of the port config states
1195             //  if there is a start command, we can do it seemlessly (by continuing the port reconfig)
1196             if (iProcessingState == EPVMFOMXEncNodeProcessingState_ReadyToEncode)
1197                 iProcessingState = EPVMFOMXEncNodeProcessingState_Stopping;
1198 
1199         }
1200         else
1201         {
1202             //Error condition report
1203             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
1204                             (0, "PVMFOMXEncNode-%s::Run(): Flush pending : Encoder is not in the Executing or Pause state!", iNodeTypeId));
1205 
1206             CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFErrInvalidState);
1207             return;
1208         }
1209 
1210 
1211     }
1212 
1213     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::Run() Out", iNodeTypeId));
1214 }
1215 
1216 /////////////////////////////////////////////////////////////////////////////
1217 // This routine will dispatch recived commands
1218 /////////////////////////////////////////////////////////////////////////////
ProcessCommand(PVMFOMXEncNodeCommand & aCmd)1219 bool PVMFOMXEncNode::ProcessCommand(PVMFOMXEncNodeCommand& aCmd)
1220 {
1221     //normally this node will not start processing one command
1222     //until the prior one is finished.  However, a hi priority
1223     //command such as Cancel must be able to interrupt a command
1224     //in progress.
1225     if (!iCurrentCommand.empty() && !aCmd.hipri())
1226         return false;
1227 
1228     switch (aCmd.iCmd)
1229     {
1230         case PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_QUERYUUID:
1231             DoQueryUuid(aCmd);
1232             break;
1233 
1234         case PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_QUERYINTERFACE:
1235             DoQueryInterface(aCmd);
1236             break;
1237 
1238         case PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_REQUESTPORT:
1239             DoRequestPort(aCmd);
1240             break;
1241 
1242         case PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_RELEASEPORT:
1243             DoReleasePort(aCmd);
1244             break;
1245 
1246         case PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_INIT:
1247             DoInit(aCmd);
1248             break;
1249 
1250         case PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_PREPARE:
1251             DoPrepare(aCmd);
1252             break;
1253 
1254         case PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_START:
1255             DoStart(aCmd);
1256             break;
1257 
1258         case PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_STOP:
1259             DoStop(aCmd);
1260             break;
1261 
1262         case PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_FLUSH:
1263             DoFlush(aCmd);
1264             break;
1265 
1266         case PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_PAUSE:
1267             DoPause(aCmd);
1268             break;
1269 
1270         case PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_RESET:
1271             DoReset(aCmd);
1272             break;
1273 
1274         case PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_CANCELCMD:
1275             DoCancelCommand(aCmd);
1276             break;
1277 
1278         case PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_CANCELALL:
1279             DoCancelAllCommands(aCmd);
1280             break;
1281 
1282         case PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_GETNODEMETADATAKEY:
1283         {
1284             PVMFStatus retval = DoGetNodeMetadataKey(aCmd);
1285             CommandComplete(iInputCommands, aCmd, retval);
1286         }
1287         break;
1288 
1289         case PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_GETNODEMETADATAVALUE:
1290         {
1291             PVMFStatus retval = DoGetNodeMetadataValue(aCmd);
1292             CommandComplete(iInputCommands, aCmd, retval);
1293         }
1294         break;
1295 
1296         default://unknown command type
1297             CommandComplete(iInputCommands, aCmd, PVMFFailure);
1298             break;
1299     }
1300 
1301     return true;
1302 }
1303 
1304 /////////////////////////////////////////////////////////////////////////////
1305 // This routine will process incomming message from the port
1306 /////////////////////////////////////////////////////////////////////////////
ProcessIncomingMsg(PVMFPortInterface * aPort)1307 bool PVMFOMXEncNode::ProcessIncomingMsg(PVMFPortInterface* aPort)
1308 {
1309     //Called by the AO to process one buffer off the port's
1310     //incoming data queue.  This routine will dequeue and
1311     //dispatch the data.
1312 
1313     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1314                     (0, "0x%x PVMFOMXEncNode-%s::ProcessIncomingMsg: aPort=0x%x", this, iNodeTypeId, aPort));
1315 
1316     PVMFStatus status = PVMFFailure;
1317 
1318 
1319     //#define SIMULATE_BOS
1320 #ifdef SIMULATE_BOS
1321 
1322     if (((PVMFOMXEncPort*)aPort)->iNumFramesConsumed == 6))
1323     {
1324 
1325         PVMFSharedMediaCmdPtr BOSCmdPtr = PVMFMediaCmd::createMediaCmd();
1326 
1327         // Set the format ID to BOS
1328         BOSCmdPtr->setFormatID(PVMF_MEDIA_CMD_BOS_FORMAT_ID);
1329 
1330         // Set the timestamp
1331         BOSCmdPtr->setTimestamp(201);
1332         BOSCmdPtr->setStreamID(0);
1333 
1334         // Convert to media message and send it out
1335         PVMFSharedMediaMsgPtr mediaMsgOut;
1336         convertToPVMFMediaCmdMsg(mediaMsgOut, BOSCmdPtr);
1337 
1338         //store the stream id and time stamp of bos message
1339         iStreamID = mediaMsgOut->getStreamID();
1340         iBOSTimestamp = mediaMsgOut->getTimestamp();
1341         iSendBOS = true;
1342 
1343 #ifdef _DEBUG
1344         printf("PVMFOMXEncNode-%s::ProcessIncomingMsg() SIMULATED BOS\n", iNodeTypeId);
1345 #endif
1346         ((PVMFOMXEncPort*)aPort)->iNumFramesConsumed++;
1347         return true;
1348 
1349     }
1350 #endif
1351 //#define SIMULATE_PREMATURE_EOS
1352 #ifdef SIMULATE_PREMATURE_EOS
1353     if (((PVMFOMXEncPort*)aPort)->iNumFramesConsumed == 5)
1354     {
1355         PVMFSharedMediaCmdPtr EOSCmdPtr = PVMFMediaCmd::createMediaCmd();
1356 
1357         // Set the format ID to EOS
1358         EOSCmdPtr->setFormatID(PVMF_MEDIA_CMD_EOS_FORMAT_ID);
1359 
1360         // Set the timestamp
1361         EOSCmdPtr->setTimestamp(200);
1362 
1363         // Convert to media message and send it out
1364         PVMFSharedMediaMsgPtr mediaMsgOut;
1365         convertToPVMFMediaCmdMsg(mediaMsgOut, EOSCmdPtr);
1366 
1367         ((PVMFOMXEncPort*)aPort)->iNumFramesConsumed++;
1368 
1369         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1370                         (0, "PVMFOMXEncNode-%s::ProcessIncomingMsg: SIMULATED EOS", iNodeTypeId));
1371 #ifdef _DEBUG
1372         printf("PVMFOMXEncNode-%s::ProcessIncomingMsg() SIMULATED EOS\n", iNodeTypeId);
1373 #endif
1374         // Set EOS flag
1375         iEndOfDataReached = true;
1376         // Save the timestamp for the EOS cmd
1377         iEndOfDataTimestamp = mediaMsgOut->getTimestamp();
1378 
1379         return true;
1380     }
1381 
1382 #endif
1383 
1384 
1385 
1386     PVMFSharedMediaMsgPtr msg;
1387 
1388     status = aPort->DequeueIncomingMsg(msg);
1389     if (status != PVMFSuccess)
1390 {
1391     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1392                     (0, "0x%x PVMFOMXEncNode-%s::ProcessIncomingMsg: Error - DequeueIncomingMsg failed", this, iNodeTypeId));
1393         return false;
1394     }
1395 
1396     if (msg->getFormatID() == PVMF_MEDIA_CMD_BOS_FORMAT_ID)
1397     {
1398         //store the stream id and time stamp of bos message
1399         iStreamID = msg->getStreamID();
1400         iBOSTimestamp = msg->getTimestamp();
1401         iSendBOS = true;
1402 
1403         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1404                         (0, "PVMFOMXEncNode-%s::ProcessIncomingMsg: Received BOS stream %d, timestamp %d", iNodeTypeId, iStreamID, iBOSTimestamp));
1405         ((PVMFOMXEncPort*)aPort)->iNumFramesConsumed++;
1406         return true;
1407     }
1408     else if (msg->getFormatID() == PVMF_MEDIA_CMD_EOS_FORMAT_ID)
1409     {
1410         // Set EOS flag
1411         iEndOfDataReached = true;
1412         // Save the timestamp for the EOS cmd
1413         iEndOfDataTimestamp = msg->getTimestamp();
1414 
1415         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1416                         (0, "PVMFOMXEncNode-%s::ProcessIncomingMsg: Received EOS", iNodeTypeId));
1417 
1418         ((PVMFOMXEncPort*)aPort)->iNumFramesConsumed++;
1419         return true; // do not do conversion into media data, just set the flag and leave
1420     }
1421 
1422     convertToPVMFMediaData(iDataIn, msg);
1423 
1424 
1425     iCurrFragNum = 0; // for new message, reset the fragment counter
1426 
1427 
1428     ((PVMFOMXEncPort*)aPort)->iNumFramesConsumed++;
1429     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::ProcessIncomingMsg() Received %d frames", iNodeTypeId, ((PVMFOMXEncPort*)aPort)->iNumFramesConsumed));
1430 
1431 //return true if we processed an activity...
1432     return true;
1433 }
1434 
1435 /////////////////////////////////////////////////////////////////////////////
1436 // This routine will process outgoing message by sending it into output the port
1437 /////////////////////////////////////////////////////////////////////////////
ProcessOutgoingMsg(PVMFPortInterface * aPort)1438 bool PVMFOMXEncNode::ProcessOutgoingMsg(PVMFPortInterface* aPort)
1439 {
1440     //Called by the AO to process one message off the outgoing
1441     //message queue for the given port.  This routine will
1442     //try to send the data to the connected port.
1443 
1444     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1445                     (0, "0x%x PVMFOMXEncNode-%s::ProcessOutgoingMsg: aPort=0x%x", this, iNodeTypeId, aPort));
1446 
1447     PVMFStatus status = aPort->Send();
1448     if (status == PVMFErrBusy)
1449     {
1450         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1451                         (0, "0x%x PVMFOMXEncNode-%s::ProcessOutgoingMsg: Connected port goes into busy state", this, iNodeTypeId));
1452     }
1453 
1454     //Report any unexpected failure in port processing...
1455     //(the InvalidState error happens when port input is suspended,
1456     //so don't report it.)
1457     if (status != PVMFErrBusy
1458             && status != PVMFSuccess
1459             && status != PVMFErrInvalidState)
1460     {
1461         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1462                         (0, "0x%x PVMFOMXEncNode-%s::ProcessOutgoingMsg: Error - ProcessPortActivity failed. port=0x%x, type=%d",
1463                          this, iNodeTypeId, iOutPort, PVMF_PORT_ACTIVITY_OUTGOING_MSG));
1464         ReportErrorEvent(PVMFErrPortProcessing);
1465     }
1466 
1467     //return true if we processed an activity...
1468     return (status != PVMFErrBusy);
1469 }
1470 
1471 /////////////////////////////////////////////////////////////////////////////
1472 // This routine will process received data usign State Machine
1473 /////////////////////////////////////////////////////////////////////////////
HandleProcessingState()1474 PVMFStatus PVMFOMXEncNode::HandleProcessingState()
1475 {
1476     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::HandleProcessingState() In", iNodeTypeId));
1477 
1478     PVMFStatus status = PVMFSuccess;
1479 
1480     switch (iProcessingState)
1481     {
1482 
1483             // The FOLLOWING 4 states handle Dynamic Port Reconfiguration
1484         case EPVMFOMXEncNodeProcessingState_PortReconfig:
1485         {
1486             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1487                             (0, "PVMFOMXEncNode-%s::HandleProcessingState() Port Reconfiguration -> Sending Port Disable Command", iNodeTypeId));
1488 
1489             // port reconfiguration is required. Only one port at a time is disabled and then re-enabled after buffer resizing
1490             OMX_SendCommand(iOMXEncoder, OMX_CommandPortDisable, iPortIndexForDynamicReconfig, NULL);
1491             // the port will now start returning outstanding buffers
1492             // set the flag to prevent output from going downstream (in case of output port being reconfigd)
1493             // set the flag to prevent input from being saved and returned to component (in case of input port being reconfigd)
1494             // set the state to wait for port saying it is disabled
1495             if (iPortIndexForDynamicReconfig == iOutputPortIndex)
1496             {
1497                 iDoNotSendOutputBuffersDownstreamFlag = true;
1498             }
1499             else if (iPortIndexForDynamicReconfig == iInputPortIndex)
1500             {
1501                 iDoNotSaveInputBuffersFlag = true;
1502 
1503             }
1504             iProcessingState = EPVMFOMXEncNodeProcessingState_WaitForBufferReturn;
1505 
1506 
1507             // fall through to the next case to check if all buffers are already back
1508         }
1509 
1510         case EPVMFOMXEncNodeProcessingState_WaitForBufferReturn:
1511         {
1512             // as buffers are coming back, Run may be called, wait until all buffers are back, then Free them all
1513 
1514             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1515                             (0, "PVMFOMXEncNode-%s::HandleProcessingState() Port Reconfiguration -> WaitForBufferReturn ", iNodeTypeId));
1516             // check if it's output port being reconfigured
1517             if (iPortIndexForDynamicReconfig == iOutputPortIndex)
1518             {
1519                 // if all buffers have returned, free them
1520                 if (iNumOutstandingOutputBuffers == 0)
1521                 {
1522                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1523                                     (0, "PVMFOMXEncNode-%s::HandleProcessingState() Port Reconfiguration -> all output buffers are back, free them", iNodeTypeId));
1524                     if (false == iOutputBuffersFreed)
1525                     {
1526                         if (!FreeBuffersFromComponent(iOutBufMemoryPool, // allocator
1527                                                       iOutputAllocSize,  // size to allocate from pool (hdr only or hdr+ buffer)
1528                                                       iNumOutputBuffers, // number of buffers
1529                                                       iOutputPortIndex, // port idx
1530                                                       false // this is not input
1531                                                      ))
1532                         {
1533                             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
1534                                             (0, "PVMFOMXEncNode-%s::HandleProcessingState() Port Reconfiguration -> Cannot free output buffers ", iNodeTypeId));
1535 
1536                             SetState(EPVMFNodeError);
1537                             ReportErrorEvent(PVMFErrNoMemory);
1538                             return PVMFErrNoMemory;
1539                         }
1540                     }
1541                     // if the callback (that port is disabled) has not arrived yet, wait for it
1542                     // if it has arrived, it will set the state to PortReEnable
1543                     if (iProcessingState != EPVMFOMXEncNodeProcessingState_PortReEnable)
1544                         iProcessingState = EPVMFOMXEncNodeProcessingState_WaitForPortDisable;
1545 
1546                     status = PVMFSuccess; // allow rescheduling of the node potentially
1547                 }
1548                 else
1549                     status = PVMFErrNoMemory; // must wait for buffers to come back. No point in automatic rescheduling
1550                 // but each buffer will reschedule the node when it comes in
1551             }
1552             else
1553             {
1554                 // this is input port
1555 
1556                 // if all buffers have returned, free them
1557                 if (iNumOutstandingInputBuffers == 0)
1558                 {
1559 
1560                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1561                                     (0, "PVMFOMXEncNode-%s::HandleProcessingState() Port Reconfiguration -> all input buffers are back, free them", iNodeTypeId));
1562                     if (false == iInputBuffersFreed)
1563                     {
1564                         if (!FreeBuffersFromComponent(iInBufMemoryPool, // allocator
1565                                                       iInputAllocSize,   // size to allocate from pool (hdr only or hdr+ buffer)
1566                                                       iNumInputBuffers, // number of buffers
1567                                                       iInputPortIndex, // port idx
1568                                                       true // this is input
1569                                                      ))
1570                         {
1571                             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
1572                                             (0, "PVMFOMXEncNode-%s::HandleProcessingState() Port Reconfiguration -> Cannot free input buffers ", iNodeTypeId));
1573 
1574                             SetState(EPVMFNodeError);
1575                             ReportErrorEvent(PVMFErrNoMemory);
1576                             return PVMFErrNoMemory;
1577 
1578                         }
1579                     }
1580                     // if the callback (that port is disabled) has not arrived yet, wait for it
1581                     // if it has arrived, it will set the state to PortReEnable
1582                     if (iProcessingState != EPVMFOMXEncNodeProcessingState_PortReEnable)
1583                         iProcessingState = EPVMFOMXEncNodeProcessingState_WaitForPortDisable;
1584 
1585                     status = PVMFSuccess; // allow rescheduling of the node
1586                 }
1587                 else
1588                     status = PVMFErrNoMemory; // must wait for buffers to come back. No point in automatic
1589                 // rescheduling. Each buffer will reschedule the node
1590                 // when it comes in
1591             }
1592 
1593 
1594             // the state will be changed to PortReEnable once we get confirmation that Port was actually disabled
1595             break;
1596         }
1597 
1598         case EPVMFOMXEncNodeProcessingState_WaitForPortDisable:
1599         {
1600 
1601             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1602                             (0, "PVMFOMXEncNode-%s::HandleProcessingState() Port Reconfiguration -> wait for port disable callback", iNodeTypeId));
1603             // do nothing. Just wait for the port to become disabled (we'll get event from component, which will
1604             // transition the state to PortReEnable
1605             status = PVMFErrNoMemory; // prevent Rescheduling the node
1606             break;
1607         }
1608 
1609         case EPVMFOMXEncNodeProcessingState_PortReEnable:
1610         {
1611 
1612             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1613                             (0, "PVMFOMXEncNode-%s::HandleProcessingState() Port Reconfiguration -> Sending reenable port command", iNodeTypeId));
1614             // set the port index so that we get parameters for the proper port
1615             iParamPort.nPortIndex = iPortIndexForDynamicReconfig;
1616             // iParamPort.nVersion = OMX_VERSION;
1617 
1618             // get new parameters of the port
1619             OMX_GetParameter(iOMXEncoder, OMX_IndexParamPortDefinition, &iParamPort);
1620 
1621             // send command for port re-enabling (for this to happen, we must first recreate the buffers)
1622             OMX_SendCommand(iOMXEncoder, OMX_CommandPortEnable, iPortIndexForDynamicReconfig, NULL);
1623 
1624             // is this output port?
1625             if (iPortIndexForDynamicReconfig == iOutputPortIndex)
1626             {
1627                 iOMXComponentOutputBufferSize = ((iParamPort.format.video.nFrameWidth + 15) & (~15)) * ((iParamPort.format.video.nFrameHeight + 15) & (~15)) * 3 / 2;
1628 
1629                 // check the new buffer size
1630                 if (iInPort)
1631                 {
1632                     if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO ||
1633                             ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_MP4 ||
1634                             ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_RAW ||
1635                             ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_M4V ||
1636                             ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H2631998 ||
1637                             ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H2632000)
1638                     {
1639                         iOMXComponentOutputBufferSize = ((iParamPort.format.video.nFrameWidth + 15) & (~15)) * ((iParamPort.format.video.nFrameHeight + 15) & (~15)) * 3 / 2;
1640                     }
1641                     else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_WMV)
1642                     {
1643                         // This is a requirement for the WMV encoder that we have currently
1644                         iOMXComponentOutputBufferSize = ((iParamPort.format.video.nFrameWidth + 3) & (~3)) * (iParamPort.format.video.nFrameHeight) * 3 / 2;
1645                     }
1646                     else
1647                     {
1648                         OSCL_ASSERT(false);
1649                     }
1650                 }
1651                 // set the new width / height
1652                 iYUVWidth =  iParamPort.format.video.nFrameWidth;
1653                 iYUVHeight = iParamPort.format.video.nFrameHeight;
1654 
1655                 if (iOMXComponentOutputBufferSize < iParamPort.nBufferSize)
1656                     iOMXComponentOutputBufferSize = iParamPort.nBufferSize;
1657 
1658                 // do we need to increase the number of buffers?
1659                 if (iNumOutputBuffers < iParamPort.nBufferCountMin)
1660                     iNumOutputBuffers = iParamPort.nBufferCountMin;
1661 
1662                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1663                                 (0, "PVMFOMXEncNode-%s::HandleProcessingState() new output buffers %d, size %d", iNodeTypeId, iNumOutputBuffers, iOMXComponentOutputBufferSize));
1664 
1665                 /* Allocate output buffers */
1666                 if (!CreateOutMemPool(iNumOutputBuffers))
1667                 {
1668 
1669                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
1670                                     (0, "PVMFOMXEncNode-%s::HandleProcessingState() Port Reconfiguration -> Cannot allocate output buffers ", iNodeTypeId));
1671 
1672                     SetState(EPVMFNodeError);
1673                     ReportErrorEvent(PVMFErrNoMemory);
1674                     return PVMFErrNoMemory;
1675                 }
1676 
1677                 if (!ProvideBuffersToComponent(iOutBufMemoryPool, // allocator
1678                                                iOutputAllocSize,     // size to allocate from pool (hdr only or hdr+ buffer)
1679                                                iNumOutputBuffers, // number of buffers
1680                                                iOMXComponentOutputBufferSize, // actual buffer size
1681                                                iOutputPortIndex, // port idx
1682                                                iOMXComponentSupportsExternalOutputBufferAlloc, // can component use OMX_UseBuffer
1683                                                false // this is not input
1684                                               ))
1685                 {
1686 
1687 
1688                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
1689                                     (0, "PVMFOMXEncNode-%s::HandleProcessingState() Port Reconfiguration -> Cannot provide output buffers to component", iNodeTypeId));
1690 
1691                     SetState(EPVMFNodeError);
1692                     ReportErrorEvent(PVMFErrNoMemory);
1693                     return PVMFErrNoMemory;
1694 
1695                 }
1696 
1697                 // do not drop output any more, i.e. enable output to be sent downstream
1698                 iDoNotSendOutputBuffersDownstreamFlag = false;
1699 
1700 
1701             }
1702             else
1703             {
1704                 // this is input port
1705 
1706                 iOMXComponentInputBufferSize = iParamPort.nBufferSize;
1707                 // do we need to increase the number of buffers?
1708                 if (iNumInputBuffers < iParamPort.nBufferCountMin)
1709                     iNumInputBuffers = iParamPort.nBufferCountMin;
1710 
1711                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1712                                 (0, "PVMFOMXEncNode-%s::HandleProcessingState() new buffers %d, size %d", iNodeTypeId, iNumInputBuffers, iOMXComponentInputBufferSize));
1713 
1714                 /* Allocate input buffers */
1715                 if (!CreateInputMemPool(iNumInputBuffers))
1716                 {
1717                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
1718                                     (0, "PVMFOMXEncNode-%s::HandleProcessingState() Port Reconfiguration -> Cannot allocate new input buffers to component", iNodeTypeId));
1719 
1720                     SetState(EPVMFNodeError);
1721                     ReportErrorEvent(PVMFErrNoMemory);
1722                     return PVMFErrNoMemory;
1723                 }
1724 
1725                 if (!ProvideBuffersToComponent(iInBufMemoryPool, // allocator
1726                                                iInputAllocSize,  // size to allocate from pool (hdr only or hdr+ buffer)
1727                                                iNumInputBuffers, // number of buffers
1728                                                iOMXComponentInputBufferSize, // actual buffer size
1729                                                iInputPortIndex, // port idx
1730                                                iOMXComponentSupportsExternalInputBufferAlloc, // can component use OMX_UseBuffer
1731                                                true // this is input
1732                                               ))
1733                 {
1734 
1735 
1736                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
1737                                     (0, "PVMFOMXEncNode-%s::HandleProcessingState() Port Reconfiguration -> Cannot provide new input buffers to component", iNodeTypeId));
1738 
1739                     SetState(EPVMFNodeError);
1740                     ReportErrorEvent(PVMFErrNoMemory);
1741                     return PVMFErrNoMemory;
1742 
1743                 }
1744                 // do not drop partially consumed input
1745                 iDoNotSaveInputBuffersFlag = false;
1746 
1747 
1748             }
1749 
1750             // if the callback that the port was re-enabled has not arrived yet, wait for it
1751             // if it has arrived, it will set the state to either PortReconfig or to ReadyToEncode
1752             if (iProcessingState != EPVMFOMXEncNodeProcessingState_PortReconfig &&
1753                     iProcessingState != EPVMFOMXEncNodeProcessingState_ReadyToEncode)
1754                 iProcessingState = EPVMFOMXEncNodeProcessingState_WaitForPortEnable;
1755 
1756             status = PVMFSuccess; // allow rescheduling of the node
1757             break;
1758         }
1759 
1760         case EPVMFOMXEncNodeProcessingState_WaitForPortEnable:
1761         {
1762             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1763                             (0, "PVMFOMXEncNode-%s::HandleProcessingState() Port Reconfiguration -> wait for port enable callback", iNodeTypeId));
1764             // do nothing. Just wait for the port to become enabled (we'll get event from component, which will
1765             // transition the state to ReadyToEncode
1766             status = PVMFErrNoMemory; // prevent ReScheduling
1767             break;
1768         }
1769 
1770         // NORMAL DATA FLOW STATE:
1771         case EPVMFOMXEncNodeProcessingState_ReadyToEncode:
1772         {
1773 
1774             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1775                             (0, "PVMFOMXEncNode-%s::HandleProcessingState() Ready To Encode start", iNodeTypeId));
1776             // In normal data flow and decoding state
1777             // Send all available output buffers to the encoder
1778 
1779             while (iNumOutstandingOutputBuffers < iNumOutputBuffers)
1780             {
1781                 // grab buffer header from the mempool if possible, and send to component
1782                 if (!SendOutputBufferToOMXComponent())
1783 
1784                     break;
1785 
1786             }
1787 
1788 
1789             // next, see if partially consumed input buffer needs to be resent back to OMX component
1790             // NOTE: it is not allowed that the component returns more than 1 partially consumed input buffers
1791             //       i.e. if a partially consumed input buffer is returned, it is assumed that the OMX component
1792             //       will be waiting to get data
1793 
1794             if (iInputBufferToResendToComponent != NULL)
1795             {
1796                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1797                                 (0, "PVMFOMXEncNode-%s::HandleProcessingState() Sending previous - partially consumed input back to the OMX component", iNodeTypeId));
1798 
1799                 OMX_EmptyThisBuffer(iOMXEncoder, iInputBufferToResendToComponent);
1800                 iInputBufferToResendToComponent = NULL; // do this only once
1801             }
1802             else if ((iNumOutstandingInputBuffers < iNumInputBuffers) && (iDataIn.GetRep() != NULL))
1803             {
1804                 // try to get an input buffer header
1805                 // and send the input data over to the component
1806                 SendInputBufferToOMXComponent();
1807             }
1808 
1809             status = PVMFSuccess;
1810             break;
1811 
1812 
1813         }
1814         case EPVMFOMXEncNodeProcessingState_Stopping:
1815         {
1816 
1817             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1818                             (0, "PVMFOMXEncNode-%s::HandleProcessingState() Stopping -> wait for Component to move from Executing->Idle", iNodeTypeId));
1819 
1820 
1821             status = PVMFErrNoMemory; // prevent rescheduling
1822             break;
1823         }
1824 
1825         case EPVMFOMXEncNodeProcessingState_WaitForOutgoingQueue:
1826             status = PVMFErrNoMemory;
1827             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::HandleProcessingState() Do nothing since waiting for output port queue to become available", iNodeTypeId));
1828             break;
1829 
1830         default:
1831             break;
1832     }
1833 
1834     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::HandleProcessingState() Out", iNodeTypeId));
1835 
1836     return status;
1837 
1838 }
1839 /////////////////////////////////////////////////////////////////////////////
SendOutputBufferToOMXComponent()1840 bool PVMFOMXEncNode::SendOutputBufferToOMXComponent()
1841 {
1842     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1843                     (0, "PVMFOMXEncNode-%s::SendOutputBufferToOMXComponent() In", iNodeTypeId));
1844 
1845 
1846     OutputBufCtrlStruct *output_buf = NULL;
1847     int32  errcode = 0;
1848     uint32 ii;
1849 
1850     // try to get output buffer header
1851     OSCL_TRY(errcode, output_buf = (OutputBufCtrlStruct *) iOutBufMemoryPool->allocate(iOutputAllocSize));
1852     if (errcode != 0)
1853     {
1854         if (errcode == OsclErrNoResources)
1855         {
1856 
1857             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger,
1858                             PVLOGMSG_DEBUG, (0, "PVMFOMXEncNode-%s::SendOutputBufferToOMXComponent() No more output buffers in the mempool", iNodeTypeId));
1859 
1860             iOutBufMemoryPool->notifyfreechunkavailable(*this, (OsclAny *) iOutBufMemoryPool); // To signal when next deallocate() is called on mempool
1861 
1862             return false;
1863         }
1864         else
1865         {
1866             // Memory allocation for the pool failed
1867             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
1868                             (0, "PVMFOMXEncNode-%s::SendOutputBufferToOMXComponent() Output mempool error", iNodeTypeId));
1869 
1870 
1871             SetState(EPVMFNodeError);
1872             ReportErrorEvent(PVMFErrNoMemory);
1873             return false;
1874         }
1875 
1876     }
1877 
1878     //for every allocated buffer, make sure you notify when buffer is released. Keep track of allocated buffers
1879     // use mempool as context to recognize which buffer (input or output) was returned
1880     iOutBufMemoryPool->notifyfreechunkavailable(*this, (OsclAny *)iOutBufMemoryPool);
1881     iNumOutstandingOutputBuffers++;
1882 
1883     for (ii = 0; ii < iNumOutputBuffers; ii++)
1884     {
1885         if (output_buf == out_ctrl_struct_ptr[ii])
1886         {
1887             break;
1888         }
1889     }
1890 
1891     if (ii == iNumOutputBuffers)
1892         return false;
1893 
1894     output_buf->pBufHdr = (OMX_BUFFERHEADERTYPE *)out_buff_hdr_ptr[ii];
1895 
1896 
1897 
1898     output_buf->pBufHdr->nFilledLen = 0; // make sure you tell OMX component buffer is empty
1899     output_buf->pBufHdr->nOffset = 0;
1900     output_buf->pBufHdr->pAppPrivate = output_buf; // set pAppPrivate to be pointer to output_buf
1901     // (this is context for future release of this buffer to the mempool)
1902     // this was done during buffer creation, but still repeat just in case
1903 
1904     output_buf->pBufHdr->nFlags = 0; // zero out the flags
1905     OMX_FillThisBuffer(iOMXEncoder, output_buf->pBufHdr);
1906 
1907 
1908 
1909     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1910                     (0, "PVMFOMXEncNode-%s::SendOutputBufferToOMXComponent() Out", iNodeTypeId));
1911 
1912     return true;
1913 }
1914 ////////////////////////////////////////////////////////////////////////////////
NegotiateVideoComponentParameters()1915 bool PVMFOMXEncNode::NegotiateVideoComponentParameters()
1916 {
1917     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1918                     (0, "PVMFOMXEncNode-%s::NegotiateVideoParameters() In", iNodeTypeId));
1919 
1920     OMX_ERRORTYPE Err;
1921     OMX_CONFIG_ROTATIONTYPE InputRotationType;
1922 
1923     // first get the number of ports and port indices
1924     OMX_PORT_PARAM_TYPE VideoPortParameters;
1925     uint32 NumPorts;
1926     uint32 ii;
1927 
1928     // get starting number
1929     CONFIG_SIZE_AND_VERSION(VideoPortParameters);
1930 
1931     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamVideoInit, &VideoPortParameters);
1932     NumPorts = VideoPortParameters.nPorts; // must be at least 2 of them (in&out)
1933 
1934     if (Err != OMX_ErrorNone || NumPorts < 2)
1935     {
1936         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1937                         (0, "PVMFOMXEncNode-%s::NegotiateVideoComponentParameters() There is insuffucient (%d) ports", iNodeTypeId, NumPorts));
1938         return false;
1939     }
1940 
1941 
1942     // loop through video ports starting from the starting index to find index of the first input port
1943     for (ii = VideoPortParameters.nStartPortNumber ; ii < VideoPortParameters.nStartPortNumber + NumPorts; ii++)
1944     {
1945         // get port parameters, and determine if it is input or output
1946         // if there are more than 2 ports, the first one we encounter that has input direction is picked
1947 
1948 
1949         CONFIG_SIZE_AND_VERSION(iParamPort);
1950         //port
1951         iParamPort.nPortIndex = ii; // iInputPortIndex; //OMF_MC_H264D_PORT_INDEX_OF_STREAM;
1952         Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamPortDefinition, &iParamPort);
1953 
1954         if (Err != OMX_ErrorNone)
1955         {
1956             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1957                             (0, "PVMFOMXEncNode-%s::NegotiateVideoComponentParameters() Problem negotiating with port %d ", iNodeTypeId, ii));
1958 
1959             return false;
1960         }
1961 
1962         if (iParamPort.eDir == OMX_DirInput)
1963         {
1964             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1965                             (0, "PVMFOMXEncNode-%s::NegotiateVideoComponentParameters() Found Input port index %d ", iNodeTypeId, ii));
1966 
1967             iInputPortIndex = ii;
1968             break;
1969         }
1970     }
1971     if (ii == VideoPortParameters.nStartPortNumber + NumPorts)
1972     {
1973         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1974                         (0, "PVMFOMXEncNode-%s::NegotiateVideoComponentParameters() Cannot find any input port ", iNodeTypeId));
1975         return false;
1976     }
1977 
1978 
1979     // loop through video ports starting from the starting index to find index of the first output port
1980     for (ii = VideoPortParameters.nStartPortNumber ; ii < VideoPortParameters.nStartPortNumber + NumPorts; ii++)
1981     {
1982         // get port parameters, and determine if it is input or output
1983         // if there are more than 2 ports, the first one we encounter that has output direction is picked
1984 
1985 
1986         CONFIG_SIZE_AND_VERSION(iParamPort);
1987         //port
1988         iParamPort.nPortIndex = ii;
1989         Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamPortDefinition, &iParamPort);
1990 
1991         if (Err != OMX_ErrorNone)
1992         {
1993             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1994                             (0, "PVMFOMXEncNode-%s::NegotiateVideoComponentParameters() Problem negotiating with port %d ", iNodeTypeId, ii));
1995 
1996             return false;
1997         }
1998 
1999         if (iParamPort.eDir == OMX_DirOutput)
2000         {
2001             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2002                             (0, "PVMFOMXEncNode-%s::NegotiateVideoComponentParameters() Found Output port index %d ", iNodeTypeId, ii));
2003 
2004             iOutputPortIndex = ii;
2005             break;
2006         }
2007     }
2008     if (ii == VideoPortParameters.nStartPortNumber + NumPorts)
2009     {
2010         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2011                         (0, "PVMFOMXEncNode-%s::NegotiateVideoComponentParameters() Cannot find any output port ", iNodeTypeId));
2012         return false;
2013     }
2014 
2015 
2016 
2017     // now get input parameters
2018 
2019 
2020     //INPUT PORT
2021 
2022     // first check if encode parameters have been set correctly
2023     if ((0 == iVideoEncodeParam.iFrameWidth[0]) ||
2024             (0 == iVideoEncodeParam.iFrameHeight[0]) ||
2025             (0 == iVideoEncodeParam.iFrameRate[0])   ||
2026             (0 == iVideoEncodeParam.iBitRate[0]) ||
2027             (0 == iVideoInputFormat.iFrameWidth) ||
2028             (0 == iVideoInputFormat.iFrameHeight) ||
2029             (0 == iVideoInputFormat.iFrameRate)
2030        )
2031     {
2032         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2033                         (0, "PVMFOMXEncNode-%s::NegotiateVideoComponentParameters() Encode parameters not set correctly", iNodeTypeId));
2034         return false;
2035     }
2036 
2037     // first of all, check if the port supports the adequate port format
2038     OMX_VIDEO_PARAM_PORTFORMATTYPE Video_port_format;
2039 
2040     //TODO: get color format from MIO. JJ 03/09/09
2041     OMX_COLOR_FORMATTYPE DesiredPortColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
2042     //OMX_COLOR_FORMATTYPE DesiredPortColorFormat = OMX_COLOR_FormatYUV420Planar;
2043 
2044     CONFIG_SIZE_AND_VERSION(Video_port_format);
2045 
2046     Video_port_format.nPortIndex = iInputPortIndex; // set input port as target
2047 
2048     // loop over supported formats until we hit the one we want
2049     // or until the component has no more supported formats (in which case it returns OMX_ErrorNoMore
2050     Err = OMX_ErrorNone;
2051     Video_port_format.nIndex = 0; //init the format counter
2052     while (OMX_ErrorNone == Err)
2053     {
2054 
2055         Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamVideoPortFormat, &Video_port_format);
2056         if ((OMX_ErrorNone != Err))
2057         {
2058             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2059                             (0, "PVMFOMXEncNode-%s::NegotiateVideoComponentParameters() Problem getting port format for input port %d or no desired port format found", iNodeTypeId, iInputPortIndex));
2060             return false;
2061         }
2062 
2063         if ((Video_port_format.eColorFormat == DesiredPortColorFormat))
2064             break;
2065 
2066         Video_port_format.nIndex ++;
2067     }
2068 
2069     // OK, we've found the desired format, set it as the one used
2070     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamVideoPortFormat, &Video_port_format);
2071     if ((OMX_ErrorNone != Err))
2072     {
2073         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2074                         (0, "PVMFOMXEncNode-%s::NegotiateVideoComponentParameters() Problem setting port format for input port %d ", iNodeTypeId, iInputPortIndex));
2075         return false;
2076     }
2077 
2078 
2079 
2080     CONFIG_SIZE_AND_VERSION(iParamPort);
2081     iParamPort.nPortIndex = iInputPortIndex;
2082     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamPortDefinition, &iParamPort);
2083     if (Err != OMX_ErrorNone)
2084     {
2085         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2086                         (0, "PVMFOMXEncNode-%s::NegotiateVideoComponentParameters() Problem negotiating with input port %d ", iNodeTypeId, iInputPortIndex));
2087         return false;
2088     }
2089 
2090     if (iInFormat == PVMF_MIME_RGB24)
2091     {
2092         iOMXComponentInputBufferSize = (iVideoInputFormat.iFrameWidth * iVideoInputFormat.iFrameHeight * 3);
2093         iParamPort.format.video.eColorFormat = OMX_COLOR_Format24bitRGB888;
2094     }
2095     else if (iInFormat == PVMF_MIME_RGB12)
2096     {
2097         iOMXComponentInputBufferSize = (iVideoInputFormat.iFrameWidth * iVideoInputFormat.iFrameHeight * 2);
2098         iParamPort.format.video.eColorFormat = OMX_COLOR_Format12bitRGB444;
2099     }
2100     else if (iInFormat == PVMF_MIME_YUV420)
2101     {
2102         iOMXComponentInputBufferSize = (iVideoInputFormat.iFrameWidth * iVideoInputFormat.iFrameHeight * 3) >> 1;
2103         //TODO: get color format from MIO. JJ 03/09/09
2104         iParamPort.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
2105         //iParamPort.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
2106     }
2107     else
2108     {
2109         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2110                         (0, "PVMFOMXEncNode-%s::NegotiateVideoComponentParameters() Problem with input port %d color format", iNodeTypeId, iInputPortIndex));
2111         return false;
2112     }
2113 
2114     //Set the input buffer size to the encoder component
2115     iParamPort.nBufferSize = iOMXComponentInputBufferSize;
2116 
2117     // set the width and height of video frame and input framerate
2118 
2119     iParamPort.format.video.nFrameWidth = iVideoInputFormat.iFrameWidth;
2120     iParamPort.format.video.nFrameHeight = iVideoInputFormat.iFrameHeight;
2121     // This is Q16 value, so shift by 16 first and cast to preserve accuracy
2122     iParamPort.format.video.xFramerate = (uint32)(iVideoInputFormat.iFrameRate * (1 << 16));
2123 
2124     // indicate that input is uncompressed so that color format is valid
2125     iParamPort.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
2126 
2127 
2128     // let the component decide about the number of input buffers
2129     iNumInputBuffers = iParamPort.nBufferCountActual;
2130 
2131     // do we need to increase the number of buffers?
2132     if (iNumInputBuffers < iParamPort.nBufferCountMin)
2133         iNumInputBuffers = iParamPort.nBufferCountMin;
2134 
2135 
2136     // if component allows us to allocate buffers, we'll decide how many to allocate
2137     if (iOMXComponentSupportsExternalInputBufferAlloc && (iParamPort.nBufferCountMin < NUMBER_INPUT_BUFFER))
2138     {
2139         // preset the number of input buffers
2140         iNumInputBuffers = NUMBER_INPUT_BUFFER;
2141     }
2142 
2143     // set the number of input buffer
2144     iParamPort.nBufferCountActual = iNumInputBuffers;
2145 
2146     // set the number of actual input buffers
2147     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2148                     (0, "PVMFOMXEncNode-%s::NegotiateVideoComponentParameters() Inport buffers %d,size %d", iNodeTypeId, iNumInputBuffers, iOMXComponentInputBufferSize));
2149 
2150     // lock in the input port parameters
2151     CONFIG_SIZE_AND_VERSION(iParamPort);
2152     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamPortDefinition, &iParamPort);
2153     if (Err != OMX_ErrorNone)
2154     {
2155         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2156                         (0, "PVMFOMXEncNode-%s::NegotiateVideoComponentParameters() Problem setting parameters in input port %d ", iNodeTypeId, iInputPortIndex));
2157         return false;
2158     }
2159 
2160 
2161     //////////////////// OUTPUT PORT //////////////////////////////////////////////
2162     CONFIG_SIZE_AND_VERSION(Video_port_format);
2163 
2164     Video_port_format.nPortIndex = iOutputPortIndex; // set output port as target
2165     OMX_VIDEO_CODINGTYPE DesiredPortFormat = OMX_VIDEO_CodingUnused;
2166     if (iOutFormat == PVMF_MIME_M4V)
2167     {
2168         DesiredPortFormat = OMX_VIDEO_CodingMPEG4;
2169     }
2170     else if (iOutFormat == PVMF_MIME_H2631998 ||
2171              iOutFormat == PVMF_MIME_H2632000)
2172     {
2173         DesiredPortFormat = OMX_VIDEO_CodingH263;
2174     }
2175     else if (iOutFormat == PVMF_MIME_H264_VIDEO_RAW ||
2176              iOutFormat == PVMF_MIME_H264_VIDEO_MP4)
2177     {
2178         DesiredPortFormat = OMX_VIDEO_CodingAVC;
2179     }
2180     else
2181     {
2182         DesiredPortFormat = OMX_VIDEO_CodingUnused;
2183     }
2184 
2185     if (DesiredPortFormat == OMX_VIDEO_CodingUnused)
2186     {
2187         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2188                         (0, "PVMFOMXEncNode-%s::NegotiateVideoComponentParameters() Problem with output port %d format", iNodeTypeId, iOutputPortIndex));
2189         return false;
2190     }
2191     // loop over supported formats until we hit the one we want
2192     // or until the component has no more supported formats (in which case it returns OMX_ErrorNoMore
2193     Err = OMX_ErrorNone;
2194     Video_port_format.nIndex = 0; //init the format counter
2195     while (OMX_ErrorNone == Err)
2196     {
2197 
2198         Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamVideoPortFormat, &Video_port_format);
2199         if ((OMX_ErrorNone != Err))
2200         {
2201             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2202                             (0, "PVMFOMXEncNode-%s::NegotiateVideoComponentParameters() Problem getting port format for output port %d or no desired port format found", iNodeTypeId, iOutputPortIndex));
2203             return false;
2204         }
2205 
2206         if ((Video_port_format.eCompressionFormat == DesiredPortFormat))
2207             break;
2208 
2209         Video_port_format.nIndex ++;
2210     }
2211 
2212     // OK, we've found the desired format, set it as the one used
2213     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamVideoPortFormat, &Video_port_format);
2214     if ((OMX_ErrorNone != Err))
2215     {
2216         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2217                         (0, "PVMFOMXEncNode-%s::NegotiateVideoComponentParameters() Problem setting port format for output port %d ", iNodeTypeId, iOutputPortIndex));
2218         return false;
2219     }
2220 
2221 
2222 
2223 
2224     //Port 1 for output port
2225     CONFIG_SIZE_AND_VERSION(iParamPort);
2226     iParamPort.nPortIndex = iOutputPortIndex;
2227     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamPortDefinition, &iParamPort);
2228     if (Err != OMX_ErrorNone)
2229     {
2230         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2231                         (0, "PVMFOMXEncNode-%s::NegotiateVideoComponentParameters() Problem negotiating with output port %d ", iNodeTypeId, iOutputPortIndex));
2232         return false;
2233     }
2234 
2235     // let the component decide output buffer size
2236     iOMXComponentOutputBufferSize = iParamPort.nBufferSize;
2237 
2238     // let the component decide num output buffers
2239     iNumOutputBuffers = iParamPort.nBufferCountActual;
2240 
2241 
2242     //check the number
2243     if (iNumOutputBuffers < iParamPort.nBufferCountMin)
2244         iNumOutputBuffers = iParamPort.nBufferCountMin;
2245 
2246 
2247     // set the number ourselves
2248     if (iOMXComponentSupportsExternalOutputBufferAlloc && (iParamPort.nBufferCountMin < NUMBER_OUTPUT_BUFFER))
2249     {
2250         iNumOutputBuffers = NUMBER_OUTPUT_BUFFER;
2251     }
2252 
2253     iParamPort.nBufferCountActual = iNumOutputBuffers;
2254 
2255 
2256     // set the output (target) bitrate, framerate, width/height etc.
2257     iParamPort.format.video.nFrameWidth = iVideoEncodeParam.iFrameWidth[0];
2258     iParamPort.format.video.nFrameHeight = iVideoEncodeParam.iFrameHeight[0];
2259     // Q16 value, cast after the shift to preserve the accuracy.
2260     iParamPort.format.video.xFramerate = (uint32)(iVideoEncodeParam.iFrameRate[0] * (1 << 16));
2261 
2262     iParamPort.format.video.nBitrate = iVideoEncodeParam.iBitRate[0];
2263     iParamPort.format.video.eColorFormat = OMX_COLOR_FormatUnused;
2264 
2265     if (iOutFormat == PVMF_MIME_M4V)
2266     {
2267         iParamPort.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4;
2268     }
2269     else if (iOutFormat == PVMF_MIME_H2631998 ||
2270              iOutFormat == PVMF_MIME_H2632000)
2271     {
2272         iParamPort.format.video.eCompressionFormat = OMX_VIDEO_CodingH263;
2273     }
2274     else if (iOutFormat == PVMF_MIME_H264_VIDEO_RAW ||
2275              iOutFormat == PVMF_MIME_H264_VIDEO_MP4)
2276     {
2277         iParamPort.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
2278     }
2279     else
2280     {
2281         iParamPort.format.video.eCompressionFormat = OMX_VIDEO_CodingAutoDetect;
2282     }
2283 
2284     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2285                     (0, "PVMFOMXEncNode-%s::NegotiateVideoComponentParameters() Outport buffers %d,size %d", iNodeTypeId, iNumOutputBuffers, iOMXComponentOutputBufferSize));
2286     CONFIG_SIZE_AND_VERSION(iParamPort);
2287     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamPortDefinition, &iParamPort);
2288     if (Err != OMX_ErrorNone)
2289     {
2290         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2291                         (0, "PVMFOMXEncNode-%s::NegotiateVideoComponentParameters() Problem setting parameters in output port %d ", iNodeTypeId, iOutputPortIndex));
2292         return false;
2293     }
2294 
2295     InputRotationType.nPortIndex = iInputPortIndex;
2296     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexConfigCommonRotate, &InputRotationType);
2297     if (Err != OMX_ErrorNone)
2298     {
2299         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2300                         (0, "PVMFOMXEncNode-%s::NegotiateVideoComponentParameters() Problem getting OMX_IndexConfigCommonRotate param ", iNodeTypeId));
2301     }
2302 
2303     //Set the OMX_CONFIG_ROTATIONTYPE parameters
2304     InputRotationType.nRotation = ((iVideoInputFormat.iFrameOrientation == 1) ? 180 : 0);
2305     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexConfigCommonRotate, &InputRotationType);
2306     if (Err != OMX_ErrorNone)
2307     {
2308         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2309                         (0, "PVMFOMXEncNode-%s::NegotiateVideoComponentParameters() Problem setting OMX_IndexConfigCommonRotate param ", iNodeTypeId));
2310     }
2311 
2312 
2313     // now call codec specific parameter setting
2314     bool status = true;
2315     if (iOutFormat == PVMF_MIME_M4V)
2316     {
2317         status = SetMP4EncoderParameters();
2318     }
2319     else if (iOutFormat == PVMF_MIME_H2631998 ||
2320              iOutFormat == PVMF_MIME_H2632000)
2321     {
2322         status = SetH263EncoderParameters();
2323     }
2324     else if (iOutFormat == PVMF_MIME_H264_VIDEO_RAW ||
2325              iOutFormat == PVMF_MIME_H264_VIDEO_MP4)
2326     {
2327         status = SetH264EncoderParameters();
2328     }
2329 
2330     return status;
2331 }
SetMP4EncoderParameters()2332 bool PVMFOMXEncNode::SetMP4EncoderParameters()
2333 {
2334     OMX_ERRORTYPE Err = OMX_ErrorNone;
2335 
2336     OMX_VIDEO_PARAM_MPEG4TYPE Mpeg4Type;
2337     OMX_VIDEO_PARAM_BITRATETYPE BitRateType;
2338     OMX_VIDEO_PARAM_QUANTIZATIONTYPE QuantParam;
2339     OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE ErrCorrType;
2340 
2341     // DV: VALUES HERE ARE FOR THE MOST PART HARDCODED BASED ON PV DEFAULTS
2342     OMX_VIDEO_PARAM_MOTIONVECTORTYPE MotionVector;
2343     OMX_VIDEO_PARAM_INTRAREFRESHTYPE RefreshParam;
2344 
2345 
2346     CONFIG_SIZE_AND_VERSION(Mpeg4Type);
2347     Mpeg4Type.nPortIndex = iOutputPortIndex;
2348 
2349     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamVideoMpeg4, &Mpeg4Type);
2350     if (OMX_ErrorNone != Err)
2351     {
2352         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2353                         (0, "PVMFOMXEncNode-%s::SetMP4EncoderParameters Parameter Invalid", iNodeTypeId));
2354     }
2355 
2356 
2357     //Set the OMX_VIDEO_PARAM_MPEG4TYPE parameters
2358 
2359     Mpeg4Type.nPortIndex = iOutputPortIndex;
2360     // extra parameters - hardcoded
2361     Mpeg4Type.nSliceHeaderSpacing = 0;
2362     Mpeg4Type.bSVH = OMX_FALSE; //((iEncoderParam.iContentType == EI_H263)? true: false);
2363     Mpeg4Type.bGov = OMX_FALSE; // disable or enable GOV header
2364     // extra parameters - hardcoded
2365     Mpeg4Type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2366 
2367 
2368     // params based on iFrame interval
2369     if (iVideoEncodeParam.iIFrameInterval == -1) // encode only one frame
2370     {
2371         Mpeg4Type.nPFrames = 0xFFFFFFFF;
2372     }
2373     else if (iVideoEncodeParam.iIFrameInterval == 0) // no P frames
2374     {
2375         Mpeg4Type.nPFrames = 0;
2376         Mpeg4Type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; // maps to only supporting I-frames
2377     }
2378     else
2379     {
2380         Mpeg4Type.nPFrames = (OMX_U32)(iVideoEncodeParam.iIFrameInterval * iVideoEncodeParam.iFrameRate[0] - 1);
2381     }
2382 
2383     // extra parameters - hardcoded
2384     Mpeg4Type.nBFrames = 0;
2385     Mpeg4Type.nIDCVLCThreshold = 0;
2386     Mpeg4Type.bACPred = OMX_TRUE;
2387     Mpeg4Type.nMaxPacketSize = iVideoEncodeParam.iPacketSize;
2388     Mpeg4Type.nTimeIncRes = 1000; // (in relation to (should be higher than) frame rate )
2389     Mpeg4Type.nHeaderExtension = 0;
2390     Mpeg4Type.bReversibleVLC = ((iVideoEncodeParam.iRVLCEnable == true) ? OMX_TRUE : OMX_FALSE);
2391 
2392     switch (iVideoEncodeParam.iProfileLevel)
2393     {
2394 
2395         case EI_SIMPLE_LEVEL0:
2396             Mpeg4Type.eProfile = OMX_VIDEO_MPEG4ProfileSimple;
2397             Mpeg4Type.eLevel = OMX_VIDEO_MPEG4Level0;
2398             break;
2399 
2400         case EI_SIMPLE_LEVEL1:
2401             Mpeg4Type.eProfile = OMX_VIDEO_MPEG4ProfileSimple;
2402             Mpeg4Type.eLevel = OMX_VIDEO_MPEG4Level1;
2403             break;
2404 
2405         case EI_SIMPLE_LEVEL2:
2406             Mpeg4Type.eProfile = OMX_VIDEO_MPEG4ProfileSimple;
2407             Mpeg4Type.eLevel = OMX_VIDEO_MPEG4Level2;
2408             break;
2409 
2410         case EI_SIMPLE_LEVEL3:
2411             Mpeg4Type.eProfile = OMX_VIDEO_MPEG4ProfileSimple;
2412             Mpeg4Type.eLevel = OMX_VIDEO_MPEG4Level3;
2413             break;
2414 
2415         case EI_CORE_LEVEL1:
2416             Mpeg4Type.eProfile = OMX_VIDEO_MPEG4ProfileCore;
2417             Mpeg4Type.eLevel = OMX_VIDEO_MPEG4Level1;
2418             break;
2419 
2420         case EI_CORE_LEVEL2:
2421             Mpeg4Type.eProfile = OMX_VIDEO_MPEG4ProfileCore;
2422             Mpeg4Type.eLevel = OMX_VIDEO_MPEG4Level2;
2423             break;
2424 
2425         case EI_SIMPLE_SCALABLE_LEVEL0:
2426             Mpeg4Type.eProfile = OMX_VIDEO_MPEG4ProfileSimpleScalable;
2427             Mpeg4Type.eLevel = OMX_VIDEO_MPEG4Level0;
2428             break;
2429 
2430         case EI_SIMPLE_SCALABLE_LEVEL1:
2431             Mpeg4Type.eProfile = OMX_VIDEO_MPEG4ProfileSimpleScalable;
2432             Mpeg4Type.eLevel = OMX_VIDEO_MPEG4Level1;
2433             break;
2434 
2435         case EI_SIMPLE_SCALABLE_LEVEL2:
2436             Mpeg4Type.eProfile = OMX_VIDEO_MPEG4ProfileSimpleScalable;
2437             Mpeg4Type.eLevel = OMX_VIDEO_MPEG4Level2;
2438             break;
2439 
2440         case EI_CORE_SCALABLE_LEVEL1:
2441             Mpeg4Type.eProfile = OMX_VIDEO_MPEG4ProfileCoreScalable;
2442             Mpeg4Type.eLevel = OMX_VIDEO_MPEG4Level1;
2443             break;
2444 
2445         case EI_CORE_SCALABLE_LEVEL2:
2446             Mpeg4Type.eProfile = OMX_VIDEO_MPEG4ProfileCoreScalable;
2447             Mpeg4Type.eLevel = OMX_VIDEO_MPEG4Level2;
2448             break;
2449 
2450         case EI_CORE_SCALABLE_LEVEL3:
2451             Mpeg4Type.eProfile = OMX_VIDEO_MPEG4ProfileCoreScalable;
2452             Mpeg4Type.eLevel = OMX_VIDEO_MPEG4Level3;
2453             break;
2454 
2455     }
2456 
2457     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamVideoMpeg4, &Mpeg4Type);
2458     if (OMX_ErrorNone != Err)
2459     {
2460         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2461                         (0, "PVMFOMXEncNode-%s::SetMP4EncoderParameters Parameter Invalid", iNodeTypeId));
2462     }
2463 
2464     //OMX_VIDEO_PARAM_BITRATETYPE Settings
2465     CONFIG_SIZE_AND_VERSION(BitRateType);
2466 
2467     BitRateType.nPortIndex = iOutputPortIndex;
2468     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamVideoBitrate, &BitRateType);
2469 
2470     if (OMX_ErrorNone != Err)
2471     {
2472         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2473                         (0, "PVMFOMXEncNode-%s::SetMP4EncoderParameters Parameter Invalid", iNodeTypeId));
2474     }
2475 
2476     //Set the parameters now
2477     BitRateType.nPortIndex = iOutputPortIndex;
2478     BitRateType.eControlRate = static_cast<OMX_VIDEO_CONTROLRATETYPE>(iVideoEncodeParam.iRateControlType);
2479     BitRateType.nTargetBitrate = iVideoEncodeParam.iBitRate[0];
2480     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamVideoBitrate, &BitRateType);
2481 
2482     if (OMX_ErrorNone != Err)
2483     {
2484         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2485                         (0, "PVMFOMXEncNode-%s::SetMP4EncoderParameters Parameter Invalid", iNodeTypeId));
2486     }
2487 
2488     //OMX_VIDEO_PARAM_QUANTIZATIONTYPE Settings
2489     if (BitRateType.eControlRate == OMX_Video_ControlRateDisable)
2490     {
2491         CONFIG_SIZE_AND_VERSION(QuantParam);
2492         QuantParam.nPortIndex = iOutputPortIndex;
2493 
2494         Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamVideoQuantization, &QuantParam);
2495         if (OMX_ErrorNone != Err)
2496         {
2497             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2498                             (0, "PVMFOMXEncNode-%s::SetMP4EncoderParameters Parameter Invalid", iNodeTypeId));
2499         }
2500 
2501         //Set the parameters now
2502         QuantParam.nPortIndex = iOutputPortIndex;
2503         QuantParam.nQpI = DEFAULT_OMX_MP4ENC_QPI;
2504         QuantParam.nQpP = DEFAULT_OMX_MP4ENC_QPP;
2505         QuantParam.nQpB = DEFAULT_OMX_MP4ENC_QPB;
2506         Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamVideoQuantization, &QuantParam);
2507         if (OMX_ErrorNone != Err)
2508         {
2509             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2510                             (0, "PVMFOMXEncNode-%s::SetMP4EncoderParameters Parameter Invalid", iNodeTypeId));
2511         }
2512     }
2513 
2514 
2515 
2516     //OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE Settings (For streaming/2-way)
2517 
2518     CONFIG_SIZE_AND_VERSION(ErrCorrType);
2519     ErrCorrType.nPortIndex = iOutputPortIndex;
2520     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamVideoErrorCorrection, &ErrCorrType);
2521     if (OMX_ErrorNone != Err)
2522     {
2523         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2524                         (0, "PVMFOMXEncNode-%s::SetMP4EncoderParameters Parameter Invalid", iNodeTypeId));
2525     }
2526 
2527     //Set the parameters now
2528     ErrCorrType.nPortIndex = iOutputPortIndex;
2529     ErrCorrType.bEnableDataPartitioning = ((iVideoEncodeParam.iDataPartitioning == true) ? OMX_TRUE : OMX_FALSE);
2530     ErrCorrType.bEnableResync = ((iVideoEncodeParam.iResyncMarker == true) ? OMX_TRUE : OMX_FALSE);
2531 
2532     // extra parameters - hardcoded
2533     ErrCorrType.bEnableHEC = OMX_FALSE;
2534     ErrCorrType.nResynchMarkerSpacing = iVideoEncodeParam.iPacketSize;
2535     ErrCorrType.bEnableRVLC = ((iVideoEncodeParam.iRVLCEnable == true) ? OMX_TRUE : OMX_FALSE); // corresponds to encode param rvlcEnable
2536 
2537     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamVideoErrorCorrection, &ErrCorrType);
2538     if (OMX_ErrorNone != Err)
2539     {
2540         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2541                         (0, "PVMFOMXEncNode-%s::SetMP4EncoderParameters Parameter Invalid", iNodeTypeId));
2542     }
2543 
2544 
2545     //OMX_VIDEO_PARAM_MOTIONVECTORTYPE Settings
2546     CONFIG_SIZE_AND_VERSION(MotionVector);
2547     MotionVector.nPortIndex = iOutputPortIndex;
2548 
2549     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamVideoMotionVector, &MotionVector);
2550     if (OMX_ErrorNone != Err)
2551     {
2552         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2553                         (0, "PVMFOMXEncNode-%s::SetMP4EncoderParameters Parameter Invalid", iNodeTypeId));
2554     }
2555 
2556     MotionVector.nPortIndex = iOutputPortIndex;
2557 
2558     // extra parameters - hardcoded
2559     MotionVector.sXSearchRange = iVideoEncodeParam.iSearchRange;
2560     MotionVector.sYSearchRange = iVideoEncodeParam.iSearchRange;
2561     MotionVector.bFourMV = ((iVideoEncodeParam.iMV8x8 == true) ? OMX_TRUE : OMX_FALSE);
2562     MotionVector.eAccuracy = ((iVideoEncodeParam.iMVHalfPel == true) ? OMX_Video_MotionVectorHalfPel : OMX_Video_MotionVectorPixel);
2563     MotionVector.bUnrestrictedMVs = OMX_TRUE;
2564 
2565     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamVideoMotionVector, &MotionVector);
2566     if (OMX_ErrorNone != Err)
2567     {
2568         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2569                         (0, "PVMFOMXEncNode-%s::SetMP4EncoderParameters Parameter Invalid", iNodeTypeId));
2570     }
2571 
2572 
2573     //OMX_VIDEO_PARAM_INTRAREFRESHTYPE Settings
2574     CONFIG_SIZE_AND_VERSION(RefreshParam);
2575     RefreshParam.nPortIndex = iOutputPortIndex;
2576 
2577     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamVideoIntraRefresh, &RefreshParam);
2578     if (OMX_ErrorNone != Err)
2579     {
2580         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2581                         (0, "PVMFOMXEncNode-%s::SetMP4EncoderParameters Parameter Invalid", iNodeTypeId));
2582     }
2583 
2584     // extra parameters - hardcoded based on PV defaults
2585     RefreshParam.nPortIndex = iOutputPortIndex;
2586     RefreshParam.eRefreshMode = OMX_VIDEO_IntraRefreshBoth;
2587     RefreshParam.nCirMBs = iVideoEncodeParam.iNumIntraMBRefresh;
2588 
2589     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamVideoIntraRefresh, &RefreshParam);
2590     if (OMX_ErrorNone != Err)
2591     {
2592         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2593                         (0, "PVMFOMXEncNode-%s::SetMP4EncoderParameters Parameter Invalid", iNodeTypeId));
2594     }
2595 
2596     return true;
2597 }
2598 
SetH263EncoderParameters()2599 bool PVMFOMXEncNode::SetH263EncoderParameters()
2600 {
2601 
2602     OMX_ERRORTYPE Err = OMX_ErrorNone;
2603 
2604     OMX_VIDEO_PARAM_H263TYPE H263Type;
2605     OMX_VIDEO_PARAM_BITRATETYPE BitRateType;
2606     OMX_VIDEO_PARAM_QUANTIZATIONTYPE QuantParam;
2607     OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE ErrCorrType;
2608 
2609     // DV: VALUES HERE ARE FOR THE MOST PART HARDCODED BASED ON PV DEFAULTS
2610     OMX_VIDEO_PARAM_MOTIONVECTORTYPE MotionVector;
2611     OMX_VIDEO_PARAM_INTRAREFRESHTYPE RefreshParam;
2612 
2613 
2614     CONFIG_SIZE_AND_VERSION(H263Type);
2615     H263Type.nPortIndex = iOutputPortIndex;
2616 
2617     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamVideoH263, &H263Type);
2618     if (OMX_ErrorNone != Err)
2619     {
2620         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2621                         (0, "PVMFOMXEncNode-%s::SetH263EncoderParameters OMX_GetParameter() failed for index(0x%x)", iNodeTypeId, OMX_IndexParamVideoH263));
2622     }
2623 
2624 
2625     //Set the OMX_VIDEO_PARAM_H263TYPE parameters
2626 
2627     //DV: Here, we only set the nPFrames and AllowedFrameTypes, i.e. iIFrameInterval related variables
2628 
2629     H263Type.nPortIndex = iOutputPortIndex;
2630 
2631     H263Type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2632     if (iVideoEncodeParam.iIFrameInterval == -1) // encode only one I frame followed by P frames
2633     {
2634         H263Type.nPFrames = 0xFFFFFFFF;
2635     }
2636     else if (iVideoEncodeParam.iIFrameInterval == 0) // no P frames
2637     {
2638         H263Type.nPFrames = 0;
2639         H263Type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; // maps to only supporting I-frames
2640     }
2641     else
2642     {
2643         H263Type.nPFrames = (OMX_U32)(iVideoEncodeParam.iIFrameInterval * iVideoEncodeParam.iFrameRate[0] - 1);
2644     }
2645 
2646     // extra parameters - hardcoded
2647     H263Type.nBFrames = 0;
2648     H263Type.eProfile = OMX_VIDEO_H263ProfileBaseline;
2649 
2650     // the supported level is up to OMX_VIDEO_H263Level45
2651     if (H263Type.eLevel > OMX_VIDEO_H263Level45)
2652     {
2653         H263Type.eLevel = OMX_VIDEO_H263Level45;
2654     }
2655     H263Type.bPLUSPTYPEAllowed = OMX_FALSE;
2656     H263Type.bForceRoundingTypeToZero = OMX_FALSE;
2657     H263Type.nPictureHeaderRepetition = 0;
2658     H263Type.nGOBHeaderInterval = 2;
2659 
2660     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamVideoH263, &H263Type);
2661     if (OMX_ErrorNone != Err)
2662     {
2663         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2664                         (0, "PVMFOMXEncNode-%s::SetH263EncoderParameters OMX_SetParameter() failed for index(0x%x)", iNodeTypeId, OMX_IndexParamVideoH263));
2665     }
2666 
2667     //OMX_VIDEO_PARAM_BITRATETYPE Settings
2668     CONFIG_SIZE_AND_VERSION(BitRateType);
2669 
2670     BitRateType.nPortIndex = iOutputPortIndex;
2671     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamVideoBitrate, &BitRateType);
2672     if (OMX_ErrorNone != Err)
2673     {
2674         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2675                         (0, "PVMFOMXEncNode-%s::SetH263EncoderParameters OMX_GetParameter() failed for index(0x%x)", iNodeTypeId, OMX_IndexParamVideoBitrate));
2676     }
2677 
2678     //Set the parameters now
2679     BitRateType.nPortIndex = iOutputPortIndex;
2680     BitRateType.eControlRate = static_cast<OMX_VIDEO_CONTROLRATETYPE>(iVideoEncodeParam.iRateControlType);
2681     BitRateType.nTargetBitrate = iVideoEncodeParam.iBitRate[0];
2682     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamVideoBitrate, &BitRateType);
2683     if (OMX_ErrorNone != Err)
2684     {
2685         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2686                         (0, "PVMFOMXEncNode-%s::SetH263EncoderParameters OMX_SetParameter() failed for index(0x%x)", iNodeTypeId, OMX_IndexParamVideoBitrate));
2687     }
2688 
2689 
2690     //OMX_VIDEO_PARAM_QUANTIZATIONTYPE Settings
2691     if (BitRateType.eControlRate == OMX_Video_ControlRateDisable)
2692     {
2693         CONFIG_SIZE_AND_VERSION(QuantParam);
2694         QuantParam.nPortIndex = iOutputPortIndex;
2695 
2696         Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamVideoQuantization, &QuantParam);
2697         if (OMX_ErrorNone != Err)
2698         {
2699             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2700                             (0, "PVMFOMXEncNode-%s::SetH263EncoderParameters OMX_GetParameter() failed for index(0x%x", iNodeTypeId, OMX_IndexParamVideoQuantization));
2701         }
2702 
2703         //Set the parameters now
2704         QuantParam.nPortIndex = iOutputPortIndex;
2705         QuantParam.nQpI = DEFAULT_OMX_MP4ENC_QPI;
2706         QuantParam.nQpP = DEFAULT_OMX_MP4ENC_QPP;
2707         QuantParam.nQpB = DEFAULT_OMX_MP4ENC_QPB;
2708         Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamVideoQuantization, &QuantParam);
2709         if (OMX_ErrorNone != Err)
2710         {
2711             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2712                             (0, "PVMFOMXEncNode-%s::SetH263EncoderParameters OMX_SetParameter() failed for index(0x%x)", iNodeTypeId, OMX_IndexParamVideoQuantization));
2713         }
2714     }
2715 
2716 
2717     //OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE Settings (For streaming/2-way)
2718 
2719     CONFIG_SIZE_AND_VERSION(ErrCorrType);
2720     ErrCorrType.nPortIndex = iOutputPortIndex;
2721     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamVideoErrorCorrection, &ErrCorrType);
2722     if (OMX_ErrorNone != Err)
2723     {
2724         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2725                         (0, "PVMFOMXEncNode-%s::SetH263EncoderParameters OMX_GetParameter() faile for index(0x%x)", iNodeTypeId, OMX_IndexParamVideoErrorCorrection));
2726     }
2727 
2728     //Set the parameters now
2729     ErrCorrType.nPortIndex = iOutputPortIndex;
2730     //if (iVideoEncodeParam.iContentType == EI_M4V_STREAMING)
2731     //{
2732     //    ErrCorrType.bEnableDataPartitioning = OMX_TRUE;
2733     //}
2734     //else
2735     //{
2736     //    ErrCorrType.bEnableDataPartitioning = OMX_FALSE;
2737     //}
2738     ErrCorrType.bEnableHEC = OMX_FALSE;
2739     ErrCorrType.bEnableResync = OMX_FALSE;
2740     ErrCorrType.nResynchMarkerSpacing = 0;
2741     ErrCorrType.bEnableRVLC = OMX_FALSE;        // corresponds to encode param rvlcEnable
2742     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamVideoErrorCorrection, &ErrCorrType);
2743     if (OMX_ErrorNone != Err)
2744     {
2745         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2746                         (0, "PVMFOMXEncNode-%s::SetH263EncoderParameters OMX_SetParameter() failed for index(0x%x)", iNodeTypeId, OMX_IndexParamVideoErrorCorrection));
2747     }
2748 
2749 
2750 
2751     //OMX_VIDEO_PARAM_MOTIONVECTORTYPE Settings
2752     CONFIG_SIZE_AND_VERSION(MotionVector);
2753     MotionVector.nPortIndex = iOutputPortIndex;
2754 
2755     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamVideoMotionVector, &MotionVector);
2756     if (OMX_ErrorNone != Err)
2757     {
2758         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2759                         (0, "PVMFOMXEncNode-%s::SetH263EncoderParameters OMX_GetParameter() failed for index(0x%x)", iNodeTypeId, OMX_IndexParamVideoMotionVector));
2760     }
2761 
2762     // extra parameters - hardcoded
2763     MotionVector.sXSearchRange = iVideoEncodeParam.iSearchRange;
2764     MotionVector.sYSearchRange = iVideoEncodeParam.iSearchRange;
2765     MotionVector.bFourMV =  OMX_FALSE;
2766     MotionVector.eAccuracy = ((iVideoEncodeParam.iMVHalfPel == true) ? OMX_Video_MotionVectorHalfPel : OMX_Video_MotionVectorPixel);
2767     MotionVector.bUnrestrictedMVs = OMX_FALSE;
2768 
2769 
2770     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamVideoMotionVector, &MotionVector);
2771     if (OMX_ErrorNone != Err)
2772     {
2773         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2774                         (0, "PVMFOMXEncNode-%s::SetH263EncoderParameters OMX_SetParameter() failed for index(0x%x", iNodeTypeId, OMX_IndexParamVideoMotionVector));
2775     }
2776 
2777 
2778     //OMX_VIDEO_PARAM_INTRAREFRESHTYPE Settings
2779 
2780     CONFIG_SIZE_AND_VERSION(RefreshParam);
2781     RefreshParam.nPortIndex = iOutputPortIndex;
2782 
2783     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamVideoIntraRefresh, &RefreshParam);
2784     if (OMX_ErrorNone != Err)
2785     {
2786         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2787                         (0, "PVMFOMXEncNode-%s::SetH263EncoderParameters OMX_GetParameter() failed for index(0x%x)", iNodeTypeId, OMX_IndexParamVideoIntraRefresh));
2788     }
2789 
2790     // extra parameters - hardcoded based on PV defaults
2791     RefreshParam.nPortIndex = iOutputPortIndex;
2792     RefreshParam.eRefreshMode = OMX_VIDEO_IntraRefreshBoth;
2793     RefreshParam.nCirMBs = iVideoEncodeParam.iNumIntraMBRefresh;
2794 
2795 
2796     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamVideoIntraRefresh, &RefreshParam);
2797     if (OMX_ErrorNone != Err)
2798     {
2799         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2800                         (0, "PVMFOMXEncNode-%s::SetH263EncoderParameters OMX_SetParameter() failed for index(0x%x)", iNodeTypeId, OMX_IndexParamVideoIntraRefresh));
2801     }
2802 
2803     return true;
2804 }
2805 
SetH264EncoderParameters()2806 bool PVMFOMXEncNode::SetH264EncoderParameters()
2807 {
2808     OMX_ERRORTYPE Err = OMX_ErrorNone;
2809 
2810     OMX_VIDEO_PARAM_AVCTYPE H264Type;
2811     OMX_VIDEO_PARAM_BITRATETYPE BitRateType;
2812     OMX_VIDEO_PARAM_QUANTIZATIONTYPE QuantParam;
2813 
2814     // to be refined
2815     OMX_VIDEO_PARAM_MOTIONVECTORTYPE MotionVector;
2816     OMX_VIDEO_PARAM_INTRAREFRESHTYPE RefreshParam;
2817     OMX_VIDEO_PARAM_VBSMCTYPE VbsmcType;
2818 
2819 
2820     CONFIG_SIZE_AND_VERSION(H264Type);
2821     H264Type.nPortIndex = iOutputPortIndex;
2822 
2823     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamVideoAvc, &H264Type);
2824     if (OMX_ErrorNone != Err)
2825     {
2826         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2827                         (0, "PVMFOMXEncNode-%s::SetH264EncoderParameters Parameter Invalid", iNodeTypeId));
2828     }
2829 
2830 
2831     H264Type.nPortIndex = iOutputPortIndex;
2832 
2833     H264Type.nAllowedPictureTypes  = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
2834     if (iVideoEncodeParam.iIFrameInterval == -1) // encode only one I frame followed by P frames
2835     {
2836         H264Type.nPFrames = 0xFFFFFFFF;
2837     }
2838     else if (iVideoEncodeParam.iIFrameInterval == 0) // no P frames
2839     {
2840         H264Type.nPFrames = 0;
2841         H264Type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; // maps to only supporting I-frames
2842     }
2843     else
2844     {
2845         H264Type.nPFrames = (OMX_U32)(iVideoEncodeParam.iIFrameInterval * iVideoEncodeParam.iFrameRate[0] - 1);
2846     }
2847 
2848     // extra parameters -hardcoded
2849     H264Type.nSliceHeaderSpacing = 0;
2850     H264Type.nBFrames = 0;
2851     H264Type.bUseHadamard = OMX_TRUE;
2852     H264Type.nRefFrames = 1;
2853     H264Type.nRefIdx10ActiveMinus1 = 0;
2854     H264Type.nRefIdx11ActiveMinus1 = 0;
2855     H264Type.bEnableUEP = OMX_FALSE;
2856     H264Type.bEnableFMO = OMX_FALSE;
2857     H264Type.bEnableASO = OMX_FALSE;
2858     H264Type.bEnableRS = OMX_FALSE;
2859     H264Type.eProfile = OMX_VIDEO_AVCProfileBaseline;
2860     H264Type.eLevel = OMX_VIDEO_AVCLevel1b;
2861     H264Type.bFrameMBsOnly = OMX_TRUE;
2862     H264Type.bMBAFF = OMX_FALSE;
2863     H264Type.bEntropyCodingCABAC = OMX_FALSE;
2864     H264Type.bWeightedPPrediction = OMX_FALSE;
2865     H264Type.bconstIpred = OMX_FALSE;
2866     H264Type.bDirect8x8Inference = OMX_FALSE;
2867     H264Type.bDirectSpatialTemporal = OMX_FALSE;
2868     H264Type.nCabacInitIdc = 0;
2869     H264Type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
2870 
2871 
2872     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamVideoAvc, &H264Type);
2873     if (OMX_ErrorNone != Err)
2874     {
2875         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2876                         (0, "PVMFOMXEncNode-%s::SetH264EncoderParameters Parameter Invalid", iNodeTypeId));
2877     }
2878 
2879 
2880     //OMX_VIDEO_PARAM_BITRATETYPE Settings
2881     CONFIG_SIZE_AND_VERSION(BitRateType);
2882 
2883     BitRateType.nPortIndex = iOutputPortIndex;
2884     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamVideoBitrate, &BitRateType);
2885     if (OMX_ErrorNone != Err)
2886     {
2887         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2888                         (0, "PVMFOMXEncNode-%s::SetH264EncoderParameters Parameter Invalid", iNodeTypeId));
2889     }
2890 
2891     //Set the parameters now
2892     BitRateType.nPortIndex = iOutputPortIndex;
2893     BitRateType.eControlRate = static_cast<OMX_VIDEO_CONTROLRATETYPE>(iVideoEncodeParam.iRateControlType);
2894     BitRateType.nTargetBitrate = iVideoEncodeParam.iBitRate[0];
2895     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamVideoBitrate, &BitRateType);
2896     if (OMX_ErrorNone != Err)
2897     {
2898         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2899                         (0, "PVMFOMXEncNode-%s::SetH264EncoderParameters Parameter Invalid", iNodeTypeId));
2900     }
2901 
2902 
2903     //OMX_VIDEO_PARAM_QUANTIZATIONTYPE Settings
2904     if (BitRateType.eControlRate == OMX_Video_ControlRateDisable)
2905     {
2906         CONFIG_SIZE_AND_VERSION(QuantParam);
2907         QuantParam.nPortIndex = iOutputPortIndex;
2908 
2909         Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamVideoQuantization, &QuantParam);
2910         if (OMX_ErrorNone != Err)
2911         {
2912             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2913                             (0, "PVMFOMXEncNode-%s::SetH264EncoderParameters Parameter Invalid", iNodeTypeId));
2914         }
2915 
2916         //Set the parameters now
2917         QuantParam.nPortIndex = iOutputPortIndex;
2918         QuantParam.nQpI = DEFAULT_OMX_AVCENC_QPI;
2919         QuantParam.nQpP = DEFAULT_OMX_AVCENC_QPP;
2920         QuantParam.nQpB = DEFAULT_OMX_AVCENC_QPB;
2921         Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamVideoQuantization, &QuantParam);
2922         if (OMX_ErrorNone != Err)
2923         {
2924             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2925                             (0, "PVMFOMXEncNode-%s::SetH264EncoderParameters Parameter Invalid", iNodeTypeId));
2926         }
2927     }
2928 
2929 
2930 
2931 
2932     //OMX_VIDEO_PARAM_MOTIONVECTORTYPE Settings
2933     CONFIG_SIZE_AND_VERSION(MotionVector);
2934     MotionVector.nPortIndex = iOutputPortIndex;
2935 
2936     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamVideoMotionVector, &MotionVector);
2937     if (OMX_ErrorNone != Err)
2938     {
2939         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2940                         (0, "PVMFOMXEncNode-%s::SetH264EncoderParameters Parameter Invalid", iNodeTypeId));
2941     }
2942 
2943     // extra parameters - hardcoded
2944     MotionVector.sXSearchRange = iVideoEncodeParam.iSearchRange;
2945     MotionVector.sYSearchRange = iVideoEncodeParam.iSearchRange;
2946     MotionVector.bFourMV =  OMX_FALSE;
2947     MotionVector.eAccuracy = OMX_Video_MotionVectorQuarterPel; // hardcoded
2948     MotionVector.bUnrestrictedMVs = OMX_TRUE;
2949 
2950 
2951     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamVideoMotionVector, &MotionVector);
2952     if (OMX_ErrorNone != Err)
2953     {
2954         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2955                         (0, "PVMFOMXEncNode-%s::SetH264EncoderParameters Parameter Invalid", iNodeTypeId));
2956     }
2957 
2958 
2959     //OMX_VIDEO_PARAM_INTRAREFRESHTYPE Settings
2960 
2961     CONFIG_SIZE_AND_VERSION(RefreshParam);
2962     RefreshParam.nPortIndex = iOutputPortIndex;
2963 
2964     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamVideoIntraRefresh, &RefreshParam);
2965     if (OMX_ErrorNone != Err)
2966     {
2967         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2968                         (0, "PVMFOMXEncNode-%s::SetH264EncoderParameters Parameter Invalid", iNodeTypeId));
2969     }
2970 
2971     // extra parameters - hardcoded based on PV defaults
2972     RefreshParam.nPortIndex = iOutputPortIndex;
2973     RefreshParam.eRefreshMode = OMX_VIDEO_IntraRefreshBoth;
2974     RefreshParam.nCirMBs = iVideoEncodeParam.iNumIntraMBRefresh;
2975 
2976 
2977     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamVideoIntraRefresh, &RefreshParam);
2978     if (OMX_ErrorNone != Err)
2979     {
2980         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2981                         (0, "PVMFOMXEncNode-%s::SetH264EncoderParameters Parameter Invalid", iNodeTypeId));
2982     }
2983 
2984     CONFIG_SIZE_AND_VERSION(VbsmcType);
2985     VbsmcType.nPortIndex = iOutputPortIndex;
2986 
2987     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamVideoVBSMC, &VbsmcType);
2988     if (OMX_ErrorNone != Err)
2989     {
2990         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2991                         (0, "PVMFOMXEncNode-%s::SetH264EncoderParameters Parameter Invalid", iNodeTypeId));
2992     }
2993 
2994     VbsmcType.b16x16 = OMX_TRUE;
2995     VbsmcType.b16x8 = VbsmcType.b8x16 = VbsmcType.b8x8 = VbsmcType.b8x4 = VbsmcType.b4x8 = VbsmcType.b4x4 = OMX_FALSE;
2996 
2997     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamVideoVBSMC, &VbsmcType);
2998     if (OMX_ErrorNone != Err)
2999     {
3000         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3001                         (0, "PVMFOMXEncNode-%s::SetH264EncoderParameters Parameter Invalid", iNodeTypeId));
3002     }
3003 
3004     return true;
3005 }
3006 
3007 ////////////////////////////////////////////////////////////////////////////////
NegotiateAudioComponentParameters()3008 bool PVMFOMXEncNode::NegotiateAudioComponentParameters()
3009 {
3010     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3011                     (0, "PVMFOMXEncNode-%s::NegotiateAudioParameters() In", iNodeTypeId));
3012 
3013     OMX_ERRORTYPE Err;
3014 
3015     // first get the number of ports and port indices
3016     OMX_PORT_PARAM_TYPE AudioPortParameters;
3017     uint32 NumPorts;
3018     uint32 ii;
3019 
3020     // get starting number
3021     CONFIG_SIZE_AND_VERSION(AudioPortParameters);
3022 
3023     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamAudioInit, &AudioPortParameters);
3024     NumPorts = AudioPortParameters.nPorts; // must be at least 2 of them (in&out)
3025 
3026     if (Err != OMX_ErrorNone || NumPorts < 2)
3027     {
3028         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3029                         (0, "PVMFOMXEncNode-%s::NegotiateAudioComponentParameters() There is insuffucient (%d) ports", iNodeTypeId, NumPorts));
3030         return false;
3031     }
3032 
3033 
3034     // loop through ports starting from the starting index to find index of the first input port
3035     for (ii = AudioPortParameters.nStartPortNumber ; ii < AudioPortParameters.nStartPortNumber + NumPorts; ii++)
3036     {
3037         // get port parameters, and determine if it is input or output
3038         // if there are more than 2 ports, the first one we encounter that has input direction is picked
3039 
3040 
3041         CONFIG_SIZE_AND_VERSION(iParamPort);
3042         //port
3043         iParamPort.nPortIndex = ii;
3044         Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamPortDefinition, &iParamPort);
3045 
3046         if (Err != OMX_ErrorNone)
3047         {
3048             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3049                             (0, "PVMFOMXEncNode-%s::NegotiateAudioComponentParameters() Problem negotiating with port %d ", iNodeTypeId, ii));
3050 
3051             return false;
3052         }
3053 
3054         if (iParamPort.eDir == OMX_DirInput)
3055         {
3056             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3057                             (0, "PVMFOMXEncNode-%s::NegotiateAudioComponentParameters() Found Input port index %d ", iNodeTypeId, ii));
3058 
3059             iInputPortIndex = ii;
3060             break;
3061         }
3062     }
3063     if (ii == AudioPortParameters.nStartPortNumber + NumPorts)
3064     {
3065         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3066                         (0, "PVMFOMXEncNode-%s::NegotiateAudioComponentParameters() Cannot find any input port ", iNodeTypeId));
3067         return false;
3068     }
3069 
3070 
3071     // loop through ports starting from the starting index to find index of the first output port
3072     for (ii = AudioPortParameters.nStartPortNumber ; ii < AudioPortParameters.nStartPortNumber + NumPorts; ii++)
3073     {
3074         // get port parameters, and determine if it is input or output
3075         // if there are more than 2 ports, the first one we encounter that has output direction is picked
3076 
3077 
3078         CONFIG_SIZE_AND_VERSION(iParamPort);
3079         //port
3080         iParamPort.nPortIndex = ii;
3081         Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamPortDefinition, &iParamPort);
3082 
3083         if (Err != OMX_ErrorNone)
3084         {
3085             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3086                             (0, "PVMFOMXEncNode-%s::NegotiateAudioComponentParameters() Problem negotiating with port %d ", iNodeTypeId, ii));
3087 
3088             return false;
3089         }
3090 
3091         if (iParamPort.eDir == OMX_DirOutput)
3092         {
3093             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3094                             (0, "PVMFOMXEncNode-%s::NegotiateAudioComponentParameters() Found Output port index %d ", iNodeTypeId, ii));
3095 
3096             iOutputPortIndex = ii;
3097             break;
3098         }
3099     }
3100     if (ii == AudioPortParameters.nStartPortNumber + NumPorts)
3101     {
3102         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3103                         (0, "PVMFOMXEncNode-%s::NegotiateAudioComponentParameters() Cannot find any output port ", iNodeTypeId));
3104         return false;
3105     }
3106 
3107 
3108 
3109     // now get input parameters
3110 
3111 
3112     //INPUT PORT
3113 
3114     // first basic check if encode parameters have been set correctly
3115     if ((0 == iAudioEncodeParam.iMaxNumOutputFramesPerBuffer) ||
3116             (0 == iAudioEncodeParam.iAMRBitrate) ||
3117             (0 == iAudioEncodeParam.iOutputNumChannels) ||
3118             (2 < iAudioEncodeParam.iOutputNumChannels) ||
3119             (0 == iAudioEncodeParam.iOutputSamplingRate) ||
3120             (0 == iAudioInputFormat.iInputBitsPerSample) ||
3121             (0 == iAudioInputFormat.iInputNumChannels) ||
3122             (2 < iAudioInputFormat.iInputNumChannels) ||
3123             (0 == iAudioInputFormat.iInputSamplingRate)
3124        )
3125     {
3126         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3127                         (0, "PVMFOMXEncNode-%s::NegotiateAudioComponentParameters() Encode parameters not set correctly", iNodeTypeId));
3128         return false;
3129     }
3130 
3131     // first of all, check if the port supports the adequate port format
3132     OMX_AUDIO_PARAM_PORTFORMATTYPE Audio_port_format;
3133     OMX_AUDIO_CODINGTYPE DesiredPortFormat = OMX_AUDIO_CodingPCM;
3134     CONFIG_SIZE_AND_VERSION(Audio_port_format);
3135 
3136     Audio_port_format.nPortIndex = iInputPortIndex; // set input port as target
3137 
3138     // loop over supported formats until we hit the one we want
3139     // or until the component has no more supported formats (in which case it returns OMX_ErrorNoMore
3140     Err = OMX_ErrorNone;
3141     Audio_port_format.nIndex = 0; //init the format counter
3142     while (OMX_ErrorNone == Err)
3143     {
3144 
3145         Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamAudioPortFormat, &Audio_port_format);
3146         if ((OMX_ErrorNone != Err))
3147         {
3148             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3149                             (0, "PVMFOMXEncNode-%s::NegotiateAudioComponentParameters() Problem getting port format for input port %d or no desired port format found", iNodeTypeId, iInputPortIndex));
3150             return false;
3151         }
3152 
3153         if (Audio_port_format.eEncoding == DesiredPortFormat)
3154             break;
3155 
3156         Audio_port_format.nIndex ++;
3157     }
3158 
3159     // OK, we've found the desired format, set it as the one used
3160     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamAudioPortFormat, &Audio_port_format);
3161     if ((OMX_ErrorNone != Err))
3162     {
3163         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3164                         (0, "PVMFOMXEncNode-%s::NegotiateAudioComponentParameters() Problem setting port format for input port %d ", iNodeTypeId, iInputPortIndex));
3165         return false;
3166     }
3167 
3168 
3169 
3170 
3171     CONFIG_SIZE_AND_VERSION(iParamPort);
3172     iParamPort.nPortIndex = iInputPortIndex;
3173     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamPortDefinition, &iParamPort);
3174     if (Err != OMX_ErrorNone)
3175     {
3176         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3177                         (0, "PVMFOMXEncNode-%s::NegotiateAudioComponentParameters() Problem negotiating with input port %d ", iNodeTypeId, iInputPortIndex));
3178         return false;
3179     }
3180 
3181     // TODO: FIX THIS - JUST READ THE BUFFER SIZE FROM COMPONENT PORT
3182     if (iInFormat == PVMF_MIME_PCM16)
3183     {
3184         iOMXComponentInputBufferSize = MAX_NUM_AMR_FRAMES_PER_BUFFER * (PVMF_AMRENC_DEFAULT_FRAME_DURATION * PVMF_AMRENC_DEFAULT_SAMPLING_RATE * PVMF_AMRENC_DEFAULT_BITSPERSAMPLE) / (1000 * 8);
3185 
3186     }
3187     else
3188     {
3189         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3190                         (0, "PVMFOMXEncNode-%s::NegotiateAudioComponentParameters() Problem with input port %d color format", iNodeTypeId, iInputPortIndex));
3191         return false;
3192     }
3193 
3194     //Set the input buffer size to the encoder component
3195     iParamPort.nBufferSize = iOMXComponentInputBufferSize;
3196 
3197     // set Encoding type
3198 
3199     //iParamPort.format.audio.bFlagErrorConcealment = OMX_TRUE;
3200 
3201     // indicate that input is uncompressed i.e. PCM
3202     iParamPort.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
3203 
3204     // let the component decide about the number of input buffers
3205     iNumInputBuffers = iParamPort.nBufferCountActual;
3206 
3207     // do we need to increase the number of buffers?
3208     if (iNumInputBuffers < iParamPort.nBufferCountMin)
3209         iNumInputBuffers = iParamPort.nBufferCountMin;
3210 
3211 
3212     // if component allows us to allocate buffers, we'll decide how many to allocate
3213     if (iOMXComponentSupportsExternalInputBufferAlloc && (iParamPort.nBufferCountMin < NUMBER_INPUT_BUFFER))
3214     {
3215         // preset the number of input buffers
3216         iNumInputBuffers = NUMBER_INPUT_BUFFER;
3217     }
3218 
3219     // set the number of input buffer
3220     iParamPort.nBufferCountActual = iNumInputBuffers;
3221 
3222     // set the number of actual input buffers
3223     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3224                     (0, "PVMFOMXEncNode-%s::NegotiateAudioComponentParameters() Inport buffers %d,size %d", iNodeTypeId, iNumInputBuffers, iOMXComponentInputBufferSize));
3225 
3226     // lock in the input port parameters
3227     CONFIG_SIZE_AND_VERSION(iParamPort);
3228     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamPortDefinition, &iParamPort);
3229     if (Err != OMX_ErrorNone)
3230     {
3231         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3232                         (0, "PVMFOMXEncNode-%s::NegotiateAudioComponentParameters() Problem setting parameters in input port %d ", iNodeTypeId, iInputPortIndex));
3233         return false;
3234     }
3235 
3236     // For INPUT, we also need to set the PCM parameters, such as sampling rate, etc.
3237     // GET the output buffer params and sizes
3238     OMX_AUDIO_PARAM_PCMMODETYPE Audio_Pcm_Param;
3239     Audio_Pcm_Param.nPortIndex = iInputPortIndex;
3240 
3241     CONFIG_SIZE_AND_VERSION(Audio_Pcm_Param);
3242 
3243 
3244     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamAudioPcm, &Audio_Pcm_Param);
3245     if (Err != OMX_ErrorNone)
3246     {
3247         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3248                         (0, "PVMFOMXEncNode-%s::NegotiateAudioComponentParameters() Problem getting PCM parameters with input port %d ", iNodeTypeId, iInputPortIndex));
3249         return false;
3250     }
3251 
3252 
3253     Audio_Pcm_Param.nChannels       = (OMX_U32) iAudioInputFormat.iInputNumChannels;
3254     Audio_Pcm_Param.eNumData        =   OMX_NumericalDataSigned; // signed
3255     Audio_Pcm_Param.eEndian         =   OMX_EndianLittle; // little-endian
3256     Audio_Pcm_Param.bInterleaved    = ((EINTERLEAVE_LR == iAudioInputFormat.iInputInterleaveMode) ? OMX_TRUE : OMX_FALSE);
3257     Audio_Pcm_Param.nBitPerSample   = (OMX_U32) iAudioInputFormat.iInputBitsPerSample;
3258     Audio_Pcm_Param.nSamplingRate   = (OMX_U32) iAudioInputFormat.iInputSamplingRate;
3259     Audio_Pcm_Param.ePCMMode        =   OMX_AUDIO_PCMModeLinear;
3260     // don't set - let use default Audio_Pcm_Param.eChannelMapping
3261 
3262 
3263     CONFIG_SIZE_AND_VERSION(Audio_Pcm_Param);
3264 
3265     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamAudioPcm, &Audio_Pcm_Param);
3266     if (Err != OMX_ErrorNone)
3267     {
3268         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3269                         (0, "PVMFOMXEncNode-%s::NegotiateAudioComponentParameters() Problem setting PCM parameters with input port %d ", iNodeTypeId, iInputPortIndex));
3270         return false;
3271     }
3272 
3273     //////////////////////// OUTPUT PORT////////////////////////////////////////////////
3274 
3275     // first of all, check if the port supports the adequate port format
3276     if ((iOutFormat == PVMF_MIME_AMR_IETF) ||
3277             (iOutFormat == PVMF_MIME_AMRWB_IETF) ||
3278             (iOutFormat == PVMF_MIME_AMR_IF2))
3279     {
3280         DesiredPortFormat = OMX_AUDIO_CodingAMR;
3281     }
3282     else if ((iOutFormat == PVMF_MIME_ADIF) ||
3283              (iOutFormat == PVMF_MIME_ADTS) ||
3284              (iOutFormat == PVMF_MIME_MPEG4_AUDIO))
3285     {
3286         DesiredPortFormat = OMX_AUDIO_CodingAAC;
3287     }
3288     else
3289     {
3290         DesiredPortFormat = OMX_AUDIO_CodingUnused;
3291     }
3292 
3293     if (DesiredPortFormat == OMX_AUDIO_CodingUnused)
3294     {
3295         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3296                         (0, "PVMFOMXEncNode-%s::NegotiateAudioComponentParameters() Problem with output port %d format", iNodeTypeId, iOutputPortIndex));
3297         return false;
3298     }
3299 
3300     CONFIG_SIZE_AND_VERSION(Audio_port_format);
3301 
3302     Audio_port_format.nPortIndex = iOutputPortIndex; // set output port as target
3303 
3304     // loop over supported formats until we hit the one we want
3305     // or until the component has no more supported formats (in which case it returns OMX_ErrorNoMore
3306     Err = OMX_ErrorNone;
3307     Audio_port_format.nIndex = 0; //init the format counter
3308     while (OMX_ErrorNone == Err)
3309     {
3310 
3311         Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamAudioPortFormat, &Audio_port_format);
3312         if ((OMX_ErrorNone != Err))
3313         {
3314             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3315                             (0, "PVMFOMXEncNode-%s::NegotiateAudioComponentParameters() Problem getting port format for output port %d or no desired port format found", iNodeTypeId, iOutputPortIndex));
3316             return false;
3317         }
3318 
3319         if (Audio_port_format.eEncoding == DesiredPortFormat)
3320             break;
3321 
3322         Audio_port_format.nIndex ++;
3323     }
3324 
3325     // OK, we've found the desired format, set it as the one used
3326     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamAudioPortFormat, &Audio_port_format);
3327     if ((OMX_ErrorNone != Err))
3328     {
3329         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3330                         (0, "PVMFOMXEncNode-%s::NegotiateAudioComponentParameters() Problem setting port format for output port %d ", iNodeTypeId, iOutputPortIndex));
3331         return false;
3332     }
3333 
3334 
3335     //Port 1 for output port
3336     CONFIG_SIZE_AND_VERSION(iParamPort);
3337     iParamPort.nPortIndex = iOutputPortIndex;
3338     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamPortDefinition, &iParamPort);
3339     if (Err != OMX_ErrorNone)
3340     {
3341         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3342                         (0, "PVMFOMXEncNode-%s::NegotiateAudioComponentParameters() Problem negotiating with output port %d ", iNodeTypeId, iOutputPortIndex));
3343         return false;
3344     }
3345 
3346     // let the component decide output buffer size
3347     iOMXComponentOutputBufferSize = iParamPort.nBufferSize;
3348 
3349     // let the component decide num output buffers
3350     iNumOutputBuffers = iParamPort.nBufferCountActual;
3351 
3352     //check the number
3353     if (iNumOutputBuffers < iParamPort.nBufferCountMin)
3354         iNumOutputBuffers = iParamPort.nBufferCountMin;
3355 
3356 
3357     // set the number ourselves
3358     if (iOMXComponentSupportsExternalOutputBufferAlloc && (iParamPort.nBufferCountMin < NUMBER_OUTPUT_BUFFER))
3359     {
3360         iNumOutputBuffers = NUMBER_OUTPUT_BUFFER;
3361     }
3362 
3363     iParamPort.nBufferCountActual = iNumOutputBuffers;
3364 
3365 
3366     // set the output (target) format, etc.
3367     iParamPort.format.audio.bFlagErrorConcealment = OMX_TRUE;
3368 
3369 
3370 
3371     if ((iOutFormat == PVMF_MIME_AMR_IETF) ||
3372             (iOutFormat == PVMF_MIME_AMRWB_IETF) ||
3373             (iOutFormat == PVMF_MIME_AMR_IF2))
3374     {
3375         iParamPort.format.audio.eEncoding = OMX_AUDIO_CodingAMR;
3376     }
3377     else if ((iOutFormat == PVMF_MIME_ADTS) ||
3378              (iOutFormat == PVMF_MIME_ADIF) ||
3379              (iOutFormat == PVMF_MIME_MPEG4_AUDIO))
3380     {
3381         iParamPort.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
3382     }
3383 
3384     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3385                     (0, "PVMFOMXEncNode-%s::NegotiateAudioComponentParameters() Outport buffers %d,size %d", iNodeTypeId, iNumOutputBuffers, iOMXComponentOutputBufferSize));
3386 
3387 
3388     CONFIG_SIZE_AND_VERSION(iParamPort);
3389     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamPortDefinition, &iParamPort);
3390     if (Err != OMX_ErrorNone)
3391     {
3392         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3393                         (0, "PVMFOMXEncNode-%s::NegotiateAudioComponentParameters() Problem setting parameters in output port %d ", iNodeTypeId, iOutputPortIndex));
3394         return false;
3395 
3396     }
3397 
3398     // now call codec specific parameter setting
3399     bool status = true;
3400     if ((iOutFormat == PVMF_MIME_AMR_IETF) ||
3401             (iOutFormat == PVMF_MIME_AMRWB_IETF) ||
3402             (iOutFormat == PVMF_MIME_AMR_IF2))
3403     {
3404 
3405         status = SetAMREncoderParameters();
3406     }
3407     else if ((iOutFormat == PVMF_MIME_ADTS) ||
3408              (iOutFormat == PVMF_MIME_ADIF) ||
3409              (iOutFormat == PVMF_MIME_MPEG4_AUDIO))
3410     {
3411         status = SetAACEncoderParameters();
3412     }
3413 
3414 
3415     return status;
3416 }
3417 
SetAMREncoderParameters()3418 bool PVMFOMXEncNode::SetAMREncoderParameters()
3419 {
3420 
3421     OMX_ERRORTYPE Err = OMX_ErrorNone;
3422     OMX_AUDIO_PARAM_AMRTYPE AmrType;
3423 
3424     CONFIG_SIZE_AND_VERSION(AmrType);
3425     AmrType.nPortIndex = iOutputPortIndex;
3426 
3427     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamAudioAmr, &AmrType);
3428     if (Err != OMX_ErrorNone)
3429     {
3430         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3431                         (0, "PVMFOMXEncNode-%s::SetAMREncoderParameters - Problem getting AMR parameters in output port %d ", iNodeTypeId, iOutputPortIndex));
3432         return false;
3433     }
3434 
3435     AmrType.nChannels = iAudioEncodeParam.iOutputNumChannels; // must be 1
3436 
3437     switch (iAudioEncodeParam.iAMRBitrate)
3438     {
3439         case GSM_AMR_4_75:  // AMR NB bitrates
3440             AmrType.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0;
3441             break;
3442         case GSM_AMR_5_15:
3443             AmrType.eAMRBandMode = OMX_AUDIO_AMRBandModeNB1;
3444             break;
3445         case GSM_AMR_5_90:
3446             AmrType.eAMRBandMode = OMX_AUDIO_AMRBandModeNB2;
3447             break;
3448         case GSM_AMR_6_70:
3449             AmrType.eAMRBandMode = OMX_AUDIO_AMRBandModeNB3;
3450             break;
3451         case GSM_AMR_7_40:
3452             AmrType.eAMRBandMode = OMX_AUDIO_AMRBandModeNB4;
3453             break;
3454         case GSM_AMR_7_95:
3455             AmrType.eAMRBandMode = OMX_AUDIO_AMRBandModeNB5;
3456             break;
3457         case GSM_AMR_10_2:
3458             AmrType.eAMRBandMode = OMX_AUDIO_AMRBandModeNB6;
3459             break;
3460         case GSM_AMR_12_2:
3461             AmrType.eAMRBandMode = OMX_AUDIO_AMRBandModeNB7;
3462             break;
3463         case GSM_AMR_6_60: // AMR WB bitrates start here
3464             AmrType.eAMRBandMode = OMX_AUDIO_AMRBandModeWB0;
3465             break;
3466         case GSM_AMR_8_85:
3467             AmrType.eAMRBandMode = OMX_AUDIO_AMRBandModeWB1;
3468             break;
3469         case GSM_AMR_12_65:
3470             AmrType.eAMRBandMode = OMX_AUDIO_AMRBandModeWB2;
3471             break;
3472         case GSM_AMR_14_25:
3473             AmrType.eAMRBandMode = OMX_AUDIO_AMRBandModeWB3;
3474             break;
3475         case GSM_AMR_15_85:
3476             AmrType.eAMRBandMode = OMX_AUDIO_AMRBandModeWB4;
3477             break;
3478         case GSM_AMR_18_25:
3479             AmrType.eAMRBandMode = OMX_AUDIO_AMRBandModeWB5;
3480             break;
3481         case GSM_AMR_19_85:
3482             AmrType.eAMRBandMode = OMX_AUDIO_AMRBandModeWB6;
3483             break;
3484         case GSM_AMR_23_05:
3485             AmrType.eAMRBandMode = OMX_AUDIO_AMRBandModeWB7;
3486             break;
3487         case GSM_AMR_23_85:
3488             AmrType.eAMRBandMode = OMX_AUDIO_AMRBandModeWB8;
3489             break;
3490         default:
3491             return false;
3492     }
3493 
3494     AmrType.eAMRDTXMode = OMX_AUDIO_AMRDTXModeOnAuto;
3495 
3496     if ((iOutFormat == PVMF_MIME_AMR_IETF) || (iOutFormat == PVMF_MIME_AMRWB_IETF))
3497     {
3498         AmrType.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
3499     }
3500     else if (iOutFormat == PVMF_MIME_AMR_IF2)
3501     {
3502         AmrType.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatIF2;
3503     }
3504 
3505     CONFIG_SIZE_AND_VERSION(AmrType);
3506     AmrType.nPortIndex = iOutputPortIndex;
3507 
3508     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamAudioAmr, &AmrType);
3509     if (Err != OMX_ErrorNone)
3510     {
3511         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3512                         (0, "PVMFOMXEncNode-%s::SetAMREncoderParameters - Problem setting AMR parameters in output port %d ", iNodeTypeId, iOutputPortIndex));
3513         return false;
3514     }
3515 
3516     return true;
3517 }
3518 
SetAACEncoderParameters()3519 bool PVMFOMXEncNode::SetAACEncoderParameters()
3520 {
3521 
3522     OMX_ERRORTYPE Err = OMX_ErrorNone;
3523     OMX_AUDIO_PARAM_AACPROFILETYPE AacType;
3524 
3525 
3526     CONFIG_SIZE_AND_VERSION(AacType);
3527     AacType.nPortIndex = iOutputPortIndex;
3528 
3529     Err = OMX_GetParameter(iOMXEncoder, OMX_IndexParamAudioAac, &AacType);
3530     if (Err != OMX_ErrorNone)
3531     {
3532         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3533                         (0, "PVMFOMXEncNode-%s::SetAACEncoderParameters - Problem getting AAC parameters in output port %d ", iNodeTypeId, iOutputPortIndex));
3534         return false;
3535     }
3536 
3537     AacType.nChannels = iAudioEncodeParam.iOutputNumChannels;
3538     // The following parameter could be set to input sampling rate or 0 (i.e. unknown)
3539     AacType.nSampleRate = iAudioEncodeParam.iOutputSamplingRate;
3540     // The following parameter could be set to 0 (i.e. unknown)
3541     AacType.nBitRate = iAudioEncodeParam.iOutputBitrate;
3542 
3543     // Let encoder decide the following parameters - i.e. set to 0
3544     AacType.nAudioBandWidth =   0;
3545     AacType.nFrameLength    =   0;
3546     AacType.nAACtools =         OMX_AUDIO_AACToolAll; // this means all tools are allowed - let encoder decide
3547     AacType.nAACERtools =       OMX_AUDIO_AACERNone;   // error resilience tools are not allowed
3548 
3549     // Set the AAC profile to use LC
3550     AacType.eAACProfile = OMX_AUDIO_AACObjectLC;
3551 
3552     // Do set the stream format
3553     if (iOutFormat == PVMF_MIME_ADTS)
3554     {
3555         AacType.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
3556     }
3557     else if (iOutFormat == PVMF_MIME_ADIF)
3558     {
3559         AacType.eAACStreamFormat = OMX_AUDIO_AACStreamFormatADIF;
3560     }
3561     else if (iOutFormat == PVMF_MIME_MPEG4_AUDIO)
3562     {
3563         AacType.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
3564     }
3565 
3566     // Set the AAC channel mode - (stereo, or mono)
3567     if (iAudioEncodeParam.iOutputNumChannels == 1)
3568     {
3569         AacType.eChannelMode = OMX_AUDIO_ChannelModeMono;
3570     }
3571     else if (iAudioEncodeParam.iOutputNumChannels == 2)
3572     {
3573         AacType.eChannelMode = OMX_AUDIO_ChannelModeStereo;
3574     }
3575 
3576     CONFIG_SIZE_AND_VERSION(AacType);
3577     AacType.nPortIndex = iOutputPortIndex;
3578 
3579     Err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamAudioAac, &AacType);
3580     if (Err != OMX_ErrorNone)
3581     {
3582         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3583                         (0, "PVMFOMXEncNode-%s::SetAACEncoderParameters - Problem setting AAC parameters in output port %d ", iNodeTypeId, iOutputPortIndex));
3584         return false;
3585     }
3586 
3587     return true;
3588 }
3589 
SetDefaultCapabilityFlags()3590 bool PVMFOMXEncNode::SetDefaultCapabilityFlags()
3591 {
3592 
3593     iIsOMXComponentMultiThreaded = true;
3594 
3595     iOMXComponentSupportsExternalOutputBufferAlloc = false;
3596     iOMXComponentSupportsExternalInputBufferAlloc = false;
3597     iOMXComponentSupportsMovableInputBuffers = false;
3598 
3599     iOMXComponentUsesNALStartCodes = true;
3600     iOMXComponentSupportsPartialFrames = false;
3601     iOMXComponentCanHandleIncompleteFrames = false;
3602     iOMXComponentUsesFullAVCFrames = false;
3603 
3604     return true;
3605 }
3606 
3607 
3608 
SendEOSBufferToOMXComponent()3609 bool PVMFOMXEncNode::SendEOSBufferToOMXComponent()
3610 {
3611 
3612     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3613                     (0, "PVMFOMXEncNode-%s::SendEOSBufferToOMXComponent() In", iNodeTypeId));
3614 
3615 
3616     // first of all, check if the component is running. EOS could be sent prior to component/encoder
3617     // even being initialized
3618 
3619     // returning false will ensure that the EOS will be sent downstream anyway without waiting for the
3620     // Component to respond
3621     if (iCurrentEncoderState != OMX_StateExecuting)
3622         return false;
3623 
3624     // get an input buffer. Without a buffer, no point in proceeding
3625     InputBufCtrlStruct *input_buf = NULL;
3626     int32 errcode = 0;
3627 
3628     // we already checked that the number of buffers is OK, so we don't expect problems
3629     // try to get input buffer header
3630     OSCL_TRY(errcode, input_buf = (InputBufCtrlStruct *) iInBufMemoryPool->allocate(iInputAllocSize));
3631     if (errcode != 0)
3632     {
3633         if (errcode == OsclErrNoResources)
3634         {
3635 
3636             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger,
3637                             PVLOGMSG_DEBUG, (0, "PVMFOMXEncNode-%s::SendEOSBufferToOMXComponent() No more buffers in the mempool - unexpected", iNodeTypeId));
3638 
3639             iInBufMemoryPool->notifyfreechunkavailable(*this, (OsclAny*) iInBufMemoryPool); // To signal when next deallocate() is called on mempool
3640 
3641             return false;
3642         }
3643         else
3644         {
3645             // Memory allocation for the pool failed
3646             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
3647                             (0, "PVMFOMXEncNode-%s::SendEOSBufferToOMXComponent() Input mempool error", iNodeTypeId));
3648 
3649 
3650             SetState(EPVMFNodeError);
3651             ReportErrorEvent(PVMFErrNoMemory);
3652             return false;
3653         }
3654 
3655     }
3656 
3657     // keep track of buffers. When buffer is deallocated/released, the counter will be decremented
3658     iInBufMemoryPool->notifyfreechunkavailable(*this, (OsclAny*) iInBufMemoryPool);
3659     iNumOutstandingInputBuffers++;
3660 
3661     // in this case, no need to use input msg refcounter. Make sure its unbound
3662     (input_buf->pMediaData).Unbind();
3663 
3664     // THIS IS AN EMPTY BUFFER. FLAGS ARE THE ONLY IMPORTANT THING
3665     input_buf->pBufHdr->nFilledLen = 0;
3666     input_buf->pBufHdr->nOffset = 0;
3667 
3668     input_buf->pBufHdr->nTimeStamp = iEndOfDataTimestamp;
3669     if (bIsQCOMOmxComp)
3670     {
3671         input_buf->pBufHdr->nTimeStamp = 1000 * iEndOfDataTimestamp;
3672     }
3673 
3674     // set ptr to input_buf structure for Context (for when the buffer is returned)
3675     input_buf->pBufHdr->pAppPrivate = (OMX_PTR) input_buf;
3676 
3677     // do not use Mark here (but init to NULL to prevent problems)
3678     input_buf->pBufHdr->hMarkTargetComponent = NULL;
3679     input_buf->pBufHdr->pMarkData = NULL;
3680 
3681 
3682     // init buffer flags
3683     input_buf->pBufHdr->nFlags = 0;
3684 
3685     input_buf->pBufHdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
3686     // most importantly, set the EOS flag:
3687     input_buf->pBufHdr->nFlags |= OMX_BUFFERFLAG_EOS;
3688 
3689     // send buffer to component
3690     OMX_EmptyThisBuffer(iOMXEncoder, input_buf->pBufHdr);
3691 
3692     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3693                     (0, "PVMFOMXEncNode-%s::SendEOSBufferToOMXComponent() Out", iNodeTypeId));
3694 
3695     return true;
3696 
3697 }
3698 
3699 
SendInputBufferToOMXComponent()3700 bool PVMFOMXEncNode::SendInputBufferToOMXComponent()
3701 {
3702 
3703     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3704                     (0, "PVMFOMXEncNode-%s::SendInputBufferToOMXComponent() In", iNodeTypeId));
3705 
3706     // first of all , get an input buffer. Without a buffer, no point in proceeding
3707     InputBufCtrlStruct *input_buf = NULL;
3708     int32 errcode = 0;
3709     uint32 ii;
3710 
3711     do
3712     {
3713         // do loop to loop over all fragments
3714 
3715         // try to get input buffer header
3716         InputBufCtrlStruct *temp = NULL;
3717         OSCL_TRY(errcode, temp = (InputBufCtrlStruct *) iInBufMemoryPool->allocate(iInputAllocSize));
3718         //input_buf = temp; //JJDBG
3719         if (errcode != 0)
3720         {
3721             if (errcode == OsclErrNoResources)
3722             {
3723 
3724                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger,
3725                                 PVLOGMSG_DEBUG, (0, "PVMFOMXEncNode-%s::SendInputBufferToOMXComponent() No more buffers in the mempool", iNodeTypeId));
3726 
3727                 iInBufMemoryPool->notifyfreechunkavailable(*this, (OsclAny*) iInBufMemoryPool); // To signal when next deallocate() is called on mempool
3728 
3729                 return false;
3730             }
3731             else
3732             {
3733                 // Memory allocation for the pool failed
3734                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
3735                                 (0, "PVMFOMXEncNode-%s::SendInputBufferToOMXComponent() Input mempool error", iNodeTypeId));
3736 
3737 
3738                 SetState(EPVMFNodeError);
3739                 ReportErrorEvent(PVMFErrNoMemory);
3740                 return false;
3741             }
3742 
3743         }
3744         input_buf = new(temp)InputBufCtrlStruct ; //JJDBG
3745 
3746         // keep track of buffers. When buffer is deallocated/released, the counter will be decremented
3747         iInBufMemoryPool->notifyfreechunkavailable(*this, (OsclAny*) iInBufMemoryPool);
3748         iNumOutstandingInputBuffers++;
3749 
3750         for (ii = 0; ii < iNumInputBuffers; ii++)
3751         {
3752             if (input_buf == in_ctrl_struct_ptr[ii])
3753             {
3754                 break;
3755             }
3756         }
3757 
3758         if (ii == iNumInputBuffers)
3759             return false;
3760 
3761         input_buf->pBufHdr = (OMX_BUFFERHEADERTYPE *)in_buff_hdr_ptr[ii];
3762 
3763         // Now we have the buffer header (i.e. a buffer) to send to component:
3764         // Depending on OMX component capabilities, either pass the input msg fragment(s) directly
3765         //  into OMX component without copying (and update the input msg refcount)
3766         //  or memcopy the content of input msg memfrag(s) into OMX component allocated buffers
3767 
3768 
3769         // if this is the first fragment in a new message, extract some info:
3770         if (iCurrFragNum == 0)
3771         {
3772 
3773             // NOTE: SeqNum differ in Codec and in Node because of the fact that
3774             // one msg can contain multiple fragments that are sent to the codec as
3775             // separate buffers. Node tracks msgs and codec tracks even separate fragments
3776 
3777             iCodecSeqNum += (iDataIn->getSeqNum() - iInPacketSeqNum); // increment the codec seq. # by the same
3778             // amount that the input seq. number increased
3779 
3780             iInPacketSeqNum = iDataIn->getSeqNum(); // remember input sequence number
3781             iInTimestamp = iDataIn->getTimestamp();
3782             if (bIsQCOMOmxComp)
3783             {
3784                 iInTimestamp *= 1000;
3785             }
3786             iInDuration = iDataIn->getDuration();
3787             iInNumFrags = iDataIn->getNumFragments();
3788 
3789 
3790 
3791             iCurrentMsgMarkerBit = iDataIn->getMarkerInfo() & PVMF_MEDIA_DATA_MARKER_INFO_M_BIT;
3792 
3793 
3794             // logging info:
3795             if (iDataIn->getNumFragments() > 1)
3796             {
3797                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3798                                 (0, "PVMFOMXEncNode-%s::SendInputBufferToOMXComponent() - New msg has MULTI-FRAGMENTS", iNodeTypeId));
3799             }
3800 
3801             if (!(iDataIn->getMarkerInfo() & PVMF_MEDIA_DATA_MARKER_INFO_M_BIT))
3802             {
3803 
3804                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3805                                 (0, "PVMFOMXEncNode-%s::SendInputBufferToOMXComponent() - New msg has NO MARKER BIT", iNodeTypeId));
3806             }
3807         }
3808 
3809 
3810         // get a memfrag from the message
3811         OsclRefCounterMemFrag frag;
3812         iDataIn->getMediaFragment(iCurrFragNum, frag);
3813 
3814 
3815         if (iOMXComponentSupportsMovableInputBuffers)
3816         {
3817             // no copying required
3818 
3819             // increment the RefCounter of the message associated with the mem fragment/buffer
3820             // when sending this buffer to OMX component. (When getting the buffer back, the refcounter
3821             // will be decremented. Thus, when the last fragment is returned, the input mssage is finally released
3822 
3823             iDataIn.GetRefCounter()->addRef();
3824 
3825             // associate the buffer ctrl structure with the message ref counter and ptr
3826             input_buf->pMediaData = PVMFSharedMediaDataPtr(iDataIn.GetRep(), iDataIn.GetRefCounter());
3827 
3828 
3829             // set pointer to the data, length, offset
3830             input_buf->pBufHdr->pBuffer = (uint8 *)frag.getMemFragPtr();
3831             input_buf->pBufHdr->nFilledLen = frag.getMemFragSize();
3832 
3833             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3834                             (0, "PVMFOMXEncNode-%s::SendInputBufferToOMXComponent() - Buffer 0x%x of size %d, %d frag out of tot. %d, TS=%d", iNodeTypeId, input_buf->pBufHdr->pBuffer, frag.getMemFragSize(), iCurrFragNum + 1, iDataIn->getNumFragments(), iInTimestamp));
3835 
3836             iCurrFragNum++; // increment fragment number and move on to the next
3837 
3838 
3839         }
3840         else
3841         {
3842 
3843             // in this case, no need to use input msg refcounter, each buffer fragment is copied over and treated separately
3844             (input_buf->pMediaData).Unbind();
3845 
3846 
3847             // init variables
3848             iCopyPosition = 0;
3849             iFragmentSizeRemainingToCopy  = frag.getMemFragSize();
3850 
3851 
3852             // can the remaining fragment fit into the buffer?
3853             if (iFragmentSizeRemainingToCopy <= (input_buf->pBufHdr->nAllocLen))
3854             {
3855 
3856                 oscl_memcpy(input_buf->pBufHdr->pBuffer,
3857                             (void *)((uint8 *)frag.getMemFragPtr() + iCopyPosition),
3858                             iFragmentSizeRemainingToCopy);
3859 
3860                 input_buf->pBufHdr->nFilledLen = iFragmentSizeRemainingToCopy;
3861 
3862                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3863                                 (0, "PVMFOMXEncNode-%s::SendInputBufferToOMXComponent() - Copied %d bytes of fragment %d out of %d into buffer 0x%x of size %d, TS=%d ", iNodeTypeId, iFragmentSizeRemainingToCopy, iCurrFragNum + 1, iDataIn->getNumFragments(), input_buf->pBufHdr->pBuffer, input_buf->pBufHdr->nFilledLen, iInTimestamp));
3864 
3865                 iCopyPosition += iFragmentSizeRemainingToCopy;
3866                 iFragmentSizeRemainingToCopy = 0;
3867 
3868 
3869 
3870             }
3871             else
3872             {
3873                 // copy as much as you can of the current fragment into the current buffer
3874                 oscl_memcpy(input_buf->pBufHdr->pBuffer,
3875                             (void *)((uint8 *)frag.getMemFragPtr() + iCopyPosition),
3876                             input_buf->pBufHdr->nAllocLen);
3877 
3878                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3879                                 (0, "PVMFOMXEncNode-%s::SendInputBufferToOMXComponent() - Frame cannot fit into input buffer ! Copied %d bytes of fragment %d out of %d into buffer 0x%x of size %d, TS=%d", iNodeTypeId, input_buf->pBufHdr->nAllocLen, iCurrFragNum + 1, iDataIn->getNumFragments(), input_buf->pBufHdr->pBuffer, input_buf->pBufHdr->nFilledLen, iInTimestamp));
3880 
3881                 input_buf->pBufHdr->nFilledLen = input_buf->pBufHdr->nAllocLen;
3882                 iCopyPosition += input_buf->pBufHdr->nAllocLen; // move current position within fragment forward
3883                 iFragmentSizeRemainingToCopy -= input_buf->pBufHdr->nAllocLen;
3884 
3885             }
3886 
3887             // proceed to the next fragment regardless of input buffer size
3888             iCurrFragNum++;
3889         }
3890 
3891 
3892         // set buffer fields (this is the same regardless of whether the input is movable or not
3893         input_buf->pBufHdr->nOffset = 0;
3894         input_buf->pBufHdr->nTimeStamp = iInTimestamp;
3895 
3896         // set ptr to input_buf structure for Context (for when the buffer is returned)
3897         input_buf->pBufHdr->pAppPrivate = (OMX_PTR) input_buf;
3898 
3899         // do not use Mark here (but init to NULL to prevent problems)
3900         input_buf->pBufHdr->hMarkTargetComponent = NULL;
3901         input_buf->pBufHdr->pMarkData = NULL;
3902 
3903 
3904         // init buffer flags
3905         input_buf->pBufHdr->nFlags = 0;
3906 
3907 
3908         // set the key frame flag if necessary (mark every fragment that belongs to it)
3909         if (iDataIn->getMarkerInfo() & PVMF_MEDIA_DATA_MARKER_INFO_RANDOM_ACCESS_POINT_BIT)
3910             input_buf->pBufHdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
3911 
3912 
3913         // in case of encoder, all input frames should be marked
3914         input_buf->pBufHdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
3915         OMX_EmptyThisBuffer(iOMXEncoder, input_buf->pBufHdr);
3916 
3917 
3918         // if we sent all fragments to OMX component, decouple the input message from iDataIn
3919         // Input message is "decoupled", so that we can get a new message for processing into iDataIn
3920         //  However, the actual message is released completely to upstream mempool once all of its fragments
3921         //  are returned by the OMX component
3922 
3923         if (iCurrFragNum == iDataIn->getNumFragments())
3924         {
3925             iDataIn.Unbind();
3926 
3927         }
3928 
3929 
3930     }
3931     while (iCurrFragNum < iInNumFrags); //iDataIn->getNumFragments());
3932 
3933 
3934     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3935                     (0, "PVMFOMXEncNode-%s::SendInputBufferToOMXComponent() Out", iNodeTypeId));
3936 
3937     return true;
3938 
3939 }
3940 
3941 
3942 
3943 /////////////////////////////////////////////////////////////////////////////
CreateOutMemPool(uint32 num_buffers)3944 bool PVMFOMXEncNode::CreateOutMemPool(uint32 num_buffers)
3945 {
3946 
3947     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3948                     (0, "PVMFOMXEncNode-%s::CreateOutMemPool() start", iNodeTypeId));
3949     // In the case OMX component wants to allocate its own buffers,
3950     // mempool only contains OutputBufCtrlStructures (i.e. ptrs to buffer headers)
3951     // In case OMX component uses pre-allocated buffers (here),
3952     // mempool allocates OutputBufCtrlStructure (i.e. ptrs to buffer hdrs), followed by actual buffers
3953 
3954     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3955                     (0, "PVMFOMXEncNode-%s::CreateOutMemPool() Allocating output buffer header pointers", iNodeTypeId));
3956 
3957     iOutputAllocSize = oscl_mem_aligned_size((uint32)sizeof(OutputBufCtrlStruct));
3958 
3959     if (iOMXComponentSupportsExternalOutputBufferAlloc)
3960     {
3961         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3962                         (0, "PVMFOMXEncNode-%s::CreateOutMemPool() Allocating output buffers of size %d as well", iNodeTypeId, iOMXComponentOutputBufferSize));
3963 
3964         //pre-negotiated output buffer size
3965         iOutputAllocSize += iOMXComponentOutputBufferSize;
3966     }
3967 
3968     // ENCODER SPECIFIC FOR AVC RAW (BYTESTREAM) FORMAT
3969     if ((iOutFormat == PVMF_MIME_H264_VIDEO_RAW) &&
3970             (!iOMXComponentUsesFullAVCFrames) &&
3971             (!iOMXComponentUsesNALStartCodes))
3972     {
3973         iOutputAllocSize += 4; // NAL SYNC WORD SIZE
3974     }
3975 
3976     // for media data wrapper
3977     if (iMediaDataMemPool)
3978     {
3979         iMediaDataMemPool->removeRef();
3980         iMediaDataMemPool = NULL;
3981     }
3982 
3983     if (iOutBufMemoryPool)
3984     {
3985         iOutBufMemoryPool->removeRef();
3986         iOutBufMemoryPool = NULL;
3987     }
3988 
3989     int32 leavecode = 0;
3990     OSCL_TRY(leavecode, iOutBufMemoryPool = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (num_buffers)););
3991     if (leavecode || iOutBufMemoryPool == NULL)
3992     {
3993         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger,
3994                         PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::CreateOutMemPool() Memory pool structure for output buffers failed to allocate", iNodeTypeId));
3995         return false;
3996     }
3997 
3998 
3999 
4000     // allocate a dummy buffer to actually create the mempool
4001     OsclAny *dummy_alloc = NULL; // this dummy buffer will be released at end of scope
4002     leavecode = 0;
4003     OSCL_TRY(leavecode, dummy_alloc = iOutBufMemoryPool->allocate(iOutputAllocSize));
4004     if (leavecode || dummy_alloc == NULL)
4005     {
4006 
4007         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger,
4008                         PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::CreateOutMemPool() Memory pool for output buffers failed to allocate", iNodeTypeId));
4009         return false;
4010     }
4011     iOutBufMemoryPool->deallocate(dummy_alloc);
4012     // init the counter
4013     iNumOutstandingOutputBuffers = 0;
4014 
4015     // allocate mempool for media data message wrapper
4016     leavecode = 0;
4017     OSCL_TRY(leavecode, iMediaDataMemPool = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (num_buffers, PVOMXENC_MEDIADATA_CHUNKSIZE)));
4018     if (leavecode || iMediaDataMemPool == NULL)
4019     {
4020         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::CreateOutMemPool() Media Data Buffer pool for output buffers failed to allocate", iNodeTypeId));
4021         return false;
4022     }
4023 
4024     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::CreateOutMemPool() done", iNodeTypeId));
4025     return true;
4026 }
4027 /////////////////////////////////////////////////////////////////////////////////////////////////////
4028 ///////////////////////////// Creates memory pool for input buffer management ///////////////////////
4029 /////////////////////////////////////////////////////////////////////////////////////////////////////
CreateInputMemPool(uint32 num_buffers)4030 bool PVMFOMXEncNode::CreateInputMemPool(uint32 num_buffers)
4031 {
4032     // 3 cases in order of preference and simplicity
4033 
4034     // Case 1 (buffers allocated upstream - no memcpy needed):
4035     //  PV OMX Component - We use buffers allocated outside the OMX node (i.e. allocated upstream)
4036     // Mempool contains InputBufCtrlStructures (ptrs to buffer headers and PMVFMediaData ptrs - to keep track of when to unbind input msgs)
4037 
4038     // NOTE:    in this case, when providing input buffers to OMX component,
4039     //          OMX_UseBuffer calls will provide some initial pointers and sizes of buffers, but these
4040     //          are dummy values. Actual buffer pointers and filled sizes will be obtained from the input msg fragments.
4041     //          The PV OMX component will use the buffers even if the ptrs differ from the ones during initialization
4042     //          3rd party OMX components can also use this case if they are capable of ignoring the actual buffer pointers in
4043     //          buffer header field (i.e. if after OMX_UseBuffer(...) call, they allow the ptr to actual buffer data to change at a later time
4044 
4045     // CASE 2 (buffers allocated in the node - memcpy needed)
4046     //          If 3rd party OMX component can use buffers allocated outside the OMX component, but it cannot
4047     //          change buffer ptr allocations dynamically (i.e. after initialization with OMX_UseBuffer call is complete)
4048 
4049     //      Mempool contains InputBufCtrlStructures (ptrs to buffer headers, PVMFMediaData ptrs to keep track of when to unbind input msgs) +
4050     //              actual buffers.
4051     //          NOTE: Data must be copied from input message into the local buffer before the buffer is given to the OMX component
4052 
4053     // CASE 3 (buffers allocated in the component - memcpy needed)
4054     //          If 3rd party OMX component must allocate its own buffers
4055     //          Mempool only contains InputBufCtrlStruct (ptrs to buffer headers + PMVFMediaData ptrs to keep track of when to unbind input msgs)
4056     //          NOTE: Data must be copied from input message into the local buffer before the buffer is given to the OMX component (like in case 2)
4057 
4058     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4059                     (0, "PVMFOMXEncNode-%s::CreateInputMemPool() start ", iNodeTypeId));
4060 
4061     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4062                     (0, "PVMFOMXEncNode-%s::CreateInputMemPool() allocating buffer header pointers and shared media data ptrs ", iNodeTypeId));
4063 
4064 
4065 
4066     iInputAllocSize = oscl_mem_aligned_size((uint32) sizeof(InputBufCtrlStruct)); //aligned_size_buffer_header_ptr+aligned_size_media_data_ptr;
4067 
4068     // Need to allocate buffers in the node either if component supports external buffers buffers
4069     // but they are not movable
4070 
4071     if ((iOMXComponentSupportsExternalInputBufferAlloc && !iOMXComponentSupportsMovableInputBuffers))
4072     {
4073         //pre-negotiated input buffer size
4074         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4075                         (0, "PVMFOMXEncNode-%s::CreateOutMemPool() Allocating input buffers of size %d as well", iNodeTypeId, iOMXComponentInputBufferSize));
4076 
4077         iInputAllocSize += iOMXComponentInputBufferSize;
4078     }
4079 
4080     if (iInBufMemoryPool)
4081     {
4082         iInBufMemoryPool->removeRef();
4083         iInBufMemoryPool = NULL;
4084     }
4085 
4086     int32 leavecode = 0;
4087     OSCL_TRY(leavecode, iInBufMemoryPool = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (num_buffers)););
4088     if (leavecode || iInBufMemoryPool == NULL)
4089     {
4090         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger,
4091                         PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::CreateInputMemPool() Memory pool structure for input buffers failed to allocate", iNodeTypeId));
4092         return false;
4093     }
4094     // try to allocate a dummy buffer to actually create the mempool and allocate the needed memory
4095     // allocate a dummy buffer to actually create the mempool, this dummy buffer will be released at end of scope of this method
4096     OsclAny *dummy_alloc = NULL;
4097     leavecode = 0;
4098     OSCL_TRY(leavecode, dummy_alloc = iInBufMemoryPool->allocate(iInputAllocSize));
4099     if (leavecode || dummy_alloc == NULL)
4100     {
4101 
4102         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger,
4103                         PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::CreateInputMemPool() Memory pool for input buffers failed to allocate", iNodeTypeId));
4104         return false;
4105     }
4106 
4107     // init the counter
4108     iNumOutstandingInputBuffers = 0;
4109 
4110 
4111     iInputBufferToResendToComponent = NULL; // nothing to resend yet
4112     iInBufMemoryPool->deallocate(dummy_alloc);
4113 
4114     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::CreateInputMemPool() done", iNodeTypeId));
4115     return true;
4116 }
4117 ////////////////////////////////////////////////////////////////////////////
ProvideBuffersToComponent(OsclMemPoolFixedChunkAllocator * aMemPool,uint32 aAllocSize,uint32 aNumBuffers,uint32 aActualBufferSize,uint32 aPortIndex,bool aUseBufferOK,bool aIsThisInputBuffer)4118 bool PVMFOMXEncNode::ProvideBuffersToComponent(OsclMemPoolFixedChunkAllocator *aMemPool, // allocator
4119         uint32 aAllocSize,    // size to allocate from pool (hdr only or hdr+ buffer)
4120         uint32 aNumBuffers,    // number of buffers
4121         uint32 aActualBufferSize, // aactual buffer size
4122         uint32 aPortIndex,      // port idx
4123         bool aUseBufferOK,       // can component use OMX_UseBuffer or should it use OMX_AllocateBuffer
4124         bool aIsThisInputBuffer      // is this input or output
4125                                               )
4126 {
4127     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::ProvideBuffersToComponent() enter", iNodeTypeId));
4128 
4129     uint32 ii = 0;
4130     OMX_ERRORTYPE err = OMX_ErrorNone;
4131     OsclAny **ctrl_struct_ptr = aIsThisInputBuffer ? in_ctrl_struct_ptr : out_ctrl_struct_ptr;
4132 
4133     // Now, go through all buffers and tell component to
4134     // either use a buffer, or to allocate its own buffer
4135     for (ii = 0; ii < aNumBuffers; ii++)
4136     {
4137 
4138         int32 errcode = 0;
4139         // get the address where the buf hdr ptr will be stored
4140         errcode = MemAllocate(ctrl_struct_ptr[ii], aMemPool, aAllocSize);
4141         if ((errcode != OsclErrNone) || (ctrl_struct_ptr[ii] == NULL))
4142         {
4143             if (errcode == OsclErrNoResources)
4144             {
4145                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4146                                 (0, "PVMFOMXEncNode-%s::ProvideBuffersToComponent ->allocate() failed for no mempool chunk available", iNodeTypeId));
4147             }
4148             else
4149             {
4150                 // General error
4151                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
4152                                 (0, "PVMFOMXEncNode-%s::ProvideBuffersToComponent ->allocate() failed due to some general error", iNodeTypeId));
4153 
4154                 ReportErrorEvent(PVMFFailure);
4155                 ChangeNodeState(EPVMFNodeError);
4156             }
4157 
4158             return false;
4159         }
4160 
4161         if (aUseBufferOK)
4162         {
4163             // Buffers are already allocated outside OMX component.
4164             // In case of output buffers, the buffer itself is located
4165             // just after the buffer header pointer.
4166 
4167             // In case of input buffers, the buffer header pointer is followed by a MediaDataSharedPtr
4168             //  which is used to ensure proper unbinding of the input messages. The buffer itself is either:
4169             //      a) allocated upstream (and the ptr to the buffer
4170             //          is a dummy pointer to which the component does not pay attention - PV OMX component)
4171             //      b) located just after the buffer header pointer and MediaDataSharedPtr
4172 
4173             uint8 *pB = ((uint8*) ctrl_struct_ptr[ii]);
4174 
4175 
4176             // in case of input buffers, initialize also MediaDataSharedPtr structure
4177             if (aIsThisInputBuffer)
4178             {
4179 
4180                 InputBufCtrlStruct *temp = (InputBufCtrlStruct *) ctrl_struct_ptr[ii];
4181                 oscl_memset(&(temp->pMediaData), 0, sizeof(PVMFSharedMediaDataPtr));
4182                 temp->pMediaData = PVMFSharedMediaDataPtr(NULL, NULL);
4183 
4184                 // advance ptr to skip the structure
4185                 pB += oscl_mem_aligned_size(sizeof(InputBufCtrlStruct));
4186 
4187                 err = OMX_UseBuffer(iOMXEncoder,    // hComponent
4188                                     &(temp->pBufHdr),       // address where ptr to buffer header will be stored
4189                                     aPortIndex,             // port index (for port for which buffer is provided)
4190                                     ctrl_struct_ptr[ii],    // App. private data = pointer to beginning of allocated data
4191                                     //              to have a context when component returns with a callback (i.e. to know
4192                                     //              what to free etc.
4193                                     (OMX_U32)aActualBufferSize,     // buffer size
4194                                     pB);                        // buffer data ptr
4195 
4196                 in_buff_hdr_ptr[ii] = temp->pBufHdr;
4197 
4198             }
4199             else
4200             {
4201                 OutputBufCtrlStruct *temp = (OutputBufCtrlStruct *) ctrl_struct_ptr[ii];
4202                 // advance buffer ptr to skip the structure
4203                 pB += oscl_mem_aligned_size(sizeof(OutputBufCtrlStruct));
4204 
4205                 if ((iOutFormat == PVMF_MIME_H264_VIDEO_RAW) &&
4206                         !iOMXComponentUsesFullAVCFrames &&
4207                         !iOMXComponentUsesNALStartCodes)
4208                 {
4209                     // write out NAL sync word at the beginning of the buffer
4210                     pB[0] = 0;
4211                     pB[1] = 0;
4212                     pB[2] = 0;
4213                     pB[3] = 1;
4214                     pB += 4;
4215 
4216                     // THe buffer that the component knows is always the same
4217                     // The node will move the ptr -4 when it needs teh sync word
4218                 }
4219 
4220                 err = OMX_UseBuffer(iOMXEncoder,    // hComponent
4221                                     &(temp->pBufHdr),       // address where ptr to buffer header will be stored
4222                                     aPortIndex,             // port index (for port for which buffer is provided)
4223                                     ctrl_struct_ptr[ii],    // App. private data = pointer to beginning of allocated data
4224                                     //              to have a context when component returns with a callback (i.e. to know
4225                                     //              what to free etc.
4226                                     (OMX_U32)aActualBufferSize,     // buffer size
4227                                     pB);                        // buffer data ptr
4228 
4229                 out_buff_hdr_ptr[ii] = temp->pBufHdr;
4230 
4231 
4232             }
4233 
4234 
4235         }
4236         else
4237         {
4238             // the component must allocate its own buffers.
4239             if (aIsThisInputBuffer)
4240             {
4241 
4242                 InputBufCtrlStruct *temp = (InputBufCtrlStruct *) ctrl_struct_ptr[ii];
4243                 // initialize the media data field to 0 //TODO cleanup work started in another record. JJ 05/12/09
4244                 oscl_memset(&(temp->pMediaData), 0, sizeof(PVMFSharedMediaDataPtr));
4245                 temp->pMediaData = PVMFSharedMediaDataPtr(NULL, NULL);
4246 
4247                 err = OMX_AllocateBuffer(iOMXEncoder,
4248                                          &(temp->pBufHdr),
4249                                          aPortIndex,
4250                                          ctrl_struct_ptr[ii],
4251                                          (OMX_U32)aActualBufferSize);
4252 
4253                 in_buff_hdr_ptr[ii] = temp->pBufHdr;
4254             }
4255             else
4256             {
4257                 OutputBufCtrlStruct *temp = (OutputBufCtrlStruct *) ctrl_struct_ptr[ii];
4258                 err = OMX_AllocateBuffer(iOMXEncoder,
4259                                          &(temp->pBufHdr),
4260                                          aPortIndex,
4261                                          ctrl_struct_ptr[ii],
4262                                          (OMX_U32)aActualBufferSize);
4263 
4264                 out_buff_hdr_ptr[ii] = temp->pBufHdr;
4265             }
4266 
4267         }
4268 
4269         if (err != OMX_ErrorNone)
4270         {
4271             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
4272                             (0, "PVMFOMXEncNode-%s::ProvideBuffersToComponent() Problem using/allocating a buffer", iNodeTypeId));
4273 
4274 
4275             return false;
4276         }
4277 
4278     }
4279 
4280     for (ii = 0; ii < aNumBuffers; ii++)
4281     {
4282         // after initializing the buffer hdr ptrs, return them
4283         // to the mempool
4284         aMemPool->deallocate((OsclAny*) ctrl_struct_ptr[ii]);
4285     }
4286 
4287     // set the flags
4288     if (aIsThisInputBuffer)
4289     {
4290         iInputBuffersFreed = false;
4291     }
4292     else
4293     {
4294         iOutputBuffersFreed = false;
4295     }
4296 
4297     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::ProvideBuffersToComponent() done", iNodeTypeId));
4298     return true;
4299 }
4300 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
4301 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
FreeBuffersFromComponent(OsclMemPoolFixedChunkAllocator * aMemPool,uint32 aAllocSize,uint32 aNumBuffers,uint32 aPortIndex,bool aIsThisInputBuffer)4302 bool PVMFOMXEncNode::FreeBuffersFromComponent(OsclMemPoolFixedChunkAllocator *aMemPool, // allocator
4303         uint32 aAllocSize,     // size to allocate from pool (hdr only or hdr+ buffer)
4304         uint32 aNumBuffers,    // number of buffers
4305         uint32 aPortIndex,      // port idx
4306         bool  aIsThisInputBuffer      // is this input or output
4307                                              )
4308 {
4309     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::FreeBuffersToComponent() enter", iNodeTypeId));
4310 
4311     uint32 ii = 0;
4312     OMX_ERRORTYPE err = OMX_ErrorNone;
4313     OsclAny **ctrl_struct_ptr = aIsThisInputBuffer ? in_ctrl_struct_ptr : out_ctrl_struct_ptr;
4314 
4315     // Now, go through all buffers and tell component to free them
4316     for (ii = 0; ii < aNumBuffers; ii++)
4317     {
4318 
4319         int32 errcode = 0;
4320         // get the address where the buf hdr ptr will be stored
4321 
4322         errcode = MemAllocate(ctrl_struct_ptr[ii], aMemPool, aAllocSize);
4323         if ((errcode != OsclErrNone) || (ctrl_struct_ptr[ii] == NULL))
4324         {
4325             if (errcode == OsclErrNoResources)
4326             {
4327                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4328                                 (0, "PVMFOMXEncNode-%s::FreeBuffersFromComponent ->allocate() failed for no mempool chunk available", iNodeTypeId));
4329             }
4330             else
4331             {
4332                 // General error
4333                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
4334                                 (0, "PVMFOMXEncNode-%s::FreeBuffersFromComponent ->allocate() failed due to some general error", iNodeTypeId));
4335 
4336                 ReportErrorEvent(PVMFFailure);
4337                 ChangeNodeState(EPVMFNodeError);
4338             }
4339 
4340             return false;
4341         }
4342         // to maintain correct count
4343         aMemPool->notifyfreechunkavailable((*this), (OsclAny*) aMemPool);
4344 
4345         if (aIsThisInputBuffer)
4346         {
4347 
4348             iNumOutstandingInputBuffers++;
4349             // get the buf hdr pointer
4350             InputBufCtrlStruct *temp = (InputBufCtrlStruct *) ctrl_struct_ptr[ii];
4351             err = OMX_FreeBuffer(iOMXEncoder,
4352                                  aPortIndex,
4353                                  temp->pBufHdr);
4354 
4355         }
4356         else
4357         {
4358             iNumOutstandingOutputBuffers++;
4359             OutputBufCtrlStruct *temp = (OutputBufCtrlStruct *) ctrl_struct_ptr[ii];
4360             err = OMX_FreeBuffer(iOMXEncoder,
4361                                  aPortIndex,
4362                                  temp->pBufHdr);
4363 
4364         }
4365 
4366         if (err != OMX_ErrorNone)
4367         {
4368             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
4369                             (0, "PVMFOMXEncNode-%s::FreeBuffersFromComponent() Problem freeing a buffer", iNodeTypeId));
4370 
4371             return false;
4372         }
4373 
4374     }
4375 
4376     for (ii = 0; ii < aNumBuffers; ii++)
4377     {
4378         // after freeing the buffer hdr ptrs, return them
4379         // to the mempool (which will itself then be deleted promptly)
4380         aMemPool->deallocate((OsclAny*) ctrl_struct_ptr[ii]);
4381     }
4382 
4383 
4384     // mark buffers as freed (so as not to do it twice)
4385     if (aIsThisInputBuffer)
4386     {
4387         oscl_free(in_ctrl_struct_ptr);
4388         oscl_free(in_buff_hdr_ptr);
4389 
4390         in_ctrl_struct_ptr = NULL;
4391         in_buff_hdr_ptr = NULL;
4392         iInputBuffersFreed = true;
4393     }
4394     else
4395     {
4396         oscl_free(out_ctrl_struct_ptr);
4397         oscl_free(out_buff_hdr_ptr);
4398 
4399         out_ctrl_struct_ptr = NULL;
4400         out_buff_hdr_ptr = NULL;
4401 
4402         iOutputBuffersFreed = true;
4403     }
4404     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::FreeBuffersFromComponent() done", iNodeTypeId));
4405     return true;
4406 }
4407 
4408 
4409 
4410 /////////////////////////////////////////////////////////////////////////////
4411 ////////////////////// CALLBACK PROCESSING FOR EVENT HANDLER
4412 /////////////////////////////////////////////////////////////////////////////
EventHandlerProcessing(OMX_OUT OMX_HANDLETYPE aComponent,OMX_OUT OMX_PTR aAppData,OMX_OUT OMX_EVENTTYPE aEvent,OMX_OUT OMX_U32 aData1,OMX_OUT OMX_U32 aData2,OMX_OUT OMX_PTR aEventData)4413 OMX_ERRORTYPE PVMFOMXEncNode::EventHandlerProcessing(OMX_OUT OMX_HANDLETYPE aComponent,
4414         OMX_OUT OMX_PTR aAppData,
4415         OMX_OUT OMX_EVENTTYPE aEvent,
4416         OMX_OUT OMX_U32 aData1,
4417         OMX_OUT OMX_U32 aData2,
4418         OMX_OUT OMX_PTR aEventData)
4419 {
4420     OSCL_UNUSED_ARG(aComponent);
4421     OSCL_UNUSED_ARG(aAppData);
4422     OSCL_UNUSED_ARG(aEventData);
4423 
4424     switch (aEvent)
4425     {
4426         case OMX_EventCmdComplete:
4427         {
4428 
4429             switch (aData1)
4430             {
4431                 case OMX_CommandStateSet:
4432                 {
4433                     HandleComponentStateChange(aData2);
4434                     break;
4435                 }
4436                 case OMX_CommandFlush:            //not supported
4437                     // nothing to do here yet
4438                     break;
4439 
4440                 case OMX_CommandPortDisable:
4441                 {
4442                     // if port disable command is done, we can re-allocate the buffers and re-enable the port
4443 
4444                     iProcessingState = EPVMFOMXEncNodeProcessingState_PortReEnable;
4445                     iPortIndexForDynamicReconfig =  aData2;
4446 
4447                     RunIfNotReady();
4448                     break;
4449                 }
4450                 case OMX_CommandPortEnable:
4451                     // port enable command is done. Check if the other port also reported change.
4452                     // If not, we can start data flow. Otherwise, must start dynamic reconfig procedure for
4453                     // the other port as well.
4454                 {
4455                     if (iSecondPortReportedChange)
4456                     {
4457                         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
4458                                         (0, "PVMFOMXEncNode-%s::EventHandlerProcessing: OMX_CommandPortEnable - completed on port %d, dynamic reconfiguration needed on port %d", iNodeTypeId, aData2, iSecondPortToReconfig));
4459 
4460                         iProcessingState = EPVMFOMXEncNodeProcessingState_PortReconfig;
4461                         iPortIndexForDynamicReconfig = iSecondPortToReconfig;
4462                         iSecondPortReportedChange = false;
4463                     }
4464                     else
4465                     {
4466                         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
4467                                         (0, "PVMFOMXEncNode-%s::EventHandlerProcessing: OMX_CommandPortEnable - completed on port %d, resuming normal data flow", iNodeTypeId, aData2));
4468                         iProcessingState = EPVMFOMXEncNodeProcessingState_ReadyToEncode;
4469                         iDynamicReconfigInProgress = false;
4470                     }
4471                     RunIfNotReady();
4472                     break;
4473                 }
4474 
4475                 case OMX_CommandMarkBuffer:
4476                     // nothing to do here yet;
4477                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
4478                                     (0, "PVMFOMXEncNode-%s::EventHandlerProcessing: OMX_CommandMarkBuffer - completed - no action taken", iNodeTypeId));
4479 
4480                     break;
4481 
4482                 default:
4483                 {
4484                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
4485                                     (0, "PVMFOMXEncNode-%s::EventHandlerProcessing: Unsupported event", iNodeTypeId));
4486                     break;
4487                 }
4488             }//end of switch (aData1)
4489 
4490             break;
4491         }//end of case OMX_EventCmdComplete
4492 
4493         case OMX_EventError:
4494         {
4495 
4496             if (aData1 == (OMX_U32) OMX_ErrorStreamCorrupt)
4497             {
4498                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
4499                                 (0, "PVMFOMXEncNode-%s::EventHandlerProcessing: OMX_EventError - Bitstream corrupt error", iNodeTypeId));
4500                 // Errors from corrupt bitstream are reported as info events
4501                 ReportInfoEvent(PVMFInfoProcessingFailure, NULL);
4502 
4503             }
4504             else
4505             {
4506 
4507                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
4508                                 (0, "PVMFOMXEncNode-%s::EventHandlerProcessing: OMX_EventError", iNodeTypeId));
4509                 // for now, any error from the component will be reported as error
4510                 ReportErrorEvent(PVMFErrProcessing, NULL, NULL);
4511                 SetState(EPVMFNodeError);
4512             }
4513             break;
4514 
4515         }
4516 
4517         case OMX_EventBufferFlag:
4518         {
4519             // the component is reporting it encountered end of stream flag
4520             // we'll send eos when we get the actual last buffer with marked eos
4521 
4522             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4523                             (0, "PVMFOMXEncNode-%s::EventHandlerProcessing: OMX_EventBufferFlag (EOS) flag returned from OMX component", iNodeTypeId));
4524 
4525             RunIfNotReady();
4526             break;
4527         }//end of case OMX_EventBufferFlag
4528 
4529         case OMX_EventMark:
4530         {
4531 
4532             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4533                             (0, "PVMFOMXEncNode-%s::EventHandlerProcessing: OMX_EventMark returned from OMX component - no action taken", iNodeTypeId));
4534 
4535             RunIfNotReady();
4536             break;
4537         }//end of case OMX_EventMark
4538 
4539         case OMX_EventPortSettingsChanged:
4540         {
4541 
4542             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4543                             (0, "PVMFOMXEncNode-%s::EventHandlerProcessing: OMX_EventPortSettingsChanged returned from OMX component", iNodeTypeId));
4544 
4545             // first check if dynamic reconfiguration is already in progress,
4546             // if so, wait until this is completed, and then initiate the 2nd reconfiguration
4547             if (iDynamicReconfigInProgress)
4548             {
4549                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4550                                 (0, "PVMFOMXEncNode-%s::EventHandlerProcessing: OMX_EventPortSettingsChanged returned for port %d, dynamic reconfig already in progress", iNodeTypeId, aData1));
4551 
4552                 iSecondPortToReconfig = aData1;
4553                 iSecondPortReportedChange = true;
4554             }
4555             else
4556             {
4557                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4558                                 (0, "PVMFOMXEncNode-%s::EventHandlerProcessing: OMX_EventPortSettingsChanged returned for port %d", iNodeTypeId, aData1));
4559 
4560                 iProcessingState = EPVMFOMXEncNodeProcessingState_PortReconfig;
4561                 iPortIndexForDynamicReconfig = aData1;
4562                 iDynamicReconfigInProgress = true;
4563             }
4564 
4565             RunIfNotReady();
4566             break;
4567         }//end of case OMX_PortSettingsChanged
4568 
4569         case OMX_EventResourcesAcquired:        //not supported
4570         {
4571             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4572                             (0, "PVMFOMXEncNode-%s::EventHandlerProcessing: OMX_EventResourcesAcquired returned from OMX component - no action taken", iNodeTypeId));
4573 
4574             RunIfNotReady();
4575 
4576             break;
4577         }
4578 
4579         default:
4580         {
4581             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4582                             (0, "PVMFOMXEncNode-%s::EventHandlerProcessing:  Unknown Event returned from OMX component - no action taken", iNodeTypeId));
4583 
4584             break;
4585         }
4586 
4587     }//end of switch (eEvent)
4588 
4589 
4590 
4591     return OMX_ErrorNone;
4592 }
4593 
4594 
4595 
4596 
4597 /////////////////////////////////////////////////////////////////////////////
4598 // This function handles the event of OMX component state change
4599 /////////////////////////////////////////////////////////////////////////////
HandleComponentStateChange(OMX_U32 encoder_state)4600 void PVMFOMXEncNode::HandleComponentStateChange(OMX_U32 encoder_state)
4601 {
4602     switch (encoder_state)
4603     {
4604         case OMX_StateIdle:
4605         {
4606             iCurrentEncoderState = OMX_StateIdle;
4607 
4608             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4609                             (0, "PVMFOMXEncNode-%s::HandleComponentStateChange: OMX_StateIdle reached", iNodeTypeId));
4610 
4611             //  this state can be reached either going from OMX_Loaded->OMX_Idle (preparing)
4612             //  or going from OMX_Executing->OMX_Idle (stopping)
4613 
4614 
4615             if ((iCurrentCommand.size() > 0) &&
4616                     (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_PREPARE))
4617             {
4618                 iProcessingState = EPVMFOMXEncNodeProcessingState_ReadyToEncode;
4619                 SetState(EPVMFNodePrepared);
4620                 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess);
4621                 RunIfNotReady();
4622             }
4623             else if ((iCurrentCommand.size() > 0) &&
4624                      (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_STOP))
4625             {
4626                 // if we are stopped, we won't start until the node gets DoStart command.
4627                 //  in this case, we are ready to start sending buffers
4628                 if (iProcessingState == EPVMFOMXEncNodeProcessingState_Stopping)
4629                     iProcessingState = EPVMFOMXEncNodeProcessingState_ReadyToEncode;
4630                 // if the processing state was not stopping, leave the state as it was (continue port reconfiguration)
4631                 SetState(EPVMFNodePrepared);
4632                 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess);
4633 
4634                 RunIfNotReady();
4635             }
4636             else if ((iCurrentCommand.size() > 0) &&
4637                      (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_FLUSH))
4638             {
4639                 // if there is a flush, similar to the case of stop, we won't start until the node gets
4640                 // DoStart command. In this case, we'll be ready
4641                 if (iProcessingState == EPVMFOMXEncNodeProcessingState_Stopping)
4642                     iProcessingState = EPVMFOMXEncNodeProcessingState_ReadyToEncode;
4643 
4644 
4645 
4646                 //Flush is complete.  Go to prepared state.
4647                 SetState(EPVMFNodePrepared);
4648                 //resume port input (if possible) so the ports can be re-started.
4649                 if (iInPort)
4650                 {
4651                     iInPort->ResumeInput();
4652                 }
4653                 if (iOutPort)
4654                 {
4655                     iOutPort->ResumeInput();
4656                 }
4657                 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess);
4658                 RunIfNotReady();
4659 
4660             }
4661             else if ((iCurrentCommand.size() > 0) &&
4662                      (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_RESET))
4663             {
4664                 // State change to Idle was initiated due to Reset. First need to reach idle, and then loaded
4665                 // Once Idle is reached, we need to initiate idle->loaded transition
4666                 iStopInResetMsgSent = false;
4667                 RunIfNotReady();
4668             }
4669             break;
4670         }//end of case OMX_StateIdle
4671 
4672         case OMX_StateExecuting:
4673         {
4674             iCurrentEncoderState = OMX_StateExecuting;
4675 
4676             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4677                             (0, "PVMFOMXEncNode-%s::HandleComponentStateChange: OMX_StateExecuting reached", iNodeTypeId));
4678 
4679             // this state can be reached going from OMX_Idle -> OMX_Executing (preparing)
4680             //  or going from OMX_Pause -> OMX_Executing (coming from pause)
4681             //  either way, this is a response to "DoStart" command
4682 
4683             if ((iCurrentCommand.size() > 0) &&
4684                     (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_START))
4685             {
4686                 SetState(EPVMFNodeStarted);
4687                 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess);
4688 
4689                 RunIfNotReady();
4690             }
4691 
4692             break;
4693         }//end of case OMX_StateExecuting
4694 
4695         case OMX_StatePause:
4696         {
4697             iCurrentEncoderState = OMX_StatePause;
4698 
4699             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4700                             (0, "PVMFOMXEncNode-%s::HandleComponentStateChange: OMX_StatePause reached", iNodeTypeId));
4701 
4702 
4703             //  This state can be reached going from OMX_Executing-> OMX_Pause
4704             if ((iCurrentCommand.size() > 0) &&
4705                     (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_PAUSE))
4706             {
4707                 SetState(EPVMFNodePaused);
4708                 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess);
4709                 RunIfNotReady();
4710             }
4711 
4712             break;
4713         }//end of case OMX_StatePause
4714 
4715         case OMX_StateLoaded:
4716         {
4717             iCurrentEncoderState = OMX_StateLoaded;
4718 
4719             //  this state can be reached only going from OMX_Idle ->OMX_Loaded (stopped to reset)
4720             //
4721 
4722             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4723                             (0, "PVMFOMXEncNode-%s::HandleComponentStateChange: OMX_StateLoaded reached", iNodeTypeId));
4724             //Check if command's responce is pending
4725             if ((iCurrentCommand.size() > 0) &&
4726                     (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_RESET))
4727             {
4728 
4729                 // move this here
4730                 if (iInPort)
4731                 {
4732                     OSCL_DELETE(((PVMFOMXEncPort*)iInPort));
4733                     iInPort = NULL;
4734                 }
4735 
4736                 if (iOutPort)
4737                 {
4738                     OSCL_DELETE(((PVMFOMXEncPort*)iOutPort));
4739                     iOutPort = NULL;
4740                 }
4741 
4742                 iDataIn.Unbind();
4743 
4744                 // Reset the metadata key list
4745                 iAvailableMetadataKeys.clear();
4746 
4747 
4748                 iProcessingState = EPVMFOMXEncNodeProcessingState_Idle;
4749                 //logoff & go back to Created state.
4750                 SetState(EPVMFNodeIdle);
4751                 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess);
4752                 iResetInProgress = false;
4753                 iResetMsgSent = false;
4754             }
4755 
4756             break;
4757         }//end of case OMX_StateLoaded
4758 
4759         case OMX_StateInvalid:
4760         default:
4761         {
4762             iCurrentEncoderState = OMX_StateInvalid;
4763 
4764             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
4765                             (0, "PVMFOMXEncNode-%s::HandleComponentStateChange: OMX_StateInvalid reached", iNodeTypeId));
4766 
4767             break;
4768         }//end of case OMX_StateInvalid
4769 
4770     }//end of switch(encoder_state)
4771 
4772 }
4773 
4774 
4775 
4776 
4777 
4778 
4779 /////////////////////////////////////////////////////////////////////////////
4780 ////////////////////// CALLBACK PROCESSING FOR EMPTY BUFFER DONE - input buffer was consumed
4781 /////////////////////////////////////////////////////////////////////////////
EmptyBufferDoneProcessing(OMX_OUT OMX_HANDLETYPE aComponent,OMX_OUT OMX_PTR aAppData,OMX_OUT OMX_BUFFERHEADERTYPE * aBuffer)4782 OMX_ERRORTYPE PVMFOMXEncNode::EmptyBufferDoneProcessing(OMX_OUT OMX_HANDLETYPE aComponent,
4783         OMX_OUT OMX_PTR aAppData,
4784         OMX_OUT OMX_BUFFERHEADERTYPE* aBuffer)
4785 {
4786 
4787     OSCL_UNUSED_ARG(aComponent);
4788     OSCL_UNUSED_ARG(aAppData);
4789     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4790                     (0, "PVMFOMXEncNode-%s::EmptyBufferDoneProcessing: In", iNodeTypeId));
4791 
4792     OSCL_ASSERT((void*) aComponent == (void*) iOMXEncoder); // component should match the component
4793     OSCL_ASSERT(aAppData == (OMX_PTR)(this));       // AppData should represent this node ptr
4794 
4795     // first, get the buffer "context", i.e. pointer to application private data that contains the
4796     // address of the mempool buffer (so that it can be released)
4797     InputBufCtrlStruct *pContext = (InputBufCtrlStruct *)(aBuffer->pAppPrivate);
4798 
4799 
4800 
4801     // if a buffer is not empty, log a msg, but release anyway
4802     if ((aBuffer->nFilledLen > 0) && (iDoNotSaveInputBuffersFlag == false))
4803         // if dynamic port reconfig is in progress for input port, don't keep the buffer
4804     {
4805 
4806         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4807                         (0, "PVMFOMXEncNode-%s::EmptyBufferDoneProcessing: Input buffer returned non-empty with %d bytes still in it", iNodeTypeId, aBuffer->nFilledLen));
4808 
4809 
4810     }
4811 
4812     iInputBufferToResendToComponent = NULL;
4813 
4814 
4815     // input buffer is to be released,
4816     // refcount needs to be decremented (possibly - the input msg associated with the buffer will be unbound)
4817     // NOTE: in case of "moveable" input buffers (passed into component without copying), unbinding decrements a refcount which eventually results
4818     //          in input message being released back to upstream mempool once all its fragments are returned
4819     //      in case of input buffers passed into component by copying, unbinding has no effect
4820     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4821                     (0, "PVMFOMXEncNode-%s::EmptyBufferDoneProcessing: Release input buffer (with %d refcount remaining of input message)", iNodeTypeId, (pContext->pMediaData).get_count() - 1));
4822 
4823 
4824     (pContext->pMediaData).Unbind();
4825 
4826 
4827     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4828                     (0, "PVMFOMXEncNode-%s::EmptyBufferDoneProcessing: Release input buffer %x back to mempool", iNodeTypeId, pContext));
4829 
4830     iInBufMemoryPool->deallocate((OsclAny *) pContext);
4831 
4832 
4833     // the OMX spec says that no error is to be returned
4834     return OMX_ErrorNone;
4835 
4836 }
4837 
4838 
4839 
4840 /////////////////////////////////////////////////////////////////////////////
4841 ////////////////////// CALLBACK PROCESSING FOR FILL BUFFER DONE - output buffer is ready
4842 /////////////////////////////////////////////////////////////////////////////
FillBufferDoneProcessing(OMX_OUT OMX_HANDLETYPE aComponent,OMX_OUT OMX_PTR aAppData,OMX_OUT OMX_BUFFERHEADERTYPE * aBuffer)4843 OMX_ERRORTYPE PVMFOMXEncNode::FillBufferDoneProcessing(OMX_OUT OMX_HANDLETYPE aComponent,
4844         OMX_OUT OMX_PTR aAppData,
4845         OMX_OUT OMX_BUFFERHEADERTYPE* aBuffer)
4846 {
4847 
4848     OSCL_UNUSED_ARG(aComponent);
4849     OSCL_UNUSED_ARG(aAppData);
4850     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4851                     (0, "PVMFOMXEncNode-%s::FillBufferDoneProcessing: In", iNodeTypeId));
4852 
4853     OSCL_ASSERT((void*) aComponent == (void*) iOMXEncoder); // component should match the component
4854     OSCL_ASSERT(aAppData == (OMX_PTR)(this));       // AppData should represent this node ptr
4855 
4856     // first, get the buffer "context", i.e. pointer to application private data that contains the
4857     // address of the mempool buffer (so that it can be released)
4858     OsclAny *pContext = (OsclAny*) aBuffer->pAppPrivate;
4859 
4860 
4861     // check for EOS flag
4862     if ((aBuffer->nFlags & OMX_BUFFERFLAG_EOS))
4863     {
4864         // EOS received - enable sending EOS msg
4865         iIsEOSReceivedFromComponent = true;
4866 
4867         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4868                         (0, "PVMFOMXEncNode-%s::FillBufferDoneProcessing: Output buffer has EOS set", iNodeTypeId));
4869 
4870     }
4871 
4872     if (((iOutFormat == PVMF_MIME_H264_VIDEO_MP4) || (iOutFormat == PVMF_MIME_H264_VIDEO_RAW))
4873             && (iOMXComponentUsesNALStartCodes))
4874     {
4875         // find size of first start code, since it can be either 3 or 4 bytes
4876         uint8* pData = (uint8*)aBuffer->pBuffer + aBuffer->nOffset;
4877         uint8* pTemp;
4878         uint32 size = aBuffer->nFilledLen;
4879         if (AVCAnnexBGetNALUnit(pData, &pTemp, (int32*)&size, true))
4880         {
4881             iFirstNALStartCodeSize = (uint32)pTemp - (uint32)pData;
4882         }
4883         else
4884         {
4885             iFirstNALStartCodeSize = 0;
4886         }
4887     }
4888 
4889     /* the case in which a buffer simply containing a start code is sent */
4890     if (aBuffer->nFilledLen <= iFirstNALStartCodeSize && iOMXComponentUsesNALStartCodes)
4891     {
4892         aBuffer->nFilledLen = 0;
4893     }
4894 
4895     // if a buffer is empty, or if it should not be sent downstream (say, due to state change)
4896     // release the buffer back to the pool
4897     if ((aBuffer->nFilledLen == 0) || (iDoNotSendOutputBuffersDownstreamFlag == true))
4898     {
4899         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4900                         (0, "PVMFOMXEncNode-%s::FillBufferDoneProcessing: Release output buffer %x back to mempool - buffer empty or not to be sent downstream", iNodeTypeId, pContext));
4901 
4902         iOutBufMemoryPool->deallocate(pContext);
4903 
4904     }
4905     else
4906     {
4907 
4908         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4909                         (0, "PVMFOMXEncNode-%s::FillBufferDoneProcessing: Output frame %d received", iNodeTypeId, iFrameCounter));
4910 
4911         iFrameCounter++;
4912         // get pointer to actual buffer data
4913         uint8 *pBufdata = ((uint8*) aBuffer->pBuffer);
4914         // move the data pointer based on offset info
4915         pBufdata += aBuffer->nOffset;
4916 
4917         uint32 bufLen = (uint32) aBuffer->nFilledLen;
4918 
4919         // in case of mp4 streaming and the very 1st buffer, save vol header separately
4920         if ((iOutFormat == PVMF_MIME_M4V) && (iFrameCounter == 1))
4921         {
4922 
4923             // save the first buffer since this is the VOL header
4924             uint refCounterSize = oscl_mem_aligned_size(sizeof(OsclRefCounterDA));
4925             OsclMemoryFragment volHeader;
4926 
4927             int vol_len = aBuffer->nFilledLen;
4928             bool frameInVolHdr = CheckM4vVopStartCode(pBufdata, &vol_len);
4929 
4930             volHeader.ptr = NULL;
4931             volHeader.len = vol_len;
4932             uint8* memBuffer = (uint8*)iAlloc.allocate(refCounterSize + volHeader.len);
4933             oscl_memset(memBuffer, 0, refCounterSize + volHeader.len);
4934             OsclRefCounter* refCounter = OSCL_PLACEMENT_NEW(memBuffer, OsclRefCounterDA(memBuffer, (OsclDestructDealloc*) & iAlloc));
4935             memBuffer += refCounterSize;
4936             volHeader.ptr = (OsclAny*)memBuffer;
4937 
4938             // copy the vol header from OMX buffer
4939             oscl_memcpy(volHeader.ptr, pBufdata, volHeader.len);
4940 
4941             // save in class variable
4942             iVolHeader = OsclRefCounterMemFrag(volHeader, refCounter, volHeader.len);
4943 
4944             if (frameInVolHdr == false)
4945             {
4946                 // release the OMX buffer
4947                 iOutBufMemoryPool->deallocate(pContext);
4948                 return OMX_ErrorNone;
4949             }
4950             else  // there is a frame in this buffer, update the pointer and continue to process it.
4951             {
4952                 pBufdata += vol_len;
4953                 bufLen -= vol_len;
4954             }
4955         }
4956 
4957         if (iFrameCounter == 1)
4958         {
4959             if ((iOutFormat == PVMF_MIME_ADTS)
4960                     || (iOutFormat == PVMF_MIME_ADIF)
4961                     || (iOutFormat == PVMF_MIME_MPEG4_AUDIO)
4962                     || (iOutFormat == PVMF_MIME_WMA)
4963                     || (iOutFormat == PVMF_MIME_WMV)
4964                )
4965             {
4966 
4967                 // save the first buffer since this is the config header and needs to be sent separately
4968                 uint refCounterSize = oscl_mem_aligned_size(sizeof(OsclRefCounterDA));
4969                 OsclMemoryFragment configHeader;
4970                 configHeader.ptr = NULL;
4971                 configHeader.len = aBuffer->nFilledLen;
4972                 uint8* memBuffer = (uint8*)iAlloc.allocate(refCounterSize + configHeader.len);
4973                 oscl_memset(memBuffer, 0, refCounterSize + configHeader.len);
4974                 OsclRefCounter* refCounter = OSCL_PLACEMENT_NEW(memBuffer, OsclRefCounterDA(memBuffer, (OsclDestructDealloc*) & iAlloc));
4975                 memBuffer += refCounterSize;
4976                 configHeader.ptr = (OsclAny*)memBuffer;
4977 
4978                 // copy the vol header from OMX buffer
4979                 oscl_memcpy(configHeader.ptr, pBufdata, configHeader.len);
4980 
4981                 // save in class variable
4982                 iConfigHeader = OsclRefCounterMemFrag(configHeader, refCounter, configHeader.len);
4983 
4984                 // release the OMX buffer
4985                 iOutBufMemoryPool->deallocate(pContext);
4986                 return OMX_ErrorNone;
4987             }
4988         }
4989 
4990         // in case of avc mp4, need to save sps/pps sequences
4991         if ((iOutFormat == PVMF_MIME_H264_VIDEO_MP4) && (!iSpsPpsSequenceOver))
4992         {
4993 
4994             if (iOMXComponentUsesNALStartCodes)
4995             {
4996                 // remove the start code from these single NAL frames
4997                 pBufdata += iFirstNALStartCodeSize;
4998                 bufLen -= iFirstNALStartCodeSize;
4999             }
5000             // detect nal type
5001             uint8 *bitstream = pBufdata;
5002             int nal_type;
5003 
5004             // adjust the pointers in the iParamSet memfragment
5005             uint8 *destptr = (uint8*) iParamSet.getMemFragPtr();
5006             uint32 length = iParamSet.getMemFrag().len;
5007             uint32 capacity = iParamSet.getCapacity();
5008 
5009             destptr += length;
5010 
5011 
5012             nal_type = bitstream[0] & 0x1F;
5013 
5014             if (nal_type == 0x07) // SPS type NAL
5015             {
5016                 // can the SPS fit into the buffer
5017                 if (aBuffer->nFilledLen <= (capacity - length))
5018                 {
5019                     iSPSs[iNumSPSs].ptr = destptr;
5020                     iSPSs[iNumSPSs++].len = aBuffer->nFilledLen;
5021 
5022                     oscl_memcpy(destptr, pBufdata, aBuffer->nFilledLen); // copy SPS into iParamSet memfragment
5023                     length += aBuffer->nFilledLen;
5024                     iParamSet.getMemFrag().len = length; // update length
5025                 }
5026 
5027 
5028                 // release the OMX buffer
5029                 iOutBufMemoryPool->deallocate(pContext);
5030                 return OMX_ErrorNone;
5031             }
5032             else if (nal_type == 0x08) // PPS type NAL
5033             {
5034 
5035                 // can the PPS fit into the buffer?
5036                 if (aBuffer->nFilledLen <= (capacity - length))
5037                 {
5038 
5039                     iPPSs[iNumPPSs].ptr = destptr;
5040                     iPPSs[iNumPPSs++].len = aBuffer->nFilledLen;
5041 
5042                     oscl_memcpy(destptr, pBufdata, aBuffer->nFilledLen); // copy PPS into iParamSet memfragment
5043                     length += aBuffer->nFilledLen;
5044                     iParamSet.getMemFrag().len = length; // update length
5045 
5046 
5047                 }
5048 
5049                 // release the OMX buffer
5050                 iOutBufMemoryPool->deallocate(pContext);
5051                 return OMX_ErrorNone;
5052             }
5053             else
5054             {
5055                 if (iOMXComponentUsesNALStartCodes)
5056                 {
5057                     // bring start code back since it's not a SPS or PPS
5058                     pBufdata -= iFirstNALStartCodeSize;
5059                     bufLen += iFirstNALStartCodeSize;
5060                 }
5061 
5062                 // this is neither SPS nor PPS
5063                 // stop recording SPS/PPS
5064                 iSpsPpsSequenceOver = true;
5065                 iFirstNAL = true; // set indicator of first NAL
5066                 // send out SPS/PPS recorded so far
5067                 if (((PVMFOMXEncPort*)iOutPort))
5068                 {
5069                     ((PVMFOMXEncPort*)iOutPort)->SendSPS_PPS(iSPSs, iNumSPSs, iPPSs, iNumPPSs);
5070                 }
5071             }
5072 
5073         }
5074 
5075         if (iOMXComponentUsesFullAVCFrames && iOutFormat == PVMF_MIME_H264_VIDEO_MP4)
5076         {
5077             // do not parse fo PVMF_MIME_H264_VIDEO_RAW, since this data is just written raw, and knowing
5078             // the NAL boundaries isn't necessary
5079 
5080             if (!ParseFullAVCFramesIntoNALs(aBuffer))
5081             {
5082                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
5083                                 (0, "PVMFOMXEncNode-%s::FillBufferDoneProcessing: Problem parsing NALs in buffer %x of size %d - releasing the buffer", iNodeTypeId, pBufdata, aBuffer->nFilledLen));
5084 
5085                 iOutBufMemoryPool->deallocate(pContext);
5086             }
5087         }
5088 
5089         // adjust ptr to data to expose the NAL sync word if necessary
5090         if ((iOutFormat == PVMF_MIME_H264_VIDEO_RAW) &&
5091                 (iOMXComponentSupportsExternalOutputBufferAlloc) &&
5092                 (!iOMXComponentUsesFullAVCFrames) &&
5093                 (!iOMXComponentUsesNALStartCodes) &&
5094                 ((iFirstNAL == true) || (iEndOfNALFlagPrevious != 0))
5095            )
5096         {
5097             pBufdata -= 4;
5098             bufLen += 4;
5099         }
5100 
5101         // otherwise, queue output buffer
5102         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
5103                         (0, "PVMFOMXEncNode-%s::FillBufferDoneProcessing: Wrapping buffer %x of size %d", iNodeTypeId, pBufdata, aBuffer->nFilledLen));
5104         // wrap the buffer into the MediaDataImpl wrapper, and queue it for sending downstream
5105         // wrapping will create a refcounter. When refcounter goes to 0 i.e. when media data
5106         // is released in downstream components, the custom deallocator will automatically release the buffer back to the
5107         //  mempool. To do that, the deallocator needs to have info about Context
5108         // NOTE: we had to wait until now to wrap the buffer data because we only know
5109         //          now where the actual data is located (based on buffer offset)
5110         OsclSharedPtr<PVMFMediaDataImpl> MediaDataCurr = WrapOutputBuffer(pBufdata, bufLen, pContext);
5111 
5112         // if you can't get the MediaDataCurr, release the buffer back to the pool
5113         if (MediaDataCurr.GetRep() == NULL)
5114         {
5115             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
5116                             (0, "PVMFOMXEncNode-%s::FillBufferDoneProcessing: Problem wrapping buffer %x of size %d - releasing the buffer", iNodeTypeId, pBufdata, aBuffer->nFilledLen));
5117 
5118             iOutBufMemoryPool->deallocate(pContext);
5119         }
5120         else
5121         {
5122             OsclSharedPtr<PVMFMediaDataImpl> MediaDataOut;
5123 
5124             //DV - NOTE:
5125             //In case of AVC, OMX_EndOfFrameFlag is used to mark the end of NAL
5126             //                End of frame is determined by comparing timestamps
5127             //              As a consequence, there is a lag of one buffer
5128             //              i.e. we send/queue the previous buffer and keep the current one so that
5129             //              When the next buffer arrives, we can compare timestamps etc.
5130 
5131             // In case of MP4, OMX_EndOFFrameFlag is used to mark end of frame and there is no lag
5132 
5133             if ((iOutFormat == PVMF_MIME_H264_VIDEO_MP4) || (iOutFormat == PVMF_MIME_H264_VIDEO_RAW))
5134             {
5135 
5136                 MediaDataOut = iPreviousMediaData; // send out previous media data
5137 
5138                 // copy data to be attached with outgoing media data from previous buffer
5139                 iTimeStampOut = iTimeStampPrevious;
5140                 iKeyFrameFlagOut = iKeyFrameFlagPrevious;
5141                 iEndOfNALFlagOut = iEndOfNALFlagPrevious;
5142                 // figure out if we need to set end of frame based on TS
5143                 if (aBuffer->nTimeStamp != iTimeStampPrevious)
5144                     iEndOfFrameFlagOut = 1;
5145                 else
5146                     iEndOfFrameFlagOut = 0;
5147                 iBufferLenOut = iBufferLenPrevious;
5148 
5149                 // now read the info for the current data
5150                 iPreviousMediaData = MediaDataCurr;
5151                 // record timestamp, flags etc.
5152                 iTimeStampPrevious = aBuffer->nTimeStamp;
5153                 // check for Key Frame
5154                 iKeyFrameFlagPrevious = (aBuffer->nFlags & OMX_BUFFERFLAG_SYNCFRAME);
5155                 // for avc, ENDOFFRAMEFLAG is used to delimit NALs
5156                 iEndOfNALFlagPrevious = (aBuffer->nFlags & OMX_BUFFERFLAG_ENDOFFRAME);
5157                 iBufferLenPrevious = bufLen;
5158 
5159 
5160             }
5161             else // MP4 case
5162             {
5163 
5164                 MediaDataOut = MediaDataCurr;
5165                 // record timestamp, flags etc.
5166                 iTimeStampOut = aBuffer->nTimeStamp;
5167                 if (bIsQCOMOmxComp)
5168                 {
5169                     iTimeStampOut /= 1000;
5170                 }
5171 
5172                 // check for Key Frame
5173                 iKeyFrameFlagOut = (aBuffer->nFlags & OMX_BUFFERFLAG_SYNCFRAME);
5174                 iEndOfNALFlagOut = 0; // set this to 0 for mp4
5175                 //check for END OF FRAME FLAG
5176                 iEndOfFrameFlagOut = (aBuffer->nFlags & OMX_BUFFERFLAG_ENDOFFRAME);
5177                 iBufferLenOut = aBuffer->nFilledLen;
5178 
5179 
5180             }
5181             // if there's a problem queuing output buffer, MediaDataCurr will expire at end of scope and
5182             // release buffer back to the pool, (this should not be the case)
5183 
5184             // queue only if not the first NAL
5185             if (!iFirstNAL)
5186             {
5187                 if (QueueOutputBuffer(MediaDataOut, iBufferLenOut))
5188                 {
5189                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
5190                                     (0, "PVMFOMXEncNode-%s::FillBufferDoneProcessing: Buffer %x of size %d queued - reschedule the node to send out", iNodeTypeId, pBufdata, aBuffer->nFilledLen));
5191 
5192                     // if queing went OK,
5193                     // re-schedule the node so that outgoing queue can be emptied (unless the outgoing port is busy)
5194                     if ((iOutPort) && !(iOutPort->IsConnectedPortBusy()))
5195                         RunIfNotReady();
5196                 }
5197                 else
5198                 {
5199                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
5200                                     (0, "PVMFOMXEncNode-%s::FillBufferDoneProcessing: Problem queing buffer %x of size %d - releasing the buffer", iNodeTypeId, pBufdata, aBuffer->nFilledLen));
5201                 }
5202             }
5203             else
5204             {
5205                 iFirstNAL = false;
5206             }
5207 
5208             // if EOS and AVC (with a lag), queue also the last buffer
5209             if ((aBuffer->nFlags & OMX_BUFFERFLAG_EOS) &&
5210                     ((iOutFormat == PVMF_MIME_H264_VIDEO_MP4) || (iOutFormat == PVMF_MIME_H264_VIDEO_RAW))
5211                )
5212             {
5213 
5214                 MediaDataOut = iPreviousMediaData; // send out previous media data
5215 
5216                 // copy data to be attached with outgoing media data from previous buffer
5217                 iTimeStampOut = iTimeStampPrevious;
5218                 iKeyFrameFlagOut = iKeyFrameFlagPrevious;
5219                 iEndOfNALFlagOut =   1;
5220                 iEndOfFrameFlagOut = 1;
5221 
5222                 iBufferLenOut = iBufferLenPrevious;
5223 
5224                 if (QueueOutputBuffer(MediaDataOut, iBufferLenOut))
5225                 {
5226                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
5227                                     (0, "PVMFOMXEncNode-%s::FillBufferDoneProcessing: Buffer %x of size %d queued - reschedule the node to send out", iNodeTypeId, pBufdata, aBuffer->nFilledLen));
5228 
5229                     // if queing went OK,
5230                     // re-schedule the node so that outgoing queue can be emptied (unless the outgoing port is busy)
5231                     if ((iOutPort) && !(iOutPort->IsConnectedPortBusy()))
5232                         RunIfNotReady();
5233                 }
5234                 else
5235                 {
5236                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
5237                                     (0, "PVMFOMXEncNode-%s::FillBufferDoneProcessing: Problem queing buffer %x of size %d - releasing the buffer", iNodeTypeId, pBufdata, aBuffer->nFilledLen));
5238                 }
5239 
5240             }
5241         }
5242 
5243     }
5244     // the OMX spec says that no error is to be returned
5245     return OMX_ErrorNone;
5246 
5247 }
5248 ////////////////////////////////////////////////////////////////////////////////////////////////
5249 ///////////////////////////// Put output buffer in outgoing queue //////////////////////////////
5250 ////////////////////////////////////////////////////////////////////////////////////////////////
QueueOutputBuffer(OsclSharedPtr<PVMFMediaDataImpl> & mediadataimplout,uint32 aDataLen)5251 bool PVMFOMXEncNode::QueueOutputBuffer(OsclSharedPtr<PVMFMediaDataImpl> &mediadataimplout, uint32 aDataLen)
5252 {
5253 
5254     bool status = true;
5255     PVMFSharedMediaDataPtr mediaDataOut;
5256     int32 leavecode = 0;
5257 
5258     // NOTE: ASSUMPTION IS THAT OUTGOING QUEUE IS BIG ENOUGH TO QUEUE ALL THE OUTPUT BUFFERS
5259     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
5260                     (0, "PVMFOMXEncNode-%s::QueueOutputFrame: In", iNodeTypeId));
5261 
5262     // Check if the port is still connected
5263     if (iOutPort == NULL)
5264     {
5265         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
5266                         (0, "PVMFOMXEncNode-%s::QueueOutputFrame() OutgoingQueue Out Port is disconnected"));
5267         return false;
5268     }
5269 
5270     // First check if we can put outgoing msg. into the queue
5271     if (iOutPort->IsOutgoingQueueBusy())
5272     {
5273         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
5274                         (0, "PVMFOMXEncNode-%s::QueueOutputFrame() OutgoingQueue is busy", iNodeTypeId));
5275         return false;
5276     }
5277 
5278     OSCL_TRY(leavecode,
5279              mediaDataOut = PVMFMediaData::createMediaData(mediadataimplout, iMediaDataMemPool););
5280     if (leavecode == 0)
5281     {
5282 
5283         uint32 marker_bits = mediaDataOut->getMarkerInfo();
5284 
5285         if (iEndOfFrameFlagOut != 0)
5286         {
5287             marker_bits |= PVMF_MEDIA_DATA_MARKER_INFO_M_BIT;
5288         }
5289 
5290         if (iKeyFrameFlagOut != 0)
5291         {
5292             marker_bits |= PVMF_MEDIA_DATA_MARKER_INFO_RANDOM_ACCESS_POINT_BIT;
5293         }
5294 
5295         if (iEndOfNALFlagOut != 0)
5296         {
5297             marker_bits |= PVMF_MEDIA_DATA_MARKER_INFO_END_OF_NAL_BIT;
5298         }
5299 
5300         // attach marker bit
5301         mediaDataOut->setMarkerInfo(marker_bits);
5302 
5303 
5304         // Update the filled length of the fragment
5305         mediaDataOut->setMediaFragFilledLen(0, aDataLen);
5306 
5307         // Set timestamp
5308         mediaDataOut->setTimestamp(iTimeStampOut);
5309 
5310         // Set Streamid
5311         mediaDataOut->setStreamID(iStreamID);
5312 
5313         // Set sequence number
5314         mediaDataOut->setSeqNum(iSeqNum++);
5315 
5316         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iDataPathLogger, PVLOGMSG_INFO, (0, ":PVMFOMXEncNode-%s::QueueOutputFrame(): - SeqNum=%d, TS=%d", iNodeTypeId, iSeqNum, iTimeStampOut));
5317 
5318 
5319         // Check if Fsi needs to be sent (VOL header)
5320         if (sendYuvFsi)
5321         {
5322             if (iOutFormat == PVMF_MIME_M4V)
5323             {
5324                 mediaDataOut->setFormatSpecificInfo(iVolHeader);
5325 
5326             }
5327             else if ((iOutFormat == PVMF_MIME_ADTS)
5328                      || (iOutFormat == PVMF_MIME_ADIF)
5329                      || (iOutFormat == PVMF_MIME_MPEG4_AUDIO)
5330                      || (iOutFormat == PVMF_MIME_WMA)
5331                      || (iOutFormat == PVMF_MIME_WMV))
5332             {
5333 
5334                 mediaDataOut->setFormatSpecificInfo(iConfigHeader);
5335 
5336             }
5337 
5338             sendYuvFsi = false;
5339         }
5340 
5341         // Send frame to downstream node
5342         PVMFSharedMediaMsgPtr mediaMsgOut;
5343         convertToPVMFMediaMsg(mediaMsgOut, mediaDataOut);
5344 
5345         if (iOutPort && (iOutPort->QueueOutgoingMsg(mediaMsgOut) == PVMFSuccess))
5346         {
5347             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO,
5348                             (0, "PVMFOMXEncNode-%s::QueueOutputFrame(): Queued frame OK ", iNodeTypeId));
5349 
5350         }
5351         else
5352         {
5353             // we should not get here because we always check for whether queue is busy or not
5354             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
5355                             (0, "PVMFOMXEncNode-%s::QueueOutputFrame(): Send frame failed", iNodeTypeId));
5356             return false;
5357         }
5358 
5359 
5360 
5361 
5362     }//end of if (leavecode==0)
5363     else
5364     {
5365         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
5366                         (0, "PVMFOMXEncNode-%s::QueueOutputFrame() call PVMFMediaData::createMediaData is failed", iNodeTypeId));
5367         return false;
5368     }
5369 
5370     return status;
5371 
5372 }
5373 
5374 //////////////////////////////////////////////////////////////////////////////////////////////
5375 ///////////////////////////// Attach a MediaDataImpl wrapper (refcount, deallocator etc.)
5376 /////////////////////////////// to the output buffer /////////////////////////////////////////
WrapOutputBuffer(uint8 * pData,uint32 aDataLen,OsclAny * pContext)5377 OsclSharedPtr<PVMFMediaDataImpl> PVMFOMXEncNode::WrapOutputBuffer(uint8 *pData, uint32 aDataLen, OsclAny *pContext)
5378 {
5379     // wrap output buffer into a mediadataimpl
5380     uint32 aligned_cleanup_size = oscl_mem_aligned_size(sizeof(PVOMXEncBufferSharedPtrWrapperCombinedCleanupDA));
5381     uint32 aligned_refcnt_size = oscl_mem_aligned_size(sizeof(OsclRefCounterDA));
5382     uint8 *my_ptr = (uint8*) oscl_malloc(aligned_cleanup_size + aligned_refcnt_size);
5383 
5384     if (my_ptr == NULL)
5385     {
5386         OsclSharedPtr<PVMFMediaDataImpl> null_buff(NULL, NULL);
5387         return null_buff;
5388     }
5389 
5390     // create a deallocator and pass the buffer_allocator to it as well as pointer to data that needs to be returned to the mempool
5391     PVOMXEncBufferSharedPtrWrapperCombinedCleanupDA *cleanup_ptr =
5392         OSCL_PLACEMENT_NEW(my_ptr + aligned_refcnt_size, PVOMXEncBufferSharedPtrWrapperCombinedCleanupDA(iOutBufMemoryPool, pContext));
5393 
5394     // create the ref counter after the cleanup object (refcount is set to 1 at creation)
5395     OsclRefCounterDA *my_refcnt;
5396     PVMFMediaDataImpl* media_data_ptr;
5397 
5398     if (iOMXComponentUsesFullAVCFrames && iNumNALs > 0)
5399     {
5400         uint32 ii;
5401         media_data_ptr = OSCL_NEW(PVMFMediaFragGroup<OsclMemAllocator>, (iNumNALs));
5402         my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterDA(media_data_ptr, cleanup_ptr));
5403 
5404         // loop through and assign a create a media fragment for each NAL
5405         for (ii = 0; ii < iNumNALs; ii++)
5406         {
5407             OsclMemoryFragment memFrag;
5408 
5409             if (iOMXComponentUsesNALStartCodes)
5410             {
5411                 // need to get NAL ptr from stored array, since start codes can be 3 or 4 bytes,
5412                 // and the only way to know is by parsing the buffer (which we should have done by now and stored in the array)
5413                 memFrag.ptr = iNALPtrArray[ii];
5414             }
5415             else
5416             {
5417                 memFrag.ptr = pData;
5418                 pData += iNALSizeArray[ii];
5419             }
5420 
5421             memFrag.len = iNALSizeArray[ii];
5422 
5423             OsclRefCounterMemFrag refCountMemFragOut(memFrag, my_refcnt, memFrag.len);
5424             media_data_ptr->appendMediaFragment(refCountMemFragOut);
5425         }
5426 
5427         oscl_memset((void *) iNALSizeArray, 0, sizeof(uint32) * iNumNALs);
5428         iNumNALs = 0;
5429     }
5430     else
5431     {
5432         media_data_ptr = OSCL_NEW(PVMFMediaFragGroup<OsclMemAllocator>, (1));
5433         my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterDA(media_data_ptr, cleanup_ptr));
5434 
5435         OsclMemoryFragment memFrag;
5436 
5437         if (iOMXComponentUsesNALStartCodes && (iOutFormat != PVMF_MIME_H264_VIDEO_RAW))
5438         {
5439             // skip start code
5440             pData += iFirstNALStartCodeSize;
5441         }
5442 
5443         memFrag.ptr = pData;
5444         memFrag.len = aDataLen;
5445 
5446         OsclRefCounterMemFrag refCountMemFragOut(memFrag, my_refcnt, memFrag.len);
5447         media_data_ptr->appendMediaFragment(refCountMemFragOut);
5448     }
5449 
5450     OsclSharedPtr<PVMFMediaDataImpl> MediaDataImplOut(media_data_ptr, my_refcnt);
5451 
5452     return MediaDataImplOut;
5453 }
5454 //////////////////////////////////////////////////////////////////////////////
SendBeginOfMediaStreamCommand()5455 bool PVMFOMXEncNode::SendBeginOfMediaStreamCommand()
5456 {
5457     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
5458                     (0, "PVMFOMXEncNode-%s::SendBeginOfMediaStreamCommand() In", iNodeTypeId));
5459 
5460     PVMFSharedMediaCmdPtr sharedMediaCmdPtr = PVMFMediaCmd::createMediaCmd();
5461     // Set the formatID, timestamp, sequenceNumber and streamID for the media message
5462     sharedMediaCmdPtr->setFormatID(PVMF_MEDIA_CMD_BOS_FORMAT_ID);
5463     sharedMediaCmdPtr->setTimestamp(iBOSTimestamp);
5464     //reset the sequence number
5465     uint32 seqNum = 0;
5466     sharedMediaCmdPtr->setSeqNum(seqNum);
5467     sharedMediaCmdPtr->setStreamID(iStreamID);
5468 
5469     PVMFSharedMediaMsgPtr mediaMsgOut;
5470     convertToPVMFMediaCmdMsg(mediaMsgOut, sharedMediaCmdPtr);
5471     if (iOutPort->QueueOutgoingMsg(mediaMsgOut) != PVMFSuccess)
5472     {
5473         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
5474                         (0, "PVMFOMXEncNode-%s::SendBeginOfMediaStreamCommand() Outgoing queue busy", iNodeTypeId));
5475         return false;
5476     }
5477 
5478     iSendBOS = false;
5479 
5480     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
5481                     (0, "PVMFOMXEncNode-%s::SendBeginOfMediaStreamCommand() BOS Sent StreamID %d", iNodeTypeId, iStreamID));
5482     return true;
5483 }
5484 ////////////////////////////////////
SendEndOfTrackCommand(void)5485 bool PVMFOMXEncNode::SendEndOfTrackCommand(void)
5486 {
5487     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
5488                     (0, "PVMFOMXEncNode-%s::SendEndOfTrackCommand() In", iNodeTypeId));
5489 
5490     PVMFSharedMediaCmdPtr sharedMediaCmdPtr = PVMFMediaCmd::createMediaCmd();
5491 
5492     sharedMediaCmdPtr->setFormatID(PVMF_MEDIA_CMD_EOS_FORMAT_ID);
5493 
5494     // Set the timestamp
5495     sharedMediaCmdPtr->setTimestamp(iEndOfDataTimestamp);
5496 
5497     // Set Streamid
5498     sharedMediaCmdPtr->setStreamID(iStreamID);
5499 
5500     // Set the sequence number
5501     sharedMediaCmdPtr->setSeqNum(iSeqNum++);
5502 
5503     PVMFSharedMediaMsgPtr mediaMsgOut;
5504     convertToPVMFMediaCmdMsg(mediaMsgOut, sharedMediaCmdPtr);
5505     if (iOutPort->QueueOutgoingMsg(mediaMsgOut) != PVMFSuccess)
5506     {
5507         // this should not happen because we check for queue busy before calling this function
5508         return false;
5509     }
5510 
5511     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
5512                     (0, "PVMFOMXEncNode-%s::SendEndOfTrackCommand() Out", iNodeTypeId));
5513     return true;
5514 }
5515 
5516 /////////////////////////////////////////////////////////////////////////////
5517 //The various command handlers call this routine when a command is complete.
5518 /////////////////////////////////////////////////////////////////////////////
CommandComplete(PVMFOMXEncNodeCmdQ & aCmdQ,PVMFOMXEncNodeCommand & aCmd,PVMFStatus aStatus,OsclAny * aEventData)5519 void PVMFOMXEncNode::CommandComplete(PVMFOMXEncNodeCmdQ& aCmdQ, PVMFOMXEncNodeCommand& aCmd, PVMFStatus aStatus, OsclAny* aEventData)
5520 {
5521     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::CommandComplete Id %d Cmd %d Status %d Context %d Data %d", iNodeTypeId
5522                     , aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData));
5523 
5524     //create response
5525     PVMFCmdResp resp(aCmd.iId, aCmd.iContext, aStatus, aEventData);
5526     PVMFSessionId session = aCmd.iSession;
5527 
5528     //Erase the command from the queue.
5529     aCmdQ.Erase(&aCmd);
5530 
5531     //Report completion to the session observer.
5532     ReportCmdCompleteEvent(session, resp);
5533 }
5534 
5535 /////////////////////////////////////////////////////////////////////////////
DoInit(PVMFOMXEncNodeCommand & aCmd)5536 void PVMFOMXEncNode::DoInit(PVMFOMXEncNodeCommand& aCmd)
5537 {
5538     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoInit() In", iNodeTypeId));
5539     switch (iInterfaceState)
5540     {
5541         case EPVMFNodeIdle:
5542         {
5543             SetState(EPVMFNodeInitialized);
5544             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
5545             break;
5546         }
5547 
5548         default:
5549             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
5550             break;
5551     }
5552 }
5553 
5554 /////////////////////////////////////////////////////////////////////////////
DoPrepare(PVMFOMXEncNodeCommand & aCmd)5555 void PVMFOMXEncNode::DoPrepare(PVMFOMXEncNodeCommand& aCmd)
5556 {
5557     OMX_ERRORTYPE err = OMX_ErrorNone;
5558     OMX_STRING Role = NULL;
5559 
5560     switch (iInterfaceState)
5561     {
5562         case EPVMFNodeInitialized:
5563         {
5564             if (NULL == iInPort)
5565             {
5566                 CommandComplete(iInputCommands, aCmd, PVMFFailure);
5567             }
5568 
5569 
5570             // by now the encode parameters have been set
5571 
5572             if (iOutFormat == PVMF_MIME_H2631998 ||
5573                     iOutFormat == PVMF_MIME_H2632000)
5574             {
5575                 Role = (OMX_STRING)"video_encoder.h263";
5576                 iNodeTypeId = LOG_ID_VIDEO_H263;
5577             }
5578             else if (iOutFormat == PVMF_MIME_M4V)
5579             {
5580                 Role = (OMX_STRING)"video_encoder.mpeg4";
5581                 iNodeTypeId = LOG_ID_VIDEO_M4V;
5582             }
5583             else if (iOutFormat == PVMF_MIME_H264_VIDEO_RAW ||
5584                      iOutFormat == PVMF_MIME_H264_VIDEO_MP4)
5585             {
5586                 Role = (OMX_STRING)"video_encoder.avc";
5587                 iNodeTypeId = LOG_ID_VIDEO_AVC;
5588                 iFirstNAL = true; // set this flag to prevent node from queueing the first
5589                 // buffer
5590             }
5591             else if ((iOutFormat == PVMF_MIME_AMR_IETF) ||
5592                      (iOutFormat == PVMF_MIME_AMR_IF2))
5593             {
5594                 Role = (OMX_STRING)"audio_encoder.amrnb";
5595                 iNodeTypeId = LOG_ID_AUDIO_AMRNB;
5596             }
5597             else if (iOutFormat == PVMF_MIME_AMRWB_IETF)
5598             {
5599                 Role = (OMX_STRING)"audio_encoder.amrwb";
5600                 iNodeTypeId = LOG_ID_AUDIO_AMRWB;
5601             }
5602             else if (iOutFormat == PVMF_MIME_ADTS ||
5603                      iOutFormat == PVMF_MIME_ADIF ||
5604                      iOutFormat == PVMF_MIME_MPEG4_AUDIO)
5605             {
5606                 Role = (OMX_STRING)"audio_encoder.aac";
5607                 iNodeTypeId = LOG_ID_AUDIO_AAC;
5608             }
5609             else
5610             {
5611                 // Illegal codec specified.
5612                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoPrepare() Input port format other then codec type", iNodeTypeId));
5613                 CommandComplete(iInputCommands, aCmd, PVMFErrArgument);
5614                 return;
5615             }
5616 
5617 
5618             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_DEBUG,
5619                             (0, "PVMFOMXEncNode-%s::Initializing OMX component and encoder for role %s", iNodeTypeId, Role));
5620 
5621             /* Set callback structure */
5622             iCallbacks.EventHandler    = CallbackEventHandlerEnc; //event_handler;
5623             iCallbacks.EmptyBufferDone = CallbackEmptyBufferDoneEnc; //empty_buffer_done;
5624             iCallbacks.FillBufferDone  = CallbackFillBufferDoneEnc; //fill_buffer_done;
5625 
5626 
5627             // determine components which can fit the role
5628             // then, create the component. If multiple components fit the role,
5629             // the first one registered will be selected. If that one fails to
5630             // be created, the second one in the list is selected etc.
5631             OMX_U32 num_comps = 0;
5632             OMX_STRING *CompOfRole;
5633             OMX_S8 CompName[PV_OMX_MAX_COMPONENT_NAME_LENGTH];
5634             // call once to find out the number of components that can fit the role
5635             OMX_MasterGetComponentsOfRole(Role, &num_comps, NULL);
5636             uint32 ii;
5637 
5638             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
5639                             (0, "PVMFOMXEncNode-%s::DoPrepare(): There are %d components of role %s ", iNodeTypeId, num_comps, Role));
5640 
5641             if (num_comps > 0)
5642             {
5643                 CompOfRole = (OMX_STRING *)oscl_malloc(num_comps * sizeof(OMX_STRING));
5644 
5645                 for (ii = 0; ii < num_comps; ii++)
5646                     CompOfRole[ii] = (OMX_STRING) oscl_malloc(PV_OMX_MAX_COMPONENT_NAME_LENGTH * sizeof(OMX_U8));
5647 
5648                 // call 2nd time to get the component names
5649                 OMX_MasterGetComponentsOfRole(Role, &num_comps, (OMX_U8 **)CompOfRole);
5650 
5651                 for (ii = 0; ii < num_comps; ii++)
5652                 {
5653                     // try to create component
5654                     err = OMX_MasterGetHandle(&iOMXEncoder, (OMX_STRING) CompOfRole[ii], (OMX_PTR) this, (OMX_CALLBACKTYPE *) & iCallbacks);
5655                     // if successful, no need to continue
5656                     if ((err == OMX_ErrorNone) && (iOMXEncoder != NULL))
5657                     {
5658                         oscl_strncpy((OMX_STRING)CompName, (OMX_STRING) CompOfRole[ii], PV_OMX_MAX_COMPONENT_NAME_LENGTH);
5659 
5660                         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
5661                                         (0, "PVMFOMXEncNode-%s::DoPrepare(): Got Component %s handle ", iNodeTypeId, CompOfRole[ii]));
5662 
5663                         break;
5664                     }
5665                     else
5666                     {
5667                         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
5668                                         (0, "PVMFOMXEncNode-%s::DoPrepare(): Cannot get component %s handle, try another component if available", iNodeTypeId, CompOfRole[ii]));
5669                     }
5670 
5671                 }
5672                 // whether successful or not, need to free CompOfRoles
5673                 for (ii = 0; ii < num_comps; ii++)
5674                 {
5675                     oscl_free(CompOfRole[ii]);
5676                     CompOfRole[ii] = NULL;
5677                 }
5678 
5679                 oscl_free(CompOfRole);
5680                 // check if there was a problem
5681                 if ((err != OMX_ErrorNone) || (iOMXEncoder == NULL))
5682                 {
5683                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
5684                                     (0, "PVMFOMXEncNode-%s::Can't get handle for encoder!", iNodeTypeId));
5685                     iOMXEncoder = NULL;
5686                     CommandComplete(iInputCommands, aCmd, PVMFErrResource);
5687                     return;
5688                 }
5689             }
5690             else
5691             {
5692                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
5693                                 (0, "PVMFOMXEncNode-%s::No component can handle role %s !", iNodeTypeId, Role));
5694                 iOMXEncoder = NULL;
5695                 CommandComplete(iInputCommands, aCmd, PVMFErrResource);
5696                 return;
5697             }
5698 
5699 
5700 
5701             if (!iOMXEncoder)
5702             {
5703                 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources);
5704                 return;
5705             }
5706 
5707 
5708             // find out how many roles the component supports
5709             OMX_U32 NumRoles;
5710             err = OMX_MasterGetRolesOfComponent((OMX_STRING)CompName, &NumRoles, NULL);
5711             if (err != OMX_ErrorNone)
5712             {
5713                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
5714                                 (0, "PVMFOMXEncNode-%s::DoPrepare() Problem getting component roles", iNodeTypeId));
5715 
5716                 CommandComplete(iInputCommands, aCmd, PVMFErrResource);
5717                 return;
5718             }
5719 
5720             if ((0 == oscl_strcmp((char*)CompName, "OMX.qcom.video.encoder.h263"))
5721                     || (0 == oscl_strcmp((char*)CompName, "OMX.qcom.video.encoder.mpeg4")))
5722             {
5723                 bIsQCOMOmxComp = true;
5724             }
5725             else
5726             {
5727                 bIsQCOMOmxComp = false;
5728             }
5729 
5730             // if the component supports multiple roles, call OMX_SetParameter
5731             if (NumRoles > 1)
5732             {
5733                 OMX_PARAM_COMPONENTROLETYPE RoleParam;
5734                 CONFIG_SIZE_AND_VERSION(RoleParam);
5735                 oscl_strncpy((OMX_STRING)RoleParam.cRole, (OMX_STRING)Role, OMX_MAX_STRINGNAME_SIZE);
5736                 err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamStandardComponentRole, &RoleParam);
5737                 if (err != OMX_ErrorNone)
5738                 {
5739                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
5740                                     (0, "PVMFOMXEncNode-%s::DoPrepare() Problem setting component role", iNodeTypeId));
5741 
5742                     CommandComplete(iInputCommands, aCmd, PVMFErrResource);
5743                     return;
5744                 }
5745             }
5746 
5747 
5748             // GET CAPABILITY FLAGS FROM PV COMPONENT, IF this fails, use defaults
5749             PV_OMXComponentCapabilityFlagsType Cap_flags;
5750             err = OMX_GetParameter(iOMXEncoder, (OMX_INDEXTYPE) PV_OMX_COMPONENT_CAPABILITY_TYPE_INDEX, &Cap_flags);
5751             if (err != OMX_ErrorNone)
5752             {
5753                 SetDefaultCapabilityFlags();
5754             }
5755             else
5756             {
5757                 iIsOMXComponentMultiThreaded = (OMX_TRUE == Cap_flags.iIsOMXComponentMultiThreaded) ? true : false;
5758                 iOMXComponentSupportsExternalInputBufferAlloc = (OMX_TRUE == Cap_flags.iOMXComponentSupportsExternalInputBufferAlloc) ? true : false;
5759                 iOMXComponentSupportsExternalOutputBufferAlloc = (OMX_TRUE == Cap_flags.iOMXComponentSupportsExternalOutputBufferAlloc) ? true : false;
5760                 iOMXComponentSupportsMovableInputBuffers = (OMX_TRUE == Cap_flags.iOMXComponentSupportsMovableInputBuffers) ? true : false;
5761                 iOMXComponentSupportsPartialFrames = (OMX_TRUE == Cap_flags.iOMXComponentSupportsPartialFrames) ? true : false;
5762                 iOMXComponentUsesNALStartCodes = (OMX_TRUE == Cap_flags.iOMXComponentUsesNALStartCodes) ? true : false;
5763                 iOMXComponentCanHandleIncompleteFrames = (OMX_TRUE == Cap_flags.iOMXComponentCanHandleIncompleteFrames) ? true : false;
5764                 iOMXComponentUsesFullAVCFrames = (OMX_TRUE == Cap_flags.iOMXComponentUsesFullAVCFrames) ? true : false;
5765             }
5766 
5767             /*  iOMXComponentUsesNALStartCodes:             The component inserts start codes before NALs
5768 
5769                 iOMXComponentUsesFullAVCFrames
5770                 && !iOMXComponentUsesNALStartCodes:     The component outputs full frames, and stores NAL start codes using the
5771                 OMX ExtraData structure in the output buffer
5772                 iOMXComponentUsesFullAVCFrames
5773                 && iOMXComponentUsesNALStartCodes:      The component outputs full frames, and delimits NALs by their start codes
5774 
5775                 iOutFormat == PVMF_MIME_H264_VIDEO_RAW
5776                 && !iOMXComponentUsesNALStartCodes:     The node inserts the start codes and hides them / exposes them when needed
5777 
5778                 iOutFormat == PVMF_MIME_H264_VIDEO_RAW
5779                 && !iOMXComponentUsesNALStartCodes
5780                 && iOMXComponentUsesFullAVCFrames:      This is an invalid combination.  If the node wants raw output, and the component
5781                 uses full frames, and no start codes, then there is no way to detect the
5782                 NAL boundaries.
5783 
5784             */
5785 
5786             if (iOutFormat == PVMF_MIME_H264_VIDEO_RAW &&
5787                     iOMXComponentUsesFullAVCFrames && !iOMXComponentUsesNALStartCodes)
5788             {
5789                 // This is an invalid combination (see above). Therefore, return an error.
5790 
5791 
5792                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
5793                                 (0, "PVMFOMXEncNode-%s::DoPrepare() Component cannot support %s format", iNodeTypeId, PVMF_MIME_H264_VIDEO_RAW));
5794 
5795                 CommandComplete(iInputCommands, aCmd, PVMFErrNotSupported);
5796                 return;
5797             }
5798 
5799 
5800             // find out about parameters
5801             if ((iOutFormat == PVMF_MIME_AMR_IETF) || (iOutFormat == PVMF_MIME_AMRWB_IETF) || (iOutFormat == PVMF_MIME_AMR_IF2) ||
5802                     (iOutFormat == PVMF_MIME_ADIF) || (iOutFormat == PVMF_MIME_ADTS) || (iOutFormat == PVMF_MIME_MPEG4_AUDIO))
5803             {
5804                 if (!NegotiateAudioComponentParameters())
5805                 {
5806                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
5807                                     (0, "PVMFOMXEncNode-%s::DoPrepare() Cannot get component parameters", iNodeTypeId));
5808 
5809                     CommandComplete(iInputCommands, aCmd, PVMFErrNoResources);
5810                     return;
5811                 }
5812             }
5813             else
5814             {
5815 
5816                 if (!NegotiateVideoComponentParameters())
5817                 {
5818                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
5819                                     (0, "PVMFOMXEncNode-%s::DoPrepare() Cannot get component parameters", iNodeTypeId));
5820 
5821                     CommandComplete(iInputCommands, aCmd, PVMFErrNoResources);
5822                     return;
5823                 }
5824             }
5825 
5826             // create active objects to handle callbacks in case of multithreaded implementation
5827 
5828             // NOTE: CREATE THE THREADSAFE CALLBACK AOs REGARDLESS OF WHETHER MULTITHREADED COMPONENT OR NOT
5829             //      If it is not multithreaded, we won't use them
5830             //      The Flag iIsComponentMultiThreaded decides which mechanism is used for callbacks.
5831             //      This flag is set by looking at component capabilities (or to true by default)
5832 
5833             if (iThreadSafeHandlerEventHandler)
5834             {
5835                 OSCL_DELETE(iThreadSafeHandlerEventHandler);
5836                 iThreadSafeHandlerEventHandler = NULL;
5837             }
5838             // substitute default parameters: observer(this node),queuedepth(3),nameAO for logging
5839             // Get the priority of the encoder node, and set the threadsafe callback AO priority to 1 higher
5840 
5841             iThreadSafeHandlerEventHandler = OSCL_NEW(EventHandlerThreadSafeCallbackAOEnc, (this, 10, "EventHandlerAO", Priority() + 2));
5842 
5843             if (iThreadSafeHandlerEmptyBufferDone)
5844             {
5845                 OSCL_DELETE(iThreadSafeHandlerEmptyBufferDone);
5846                 iThreadSafeHandlerEmptyBufferDone = NULL;
5847             }
5848             // use queue depth of iNumInputBuffers to prevent deadlock
5849             iThreadSafeHandlerEmptyBufferDone = OSCL_NEW(EmptyBufferDoneThreadSafeCallbackAOEnc, (this, iNumInputBuffers, "EmptyBufferDoneAO", Priority() + 1));
5850 
5851             if (iThreadSafeHandlerFillBufferDone)
5852             {
5853                 OSCL_DELETE(iThreadSafeHandlerFillBufferDone);
5854                 iThreadSafeHandlerFillBufferDone = NULL;
5855             }
5856             // use queue depth of iNumOutputBuffers to prevent deadlock
5857             iThreadSafeHandlerFillBufferDone = OSCL_NEW(FillBufferDoneThreadSafeCallbackAOEnc, (this, iNumOutputBuffers, "FillBufferDoneAO", Priority() + 1));
5858 
5859             if ((iThreadSafeHandlerEventHandler == NULL) ||
5860                     (iThreadSafeHandlerEmptyBufferDone == NULL) ||
5861                     (iThreadSafeHandlerFillBufferDone == NULL)
5862                )
5863             {
5864                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
5865                                 (0, "PVMFOMXEncNode-%s::Can't get threadsafe callbacks for encoder!", iNodeTypeId));
5866                 iOMXEncoder = NULL;
5867             }
5868 
5869 
5870             // Init Encoder
5871             iCurrentEncoderState = OMX_StateLoaded;
5872 
5873             /* Change state to OMX_StateIdle from OMX_StateLoaded. */
5874             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
5875                             (0, "PVMFOMXEncNode-%s::DoPrepare(): Changing Component state Loaded -> Idle ", iNodeTypeId));
5876 
5877             err = OMX_SendCommand(iOMXEncoder, OMX_CommandStateSet, OMX_StateIdle, NULL);
5878             if (err != OMX_ErrorNone)
5879             {
5880                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
5881                                 (0, "PVMFOMXEncNode-%s::DoPrepare() Can't send StateSet command!", iNodeTypeId));
5882 
5883                 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources);
5884                 return;
5885             }
5886 
5887 
5888             /* Allocate input buffers */
5889             if (!CreateInputMemPool(iNumInputBuffers))
5890             {
5891                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
5892                                 (0, "PVMFOMXEncNode-%s::DoPrepare() Can't allocate mempool for input buffers!", iNodeTypeId));
5893 
5894                 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources);
5895                 return;
5896             }
5897 
5898             if (in_ctrl_struct_ptr)
5899             {
5900                 oscl_free(in_ctrl_struct_ptr);
5901                 in_ctrl_struct_ptr = NULL;
5902             }
5903             if (in_buff_hdr_ptr)
5904             {
5905                 oscl_free(in_buff_hdr_ptr);
5906                 in_buff_hdr_ptr = NULL;
5907             }
5908 
5909             in_ctrl_struct_ptr = (OsclAny **) oscl_malloc(iNumInputBuffers * sizeof(OsclAny *));
5910 
5911             if (in_ctrl_struct_ptr == NULL)
5912             {
5913                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
5914                                 (0, "PVMFOMXEncNode-%s::DoPreapare in_ctrl_struct_ptr == NULL", iNodeTypeId));
5915 
5916                 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources);
5917                 return ;
5918             }
5919 
5920             in_buff_hdr_ptr = (OsclAny **) oscl_malloc(iNumInputBuffers * sizeof(OsclAny *));
5921 
5922             if (in_buff_hdr_ptr == NULL)
5923             {
5924                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
5925                                 (0, "PVMFOMXEncNode-%s::DoPreapare in_buff_hdr_ptr == NULL", iNodeTypeId));
5926 
5927                 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources);
5928                 return ;
5929             }
5930 
5931 
5932             if (!ProvideBuffersToComponent(iInBufMemoryPool, // allocator
5933                                            iInputAllocSize,  // size to allocate from pool (hdr only or hdr+ buffer)
5934                                            iNumInputBuffers, // number of buffers
5935                                            iOMXComponentInputBufferSize, // actual buffer size
5936                                            iInputPortIndex, // port idx
5937                                            iOMXComponentSupportsExternalInputBufferAlloc, // can component use OMX_UseBuffer
5938                                            true // this is input
5939                                           ))
5940             {
5941                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
5942                                 (0, "PVMFOMXEncNode-%s::DoPrepare() Component can't use input buffers!", iNodeTypeId));
5943 
5944                 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources);
5945                 return;
5946             }
5947 
5948 
5949             /* Allocate output buffers */
5950             if (!CreateOutMemPool(iNumOutputBuffers))
5951             {
5952                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
5953                                 (0, "PVMFOMXEncNode-%s::DoPrepare() Can't allocate mempool for output buffers!", iNodeTypeId));
5954 
5955                 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources);
5956                 return;
5957             }
5958 
5959             if (out_ctrl_struct_ptr)
5960             {
5961                 oscl_free(out_ctrl_struct_ptr);
5962                 out_ctrl_struct_ptr = NULL;
5963             }
5964             if (out_buff_hdr_ptr)
5965             {
5966                 oscl_free(out_buff_hdr_ptr);
5967                 out_buff_hdr_ptr = NULL;
5968             }
5969 
5970             out_ctrl_struct_ptr = (OsclAny **) oscl_malloc(iNumOutputBuffers * sizeof(OsclAny *));
5971 
5972             if (out_ctrl_struct_ptr == NULL)
5973             {
5974                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
5975                                 (0, "PVMFOMXEncNode-%s::DoPreapare out_ctrl_struct_ptr == NULL", iNodeTypeId));
5976 
5977                 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources);
5978                 return ;
5979             }
5980 
5981             out_buff_hdr_ptr = (OsclAny **) oscl_malloc(iNumOutputBuffers * sizeof(OsclAny *));
5982 
5983             if (out_buff_hdr_ptr == NULL)
5984             {
5985                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
5986                                 (0, "PVMFOMXEncNode-%s::DoPreapare out_buff_hdr_ptr == NULL", iNodeTypeId));
5987 
5988                 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources);
5989                 return ;
5990             }
5991 
5992 
5993             if (!ProvideBuffersToComponent(iOutBufMemoryPool, // allocator
5994                                            iOutputAllocSize,     // size to allocate from pool (hdr only or hdr+ buffer)
5995                                            iNumOutputBuffers, // number of buffers
5996                                            iOMXComponentOutputBufferSize, // actual buffer size
5997                                            iOutputPortIndex, // port idx
5998                                            iOMXComponentSupportsExternalOutputBufferAlloc, // can component use OMX_UseBuffer
5999                                            false // this is not input
6000                                           ))
6001             {
6002                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
6003                                 (0, "PVMFOMXEncNode-%s::DoPrepare() Component can't use output buffers!", iNodeTypeId));
6004 
6005                 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources);
6006                 return;
6007             }
6008 
6009 
6010             //this command is asynchronous.  move the command from
6011             //the input command queue to the current command, where
6012             //it will remain until it completes. We have to wait for
6013             // OMX component state transition to complete
6014 
6015             int32 err;
6016             OSCL_TRY(err, iCurrentCommand.StoreL(aCmd););
6017             if (err != OsclErrNone)
6018             {
6019                 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
6020                 return;
6021             }
6022             iInputCommands.Erase(&aCmd);
6023 
6024         }
6025         break;
6026         case EPVMFNodePrepared:
6027             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
6028             break;
6029         default:
6030             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
6031             break;
6032     }
6033 
6034 }
6035 
6036 /////////////////////////////////////////////////////////////////////////////
DoStart(PVMFOMXEncNodeCommand & aCmd)6037 void PVMFOMXEncNode::DoStart(PVMFOMXEncNodeCommand& aCmd)
6038 {
6039     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoStart() In", iNodeTypeId));
6040 
6041     iDiagnosticsLogged = false;
6042 
6043     PVMFStatus status = PVMFSuccess;
6044 
6045     OMX_ERRORTYPE  err;
6046     OMX_STATETYPE sState;
6047 
6048 #ifdef _TEST_AE_ERROR_HANDLING
6049     if (FAIL_NODE_CMD_START == iErrorNodeCmd)
6050     {
6051         iInterfaceState = EPVMFNodeError;
6052     }
6053 #endif
6054 
6055 
6056 
6057     switch (iInterfaceState)
6058     {
6059         case EPVMFNodePrepared:
6060         case EPVMFNodePaused:
6061         {
6062             //Get state of OpenMAX encoder
6063             err = OMX_GetState(iOMXEncoder, &sState);
6064             if (err != OMX_ErrorNone)
6065             {
6066                 //Error condition report
6067                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
6068                                 (0, "PVMFOMXEncNode-%s::DoStart(): Can't get State of encoder!", iNodeTypeId));
6069 
6070                 sState = OMX_StateInvalid;
6071             }
6072 #ifdef _TEST_AE_ERROR_HANDLING
6073             if (iErrorHandlingInit)
6074             {
6075                 //some random state ,we want Init to fail
6076 
6077                 sState = OMX_StateInvalid;
6078             }
6079 #endif
6080             if ((sState == OMX_StateIdle) || (sState == OMX_StatePause))
6081             {
6082                 /* Change state to OMX_StateExecuting form OMX_StateIdle. */
6083                 // init the flag
6084                 iDoNotSendOutputBuffersDownstreamFlag = false; // or if output was not being sent downstream due to state changes
6085                 // re-anable sending output
6086 
6087                 iDoNotSaveInputBuffersFlag = false;
6088 
6089 
6090                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
6091                                 (0, "PVMFOMXEncNode-%s::DoStart() Changing Component state Idle->Executing", iNodeTypeId));
6092 
6093                 err = OMX_SendCommand(iOMXEncoder, OMX_CommandStateSet, OMX_StateExecuting, NULL);
6094                 if (err != OMX_ErrorNone)
6095                 {
6096                     //Error condition report
6097                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
6098                                     (0, "PVMFOMXEncNode-%s::DoStart(): Can't send StateSet command to encoder!", iNodeTypeId));
6099 
6100                     status = PVMFErrInvalidState;
6101                 }
6102 
6103             }
6104             else
6105             {
6106                 //Error condition report
6107                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
6108                                 (0, "PVMFOMXEncNode-%s::DoStart(): Encoder is not in the Idle or Pause state!", iNodeTypeId));
6109 
6110                 status = PVMFErrInvalidState;
6111             }
6112 
6113 
6114         }
6115         break;
6116 
6117         default:
6118             status = PVMFErrInvalidState;
6119             break;
6120     }
6121 
6122     if (status == PVMFErrInvalidState)
6123     {
6124         CommandComplete(iInputCommands, aCmd, status);
6125     }
6126     else
6127     {
6128         //this command is asynchronous.  move the command from
6129         //the input command queue to the current command, where
6130         //it will remain until it completes.
6131         int32 err;
6132         OSCL_TRY(err, iCurrentCommand.StoreL(aCmd););
6133         if (err != OsclErrNone)
6134         {
6135             CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
6136         }
6137         iInputCommands.Erase(&aCmd);
6138     }
6139 }
6140 
6141 /////////////////////////////////////////////////////////////////////////////
DoStop(PVMFOMXEncNodeCommand & aCmd)6142 void PVMFOMXEncNode::DoStop(PVMFOMXEncNodeCommand& aCmd)
6143 {
6144     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoStop() In", iNodeTypeId));
6145 
6146     LogDiagnostics();
6147 
6148     OMX_ERRORTYPE  err;
6149     OMX_STATETYPE sState;
6150 #ifdef _TEST_AE_ERROR_HANDLING
6151     if (FAIL_NODE_CMD_STOP == iErrorNodeCmd)
6152     {
6153         iInterfaceState = EPVMFNodeError;
6154     }
6155 #endif
6156     switch (iInterfaceState)
6157     {
6158         case EPVMFNodeStarted:
6159         case EPVMFNodePaused:
6160         case EPVMFNodePrepared:
6161             // Stop data source
6162             // This will also prevent execution of HandleProcessingState
6163 
6164             iDataIn.Unbind();
6165             iPreviousMediaData.Unbind();
6166             if ((iOutFormat == PVMF_MIME_H264_VIDEO_MP4) || (iOutFormat == PVMF_MIME_H264_VIDEO_RAW))
6167             {
6168                 // prepare for next start (if it comes)
6169                 iFirstNAL = true;
6170             }
6171             // Clear queued messages in ports
6172             if (iInPort)
6173             {
6174                 iInPort->ClearMsgQueues();
6175             }
6176 
6177             if (iOutPort)
6178             {
6179                 iOutPort->ClearMsgQueues();
6180             }
6181 
6182             // Clear the data flags
6183 
6184             iEndOfDataReached = false;
6185             iIsEOSSentToComponent = false;
6186             iIsEOSReceivedFromComponent = false;
6187 
6188 
6189             iDoNotSendOutputBuffersDownstreamFlag = true; // stop sending output buffers downstream
6190             iDoNotSaveInputBuffersFlag = true;
6191 
6192 
6193             //Get state of OpenMAX encoder
6194             err = OMX_GetState(iOMXEncoder, &sState);
6195             if (err != OMX_ErrorNone)
6196             {
6197                 //Error condition report
6198                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
6199                                 (0, "PVMFOMXEncNode-%s::DoStop(): Can't get State of encoder!", iNodeTypeId));
6200 
6201                 sState = OMX_StateInvalid;
6202             }
6203 
6204             if ((sState == OMX_StateExecuting) || (sState == OMX_StatePause))
6205             {
6206                 /* Change state to OMX_StateIdle from OMX_StateExecuting or OMX_StatePause. */
6207 
6208                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
6209                                 (0, "PVMFOMXEncNode-%s::DoStop() Changing Component State Executing->Idle or Pause->Idle", iNodeTypeId));
6210 
6211                 err = OMX_SendCommand(iOMXEncoder, OMX_CommandStateSet, OMX_StateIdle, NULL);
6212                 if (err != OMX_ErrorNone)
6213                 {
6214                     //Error condition report
6215                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
6216                                     (0, "PVMFOMXEncNode-%s::DoStop(): Can't send StateSet command to encoder!", iNodeTypeId));
6217 
6218                     CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
6219                     break;
6220                 }
6221 
6222                 // prevent the node from sending more buffers etc.
6223                 // if port reconfiguration is in process, let the state remain one of the port config states
6224                 //  if there is a start command, we can do it seemlessly (by continuing the port reconfig)
6225                 if (iProcessingState == EPVMFOMXEncNodeProcessingState_ReadyToEncode)
6226                     iProcessingState = EPVMFOMXEncNodeProcessingState_Stopping;
6227 
6228             }
6229             else
6230             {
6231                 //Error condition report
6232                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
6233                                 (0, "PVMFOMXEncNode-%s::DoStop(): Encoder is not in the Executing or Pause state!", iNodeTypeId));
6234 
6235                 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
6236                 break;
6237             }
6238 
6239             //this command is asynchronous.  move the command from
6240             //the input command queue to the current command, where
6241             //it will remain until it completes.
6242             int32 err;
6243             OSCL_TRY(err, iCurrentCommand.StoreL(aCmd););
6244             if (err != OsclErrNone)
6245             {
6246                 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
6247                 return;
6248             }
6249             iInputCommands.Erase(&aCmd);
6250 
6251             break;
6252 
6253         default:
6254             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
6255             break;
6256     }
6257 }
6258 
6259 /////////////////////////////////////////////////////////////////////////////
DoFlush(PVMFOMXEncNodeCommand & aCmd)6260 void PVMFOMXEncNode::DoFlush(PVMFOMXEncNodeCommand& aCmd)
6261 {
6262 #ifdef _TEST_AE_ERROR_HANDLING
6263     if (FAIL_NODE_CMD_FLUSH == iErrorNodeCmd)
6264     {
6265         iInterfaceState = EPVMFNodeError;
6266     }
6267 #endif
6268     switch (iInterfaceState)
6269     {
6270         case EPVMFNodeStarted:
6271         case EPVMFNodePaused:
6272             //the flush is asynchronous.  move the command from
6273             //the input command queue to the current command, where
6274             //it will remain until the flush completes.
6275             int32 err;
6276             OSCL_TRY(err, iCurrentCommand.StoreL(aCmd););
6277             if (err != OsclErrNone)
6278             {
6279                 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
6280                 return;
6281             }
6282             iInputCommands.Erase(&aCmd);
6283 
6284             //Notify all ports to suspend their input
6285             if (iInPort)
6286             {
6287                 iInPort->SuspendInput();
6288             }
6289             RunIfNotReady();
6290             if (iOutPort)
6291             {
6292                 iOutPort->SuspendInput();
6293             }
6294             // Stop data source
6295 
6296             // DV: Sending "OMX_CommandFlush" to the encoder;
6297             // Not used because PV Flush command expects data to be processed before getting out
6298             iDoNotSendOutputBuffersDownstreamFlag = true; // collect output buffers
6299 
6300             break;
6301 
6302         default:
6303             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
6304             break;
6305     }
6306 }
6307 
6308 /////////////////////////////////////////////////////////////////////////////
DoPause(PVMFOMXEncNodeCommand & aCmd)6309 void PVMFOMXEncNode::DoPause(PVMFOMXEncNodeCommand& aCmd)
6310 {
6311     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoPause() In", iNodeTypeId));
6312 
6313     OMX_ERRORTYPE  err;
6314     OMX_STATETYPE sState;
6315 #ifdef _TEST_AE_ERROR_HANDLING
6316     if (FAIL_NODE_CMD_PAUSE == iErrorNodeCmd)
6317     {
6318         iInterfaceState = EPVMFNodeError;
6319     }
6320 #endif
6321 
6322     switch (iInterfaceState)
6323     {
6324         case EPVMFNodeStarted:
6325 
6326 
6327             //Get state of OpenMAX encoder
6328             err = OMX_GetState(iOMXEncoder, &sState);
6329             if (err != OMX_ErrorNone)
6330             {
6331                 //Error condition report
6332                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
6333                                 (0, "PVMFOMXEncNode-%s::DoPause(): Can't get State of encoder!", iNodeTypeId));
6334 
6335                 sState = OMX_StateInvalid;
6336             }
6337 
6338             if (sState == OMX_StateExecuting)
6339             {
6340                 /* Change state to OMX_StatePause from OMX_StateExecuting. */
6341                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
6342                                 (0, "PVMFOMXEncNode-%s::DoPause() Changing Component State Executing->Idle", iNodeTypeId));
6343 
6344                 err = OMX_SendCommand(iOMXEncoder, OMX_CommandStateSet, OMX_StatePause, NULL);
6345                 if (err != OMX_ErrorNone)
6346                 {
6347                     //Error condition report
6348                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
6349                                     (0, "PVMFOMXEncNode-%s::DoPause(): Can't send StateSet command to encoder!", iNodeTypeId));
6350 
6351                     CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
6352                     break;
6353                 }
6354 
6355             }
6356             else
6357             {
6358                 //Error condition report
6359                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
6360                                 (0, "PVMFOMXEncNode-%s::DoPause(): Encoder is not in the Executing state!", iNodeTypeId));
6361                 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
6362                 break;
6363             }
6364 
6365             //this command is asynchronous.  move the command from
6366             //the input command queue to the current command, where
6367             //it will remain until it completes.
6368             int32 err;
6369             OSCL_TRY(err, iCurrentCommand.StoreL(aCmd););
6370             if (err != OsclErrNone)
6371             {
6372                 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
6373                 return;
6374             }
6375             iInputCommands.Erase(&aCmd);
6376 
6377             break;
6378         default:
6379             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
6380             break;
6381     }
6382 }
6383 
6384 /////////////////////////////////////////////////////////////////////////////
DoReset(PVMFOMXEncNodeCommand & aCmd)6385 void PVMFOMXEncNode::DoReset(PVMFOMXEncNodeCommand& aCmd)
6386 {
6387 
6388     OMX_ERRORTYPE  err;
6389     OMX_STATETYPE sState;
6390 
6391     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
6392                     (0, "PVMFOMXEncNode-%s::DoReset() In", iNodeTypeId));
6393 
6394     LogDiagnostics();
6395 
6396     switch (iInterfaceState)
6397     {
6398         case EPVMFNodeIdle:
6399         case EPVMFNodeInitialized:
6400         case EPVMFNodePrepared:
6401         case EPVMFNodeStarted:
6402         case EPVMFNodePaused:
6403         case EPVMFNodeError:
6404         {
6405             //Check if encoder is initilized
6406             if (iOMXEncoder != NULL)
6407             {
6408                 //Get state of OpenMAX encoder
6409                 err = OMX_GetState(iOMXEncoder, &sState);
6410                 if (err != OMX_ErrorNone)
6411                 {
6412                     //Error condition report
6413                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
6414                                     (0, "PVMFOMXEncNode-%s::DoReset(): Can't get State of encoder!", iNodeTypeId));
6415                     if (iResetInProgress)
6416                     {
6417                         // cmd is in current q
6418                         iResetInProgress = false;
6419                         if ((iCurrentCommand.size() > 0) &&
6420                                 (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_RESET)
6421                            )
6422                         {
6423                             CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFErrResource);
6424                         }
6425 
6426                     }
6427                     else
6428                     {
6429                         CommandComplete(iInputCommands, aCmd, PVMFErrResource);
6430                     }
6431                     return;
6432                 }
6433 
6434                 if (sState == OMX_StateLoaded)
6435                 {
6436                     // this is a value obtained by synchronous call to component. Either the component was
6437                     // already in this state without node issuing any commands,
6438                     // or perhaps we started the Reset, but the callback notification has not yet arrived.
6439                     if (iResetInProgress)
6440                     {
6441                         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
6442                                         (0, "PVMFOMXEncNode-%s::DoReset() OMX comp is in loaded state. Wait for official callback to change variables etc.", iNodeTypeId));
6443                         return;
6444                     }
6445                     else
6446                     {
6447                         //delete all ports and notify observer.
6448                         if (iInPort)
6449                         {
6450                             OSCL_DELETE(((PVMFOMXEncPort*)iInPort));
6451                             iInPort = NULL;
6452                         }
6453 
6454                         if (iOutPort)
6455                         {
6456                             OSCL_DELETE(((PVMFOMXEncPort*)iOutPort));
6457                             iOutPort = NULL;
6458                         }
6459 
6460                         iDataIn.Unbind();
6461 
6462 
6463                         // Reset the metadata key list
6464                         iAvailableMetadataKeys.clear();
6465 
6466                         iEndOfDataReached = false;
6467                         iIsEOSSentToComponent = false;
6468                         iIsEOSReceivedFromComponent = false;
6469 
6470 
6471                         iProcessingState = EPVMFOMXEncNodeProcessingState_Idle;
6472                         //logoff & go back to Created state.
6473                         SetState(EPVMFNodeIdle);
6474 
6475                         CommandComplete(iInputCommands, aCmd, PVMFSuccess);
6476 
6477                         //CommandComplete(iInputCommands, aCmd, PVMFErrResource);
6478                         return;
6479                     }
6480                 }
6481 
6482                 if (sState == OMX_StateIdle)
6483                 {
6484 
6485 
6486                     //this command is asynchronous.  move the command from
6487                     //the input command queue to the current command, where
6488                     //it will remain until it is completed.
6489                     if (!iResetInProgress)
6490                     {
6491                         int32 err;
6492                         OSCL_TRY(err, iCurrentCommand.StoreL(aCmd););
6493                         if (err != OsclErrNone)
6494                         {
6495                             CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
6496                             return;
6497                         }
6498                         iInputCommands.Erase(&aCmd);
6499 
6500                         iResetInProgress = true;
6501                     }
6502 
6503                     // if buffers aren't all back (due to timing issues with different callback AOs
6504                     //      state change can be reported before all buffers are returned)
6505                     if (iNumOutstandingInputBuffers > 0 || iNumOutstandingOutputBuffers > 0)
6506                     {
6507                         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
6508                                         (0, "PVMFOMXEncNode-%s::DoReset() Waiting for %d input and-or %d output buffers", iNodeTypeId, iNumOutstandingInputBuffers, iNumOutstandingOutputBuffers));
6509 
6510                         return;
6511                     }
6512 
6513                     if (!iResetMsgSent)
6514                     {
6515                         // We can come here only if all buffers are already back
6516                         // Don't repeat any of this twice.
6517                         /* Change state to OMX_StateLoaded form OMX_StateIdle. */
6518                         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
6519                                         (0, "PVMFOMXEncNode-%s::DoReset() Changing Component State Idle->Loaded", iNodeTypeId));
6520 
6521                         err = OMX_SendCommand(iOMXEncoder, OMX_CommandStateSet, OMX_StateLoaded, NULL);
6522                         if (err != OMX_ErrorNone)
6523                         {
6524                             //Error condition report
6525                             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
6526                                             (0, "PVMFOMXEncNode-%s::DoReset(): Can't send StateSet command to encoder!", iNodeTypeId));
6527                         }
6528 
6529                         iResetMsgSent = true;
6530 
6531 
6532                         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
6533                                         (0, "PVMFOMXEncNode-%s::DoReset() freeing output buffers", iNodeTypeId));
6534 
6535                         if (false == iOutputBuffersFreed)
6536                         {
6537                             if (!FreeBuffersFromComponent(iOutBufMemoryPool, // allocator
6538                                                           iOutputAllocSize,  // size to allocate from pool (hdr only or hdr+ buffer)
6539                                                           iNumOutputBuffers, // number of buffers
6540                                                           iOutputPortIndex, // port idx
6541                                                           false // this is not input
6542                                                          ))
6543                             {
6544                                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
6545                                                 (0, "PVMFOMXEncNode-%s::DoReset() Cannot free output buffers ", iNodeTypeId));
6546 
6547                                 if (iResetInProgress)
6548                                 {
6549                                     iResetInProgress = false;
6550                                     if ((iCurrentCommand.size() > 0) &&
6551                                             (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_RESET)
6552                                        )
6553                                     {
6554                                         CommandComplete(iCurrentCommand, iCurrentCommand.front() , PVMFErrResource);
6555                                     }
6556                                 }
6557 
6558                             }
6559 
6560                         }
6561                         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
6562                                         (0, "PVMFOMXEncNode-%s::DoReset() freeing input buffers ", iNodeTypeId));
6563                         if (false == iInputBuffersFreed)
6564                         {
6565                             if (!FreeBuffersFromComponent(iInBufMemoryPool, // allocator
6566                                                           iInputAllocSize,   // size to allocate from pool (hdr only or hdr+ buffer)
6567                                                           iNumInputBuffers, // number of buffers
6568                                                           iInputPortIndex, // port idx
6569                                                           true // this is input
6570                                                          ))
6571                             {
6572                                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
6573                                                 (0, "PVMFOMXEncNode-%s::DoReset() Cannot free input buffers ", iNodeTypeId));
6574 
6575                                 if (iResetInProgress)
6576                                 {
6577                                     iResetInProgress = false;
6578                                     if ((iCurrentCommand.size() > 0) &&
6579                                             (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_RESET)
6580                                        )
6581                                     {
6582                                         CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFErrResource);
6583                                     }
6584                                 }
6585 
6586 
6587                             }
6588                         }
6589 
6590 
6591 
6592                         iEndOfDataReached = false;
6593                         iIsEOSSentToComponent = false;
6594                         iIsEOSReceivedFromComponent = false;
6595 
6596 
6597 
6598                         // also, perform Port deletion when the component replies with the command
6599                         // complete, not right here
6600                     } // end of if(iResetMsgSent)
6601 
6602 
6603                     return;
6604 
6605                 }
6606                 if ((sState == OMX_StateExecuting) || (sState == OMX_StatePause))
6607                 {
6608                     //this command is asynchronous.  move the command from
6609                     //the input command queue to the current command, where
6610                     //it will remain until it is completed.
6611                     if (!iResetInProgress)
6612                     {
6613                         int32 err;
6614                         OSCL_TRY(err, iCurrentCommand.StoreL(aCmd););
6615                         if (err != OsclErrNone)
6616                         {
6617                             CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
6618                             return;
6619                         }
6620                         iInputCommands.Erase(&aCmd);
6621 
6622                         iResetInProgress = true;
6623                     }
6624 
6625                     /* Change state to OMX_StateIdle from OMX_StateExecuting or OMX_StatePause. */
6626 
6627                     if (!iStopInResetMsgSent)
6628                     {
6629 
6630                         // don't send twice in a row
6631 
6632                         iDataIn.Unbind();
6633                         iPreviousMediaData.Unbind();
6634                         if ((iOutFormat == PVMF_MIME_H264_VIDEO_MP4) || (iOutFormat == PVMF_MIME_H264_VIDEO_RAW))
6635                         {
6636                             // prepare for next start (if it comes)
6637                             iFirstNAL = true;
6638                         }
6639                         // Clear queued messages in ports
6640                         if (iInPort)
6641                         {
6642                             iInPort->ClearMsgQueues();
6643                         }
6644 
6645                         if (iOutPort)
6646                         {
6647                             iOutPort->ClearMsgQueues();
6648                         }
6649 
6650                         // Clear the data flags
6651 
6652                         iEndOfDataReached = false;
6653                         iIsEOSSentToComponent = false;
6654                         iIsEOSReceivedFromComponent = false;
6655 
6656 
6657                         iDoNotSendOutputBuffersDownstreamFlag = true; // stop sending output buffers downstream
6658                         iDoNotSaveInputBuffersFlag = true;
6659 
6660                         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
6661                                         (0, "PVMFOMXEncNode-%s::DoReset() Changing Component State Executing->Idle or Pause->Idle", iNodeTypeId));
6662 
6663                         err = OMX_SendCommand(iOMXEncoder, OMX_CommandStateSet, OMX_StateIdle, NULL);
6664                         if (err != OMX_ErrorNone)
6665                         {
6666                             //Error condition report
6667                             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
6668                                             (0, "PVMFOMXEncNode-%s::DoReset(): Can't send StateSet command to Encoder!", iNodeTypeId));
6669 
6670                             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
6671                             break;
6672                         }
6673 
6674                         iStopInResetMsgSent = true;
6675 
6676                         // prevent the node from sending more buffers etc.
6677                         // if port reconfiguration is in process, let the state remain one of the port config states
6678                         //  if there is a start command, we can do it seemlessly (by continuing the port reconfig)
6679                         if (iProcessingState == EPVMFOMXEncNodeProcessingState_ReadyToEncode)
6680                             iProcessingState = EPVMFOMXEncNodeProcessingState_Stopping;
6681                     }
6682                     return;
6683 
6684                 }
6685                 else
6686                 {
6687                     //Error condition report
6688                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
6689                                     (0, "PVMFOMXEncNode-%s::DoReset(): Encoder is not in the Idle state!", iNodeTypeId));
6690                     if (iResetInProgress)
6691                     {
6692                         iResetInProgress = false;
6693                         if ((iCurrentCommand.size() > 0) &&
6694                                 (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_RESET)
6695                            )
6696                         {
6697                             CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFErrInvalidState);
6698                         }
6699                     }
6700                     else
6701                     {
6702                         CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
6703                     }
6704                     break;
6705                 }//end of if (sState == OMX_StateIdle)
6706             }//end of if (iOMXEncoder != NULL)
6707 
6708             //delete all ports and notify observer.
6709             if (iInPort)
6710             {
6711                 OSCL_DELETE(((PVMFOMXEncPort*)iInPort));
6712                 iInPort = NULL;
6713             }
6714 
6715             if (iOutPort)
6716             {
6717                 OSCL_DELETE(((PVMFOMXEncPort*)iOutPort));
6718                 iOutPort = NULL;
6719             }
6720 
6721             iDataIn.Unbind();
6722 
6723 
6724             // Reset the metadata key list
6725             iAvailableMetadataKeys.clear();
6726 
6727             iEndOfDataReached = false;
6728             iIsEOSSentToComponent = false;
6729             iIsEOSReceivedFromComponent = false;
6730 
6731 
6732             iProcessingState = EPVMFOMXEncNodeProcessingState_Idle;
6733             //logoff & go back to Created state.
6734             SetState(EPVMFNodeIdle);
6735 
6736 
6737             if (iResetInProgress)
6738             {
6739                 iResetInProgress = false;
6740                 if ((iCurrentCommand.size() > 0) &&
6741                         (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_RESET)
6742                    )
6743                 {
6744                     CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess);
6745                 }
6746             }
6747             else
6748             {
6749                 CommandComplete(iInputCommands, aCmd, PVMFSuccess);
6750             }
6751 
6752         }
6753         break;
6754 
6755         default:
6756             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
6757             break;
6758     }
6759 }
6760 
6761 /////////////////////////////////////////////////////////////////////////////
DoRequestPort(PVMFOMXEncNodeCommand & aCmd)6762 void PVMFOMXEncNode::DoRequestPort(PVMFOMXEncNodeCommand& aCmd)
6763 {
6764     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
6765                     (0, "PVMFOMXEncNode-%s::DoRequestPort() In", iNodeTypeId));
6766     //This node supports port request from any state
6767 
6768     //retrieve port tag.
6769     int32 tag;
6770     OSCL_String* portconfig;
6771 
6772     aCmd.PVMFOMXEncNodeCommandBase::Parse(tag, portconfig);
6773 
6774     PVMFPortInterface* port = NULL;
6775 
6776 
6777     int32 leavecode = 0;
6778     //validate the tag...
6779 
6780     switch (tag)
6781     {
6782         case PVMF_OMX_ENC_NODE_PORT_TYPE_INPUT:
6783             if (iInPort)
6784             {
6785                 CommandComplete(iInputCommands, aCmd, PVMFFailure);
6786                 break;
6787             }
6788             OSCL_TRY(leavecode, iInPort = OSCL_NEW(PVMFOMXEncPort, ((int32)tag, this, "OMXEncIn")););
6789             if (leavecode || iInPort == NULL)
6790             {
6791                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
6792                                 (0, "PVMFOMXEncNode-%s::DoRequestPort: Error - Input port instantiation failed", iNodeTypeId));
6793                 CommandComplete(iInputCommands, aCmd, PVMFErrArgument);
6794                 return;
6795             }
6796 
6797             // if format was provided in mimestring, set it now.
6798             if (portconfig)
6799             {
6800                 PVMFFormatType format = portconfig->get_str();
6801                 if (((PVMFOMXEncPort*)iInPort)->IsFormatSupported(format))
6802                 {
6803                     ((PVMFOMXEncPort*)iInPort)->iFormat = format;
6804                 }
6805                 else
6806                 {
6807 
6808                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
6809                                     (0, "PVMFOMXEncNode-%s::DoRequestPort: Error - Input port does not support format %s", iNodeTypeId, format.getMIMEStrPtr()));
6810                     OSCL_DELETE(((PVMFOMXEncPort*)iInPort));
6811                     iInPort = NULL;
6812                     CommandComplete(iInputCommands, aCmd, PVMFErrArgument);
6813                     return;
6814                 }
6815 
6816             }
6817 
6818 
6819             port = iInPort;
6820             break;
6821 
6822         case PVMF_OMX_ENC_NODE_PORT_TYPE_OUTPUT:
6823             if (iOutPort)
6824             {
6825                 CommandComplete(iInputCommands, aCmd, PVMFFailure);
6826                 break;
6827             }
6828             OSCL_TRY(leavecode, iOutPort = OSCL_NEW(PVMFOMXEncPort, ((int32)tag, this, "OMXEncOut")));
6829             if (leavecode || iOutPort == NULL)
6830             {
6831                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
6832                                 (0, "PVMFOMXEncNode-%s::DoRequestPort: Error - Output port instantiation failed", iNodeTypeId));
6833                 CommandComplete(iInputCommands, aCmd, PVMFErrArgument);
6834                 return;
6835             }
6836 
6837             // if format was provided in mimestring, set it now.
6838             if (portconfig)
6839             {
6840                 PVMFFormatType format = portconfig->get_str();
6841                 if (((PVMFOMXEncPort*)iOutPort)->IsFormatSupported(format) && (SetCodecType(format) == PVMFSuccess))
6842                 {
6843                     ((PVMFOMXEncPort*)iOutPort)->iFormat = format;
6844                 }
6845                 else
6846                 {
6847 
6848                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
6849                                     (0, "PVMFOMXEncNode-%s::DoRequestPort: Error - Output port does not support format %s", iNodeTypeId, format.getMIMEStrPtr()));
6850                     OSCL_DELETE(((PVMFOMXEncPort*)iOutPort));
6851                     iOutPort = NULL;
6852                     CommandComplete(iInputCommands, aCmd, PVMFErrArgument);
6853                     return;
6854                 }
6855 
6856 
6857             }
6858 
6859             port = iOutPort;
6860             break;
6861 
6862         default:
6863             //bad port tag
6864             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
6865                             (0, "PVMFOMXEncNode-%s::DoRequestPort: Error - Invalid port tag", iNodeTypeId));
6866             CommandComplete(iInputCommands, aCmd, PVMFErrArgument);
6867             return;
6868     }
6869 
6870     //Return the port pointer to the caller.
6871     CommandComplete(iInputCommands, aCmd, PVMFSuccess, (OsclAny*)port);
6872 }
6873 
6874 /////////////////////////////////////////////////////////////////////////////
DoReleasePort(PVMFOMXEncNodeCommand & aCmd)6875 void PVMFOMXEncNode::DoReleasePort(PVMFOMXEncNodeCommand& aCmd)
6876 {
6877     PVMFPortInterface* temp;
6878     aCmd.PVMFOMXEncNodeCommandBase::Parse(temp);
6879     PVMFOMXEncPort* port = (PVMFOMXEncPort*) temp;
6880 #ifdef _TEST_AE_ERROR_HANDLING
6881     if (FAIL_NODE_CMD_RELEASE_PORT == iErrorNodeCmd)
6882     {
6883         port = NULL;
6884     }
6885 #endif
6886 
6887     if (port != NULL && (port == iInPort || port == iOutPort))
6888     {
6889         if (port == iInPort)
6890         {
6891             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
6892                             (0, "PVMFOMXEncNode-%s::DoReleasePort Input port released", iNodeTypeId));
6893 
6894             OSCL_DELETE(((PVMFOMXEncPort*)iInPort));
6895             iInPort = NULL;
6896         }
6897         else
6898         {
6899             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
6900                             (0, "PVMFOMXEncNode-%s::DoReleasePort Output port released", iNodeTypeId));
6901 
6902             OSCL_DELETE(((PVMFOMXEncPort*)iOutPort));
6903             iOutPort = NULL;
6904         }
6905         //delete the port.
6906         CommandComplete(iInputCommands, aCmd, PVMFSuccess);
6907     }
6908     else
6909     {
6910         //port not found.
6911         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
6912                         (0, "PVMFOMXEncNode-%s::DoReleasePort ERROR unknown port cannot be released", iNodeTypeId));
6913 
6914         CommandComplete(iInputCommands, aCmd, PVMFFailure);
6915     }
6916 }
6917 
6918 /////////////////////////////////////////////////////////////////////////////
DoGetNodeMetadataKey(PVMFOMXEncNodeCommand & aCmd)6919 PVMFStatus PVMFOMXEncNode::DoGetNodeMetadataKey(PVMFOMXEncNodeCommand& aCmd)
6920 {
6921     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
6922                     (0, "PVMFOMXEncNode-%s::DoGetNodeMetadataKey() In", iNodeTypeId));
6923 
6924     PVMFMetadataList* keylistptr = NULL;
6925     uint32 starting_index;
6926     int32 max_entries;
6927     char* query_key;
6928 
6929     aCmd.PVMFOMXEncNodeCommand::Parse(keylistptr, starting_index, max_entries, query_key);
6930 
6931     // Check parameters
6932     if (keylistptr == NULL)
6933     {
6934         // The list pointer is invalid
6935         return PVMFErrArgument;
6936     }
6937 
6938     // Update the available metadata keys
6939     iAvailableMetadataKeys.clear();
6940     int32 leavecode = 0;
6941     leavecode = Push_Back_MetadataKeys(PVOMXENCMETADATA_CODECINFO_VIDEO_FORMAT_KEY);
6942 
6943     if (iYUVWidth > 0 && iYUVHeight > 0)
6944     {
6945         leavecode = 0;
6946         leavecode = Push_Back_MetadataKeys(PVOMXENCMETADATA_CODECINFO_VIDEO_WIDTH_KEY);
6947         if (0 == leavecode)
6948             leavecode = Push_Back_MetadataKeys(PVOMXENCMETADATA_CODECINFO_VIDEO_HEIGHT_KEY);
6949     }
6950     // add the profile, level and avgbitrate
6951     PVMF_MPEGVideoProfileType aProfile;
6952     PVMF_MPEGVideoLevelType aLevel;
6953     if (GetProfileAndLevel(aProfile, aLevel) == PVMFSuccess)
6954     {
6955         // For H263 this metadata will be available only after first frame decoding
6956         leavecode = 0;
6957         leavecode = Push_Back_MetadataKeys(PVOMXENCMETADATA_CODECINFO_VIDEO_PROFILE_KEY);
6958         if (0 == leavecode)
6959             leavecode = Push_Back_MetadataKeys(PVOMXENCMETADATA_CODECINFO_VIDEO_LEVEL_KEY);
6960     }
6961     if (0 == leavecode)
6962         leavecode = Push_Back_MetadataKeys(PVOMXENCMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY);
6963 
6964     if ((starting_index > (iAvailableMetadataKeys.size() - 1)) || max_entries == 0)
6965     {
6966         // Invalid starting index and/or max entries
6967         return PVMFErrArgument;
6968     }
6969 
6970     // Copy the requested keys
6971     uint32 num_entries = 0;
6972     int32 num_added = 0;
6973     for (uint32 lcv = 0; lcv < iAvailableMetadataKeys.size(); lcv++)
6974     {
6975         if (query_key == NULL)
6976         {
6977             // No query key so this key is counted
6978             ++num_entries;
6979             if (num_entries > starting_index)
6980             {
6981                 // Past the starting index so copy the key
6982                 leavecode = 0;
6983                 leavecode = Push_Back_MetadataKeys(keylistptr, lcv);
6984                 OSCL_FIRST_CATCH_ANY(leavecode,
6985                                      PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
6986                                                      (0, "PVMFOMXEncNode-%s::DoGetNodeMetadataKey() Memory allocation failure when copying metadata key", iNodeTypeId));
6987                                      return PVMFErrNoMemory);
6988                 num_added++;
6989             }
6990         }
6991         else
6992         {
6993             // Check if the key matche the query key
6994             if (pv_mime_strcmp(iAvailableMetadataKeys[lcv].get_cstr(), query_key) >= 0)
6995             {
6996                 // This key is counted
6997                 ++num_entries;
6998                 if (num_entries > starting_index)
6999                 {
7000                     // Past the starting index so copy the key
7001                     leavecode = 0;
7002                     leavecode = Push_Back_MetadataKeys(keylistptr, lcv);
7003                     OSCL_FIRST_CATCH_ANY(leavecode,
7004                                          PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoGetNodeMetadataKey() Memory allocation failure when copying metadata key", iNodeTypeId));
7005                                          return PVMFErrNoMemory);
7006                     num_added++;
7007                 }
7008             }
7009         }
7010 
7011         // Check if max number of entries have been copied
7012         if (max_entries > 0 && num_added >= max_entries)
7013         {
7014             break;
7015         }
7016     }
7017 
7018     return PVMFSuccess;
7019 }
7020 
7021 /////////////////////////////////////////////////////////////////////////////
DoGetNodeMetadataValue(PVMFOMXEncNodeCommand & aCmd)7022 PVMFStatus PVMFOMXEncNode::DoGetNodeMetadataValue(PVMFOMXEncNodeCommand& aCmd)
7023 {
7024     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoGetNodeMetadataValue() In", iNodeTypeId));
7025 
7026     PVMFMetadataList* keylistptr = NULL;
7027     Oscl_Vector<PvmiKvp, OsclMemAllocator>* valuelistptr = NULL;
7028     uint32 starting_index;
7029     int32 max_entries;
7030 
7031     aCmd.PVMFOMXEncNodeCommand::Parse(keylistptr, valuelistptr, starting_index, max_entries);
7032 
7033     // Check the parameters
7034     if (keylistptr == NULL || valuelistptr == NULL)
7035     {
7036         return PVMFErrArgument;
7037     }
7038 
7039     uint32 numkeys = keylistptr->size();
7040 
7041     if (starting_index > (numkeys - 1) || numkeys <= 0 || max_entries == 0)
7042     {
7043         // Don't do anything
7044         return PVMFErrArgument;
7045     }
7046 
7047     uint32 numvalentries = 0;
7048     int32 numentriesadded = 0;
7049     for (uint32 lcv = 0; lcv < numkeys; lcv++)
7050     {
7051         int32 leavecode = 0;
7052         PvmiKvp KeyVal;
7053         KeyVal.key = NULL;
7054         uint32 KeyLen = 0;
7055 
7056         if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_WIDTH_KEY) == 0) &&
7057                 iYUVWidth > 0)
7058         {
7059             // Video width
7060             // Increment the counter for the number of values found so far
7061             ++numvalentries;
7062 
7063             // Create a value entry if past the starting index
7064             if (numvalentries > starting_index)
7065             {
7066                 KeyLen = oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_WIDTH_KEY) + 1; // for "codec-info/video/width;"
7067                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype="
7068                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator
7069 
7070                 // Allocate memory for the string
7071                 leavecode = 0;
7072                 leavecode = CreateNewArray(KeyVal.key, KeyLen);
7073 
7074 
7075 
7076                 if (leavecode == 0)
7077                 {
7078                     // Copy the key string
7079                     oscl_strncpy(KeyVal.key, PVOMXENCMETADATA_CODECINFO_VIDEO_WIDTH_KEY, oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_WIDTH_KEY) + 1);
7080                     oscl_strncat(KeyVal.key, PVOMXENCMETADATA_SEMICOLON, oscl_strlen(PVOMXENCMETADATA_SEMICOLON));
7081                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR));
7082                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR));
7083                     KeyVal.key[KeyLen-1] = NULL_TERM_CHAR;
7084                     // Copy the value
7085                     KeyVal.value.uint32_value = iYUVWidth;
7086                     // Set the length and capacity
7087                     KeyVal.length = 1;
7088                     KeyVal.capacity = 1;
7089                 }
7090                 else
7091                 {
7092                     // Memory allocation failed
7093                     KeyVal.key = NULL;
7094                     break;
7095                 }
7096             }
7097         }
7098         else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_HEIGHT_KEY) == 0) &&
7099                  iYUVHeight > 0)
7100         {
7101             // Video height
7102             // Increment the counter for the number of values found so far
7103             ++numvalentries;
7104 
7105             // Create a value entry if past the starting index
7106             if (numvalentries > starting_index)
7107             {
7108                 KeyLen = oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_HEIGHT_KEY) + 1; // for "codec-info/video/height;"
7109                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype="
7110                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator
7111 
7112                 // Allocate memory for the string
7113                 leavecode = 0;
7114                 leavecode = CreateNewArray(KeyVal.key, KeyLen);
7115 
7116 
7117 
7118                 if (leavecode == 0)
7119                 {
7120                     // Copy the key string
7121                     oscl_strncpy(KeyVal.key, PVOMXENCMETADATA_CODECINFO_VIDEO_HEIGHT_KEY, oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_HEIGHT_KEY) + 1);
7122                     oscl_strncat(KeyVal.key, PVOMXENCMETADATA_SEMICOLON, oscl_strlen(PVOMXENCMETADATA_SEMICOLON));
7123                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR));
7124                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR));
7125                     KeyVal.key[KeyLen-1] = NULL_TERM_CHAR;
7126                     // Copy the value
7127                     KeyVal.value.uint32_value = iYUVHeight;
7128                     // Set the length and capacity
7129                     KeyVal.length = 1;
7130                     KeyVal.capacity = 1;
7131                 }
7132                 else
7133                 {
7134                     // Memory allocation failed
7135                     KeyVal.key = NULL;
7136                     break;
7137                 }
7138             }
7139         }
7140         else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_PROFILE_KEY) == 0))
7141         {
7142             // Video profile
7143             // Increment the counter for the number of values found so far
7144             ++numvalentries;
7145 
7146             // Create a value entry if past the starting index
7147             if (numvalentries > starting_index)
7148             {
7149                 KeyLen = oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_PROFILE_KEY) + 1; // for "codec-info/video/profile;"
7150                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype="
7151                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator
7152 
7153                 // Allocate memory for the string
7154                 leavecode = 0;
7155                 leavecode = CreateNewArray(KeyVal.key, KeyLen);
7156 
7157 
7158 
7159                 if (leavecode == 0)
7160                 {
7161                     PVMF_MPEGVideoProfileType aProfile;
7162                     PVMF_MPEGVideoLevelType aLevel;
7163                     if (GetProfileAndLevel(aProfile, aLevel) == PVMFSuccess)
7164                     {
7165                         // Copy the key string
7166                         oscl_strncpy(KeyVal.key, PVOMXENCMETADATA_CODECINFO_VIDEO_PROFILE_KEY, oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_PROFILE_KEY) + 1);
7167                         oscl_strncat(KeyVal.key, PVOMXENCMETADATA_SEMICOLON, oscl_strlen(PVOMXENCMETADATA_SEMICOLON));
7168                         oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR));
7169                         oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR));
7170                         KeyVal.key[KeyLen-1] = NULL_TERM_CHAR;
7171                         // Copy the value
7172                         KeyVal.value.uint32_value = (uint32)aProfile; // This is to be decided, who will interpret these value
7173                         // Set the length and capacity
7174                         KeyVal.length = 1;
7175                         KeyVal.capacity = 1;
7176                     }
7177                     else
7178                     {
7179                         // Memory allocation failed
7180                         KeyVal.key = NULL;
7181                         break;
7182                     }
7183                 }
7184                 else
7185                 {
7186                     // Memory allocation failed
7187                     KeyVal.key = NULL;
7188                     break;
7189                 }
7190             }
7191         }
7192         else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_LEVEL_KEY) == 0))
7193         {
7194             // Video level
7195             // Increment the counter for the number of values found so far
7196             ++numvalentries;
7197 
7198             // Create a value entry if past the starting index
7199             if (numvalentries > starting_index)
7200             {
7201                 KeyLen = oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_LEVEL_KEY) + 1; // for "codec-info/video/level;"
7202                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype="
7203                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator
7204 
7205                 // Allocate memory for the string
7206                 leavecode = 0;
7207                 leavecode = CreateNewArray(KeyVal.key, KeyLen);
7208 
7209 
7210 
7211                 if (leavecode == 0)
7212                 {
7213                     PVMF_MPEGVideoProfileType aProfile;
7214                     PVMF_MPEGVideoLevelType aLevel;
7215                     if (GetProfileAndLevel(aProfile, aLevel) == PVMFSuccess)
7216                     {
7217                         // Copy the key string
7218                         oscl_strncpy(KeyVal.key, PVOMXENCMETADATA_CODECINFO_VIDEO_LEVEL_KEY, oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_LEVEL_KEY) + 1);
7219                         oscl_strncat(KeyVal.key, PVOMXENCMETADATA_SEMICOLON, oscl_strlen(PVOMXENCMETADATA_SEMICOLON));
7220                         oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR));
7221                         oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR));
7222                         KeyVal.key[KeyLen-1] = NULL_TERM_CHAR;
7223                         // Copy the value
7224                         KeyVal.value.uint32_value = (uint32)aLevel; // This is to be decided, who will interpret these value
7225                         // Set the length and capacity
7226                         KeyVal.length = 1;
7227                         KeyVal.capacity = 1;
7228                     }
7229                     else
7230                     {
7231                         // Memory allocation failed
7232                         KeyVal.key = NULL;
7233                         break;
7234                     }
7235                 }
7236                 else
7237                 {
7238                     // Memory allocation failed
7239                     KeyVal.key = NULL;
7240                     break;
7241                 }
7242             }
7243         }
7244         else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY) == 0) &&
7245                  (iAvgBitrateValue > 0))
7246         {
7247             // Video average bitrate
7248             // Increment the counter for the number of values found so far
7249             ++numvalentries;
7250 
7251             // Create a value entry if past the starting index
7252             if (numvalentries > starting_index)
7253             {
7254                 KeyLen = oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY) + 1; // for "codec-info/video/avgbitrate;"
7255                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype="
7256                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator
7257 
7258                 // Allocate memory for the string
7259                 leavecode = 0;
7260                 leavecode = CreateNewArray(KeyVal.key, KeyLen);
7261 
7262 
7263 
7264                 if (leavecode == 0)
7265                 {
7266                     // Copy the key string
7267                     oscl_strncpy(KeyVal.key, PVOMXENCMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY, oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY) + 1);
7268                     oscl_strncat(KeyVal.key, PVOMXENCMETADATA_SEMICOLON, oscl_strlen(PVOMXENCMETADATA_SEMICOLON));
7269                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR));
7270                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR));
7271                     KeyVal.key[KeyLen-1] = NULL_TERM_CHAR;
7272                     // Copy the value
7273                     KeyVal.value.uint32_value = iAvgBitrateValue;
7274                     // Set the length and capacity
7275                     KeyVal.length = 1;
7276                     KeyVal.capacity = 1;
7277 
7278                 }
7279                 else
7280                 {
7281                     // Memory allocation failed
7282                     KeyVal.key = NULL;
7283                     break;
7284                 }
7285             }
7286         }
7287         else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_FORMAT_KEY) == 0) &&
7288                  (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H2631998 || ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H2632000 || ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_M4V ||
7289                   ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO || ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_MP4 ||
7290                   ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_RAW  || ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_WMV))
7291         {
7292             // Format
7293             // Increment the counter for the number of values found so far
7294             ++numvalentries;
7295 
7296             // Create a value entry if past the starting index
7297             if (numvalentries > starting_index)
7298             {
7299                 KeyLen = oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_FORMAT_KEY) + 1; // for "codec-info/video/format;"
7300                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype="
7301                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_CHARPTR_STRING_CONSTCHAR) + 1; // for "char*" and NULL terminator
7302 
7303                 uint32 valuelen = 0;
7304                 if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO)
7305                 {
7306                     valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_H264_VIDEO)) + 1; // Value string plus one for NULL terminator
7307                 }
7308                 else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_MP4)
7309                 {
7310                     valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_H264_VIDEO_MP4)) + 1; // Value string plus one for NULL terminator
7311                 }
7312                 else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_RAW)
7313                 {
7314                     valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_H264_VIDEO_RAW)) + 1; // Value string plus one for NULL terminator
7315                 }
7316                 else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_M4V)
7317                 {
7318                     valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_M4V)) + 1; // Value string plus one for NULL terminator
7319                 }
7320                 else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H2631998)
7321                 {
7322                     valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_H2631998)) + 1; // Value string plus one for NULL terminator
7323                 }
7324                 else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H2632000)
7325                 {
7326                     oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_H2632000), valuelen);
7327                 }
7328                 else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_WMV)
7329                 {
7330                     valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_WMV)) + 1; // Value string plus one for NULL terminator
7331                 }
7332                 else
7333                 {
7334                     // Should not enter here
7335                     OSCL_ASSERT(false);
7336                     valuelen = 1;
7337                 }
7338 
7339                 // Allocate memory for the strings
7340                 leavecode = 0;
7341                 leavecode = CreateNewArray(KeyVal.key, KeyLen);
7342                 if (0 == leavecode)
7343                 {
7344                     leavecode = CreateNewArray(KeyVal.value.pChar_value , valuelen);
7345                 }
7346 
7347                 if (leavecode == 0)
7348                 {
7349                     // Copy the key string
7350                     oscl_strncpy(KeyVal.key, PVOMXENCMETADATA_CODECINFO_VIDEO_FORMAT_KEY, oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_FORMAT_KEY) + 1);
7351                     oscl_strncat(KeyVal.key, PVOMXENCMETADATA_SEMICOLON, oscl_strlen(PVOMXENCMETADATA_SEMICOLON));
7352                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR));
7353                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_CHARPTR_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_CHARPTR_STRING_CONSTCHAR));
7354                     KeyVal.key[KeyLen-1] = NULL_TERM_CHAR;
7355                     // Copy the value
7356                     if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO)
7357                     {
7358                         oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_H264_VIDEO), valuelen);
7359                     }
7360                     else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_MP4)
7361                     {
7362                         oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_H264_VIDEO_MP4), valuelen);
7363                     }
7364                     else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_RAW)
7365                     {
7366                         oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_H264_VIDEO_RAW), valuelen);
7367                     }
7368                     else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_M4V)
7369                     {
7370                         oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_M4V), valuelen);
7371                     }
7372                     else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H2631998)
7373                     {
7374                         oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_H2631998), valuelen);
7375                     }
7376                     else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H2632000)
7377                     {
7378                         oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_H2632000), valuelen);
7379                     }
7380                     else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_WMV)
7381                     {
7382                         oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_WMV), valuelen);
7383                     }
7384                     else
7385                     {
7386                         // Should not enter here
7387                         OSCL_ASSERT(false);
7388                         valuelen = 1;
7389                     }
7390 
7391                     KeyVal.value.pChar_value[valuelen-1] = NULL_TERM_CHAR;
7392                     // Set the length and capacity
7393                     KeyVal.length = valuelen;
7394                     KeyVal.capacity = valuelen;
7395                 }
7396                 else
7397                 {
7398                     // Memory allocation failed so clean up
7399                     if (KeyVal.key)
7400                     {
7401                         OSCL_ARRAY_DELETE(KeyVal.key);
7402                         KeyVal.key = NULL;
7403                     }
7404                     if (KeyVal.value.pChar_value)
7405                     {
7406                         OSCL_ARRAY_DELETE(KeyVal.value.pChar_value);
7407                     }
7408                     break;
7409                 }
7410             }
7411         }
7412 
7413         if (KeyVal.key != NULL)
7414         {
7415             leavecode = 0;
7416             leavecode = PushBackKeyVal(valuelistptr, KeyVal);
7417             if (leavecode != 0)
7418             {
7419                 switch (GetValTypeFromKeyString(KeyVal.key))
7420                 {
7421                     case PVMI_KVPVALTYPE_CHARPTR:
7422                         if (KeyVal.value.pChar_value != NULL)
7423                         {
7424                             OSCL_ARRAY_DELETE(KeyVal.value.pChar_value);
7425                             KeyVal.value.pChar_value = NULL;
7426                         }
7427                         break;
7428 
7429                     default:
7430                         // Add more case statements if other value types are returned
7431                         break;
7432                 }
7433 
7434                 OSCL_ARRAY_DELETE(KeyVal.key);
7435                 KeyVal.key = NULL;
7436             }
7437             else
7438             {
7439                 // Increment the counter for number of value entries added to the list
7440                 ++numentriesadded;
7441             }
7442 
7443             // Check if the max number of value entries were added
7444             if (max_entries > 0 && numentriesadded >= max_entries)
7445             {
7446                 break;
7447             }
7448         }
7449     }
7450 
7451     return PVMFSuccess;
7452 }
7453 
7454 /////////////////////////////////////////////////////////////////////////////
ReleaseAllPorts()7455 bool PVMFOMXEncNode::ReleaseAllPorts()
7456 {
7457     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::ReleaseAllPorts() In", iNodeTypeId));
7458 
7459     if (iInPort)
7460     {
7461         iInPort->ClearMsgQueues();
7462         iInPort->Disconnect();
7463         OSCL_DELETE(((PVMFOMXEncPort*)iInPort));
7464         iInPort = NULL;
7465     }
7466 
7467     if (iOutPort)
7468     {
7469         iOutPort->ClearMsgQueues();
7470         iOutPort->Disconnect();
7471         OSCL_DELETE(((PVMFOMXEncPort*)iOutPort));
7472         iOutPort = NULL;
7473     }
7474 
7475     return true;
7476 }
7477 
7478 /////////////////////////////////////////////////////////////////////////////
7479 // Clean Up Encoder
7480 /////////////////////////////////////////////////////////////////////////////
DeleteOMXEncoder()7481 bool PVMFOMXEncNode::DeleteOMXEncoder()
7482 {
7483     OMX_ERRORTYPE  err;
7484 
7485     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
7486                     (0, "PVMFOMXEncNode-%s::DeleteOMXEncoder() In", iNodeTypeId));
7487 
7488     if (iOMXEncoder != NULL)
7489     {
7490         /* Free Component handle. */
7491         err = OMX_MasterFreeHandle(iOMXEncoder);
7492         if (err != OMX_ErrorNone)
7493         {
7494             //Error condition report
7495             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
7496                             (0, "PVMFOMXEncNode-%s::DeleteOMXEncoder(): Can't free encoder's handle!", iNodeTypeId));
7497         }
7498         iOMXEncoder = NULL;
7499 
7500     }//end of if (iOMXEncoder != NULL)
7501 
7502 
7503     return true;
7504 }
7505 
7506 /////////////////////////////////////////////////////////////////////////////
ChangeNodeState(TPVMFNodeInterfaceState aNewState)7507 void PVMFOMXEncNode::ChangeNodeState(TPVMFNodeInterfaceState aNewState)
7508 {
7509     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::ChangeNodeState() Changing state from %d to %d", iNodeTypeId, iInterfaceState, aNewState));
7510     iInterfaceState = aNewState;
7511 }
7512 
7513 /////////////////////////////////////////////////////////////////////////////
freechunkavailable(OsclAny * aContext)7514 void PVMFOMXEncNode::freechunkavailable(OsclAny *aContext)
7515 {
7516 
7517     // check context to see whether input or output buffer was returned to the mempool
7518     if (aContext == (OsclAny *) iInBufMemoryPool)
7519     {
7520 
7521         iNumOutstandingInputBuffers--;
7522 
7523         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
7524                         (0, "PVMFOMXEncNode-%s::freechunkavailable() Memory chunk in INPUT mempool was deallocated, %d out of %d now available", iNodeTypeId, iNumInputBuffers - iNumOutstandingInputBuffers, iNumInputBuffers));
7525 
7526         // notification only works once.
7527         // If there are multiple buffers coming back in a row, make sure to set the notification
7528         // flag in the mempool again, so that next buffer also causes notification
7529         iInBufMemoryPool->notifyfreechunkavailable(*this, aContext);
7530 
7531     }
7532     else if (aContext == (OsclAny *) iOutBufMemoryPool)
7533     {
7534 
7535         iNumOutstandingOutputBuffers--;
7536         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
7537                         (0, "PVMFOMXEncNode-%s::freechunkavailable() Memory chunk in OUTPUT mempool was deallocated, %d out of %d now available", iNodeTypeId, iNumOutputBuffers - iNumOutstandingOutputBuffers, iNumOutputBuffers));
7538 
7539         // notification only works once.
7540         // If there are multiple buffers coming back in a row, make sure to set the notification
7541         // flag in the mempool again, so that next buffer also causes notification
7542         iOutBufMemoryPool->notifyfreechunkavailable(*this, aContext);
7543 
7544     }
7545     else
7546     {
7547         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
7548                         (0, "PVMFOMXEncNode-%s::freechunkavailable() UNKNOWN mempool ", iNodeTypeId));
7549 
7550     }
7551 
7552     // reschedule
7553     if (IsAdded())
7554         RunIfNotReady();
7555 
7556 
7557 }
7558 
7559 /////////////////////////////////////////////////////////////////////////////
HandlePortActivity(const PVMFPortActivity & aActivity)7560 void PVMFOMXEncNode::HandlePortActivity(const PVMFPortActivity &aActivity)
7561 {
7562     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
7563                     (0, "0x%x PVMFOMXEncNode-%s::PortActivity: port=0x%x, type=%d",
7564                      this, iNodeTypeId, aActivity.iPort, aActivity.iType));
7565 
7566     switch (aActivity.iType)
7567     {
7568         case PVMF_PORT_ACTIVITY_OUTGOING_MSG:
7569             //An outgoing message was queued on this port.
7570             //We only need to queue a port activity event on the
7571             //first message.  Additional events will be queued during
7572             //the port processing as needed.
7573             if (aActivity.iPort->OutgoingMsgQueueSize() == 1)
7574             {
7575                 //wake up the AO to process the port activity event.
7576                 RunIfNotReady();
7577             }
7578             break;
7579 
7580         case PVMF_PORT_ACTIVITY_INCOMING_MSG:
7581             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
7582                             (0, "PVMFOMXEncNode-%s::PortActivity: IncomingMsgQueueSize=%d", iNodeTypeId, aActivity.iPort->IncomingMsgQueueSize()));
7583             if (aActivity.iPort->IncomingMsgQueueSize() == 1)
7584             {
7585                 //wake up the AO to process the port activity event.
7586                 RunIfNotReady();
7587             }
7588             break;
7589 
7590         case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY:
7591             if (iProcessingState == EPVMFOMXEncNodeProcessingState_WaitForOutgoingQueue)
7592             {
7593                 iProcessingState = EPVMFOMXEncNodeProcessingState_ReadyToEncode;
7594                 RunIfNotReady();
7595             }
7596             break;
7597 
7598         case PVMF_PORT_ACTIVITY_CONNECT:
7599             //nothing needed.
7600             break;
7601 
7602         case PVMF_PORT_ACTIVITY_DISCONNECT:
7603             //clear the node input data when either port is disconnected.
7604 
7605             iDataIn.Unbind();
7606             break;
7607 
7608         case PVMF_PORT_ACTIVITY_CONNECTED_PORT_BUSY:
7609             // The connected port has become busy (its incoming queue is
7610             // busy).
7611             // No action is needed here-- the port processing code
7612             // checks for connected port busy during data processing.
7613             break;
7614 
7615         case PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY:
7616             // The connected port has transitioned from Busy to Ready to Receive.
7617             // It's time to start processing outgoing messages again.
7618 
7619             //iProcessingState should transition from WaitForOutputPort to ReadyToEncode
7620             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
7621                             (0, "0x%x PVMFOMXEncNode-%s::PortActivity: Connected port is now ready", this, iNodeTypeId));
7622             RunIfNotReady();
7623             break;
7624 
7625         default:
7626             break;
7627     }
7628 }
7629 
7630 /////////////////////////////////////////////////////////////////////////////
DoCancelAllCommands(PVMFOMXEncNodeCommand & aCmd)7631 void PVMFOMXEncNode::DoCancelAllCommands(PVMFOMXEncNodeCommand& aCmd)
7632 {
7633     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
7634                     (0, "PVMFOMXEncNode-%s::DoCancelAllCommands", iNodeTypeId));
7635 
7636     //first cancel the current command if any
7637     {
7638         while (!iCurrentCommand.empty())
7639         {
7640             CommandComplete(iCurrentCommand, iCurrentCommand[0], PVMFErrCancelled);
7641         }
7642 
7643     }
7644 
7645     //next cancel all queued commands
7646     {
7647         //start at element 1 since this cancel command is element 0.
7648         while (iInputCommands.size() > 1)
7649         {
7650             CommandComplete(iInputCommands, iInputCommands[1], PVMFErrCancelled);
7651         }
7652     }
7653 
7654     if (iResetInProgress && !iResetMsgSent)
7655     {
7656         // if reset is started but reset msg has not been sent, we can cancel reset
7657         // as if nothing happened. Otherwise, the callback will set the flag back to false
7658         iResetInProgress = false;
7659     }
7660     //finally, report cancel complete.
7661     CommandComplete(iInputCommands, aCmd, PVMFSuccess);
7662 }
7663 
7664 /////////////////////////////////////////////////////////////////////////////
DoCancelCommand(PVMFOMXEncNodeCommand & aCmd)7665 void PVMFOMXEncNode::DoCancelCommand(PVMFOMXEncNodeCommand& aCmd)
7666 {
7667     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
7668                     (0, "PVMFOMXEncNode-%s::DoCancelCommand", iNodeTypeId));
7669 
7670     //extract the command ID from the parameters.
7671     PVMFCommandId id;
7672     aCmd.PVMFOMXEncNodeCommandBase::Parse(id);
7673 
7674     //first check "current" command if any
7675     {
7676         PVMFOMXEncNodeCommand* cmd = iCurrentCommand.FindById(id);
7677         if (cmd)
7678         {
7679 
7680             // if reset is being canceled:
7681             if (cmd->iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_RESET)
7682             {
7683                 if (iResetInProgress && !iResetMsgSent)
7684                 {
7685                     // if reset is started but reset msg has not been sent, we can cancel reset
7686                     // as if nothing happened. Otherwise, the callback will set the flag back to false
7687                     iResetInProgress = false;
7688                 }
7689             }
7690             //cancel the queued command
7691             CommandComplete(iCurrentCommand, *cmd, PVMFErrCancelled);
7692             //report cancel success
7693             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
7694             return;
7695         }
7696     }
7697 
7698     //next check input queue.
7699     {
7700         //start at element 1 since this cancel command is element 0.
7701         PVMFOMXEncNodeCommand* cmd = iInputCommands.FindById(id, 1);
7702         if (cmd)
7703         {
7704             //cancel the queued command
7705             CommandComplete(iInputCommands, *cmd, PVMFErrCancelled);
7706             //report cancel success
7707             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
7708             return;
7709         }
7710     }
7711     //if we get here the command isn't queued so the cancel fails.
7712     CommandComplete(iInputCommands, aCmd, PVMFErrArgument);
7713 }
7714 
7715 /////////////////////////////////////////////////////////////////////////////
DoQueryUuid(PVMFOMXEncNodeCommand & aCmd)7716 void PVMFOMXEncNode::DoQueryUuid(PVMFOMXEncNodeCommand& aCmd)
7717 {
7718     //This node supports Query UUID from any state
7719 
7720     OSCL_String* mimetype;
7721     Oscl_Vector<PVUuid, OsclMemAllocator> *uuidvec;
7722     bool exactmatch;
7723     aCmd.PVMFOMXEncNodeCommandBase::Parse(mimetype, uuidvec, exactmatch);
7724 
7725     //Try to match the input mimetype against any of
7726     //the custom interfaces for this node
7727 
7728     //Match against custom interface1...
7729     if (*mimetype == PVMF_OMX_ENC_NODE_CUSTOM1_MIMETYPE
7730             //also match against base mimetypes for custom interface1,
7731             //unless exactmatch is set.
7732             || (!exactmatch && *mimetype == PVMF_OMX_ENC_NODE_MIMETYPE)
7733             || (!exactmatch && *mimetype == PVMF_BASEMIMETYPE))
7734     {
7735 
7736         PVUuid uuid(PVMF_OMX_ENC_NODE_CUSTOM1_UUID);
7737         uuidvec->push_back(uuid);
7738     }
7739     CommandComplete(iInputCommands, aCmd, PVMFSuccess);
7740 }
7741 
7742 /////////////////////////////////////////////////////////////////////////////
DoQueryInterface(PVMFOMXEncNodeCommand & aCmd)7743 void PVMFOMXEncNode::DoQueryInterface(PVMFOMXEncNodeCommand&  aCmd)
7744 {
7745     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
7746                     (0, "PVMFOMXEncNode-%s::DoQueryInterface", iNodeTypeId));
7747     PVUuid* uuid;
7748     PVInterface** ptr;
7749     aCmd.PVMFOMXEncNodeCommandBase::Parse(uuid, ptr);
7750 
7751     if (*uuid == PVUuid(PVMF_OMX_ENC_NODE_CUSTOM1_UUID))
7752     {
7753         addRef();
7754         *ptr = (PVMFOMXEncNodeExtensionInterface*)this;
7755         CommandComplete(iInputCommands, aCmd, PVMFSuccess);
7756     }
7757     else if (*uuid == PVUuid(KPVMFMetadataExtensionUuid))
7758     {
7759         addRef();
7760         *ptr = (PVMFMetadataExtensionInterface*)this;
7761         CommandComplete(iInputCommands, aCmd, PVMFSuccess);
7762     }
7763     else if (*uuid == PVUuid(PVMI_CAPABILITY_AND_CONFIG_PVUUID))
7764     {
7765         addRef();
7766         *ptr = (PvmiCapabilityAndConfig*)this;
7767         CommandComplete(iInputCommands, aCmd, PVMFSuccess);
7768     }
7769     else if (*uuid == PVMp4H263EncExtensionUUID)
7770     {
7771         addRef();
7772         *ptr = OSCL_STATIC_CAST(PVMp4H263EncExtensionInterface*, this);
7773         CommandComplete(iInputCommands, aCmd, PVMFSuccess);
7774         //iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
7775 
7776     }
7777     else if (*uuid == PVAudioEncExtensionUUID)
7778     {
7779         addRef();
7780         *ptr = OSCL_STATIC_CAST(PVAudioEncExtensionInterface*, this);
7781         //iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
7782         CommandComplete(iInputCommands, aCmd, PVMFSuccess);
7783 
7784     }
7785     else
7786     {
7787         //not supported
7788         *ptr = NULL;
7789         CommandComplete(iInputCommands, aCmd, PVMFFailure);
7790     }
7791 }
7792 
7793 /////////////////////////////////////////////////////////////////////////////
addRef()7794 void PVMFOMXEncNode::addRef()
7795 {
7796     ++iExtensionRefCount;
7797 }
7798 
7799 /////////////////////////////////////////////////////////////////////////////
removeRef()7800 void PVMFOMXEncNode::removeRef()
7801 {
7802     --iExtensionRefCount;
7803 }
7804 
7805 /////////////////////////////////////////////////////////////////////////////
queryInterface(const PVUuid & uuid,PVInterface * & iface)7806 bool PVMFOMXEncNode::queryInterface(const PVUuid& uuid, PVInterface*& iface)
7807 {
7808     PVUuid my_uuid(PVMF_OMX_ENC_NODE_CUSTOM1_UUID);
7809     if (uuid == my_uuid)
7810     {
7811         PVMFOMXEncNodeExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFOMXEncNodeExtensionInterface*, this);
7812         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
7813         ++iExtensionRefCount;
7814         return true;
7815     }
7816     else if (uuid == KPVMFMetadataExtensionUuid)
7817     {
7818         PVMFMetadataExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFMetadataExtensionInterface*, this);
7819         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
7820         ++iExtensionRefCount;
7821         return true;
7822     }
7823     return false;
7824 }
7825 
7826 /////////////////////////////////////////////////////////////////////////////
GetNumMetadataKeys(char * aQueryKeyString)7827 uint32 PVMFOMXEncNode::GetNumMetadataKeys(char* aQueryKeyString)
7828 {
7829     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::GetNumMetadataKeys() called", iNodeTypeId));
7830 
7831     // Update the available metadata keys
7832     iAvailableMetadataKeys.clear();
7833     int32 errcode = 0;
7834     OSCL_TRY(errcode, iAvailableMetadataKeys.push_back(PVOMXENCMETADATA_CODECINFO_VIDEO_FORMAT_KEY));
7835 
7836     if (iYUVWidth > 0 && iYUVHeight > 0)
7837     {
7838         errcode = 0;
7839         OSCL_TRY(errcode,
7840                  iAvailableMetadataKeys.push_back(PVOMXENCMETADATA_CODECINFO_VIDEO_WIDTH_KEY);
7841                  iAvailableMetadataKeys.push_back(PVOMXENCMETADATA_CODECINFO_VIDEO_HEIGHT_KEY));
7842     }
7843     // add the profile, level and avgbitrate
7844     PVMF_MPEGVideoProfileType aProfile;
7845     PVMF_MPEGVideoLevelType aLevel;
7846     if (GetProfileAndLevel(aProfile, aLevel) == PVMFSuccess)
7847     {
7848         // For H263 this metadata will be available only after first frame decoding
7849         errcode = 0;
7850         OSCL_TRY(errcode, iAvailableMetadataKeys.push_back(PVOMXENCMETADATA_CODECINFO_VIDEO_PROFILE_KEY));
7851         errcode = 0;
7852         OSCL_TRY(errcode, iAvailableMetadataKeys.push_back(PVOMXENCMETADATA_CODECINFO_VIDEO_LEVEL_KEY));
7853     }
7854     errcode = 0;
7855     OSCL_TRY(errcode, iAvailableMetadataKeys.push_back(PVOMXENCMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY));
7856 
7857 
7858 
7859     uint32 num_entries = 0;
7860 
7861     if (aQueryKeyString == NULL)
7862     {
7863         num_entries = iAvailableMetadataKeys.size();
7864     }
7865     else
7866     {
7867         for (uint32 i = 0; i < iAvailableMetadataKeys.size(); i++)
7868         {
7869             if (pv_mime_strcmp(iAvailableMetadataKeys[i].get_cstr(), aQueryKeyString) >= 0)
7870             {
7871                 num_entries++;
7872             }
7873         }
7874     }
7875     return num_entries; // Number of elements
7876 }
7877 
7878 ///////////////////////////////////////////////////////////////////////////////////////
setObserver(PvmiConfigAndCapabilityCmdObserver * aObserver)7879 void PVMFOMXEncNode::setObserver(PvmiConfigAndCapabilityCmdObserver* aObserver)
7880 {
7881     OSCL_UNUSED_ARG(aObserver);
7882     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::setObserver()", iNodeTypeId));
7883     // This method is not supported so leave
7884     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::setObserver() is not supported!", iNodeTypeId));
7885     OSCL_LEAVE(PVMFErrNotSupported);
7886 }
7887 
7888 
getParametersSync(PvmiMIOSession aSession,PvmiKeyType aIdentifier,PvmiKvp * & aParameters,int & aNumParamElements,PvmiCapabilityContext aContext)7889 PVMFStatus PVMFOMXEncNode::getParametersSync(PvmiMIOSession aSession, PvmiKeyType aIdentifier, PvmiKvp*& aParameters, int& aNumParamElements, PvmiCapabilityContext aContext)
7890 {
7891     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::getParametersSync()", iNodeTypeId));
7892     OSCL_UNUSED_ARG(aSession);
7893 
7894     return DoCapConfigGetParametersSync(aIdentifier, aParameters, aNumParamElements, aContext);
7895 }
7896 
7897 
releaseParameters(PvmiMIOSession aSession,PvmiKvp * aParameters,int aNumElements)7898 PVMFStatus PVMFOMXEncNode::releaseParameters(PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements)
7899 {
7900     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::releaseParameters()", iNodeTypeId));
7901     OSCL_UNUSED_ARG(aSession);
7902 
7903     return DoCapConfigReleaseParameters(aParameters, aNumElements);
7904 }
7905 
7906 
createContext(PvmiMIOSession aSession,PvmiCapabilityContext & aContext)7907 void PVMFOMXEncNode::createContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext)
7908 {
7909     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::createContext()", iNodeTypeId));
7910     OSCL_UNUSED_ARG(aSession);
7911     OSCL_UNUSED_ARG(aContext);
7912     // This method is not supported so leave
7913     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::createContext() is not supported!", iNodeTypeId));
7914     OSCL_LEAVE(PVMFErrNotSupported);
7915 }
7916 
7917 
setContextParameters(PvmiMIOSession aSession,PvmiCapabilityContext & aContext,PvmiKvp * aParameters,int aNumParamElements)7918 void PVMFOMXEncNode::setContextParameters(PvmiMIOSession aSession, PvmiCapabilityContext& aContext, PvmiKvp* aParameters, int aNumParamElements)
7919 {
7920     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::setContextParameters()", iNodeTypeId));
7921     OSCL_UNUSED_ARG(aSession);
7922     OSCL_UNUSED_ARG(aContext);
7923     OSCL_UNUSED_ARG(aParameters);
7924     OSCL_UNUSED_ARG(aNumParamElements);
7925     // This method is not supported so leave
7926     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::setContextParameters() is not supported!", iNodeTypeId));
7927     OSCL_LEAVE(PVMFErrNotSupported);
7928 }
7929 
7930 
DeleteContext(PvmiMIOSession aSession,PvmiCapabilityContext & aContext)7931 void PVMFOMXEncNode::DeleteContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext)
7932 {
7933     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DeleteContext()", iNodeTypeId));
7934     OSCL_UNUSED_ARG(aSession);
7935     OSCL_UNUSED_ARG(aContext);
7936     // This method is not supported so leave
7937     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DeleteContext() is not supported!", iNodeTypeId));
7938     OSCL_LEAVE(PVMFErrNotSupported);
7939 }
7940 
7941 
setParametersSync(PvmiMIOSession aSession,PvmiKvp * aParameters,int aNumElements,PvmiKvp * & aRetKVP)7942 void PVMFOMXEncNode::setParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements, PvmiKvp* &aRetKVP)
7943 {
7944     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::setParametersSync()", iNodeTypeId));
7945     OSCL_UNUSED_ARG(aSession);
7946 
7947     // Complete the request synchronously
7948     DoCapConfigSetParameters(aParameters, aNumElements, aRetKVP);
7949 }
7950 
7951 
setParametersAsync(PvmiMIOSession aSession,PvmiKvp * aParameters,int aNumElements,PvmiKvp * & aRetKVP,OsclAny * aContext)7952 PVMFCommandId PVMFOMXEncNode::setParametersAsync(PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements, PvmiKvp*& aRetKVP, OsclAny* aContext)
7953 {
7954     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::setParametersAsync()", iNodeTypeId));
7955     OSCL_UNUSED_ARG(aSession);
7956     OSCL_UNUSED_ARG(aParameters);
7957     OSCL_UNUSED_ARG(aNumElements);
7958     OSCL_UNUSED_ARG(aRetKVP);
7959     OSCL_UNUSED_ARG(aContext);
7960 
7961     // This method is not supported so leave
7962     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::setParametersAsync() is not supported!", iNodeTypeId));
7963     OSCL_LEAVE(PVMFErrNotSupported);
7964     return 0;
7965 }
7966 
7967 
getCapabilityMetric(PvmiMIOSession aSession)7968 uint32 PVMFOMXEncNode::getCapabilityMetric(PvmiMIOSession aSession)
7969 {
7970     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::getCapabilityMetric()", iNodeTypeId));
7971     OSCL_UNUSED_ARG(aSession);
7972     // Not supported so return 0
7973     return 0;
7974 }
7975 
7976 
verifyParametersSync(PvmiMIOSession aSession,PvmiKvp * aParameters,int aNumElements)7977 PVMFStatus PVMFOMXEncNode::verifyParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements)
7978 {
7979     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::verifyParametersSync()", iNodeTypeId));
7980     OSCL_UNUSED_ARG(aSession);
7981 
7982     return DoCapConfigVerifyParameters(aParameters, aNumElements);
7983 }
7984 
7985 
7986 /////////////////////////////////////////////////////////////////////////////
GetNumMetadataValues(PVMFMetadataList & aKeyList)7987 uint32 PVMFOMXEncNode::GetNumMetadataValues(PVMFMetadataList& aKeyList)
7988 {
7989     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::GetNumMetadataValues() called", iNodeTypeId));
7990 
7991     uint32 numkeys = aKeyList.size();
7992 
7993     if (numkeys <= 0)
7994     {
7995         // Don't do anything
7996         return 0;
7997     }
7998 
7999     // Count the number of value entries for the provided key list
8000     uint32 numvalentries = 0;
8001     PVMF_MPEGVideoProfileType aProfile;
8002     PVMF_MPEGVideoLevelType aLevel;
8003     for (uint32 lcv = 0; lcv < numkeys; lcv++)
8004     {
8005         if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_WIDTH_KEY) == 0) &&
8006                 iYUVWidth > 0)
8007         {
8008             // Video width
8009             ++numvalentries;
8010         }
8011         else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_HEIGHT_KEY) == 0) &&
8012                  iYUVHeight > 0)
8013         {
8014             // Video height
8015             ++numvalentries;
8016         }
8017         else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_PROFILE_KEY) == 0) &&
8018                  (GetProfileAndLevel(aProfile, aLevel) == PVMFSuccess))
8019 
8020         {
8021             // Video profile
8022             ++numvalentries;
8023         }
8024         else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_LEVEL_KEY) == 0) &&
8025                  (GetProfileAndLevel(aProfile, aLevel) == PVMFSuccess))
8026         {
8027             // Video level
8028             ++numvalentries;
8029         }
8030         else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY) == 0) &&
8031                  (iAvgBitrateValue > 0))
8032 
8033         {
8034             // Video average bitrate
8035             if (iAvgBitrateValue > 0)
8036                 ++numvalentries;
8037         }
8038         else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_FORMAT_KEY) == 0) &&
8039                  (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_WMV || ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_M4V || ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H2631998 || ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H2632000 || ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO || ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_MP4 || ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_RAW))
8040         {
8041             // Format
8042             ++numvalentries;
8043         }
8044     }
8045 
8046     return numvalentries;
8047 }
8048 
8049 /////////////////////////////////////////////////////////////////////////////
GetNodeMetadataKeys(PVMFSessionId aSessionId,PVMFMetadataList & aKeyList,uint32 starting_index,int32 max_entries,char * query_key,const OsclAny * aContext)8050 PVMFCommandId PVMFOMXEncNode::GetNodeMetadataKeys(PVMFSessionId aSessionId, PVMFMetadataList& aKeyList, uint32 starting_index, int32 max_entries, char* query_key, const OsclAny* aContext)
8051 {
8052     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNodeCommand::GetNodeMetadataKeys() called", iNodeTypeId));
8053 
8054     PVMFOMXEncNodeCommand cmd;
8055     cmd.PVMFOMXEncNodeCommand::Construct(aSessionId, PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_GETNODEMETADATAKEY, &aKeyList, starting_index, max_entries, query_key, aContext);
8056     return QueueCommandL(cmd);
8057 }
8058 
8059 /////////////////////////////////////////////////////////////////////////////
GetNodeMetadataValues(PVMFSessionId aSessionId,PVMFMetadataList & aKeyList,Oscl_Vector<PvmiKvp,OsclMemAllocator> & aValueList,uint32 starting_index,int32 max_entries,const OsclAny * aContext)8060 PVMFCommandId PVMFOMXEncNode::GetNodeMetadataValues(PVMFSessionId aSessionId, PVMFMetadataList& aKeyList, Oscl_Vector<PvmiKvp, OsclMemAllocator>& aValueList, uint32 starting_index, int32 max_entries, const OsclAny* aContext)
8061 {
8062     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNodeCommand::GetNodeMetadataValue() called", iNodeTypeId));
8063 
8064     PVMFOMXEncNodeCommand cmd;
8065     cmd.PVMFOMXEncNodeCommand::Construct(aSessionId, PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_GETNODEMETADATAVALUE, &aKeyList, &aValueList, starting_index, max_entries, aContext);
8066     return QueueCommandL(cmd);
8067 }
8068 
8069 // From PVMFMetadataExtensionInterface
8070 /////////////////////////////////////////////////////////////////////////////
ReleaseNodeMetadataKeys(PVMFMetadataList &,uint32,uint32)8071 PVMFStatus PVMFOMXEncNode::ReleaseNodeMetadataKeys(PVMFMetadataList& , uint32 , uint32)
8072 {
8073     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::ReleaseNodeMetadataKeys() called", iNodeTypeId));
8074     //nothing needed-- there's no dynamic allocation in this node's key list
8075     return PVMFSuccess;
8076 }
8077 
8078 // From PVMFMetadataExtensionInterface
8079 /////////////////////////////////////////////////////////////////////////////
ReleaseNodeMetadataValues(Oscl_Vector<PvmiKvp,OsclMemAllocator> & aValueList,uint32 start,uint32 end)8080 PVMFStatus PVMFOMXEncNode::ReleaseNodeMetadataValues(Oscl_Vector<PvmiKvp, OsclMemAllocator>& aValueList, uint32 start, uint32 end)
8081 {
8082     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::ReleaseNodeMetadataValues() called", iNodeTypeId));
8083 
8084     if (aValueList.size() == 0 || start > end)
8085     {
8086         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::ReleaseNodeMetadataValues() Invalid start/end index", iNodeTypeId));
8087         return PVMFErrArgument;
8088     }
8089 
8090     if (end >= aValueList.size())
8091     {
8092         end = aValueList.size() - 1;
8093     }
8094 
8095     for (uint32 i = start; i <= end; i++)
8096     {
8097         if (aValueList[i].key != NULL)
8098         {
8099             switch (GetValTypeFromKeyString(aValueList[i].key))
8100             {
8101                 case PVMI_KVPVALTYPE_CHARPTR:
8102                     if (aValueList[i].value.pChar_value != NULL)
8103                     {
8104                         OSCL_ARRAY_DELETE(aValueList[i].value.pChar_value);
8105                         aValueList[i].value.pChar_value = NULL;
8106                     }
8107                     break;
8108 
8109                 case PVMI_KVPVALTYPE_UINT32:
8110                 case PVMI_KVPVALTYPE_UINT8:
8111                     // No memory to free for these valtypes
8112                     break;
8113 
8114                 default:
8115                     // Should not get a value that wasn't created from here
8116                     break;
8117             }
8118 
8119             OSCL_ARRAY_DELETE(aValueList[i].key);
8120             aValueList[i].key = NULL;
8121         }
8122     }
8123 
8124     return PVMFSuccess;
8125 }
8126 
8127 
8128 
8129 
8130 
8131 
GetProfileAndLevel(PVMF_MPEGVideoProfileType & aProfile,PVMF_MPEGVideoLevelType & aLevel)8132 PVMFStatus PVMFOMXEncNode::GetProfileAndLevel(PVMF_MPEGVideoProfileType& aProfile, PVMF_MPEGVideoLevelType& aLevel)
8133 {
8134 
8135     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::GetProfileAndLevel() In", iNodeTypeId));
8136 
8137     if (NULL == iOMXEncoder)
8138     {
8139         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::GetProfileAndLevel() iEncoder is Null", iNodeTypeId));
8140         aProfile = PV_MPEG_VIDEO_RESERVED_PROFILE;
8141         aLevel  = PV_MPEG_VIDEO_LEVEL_UNKNOWN;
8142         return PVMFFailure;
8143     }
8144 
8145     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::GetProfileAndLevel() iEncoder is Null", iNodeTypeId));
8146     aProfile = PV_MPEG_VIDEO_RESERVED_PROFILE;
8147     aLevel  = PV_MPEG_VIDEO_LEVEL_UNKNOWN;
8148     // DV: FOR NOW, JUST RETURN FAILURE, WE DON'T SUPPORT THIS FEATURE YET
8149     return PVMFFailure;
8150 
8151 
8152 }
8153 
8154 
8155 /////////////////////////////////////////////////////////////////////////////
LogDiagnostics()8156 void PVMFOMXEncNode::LogDiagnostics()
8157 {
8158     if (iDiagnosticsLogged == false)
8159     {
8160         iDiagnosticsLogged = true;
8161         PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO, (0, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"));
8162         PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO, (0, "PVMFOMXEncNode-%s - Number of Media Msgs Sent = %d", iNodeTypeId, iSeqNum));
8163         PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO, (0, "PVMFOMXEncNode-%s - TS of last encoded msg = %d", iNodeTypeId, iTimeStampOut));
8164     }
8165 }
8166 
8167 
8168 
8169 //////////////////////////////////
8170 /////EXTENSION INTERFACE
8171 ////////////////////////////////////
8172 ////////////////////////////////////////////////////////////////////////////
SetNumLayers(uint32 aNumLayers)8173 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetNumLayers(uint32 aNumLayers)
8174 {
8175     switch (iInterfaceState)
8176     {
8177         case EPVMFNodeStarted:
8178         case EPVMFNodePaused:
8179             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8180                             (0, "PVMFOMXEncNode-%s::SetNumLayers: Error iInterfaceState=%d", iNodeTypeId, iInterfaceState));
8181             return false;
8182 
8183         default:
8184             break;
8185     }
8186 
8187     if (aNumLayers > MAX_LAYER)
8188     {
8189         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8190                         (0, "PVMFOMXEncNode-%s::SetNumLayers: Error Max num layers is %d", iNodeTypeId, MAX_LAYER));
8191         return false;
8192     }
8193 
8194     iVideoEncodeParam.iNumLayer = aNumLayers;
8195     return true;
8196 }
8197 
8198 ////////////////////////////////////////////////////////////////////////////
SetOutputBitRate(uint32 aLayer,uint32 aBitRate)8199 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetOutputBitRate(uint32 aLayer, uint32 aBitRate)
8200 {
8201     switch (iInterfaceState)
8202     {
8203         case EPVMFNodeStarted:
8204         case EPVMFNodePaused:
8205             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::SetOutputBitRate: Error iInterfaceState=%d", iInterfaceState));
8206             return false;
8207 
8208         default:
8209             break;
8210     }
8211 
8212     if ((int32)aLayer >= iVideoEncodeParam.iNumLayer)
8213     {
8214         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8215                         (0, "PVMFOMXEncNode-%s::SetOutputBitRate: Error Invalid layer number", iNodeTypeId));
8216         return false;
8217     }
8218 
8219     iVideoEncodeParam.iBitRate[aLayer] = aBitRate;
8220     return true;
8221 }
8222 
8223 ////////////////////////////////////////////////////////////////////////////
SetOutputFrameSize(uint32 aLayer,uint32 aWidth,uint32 aHeight)8224 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetOutputFrameSize(uint32 aLayer, uint32 aWidth, uint32 aHeight)
8225 {
8226     switch (iInterfaceState)
8227     {
8228         case EPVMFNodeStarted:
8229         case EPVMFNodePaused:
8230             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8231                             (0, "PVMFOMXEncNode-%s::SetOutputFrameSize: Error iInterfaceState=%d", iNodeTypeId, iInterfaceState));
8232             return false;
8233 
8234         default:
8235             break;
8236     }
8237 
8238     if ((int32)aLayer >= iVideoEncodeParam.iNumLayer)
8239     {
8240         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8241                         (0, "PVMFOMXEncNode-%s::SetOutputFrameSize: Error Invalid layer number", iNodeTypeId));
8242         return false;
8243     }
8244 
8245     iVideoEncodeParam.iFrameWidth[aLayer] = aWidth;
8246     iVideoEncodeParam.iFrameHeight[aLayer] = aHeight;
8247     return true;
8248 }
8249 
8250 ////////////////////////////////////////////////////////////////////////////
SetOutputFrameRate(uint32 aLayer,OsclFloat aFrameRate)8251 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetOutputFrameRate(uint32 aLayer, OsclFloat aFrameRate)
8252 {
8253     switch (iInterfaceState)
8254     {
8255         case EPVMFNodeStarted:
8256         case EPVMFNodePaused:
8257             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8258                             (0, "PVMFOMXEncNode-%s::SetOutputFrameRate: Error iInterfaceState=%d", iInterfaceState));
8259             return false;
8260 
8261         default:
8262             break;
8263     }
8264 
8265     if ((int32)aLayer >= iVideoEncodeParam.iNumLayer)
8266     {
8267         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8268                         (0, "PVMFOMXEncNode-%s::SetOutputFrameRate: Error Invalid layer number", iNodeTypeId));
8269         return false;
8270     }
8271 
8272     iVideoEncodeParam.iFrameRate[aLayer] = OSCL_STATIC_CAST(float, aFrameRate);
8273     return true;
8274 }
8275 
8276 ////////////////////////////////////////////////////////////////////////////
SetSegmentTargetSize(uint32 aLayer,uint32 aSizeBytes)8277 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetSegmentTargetSize(uint32 aLayer, uint32 aSizeBytes)
8278 {
8279     OSCL_UNUSED_ARG(aLayer);
8280 
8281     switch (iInterfaceState)
8282     {
8283         case EPVMFNodeStarted:
8284         case EPVMFNodePaused:
8285             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8286                             (0, "PVMFOMXEncNode-%s::SetSegmentTargetSize: Error iInterfaceState=%d", iNodeTypeId, iInterfaceState));
8287             return false;
8288 
8289         default:
8290             break;
8291     }
8292 
8293     iVideoEncodeParam.iPacketSize = aSizeBytes;
8294     return true;
8295 }
8296 
8297 ////////////////////////////////////////////////////////////////////////////
SetRateControlType(uint32 aLayer,PVMFVENRateControlType aRateControl)8298 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetRateControlType(uint32 aLayer, PVMFVENRateControlType aRateControl)
8299 {
8300     OSCL_UNUSED_ARG(aLayer);
8301 
8302     switch (iInterfaceState)
8303     {
8304         case EPVMFNodeStarted:
8305         case EPVMFNodePaused:
8306             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8307                             (0, "PVMFOMXEncNode-%s::SetRateControlType: Error iInterfaceState=%d", iNodeTypeId, iInterfaceState));
8308             return false;
8309 
8310         default:
8311             break;
8312     }
8313 
8314     iVideoEncodeParam.iRateControlType = aRateControl;
8315     return true;
8316 }
8317 
8318 ////////////////////////////////////////////////////////////////////////////
SetDataPartitioning(bool aDataPartitioning)8319 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetDataPartitioning(bool aDataPartitioning)
8320 {
8321     switch (iInterfaceState)
8322     {
8323         case EPVMFNodeStarted:
8324         case EPVMFNodePaused:
8325             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8326                             (0, "PVMFOMXEncNode-%s::SetDataPartitioning: Error iInterfaceState=%d", iNodeTypeId, iInterfaceState));
8327             return false;
8328 
8329         default:
8330             break;
8331     }
8332 
8333     iVideoEncodeParam.iDataPartitioning = aDataPartitioning;
8334 
8335     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
8336                     (0, "PVMFOMXEncNode-%s::SetDataPartitioning Called", iNodeTypeId));
8337 
8338     return true;
8339 }
8340 
8341 ////////////////////////////////////////////////////////////////////////////
SetIFrameInterval(uint32 aIFrameInterval)8342 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetIFrameInterval(uint32 aIFrameInterval)
8343 {
8344     switch (iInterfaceState)
8345     {
8346         case EPVMFNodeStarted:
8347         case EPVMFNodePaused:
8348             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8349                             (0, "PVMFOMXEncNode-%s::SetIFrameInterval: Error iInterfaceState=%d", iNodeTypeId, iInterfaceState));
8350             return false;
8351 
8352         default:
8353             break;
8354     }
8355 
8356     iVideoEncodeParam.iIFrameInterval = aIFrameInterval;
8357     return true;
8358 }
8359 ////////////////////////////////////////////////////////////////////////////
SetSceneDetection(bool aSCD)8360 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetSceneDetection(bool aSCD)
8361 {
8362     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
8363                     (0, "PVMFOMXEncNode-%s::SetSceneDetection to %d", iNodeTypeId, aSCD));
8364 
8365 
8366     switch (iInterfaceState)
8367     {
8368         case EPVMFNodeStarted:
8369         case EPVMFNodePaused:
8370             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8371                             (0, "PVMFOMXEncEncNode-%s::SetIFrameInterval: Error iInterfaceState=%d", iNodeTypeId, iInterfaceState));
8372             return false;
8373 
8374         default:
8375             break;
8376     }
8377 
8378     iVideoEncodeParam.iSceneDetection = aSCD;
8379 
8380     return true;
8381 }
8382 ////////////////////////////////////////////////////////////////////////////
SetRVLC(bool aRVLC)8383 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetRVLC(bool aRVLC)
8384 {
8385 
8386     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
8387                     (0, "PVMFOMXEncNode-%s::SetRVLC", iNodeTypeId));
8388 
8389     switch (iInterfaceState)
8390     {
8391         case EPVMFNodeStarted:
8392         case EPVMFNodePaused:
8393             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8394                             (0, "PVMFOMXEncEncNode-%s::SetRVLC: Error iInterfaceState=%d", iNodeTypeId, iInterfaceState));
8395             return false;
8396 
8397         default:
8398             break;
8399     }
8400 
8401     iVideoEncodeParam.iRVLCEnable = aRVLC;
8402 
8403     return true;
8404 }
8405 
8406 ////////////////////////////////////////////////////////////////////////////
GetVolHeader(OsclRefCounterMemFrag & aVolHeader)8407 OSCL_EXPORT_REF bool PVMFOMXEncNode::GetVolHeader(OsclRefCounterMemFrag& aVolHeader)
8408 {
8409     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
8410                     (0, "PVMFOMXEncNode-%s::GetVolHeader", iNodeTypeId));
8411 
8412 #ifdef _TEST_AE_ERROR_HANDLING
8413     if (iErrorConfigHeader)
8414     {
8415         iInterfaceState = EPVMFNodeError;
8416     }
8417 #endif
8418     switch (iInterfaceState)
8419     {
8420         case EPVMFNodeInitialized:
8421         case EPVMFNodePrepared:
8422         case EPVMFNodeStarted:
8423         case EPVMFNodePaused:
8424             break;
8425 
8426         default:
8427             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8428                             (0, "PVMFOMXEncNode-%s::GetVolHeader: Error - Wrong state", iNodeTypeId));
8429             return false;
8430     }
8431 
8432     if (iOutFormat != PVMF_MIME_M4V)
8433     {
8434         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8435                         (0, "PVMFOMXEncNode-%s::GetVolHeader: Error - VOL header only for M4V encode", iNodeTypeId));
8436         return false;
8437     }
8438 
8439     uint8 *ptr = (uint8 *) iVolHeader.getMemFragPtr();
8440     //If data partioning mode
8441     if (iVideoEncodeParam.iDataPartitioning == true)
8442     {
8443         ptr[iVolHeader.getMemFragSize() - 1] = 0x8F;
8444     }
8445     //else combined mode
8446     else
8447     {
8448         ptr[iVolHeader.getMemFragSize() - 1] = 0x1F;
8449     }
8450 
8451     aVolHeader = iVolHeader;
8452 
8453     return true;
8454 }
8455 
8456 ////////////////////////////////////////////////////////////////////////////
RequestIFrame()8457 OSCL_EXPORT_REF bool PVMFOMXEncNode::RequestIFrame()
8458 {
8459     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
8460                     (0, "PVMFOMXEncNode-%s::RequestIFrame", iNodeTypeId));
8461 
8462     switch (iInterfaceState)
8463     {
8464         case EPVMFNodeStarted:
8465         case EPVMFNodePaused:
8466             break;
8467         default:
8468             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8469                             (0, "PVMFOMXEncNode-%s::RequestIFrame: Error - Wrong state", iNodeTypeId));
8470             return false;
8471     }
8472 
8473     return true;
8474 }
8475 
8476 ////////////////////////////////////////////////////////////////////////////
SetCodec(PVMFFormatType aCodec)8477 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetCodec(PVMFFormatType aCodec)
8478 {
8479     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
8480                     (0, "PVMFOMXEncNode-%s::SetCodec %s", iNodeTypeId, aCodec.getMIMEStrPtr()));
8481 
8482     if (SetCodecType(aCodec) == PVMFSuccess)
8483     {
8484         return true;
8485     }
8486     else
8487     {
8488         return false;
8489     }
8490 
8491 }
8492 
8493 
8494 
SetCodecType(PVMFFormatType aCodec)8495 PVMFStatus PVMFOMXEncNode::SetCodecType(PVMFFormatType aCodec)
8496 {
8497     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
8498                     (0, "PVMFOMXEncNode-%s::SetCodecType: aCodec=%s", iNodeTypeId, aCodec.getMIMEStrPtr()));
8499 
8500     switch (iInterfaceState)
8501     {
8502         case EPVMFNodeStarted:
8503         case EPVMFNodePaused:
8504             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8505                             (0, "PVMFOMXEncNode-%s::SetCodecType: Error iInterfaceState=%d", iNodeTypeId, iInterfaceState));
8506 
8507             return PVMFErrInvalidState;
8508         default:
8509             break;
8510     }
8511 
8512     if (aCodec == PVMF_MIME_H2631998)
8513     {
8514         iOutFormat = PVMF_MIME_H2631998;
8515     }
8516     else if (aCodec == PVMF_MIME_H2632000)
8517     {
8518         iOutFormat = PVMF_MIME_H2632000;
8519     }
8520     else if (aCodec == PVMF_MIME_M4V)
8521     {
8522         iOutFormat = PVMF_MIME_M4V;
8523     }
8524     else if (aCodec == PVMF_MIME_H264_VIDEO_RAW ||
8525              aCodec == PVMF_MIME_H264_VIDEO_MP4)
8526     {
8527         iOutFormat = aCodec;
8528     }
8529     else if (aCodec == PVMF_MIME_AMR_IETF ||
8530              aCodec == PVMF_MIME_AMR_IF2 ||
8531              aCodec == PVMF_MIME_AMRWB_IETF)
8532     {
8533         iOutFormat = aCodec;
8534     }
8535     else if (aCodec == PVMF_MIME_ADTS ||
8536              aCodec == PVMF_MIME_ADIF ||
8537              aCodec == PVMF_MIME_MPEG4_AUDIO)
8538     {
8539         iOutFormat = aCodec;
8540     }
8541     else
8542     {
8543         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
8544                         (0, "PVMFOMXEncNode-%s::SetCodecType: ERROR Unsupported format aCodec=%s", iNodeTypeId, aCodec.getMIMEStrPtr()));
8545 
8546         return PVMFErrNotSupported;
8547     }
8548 
8549     return PVMFSuccess;
8550 }
8551 
8552 ////////////////////////////////////////////////////////////////////////////
SetFSIParam(uint8 * aFSIBuff,int aFSIBuffLength)8553 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetFSIParam(uint8* aFSIBuff, int aFSIBuffLength)
8554 {
8555 
8556 
8557     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8558                     (0, "PVMFOMXEncNode-%s::SetFSIParam: Error- NOT IMPLEMENTED", iNodeTypeId));
8559     OSCL_UNUSED_ARG(aFSIBuff);
8560     OSCL_UNUSED_ARG(aFSIBuffLength);
8561 
8562     return true;
8563 }
8564 
8565 
8566 
8567 // The input format methods are called from the port
8568 ////////////////////////////////////////////////////////////////////////////
SetInputFormat(PVMFFormatType aFormat)8569 PVMFStatus PVMFOMXEncNode::SetInputFormat(PVMFFormatType aFormat)
8570 {
8571     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
8572                     (0, "PVMFOMXEncNode-%s::SetInputFormat: aFormat=%s", iNodeTypeId, aFormat.getMIMEStrPtr()));
8573 
8574     switch (iInterfaceState)
8575     {
8576         case EPVMFNodeStarted:
8577         case EPVMFNodePaused:
8578             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8579                             (0, "PVMFOMXEncNode-%s::SetInputFormat: Error - iInterfaceState=%d", iNodeTypeId, iInterfaceState));
8580             return PVMFErrInvalidState;
8581         default:
8582             break;
8583     }
8584 
8585     iInFormat = aFormat;
8586 
8587     if (aFormat == PVMF_MIME_YUV420)
8588     {
8589         iVideoInputFormat.iVideoFormat = EI_YUV420;
8590     }
8591     else if (aFormat == PVMF_MIME_YUV422)
8592     {
8593         iVideoInputFormat.iVideoFormat = EI_UYVY;
8594     }
8595     else if (aFormat == PVMF_MIME_RGB24)
8596     {
8597         iVideoInputFormat.iVideoFormat = EI_RGB24;
8598     }
8599     else if (aFormat == PVMF_MIME_RGB12)
8600     {
8601         iVideoInputFormat.iVideoFormat = EI_RGB12;
8602     }
8603     else if (aFormat == PVMF_MIME_PCM16)
8604     {
8605         // nothing to do here, but don't fail
8606     }
8607     else
8608     {
8609         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8610                         (0, "PVMFOMXEncNode-%s::SetInputFormat: Error - Unsupported format", iNodeTypeId));
8611         return PVMFFailure;
8612     }
8613 
8614     return PVMFSuccess;
8615 }
8616 
8617 ////////////////////////////////////////////////////////////////////////////
SetInputFrameSize(uint32 aWidth,uint32 aHeight,uint8 aFrmOrient)8618 PVMFStatus PVMFOMXEncNode::SetInputFrameSize(uint32 aWidth, uint32 aHeight, uint8 aFrmOrient)
8619 {
8620     switch (iInterfaceState)
8621     {
8622         case EPVMFNodeStarted:
8623         case EPVMFNodePaused:
8624             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8625                             (0, "PVMFOMXEncNode-%s::SetInputFrameSize: Error iInterfaceState=%d", iNodeTypeId, iInterfaceState));
8626             return false;
8627         default:
8628             break;
8629     }
8630 
8631     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
8632                     (0, "PVMFOMXEncNode-%s::SetInputFrameSize: aWidth=%d, aHeight=%d, aFrmOrient=%d", iNodeTypeId, aWidth, aHeight, aFrmOrient));
8633 
8634     iVideoInputFormat.iFrameWidth = aWidth;
8635     iVideoInputFormat.iFrameHeight = aHeight;
8636     iVideoInputFormat.iFrameOrientation = aFrmOrient;
8637     return true;
8638 }
8639 
8640 ////////////////////////////////////////////////////////////////////////////
SetInputFrameRate(OsclFloat aFrameRate)8641 PVMFStatus PVMFOMXEncNode::SetInputFrameRate(OsclFloat aFrameRate)
8642 {
8643     switch (iInterfaceState)
8644     {
8645         case EPVMFNodeStarted:
8646         case EPVMFNodePaused:
8647             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8648                             (0, "PVMFOMXEncNode-%s::SetInputFrameRate: Error iInterfaceState=%d", iNodeTypeId, iInterfaceState));
8649             return false;
8650         default:
8651             break;
8652     }
8653 
8654     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
8655                     (0, "PVMFOMXEncNode-%s::SetInputFrameRate: aFrameRate=%d", iNodeTypeId, aFrameRate));
8656 
8657     iVideoInputFormat.iFrameRate = OSCL_STATIC_CAST(float, aFrameRate);
8658     iVideoEncodeParam.iNoFrameSkip = iVideoEncodeParam.iNoCurrentSkip = false;
8659     return true;
8660 }
8661 
8662 ////////////////////////////////////////////////////////////////////////////
GetCodecType()8663 PVMFFormatType PVMFOMXEncNode::GetCodecType()
8664 {
8665     return iOutFormat;
8666 }
8667 
8668 ////////////////////////////////////////////////////////////////////////////
8669 // DV: Note - for video - there is an uint32 arg
GetOutputBitRate(uint32 aLayer)8670 uint32 PVMFOMXEncNode::GetOutputBitRate(uint32 aLayer)
8671 {
8672     if ((int32)aLayer >= iVideoEncodeParam.iNumLayer)
8673     {
8674         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8675                         (0, "PVMFOMXEncNode-%s::GetOutputBitRate: Error - Invalid layer number", iNodeTypeId));
8676         return 0;
8677     }
8678 
8679     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
8680                     (0, "PVMFOMXEncNode-%s::GetOutputBitRate: =%d", iNodeTypeId, iVideoEncodeParam.iBitRate[aLayer]));
8681 
8682     return iVideoEncodeParam.iBitRate[aLayer];
8683 }
8684 
8685 ////////////////////////////////////////////////////////////////////////////
GetOutputFrameRate(uint32 aLayer)8686 OsclFloat PVMFOMXEncNode::GetOutputFrameRate(uint32 aLayer)
8687 {
8688     if ((int32)aLayer >= iVideoEncodeParam.iNumLayer)
8689     {
8690         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8691                         (0, "PVMFOMXEncNode-%s::GetOutputFrameRate: Error Invalid layer number", iNodeTypeId));
8692         return 0;
8693     }
8694 
8695     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
8696                     (0, "PVMFOMXEncNode-%s::GetOutputFrameRate: =%f", iNodeTypeId, (OsclFloat) iVideoEncodeParam.iFrameRate[aLayer]));
8697 
8698     return (OsclFloat)iVideoEncodeParam.iFrameRate[aLayer];
8699 }
8700 
8701 ////////////////////////////////////////////////////////////////////////////
GetOutputFrameSize(uint32 aLayer,uint32 & aWidth,uint32 & aHeight)8702 PVMFStatus PVMFOMXEncNode::GetOutputFrameSize(uint32 aLayer, uint32& aWidth, uint32& aHeight)
8703 {
8704     if ((int32)aLayer >= iVideoEncodeParam.iNumLayer)
8705     {
8706         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
8707                         (0, "PVMFOMXEncNode-%s::GetOutputFrameSize: Error Invalid layer number", iNodeTypeId));
8708         return PVMFFailure;
8709     }
8710 
8711     aWidth = iVideoEncodeParam.iFrameWidth[aLayer];
8712     aHeight = iVideoEncodeParam.iFrameHeight[aLayer];
8713     return PVMFSuccess;
8714 }
8715 
8716 ////////////////////////////////////////////////////////////////////////////
GetIFrameInterval()8717 uint32 PVMFOMXEncNode::GetIFrameInterval()
8718 {
8719     return iVideoEncodeParam.iIFrameInterval;
8720 }
8721 /////////////////////////////////////////////////////////////////////////////
8722 
GetOutputSamplingRate()8723 uint32 PVMFOMXEncNode::GetOutputSamplingRate()
8724 {
8725 
8726 
8727     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
8728                     (0, "PVMFOMXEncNode-%s::GetOutputSamplingRate: =%d", iNodeTypeId, iAudioEncodeParam.iOutputSamplingRate));
8729 
8730     return (uint32) iAudioEncodeParam.iOutputSamplingRate;
8731 }
8732 /////////////////////////////////////////////////////////////////////////////
8733 
GetOutputNumChannels()8734 uint32 PVMFOMXEncNode::GetOutputNumChannels()
8735 {
8736 
8737 
8738     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
8739                     (0, "PVMFOMXEncNode-%s::GetOutputNumChannels: =%d", iNodeTypeId, iAudioEncodeParam.iOutputNumChannels));
8740 
8741     return (uint32) iAudioEncodeParam.iOutputNumChannels;
8742 }
8743 
8744 /////////////////////////AMRENCInterfaceExtension //////////////////////////
SetOutputBitRate(PVMF_GSMAMR_Rate aBitRate)8745 OSCL_EXPORT_REF PVMFStatus PVMFOMXEncNode::SetOutputBitRate(PVMF_GSMAMR_Rate aBitRate)
8746 {
8747     // this particular API is used only for AMR (NB or WB)
8748     // do some error checking - make sure that NB (i.e. WB) bitrates correspond to NB (i.e. WB) codec
8749     if ((iOutFormat == PVMF_MIME_AMR_IF2) ||
8750             (iOutFormat == PVMF_MIME_AMR_IETF)
8751        )
8752     {
8753 
8754         switch (aBitRate)
8755         {
8756             case GSM_AMR_4_75:
8757             case GSM_AMR_5_15:
8758             case GSM_AMR_5_90:
8759             case GSM_AMR_6_70:
8760             case GSM_AMR_7_40:
8761             case GSM_AMR_7_95:
8762             case GSM_AMR_10_2:
8763             case GSM_AMR_12_2:
8764 
8765                 iAudioEncodeParam.iAMRBitrate = aBitRate;
8766 
8767                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
8768                                 (0, "PVMFOMXEncNode-%s::SetOutputBitRate() OK - %d", iNodeTypeId, aBitRate));
8769 
8770                 return PVMFSuccess;
8771 
8772             case GSM_AMR_6_60: // AMR WB bitrates start here
8773             case GSM_AMR_8_85:
8774             case GSM_AMR_12_65:
8775             case GSM_AMR_14_25:
8776             case GSM_AMR_15_85:
8777             case GSM_AMR_18_25:
8778             case GSM_AMR_19_85:
8779             case GSM_AMR_23_05:
8780             case GSM_AMR_23_85:
8781 
8782                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
8783                                 (0, "PVMFOMXEncNode-%s::SetOutputBitRate() failed - %d", iNodeTypeId, aBitRate));
8784 
8785                 return PVMFFailure;
8786 
8787             default:
8788 
8789                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
8790                                 (0, "PVMFOMXEncNode-%s::SetOutputBitRate() failed - %d", iNodeTypeId, aBitRate));
8791 
8792                 return PVMFFailure;
8793         }
8794     }
8795 
8796     if (iOutFormat == PVMF_MIME_AMRWB_IETF)
8797     {
8798         switch (aBitRate)
8799         {
8800             case GSM_AMR_4_75:
8801             case GSM_AMR_5_15:
8802             case GSM_AMR_5_90:
8803             case GSM_AMR_6_70:
8804             case GSM_AMR_7_40:
8805             case GSM_AMR_7_95:
8806             case GSM_AMR_10_2:
8807             case GSM_AMR_12_2:
8808 
8809                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
8810                                 (0, "PVMFOMXEncNode-%s::SetOutputBitRate() failed - %d", iNodeTypeId, aBitRate));
8811 
8812                 return PVMFFailure;
8813 
8814             case GSM_AMR_6_60: // AMR WB bitrates start here
8815             case GSM_AMR_8_85:
8816             case GSM_AMR_12_65:
8817             case GSM_AMR_14_25:
8818             case GSM_AMR_15_85:
8819             case GSM_AMR_18_25:
8820             case GSM_AMR_19_85:
8821             case GSM_AMR_23_05:
8822             case GSM_AMR_23_85:
8823 
8824                 iAudioEncodeParam.iAMRBitrate = aBitRate;
8825                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
8826                                 (0, "PVMFOMXEncNode-%s::SetOutputBitRate() OK - %d", iNodeTypeId, aBitRate));
8827 
8828                 return PVMFSuccess;
8829 
8830             default:
8831 
8832                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
8833                                 (0, "PVMFOMXEncNode-%s::SetOutputBitRate() failed - %d", iNodeTypeId, aBitRate));
8834 
8835                 return PVMFFailure;
8836         }
8837     }
8838 
8839     return PVMFSuccess;
8840 }
8841 
8842 ////////////////////////////////////////////////////////////////////////////
SetMaxNumOutputFramesPerBuffer(uint32 aNumOutputFrames)8843 OSCL_EXPORT_REF PVMFStatus PVMFOMXEncNode::SetMaxNumOutputFramesPerBuffer(uint32 aNumOutputFrames)
8844 {
8845     iAudioEncodeParam.iMaxNumOutputFramesPerBuffer = aNumOutputFrames;
8846     return PVMFSuccess;
8847 }
8848 
8849 ////////////////////////////////////////////////////////////////////////////
SetOutputBitRate(uint32 aBitRate)8850 OSCL_EXPORT_REF PVMFStatus PVMFOMXEncNode::SetOutputBitRate(uint32 aBitRate)
8851 {
8852     // this API is used for Non-AMR codecs
8853     iAudioEncodeParam.iOutputBitrate = aBitRate;
8854     return PVMFSuccess;
8855 }
8856 
8857 ////////////////////////////////////////////////////////////////////////////
SetOutputNumChannel(uint32 aNumChannels)8858 OSCL_EXPORT_REF PVMFStatus PVMFOMXEncNode::SetOutputNumChannel(uint32 aNumChannels)
8859 {
8860 
8861     iAudioEncodeParam.iOutputNumChannels = aNumChannels;
8862     return PVMFSuccess;
8863 }
8864 
8865 ////////////////////////////////////////////////////////////////////////////
SetOutputSamplingRate(uint32 aSamplingRate)8866 OSCL_EXPORT_REF PVMFStatus PVMFOMXEncNode::SetOutputSamplingRate(uint32 aSamplingRate)
8867 {
8868     iAudioEncodeParam.iOutputSamplingRate = aSamplingRate;
8869     return PVMFSuccess;
8870 }
8871 
8872 
8873 ////////////////////////////////////////////////////////////////////////////
SetInputSamplingRate(uint32 aSamplingRate)8874 PVMFStatus PVMFOMXEncNode::SetInputSamplingRate(uint32 aSamplingRate)
8875 {
8876     // do some error checking - make sure the input sampling rate is 8khz (i.e. 16khz) for AMRNB (i.e. WB)
8877     if (((iOutFormat == PVMF_MIME_AMR_IF2) ||
8878             (iOutFormat == PVMF_MIME_AMR_IETF)) &&
8879             (aSamplingRate != 8000)
8880        )
8881     {
8882         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
8883                         (0, "PVMFOMXEncNode-%s::SetInputBitsSamplingRate() failed - %d", iNodeTypeId, aSamplingRate));
8884 
8885         return PVMFFailure;
8886     }
8887 
8888     if ((iOutFormat == PVMF_MIME_AMRWB_IETF) && (aSamplingRate != 16000))
8889     {
8890         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
8891                         (0, "PVMFOMXEncNode-%s::SetInputBitsSamplingRate() failed - %d", iNodeTypeId, aSamplingRate));
8892 
8893         return PVMFFailure;
8894     }
8895 
8896     iAudioInputFormat.iInputSamplingRate = aSamplingRate;
8897 
8898     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
8899                     (0, "PVMFOMXEncNode-%s::SetInputBitsSamplingRate() OK setting OutputSamplingRate as well - %d", iNodeTypeId, aSamplingRate));
8900 
8901     // set output as well
8902     iAudioEncodeParam.iOutputSamplingRate = aSamplingRate;
8903     return PVMFSuccess;
8904 }
8905 
8906 ////////////////////////////////////////////////////////////////////////////
SetInputBitsPerSample(uint32 aBitsPerSample)8907 PVMFStatus PVMFOMXEncNode::SetInputBitsPerSample(uint32 aBitsPerSample)
8908 {
8909     if (aBitsPerSample != 16)
8910     {
8911         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
8912                         (0, "PVMFOMXEncNode-%s::SetInputBitsPerSample() failed - %d", iNodeTypeId, aBitsPerSample));
8913 
8914         return PVMFErrNotSupported;
8915     }
8916 
8917     iAudioInputFormat.iInputBitsPerSample = aBitsPerSample;
8918 
8919     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
8920                     (0, "PVMFOMXEncNode-%s::SetInputBitsPerSample() OK - %d", iNodeTypeId, aBitsPerSample));
8921 
8922     return PVMFSuccess;
8923 }
8924 
8925 
8926 ////////////////////////////////////////////////////////////////////////////
SetInputNumChannels(uint32 aNumChannels)8927 PVMFStatus PVMFOMXEncNode::SetInputNumChannels(uint32 aNumChannels)
8928 {
8929     // do some error checking - make sure the number of INPUT channels is 1 for AMR (NB or WB)
8930 
8931     if (((iOutFormat == PVMF_MIME_AMR_IF2) ||
8932             (iOutFormat == PVMF_MIME_AMR_IETF) ||
8933             (iOutFormat == PVMF_MIME_AMRWB_IETF)) &&
8934             (aNumChannels > 1)
8935        )
8936     {
8937         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
8938                         (0, "PVMFOMXEncNode-%s::SetInputNumChannels() failed - %d", iNodeTypeId, aNumChannels));
8939         return PVMFFailure;
8940     }
8941 
8942     iAudioInputFormat.iInputNumChannels = aNumChannels;
8943 
8944     //set output as well
8945     iAudioEncodeParam.iOutputNumChannels = aNumChannels;
8946     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
8947                     (0, "PVMFOMXEncNode-%s::SetInputNumChannels() OK - %d", iNodeTypeId, aNumChannels));
8948 
8949     return PVMFSuccess;
8950 }
8951 
8952 ////////////////////////////////////////////////////////////////////////////
GetOutputBitRate()8953 uint32 PVMFOMXEncNode::GetOutputBitRate()
8954 {
8955     if ((iOutFormat == PVMF_MIME_AMR_IF2) ||
8956             (iOutFormat == PVMF_MIME_AMR_IETF) ||
8957             (iOutFormat == PVMF_MIME_AMRWB_IETF)
8958        )
8959     {
8960 
8961         switch (iAudioEncodeParam.iAMRBitrate)
8962         {
8963             case GSM_AMR_4_75:
8964                 return 4750;
8965             case GSM_AMR_5_15:
8966                 return 5150;
8967             case GSM_AMR_5_90:
8968                 return 5900;
8969             case GSM_AMR_6_70:
8970                 return 6700;
8971             case GSM_AMR_7_40:
8972                 return 7400;
8973             case GSM_AMR_7_95:
8974                 return 7950;
8975             case GSM_AMR_10_2:
8976                 return 10200;
8977             case GSM_AMR_12_2:
8978                 return 12200;
8979             case GSM_AMR_6_60: // AMR WB bitrates start here
8980                 return 6600;
8981             case GSM_AMR_8_85:
8982                 return 8850;
8983             case GSM_AMR_12_65:
8984                 return 12650;
8985             case GSM_AMR_14_25:
8986                 return 14250;
8987             case GSM_AMR_15_85:
8988                 return 15850;
8989             case GSM_AMR_18_25:
8990                 return 18250;
8991             case GSM_AMR_19_85:
8992                 return 19850;
8993             case GSM_AMR_23_05:
8994                 return 23050;
8995             case GSM_AMR_23_85:
8996                 return 23850;
8997             default:
8998                 return 0;
8999         }
9000     }
9001     else
9002     {
9003         return iAudioEncodeParam.iOutputBitrate;
9004     }
9005 }
9006 
9007 
9008 ///////////////////////// FROM CAP CONFIG IN VIDEO ENC NODE ////////////////////
GetConfigParameter(PvmiKvp * & aParameters,int & aNumParamElements,int32 aIndex,PvmiKvpAttr aReqattr)9009 PVMFStatus PVMFOMXEncNode::GetConfigParameter(PvmiKvp*& aParameters, int& aNumParamElements, int32 aIndex, PvmiKvpAttr aReqattr)
9010 {
9011     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::GetConfigParameter() In", iNodeTypeId));
9012 
9013     aNumParamElements = 0;
9014 
9015     // Allocate memory for the KVP
9016     aParameters = (PvmiKvp*)oscl_malloc(sizeof(PvmiKvp));
9017     if (NULL == aParameters)
9018     {
9019         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::GetConfigParameter() Memory allocation for KVP failed", iNodeTypeId));
9020         return PVMFErrNoMemory;
9021     }
9022     oscl_memset(aParameters, 0, sizeof(PvmiKvp));
9023     // Allocate memory for the key string in KVP
9024     PvmiKeyType memblock = (PvmiKeyType)oscl_malloc(PVOMXENCNODECONFIG_KEYSTRING_SIZE * sizeof(char));
9025     if (NULL == memblock)
9026     {
9027         oscl_free(aParameters);
9028         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::GetConfigParameter() Memory allocation for key string failed", iNodeTypeId));
9029         return PVMFErrNoMemory;
9030     }
9031     oscl_strset(memblock, 0, PVOMXENCNODECONFIG_KEYSTRING_SIZE * sizeof(char));
9032     // Assign the key string buffer to KVP
9033     aParameters[0].key = memblock;
9034 
9035     // Copy the key string
9036     if (iInFormat == PVMF_MIME_PCM16)
9037     {
9038         // Copy the key string
9039         oscl_strncat(aParameters[0].key, _STRLIT_CHAR("x-pvmf/encoder/audio/"), 21);
9040         oscl_strncat(aParameters[0].key, PVOMXEncNodeConfigBaseKeys[aIndex].iString, oscl_strlen(PVOMXEncNodeConfigBaseKeys[aIndex].iString));
9041         oscl_strncat(aParameters[0].key, _STRLIT_CHAR(";type=value;valtype="), 20);
9042     }
9043     else
9044     {
9045         oscl_strncat(aParameters[0].key, _STRLIT_CHAR("x-pvmf/encoder/video/"), 21);
9046         oscl_strncat(aParameters[0].key, PVOMXEncNodeConfigBaseKeys[aIndex].iString, oscl_strlen(PVOMXEncNodeConfigBaseKeys[aIndex].iString));
9047         oscl_strncat(aParameters[0].key, _STRLIT_CHAR(";type=value;valtype="), 20);
9048     }
9049     switch (PVOMXEncNodeConfigBaseKeys[aIndex].iValueType)
9050     {
9051         case PVMI_KVPVALTYPE_BITARRAY32:
9052             oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_BITARRAY32_STRING), oscl_strlen(PVMI_KVPVALTYPE_BITARRAY32_STRING));
9053             break;
9054 
9055         case PVMI_KVPVALTYPE_KSV:
9056             oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_KSV_STRING), oscl_strlen(PVMI_KVPVALTYPE_KSV_STRING));
9057             break;
9058 
9059         case PVMI_KVPVALTYPE_BOOL:
9060             oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_BOOL_STRING), oscl_strlen(PVMI_KVPVALTYPE_BOOL_STRING));
9061             break;
9062 
9063         case PVMI_KVPVALTYPE_INT32:
9064             if (PVMI_KVPATTR_CUR == aReqattr)
9065             {
9066                 oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_INT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_RANGE_UINT32_STRING));
9067             }
9068             break;
9069         case PVMI_KVPVALTYPE_UINT32:
9070         default:
9071             if (PVMI_KVPATTR_CAP == aReqattr)
9072             {
9073                 oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_RANGE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_RANGE_UINT32_STRING));
9074             }
9075             else
9076             {
9077                 oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING));
9078             }
9079             break;
9080     }
9081     aParameters[0].key[PVOMXENCNODECONFIG_KEYSTRING_SIZE-1] = 0;
9082 
9083     // Copy the requested info
9084     switch (aIndex)
9085     {
9086 
9087         case SAMPLING_RATE: // "sampling_rate"
9088             if (PVMI_KVPATTR_CUR == aReqattr)
9089             {
9090                 // get the parameter here
9091                 aParameters[0].value.uint32_value = iAudioInputFormat.iInputSamplingRate;
9092 
9093             }
9094             else if (PVMI_KVPATTR_DEF == aReqattr)
9095             {
9096                 // Return default
9097                 aParameters[0].value.uint32_value = PVMF_AMRENC_DEFAULT_SAMPLING_RATE;
9098 
9099             }
9100             else
9101             {
9102                 // Return capability
9103             }
9104             break;
9105 
9106         case CHANNELS:  // "channels"
9107 
9108             if (PVMI_KVPATTR_CUR == aReqattr)
9109             {
9110                 // get the par
9111                 aParameters[0].value.uint32_value = iAudioInputFormat.iInputNumChannels;
9112             }
9113             else if (PVMI_KVPATTR_DEF == aReqattr)
9114             {
9115                 // Return default
9116                 aParameters[0].value.uint32_value = PVMF_AMRENC_DEFAULT_NUM_CHANNELS;
9117             }
9118             else
9119             {
9120                 // Return capability
9121             }
9122             break;
9123 
9124         case ENCODING_MODE: // "encoding_mode"
9125             if (PVMI_KVPATTR_CUR == aReqattr)
9126             {
9127                 // Return current value
9128                 aParameters[0].value.uint32_value = iVideoEncodeParam.iEncMode;
9129             }
9130             else if (PVMI_KVPATTR_DEF == aReqattr)
9131             {
9132                 // Return default
9133                 aParameters[0].value.uint32_value = EI_ENCMODE_RECORDER;//default setting
9134             }
9135             else
9136             {
9137                 // Return capability
9138             }
9139             break;
9140 
9141 #ifdef _TEST_AE_ERROR_HANDLING
9142         case ERROR_START_INIT://error_start_init
9143             if (PVMI_KVPATTR_CUR == aReqattr)
9144             {
9145                 // Return current value
9146                 aParameters[0].value.bool_value = iErrorHandlingInit;
9147             }
9148             else if (PVMI_KVPATTR_DEF == aReqattr)
9149             {
9150                 // Return default
9151                 aParameters[0].value.bool_value = true;
9152             }
9153             else
9154             {
9155                 // Return capability
9156             }
9157             break;
9158         case ERROR_ENCODE://error_encode
9159             if (PVMI_KVPATTR_CUR == aReqattr)
9160             {
9161                 // Return current value
9162                 aParameters[0].value.uint32_value = iErrorHandlingEncodeCount;
9163             }
9164             else if (PVMI_KVPATTR_DEF == aReqattr)
9165             {
9166                 // Return default
9167                 aParameters[0].value.uint32_value = 1;
9168             }
9169             else
9170             {
9171                 // Return capability
9172             }
9173             break;
9174 
9175 #endif
9176 
9177         default:
9178             // Invalid index
9179             oscl_free(aParameters[0].key);
9180             oscl_free(aParameters);
9181             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::GetConfigParameter() Invalid index to video enc node parameter", iNodeTypeId));
9182             return PVMFErrNotSupported;
9183     }
9184 
9185     aNumParamElements = 1;
9186 
9187     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::GetConfigParameter() Out", iNodeTypeId));
9188     return PVMFSuccess;
9189 }
9190 
VerifyAndSetConfigParameter(PvmiKvp & aParameter,bool aSetParam)9191 PVMFStatus PVMFOMXEncNode::VerifyAndSetConfigParameter(PvmiKvp& aParameter, bool aSetParam)
9192 {
9193     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::VerifyAndSetConfigParameter() In", iNodeTypeId));
9194 
9195     // Determine the valtype
9196     PvmiKvpValueType keyvaltype = GetValTypeFromKeyString(aParameter.key);
9197     if (PVMI_KVPVALTYPE_UNKNOWN == keyvaltype)
9198     {
9199         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::VerifyAndSetConfigParameter() Valtype in key string unknown", iNodeTypeId));
9200         return PVMFErrNotSupported;
9201     }
9202     // Retrieve the fourth component from the key string
9203     char* compstr = NULL;
9204     pv_mime_string_extract_type(3, aParameter.key, compstr);
9205 
9206     int32 enccomp4ind;
9207     for (enccomp4ind = 0; enccomp4ind < PVOMXENCNODECONFIG_BASE_NUMKEYS; ++enccomp4ind)
9208     {
9209         // Go through each component string at 4th level
9210         if (pv_mime_strcmp(compstr, (char*)(PVOMXEncNodeConfigBaseKeys[enccomp4ind].iString)) >= 0)
9211         {
9212             // Break out of the for loop
9213             break;
9214         }
9215     }
9216 
9217     if (PVOMXENCNODECONFIG_BASE_NUMKEYS <= enccomp4ind)
9218     {
9219         // Match couldn't be found or non-leaf node specified
9220         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::VerifyAndSetConfigParameter() Unsupported key or non-leaf node", iNodeTypeId));
9221         return PVMFErrNotSupported;
9222     }
9223 
9224     // Verify the valtype
9225     if (keyvaltype != PVOMXEncNodeConfigBaseKeys[enccomp4ind].iValueType)
9226     {
9227         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::VerifyAndSetConfigParameter() Valtype does not match for key", iNodeTypeId));
9228         return PVMFErrNotSupported;
9229     }
9230 
9231     switch (enccomp4ind)
9232     {
9233 
9234 
9235         case SAMPLING_RATE: // "sampling_rate"
9236             // Change the parameter
9237             if (aSetParam)
9238             {
9239                 // set the parameter here
9240                 iAudioInputFormat.iInputSamplingRate = aParameter.value.uint32_value;
9241                 iAudioEncodeParam.iOutputSamplingRate = aParameter.value.uint32_value;
9242             }
9243             break;
9244 
9245         case CHANNELS:  // "channels"
9246             // change the parameter
9247             if (aSetParam)
9248             {
9249                 // set the parameter here
9250                 iAudioInputFormat.iInputNumChannels = aParameter.value.uint32_value;
9251                 iAudioEncodeParam.iOutputNumChannels = aParameter.value.uint32_value;
9252             }
9253             break;
9254         case ENCODING_MODE: // "encoding_mode"
9255             // change the parameter
9256             if (aSetParam)
9257             {
9258                 iVideoEncodeParam.iEncMode = (EncEncodingMode)aParameter.value.uint32_value;
9259             }
9260             break;
9261 
9262 
9263 
9264 #ifdef _TEST_AE_ERROR_HANDLING
9265         case ERROR_START_INIT: // "error_start_init"
9266             // change the parameter
9267             if (aSetParam)
9268             {
9269                 iErrorHandlingInit = aParameter.value.bool_value;
9270             }
9271             break;
9272         case ERROR_ENCODE: // "error_avcencode"
9273             // change the parameter
9274             if (aSetParam)
9275             {
9276 
9277                 char* paramstr = NULL;
9278                 OSCL_HeapString<OsclMemAllocator> mode1 = "mode=duration";
9279                 OSCL_HeapString<OsclMemAllocator> mode2 = "mode=frames";
9280 
9281                 if (pv_mime_string_parse_param(aParameter.key, mode1.get_str(), paramstr) > 0)
9282                 {
9283                     iErrorEncodeFlag = 1;
9284                     iErrorHandlingEncodeCount = aParameter.value.uint32_value;
9285 
9286                 }
9287 
9288                 else if (pv_mime_string_parse_param(aParameter.key, mode2.get_str(), paramstr) > 0)
9289                 {
9290                     iErrorEncodeFlag = 2;
9291                     iErrorHandlingEncodeCount = aParameter.value.uint32_value;
9292 
9293                 }
9294             }
9295             break;
9296         case ERROR_NODE_CMD: //"error-node-cmd"
9297             if (aSetParam)
9298             {
9299                 iErrorNodeCmd = aParameter.value.uint32_value;
9300             }
9301             break;
9302         case ERROR_CONFIG_HEADER:
9303             if (aSetParam)
9304             {
9305                 iErrorConfigHeader = aParameter.value.bool_value;
9306             }
9307             break;
9308         case ERROR_DATAPATH_STALL:
9309             if (aSetParam)
9310             {
9311                 iErrorDataPathStall = aParameter.value.uint32_value;
9312             }
9313             break;
9314 #endif
9315 
9316         default:
9317             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::VerifyAndSetConfigParameter() Invalid index for video enc node parameter", iNodeTypeId));
9318             return PVMFErrNotSupported;
9319     }
9320 
9321     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::VerifyAndSetConfigParameter() Out", iNodeTypeId));
9322     return PVMFSuccess;
9323 }
9324 
9325 //void PVMFOMXEncNode::setParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements, PvmiKvp*& aRetKVP)
DoCapConfigSetParameters(PvmiKvp * aParameters,int aNumElements,PvmiKvp * & aRetKVP)9326 void PVMFOMXEncNode::DoCapConfigSetParameters(PvmiKvp* aParameters, int aNumElements, PvmiKvp*& aRetKVP)
9327 {
9328     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoCapConfigSetParameters()", iNodeTypeId));
9329     //OSCL_UNUSED_ARG(aSession);
9330 
9331     if (NULL == aParameters || aNumElements < 1)
9332     {
9333         if (aParameters)
9334         {
9335             aRetKVP = aParameters;
9336         }
9337         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigSetParameters() Passed in parameter invalid", iNodeTypeId));
9338         return;
9339     }
9340 
9341     // Go through each parameter
9342     for (int32 paramind = 0; paramind < aNumElements; ++paramind)
9343     {
9344         // Count the number of components and parameters in the key
9345         int compcount = pv_mime_string_compcnt(aParameters[paramind].key);
9346         // Retrieve the first component from the key string
9347         char* compstr = NULL;
9348         pv_mime_string_extract_type(0, aParameters[paramind].key, compstr);
9349 
9350 
9351         if ((
9352                     (pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/video")) < 0) &&
9353                     (pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/audio")) < 0)
9354                 ) || (compcount < 4))
9355         {
9356             // First 3 components should be "x-pvmf/encoder/video" or "x-pvmf/encoder/audio" and there must
9357             // be at least 4 components
9358             aRetKVP = &aParameters[paramind];
9359             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigSetParameters() Unsupported key", iNodeTypeId));
9360             return;
9361         }
9362 
9363         // check if audio parameters are asked from video enc instance or vice versa
9364         if (((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/video")) > 0) && (iInFormat == PVMF_MIME_PCM16)) ||
9365                 ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/audio")) > 0) && (iInFormat != PVMF_MIME_PCM16))
9366            )
9367         {
9368 
9369             aRetKVP = &aParameters[paramind];
9370             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigSetParameters() Unsupported key", iNodeTypeId));
9371             return;
9372         }
9373 
9374         if (4 == compcount)
9375         {
9376             // Verify and set the passed-in video enc node setting
9377             PVMFStatus retval = VerifyAndSetConfigParameter(aParameters[paramind], true);
9378             if (PVMFSuccess != retval)
9379             {
9380                 aRetKVP = &aParameters[paramind];
9381                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigSetParameters() Setting parameter %d failed", iNodeTypeId, paramind));
9382                 return;
9383             }
9384         }
9385 
9386         else
9387         {
9388             // Do not support more than 4 components right now
9389             aRetKVP = &aParameters[paramind];
9390             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigSetParameters() Unsupported key", iNodeTypeId));
9391             return;
9392         }
9393     }
9394     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoCapConfigSetParameters() Out", iNodeTypeId));
9395 }
9396 
9397 
9398 //PVMFStatus PVMFOMXEncNode::getParametersSync(PvmiMIOSession aSession, PvmiKeyType aIdentifier, PvmiKvp*& aParameters, int& aNumParamElements, PvmiCapabilityContext aContext)
DoCapConfigGetParametersSync(PvmiKeyType aIdentifier,PvmiKvp * & aParameters,int & aNumParamElements,PvmiCapabilityContext aContext)9399 PVMFStatus PVMFOMXEncNode::DoCapConfigGetParametersSync(PvmiKeyType aIdentifier, PvmiKvp*& aParameters, int& aNumParamElements, PvmiCapabilityContext aContext)
9400 {
9401     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoCapConfigGetParametersSync()", iNodeTypeId));
9402     //OSCL_UNUSED_ARG(aSession);
9403     OSCL_UNUSED_ARG(aContext);
9404 
9405     // Initialize the output parameters
9406     aNumParamElements = 0;
9407     aParameters = NULL;
9408 
9409     // Count the number of components and parameters in the key
9410     int compcount = pv_mime_string_compcnt(aIdentifier);
9411     // Retrieve the first component from the key string
9412     char* compstr = NULL;
9413     pv_mime_string_extract_type(0, aIdentifier, compstr);
9414 
9415     if ((
9416                 (pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/video")) < 0) &&
9417                 (pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/audio")) < 0)
9418             ) || (compcount < 4))
9419     {
9420         // First 3 components should be "x-pvmf/encoder/video" or  "x-pvmf/encoder/audio" and there must
9421         // be at least 4 components
9422         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigGetParametersSync() Invalid key string", iNodeTypeId));
9423         return PVMFErrNotSupported;
9424     }
9425 
9426     // check if audio parameters are asked from video enc instance or vice versa
9427     if (((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/video")) > 0) && (iInFormat == PVMF_MIME_PCM16)) ||
9428             ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/audio")) > 0) && (iInFormat != PVMF_MIME_PCM16))
9429        )
9430     {
9431         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigGetParameters() Unsupported key", iNodeTypeId));
9432         return PVMFErrNotSupported;
9433     }
9434 
9435     // Retrieve the fourth component from the key string
9436     pv_mime_string_extract_type(3, aIdentifier, compstr);
9437 
9438     for (int32 enccomp4ind = 0; enccomp4ind < PVOMXENCNODECONFIG_BASE_NUMKEYS; ++enccomp4ind)
9439     {
9440         // Go through each video enc component string at 4th level
9441         if (pv_mime_strcmp(compstr, (char*)(PVOMXEncNodeConfigBaseKeys[enccomp4ind].iString)) >= 0)
9442         {
9443             if (4 == compcount)
9444             {
9445                 // Determine what is requested
9446                 PvmiKvpAttr reqattr = GetAttrTypeFromKeyString(aIdentifier);
9447                 if (PVMI_KVPATTR_UNKNOWN == reqattr)
9448                 {
9449                     reqattr = PVMI_KVPATTR_CUR;
9450                 }
9451 
9452                 // Return the requested info
9453                 PVMFStatus retval = GetConfigParameter(aParameters, aNumParamElements, enccomp4ind, reqattr);
9454                 if (PVMFSuccess != retval)
9455                 {
9456                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigGetParametersSync() Retrieving video enc node parameter failed", iNodeTypeId));
9457                     return retval;
9458                 }
9459             }
9460             else
9461             {
9462                 // Right now videoenc node doesn't support more than 4 components
9463                 // for this sub-key string so error out
9464                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigGetParametersSync() Unsupported key", iNodeTypeId));
9465                 return PVMFErrNotSupported;
9466             }
9467         }
9468     }
9469 
9470     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoCapConfigGetParametersSync() Out", iNodeTypeId));
9471     if (aNumParamElements == 0)
9472     {
9473         // If no one could get the parameter, return error
9474         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigGetParametersSync() Unsupported key", iNodeTypeId));
9475         return PVMFFailure;
9476     }
9477     else
9478     {
9479         return PVMFSuccess;
9480     }
9481 }
9482 
9483 //PVMFStatus PVMFOMXEncNode::releaseParameters(PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements)
DoCapConfigReleaseParameters(PvmiKvp * aParameters,int aNumElements)9484 PVMFStatus PVMFOMXEncNode::DoCapConfigReleaseParameters(PvmiKvp* aParameters, int aNumElements)
9485 {
9486     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::releaseParameters()", iNodeTypeId));
9487     //OSCL_UNUSED_ARG(aSession);
9488 
9489     if (aParameters == NULL || aNumElements < 1)
9490     {
9491         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigReleaseParameters() KVP list is NULL or number of elements is 0", iNodeTypeId));
9492         return PVMFErrArgument;
9493     }
9494 
9495     // Count the number of components and parameters in the key
9496     int compcount = pv_mime_string_compcnt(aParameters[0].key);
9497     // Retrieve the first component from the key string
9498     char* compstr = NULL;
9499     pv_mime_string_extract_type(0, aParameters[0].key, compstr);
9500 
9501     if ((
9502                 (pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/video")) < 0) &&
9503                 (pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/audio")) < 0)
9504             ) || (compcount < 3))
9505     {
9506         // First 3 component should be "x-pvmf/encoder/video" or "x-pvmf/encoder/audio" and there must
9507         // be at least three components
9508         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigReleaseParameters() Unsupported key", iNodeTypeId));
9509         return PVMFErrNotSupported;
9510     }
9511 
9512     // check if audio parameters are asked from video enc instance or vice versa
9513     if (((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/video")) > 0) && (iInFormat == PVMF_MIME_PCM16)) ||
9514             ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/audio")) > 0) && (iInFormat != PVMF_MIME_PCM16))
9515        )
9516     {
9517         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigReleaseParameters() Unsupported key", iNodeTypeId));
9518         return PVMFErrNotSupported;
9519     }
9520 
9521     // Retrieve the third component from the key string
9522     pv_mime_string_extract_type(2, aParameters[0].key, compstr);
9523 
9524     // Go through each KVP and release memory for value if allocated from heap
9525     for (int32 ii = 0; ii < aNumElements; ++ii)
9526     {
9527         // Next check if it is a value type that allocated memory
9528         PvmiKvpType kvptype = GetTypeFromKeyString(aParameters[ii].key);
9529         if (PVMI_KVPTYPE_VALUE == kvptype || PVMI_KVPTYPE_UNKNOWN == kvptype)
9530         {
9531             PvmiKvpValueType keyvaltype = GetValTypeFromKeyString(aParameters[ii].key);
9532             if (PVMI_KVPVALTYPE_UNKNOWN == keyvaltype)
9533             {
9534                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigReleaseParameters() Valtype not specified in key string", iNodeTypeId));
9535                 return PVMFErrNotSupported;
9536             }
9537 
9538             if (PVMI_KVPVALTYPE_CHARPTR == keyvaltype && NULL != aParameters[ii].value.pChar_value)
9539             {
9540                 oscl_free(aParameters[ii].value.pChar_value);
9541                 aParameters[ii].value.pChar_value = NULL;
9542             }
9543             else if (keyvaltype == PVMI_KVPVALTYPE_KSV && NULL != aParameters[ii].value.key_specific_value)
9544             {
9545                 oscl_free(aParameters[ii].value.key_specific_value);
9546                 aParameters[ii].value.key_specific_value = NULL;
9547             }
9548             else if (PVMI_KVPVALTYPE_RANGE_UINT32 == keyvaltype && NULL != aParameters[ii].value.key_specific_value)
9549             {
9550                 range_uint32* rui32 = (range_uint32*)aParameters[ii].value.key_specific_value;
9551                 aParameters[ii].value.key_specific_value = NULL;
9552                 oscl_free(rui32);
9553             }
9554             // @TODO Add more types if video enc node starts returning more types
9555         }
9556     }
9557 
9558     // Video enc node allocated its key strings in one chunk so just free the first key string ptr
9559     oscl_free(aParameters[0].key);
9560 
9561     // Free memory for the parameter list
9562     oscl_free(aParameters);
9563     aParameters = NULL;
9564 
9565     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoCapConfigReleaseParameters() Out", iNodeTypeId));
9566     return PVMFSuccess;
9567 }
9568 
9569 
9570 //PVMFStatus PVMFOMXEncNode::verifyParametersSync (PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements)
DoCapConfigVerifyParameters(PvmiKvp * aParameters,int aNumElements)9571 PVMFStatus PVMFOMXEncNode::DoCapConfigVerifyParameters(PvmiKvp* aParameters, int aNumElements)
9572 {
9573     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoCapConfigVerifyParameters()", iNodeTypeId));
9574     //OSCL_UNUSED_ARG(aSession);
9575 
9576     if (NULL == aParameters || aNumElements < 1)
9577     {
9578         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigVerifyParameters() Passed in parameter invalid", iNodeTypeId));
9579         return PVMFErrArgument;
9580     }
9581 
9582     // Go through each parameter
9583     for (int32 paramind = 0; paramind < aNumElements; ++paramind)
9584     {
9585         // Count the number of components and parameters in the key
9586         int compcount = pv_mime_string_compcnt(aParameters[paramind].key);
9587         // Retrieve the first component from the key string
9588         char* compstr = NULL;
9589         pv_mime_string_extract_type(0, aParameters[paramind].key, compstr);
9590 
9591         if (
9592             ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/video")) < 0) &&
9593              (pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/audio")) < 0)
9594             ) || compcount < 3)
9595         {
9596             // First 3 components should be "x-pvmf/encoder/video" or
9597             // "x-pvmf/enoder/audio" and there must
9598             // be at least 3 components
9599 
9600             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigVerifyParameters() Unsupported key", iNodeTypeId));
9601             return PVMFErrNotSupported;
9602         }
9603 
9604         // check if audio parameters are asked from video enc instance or vice versa
9605         if (((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/video")) > 0) && (iInFormat == PVMF_MIME_PCM16)) ||
9606                 ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/audio")) > 0) && (iInFormat != PVMF_MIME_PCM16))
9607            )
9608         {
9609             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigVerifyParameters() Unsupported key", iNodeTypeId));
9610             return PVMFErrNotSupported;
9611         }
9612 
9613         if (4 == compcount)
9614         {
9615             // Verify and set the passed-in video enc node setting
9616             PVMFStatus retval = VerifyAndSetConfigParameter(aParameters[paramind], false);
9617             if (retval != PVMFSuccess)
9618             {
9619                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigVerifyParameters() Setting parameter %d failed", iNodeTypeId, paramind));
9620                 return retval;
9621             }
9622         }
9623         else
9624         {
9625             // Do not support more than 4 components right now
9626             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigVerifyParameters() Unsupported key", iNodeTypeId));
9627             return PVMFErrNotSupported;
9628         }
9629     }
9630 
9631     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoCapConfigVerifyParameters() Out", iNodeTypeId));
9632     return PVMFSuccess;
9633 
9634 }
9635 
PushBackKeyVal(Oscl_Vector<PvmiKvp,OsclMemAllocator> * & aValueListPtr,PvmiKvp & aKeyVal)9636 int32 PVMFOMXEncNode::PushBackKeyVal(Oscl_Vector<PvmiKvp, OsclMemAllocator>*& aValueListPtr, PvmiKvp &aKeyVal)
9637 {
9638     int32 leavecode = 0;
9639     OSCL_TRY(leavecode, (*aValueListPtr).push_back(aKeyVal));
9640     return leavecode;
9641 }
9642 
Push_Back_MetadataKeys(const char * aMetadataKey)9643 int32 PVMFOMXEncNode::Push_Back_MetadataKeys(const char* aMetadataKey)
9644 {
9645     int32 leavecode = 0;
9646     OSCL_TRY(leavecode, iAvailableMetadataKeys.push_back(aMetadataKey));
9647     return leavecode;
9648 }
9649 
Push_Back_MetadataKeys(PVMFMetadataList * & aKeylistptr,uint32 aLcv)9650 int32 PVMFOMXEncNode::Push_Back_MetadataKeys(PVMFMetadataList *&aKeylistptr, uint32 aLcv)
9651 {
9652     int32 leavecode = 0;
9653     OSCL_TRY(leavecode, aKeylistptr->push_back(iAvailableMetadataKeys[aLcv]));
9654     return leavecode;
9655 }
9656 
CreateNewArray(char * & aPtr,int32 aLen)9657 int32 PVMFOMXEncNode::CreateNewArray(char*& aPtr, int32 aLen)
9658 {
9659     int32 leavecode = 0;
9660     OSCL_TRY(leavecode,
9661              aPtr = OSCL_ARRAY_NEW(char, aLen););
9662     return leavecode;
9663 }
9664 
MemAllocate(OsclAny * & aPtr,OsclMemPoolFixedChunkAllocator * aMemPool,uint32 aAllocSize)9665 int32 PVMFOMXEncNode::MemAllocate(OsclAny *&aPtr, OsclMemPoolFixedChunkAllocator *aMemPool, uint32 aAllocSize)
9666 {
9667     uint32 errcode = 0;
9668     OSCL_TRY(errcode, aPtr = (OsclAny *) aMemPool->allocate(aAllocSize));
9669     return errcode;
9670 }
9671 
ParseFullAVCFramesIntoNALs(OMX_BUFFERHEADERTYPE * aOutputBuffer)9672 bool PVMFOMXEncNode::ParseFullAVCFramesIntoNALs(OMX_BUFFERHEADERTYPE* aOutputBuffer)
9673 {
9674     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVMFOMXEncNode-%s : ParseFullAVCFramesIntoNALs IN", iNodeTypeId));
9675 
9676     if (iOMXComponentUsesNALStartCodes && !(aOutputBuffer->nFlags & OMX_BUFFERFLAG_EXTRADATA))
9677     {
9678         OMX_U32 offset = aOutputBuffer->nOffset;
9679         OMX_U32 length = aOutputBuffer->nFilledLen;
9680         OMX_U8* pBuffer = aOutputBuffer->pBuffer + offset;
9681         OMX_U8* pCurrNAL;
9682         OMX_U32 bytesConsumed;
9683         int32 nalSize;
9684 
9685         iNumNALs = 0;
9686 
9687         while (length > 0)
9688         {
9689             nalSize = length;
9690 
9691             if (false == AVCAnnexBGetNALUnit(pBuffer, &pCurrNAL, &nalSize, false))
9692             {
9693                 break;
9694             }
9695 
9696             bytesConsumed = nalSize + (int32)(pCurrNAL - pBuffer);
9697             length -= bytesConsumed;
9698             pBuffer += bytesConsumed;
9699 
9700             if ((iNALSizeArrayMaxElems > iNumNALs) && (iNALSizeArray != NULL))
9701             {
9702                 iNALSizeArray[iNumNALs] = nalSize;
9703                 iNALPtrArray[iNumNALs] = (uint8*)pCurrNAL; /* need store NAL ptrs since start code can be either 4 bytes or 3 bytes */
9704                 iNumNALs++;
9705             }
9706             else
9707             {
9708                 iNumNALs++;
9709 
9710                 // count the number of NALs in the buffer
9711                 while (length > 0)
9712                 {
9713                     nalSize = length;
9714 
9715                     if (false == AVCAnnexBGetNALUnit(pBuffer, &pCurrNAL, &nalSize, false))
9716                     {
9717                         break;
9718                     }
9719 
9720                     bytesConsumed = nalSize + (int32)(pCurrNAL - pBuffer);
9721                     length -= bytesConsumed;
9722                     pBuffer += bytesConsumed;
9723 
9724                     iNumNALs++;
9725                 }
9726 
9727                 // reassign alloc size to new max.
9728                 iNALSizeArrayMaxElems = iNumNALs;
9729 
9730                 // free memory and then reallocate
9731                 if (iNALSizeArray != NULL)
9732                 {
9733                     oscl_free(iNALSizeArray);
9734                 }
9735                 iNALSizeArray = (uint32*) oscl_malloc(sizeof(uint32) * iNALSizeArrayMaxElems);
9736 
9737                 if (iNALPtrArray != NULL)
9738                 {
9739                     oscl_free(iNALPtrArray);
9740                 }
9741                 iNALPtrArray = (uint8**) oscl_malloc(sizeof(uint8*) * iNALSizeArrayMaxElems);
9742 
9743                 // reset parameters and start over
9744                 iNumNALs = 0;
9745                 length = aOutputBuffer->nFilledLen;
9746                 pBuffer = aOutputBuffer->pBuffer + offset;
9747 
9748                 if (iNALSizeArray == NULL || iNALPtrArray == NULL)
9749                 {
9750                     iNALSizeArrayMaxElems = 0;
9751 
9752                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVMFOMXEncNode-%s : ParseFullAVCFramesIntoNALs ERROR - Out of Memory", iNodeTypeId));
9753                     return false;
9754                 }
9755             }
9756         }
9757 
9758         if (iNumNALs <= 0)
9759         {
9760             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVMFOMXEncNode-%s : ParseFullAVCFramesIntoNALs ERROR", iNodeTypeId));
9761             return false;
9762         }
9763     }
9764     else if (aOutputBuffer->nFlags & OMX_BUFFERFLAG_EXTRADATA)
9765     {
9766         // get extra data from end of buffer
9767         OMX_OTHER_EXTRADATATYPE *pExtra;
9768         OMX_U32 offset = aOutputBuffer->nOffset + aOutputBuffer->nFilledLen;
9769         OMX_U32 allocLen = aOutputBuffer->nAllocLen;
9770         OMX_U8* pTemp = aOutputBuffer->pBuffer + offset;
9771 
9772         // align
9773         pExtra = (OMX_OTHER_EXTRADATATYPE *)(((OMX_U32) pTemp + 3) & ~3);
9774         offset += (OMX_U32) pExtra - (OMX_U32) pTemp;
9775 
9776         while (pExtra->eType != OMX_ExtraDataNone)
9777         {
9778             if (pExtra->eType == OMX_ExtraDataNALSizeArray)
9779             {
9780                 iNumNALs = pExtra->nDataSize >> 2;
9781                 if ((iNALSizeArrayMaxElems > iNumNALs) && (iNALSizeArray != NULL))
9782                 {
9783                     oscl_memcpy(iNALSizeArray, ((OMX_U8*)pExtra + 20), pExtra->nDataSize); // 20 is the size of the extra data struct (minus data hint)
9784                 }
9785                 else
9786                 {
9787                     // reassign alloc size to new max.
9788                     iNALSizeArrayMaxElems = iNumNALs;
9789 
9790                     // free memory and then reallocate
9791                     if (iNALSizeArray != NULL)
9792                     {
9793                         oscl_free(iNALSizeArray);
9794                     }
9795 
9796                     iNALSizeArray = (uint32*) oscl_malloc(sizeof(uint32) * iNALSizeArrayMaxElems);
9797                     if (iNALSizeArray == NULL)
9798                     {
9799                         iNALSizeArrayMaxElems = 0;
9800 
9801                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVMFOMXEncNode-%s : ParseFullAVCFramesIntoNALs ERROR - Out of Memory", iNodeTypeId));
9802                         return false;
9803                     }
9804 
9805                     oscl_memcpy(iNALSizeArray, ((OMX_U8*)pExtra + 20), pExtra->nDataSize); // 20 is the size of the extra data struct (minus data hint)
9806                 }
9807 
9808                 break;
9809             }
9810 
9811             offset += pExtra->nSize;
9812             /* 20 is size of extra data struct (minus data hint),
9813              * so if there isn't enough room for there to be a full struct, and we haven't reached an OMX_ExtraDataNone
9814              * the data is corrupt
9815              */
9816             if (offset > (allocLen - 20))
9817             {
9818                 // corrupt data
9819                 break;
9820             }
9821             else
9822             {
9823                 pExtra = (OMX_OTHER_EXTRADATATYPE *)((OMX_U8*)pExtra + pExtra->nSize);
9824             }
9825         }
9826 
9827         if (pExtra->eType != OMX_ExtraDataNALSizeArray)
9828         {
9829             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVMFOMXEncNode-%s : ParseFullAVCFramesIntoNALs ERROR", iNodeTypeId));
9830             return false;
9831         }
9832     }
9833     else
9834     {
9835         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVMFOMXEncNode-%s : ParseFullAVCFramesIntoNALs ERROR", iNodeTypeId));
9836         return false;
9837     }
9838 
9839     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVMFOMXEncNode-%s : ParseFullAVCFramesIntoNALs OUT", iNodeTypeId));
9840     return true;
9841 }
9842 
9843 /* utility function copied from the AVC Decoder interface */
AVCAnnexBGetNALUnit(uint8 * bitstream,uint8 ** nal_unit,int32 * size,bool getPtrOnly)9844 bool PVMFOMXEncNode::AVCAnnexBGetNALUnit(uint8 *bitstream, uint8 **nal_unit, int32 *size, bool getPtrOnly)
9845 {
9846     int32 i, j, FoundStartCode = 0;
9847     int32 end;
9848 
9849     i = 0;
9850     while (bitstream[i] == 0 && i < *size)
9851     {
9852         i++;
9853     }
9854     if (i >= *size)
9855     {
9856         *nal_unit = bitstream;
9857         return false; /* cannot find any start_code_prefix. */
9858     }
9859     else if (bitstream[i] != 0x1)
9860     {
9861         i = -1;  /* start_code_prefix is not at the beginning, continue */
9862     }
9863 
9864     i++;
9865     *nal_unit = bitstream + i; /* point to the beginning of the NAL unit */
9866 
9867     if (getPtrOnly)
9868     {
9869         // size not needed, just return with ptr
9870         return true;
9871     }
9872 
9873     j = end = i;
9874     while (!FoundStartCode)
9875     {
9876         while ((j + 1 < *size) && (bitstream[j] != 0 || bitstream[j+1] != 0))  /* see 2 consecutive zero bytes */
9877         {
9878             j++;
9879         }
9880         end = j;   /* stop and check for start code */
9881         while (j + 2 < *size && bitstream[j+2] == 0) /* keep reading for zero byte */
9882         {
9883             j++;
9884         }
9885         if (j + 2 >= *size)
9886         {
9887             *size -= i;
9888             return true;  /* cannot find the second start_code_prefix */
9889         }
9890         if (bitstream[j+2] == 0x1)
9891         {
9892             FoundStartCode = 1;
9893         }
9894         else
9895         {
9896             /* could be emulation code 0x3 */
9897             j += 2; /* continue the search */
9898         }
9899     }
9900 
9901     *size = end - i;
9902 
9903     return true;
9904 }
9905 
9906 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
CheckM4vVopStartCode(uint8 * data,int * len)9907 bool PVMFOMXEncNode::CheckM4vVopStartCode(uint8* data, int* len)
9908 {
9909     int32 count = 0;
9910     int32 i = *len;
9911 
9912     if (i < 4)  // at least the size of frame header
9913     {
9914         return false;
9915     }
9916     while (--i)
9917     {
9918         if ((count > 1) && (data[0] == 0x01) && (data[1] == 0xB6))
9919         {
9920             i += 2;
9921             break;
9922         }
9923 
9924         if (*data++)
9925             count = 0;
9926         else
9927             count++;
9928     }
9929 
9930     // i is number of bytes left (including 00 00 01 B6)
9931     if (i > 0)
9932     {
9933         *len = (*len - i - 1); // len before finding VOP start code
9934         return true;
9935     }
9936 
9937     return false;
9938 }
9939 
9940