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