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