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