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 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 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 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 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 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 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 //////////////////////////////////////////////////////////////////////////////// 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 } 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 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 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 //////////////////////////////////////////////////////////////////////////////// 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 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 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 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 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 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_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 ///////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////////////////////////////// 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 //////////////////////////////////////////////////////////////////////////// 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 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// 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 ///////////////////////////////////////////////////////////////////////////// 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 if (aData1 == (OMX_U32) OMX_ErrorInvalidState) 4698 { 4699 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 4700 (0, "PVMFOMXEncNode-%s::EventHandlerProcessing: OMX_EventError - OMX_ErrorInvalidState", iNodeTypeId)); 4701 HandleComponentStateChange(OMX_StateInvalid); 4702 } 4703 else 4704 { 4705 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 4706 (0, "PVMFOMXEncNode-%s::EventHandlerProcessing: OMX_EventError", iNodeTypeId)); 4707 // for now, any error from the component will be reported as error 4708 ReportErrorEvent(PVMFErrProcessing, NULL, NULL); 4709 SetState(EPVMFNodeError); 4710 } 4711 break; 4712 4713 } 4714 4715 case OMX_EventBufferFlag: 4716 { 4717 // the component is reporting it encountered end of stream flag 4718 // we'll send eos when we get the actual last buffer with marked eos 4719 4720 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4721 (0, "PVMFOMXEncNode-%s::EventHandlerProcessing: OMX_EventBufferFlag (EOS) flag returned from OMX component", iNodeTypeId)); 4722 4723 RunIfNotReady(); 4724 break; 4725 }//end of case OMX_EventBufferFlag 4726 4727 case OMX_EventMark: 4728 { 4729 4730 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4731 (0, "PVMFOMXEncNode-%s::EventHandlerProcessing: OMX_EventMark returned from OMX component - no action taken", iNodeTypeId)); 4732 4733 RunIfNotReady(); 4734 break; 4735 }//end of case OMX_EventMark 4736 4737 case OMX_EventPortSettingsChanged: 4738 { 4739 4740 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4741 (0, "PVMFOMXEncNode-%s::EventHandlerProcessing: OMX_EventPortSettingsChanged returned from OMX component", iNodeTypeId)); 4742 4743 // first check if dynamic reconfiguration is already in progress, 4744 // if so, wait until this is completed, and then initiate the 2nd reconfiguration 4745 if (iDynamicReconfigInProgress) 4746 { 4747 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4748 (0, "PVMFOMXEncNode-%s::EventHandlerProcessing: OMX_EventPortSettingsChanged returned for port %d, dynamic reconfig already in progress", iNodeTypeId, aData1)); 4749 4750 iSecondPortToReconfig = aData1; 4751 iSecondPortReportedChange = true; 4752 } 4753 else 4754 { 4755 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4756 (0, "PVMFOMXEncNode-%s::EventHandlerProcessing: OMX_EventPortSettingsChanged returned for port %d", iNodeTypeId, aData1)); 4757 4758 iProcessingState = EPVMFOMXEncNodeProcessingState_PortReconfig; 4759 iPortIndexForDynamicReconfig = aData1; 4760 iDynamicReconfigInProgress = true; 4761 } 4762 4763 RunIfNotReady(); 4764 break; 4765 }//end of case OMX_PortSettingsChanged 4766 4767 case OMX_EventResourcesAcquired: //not supported 4768 { 4769 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4770 (0, "PVMFOMXEncNode-%s::EventHandlerProcessing: OMX_EventResourcesAcquired returned from OMX component - no action taken", iNodeTypeId)); 4771 4772 RunIfNotReady(); 4773 4774 break; 4775 } 4776 4777 default: 4778 { 4779 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4780 (0, "PVMFOMXEncNode-%s::EventHandlerProcessing: Unknown Event returned from OMX component - no action taken", iNodeTypeId)); 4781 4782 break; 4783 } 4784 4785 }//end of switch (eEvent) 4786 4787 4788 4789 return OMX_ErrorNone; 4790 } 4791 4792 4793 4794 4795 ///////////////////////////////////////////////////////////////////////////// 4796 // This function handles the event of OMX component state change 4797 ///////////////////////////////////////////////////////////////////////////// 4798 void PVMFOMXEncNode::HandleComponentStateChange(OMX_U32 encoder_state) 4799 { 4800 switch (encoder_state) 4801 { 4802 case OMX_StateIdle: 4803 { 4804 iCurrentEncoderState = OMX_StateIdle; 4805 4806 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4807 (0, "PVMFOMXEncNode-%s::HandleComponentStateChange: OMX_StateIdle reached", iNodeTypeId)); 4808 4809 // this state can be reached either going from OMX_Loaded->OMX_Idle (preparing) 4810 // or going from OMX_Executing->OMX_Idle (stopping) 4811 4812 4813 if ((iCurrentCommand.size() > 0) && 4814 (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_PREPARE)) 4815 { 4816 iProcessingState = EPVMFOMXEncNodeProcessingState_ReadyToEncode; 4817 SetState(EPVMFNodePrepared); 4818 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess); 4819 RunIfNotReady(); 4820 } 4821 else if ((iCurrentCommand.size() > 0) && 4822 (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_STOP)) 4823 { 4824 // if we are stopped, we won't start until the node gets DoStart command. 4825 // in this case, we are ready to start sending buffers 4826 if (iProcessingState == EPVMFOMXEncNodeProcessingState_Stopping) 4827 iProcessingState = EPVMFOMXEncNodeProcessingState_ReadyToEncode; 4828 // if the processing state was not stopping, leave the state as it was (continue port reconfiguration) 4829 SetState(EPVMFNodePrepared); 4830 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess); 4831 4832 RunIfNotReady(); 4833 } 4834 else if ((iCurrentCommand.size() > 0) && 4835 (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_FLUSH)) 4836 { 4837 // if there is a flush, similar to the case of stop, we won't start until the node gets 4838 // DoStart command. In this case, we'll be ready 4839 if (iProcessingState == EPVMFOMXEncNodeProcessingState_Stopping) 4840 iProcessingState = EPVMFOMXEncNodeProcessingState_ReadyToEncode; 4841 4842 4843 4844 //Flush is complete. Go to prepared state. 4845 SetState(EPVMFNodePrepared); 4846 //resume port input (if possible) so the ports can be re-started. 4847 if (iInPort) 4848 { 4849 iInPort->ResumeInput(); 4850 } 4851 if (iOutPort) 4852 { 4853 iOutPort->ResumeInput(); 4854 } 4855 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess); 4856 RunIfNotReady(); 4857 4858 } 4859 else if ((iCurrentCommand.size() > 0) && 4860 (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_RESET)) 4861 { 4862 // State change to Idle was initiated due to Reset. First need to reach idle, and then loaded 4863 // Once Idle is reached, we need to initiate idle->loaded transition 4864 iStopInResetMsgSent = false; 4865 RunIfNotReady(); 4866 } 4867 break; 4868 }//end of case OMX_StateIdle 4869 4870 case OMX_StateExecuting: 4871 { 4872 iCurrentEncoderState = OMX_StateExecuting; 4873 4874 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4875 (0, "PVMFOMXEncNode-%s::HandleComponentStateChange: OMX_StateExecuting reached", iNodeTypeId)); 4876 4877 // this state can be reached going from OMX_Idle -> OMX_Executing (preparing) 4878 // or going from OMX_Pause -> OMX_Executing (coming from pause) 4879 // either way, this is a response to "DoStart" command 4880 4881 if ((iCurrentCommand.size() > 0) && 4882 (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_START)) 4883 { 4884 SetState(EPVMFNodeStarted); 4885 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess); 4886 4887 RunIfNotReady(); 4888 } 4889 4890 break; 4891 }//end of case OMX_StateExecuting 4892 4893 case OMX_StatePause: 4894 { 4895 iCurrentEncoderState = OMX_StatePause; 4896 4897 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4898 (0, "PVMFOMXEncNode-%s::HandleComponentStateChange: OMX_StatePause reached", iNodeTypeId)); 4899 4900 4901 // This state can be reached going from OMX_Executing-> OMX_Pause 4902 if ((iCurrentCommand.size() > 0) && 4903 (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_PAUSE)) 4904 { 4905 SetState(EPVMFNodePaused); 4906 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess); 4907 RunIfNotReady(); 4908 } 4909 4910 break; 4911 }//end of case OMX_StatePause 4912 4913 case OMX_StateLoaded: 4914 { 4915 iCurrentEncoderState = OMX_StateLoaded; 4916 4917 // this state can be reached only going from OMX_Idle ->OMX_Loaded (stopped to reset) 4918 // 4919 4920 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4921 (0, "PVMFOMXEncNode-%s::HandleComponentStateChange: OMX_StateLoaded reached", iNodeTypeId)); 4922 //Check if command's responce is pending 4923 if ((iCurrentCommand.size() > 0) && 4924 (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_RESET)) 4925 { 4926 4927 // move this here 4928 if (iInPort) 4929 { 4930 OSCL_DELETE(((PVMFOMXEncPort*)iInPort)); 4931 iInPort = NULL; 4932 } 4933 4934 if (iOutPort) 4935 { 4936 OSCL_DELETE(((PVMFOMXEncPort*)iOutPort)); 4937 iOutPort = NULL; 4938 } 4939 4940 iDataIn.Unbind(); 4941 4942 // Reset the metadata key list 4943 iAvailableMetadataKeys.clear(); 4944 4945 4946 iProcessingState = EPVMFOMXEncNodeProcessingState_Idle; 4947 //logoff & go back to Created state. 4948 SetState(EPVMFNodeIdle); 4949 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess); 4950 iResetInProgress = false; 4951 iResetMsgSent = false; 4952 } 4953 4954 break; 4955 }//end of case OMX_StateLoaded 4956 4957 case OMX_StateInvalid: 4958 default: 4959 { 4960 iCurrentEncoderState = OMX_StateInvalid; 4961 4962 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 4963 (0, "PVMFOMXEncNode-%s::HandleComponentStateChange: OMX_StateInvalid reached", iNodeTypeId)); 4964 //Clearup encoder 4965 DeleteOMXEncoder(); 4966 4967 if (iCurrentCommand.size() > 0) 4968 {//can NOT be CANCEL or CANCEL_ALL. Just to cmd completion for the rest 4969 if (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_RESET) 4970 { 4971 //delete all ports and notify observer. 4972 if (iInPort) 4973 { 4974 OSCL_DELETE(((PVMFOMXEncPort*)iInPort)); 4975 iInPort = NULL; 4976 } 4977 4978 if (iOutPort) 4979 { 4980 OSCL_DELETE(((PVMFOMXEncPort*)iOutPort)); 4981 iOutPort = NULL; 4982 } 4983 4984 iDataIn.Unbind(); 4985 4986 // Reset the metadata key list 4987 iAvailableMetadataKeys.clear(); 4988 4989 iEndOfDataReached = false; 4990 iIsEOSSentToComponent = false; 4991 iIsEOSReceivedFromComponent = false; 4992 4993 iProcessingState = EPVMFOMXEncNodeProcessingState_Idle; 4994 //logoff & go back to Created state. 4995 SetState(EPVMFNodeIdle); 4996 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess); 4997 } 4998 else 4999 { 5000 SetState(EPVMFNodeError); 5001 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFErrResource); 5002 } 5003 } 5004 5005 break; 5006 }//end of case OMX_StateInvalid 5007 5008 }//end of switch(encoder_state) 5009 5010 } 5011 5012 5013 5014 5015 5016 5017 ///////////////////////////////////////////////////////////////////////////// 5018 ////////////////////// CALLBACK PROCESSING FOR EMPTY BUFFER DONE - input buffer was consumed 5019 ///////////////////////////////////////////////////////////////////////////// 5020 OMX_ERRORTYPE PVMFOMXEncNode::EmptyBufferDoneProcessing(OMX_OUT OMX_HANDLETYPE aComponent, 5021 OMX_OUT OMX_PTR aAppData, 5022 OMX_OUT OMX_BUFFERHEADERTYPE* aBuffer) 5023 { 5024 5025 OSCL_UNUSED_ARG(aComponent); 5026 OSCL_UNUSED_ARG(aAppData); 5027 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5028 (0, "PVMFOMXEncNode-%s::EmptyBufferDoneProcessing: In", iNodeTypeId)); 5029 5030 OSCL_ASSERT((void*) aComponent == (void*) iOMXEncoder); // component should match the component 5031 OSCL_ASSERT(aAppData == (OMX_PTR)(this)); // AppData should represent this node ptr 5032 5033 // first, get the buffer "context", i.e. pointer to application private data that contains the 5034 // address of the mempool buffer (so that it can be released) 5035 InputBufCtrlStruct *pContext = (InputBufCtrlStruct *)(aBuffer->pAppPrivate); 5036 5037 5038 5039 // if a buffer is not empty, log a msg, but release anyway 5040 if ((aBuffer->nFilledLen > 0) && (iDoNotSaveInputBuffersFlag == false)) 5041 // if dynamic port reconfig is in progress for input port, don't keep the buffer 5042 { 5043 5044 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5045 (0, "PVMFOMXEncNode-%s::EmptyBufferDoneProcessing: Input buffer returned non-empty with %d bytes still in it", iNodeTypeId, aBuffer->nFilledLen)); 5046 5047 5048 } 5049 5050 iInputBufferToResendToComponent = NULL; 5051 5052 5053 // input buffer is to be released, 5054 // refcount needs to be decremented (possibly - the input msg associated with the buffer will be unbound) 5055 // NOTE: in case of "moveable" input buffers (passed into component without copying), unbinding decrements a refcount which eventually results 5056 // in input message being released back to upstream mempool once all its fragments are returned 5057 // in case of input buffers passed into component by copying, unbinding has no effect 5058 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5059 (0, "PVMFOMXEncNode-%s::EmptyBufferDoneProcessing: Release input buffer (with %d refcount remaining of input message)", iNodeTypeId, (pContext->pMediaData).get_count() - 1)); 5060 5061 5062 (pContext->pMediaData).Unbind(); 5063 5064 5065 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5066 (0, "PVMFOMXEncNode-%s::EmptyBufferDoneProcessing: Release input buffer %x back to mempool", iNodeTypeId, pContext)); 5067 5068 iInBufMemoryPool->deallocate((OsclAny *) pContext); 5069 5070 5071 // the OMX spec says that no error is to be returned 5072 return OMX_ErrorNone; 5073 5074 } 5075 5076 5077 5078 ///////////////////////////////////////////////////////////////////////////// 5079 ////////////////////// CALLBACK PROCESSING FOR FILL BUFFER DONE - output buffer is ready 5080 ///////////////////////////////////////////////////////////////////////////// 5081 OMX_ERRORTYPE PVMFOMXEncNode::FillBufferDoneProcessing(OMX_OUT OMX_HANDLETYPE aComponent, 5082 OMX_OUT OMX_PTR aAppData, 5083 OMX_OUT OMX_BUFFERHEADERTYPE* aBuffer) 5084 { 5085 5086 OSCL_UNUSED_ARG(aComponent); 5087 OSCL_UNUSED_ARG(aAppData); 5088 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5089 (0, "PVMFOMXEncNode-%s::FillBufferDoneProcessing: In", iNodeTypeId)); 5090 5091 OSCL_ASSERT((void*) aComponent == (void*) iOMXEncoder); // component should match the component 5092 OSCL_ASSERT(aAppData == (OMX_PTR)(this)); // AppData should represent this node ptr 5093 5094 // first, get the buffer "context", i.e. pointer to application private data that contains the 5095 // address of the mempool buffer (so that it can be released) 5096 OsclAny *pContext = (OsclAny*) aBuffer->pAppPrivate; 5097 5098 5099 // check for EOS flag 5100 if ((aBuffer->nFlags & OMX_BUFFERFLAG_EOS)) 5101 { 5102 // EOS received - enable sending EOS msg 5103 iIsEOSReceivedFromComponent = true; 5104 5105 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5106 (0, "PVMFOMXEncNode-%s::FillBufferDoneProcessing: Output buffer has EOS set", iNodeTypeId)); 5107 5108 } 5109 5110 if (((iOutFormat == PVMF_MIME_H264_VIDEO_MP4) || (iOutFormat == PVMF_MIME_H264_VIDEO_RAW)) 5111 && (iOMXComponentUsesNALStartCodes)) 5112 { 5113 // find size of first start code, since it can be either 3 or 4 bytes 5114 uint8* pData = (uint8*)aBuffer->pBuffer + aBuffer->nOffset; 5115 uint8* pTemp; 5116 uint32 size = aBuffer->nFilledLen; 5117 if (AVCAnnexBGetNALUnit(pData, &pTemp, (int32*)&size, true)) 5118 { 5119 iFirstNALStartCodeSize = (uint32)pTemp - (uint32)pData; 5120 } 5121 else 5122 { 5123 iFirstNALStartCodeSize = 0; 5124 } 5125 } 5126 5127 /* the case in which a buffer simply containing a start code is sent */ 5128 if (aBuffer->nFilledLen <= iFirstNALStartCodeSize && iOMXComponentUsesNALStartCodes) 5129 { 5130 aBuffer->nFilledLen = 0; 5131 } 5132 5133 // if a buffer is empty, or if it should not be sent downstream (say, due to state change) 5134 // release the buffer back to the pool 5135 if ((aBuffer->nFilledLen == 0) || (iDoNotSendOutputBuffersDownstreamFlag == true)) 5136 { 5137 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5138 (0, "PVMFOMXEncNode-%s::FillBufferDoneProcessing: Release output buffer %x back to mempool - buffer empty or not to be sent downstream", iNodeTypeId, pContext)); 5139 5140 iOutBufMemoryPool->deallocate(pContext); 5141 5142 } 5143 else 5144 { 5145 5146 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5147 (0, "PVMFOMXEncNode-%s::FillBufferDoneProcessing: Output frame %d received", iNodeTypeId, iFrameCounter)); 5148 5149 iFrameCounter++; 5150 // get pointer to actual buffer data 5151 uint8 *pBufdata = ((uint8*) aBuffer->pBuffer); 5152 // move the data pointer based on offset info 5153 pBufdata += aBuffer->nOffset; 5154 5155 uint32 bufLen = (uint32) aBuffer->nFilledLen; 5156 5157 // in case of mp4 streaming and the very 1st buffer, save vol header separately 5158 if ((iOutFormat == PVMF_MIME_M4V) && (iFrameCounter == 1)) 5159 { 5160 5161 // save the first buffer since this is the VOL header 5162 uint refCounterSize = oscl_mem_aligned_size(sizeof(OsclRefCounterDA)); 5163 OsclMemoryFragment volHeader; 5164 5165 int vol_len = aBuffer->nFilledLen; 5166 bool frameInVolHdr = CheckM4vVopStartCode(pBufdata, &vol_len); 5167 5168 volHeader.ptr = NULL; 5169 volHeader.len = vol_len; 5170 uint8* memBuffer = (uint8*)iAlloc.allocate(refCounterSize + volHeader.len); 5171 oscl_memset(memBuffer, 0, refCounterSize + volHeader.len); 5172 OsclRefCounter* refCounter = OSCL_PLACEMENT_NEW(memBuffer, OsclRefCounterDA(memBuffer, (OsclDestructDealloc*) & iAlloc)); 5173 memBuffer += refCounterSize; 5174 volHeader.ptr = (OsclAny*)memBuffer; 5175 5176 // copy the vol header from OMX buffer 5177 oscl_memcpy(volHeader.ptr, pBufdata, volHeader.len); 5178 5179 // save in class variable 5180 iVolHeader = OsclRefCounterMemFrag(volHeader, refCounter, volHeader.len); 5181 5182 if (frameInVolHdr == false) 5183 { 5184 // release the OMX buffer 5185 iOutBufMemoryPool->deallocate(pContext); 5186 return OMX_ErrorNone; 5187 } 5188 else // there is a frame in this buffer, update the pointer and continue to process it. 5189 { 5190 pBufdata += vol_len; 5191 bufLen -= vol_len; 5192 } 5193 } 5194 5195 if (iFrameCounter == 1) 5196 { 5197 if ((iOutFormat == PVMF_MIME_ADTS) 5198 || (iOutFormat == PVMF_MIME_ADIF) 5199 || (iOutFormat == PVMF_MIME_MPEG4_AUDIO) 5200 || (iOutFormat == PVMF_MIME_WMA) 5201 || (iOutFormat == PVMF_MIME_WMV) 5202 ) 5203 { 5204 5205 // save the first buffer since this is the config header and needs to be sent separately 5206 uint refCounterSize = oscl_mem_aligned_size(sizeof(OsclRefCounterDA)); 5207 OsclMemoryFragment configHeader; 5208 configHeader.ptr = NULL; 5209 configHeader.len = aBuffer->nFilledLen; 5210 uint8* memBuffer = (uint8*)iAlloc.allocate(refCounterSize + configHeader.len); 5211 oscl_memset(memBuffer, 0, refCounterSize + configHeader.len); 5212 OsclRefCounter* refCounter = OSCL_PLACEMENT_NEW(memBuffer, OsclRefCounterDA(memBuffer, (OsclDestructDealloc*) & iAlloc)); 5213 memBuffer += refCounterSize; 5214 configHeader.ptr = (OsclAny*)memBuffer; 5215 5216 // copy the vol header from OMX buffer 5217 oscl_memcpy(configHeader.ptr, pBufdata, configHeader.len); 5218 5219 // save in class variable 5220 iConfigHeader = OsclRefCounterMemFrag(configHeader, refCounter, configHeader.len); 5221 5222 // release the OMX buffer 5223 iOutBufMemoryPool->deallocate(pContext); 5224 return OMX_ErrorNone; 5225 } 5226 } 5227 5228 // in case of avc mp4, need to save sps/pps sequences 5229 if ((iOutFormat == PVMF_MIME_H264_VIDEO_MP4) && (!iSpsPpsSequenceOver)) 5230 { 5231 5232 if (iOMXComponentUsesNALStartCodes) 5233 { 5234 // remove the start code from these single NAL frames 5235 pBufdata += iFirstNALStartCodeSize; 5236 bufLen -= iFirstNALStartCodeSize; 5237 } 5238 // detect nal type 5239 uint8 *bitstream = pBufdata; 5240 int nal_type; 5241 5242 // adjust the pointers in the iParamSet memfragment 5243 uint8 *destptr = (uint8*) iParamSet.getMemFragPtr(); 5244 uint32 length = iParamSet.getMemFrag().len; 5245 uint32 capacity = iParamSet.getCapacity(); 5246 5247 destptr += length; 5248 5249 5250 nal_type = bitstream[0] & 0x1F; 5251 5252 if (nal_type == 0x07) // SPS type NAL 5253 { 5254 int32 nal_size = aBuffer->nFilledLen; 5255 AVCAnnexBGetNALUnit(aBuffer->pBuffer, &bitstream, (int32*)&nal_size, false); 5256 // can the SPS fit into the buffer 5257 if (aBuffer->nFilledLen <= (capacity - length)) 5258 { 5259 iSPSs[iNumSPSs].ptr = destptr; 5260 iSPSs[iNumSPSs++].len = nal_size; 5261 5262 oscl_memcpy(destptr, pBufdata, nal_size); // copy SPS into iParamSet memfragment 5263 length += nal_size; 5264 iParamSet.getMemFrag().len = length; // update length 5265 destptr += nal_size; 5266 if (nal_size < aBuffer->nFilledLen) { 5267 LOGD("SPS and PPS are located within a single output buffer"); 5268 uint8* pData = (uint8*)aBuffer->pBuffer + nal_size +iFirstNALStartCodeSize; 5269 uint32 size = aBuffer->nFilledLen -(nal_size +iFirstNALStartCodeSize); 5270 AVCAnnexBGetNALUnit(pData, &bitstream, (int32*)&size, false); 5271 nal_size = size; 5272 nal_type = bitstream[0] & 0x1F; 5273 if (nal_type == 0x08) // PPS type NAL 5274 { 5275 if (aBuffer->nFilledLen <= (capacity - length)) 5276 { 5277 iPPSs[iNumPPSs].ptr = destptr; 5278 iPPSs[iNumPPSs++].len = nal_size; 5279 oscl_memcpy(destptr, bitstream, nal_size); // copy PPS into iParamSet memfragment$ 5280 length += nal_size; 5281 iParamSet.getMemFrag().len = length; // update length 5282 } 5283 } 5284 } 5285 } 5286 5287 // release the OMX buffer 5288 iOutBufMemoryPool->deallocate(pContext); 5289 return OMX_ErrorNone; 5290 } 5291 else if (nal_type == 0x08) // PPS type NAL 5292 { 5293 LOGD("SPS and PPS are located in separate output buffers"); 5294 // can the PPS fit into the buffer? 5295 if (aBuffer->nFilledLen <= (capacity - length)) 5296 { 5297 5298 iPPSs[iNumPPSs].ptr = destptr; 5299 iPPSs[iNumPPSs++].len = aBuffer->nFilledLen; 5300 5301 oscl_memcpy(destptr, pBufdata, aBuffer->nFilledLen); // copy PPS into iParamSet memfragment 5302 length += aBuffer->nFilledLen; 5303 iParamSet.getMemFrag().len = length; // update length 5304 5305 5306 } 5307 5308 // release the OMX buffer 5309 iOutBufMemoryPool->deallocate(pContext); 5310 return OMX_ErrorNone; 5311 } 5312 else 5313 { 5314 if (iOMXComponentUsesNALStartCodes) 5315 { 5316 // bring start code back since it's not a SPS or PPS 5317 pBufdata -= iFirstNALStartCodeSize; 5318 bufLen += iFirstNALStartCodeSize; 5319 } 5320 5321 // this is neither SPS nor PPS 5322 // stop recording SPS/PPS 5323 iSpsPpsSequenceOver = true; 5324 iFirstNAL = true; // set indicator of first NAL 5325 // send out SPS/PPS recorded so far 5326 if (((PVMFOMXEncPort*)iOutPort)) 5327 { 5328 ((PVMFOMXEncPort*)iOutPort)->SendSPS_PPS(iSPSs, iNumSPSs, iPPSs, iNumPPSs); 5329 } 5330 } 5331 5332 } 5333 5334 if (iOMXComponentUsesFullAVCFrames && iOutFormat == PVMF_MIME_H264_VIDEO_MP4) 5335 { 5336 // do not parse fo PVMF_MIME_H264_VIDEO_RAW, since this data is just written raw, and knowing 5337 // the NAL boundaries isn't necessary 5338 5339 if (!ParseFullAVCFramesIntoNALs(aBuffer)) 5340 { 5341 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5342 (0, "PVMFOMXEncNode-%s::FillBufferDoneProcessing: Problem parsing NALs in buffer %x of size %d - releasing the buffer", iNodeTypeId, pBufdata, aBuffer->nFilledLen)); 5343 5344 iOutBufMemoryPool->deallocate(pContext); 5345 } 5346 } 5347 5348 // adjust ptr to data to expose the NAL sync word if necessary 5349 if ((iOutFormat == PVMF_MIME_H264_VIDEO_RAW) && 5350 (iOMXComponentSupportsExternalOutputBufferAlloc) && 5351 (!iOMXComponentUsesFullAVCFrames) && 5352 (!iOMXComponentUsesNALStartCodes) && 5353 ((iFirstNAL == true) || (iEndOfNALFlagPrevious != 0)) 5354 ) 5355 { 5356 pBufdata -= 4; 5357 bufLen += 4; 5358 } 5359 5360 // otherwise, queue output buffer 5361 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5362 (0, "PVMFOMXEncNode-%s::FillBufferDoneProcessing: Wrapping buffer %x of size %d", iNodeTypeId, pBufdata, aBuffer->nFilledLen)); 5363 // wrap the buffer into the MediaDataImpl wrapper, and queue it for sending downstream 5364 // wrapping will create a refcounter. When refcounter goes to 0 i.e. when media data 5365 // is released in downstream components, the custom deallocator will automatically release the buffer back to the 5366 // mempool. To do that, the deallocator needs to have info about Context 5367 // NOTE: we had to wait until now to wrap the buffer data because we only know 5368 // now where the actual data is located (based on buffer offset) 5369 OsclSharedPtr<PVMFMediaDataImpl> MediaDataCurr = WrapOutputBuffer(pBufdata, bufLen, pContext); 5370 5371 // if you can't get the MediaDataCurr, release the buffer back to the pool 5372 if (MediaDataCurr.GetRep() == NULL) 5373 { 5374 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5375 (0, "PVMFOMXEncNode-%s::FillBufferDoneProcessing: Problem wrapping buffer %x of size %d - releasing the buffer", iNodeTypeId, pBufdata, aBuffer->nFilledLen)); 5376 5377 iOutBufMemoryPool->deallocate(pContext); 5378 } 5379 else 5380 { 5381 OsclSharedPtr<PVMFMediaDataImpl> MediaDataOut; 5382 5383 //DV - NOTE: 5384 //In case of AVC, OMX_EndOfFrameFlag is used to mark the end of NAL 5385 // End of frame is determined by comparing timestamps 5386 // As a consequence, there is a lag of one buffer 5387 // i.e. we send/queue the previous buffer and keep the current one so that 5388 // When the next buffer arrives, we can compare timestamps etc. 5389 5390 // In case of MP4, OMX_EndOFFrameFlag is used to mark end of frame and there is no lag 5391 5392 if ((iOutFormat == PVMF_MIME_H264_VIDEO_MP4) || (iOutFormat == PVMF_MIME_H264_VIDEO_RAW)) 5393 { 5394 5395 MediaDataOut = iPreviousMediaData; // send out previous media data 5396 5397 // copy data to be attached with outgoing media data from previous buffer 5398 iTimeStampOut = iTimeStampPrevious; 5399 iKeyFrameFlagOut = iKeyFrameFlagPrevious; 5400 iEndOfNALFlagOut = iEndOfNALFlagPrevious; 5401 // figure out if we need to set end of frame based on TS 5402 if (aBuffer->nTimeStamp != iTimeStampPrevious) 5403 iEndOfFrameFlagOut = 1; 5404 else 5405 iEndOfFrameFlagOut = 0; 5406 iBufferLenOut = iBufferLenPrevious; 5407 5408 // now read the info for the current data 5409 iPreviousMediaData = MediaDataCurr; 5410 // record timestamp, flags etc. 5411 iTimeStampPrevious = aBuffer->nTimeStamp; 5412 // check for Key Frame 5413 iKeyFrameFlagPrevious = (aBuffer->nFlags & OMX_BUFFERFLAG_SYNCFRAME); 5414 // for avc, ENDOFFRAMEFLAG is used to delimit NALs 5415 iEndOfNALFlagPrevious = (aBuffer->nFlags & OMX_BUFFERFLAG_ENDOFFRAME); 5416 iBufferLenPrevious = bufLen; 5417 5418 5419 } 5420 else // MP4 case 5421 { 5422 5423 MediaDataOut = MediaDataCurr; 5424 // record timestamp, flags etc. 5425 iTimeStampOut = aBuffer->nTimeStamp; 5426 5427 // check for Key Frame 5428 iKeyFrameFlagOut = (aBuffer->nFlags & OMX_BUFFERFLAG_SYNCFRAME); 5429 iEndOfNALFlagOut = 0; // set this to 0 for mp4 5430 //check for END OF FRAME FLAG 5431 iEndOfFrameFlagOut = (aBuffer->nFlags & OMX_BUFFERFLAG_ENDOFFRAME); 5432 iBufferLenOut = aBuffer->nFilledLen; 5433 5434 5435 } 5436 // if there's a problem queuing output buffer, MediaDataCurr will expire at end of scope and 5437 // release buffer back to the pool, (this should not be the case) 5438 5439 // queue only if not the first NAL 5440 if (!iFirstNAL) 5441 { 5442 if (QueueOutputBuffer(MediaDataOut, iBufferLenOut)) 5443 { 5444 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5445 (0, "PVMFOMXEncNode-%s::FillBufferDoneProcessing: Buffer %x of size %d queued - reschedule the node to send out", iNodeTypeId, pBufdata, aBuffer->nFilledLen)); 5446 5447 // if queing went OK, 5448 // re-schedule the node so that outgoing queue can be emptied (unless the outgoing port is busy) 5449 if ((iOutPort) && !(iOutPort->IsConnectedPortBusy())) 5450 RunIfNotReady(); 5451 } 5452 else 5453 { 5454 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5455 (0, "PVMFOMXEncNode-%s::FillBufferDoneProcessing: Problem queing buffer %x of size %d - releasing the buffer", iNodeTypeId, pBufdata, aBuffer->nFilledLen)); 5456 } 5457 } 5458 else 5459 { 5460 iFirstNAL = false; 5461 } 5462 5463 // if EOS and AVC (with a lag), queue also the last buffer 5464 if ((aBuffer->nFlags & OMX_BUFFERFLAG_EOS) && 5465 ((iOutFormat == PVMF_MIME_H264_VIDEO_MP4) || (iOutFormat == PVMF_MIME_H264_VIDEO_RAW)) 5466 ) 5467 { 5468 5469 MediaDataOut = iPreviousMediaData; // send out previous media data 5470 5471 // copy data to be attached with outgoing media data from previous buffer 5472 iTimeStampOut = iTimeStampPrevious; 5473 iKeyFrameFlagOut = iKeyFrameFlagPrevious; 5474 iEndOfNALFlagOut = 1; 5475 iEndOfFrameFlagOut = 1; 5476 5477 iBufferLenOut = iBufferLenPrevious; 5478 5479 if (QueueOutputBuffer(MediaDataOut, iBufferLenOut)) 5480 { 5481 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5482 (0, "PVMFOMXEncNode-%s::FillBufferDoneProcessing: Buffer %x of size %d queued - reschedule the node to send out", iNodeTypeId, pBufdata, aBuffer->nFilledLen)); 5483 5484 // if queing went OK, 5485 // re-schedule the node so that outgoing queue can be emptied (unless the outgoing port is busy) 5486 if ((iOutPort) && !(iOutPort->IsConnectedPortBusy())) 5487 RunIfNotReady(); 5488 } 5489 else 5490 { 5491 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5492 (0, "PVMFOMXEncNode-%s::FillBufferDoneProcessing: Problem queing buffer %x of size %d - releasing the buffer", iNodeTypeId, pBufdata, aBuffer->nFilledLen)); 5493 } 5494 5495 } 5496 } 5497 5498 } 5499 // the OMX spec says that no error is to be returned 5500 return OMX_ErrorNone; 5501 5502 } 5503 //////////////////////////////////////////////////////////////////////////////////////////////// 5504 ///////////////////////////// Put output buffer in outgoing queue ////////////////////////////// 5505 //////////////////////////////////////////////////////////////////////////////////////////////// 5506 bool PVMFOMXEncNode::QueueOutputBuffer(OsclSharedPtr<PVMFMediaDataImpl> &mediadataimplout, uint32 aDataLen) 5507 { 5508 5509 bool status = true; 5510 PVMFSharedMediaDataPtr mediaDataOut; 5511 int32 leavecode = 0; 5512 5513 // NOTE: ASSUMPTION IS THAT OUTGOING QUEUE IS BIG ENOUGH TO QUEUE ALL THE OUTPUT BUFFERS 5514 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5515 (0, "PVMFOMXEncNode-%s::QueueOutputFrame: In", iNodeTypeId)); 5516 5517 // Check if the port is still connected 5518 if (iOutPort == NULL) 5519 { 5520 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 5521 (0, "PVMFOMXEncNode-%s::QueueOutputFrame() OutgoingQueue Out Port is disconnected")); 5522 return false; 5523 } 5524 5525 // First check if we can put outgoing msg. into the queue 5526 if (iOutPort->IsOutgoingQueueBusy()) 5527 { 5528 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 5529 (0, "PVMFOMXEncNode-%s::QueueOutputFrame() OutgoingQueue is busy", iNodeTypeId)); 5530 return false; 5531 } 5532 5533 OSCL_TRY(leavecode, 5534 mediaDataOut = PVMFMediaData::createMediaData(mediadataimplout, iMediaDataMemPool);); 5535 if (leavecode == 0) 5536 { 5537 5538 uint32 marker_bits = mediaDataOut->getMarkerInfo(); 5539 5540 if (iEndOfFrameFlagOut != 0) 5541 { 5542 marker_bits |= PVMF_MEDIA_DATA_MARKER_INFO_M_BIT; 5543 } 5544 5545 if (iKeyFrameFlagOut != 0) 5546 { 5547 marker_bits |= PVMF_MEDIA_DATA_MARKER_INFO_RANDOM_ACCESS_POINT_BIT; 5548 } 5549 5550 if (iEndOfNALFlagOut != 0) 5551 { 5552 marker_bits |= PVMF_MEDIA_DATA_MARKER_INFO_END_OF_NAL_BIT; 5553 } 5554 5555 // attach marker bit 5556 mediaDataOut->setMarkerInfo(marker_bits); 5557 5558 5559 // Update the filled length of the fragment 5560 mediaDataOut->setMediaFragFilledLen(0, aDataLen); 5561 5562 // Set timestamp 5563 // first convert OMX_TICKS into output timescale 5564 uint32 output_timestamp = ConvertOMXTicksIntoTimestamp(iTimeStampOut); 5565 5566 mediaDataOut->setTimestamp(output_timestamp); 5567 5568 // Set Streamid 5569 mediaDataOut->setStreamID(iStreamID); 5570 5571 // Set sequence number 5572 mediaDataOut->setSeqNum(iSeqNum++); 5573 5574 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iDataPathLogger, PVLOGMSG_INFO, (0, ":PVMFOMXEncNode-%s::QueueOutputFrame(): - SeqNum=%d, Ticks=%l TS=%d", iNodeTypeId, iSeqNum, iTimeStampOut, output_timestamp)); 5575 5576 5577 // Check if Fsi needs to be sent (VOL header) 5578 if (sendYuvFsi) 5579 { 5580 if (iOutFormat == PVMF_MIME_M4V) 5581 { 5582 mediaDataOut->setFormatSpecificInfo(iVolHeader); 5583 5584 } 5585 else if ((iOutFormat == PVMF_MIME_ADTS) 5586 || (iOutFormat == PVMF_MIME_ADIF) 5587 || (iOutFormat == PVMF_MIME_MPEG4_AUDIO) 5588 || (iOutFormat == PVMF_MIME_WMA) 5589 || (iOutFormat == PVMF_MIME_WMV)) 5590 { 5591 5592 mediaDataOut->setFormatSpecificInfo(iConfigHeader); 5593 5594 } 5595 5596 sendYuvFsi = false; 5597 } 5598 5599 // Send frame to downstream node 5600 PVMFSharedMediaMsgPtr mediaMsgOut; 5601 convertToPVMFMediaMsg(mediaMsgOut, mediaDataOut); 5602 5603 if (iOutPort && (iOutPort->QueueOutgoingMsg(mediaMsgOut) == PVMFSuccess)) 5604 { 5605 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO, 5606 (0, "PVMFOMXEncNode-%s::QueueOutputFrame(): Queued frame OK ", iNodeTypeId)); 5607 5608 } 5609 else 5610 { 5611 // we should not get here because we always check for whether queue is busy or not 5612 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 5613 (0, "PVMFOMXEncNode-%s::QueueOutputFrame(): Send frame failed", iNodeTypeId)); 5614 return false; 5615 } 5616 5617 5618 5619 5620 }//end of if (leavecode==0) 5621 else 5622 { 5623 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 5624 (0, "PVMFOMXEncNode-%s::QueueOutputFrame() call PVMFMediaData::createMediaData is failed", iNodeTypeId)); 5625 return false; 5626 } 5627 5628 return status; 5629 5630 } 5631 5632 ////////////////////////////////////////////////////////////////////////////////////////////// 5633 ///////////////////////////// Attach a MediaDataImpl wrapper (refcount, deallocator etc.) 5634 /////////////////////////////// to the output buffer ///////////////////////////////////////// 5635 OsclSharedPtr<PVMFMediaDataImpl> PVMFOMXEncNode::WrapOutputBuffer(uint8 *pData, uint32 aDataLen, OsclAny *pContext) 5636 { 5637 // wrap output buffer into a mediadataimpl 5638 uint32 aligned_cleanup_size = oscl_mem_aligned_size(sizeof(PVOMXEncBufferSharedPtrWrapperCombinedCleanupDA)); 5639 uint32 aligned_refcnt_size = oscl_mem_aligned_size(sizeof(OsclRefCounterDA)); 5640 uint8 *my_ptr = (uint8*) oscl_malloc(aligned_cleanup_size + aligned_refcnt_size); 5641 5642 if (my_ptr == NULL) 5643 { 5644 OsclSharedPtr<PVMFMediaDataImpl> null_buff(NULL, NULL); 5645 return null_buff; 5646 } 5647 5648 // create a deallocator and pass the buffer_allocator to it as well as pointer to data that needs to be returned to the mempool 5649 PVOMXEncBufferSharedPtrWrapperCombinedCleanupDA *cleanup_ptr = 5650 OSCL_PLACEMENT_NEW(my_ptr + aligned_refcnt_size, PVOMXEncBufferSharedPtrWrapperCombinedCleanupDA(iOutBufMemoryPool, pContext)); 5651 5652 // create the ref counter after the cleanup object (refcount is set to 1 at creation) 5653 OsclRefCounterDA *my_refcnt; 5654 PVMFMediaDataImpl* media_data_ptr; 5655 5656 if (iOMXComponentUsesFullAVCFrames && iNumNALs > 0) 5657 { 5658 uint32 ii; 5659 media_data_ptr = OSCL_NEW(PVMFMediaFragGroup<OsclMemAllocator>, (iNumNALs)); 5660 my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterDA(media_data_ptr, cleanup_ptr)); 5661 5662 // loop through and assign a create a media fragment for each NAL 5663 for (ii = 0; ii < iNumNALs; ii++) 5664 { 5665 OsclMemoryFragment memFrag; 5666 5667 if (iOMXComponentUsesNALStartCodes) 5668 { 5669 // need to get NAL ptr from stored array, since start codes can be 3 or 4 bytes, 5670 // and the only way to know is by parsing the buffer (which we should have done by now and stored in the array) 5671 memFrag.ptr = iNALPtrArray[ii]; 5672 } 5673 else 5674 { 5675 memFrag.ptr = pData; 5676 pData += iNALSizeArray[ii]; 5677 } 5678 5679 memFrag.len = iNALSizeArray[ii]; 5680 5681 OsclRefCounterMemFrag refCountMemFragOut(memFrag, my_refcnt, memFrag.len); 5682 media_data_ptr->appendMediaFragment(refCountMemFragOut); 5683 } 5684 5685 oscl_memset((void *) iNALSizeArray, 0, sizeof(uint32) * iNumNALs); 5686 iNumNALs = 0; 5687 } 5688 else 5689 { 5690 media_data_ptr = OSCL_NEW(PVMFMediaFragGroup<OsclMemAllocator>, (1)); 5691 my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterDA(media_data_ptr, cleanup_ptr)); 5692 5693 OsclMemoryFragment memFrag; 5694 5695 if (iOMXComponentUsesNALStartCodes && (iOutFormat != PVMF_MIME_H264_VIDEO_RAW)) 5696 { 5697 // skip start code 5698 pData += iFirstNALStartCodeSize; 5699 aDataLen -= iFirstNALStartCodeSize; 5700 } 5701 5702 memFrag.ptr = pData; 5703 memFrag.len = aDataLen; 5704 5705 OsclRefCounterMemFrag refCountMemFragOut(memFrag, my_refcnt, memFrag.len); 5706 media_data_ptr->appendMediaFragment(refCountMemFragOut); 5707 } 5708 5709 OsclSharedPtr<PVMFMediaDataImpl> MediaDataImplOut(media_data_ptr, my_refcnt); 5710 5711 return MediaDataImplOut; 5712 } 5713 ////////////////////////////////////////////////////////////////////////////// 5714 bool PVMFOMXEncNode::SendBeginOfMediaStreamCommand() 5715 { 5716 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5717 (0, "PVMFOMXEncNode-%s::SendBeginOfMediaStreamCommand() In", iNodeTypeId)); 5718 5719 PVMFSharedMediaCmdPtr sharedMediaCmdPtr = PVMFMediaCmd::createMediaCmd(); 5720 // Set the formatID, timestamp, sequenceNumber and streamID for the media message 5721 sharedMediaCmdPtr->setFormatID(PVMF_MEDIA_CMD_BOS_FORMAT_ID); 5722 sharedMediaCmdPtr->setTimestamp(iBOSTimestamp); 5723 //reset the sequence number 5724 uint32 seqNum = 0; 5725 sharedMediaCmdPtr->setSeqNum(seqNum); 5726 sharedMediaCmdPtr->setStreamID(iStreamID); 5727 5728 PVMFSharedMediaMsgPtr mediaMsgOut; 5729 convertToPVMFMediaCmdMsg(mediaMsgOut, sharedMediaCmdPtr); 5730 if (iOutPort->QueueOutgoingMsg(mediaMsgOut) != PVMFSuccess) 5731 { 5732 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5733 (0, "PVMFOMXEncNode-%s::SendBeginOfMediaStreamCommand() Outgoing queue busy", iNodeTypeId)); 5734 return false; 5735 } 5736 5737 iSendBOS = false; 5738 5739 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5740 (0, "PVMFOMXEncNode-%s::SendBeginOfMediaStreamCommand() BOS Sent StreamID %d", iNodeTypeId, iStreamID)); 5741 return true; 5742 } 5743 //////////////////////////////////// 5744 bool PVMFOMXEncNode::SendEndOfTrackCommand(void) 5745 { 5746 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5747 (0, "PVMFOMXEncNode-%s::SendEndOfTrackCommand() In", iNodeTypeId)); 5748 5749 PVMFSharedMediaCmdPtr sharedMediaCmdPtr = PVMFMediaCmd::createMediaCmd(); 5750 5751 sharedMediaCmdPtr->setFormatID(PVMF_MEDIA_CMD_EOS_FORMAT_ID); 5752 5753 // Set the timestamp 5754 sharedMediaCmdPtr->setTimestamp(iEndOfDataTimestamp); 5755 5756 // Set Streamid 5757 sharedMediaCmdPtr->setStreamID(iStreamID); 5758 5759 // Set the sequence number 5760 sharedMediaCmdPtr->setSeqNum(iSeqNum++); 5761 5762 PVMFSharedMediaMsgPtr mediaMsgOut; 5763 convertToPVMFMediaCmdMsg(mediaMsgOut, sharedMediaCmdPtr); 5764 if (iOutPort->QueueOutgoingMsg(mediaMsgOut) != PVMFSuccess) 5765 { 5766 // this should not happen because we check for queue busy before calling this function 5767 return false; 5768 } 5769 5770 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5771 (0, "PVMFOMXEncNode-%s::SendEndOfTrackCommand() Out", iNodeTypeId)); 5772 return true; 5773 } 5774 5775 ///////////////////////////////////////////////////////////////////////////// 5776 //The various command handlers call this routine when a command is complete. 5777 ///////////////////////////////////////////////////////////////////////////// 5778 void PVMFOMXEncNode::CommandComplete(PVMFOMXEncNodeCmdQ& aCmdQ, PVMFOMXEncNodeCommand& aCmd, PVMFStatus aStatus, OsclAny* aEventData) 5779 { 5780 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::CommandComplete Id %d Cmd %d Status %d Context %d Data %d", iNodeTypeId 5781 , aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData)); 5782 5783 //create response 5784 PVMFCmdResp resp(aCmd.iId, aCmd.iContext, aStatus, aEventData); 5785 PVMFSessionId session = aCmd.iSession; 5786 5787 //Erase the command from the queue. 5788 aCmdQ.Erase(&aCmd); 5789 5790 //Report completion to the session observer. 5791 ReportCmdCompleteEvent(session, resp); 5792 } 5793 5794 ///////////////////////////////////////////////////////////////////////////// 5795 void PVMFOMXEncNode::DoInit(PVMFOMXEncNodeCommand& aCmd) 5796 { 5797 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoInit() In", iNodeTypeId)); 5798 switch (iInterfaceState) 5799 { 5800 case EPVMFNodeIdle: 5801 { 5802 SetState(EPVMFNodeInitialized); 5803 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 5804 break; 5805 } 5806 5807 default: 5808 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 5809 break; 5810 } 5811 } 5812 5813 ///////////////////////////////////////////////////////////////////////////// 5814 void PVMFOMXEncNode::DoPrepare(PVMFOMXEncNodeCommand& aCmd) 5815 { 5816 OMX_ERRORTYPE err = OMX_ErrorNone; 5817 OMX_STRING Role = NULL; 5818 5819 switch (iInterfaceState) 5820 { 5821 case EPVMFNodeInitialized: 5822 { 5823 if (NULL == iInPort) 5824 { 5825 CommandComplete(iInputCommands, aCmd, PVMFFailure); 5826 } 5827 5828 5829 // by now the encode parameters have been set 5830 5831 if (iOutFormat == PVMF_MIME_H2631998 || 5832 iOutFormat == PVMF_MIME_H2632000) 5833 { 5834 Role = (OMX_STRING)"video_encoder.h263"; 5835 iNodeTypeId = LOG_ID_VIDEO_H263; 5836 } 5837 else if (iOutFormat == PVMF_MIME_M4V) 5838 { 5839 Role = (OMX_STRING)"video_encoder.mpeg4"; 5840 iNodeTypeId = LOG_ID_VIDEO_M4V; 5841 } 5842 else if (iOutFormat == PVMF_MIME_H264_VIDEO_RAW || 5843 iOutFormat == PVMF_MIME_H264_VIDEO_MP4) 5844 { 5845 Role = (OMX_STRING)"video_encoder.avc"; 5846 iNodeTypeId = LOG_ID_VIDEO_AVC; 5847 iFirstNAL = true; // set this flag to prevent node from queueing the first 5848 // buffer 5849 } 5850 else if ((iOutFormat == PVMF_MIME_AMR_IETF) || 5851 (iOutFormat == PVMF_MIME_AMR_IF2)) 5852 { 5853 Role = (OMX_STRING)"audio_encoder.amrnb"; 5854 iNodeTypeId = LOG_ID_AUDIO_AMRNB; 5855 } 5856 else if (iOutFormat == PVMF_MIME_AMRWB_IETF) 5857 { 5858 Role = (OMX_STRING)"audio_encoder.amrwb"; 5859 iNodeTypeId = LOG_ID_AUDIO_AMRWB; 5860 } 5861 else if (iOutFormat == PVMF_MIME_ADTS || 5862 iOutFormat == PVMF_MIME_ADIF || 5863 iOutFormat == PVMF_MIME_MPEG4_AUDIO) 5864 { 5865 Role = (OMX_STRING)"audio_encoder.aac"; 5866 iNodeTypeId = LOG_ID_AUDIO_AAC; 5867 } 5868 else 5869 { 5870 // Illegal codec specified. 5871 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoPrepare() Input port format other then codec type", iNodeTypeId)); 5872 CommandComplete(iInputCommands, aCmd, PVMFErrArgument); 5873 return; 5874 } 5875 5876 5877 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_DEBUG, 5878 (0, "PVMFOMXEncNode-%s::Initializing OMX component and encoder for role %s", iNodeTypeId, Role)); 5879 5880 /* Set callback structure */ 5881 iCallbacks.EventHandler = CallbackEventHandlerEnc; //event_handler; 5882 iCallbacks.EmptyBufferDone = CallbackEmptyBufferDoneEnc; //empty_buffer_done; 5883 iCallbacks.FillBufferDone = CallbackFillBufferDoneEnc; //fill_buffer_done; 5884 5885 5886 // determine components which can fit the role 5887 // then, create the component. If multiple components fit the role, 5888 // the first one registered will be selected. If that one fails to 5889 // be created, the second one in the list is selected etc. 5890 OMX_U32 num_comps = 0; 5891 OMX_STRING *CompOfRole; 5892 OMX_S8 CompName[PV_OMX_MAX_COMPONENT_NAME_LENGTH]; 5893 // call once to find out the number of components that can fit the role 5894 OMX_MasterGetComponentsOfRole(Role, &num_comps, NULL); 5895 uint32 ii; 5896 5897 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 5898 (0, "PVMFOMXEncNode-%s::DoPrepare(): There are %d components of role %s ", iNodeTypeId, num_comps, Role)); 5899 5900 if (num_comps > 0) 5901 { 5902 CompOfRole = (OMX_STRING *)oscl_malloc(num_comps * sizeof(OMX_STRING)); 5903 5904 for (ii = 0; ii < num_comps; ii++) 5905 CompOfRole[ii] = (OMX_STRING) oscl_malloc(PV_OMX_MAX_COMPONENT_NAME_LENGTH * sizeof(OMX_U8)); 5906 5907 // call 2nd time to get the component names 5908 OMX_MasterGetComponentsOfRole(Role, &num_comps, (OMX_U8 **)CompOfRole); 5909 5910 for (ii = 0; ii < num_comps; ii++) 5911 { 5912 // try to create component 5913 err = OMX_MasterGetHandle(&iOMXEncoder, (OMX_STRING) CompOfRole[ii], (OMX_PTR) this, (OMX_CALLBACKTYPE *) & iCallbacks); 5914 5915 if ((err == OMX_ErrorNone) && (iOMXEncoder != NULL)) 5916 { 5917 oscl_strncpy((OMX_STRING)CompName, (OMX_STRING) CompOfRole[ii], PV_OMX_MAX_COMPONENT_NAME_LENGTH); 5918 5919 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 5920 (0, "PVMFOMXEncNode-%s::DoPrepare(): Got Component %s handle ", iNodeTypeId, CompOfRole[ii])); 5921 LOGE("PVMFOMXEncNode-%s::DoPrepare(): Got Component %s handle ", iNodeTypeId, CompOfRole[ii]); 5922 5923 if ((CheckComponentForMultRoles((OMX_STRING)CompName, (OMX_STRING)CompOfRole[ii])) && 5924 (CheckComponentCapabilities(&iOutFormat))) 5925 { 5926 // Found a component and it passed all tests. Break out of the loop 5927 break; 5928 } 5929 } 5930 5931 // Component failed negotiations 5932 if (iOMXEncoder != NULL) 5933 { 5934 OMX_MasterFreeHandle(iOMXEncoder); 5935 iOMXEncoder = NULL; 5936 } 5937 } 5938 5939 // whether successful or not, need to free CompOfRoles 5940 for (ii = 0; ii < num_comps; ii++) 5941 { 5942 oscl_free(CompOfRole[ii]); 5943 CompOfRole[ii] = NULL; 5944 } 5945 5946 oscl_free(CompOfRole); 5947 // check if there was a problem 5948 if ((err != OMX_ErrorNone) || (iOMXEncoder == NULL)) 5949 { 5950 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 5951 (0, "PVMFOMXEncNode-%s::Can't get handle for encoder!", iNodeTypeId)); 5952 iOMXEncoder = NULL; 5953 CommandComplete(iInputCommands, aCmd, PVMFErrResource); 5954 return; 5955 } 5956 } 5957 else 5958 { 5959 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 5960 (0, "PVMFOMXEncNode-%s::No component can handle role %s !", iNodeTypeId, Role)); 5961 iOMXEncoder = NULL; 5962 CommandComplete(iInputCommands, aCmd, PVMFErrResource); 5963 return; 5964 } 5965 5966 if (!iOMXEncoder) 5967 { 5968 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources); 5969 return; 5970 } 5971 5972 // create active objects to handle callbacks in case of multithreaded implementation 5973 5974 // NOTE: CREATE THE THREADSAFE CALLBACK AOs REGARDLESS OF WHETHER MULTITHREADED COMPONENT OR NOT 5975 // If it is not multithreaded, we won't use them 5976 // The Flag iIsComponentMultiThreaded decides which mechanism is used for callbacks. 5977 // This flag is set by looking at component capabilities (or to true by default) 5978 5979 if (iThreadSafeHandlerEventHandler) 5980 { 5981 OSCL_DELETE(iThreadSafeHandlerEventHandler); 5982 iThreadSafeHandlerEventHandler = NULL; 5983 } 5984 // substitute default parameters: observer(this node),queuedepth(3),nameAO for logging 5985 // Get the priority of the encoder node, and set the threadsafe callback AO priority to 1 higher 5986 5987 iThreadSafeHandlerEventHandler = OSCL_NEW(EventHandlerThreadSafeCallbackAOEnc, (this, 10, "EventHandlerAO", Priority() + 2)); 5988 5989 if (iThreadSafeHandlerEmptyBufferDone) 5990 { 5991 OSCL_DELETE(iThreadSafeHandlerEmptyBufferDone); 5992 iThreadSafeHandlerEmptyBufferDone = NULL; 5993 } 5994 // use queue depth of iNumInputBuffers to prevent deadlock 5995 iThreadSafeHandlerEmptyBufferDone = OSCL_NEW(EmptyBufferDoneThreadSafeCallbackAOEnc, (this, iNumInputBuffers, "EmptyBufferDoneAO", Priority() + 1)); 5996 5997 if (iThreadSafeHandlerFillBufferDone) 5998 { 5999 OSCL_DELETE(iThreadSafeHandlerFillBufferDone); 6000 iThreadSafeHandlerFillBufferDone = NULL; 6001 } 6002 // use queue depth of iNumOutputBuffers to prevent deadlock 6003 iThreadSafeHandlerFillBufferDone = OSCL_NEW(FillBufferDoneThreadSafeCallbackAOEnc, (this, iNumOutputBuffers, "FillBufferDoneAO", Priority() + 1)); 6004 6005 if ((iThreadSafeHandlerEventHandler == NULL) || 6006 (iThreadSafeHandlerEmptyBufferDone == NULL) || 6007 (iThreadSafeHandlerFillBufferDone == NULL) 6008 ) 6009 { 6010 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 6011 (0, "PVMFOMXEncNode-%s::Can't get threadsafe callbacks for encoder!", iNodeTypeId)); 6012 iOMXEncoder = NULL; 6013 } 6014 6015 6016 // Init Encoder 6017 iCurrentEncoderState = OMX_StateLoaded; 6018 6019 /* Change state to OMX_StateIdle from OMX_StateLoaded. */ 6020 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 6021 (0, "PVMFOMXEncNode-%s::DoPrepare(): Changing Component state Loaded -> Idle ", iNodeTypeId)); 6022 6023 err = OMX_SendCommand(iOMXEncoder, OMX_CommandStateSet, OMX_StateIdle, NULL); 6024 if (err != OMX_ErrorNone) 6025 { 6026 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 6027 (0, "PVMFOMXEncNode-%s::DoPrepare() Can't send StateSet command!", iNodeTypeId)); 6028 6029 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources); 6030 return; 6031 } 6032 6033 6034 /* Allocate input buffers */ 6035 if (!CreateInputMemPool(iNumInputBuffers)) 6036 { 6037 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 6038 (0, "PVMFOMXEncNode-%s::DoPrepare() Can't allocate mempool for input buffers!", iNodeTypeId)); 6039 6040 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources); 6041 return; 6042 } 6043 6044 if (in_ctrl_struct_ptr) 6045 { 6046 oscl_free(in_ctrl_struct_ptr); 6047 in_ctrl_struct_ptr = NULL; 6048 } 6049 if (in_buff_hdr_ptr) 6050 { 6051 oscl_free(in_buff_hdr_ptr); 6052 in_buff_hdr_ptr = NULL; 6053 } 6054 6055 in_ctrl_struct_ptr = (OsclAny **) oscl_malloc(iNumInputBuffers * sizeof(OsclAny *)); 6056 6057 if (in_ctrl_struct_ptr == NULL) 6058 { 6059 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 6060 (0, "PVMFOMXEncNode-%s::DoPreapare in_ctrl_struct_ptr == NULL", iNodeTypeId)); 6061 6062 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources); 6063 return ; 6064 } 6065 6066 in_buff_hdr_ptr = (OsclAny **) oscl_malloc(iNumInputBuffers * sizeof(OsclAny *)); 6067 6068 if (in_buff_hdr_ptr == NULL) 6069 { 6070 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 6071 (0, "PVMFOMXEncNode-%s::DoPreapare in_buff_hdr_ptr == NULL", iNodeTypeId)); 6072 6073 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources); 6074 return ; 6075 } 6076 6077 6078 if (!ProvideBuffersToComponent(iInBufMemoryPool, // allocator 6079 iInputAllocSize, // size to allocate from pool (hdr only or hdr+ buffer) 6080 iNumInputBuffers, // number of buffers 6081 iOMXComponentInputBufferSize, // actual buffer size 6082 iInputPortIndex, // port idx 6083 iOMXComponentSupportsExternalInputBufferAlloc, // can component use OMX_UseBuffer 6084 true // this is input 6085 )) 6086 { 6087 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 6088 (0, "PVMFOMXEncNode-%s::DoPrepare() Component can't use input buffers!", iNodeTypeId)); 6089 6090 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources); 6091 return; 6092 } 6093 6094 6095 /* Allocate output buffers */ 6096 if (!CreateOutMemPool(iNumOutputBuffers)) 6097 { 6098 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 6099 (0, "PVMFOMXEncNode-%s::DoPrepare() Can't allocate mempool for output buffers!", iNodeTypeId)); 6100 6101 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources); 6102 return; 6103 } 6104 6105 if (out_ctrl_struct_ptr) 6106 { 6107 oscl_free(out_ctrl_struct_ptr); 6108 out_ctrl_struct_ptr = NULL; 6109 } 6110 if (out_buff_hdr_ptr) 6111 { 6112 oscl_free(out_buff_hdr_ptr); 6113 out_buff_hdr_ptr = NULL; 6114 } 6115 6116 out_ctrl_struct_ptr = (OsclAny **) oscl_malloc(iNumOutputBuffers * sizeof(OsclAny *)); 6117 6118 if (out_ctrl_struct_ptr == NULL) 6119 { 6120 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 6121 (0, "PVMFOMXEncNode-%s::DoPreapare out_ctrl_struct_ptr == NULL", iNodeTypeId)); 6122 6123 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources); 6124 return ; 6125 } 6126 6127 out_buff_hdr_ptr = (OsclAny **) oscl_malloc(iNumOutputBuffers * sizeof(OsclAny *)); 6128 6129 if (out_buff_hdr_ptr == NULL) 6130 { 6131 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 6132 (0, "PVMFOMXEncNode-%s::DoPreapare out_buff_hdr_ptr == NULL", iNodeTypeId)); 6133 6134 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources); 6135 return ; 6136 } 6137 6138 6139 if (!ProvideBuffersToComponent(iOutBufMemoryPool, // allocator 6140 iOutputAllocSize, // size to allocate from pool (hdr only or hdr+ buffer) 6141 iNumOutputBuffers, // number of buffers 6142 iOMXComponentOutputBufferSize, // actual buffer size 6143 iOutputPortIndex, // port idx 6144 iOMXComponentSupportsExternalOutputBufferAlloc, // can component use OMX_UseBuffer 6145 false // this is not input 6146 )) 6147 { 6148 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 6149 (0, "PVMFOMXEncNode-%s::DoPrepare() Component can't use output buffers!", iNodeTypeId)); 6150 6151 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources); 6152 return; 6153 } 6154 6155 6156 //this command is asynchronous. move the command from 6157 //the input command queue to the current command, where 6158 //it will remain until it completes. We have to wait for 6159 // OMX component state transition to complete 6160 6161 int32 err; 6162 OSCL_TRY(err, iCurrentCommand.StoreL(aCmd);); 6163 if (err != OsclErrNone) 6164 { 6165 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory); 6166 return; 6167 } 6168 iInputCommands.Erase(&aCmd); 6169 6170 } 6171 break; 6172 case EPVMFNodePrepared: 6173 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 6174 break; 6175 default: 6176 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 6177 break; 6178 } 6179 6180 } 6181 6182 ///////////////////////////////////////////////////////////////////////////// 6183 void PVMFOMXEncNode::DoStart(PVMFOMXEncNodeCommand& aCmd) 6184 { 6185 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoStart() In", iNodeTypeId)); 6186 6187 iDiagnosticsLogged = false; 6188 6189 PVMFStatus status = PVMFSuccess; 6190 6191 OMX_ERRORTYPE err; 6192 OMX_STATETYPE sState; 6193 6194 #ifdef _TEST_AE_ERROR_HANDLING 6195 if (FAIL_NODE_CMD_START == iErrorNodeCmd) 6196 { 6197 iInterfaceState = EPVMFNodeError; 6198 } 6199 #endif 6200 6201 6202 6203 switch (iInterfaceState) 6204 { 6205 case EPVMFNodePrepared: 6206 case EPVMFNodePaused: 6207 { 6208 //Get state of OpenMAX encoder 6209 err = OMX_GetState(iOMXEncoder, &sState); 6210 if (err != OMX_ErrorNone) 6211 { 6212 //Error condition report 6213 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 6214 (0, "PVMFOMXEncNode-%s::DoStart(): Can't get State of encoder!", iNodeTypeId)); 6215 6216 sState = OMX_StateInvalid; 6217 } 6218 #ifdef _TEST_AE_ERROR_HANDLING 6219 if (iErrorHandlingInit) 6220 { 6221 //some random state ,we want Init to fail 6222 6223 sState = OMX_StateInvalid; 6224 } 6225 #endif 6226 if ((sState == OMX_StateIdle) || (sState == OMX_StatePause)) 6227 { 6228 /* Change state to OMX_StateExecuting form OMX_StateIdle. */ 6229 // init the flag 6230 iDoNotSendOutputBuffersDownstreamFlag = false; // or if output was not being sent downstream due to state changes 6231 // re-anable sending output 6232 6233 iDoNotSaveInputBuffersFlag = false; 6234 6235 6236 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 6237 (0, "PVMFOMXEncNode-%s::DoStart() Changing Component state Idle->Executing", iNodeTypeId)); 6238 6239 err = OMX_SendCommand(iOMXEncoder, OMX_CommandStateSet, OMX_StateExecuting, NULL); 6240 if (err != OMX_ErrorNone) 6241 { 6242 //Error condition report 6243 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 6244 (0, "PVMFOMXEncNode-%s::DoStart(): Can't send StateSet command to encoder!", iNodeTypeId)); 6245 6246 status = PVMFErrInvalidState; 6247 } 6248 6249 } 6250 else 6251 { 6252 //Error condition report 6253 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 6254 (0, "PVMFOMXEncNode-%s::DoStart(): Encoder is not in the Idle or Pause state!", iNodeTypeId)); 6255 6256 status = PVMFErrInvalidState; 6257 } 6258 6259 6260 } 6261 break; 6262 6263 default: 6264 status = PVMFErrInvalidState; 6265 break; 6266 } 6267 6268 if (status == PVMFErrInvalidState) 6269 { 6270 CommandComplete(iInputCommands, aCmd, status); 6271 } 6272 else 6273 { 6274 //this command is asynchronous. move the command from 6275 //the input command queue to the current command, where 6276 //it will remain until it completes. 6277 int32 err; 6278 OSCL_TRY(err, iCurrentCommand.StoreL(aCmd);); 6279 if (err != OsclErrNone) 6280 { 6281 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory); 6282 } 6283 iInputCommands.Erase(&aCmd); 6284 } 6285 } 6286 6287 ///////////////////////////////////////////////////////////////////////////// 6288 void PVMFOMXEncNode::DoStop(PVMFOMXEncNodeCommand& aCmd) 6289 { 6290 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoStop() In", iNodeTypeId)); 6291 6292 LogDiagnostics(); 6293 6294 OMX_ERRORTYPE err; 6295 OMX_STATETYPE sState; 6296 #ifdef _TEST_AE_ERROR_HANDLING 6297 if (FAIL_NODE_CMD_STOP == iErrorNodeCmd) 6298 { 6299 iInterfaceState = EPVMFNodeError; 6300 } 6301 #endif 6302 switch (iInterfaceState) 6303 { 6304 case EPVMFNodeStarted: 6305 case EPVMFNodePaused: 6306 case EPVMFNodePrepared: 6307 // Stop data source 6308 // This will also prevent execution of HandleProcessingState 6309 6310 iDataIn.Unbind(); 6311 iPreviousMediaData.Unbind(); 6312 if ((iOutFormat == PVMF_MIME_H264_VIDEO_MP4) || (iOutFormat == PVMF_MIME_H264_VIDEO_RAW)) 6313 { 6314 // prepare for next start (if it comes) 6315 iFirstNAL = true; 6316 } 6317 // Clear queued messages in ports 6318 if (iInPort) 6319 { 6320 iInPort->ClearMsgQueues(); 6321 } 6322 6323 if (iOutPort) 6324 { 6325 iOutPort->ClearMsgQueues(); 6326 } 6327 6328 // Clear the data flags 6329 6330 iEndOfDataReached = false; 6331 iIsEOSSentToComponent = false; 6332 iIsEOSReceivedFromComponent = false; 6333 6334 6335 iDoNotSendOutputBuffersDownstreamFlag = true; // stop sending output buffers downstream 6336 iDoNotSaveInputBuffersFlag = true; 6337 6338 6339 //Get state of OpenMAX encoder 6340 err = OMX_GetState(iOMXEncoder, &sState); 6341 if (err != OMX_ErrorNone) 6342 { 6343 //Error condition report 6344 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 6345 (0, "PVMFOMXEncNode-%s::DoStop(): Can't get State of encoder!", iNodeTypeId)); 6346 6347 sState = OMX_StateInvalid; 6348 } 6349 6350 if ((sState == OMX_StateExecuting) || (sState == OMX_StatePause)) 6351 { 6352 /* Change state to OMX_StateIdle from OMX_StateExecuting or OMX_StatePause. */ 6353 6354 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 6355 (0, "PVMFOMXEncNode-%s::DoStop() Changing Component State Executing->Idle or Pause->Idle", iNodeTypeId)); 6356 6357 err = OMX_SendCommand(iOMXEncoder, OMX_CommandStateSet, OMX_StateIdle, NULL); 6358 if (err != OMX_ErrorNone) 6359 { 6360 //Error condition report 6361 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 6362 (0, "PVMFOMXEncNode-%s::DoStop(): Can't send StateSet command to encoder!", iNodeTypeId)); 6363 6364 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 6365 break; 6366 } 6367 6368 // prevent the node from sending more buffers etc. 6369 // if port reconfiguration is in process, let the state remain one of the port config states 6370 // if there is a start command, we can do it seemlessly (by continuing the port reconfig) 6371 if (iProcessingState == EPVMFOMXEncNodeProcessingState_ReadyToEncode) 6372 iProcessingState = EPVMFOMXEncNodeProcessingState_Stopping; 6373 6374 } 6375 else 6376 { 6377 //Error condition report 6378 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 6379 (0, "PVMFOMXEncNode-%s::DoStop(): Encoder is not in the Executing or Pause state!", iNodeTypeId)); 6380 6381 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 6382 break; 6383 } 6384 6385 //this command is asynchronous. move the command from 6386 //the input command queue to the current command, where 6387 //it will remain until it completes. 6388 int32 err; 6389 OSCL_TRY(err, iCurrentCommand.StoreL(aCmd);); 6390 if (err != OsclErrNone) 6391 { 6392 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory); 6393 return; 6394 } 6395 iInputCommands.Erase(&aCmd); 6396 6397 break; 6398 6399 default: 6400 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 6401 break; 6402 } 6403 } 6404 6405 ///////////////////////////////////////////////////////////////////////////// 6406 void PVMFOMXEncNode::DoFlush(PVMFOMXEncNodeCommand& aCmd) 6407 { 6408 #ifdef _TEST_AE_ERROR_HANDLING 6409 if (FAIL_NODE_CMD_FLUSH == iErrorNodeCmd) 6410 { 6411 iInterfaceState = EPVMFNodeError; 6412 } 6413 #endif 6414 switch (iInterfaceState) 6415 { 6416 case EPVMFNodeStarted: 6417 case EPVMFNodePaused: 6418 //the flush is asynchronous. move the command from 6419 //the input command queue to the current command, where 6420 //it will remain until the flush completes. 6421 int32 err; 6422 OSCL_TRY(err, iCurrentCommand.StoreL(aCmd);); 6423 if (err != OsclErrNone) 6424 { 6425 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory); 6426 return; 6427 } 6428 iInputCommands.Erase(&aCmd); 6429 6430 //Notify all ports to suspend their input 6431 if (iInPort) 6432 { 6433 iInPort->SuspendInput(); 6434 } 6435 RunIfNotReady(); 6436 if (iOutPort) 6437 { 6438 iOutPort->SuspendInput(); 6439 } 6440 // Stop data source 6441 6442 // DV: Sending "OMX_CommandFlush" to the encoder; 6443 // Not used because PV Flush command expects data to be processed before getting out 6444 iDoNotSendOutputBuffersDownstreamFlag = true; // collect output buffers 6445 6446 break; 6447 6448 default: 6449 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 6450 break; 6451 } 6452 } 6453 6454 ///////////////////////////////////////////////////////////////////////////// 6455 void PVMFOMXEncNode::DoPause(PVMFOMXEncNodeCommand& aCmd) 6456 { 6457 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoPause() In", iNodeTypeId)); 6458 6459 OMX_ERRORTYPE err; 6460 OMX_STATETYPE sState; 6461 #ifdef _TEST_AE_ERROR_HANDLING 6462 if (FAIL_NODE_CMD_PAUSE == iErrorNodeCmd) 6463 { 6464 iInterfaceState = EPVMFNodeError; 6465 } 6466 #endif 6467 6468 switch (iInterfaceState) 6469 { 6470 case EPVMFNodeStarted: 6471 6472 6473 //Get state of OpenMAX encoder 6474 err = OMX_GetState(iOMXEncoder, &sState); 6475 if (err != OMX_ErrorNone) 6476 { 6477 //Error condition report 6478 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 6479 (0, "PVMFOMXEncNode-%s::DoPause(): Can't get State of encoder!", iNodeTypeId)); 6480 6481 sState = OMX_StateInvalid; 6482 } 6483 6484 if (sState == OMX_StateExecuting) 6485 { 6486 /* Change state to OMX_StatePause from OMX_StateExecuting. */ 6487 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 6488 (0, "PVMFOMXEncNode-%s::DoPause() Changing Component State Executing->Idle", iNodeTypeId)); 6489 6490 err = OMX_SendCommand(iOMXEncoder, OMX_CommandStateSet, OMX_StatePause, NULL); 6491 if (err != OMX_ErrorNone) 6492 { 6493 //Error condition report 6494 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 6495 (0, "PVMFOMXEncNode-%s::DoPause(): Can't send StateSet command to encoder!", iNodeTypeId)); 6496 6497 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 6498 break; 6499 } 6500 6501 } 6502 else 6503 { 6504 //Error condition report 6505 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 6506 (0, "PVMFOMXEncNode-%s::DoPause(): Encoder is not in the Executing state!", iNodeTypeId)); 6507 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 6508 break; 6509 } 6510 6511 //this command is asynchronous. move the command from 6512 //the input command queue to the current command, where 6513 //it will remain until it completes. 6514 int32 err; 6515 OSCL_TRY(err, iCurrentCommand.StoreL(aCmd);); 6516 if (err != OsclErrNone) 6517 { 6518 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory); 6519 return; 6520 } 6521 iInputCommands.Erase(&aCmd); 6522 6523 break; 6524 default: 6525 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 6526 break; 6527 } 6528 } 6529 6530 ///////////////////////////////////////////////////////////////////////////// 6531 void PVMFOMXEncNode::DoReset(PVMFOMXEncNodeCommand& aCmd) 6532 { 6533 6534 OMX_ERRORTYPE err; 6535 OMX_STATETYPE sState; 6536 6537 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 6538 (0, "PVMFOMXEncNode-%s::DoReset() In", iNodeTypeId)); 6539 6540 LogDiagnostics(); 6541 6542 switch (iInterfaceState) 6543 { 6544 case EPVMFNodeIdle: 6545 case EPVMFNodeInitialized: 6546 case EPVMFNodePrepared: 6547 case EPVMFNodeStarted: 6548 case EPVMFNodePaused: 6549 case EPVMFNodeError: 6550 { 6551 //Check if encoder is initilized 6552 if (iOMXEncoder != NULL) 6553 { 6554 //Get state of OpenMAX encoder 6555 err = OMX_GetState(iOMXEncoder, &sState); 6556 if (err != OMX_ErrorNone) 6557 { 6558 sState = OMX_StateInvalid; 6559 } 6560 6561 if (sState == OMX_StateLoaded) 6562 { 6563 // this is a value obtained by synchronous call to component. Either the component was 6564 // already in this state without node issuing any commands, 6565 // or perhaps we started the Reset, but the callback notification has not yet arrived. 6566 if (iResetInProgress) 6567 { 6568 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 6569 (0, "PVMFOMXEncNode-%s::DoReset() OMX comp is in loaded state. Wait for official callback to change variables etc.", iNodeTypeId)); 6570 return; 6571 } 6572 } 6573 else if (sState == OMX_StateIdle) 6574 { 6575 //this command is asynchronous. move the command from 6576 //the input command queue to the current command, where 6577 //it will remain until it is completed. 6578 if (!iResetInProgress) 6579 { 6580 int32 err; 6581 OSCL_TRY(err, iCurrentCommand.StoreL(aCmd);); 6582 if (err != OsclErrNone) 6583 { 6584 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory); 6585 return; 6586 } 6587 iInputCommands.Erase(&aCmd); 6588 6589 iResetInProgress = true; 6590 } 6591 6592 // if buffers aren't all back (due to timing issues with different callback AOs 6593 // state change can be reported before all buffers are returned) 6594 if (iNumOutstandingInputBuffers > 0 || iNumOutstandingOutputBuffers > 0) 6595 { 6596 LOGE("PVMFOMXEncNode-%s::DoReset() Waiting for %d input and-or %d output buffers", iNodeTypeId, iNumOutstandingInputBuffers, iNumOutstandingOutputBuffers); 6597 6598 return; 6599 } 6600 6601 if (!iResetMsgSent) 6602 { 6603 // We can come here only if all buffers are already back 6604 // Don't repeat any of this twice. 6605 /* Change state to OMX_StateLoaded form OMX_StateIdle. */ 6606 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 6607 (0, "PVMFOMXEncNode-%s::DoReset() Changing Component State Idle->Loaded", iNodeTypeId)); 6608 6609 err = OMX_SendCommand(iOMXEncoder, OMX_CommandStateSet, OMX_StateLoaded, NULL); 6610 if (err != OMX_ErrorNone) 6611 { 6612 //Error condition report 6613 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 6614 (0, "PVMFOMXEncNode-%s::DoReset(): Can't send StateSet command to encoder!", iNodeTypeId)); 6615 } 6616 6617 iResetMsgSent = true; 6618 6619 6620 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 6621 (0, "PVMFOMXEncNode-%s::DoReset() freeing output buffers", iNodeTypeId)); 6622 6623 if (false == iOutputBuffersFreed) 6624 { 6625 if (!FreeBuffersFromComponent(iOutBufMemoryPool, // allocator 6626 iOutputAllocSize, // size to allocate from pool (hdr only or hdr+ buffer) 6627 iNumOutputBuffers, // number of buffers 6628 iOutputPortIndex, // port idx 6629 false // this is not input 6630 )) 6631 { 6632 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 6633 (0, "PVMFOMXEncNode-%s::DoReset() Cannot free output buffers ", iNodeTypeId)); 6634 6635 if (iResetInProgress) 6636 { 6637 iResetInProgress = false; 6638 if ((iCurrentCommand.size() > 0) && 6639 (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_RESET) 6640 ) 6641 { 6642 CommandComplete(iCurrentCommand, iCurrentCommand.front() , PVMFErrResource); 6643 } 6644 } 6645 6646 } 6647 6648 } 6649 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 6650 (0, "PVMFOMXEncNode-%s::DoReset() freeing input buffers ", iNodeTypeId)); 6651 if (false == iInputBuffersFreed) 6652 { 6653 if (!FreeBuffersFromComponent(iInBufMemoryPool, // allocator 6654 iInputAllocSize, // size to allocate from pool (hdr only or hdr+ buffer) 6655 iNumInputBuffers, // number of buffers 6656 iInputPortIndex, // port idx 6657 true // this is input 6658 )) 6659 { 6660 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 6661 (0, "PVMFOMXEncNode-%s::DoReset() Cannot free input buffers ", iNodeTypeId)); 6662 6663 if (iResetInProgress) 6664 { 6665 iResetInProgress = false; 6666 if ((iCurrentCommand.size() > 0) && 6667 (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_RESET) 6668 ) 6669 { 6670 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFErrResource); 6671 } 6672 } 6673 6674 6675 } 6676 } 6677 6678 6679 6680 iEndOfDataReached = false; 6681 iIsEOSSentToComponent = false; 6682 iIsEOSReceivedFromComponent = false; 6683 6684 6685 6686 // also, perform Port deletion when the component replies with the command 6687 // complete, not right here 6688 } // end of if(iResetMsgSent) 6689 6690 6691 return; 6692 6693 } 6694 else if ((sState == OMX_StateExecuting) || (sState == OMX_StatePause)) 6695 { 6696 //this command is asynchronous. move the command from 6697 //the input command queue to the current command, where 6698 //it will remain until it is completed. 6699 if (!iResetInProgress) 6700 { 6701 int32 err; 6702 OSCL_TRY(err, iCurrentCommand.StoreL(aCmd);); 6703 if (err != OsclErrNone) 6704 { 6705 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory); 6706 return; 6707 } 6708 iInputCommands.Erase(&aCmd); 6709 6710 iResetInProgress = true; 6711 } 6712 6713 /* Change state to OMX_StateIdle from OMX_StateExecuting or OMX_StatePause. */ 6714 6715 if (!iStopInResetMsgSent) 6716 { 6717 6718 // don't send twice in a row 6719 6720 iDataIn.Unbind(); 6721 iPreviousMediaData.Unbind(); 6722 if ((iOutFormat == PVMF_MIME_H264_VIDEO_MP4) || (iOutFormat == PVMF_MIME_H264_VIDEO_RAW)) 6723 { 6724 // prepare for next start (if it comes) 6725 iFirstNAL = true; 6726 } 6727 // Clear queued messages in ports 6728 if (iInPort) 6729 { 6730 iInPort->ClearMsgQueues(); 6731 } 6732 6733 if (iOutPort) 6734 { 6735 iOutPort->ClearMsgQueues(); 6736 } 6737 6738 // Clear the data flags 6739 6740 iEndOfDataReached = false; 6741 iIsEOSSentToComponent = false; 6742 iIsEOSReceivedFromComponent = false; 6743 6744 6745 iDoNotSendOutputBuffersDownstreamFlag = true; // stop sending output buffers downstream 6746 iDoNotSaveInputBuffersFlag = true; 6747 6748 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 6749 (0, "PVMFOMXEncNode-%s::DoReset() Changing Component State Executing->Idle or Pause->Idle", iNodeTypeId)); 6750 6751 err = OMX_SendCommand(iOMXEncoder, OMX_CommandStateSet, OMX_StateIdle, NULL); 6752 if (err != OMX_ErrorNone) 6753 { 6754 //Error condition report 6755 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 6756 (0, "PVMFOMXEncNode-%s::DoReset(): Can't send StateSet command to Encoder!", iNodeTypeId)); 6757 6758 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 6759 break; 6760 } 6761 6762 iStopInResetMsgSent = true; 6763 6764 // prevent the node from sending more buffers etc. 6765 // if port reconfiguration is in process, let the state remain one of the port config states 6766 // if there is a start command, we can do it seemlessly (by continuing the port reconfig) 6767 if (iProcessingState == EPVMFOMXEncNodeProcessingState_ReadyToEncode) 6768 iProcessingState = EPVMFOMXEncNodeProcessingState_Stopping; 6769 } 6770 return; 6771 } 6772 else 6773 { 6774 //Error condition report 6775 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 6776 (0, "PVMFOMXEncNode-%s::DoReset(): Encoder is not in the Idle state! %d", iNodeTypeId, sState )); 6777 //do it here rather than relying on DTOR to avoid node reinit problems. 6778 DeleteOMXEncoder(); 6779 //still return success. 6780 }//end of if (sState == OMX_StateLoaded) 6781 }//end of if (iOMXEncoder != NULL) 6782 6783 //delete all ports and notify observer. 6784 if (iInPort) 6785 { 6786 OSCL_DELETE(((PVMFOMXEncPort*)iInPort)); 6787 iInPort = NULL; 6788 } 6789 6790 if (iOutPort) 6791 { 6792 OSCL_DELETE(((PVMFOMXEncPort*)iOutPort)); 6793 iOutPort = NULL; 6794 } 6795 6796 iDataIn.Unbind(); 6797 6798 6799 // Reset the metadata key list 6800 iAvailableMetadataKeys.clear(); 6801 6802 iEndOfDataReached = false; 6803 iIsEOSSentToComponent = false; 6804 iIsEOSReceivedFromComponent = false; 6805 6806 6807 iProcessingState = EPVMFOMXEncNodeProcessingState_Idle; 6808 //logoff & go back to Created state. 6809 SetState(EPVMFNodeIdle); 6810 6811 6812 if (iResetInProgress) 6813 { 6814 iResetInProgress = false; 6815 if ((iCurrentCommand.size() > 0) && 6816 (iCurrentCommand.front().iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_RESET) 6817 ) 6818 { 6819 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess); 6820 } 6821 } 6822 else 6823 { 6824 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 6825 } 6826 6827 } 6828 break; 6829 6830 default: 6831 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 6832 break; 6833 } 6834 } 6835 6836 ///////////////////////////////////////////////////////////////////////////// 6837 void PVMFOMXEncNode::DoRequestPort(PVMFOMXEncNodeCommand& aCmd) 6838 { 6839 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 6840 (0, "PVMFOMXEncNode-%s::DoRequestPort() In", iNodeTypeId)); 6841 //This node supports port request from any state 6842 6843 //retrieve port tag. 6844 int32 tag; 6845 OSCL_String* portconfig; 6846 6847 aCmd.PVMFOMXEncNodeCommandBase::Parse(tag, portconfig); 6848 6849 PVMFPortInterface* port = NULL; 6850 6851 6852 int32 leavecode = 0; 6853 //validate the tag... 6854 6855 switch (tag) 6856 { 6857 case PVMF_OMX_ENC_NODE_PORT_TYPE_INPUT: 6858 if (iInPort) 6859 { 6860 CommandComplete(iInputCommands, aCmd, PVMFFailure); 6861 break; 6862 } 6863 OSCL_TRY(leavecode, iInPort = OSCL_NEW(PVMFOMXEncPort, ((int32)tag, this, "OMXEncIn"));); 6864 if (leavecode || iInPort == NULL) 6865 { 6866 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 6867 (0, "PVMFOMXEncNode-%s::DoRequestPort: Error - Input port instantiation failed", iNodeTypeId)); 6868 CommandComplete(iInputCommands, aCmd, PVMFErrArgument); 6869 return; 6870 } 6871 6872 // if format was provided in mimestring, set it now. 6873 if (portconfig) 6874 { 6875 PVMFFormatType format = portconfig->get_str(); 6876 if (((PVMFOMXEncPort*)iInPort)->IsFormatSupported(format)) 6877 { 6878 ((PVMFOMXEncPort*)iInPort)->iFormat = format; 6879 } 6880 else 6881 { 6882 6883 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 6884 (0, "PVMFOMXEncNode-%s::DoRequestPort: Error - Input port does not support format %s", iNodeTypeId, format.getMIMEStrPtr())); 6885 OSCL_DELETE(((PVMFOMXEncPort*)iInPort)); 6886 iInPort = NULL; 6887 CommandComplete(iInputCommands, aCmd, PVMFErrArgument); 6888 return; 6889 } 6890 6891 } 6892 6893 6894 port = iInPort; 6895 break; 6896 6897 case PVMF_OMX_ENC_NODE_PORT_TYPE_OUTPUT: 6898 if (iOutPort) 6899 { 6900 CommandComplete(iInputCommands, aCmd, PVMFFailure); 6901 break; 6902 } 6903 OSCL_TRY(leavecode, iOutPort = OSCL_NEW(PVMFOMXEncPort, ((int32)tag, this, "OMXEncOut"))); 6904 if (leavecode || iOutPort == NULL) 6905 { 6906 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 6907 (0, "PVMFOMXEncNode-%s::DoRequestPort: Error - Output port instantiation failed", iNodeTypeId)); 6908 CommandComplete(iInputCommands, aCmd, PVMFErrArgument); 6909 return; 6910 } 6911 6912 // if format was provided in mimestring, set it now. 6913 if (portconfig) 6914 { 6915 PVMFFormatType format = portconfig->get_str(); 6916 if (((PVMFOMXEncPort*)iOutPort)->IsFormatSupported(format) && (SetCodecType(format) == PVMFSuccess)) 6917 { 6918 ((PVMFOMXEncPort*)iOutPort)->iFormat = format; 6919 } 6920 else 6921 { 6922 6923 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 6924 (0, "PVMFOMXEncNode-%s::DoRequestPort: Error - Output port does not support format %s", iNodeTypeId, format.getMIMEStrPtr())); 6925 OSCL_DELETE(((PVMFOMXEncPort*)iOutPort)); 6926 iOutPort = NULL; 6927 CommandComplete(iInputCommands, aCmd, PVMFErrArgument); 6928 return; 6929 } 6930 6931 6932 } 6933 6934 port = iOutPort; 6935 break; 6936 6937 default: 6938 //bad port tag 6939 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 6940 (0, "PVMFOMXEncNode-%s::DoRequestPort: Error - Invalid port tag", iNodeTypeId)); 6941 CommandComplete(iInputCommands, aCmd, PVMFErrArgument); 6942 return; 6943 } 6944 6945 //Return the port pointer to the caller. 6946 CommandComplete(iInputCommands, aCmd, PVMFSuccess, (OsclAny*)port); 6947 } 6948 6949 ///////////////////////////////////////////////////////////////////////////// 6950 void PVMFOMXEncNode::DoReleasePort(PVMFOMXEncNodeCommand& aCmd) 6951 { 6952 PVMFPortInterface* temp; 6953 aCmd.PVMFOMXEncNodeCommandBase::Parse(temp); 6954 PVMFOMXEncPort* port = (PVMFOMXEncPort*) temp; 6955 #ifdef _TEST_AE_ERROR_HANDLING 6956 if (FAIL_NODE_CMD_RELEASE_PORT == iErrorNodeCmd) 6957 { 6958 port = NULL; 6959 } 6960 #endif 6961 6962 if (port != NULL && (port == iInPort || port == iOutPort)) 6963 { 6964 if (port == iInPort) 6965 { 6966 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 6967 (0, "PVMFOMXEncNode-%s::DoReleasePort Input port released", iNodeTypeId)); 6968 6969 OSCL_DELETE(((PVMFOMXEncPort*)iInPort)); 6970 iInPort = NULL; 6971 } 6972 else 6973 { 6974 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 6975 (0, "PVMFOMXEncNode-%s::DoReleasePort Output port released", iNodeTypeId)); 6976 6977 OSCL_DELETE(((PVMFOMXEncPort*)iOutPort)); 6978 iOutPort = NULL; 6979 } 6980 //delete the port. 6981 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 6982 } 6983 else 6984 { 6985 //port not found. 6986 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 6987 (0, "PVMFOMXEncNode-%s::DoReleasePort ERROR unknown port cannot be released", iNodeTypeId)); 6988 6989 CommandComplete(iInputCommands, aCmd, PVMFFailure); 6990 } 6991 } 6992 6993 ///////////////////////////////////////////////////////////////////////////// 6994 PVMFStatus PVMFOMXEncNode::DoGetNodeMetadataKey(PVMFOMXEncNodeCommand& aCmd) 6995 { 6996 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 6997 (0, "PVMFOMXEncNode-%s::DoGetNodeMetadataKey() In", iNodeTypeId)); 6998 6999 PVMFMetadataList* keylistptr = NULL; 7000 uint32 starting_index; 7001 int32 max_entries; 7002 char* query_key; 7003 7004 aCmd.PVMFOMXEncNodeCommand::Parse(keylistptr, starting_index, max_entries, query_key); 7005 7006 // Check parameters 7007 if (keylistptr == NULL) 7008 { 7009 // The list pointer is invalid 7010 return PVMFErrArgument; 7011 } 7012 7013 // Update the available metadata keys 7014 iAvailableMetadataKeys.clear(); 7015 int32 leavecode = 0; 7016 leavecode = Push_Back_MetadataKeys(PVOMXENCMETADATA_CODECINFO_VIDEO_FORMAT_KEY); 7017 7018 if (iYUVWidth > 0 && iYUVHeight > 0) 7019 { 7020 leavecode = 0; 7021 leavecode = Push_Back_MetadataKeys(PVOMXENCMETADATA_CODECINFO_VIDEO_WIDTH_KEY); 7022 if (0 == leavecode) 7023 leavecode = Push_Back_MetadataKeys(PVOMXENCMETADATA_CODECINFO_VIDEO_HEIGHT_KEY); 7024 } 7025 // add the profile, level and avgbitrate 7026 PVMF_MPEGVideoProfileType aProfile; 7027 PVMF_MPEGVideoLevelType aLevel; 7028 if (GetProfileAndLevel(aProfile, aLevel) == PVMFSuccess) 7029 { 7030 // For H263 this metadata will be available only after first frame decoding 7031 leavecode = 0; 7032 leavecode = Push_Back_MetadataKeys(PVOMXENCMETADATA_CODECINFO_VIDEO_PROFILE_KEY); 7033 if (0 == leavecode) 7034 leavecode = Push_Back_MetadataKeys(PVOMXENCMETADATA_CODECINFO_VIDEO_LEVEL_KEY); 7035 } 7036 if (0 == leavecode) 7037 leavecode = Push_Back_MetadataKeys(PVOMXENCMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY); 7038 7039 if ((starting_index > (iAvailableMetadataKeys.size() - 1)) || max_entries == 0) 7040 { 7041 // Invalid starting index and/or max entries 7042 return PVMFErrArgument; 7043 } 7044 7045 // Copy the requested keys 7046 uint32 num_entries = 0; 7047 int32 num_added = 0; 7048 for (uint32 lcv = 0; lcv < iAvailableMetadataKeys.size(); lcv++) 7049 { 7050 if (query_key == NULL) 7051 { 7052 // No query key so this key is counted 7053 ++num_entries; 7054 if (num_entries > starting_index) 7055 { 7056 // Past the starting index so copy the key 7057 leavecode = 0; 7058 leavecode = Push_Back_MetadataKeys(keylistptr, lcv); 7059 OSCL_FIRST_CATCH_ANY(leavecode, 7060 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 7061 (0, "PVMFOMXEncNode-%s::DoGetNodeMetadataKey() Memory allocation failure when copying metadata key", iNodeTypeId)); 7062 return PVMFErrNoMemory); 7063 num_added++; 7064 } 7065 } 7066 else 7067 { 7068 // Check if the key matche the query key 7069 if (pv_mime_strcmp(iAvailableMetadataKeys[lcv].get_cstr(), query_key) >= 0) 7070 { 7071 // This key is counted 7072 ++num_entries; 7073 if (num_entries > starting_index) 7074 { 7075 // Past the starting index so copy the key 7076 leavecode = 0; 7077 leavecode = Push_Back_MetadataKeys(keylistptr, lcv); 7078 OSCL_FIRST_CATCH_ANY(leavecode, 7079 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoGetNodeMetadataKey() Memory allocation failure when copying metadata key", iNodeTypeId)); 7080 return PVMFErrNoMemory); 7081 num_added++; 7082 } 7083 } 7084 } 7085 7086 // Check if max number of entries have been copied 7087 if (max_entries > 0 && num_added >= max_entries) 7088 { 7089 break; 7090 } 7091 } 7092 7093 return PVMFSuccess; 7094 } 7095 7096 ///////////////////////////////////////////////////////////////////////////// 7097 PVMFStatus PVMFOMXEncNode::DoGetNodeMetadataValue(PVMFOMXEncNodeCommand& aCmd) 7098 { 7099 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoGetNodeMetadataValue() In", iNodeTypeId)); 7100 7101 PVMFMetadataList* keylistptr = NULL; 7102 Oscl_Vector<PvmiKvp, OsclMemAllocator>* valuelistptr = NULL; 7103 uint32 starting_index; 7104 int32 max_entries; 7105 7106 aCmd.PVMFOMXEncNodeCommand::Parse(keylistptr, valuelistptr, starting_index, max_entries); 7107 7108 // Check the parameters 7109 if (keylistptr == NULL || valuelistptr == NULL) 7110 { 7111 return PVMFErrArgument; 7112 } 7113 7114 uint32 numkeys = keylistptr->size(); 7115 7116 if (starting_index > (numkeys - 1) || numkeys <= 0 || max_entries == 0) 7117 { 7118 // Don't do anything 7119 return PVMFErrArgument; 7120 } 7121 7122 uint32 numvalentries = 0; 7123 int32 numentriesadded = 0; 7124 for (uint32 lcv = 0; lcv < numkeys; lcv++) 7125 { 7126 int32 leavecode = 0; 7127 PvmiKvp KeyVal; 7128 KeyVal.key = NULL; 7129 uint32 KeyLen = 0; 7130 7131 if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_WIDTH_KEY) == 0) && 7132 iYUVWidth > 0) 7133 { 7134 // Video width 7135 // Increment the counter for the number of values found so far 7136 ++numvalentries; 7137 7138 // Create a value entry if past the starting index 7139 if (numvalentries > starting_index) 7140 { 7141 KeyLen = oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_WIDTH_KEY) + 1; // for "codec-info/video/width;" 7142 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype=" 7143 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator 7144 7145 // Allocate memory for the string 7146 leavecode = 0; 7147 leavecode = CreateNewArray(KeyVal.key, KeyLen); 7148 7149 7150 7151 if (leavecode == 0) 7152 { 7153 // Copy the key string 7154 oscl_strncpy(KeyVal.key, PVOMXENCMETADATA_CODECINFO_VIDEO_WIDTH_KEY, oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_WIDTH_KEY) + 1); 7155 oscl_strncat(KeyVal.key, PVOMXENCMETADATA_SEMICOLON, oscl_strlen(PVOMXENCMETADATA_SEMICOLON)); 7156 oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR)); 7157 oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR)); 7158 KeyVal.key[KeyLen-1] = NULL_TERM_CHAR; 7159 // Copy the value 7160 KeyVal.value.uint32_value = iYUVWidth; 7161 // Set the length and capacity 7162 KeyVal.length = 1; 7163 KeyVal.capacity = 1; 7164 } 7165 else 7166 { 7167 // Memory allocation failed 7168 KeyVal.key = NULL; 7169 break; 7170 } 7171 } 7172 } 7173 else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_HEIGHT_KEY) == 0) && 7174 iYUVHeight > 0) 7175 { 7176 // Video height 7177 // Increment the counter for the number of values found so far 7178 ++numvalentries; 7179 7180 // Create a value entry if past the starting index 7181 if (numvalentries > starting_index) 7182 { 7183 KeyLen = oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_HEIGHT_KEY) + 1; // for "codec-info/video/height;" 7184 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype=" 7185 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator 7186 7187 // Allocate memory for the string 7188 leavecode = 0; 7189 leavecode = CreateNewArray(KeyVal.key, KeyLen); 7190 7191 7192 7193 if (leavecode == 0) 7194 { 7195 // Copy the key string 7196 oscl_strncpy(KeyVal.key, PVOMXENCMETADATA_CODECINFO_VIDEO_HEIGHT_KEY, oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_HEIGHT_KEY) + 1); 7197 oscl_strncat(KeyVal.key, PVOMXENCMETADATA_SEMICOLON, oscl_strlen(PVOMXENCMETADATA_SEMICOLON)); 7198 oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR)); 7199 oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR)); 7200 KeyVal.key[KeyLen-1] = NULL_TERM_CHAR; 7201 // Copy the value 7202 KeyVal.value.uint32_value = iYUVHeight; 7203 // Set the length and capacity 7204 KeyVal.length = 1; 7205 KeyVal.capacity = 1; 7206 } 7207 else 7208 { 7209 // Memory allocation failed 7210 KeyVal.key = NULL; 7211 break; 7212 } 7213 } 7214 } 7215 else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_PROFILE_KEY) == 0)) 7216 { 7217 // Video profile 7218 // Increment the counter for the number of values found so far 7219 ++numvalentries; 7220 7221 // Create a value entry if past the starting index 7222 if (numvalentries > starting_index) 7223 { 7224 KeyLen = oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_PROFILE_KEY) + 1; // for "codec-info/video/profile;" 7225 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype=" 7226 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator 7227 7228 // Allocate memory for the string 7229 leavecode = 0; 7230 leavecode = CreateNewArray(KeyVal.key, KeyLen); 7231 7232 7233 7234 if (leavecode == 0) 7235 { 7236 PVMF_MPEGVideoProfileType aProfile; 7237 PVMF_MPEGVideoLevelType aLevel; 7238 if (GetProfileAndLevel(aProfile, aLevel) == PVMFSuccess) 7239 { 7240 // Copy the key string 7241 oscl_strncpy(KeyVal.key, PVOMXENCMETADATA_CODECINFO_VIDEO_PROFILE_KEY, oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_PROFILE_KEY) + 1); 7242 oscl_strncat(KeyVal.key, PVOMXENCMETADATA_SEMICOLON, oscl_strlen(PVOMXENCMETADATA_SEMICOLON)); 7243 oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR)); 7244 oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR)); 7245 KeyVal.key[KeyLen-1] = NULL_TERM_CHAR; 7246 // Copy the value 7247 KeyVal.value.uint32_value = (uint32)aProfile; // This is to be decided, who will interpret these value 7248 // Set the length and capacity 7249 KeyVal.length = 1; 7250 KeyVal.capacity = 1; 7251 } 7252 else 7253 { 7254 // Memory allocation failed 7255 KeyVal.key = NULL; 7256 break; 7257 } 7258 } 7259 else 7260 { 7261 // Memory allocation failed 7262 KeyVal.key = NULL; 7263 break; 7264 } 7265 } 7266 } 7267 else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_LEVEL_KEY) == 0)) 7268 { 7269 // Video level 7270 // Increment the counter for the number of values found so far 7271 ++numvalentries; 7272 7273 // Create a value entry if past the starting index 7274 if (numvalentries > starting_index) 7275 { 7276 KeyLen = oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_LEVEL_KEY) + 1; // for "codec-info/video/level;" 7277 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype=" 7278 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator 7279 7280 // Allocate memory for the string 7281 leavecode = 0; 7282 leavecode = CreateNewArray(KeyVal.key, KeyLen); 7283 7284 7285 7286 if (leavecode == 0) 7287 { 7288 PVMF_MPEGVideoProfileType aProfile; 7289 PVMF_MPEGVideoLevelType aLevel; 7290 if (GetProfileAndLevel(aProfile, aLevel) == PVMFSuccess) 7291 { 7292 // Copy the key string 7293 oscl_strncpy(KeyVal.key, PVOMXENCMETADATA_CODECINFO_VIDEO_LEVEL_KEY, oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_LEVEL_KEY) + 1); 7294 oscl_strncat(KeyVal.key, PVOMXENCMETADATA_SEMICOLON, oscl_strlen(PVOMXENCMETADATA_SEMICOLON)); 7295 oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR)); 7296 oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR)); 7297 KeyVal.key[KeyLen-1] = NULL_TERM_CHAR; 7298 // Copy the value 7299 KeyVal.value.uint32_value = (uint32)aLevel; // This is to be decided, who will interpret these value 7300 // Set the length and capacity 7301 KeyVal.length = 1; 7302 KeyVal.capacity = 1; 7303 } 7304 else 7305 { 7306 // Memory allocation failed 7307 KeyVal.key = NULL; 7308 break; 7309 } 7310 } 7311 else 7312 { 7313 // Memory allocation failed 7314 KeyVal.key = NULL; 7315 break; 7316 } 7317 } 7318 } 7319 else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY) == 0) && 7320 (iAvgBitrateValue > 0)) 7321 { 7322 // Video average bitrate 7323 // Increment the counter for the number of values found so far 7324 ++numvalentries; 7325 7326 // Create a value entry if past the starting index 7327 if (numvalentries > starting_index) 7328 { 7329 KeyLen = oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY) + 1; // for "codec-info/video/avgbitrate;" 7330 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype=" 7331 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator 7332 7333 // Allocate memory for the string 7334 leavecode = 0; 7335 leavecode = CreateNewArray(KeyVal.key, KeyLen); 7336 7337 7338 7339 if (leavecode == 0) 7340 { 7341 // Copy the key string 7342 oscl_strncpy(KeyVal.key, PVOMXENCMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY, oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY) + 1); 7343 oscl_strncat(KeyVal.key, PVOMXENCMETADATA_SEMICOLON, oscl_strlen(PVOMXENCMETADATA_SEMICOLON)); 7344 oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR)); 7345 oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR)); 7346 KeyVal.key[KeyLen-1] = NULL_TERM_CHAR; 7347 // Copy the value 7348 KeyVal.value.uint32_value = iAvgBitrateValue; 7349 // Set the length and capacity 7350 KeyVal.length = 1; 7351 KeyVal.capacity = 1; 7352 7353 } 7354 else 7355 { 7356 // Memory allocation failed 7357 KeyVal.key = NULL; 7358 break; 7359 } 7360 } 7361 } 7362 else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_FORMAT_KEY) == 0) && 7363 (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H2631998 || ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H2632000 || ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_M4V || 7364 ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO || ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_MP4 || 7365 ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_RAW || ((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_WMV)) 7366 { 7367 // Format 7368 // Increment the counter for the number of values found so far 7369 ++numvalentries; 7370 7371 // Create a value entry if past the starting index 7372 if (numvalentries > starting_index) 7373 { 7374 KeyLen = oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_FORMAT_KEY) + 1; // for "codec-info/video/format;" 7375 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype=" 7376 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_CHARPTR_STRING_CONSTCHAR) + 1; // for "char*" and NULL terminator 7377 7378 uint32 valuelen = 0; 7379 if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO) 7380 { 7381 valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_H264_VIDEO)) + 1; // Value string plus one for NULL terminator 7382 } 7383 else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_MP4) 7384 { 7385 valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_H264_VIDEO_MP4)) + 1; // Value string plus one for NULL terminator 7386 } 7387 else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_RAW) 7388 { 7389 valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_H264_VIDEO_RAW)) + 1; // Value string plus one for NULL terminator 7390 } 7391 else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_M4V) 7392 { 7393 valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_M4V)) + 1; // Value string plus one for NULL terminator 7394 } 7395 else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H2631998) 7396 { 7397 valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_H2631998)) + 1; // Value string plus one for NULL terminator 7398 } 7399 else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H2632000) 7400 { 7401 oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_H2632000), valuelen); 7402 } 7403 else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_WMV) 7404 { 7405 valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_WMV)) + 1; // Value string plus one for NULL terminator 7406 } 7407 else 7408 { 7409 // Should not enter here 7410 OSCL_ASSERT(false); 7411 valuelen = 1; 7412 } 7413 7414 // Allocate memory for the strings 7415 leavecode = 0; 7416 leavecode = CreateNewArray(KeyVal.key, KeyLen); 7417 if (0 == leavecode) 7418 { 7419 leavecode = CreateNewArray(KeyVal.value.pChar_value , valuelen); 7420 } 7421 7422 if (leavecode == 0) 7423 { 7424 // Copy the key string 7425 oscl_strncpy(KeyVal.key, PVOMXENCMETADATA_CODECINFO_VIDEO_FORMAT_KEY, oscl_strlen(PVOMXENCMETADATA_CODECINFO_VIDEO_FORMAT_KEY) + 1); 7426 oscl_strncat(KeyVal.key, PVOMXENCMETADATA_SEMICOLON, oscl_strlen(PVOMXENCMETADATA_SEMICOLON)); 7427 oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR)); 7428 oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_CHARPTR_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_CHARPTR_STRING_CONSTCHAR)); 7429 KeyVal.key[KeyLen-1] = NULL_TERM_CHAR; 7430 // Copy the value 7431 if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO) 7432 { 7433 oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_H264_VIDEO), valuelen); 7434 } 7435 else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_MP4) 7436 { 7437 oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_H264_VIDEO_MP4), valuelen); 7438 } 7439 else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H264_VIDEO_RAW) 7440 { 7441 oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_H264_VIDEO_RAW), valuelen); 7442 } 7443 else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_M4V) 7444 { 7445 oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_M4V), valuelen); 7446 } 7447 else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H2631998) 7448 { 7449 oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_H2631998), valuelen); 7450 } 7451 else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_H2632000) 7452 { 7453 oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_H2632000), valuelen); 7454 } 7455 else if (((PVMFOMXEncPort*)iInPort)->iFormat == PVMF_MIME_WMV) 7456 { 7457 oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_WMV), valuelen); 7458 } 7459 else 7460 { 7461 // Should not enter here 7462 OSCL_ASSERT(false); 7463 valuelen = 1; 7464 } 7465 7466 KeyVal.value.pChar_value[valuelen-1] = NULL_TERM_CHAR; 7467 // Set the length and capacity 7468 KeyVal.length = valuelen; 7469 KeyVal.capacity = valuelen; 7470 } 7471 else 7472 { 7473 // Memory allocation failed so clean up 7474 if (KeyVal.key) 7475 { 7476 OSCL_ARRAY_DELETE(KeyVal.key); 7477 KeyVal.key = NULL; 7478 } 7479 if (KeyVal.value.pChar_value) 7480 { 7481 OSCL_ARRAY_DELETE(KeyVal.value.pChar_value); 7482 } 7483 break; 7484 } 7485 } 7486 } 7487 7488 if (KeyVal.key != NULL) 7489 { 7490 leavecode = 0; 7491 leavecode = PushBackKeyVal(valuelistptr, KeyVal); 7492 if (leavecode != 0) 7493 { 7494 switch (GetValTypeFromKeyString(KeyVal.key)) 7495 { 7496 case PVMI_KVPVALTYPE_CHARPTR: 7497 if (KeyVal.value.pChar_value != NULL) 7498 { 7499 OSCL_ARRAY_DELETE(KeyVal.value.pChar_value); 7500 KeyVal.value.pChar_value = NULL; 7501 } 7502 break; 7503 7504 default: 7505 // Add more case statements if other value types are returned 7506 break; 7507 } 7508 7509 OSCL_ARRAY_DELETE(KeyVal.key); 7510 KeyVal.key = NULL; 7511 } 7512 else 7513 { 7514 // Increment the counter for number of value entries added to the list 7515 ++numentriesadded; 7516 } 7517 7518 // Check if the max number of value entries were added 7519 if (max_entries > 0 && numentriesadded >= max_entries) 7520 { 7521 break; 7522 } 7523 } 7524 } 7525 7526 return PVMFSuccess; 7527 } 7528 7529 ///////////////////////////////////////////////////////////////////////////// 7530 bool PVMFOMXEncNode::ReleaseAllPorts() 7531 { 7532 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::ReleaseAllPorts() In", iNodeTypeId)); 7533 7534 if (iInPort) 7535 { 7536 iInPort->ClearMsgQueues(); 7537 iInPort->Disconnect(); 7538 OSCL_DELETE(((PVMFOMXEncPort*)iInPort)); 7539 iInPort = NULL; 7540 } 7541 7542 if (iOutPort) 7543 { 7544 iOutPort->ClearMsgQueues(); 7545 iOutPort->Disconnect(); 7546 OSCL_DELETE(((PVMFOMXEncPort*)iOutPort)); 7547 iOutPort = NULL; 7548 } 7549 7550 return true; 7551 } 7552 7553 ///////////////////////////////////////////////////////////////////////////// 7554 // Clean Up Encoder 7555 ///////////////////////////////////////////////////////////////////////////// 7556 bool PVMFOMXEncNode::DeleteOMXEncoder() 7557 { 7558 OMX_ERRORTYPE err; 7559 7560 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 7561 (0, "PVMFOMXEncNode-%s::DeleteOMXEncoder() In", iNodeTypeId)); 7562 7563 if (iOMXEncoder != NULL) 7564 { 7565 /* Free Component handle. */ 7566 err = OMX_MasterFreeHandle(iOMXEncoder); 7567 if (err != OMX_ErrorNone) 7568 { 7569 //Error condition report 7570 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 7571 (0, "PVMFOMXEncNode-%s::DeleteOMXEncoder(): Can't free encoder's handle!", iNodeTypeId)); 7572 } 7573 iOMXEncoder = NULL; 7574 7575 }//end of if (iOMXEncoder != NULL) 7576 7577 7578 return true; 7579 } 7580 7581 ///////////////////////////////////////////////////////////////////////////// 7582 void PVMFOMXEncNode::ChangeNodeState(TPVMFNodeInterfaceState aNewState) 7583 { 7584 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::ChangeNodeState() Changing state from %d to %d", iNodeTypeId, iInterfaceState, aNewState)); 7585 iInterfaceState = aNewState; 7586 } 7587 7588 ///////////////////////////////////////////////////////////////////////////// 7589 void PVMFOMXEncNode::freechunkavailable(OsclAny *aContext) 7590 { 7591 7592 // check context to see whether input or output buffer was returned to the mempool 7593 if (aContext == (OsclAny *) iInBufMemoryPool) 7594 { 7595 7596 iNumOutstandingInputBuffers--; 7597 7598 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 7599 (0, "PVMFOMXEncNode-%s::freechunkavailable() Memory chunk in INPUT mempool was deallocated, %d out of %d now available", iNodeTypeId, iNumInputBuffers - iNumOutstandingInputBuffers, iNumInputBuffers)); 7600 7601 // notification only works once. 7602 // If there are multiple buffers coming back in a row, make sure to set the notification 7603 // flag in the mempool again, so that next buffer also causes notification 7604 iInBufMemoryPool->notifyfreechunkavailable(*this, aContext); 7605 7606 } 7607 else if (aContext == (OsclAny *) iOutBufMemoryPool) 7608 { 7609 7610 iNumOutstandingOutputBuffers--; 7611 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 7612 (0, "PVMFOMXEncNode-%s::freechunkavailable() Memory chunk in OUTPUT mempool was deallocated, %d out of %d now available", iNodeTypeId, iNumOutputBuffers - iNumOutstandingOutputBuffers, iNumOutputBuffers)); 7613 7614 // notification only works once. 7615 // If there are multiple buffers coming back in a row, make sure to set the notification 7616 // flag in the mempool again, so that next buffer also causes notification 7617 iOutBufMemoryPool->notifyfreechunkavailable(*this, aContext); 7618 7619 } 7620 else 7621 { 7622 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 7623 (0, "PVMFOMXEncNode-%s::freechunkavailable() UNKNOWN mempool ", iNodeTypeId)); 7624 7625 } 7626 7627 // reschedule 7628 if (IsAdded()) 7629 RunIfNotReady(); 7630 7631 7632 } 7633 7634 ///////////////////////////////////////////////////////////////////////////// 7635 void PVMFOMXEncNode::HandlePortActivity(const PVMFPortActivity &aActivity) 7636 { 7637 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 7638 (0, "0x%x PVMFOMXEncNode-%s::PortActivity: port=0x%x, type=%d", 7639 this, iNodeTypeId, aActivity.iPort, aActivity.iType)); 7640 7641 switch (aActivity.iType) 7642 { 7643 case PVMF_PORT_ACTIVITY_OUTGOING_MSG: 7644 //An outgoing message was queued on this port. 7645 //We only need to queue a port activity event on the 7646 //first message. Additional events will be queued during 7647 //the port processing as needed. 7648 if (aActivity.iPort->OutgoingMsgQueueSize() == 1) 7649 { 7650 //wake up the AO to process the port activity event. 7651 RunIfNotReady(); 7652 } 7653 break; 7654 7655 case PVMF_PORT_ACTIVITY_INCOMING_MSG: 7656 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 7657 (0, "PVMFOMXEncNode-%s::PortActivity: IncomingMsgQueueSize=%d", iNodeTypeId, aActivity.iPort->IncomingMsgQueueSize())); 7658 if (aActivity.iPort->IncomingMsgQueueSize() == 1) 7659 { 7660 //wake up the AO to process the port activity event. 7661 RunIfNotReady(); 7662 } 7663 break; 7664 7665 case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY: 7666 if (iProcessingState == EPVMFOMXEncNodeProcessingState_WaitForOutgoingQueue) 7667 { 7668 iProcessingState = EPVMFOMXEncNodeProcessingState_ReadyToEncode; 7669 RunIfNotReady(); 7670 } 7671 break; 7672 7673 case PVMF_PORT_ACTIVITY_CONNECT: 7674 //nothing needed. 7675 break; 7676 7677 case PVMF_PORT_ACTIVITY_DISCONNECT: 7678 //clear the node input data when either port is disconnected. 7679 7680 iDataIn.Unbind(); 7681 break; 7682 7683 case PVMF_PORT_ACTIVITY_CONNECTED_PORT_BUSY: 7684 // The connected port has become busy (its incoming queue is 7685 // busy). 7686 // No action is needed here-- the port processing code 7687 // checks for connected port busy during data processing. 7688 break; 7689 7690 case PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY: 7691 // The connected port has transitioned from Busy to Ready to Receive. 7692 // It's time to start processing outgoing messages again. 7693 7694 //iProcessingState should transition from WaitForOutputPort to ReadyToEncode 7695 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 7696 (0, "0x%x PVMFOMXEncNode-%s::PortActivity: Connected port is now ready", this, iNodeTypeId)); 7697 RunIfNotReady(); 7698 break; 7699 7700 default: 7701 break; 7702 } 7703 } 7704 7705 ///////////////////////////////////////////////////////////////////////////// 7706 void PVMFOMXEncNode::DoCancelAllCommands(PVMFOMXEncNodeCommand& aCmd) 7707 { 7708 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 7709 (0, "PVMFOMXEncNode-%s::DoCancelAllCommands", iNodeTypeId)); 7710 7711 //first cancel the current command if any 7712 { 7713 while (!iCurrentCommand.empty()) 7714 { 7715 CommandComplete(iCurrentCommand, iCurrentCommand[0], PVMFErrCancelled); 7716 } 7717 7718 } 7719 7720 //next cancel all queued commands 7721 { 7722 //start at element 1 since this cancel command is element 0. 7723 while (iInputCommands.size() > 1) 7724 { 7725 CommandComplete(iInputCommands, iInputCommands[1], PVMFErrCancelled); 7726 } 7727 } 7728 7729 if (iResetInProgress && !iResetMsgSent) 7730 { 7731 // if reset is started but reset msg has not been sent, we can cancel reset 7732 // as if nothing happened. Otherwise, the callback will set the flag back to false 7733 iResetInProgress = false; 7734 } 7735 //finally, report cancel complete. 7736 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 7737 } 7738 7739 ///////////////////////////////////////////////////////////////////////////// 7740 void PVMFOMXEncNode::DoCancelCommand(PVMFOMXEncNodeCommand& aCmd) 7741 { 7742 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 7743 (0, "PVMFOMXEncNode-%s::DoCancelCommand", iNodeTypeId)); 7744 7745 //extract the command ID from the parameters. 7746 PVMFCommandId id; 7747 aCmd.PVMFOMXEncNodeCommandBase::Parse(id); 7748 7749 //first check "current" command if any 7750 { 7751 PVMFOMXEncNodeCommand* cmd = iCurrentCommand.FindById(id); 7752 if (cmd) 7753 { 7754 7755 // if reset is being canceled: 7756 if (cmd->iCmd == PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_RESET) 7757 { 7758 if (iResetInProgress && !iResetMsgSent) 7759 { 7760 // if reset is started but reset msg has not been sent, we can cancel reset 7761 // as if nothing happened. Otherwise, the callback will set the flag back to false 7762 iResetInProgress = false; 7763 } 7764 } 7765 //cancel the queued command 7766 CommandComplete(iCurrentCommand, *cmd, PVMFErrCancelled); 7767 //report cancel success 7768 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 7769 return; 7770 } 7771 } 7772 7773 //next check input queue. 7774 { 7775 //start at element 1 since this cancel command is element 0. 7776 PVMFOMXEncNodeCommand* cmd = iInputCommands.FindById(id, 1); 7777 if (cmd) 7778 { 7779 //cancel the queued command 7780 CommandComplete(iInputCommands, *cmd, PVMFErrCancelled); 7781 //report cancel success 7782 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 7783 return; 7784 } 7785 } 7786 //if we get here the command isn't queued so the cancel fails. 7787 CommandComplete(iInputCommands, aCmd, PVMFErrArgument); 7788 } 7789 7790 ///////////////////////////////////////////////////////////////////////////// 7791 void PVMFOMXEncNode::DoQueryUuid(PVMFOMXEncNodeCommand& aCmd) 7792 { 7793 //This node supports Query UUID from any state 7794 7795 OSCL_String* mimetype; 7796 Oscl_Vector<PVUuid, OsclMemAllocator> *uuidvec; 7797 bool exactmatch; 7798 aCmd.PVMFOMXEncNodeCommandBase::Parse(mimetype, uuidvec, exactmatch); 7799 7800 //Try to match the input mimetype against any of 7801 //the custom interfaces for this node 7802 7803 //Match against custom interface1... 7804 if (*mimetype == PVMF_OMX_ENC_NODE_CUSTOM1_MIMETYPE 7805 //also match against base mimetypes for custom interface1, 7806 //unless exactmatch is set. 7807 || (!exactmatch && *mimetype == PVMF_OMX_ENC_NODE_MIMETYPE) 7808 || (!exactmatch && *mimetype == PVMF_BASEMIMETYPE)) 7809 { 7810 7811 PVUuid uuid(PVMF_OMX_ENC_NODE_CUSTOM1_UUID); 7812 uuidvec->push_back(uuid); 7813 } 7814 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 7815 } 7816 7817 ///////////////////////////////////////////////////////////////////////////// 7818 void PVMFOMXEncNode::DoQueryInterface(PVMFOMXEncNodeCommand& aCmd) 7819 { 7820 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 7821 (0, "PVMFOMXEncNode-%s::DoQueryInterface", iNodeTypeId)); 7822 PVUuid* uuid; 7823 PVInterface** ptr; 7824 aCmd.PVMFOMXEncNodeCommandBase::Parse(uuid, ptr); 7825 7826 if (*uuid == PVUuid(PVMF_OMX_ENC_NODE_CUSTOM1_UUID)) 7827 { 7828 addRef(); 7829 *ptr = (PVMFOMXEncNodeExtensionInterface*)this; 7830 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 7831 } 7832 else if (*uuid == PVUuid(KPVMFMetadataExtensionUuid)) 7833 { 7834 addRef(); 7835 *ptr = (PVMFMetadataExtensionInterface*)this; 7836 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 7837 } 7838 else if (*uuid == PVUuid(PVMI_CAPABILITY_AND_CONFIG_PVUUID)) 7839 { 7840 addRef(); 7841 *ptr = (PvmiCapabilityAndConfig*)this; 7842 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 7843 } 7844 else if (*uuid == PVMp4H263EncExtensionUUID) 7845 { 7846 addRef(); 7847 *ptr = OSCL_STATIC_CAST(PVMp4H263EncExtensionInterface*, this); 7848 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 7849 //iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 7850 7851 } 7852 else if (*uuid == PVAudioEncExtensionUUID) 7853 { 7854 addRef(); 7855 *ptr = OSCL_STATIC_CAST(PVAudioEncExtensionInterface*, this); 7856 //iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 7857 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 7858 7859 } 7860 else 7861 { 7862 //not supported 7863 *ptr = NULL; 7864 CommandComplete(iInputCommands, aCmd, PVMFFailure); 7865 } 7866 } 7867 7868 ///////////////////////////////////////////////////////////////////////////// 7869 void PVMFOMXEncNode::addRef() 7870 { 7871 ++iExtensionRefCount; 7872 } 7873 7874 ///////////////////////////////////////////////////////////////////////////// 7875 void PVMFOMXEncNode::removeRef() 7876 { 7877 --iExtensionRefCount; 7878 } 7879 7880 ///////////////////////////////////////////////////////////////////////////// 7881 bool PVMFOMXEncNode::queryInterface(const PVUuid& uuid, PVInterface*& iface) 7882 { 7883 PVUuid my_uuid(PVMF_OMX_ENC_NODE_CUSTOM1_UUID); 7884 if (uuid == my_uuid) 7885 { 7886 PVMFOMXEncNodeExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFOMXEncNodeExtensionInterface*, this); 7887 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 7888 ++iExtensionRefCount; 7889 return true; 7890 } 7891 else if (uuid == KPVMFMetadataExtensionUuid) 7892 { 7893 PVMFMetadataExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFMetadataExtensionInterface*, this); 7894 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 7895 ++iExtensionRefCount; 7896 return true; 7897 } 7898 return false; 7899 } 7900 7901 ///////////////////////////////////////////////////////////////////////////// 7902 uint32 PVMFOMXEncNode::GetNumMetadataKeys(char* aQueryKeyString) 7903 { 7904 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::GetNumMetadataKeys() called", iNodeTypeId)); 7905 7906 // Update the available metadata keys 7907 iAvailableMetadataKeys.clear(); 7908 int32 errcode = 0; 7909 OSCL_TRY(errcode, iAvailableMetadataKeys.push_back(PVOMXENCMETADATA_CODECINFO_VIDEO_FORMAT_KEY)); 7910 7911 if (iYUVWidth > 0 && iYUVHeight > 0) 7912 { 7913 errcode = 0; 7914 OSCL_TRY(errcode, 7915 iAvailableMetadataKeys.push_back(PVOMXENCMETADATA_CODECINFO_VIDEO_WIDTH_KEY); 7916 iAvailableMetadataKeys.push_back(PVOMXENCMETADATA_CODECINFO_VIDEO_HEIGHT_KEY)); 7917 } 7918 // add the profile, level and avgbitrate 7919 PVMF_MPEGVideoProfileType aProfile; 7920 PVMF_MPEGVideoLevelType aLevel; 7921 if (GetProfileAndLevel(aProfile, aLevel) == PVMFSuccess) 7922 { 7923 // For H263 this metadata will be available only after first frame decoding 7924 errcode = 0; 7925 OSCL_TRY(errcode, iAvailableMetadataKeys.push_back(PVOMXENCMETADATA_CODECINFO_VIDEO_PROFILE_KEY)); 7926 errcode = 0; 7927 OSCL_TRY(errcode, iAvailableMetadataKeys.push_back(PVOMXENCMETADATA_CODECINFO_VIDEO_LEVEL_KEY)); 7928 } 7929 errcode = 0; 7930 OSCL_TRY(errcode, iAvailableMetadataKeys.push_back(PVOMXENCMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY)); 7931 7932 7933 7934 uint32 num_entries = 0; 7935 7936 if (aQueryKeyString == NULL) 7937 { 7938 num_entries = iAvailableMetadataKeys.size(); 7939 } 7940 else 7941 { 7942 for (uint32 i = 0; i < iAvailableMetadataKeys.size(); i++) 7943 { 7944 if (pv_mime_strcmp(iAvailableMetadataKeys[i].get_cstr(), aQueryKeyString) >= 0) 7945 { 7946 num_entries++; 7947 } 7948 } 7949 } 7950 return num_entries; // Number of elements 7951 } 7952 7953 /////////////////////////////////////////////////////////////////////////////////////// 7954 void PVMFOMXEncNode::setObserver(PvmiConfigAndCapabilityCmdObserver* aObserver) 7955 { 7956 OSCL_UNUSED_ARG(aObserver); 7957 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::setObserver()", iNodeTypeId)); 7958 // This method is not supported so leave 7959 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::setObserver() is not supported!", iNodeTypeId)); 7960 OSCL_LEAVE(PVMFErrNotSupported); 7961 } 7962 7963 7964 PVMFStatus PVMFOMXEncNode::getParametersSync(PvmiMIOSession aSession, PvmiKeyType aIdentifier, PvmiKvp*& aParameters, int& aNumParamElements, PvmiCapabilityContext aContext) 7965 { 7966 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::getParametersSync()", iNodeTypeId)); 7967 OSCL_UNUSED_ARG(aSession); 7968 7969 return DoCapConfigGetParametersSync(aIdentifier, aParameters, aNumParamElements, aContext); 7970 } 7971 7972 7973 PVMFStatus PVMFOMXEncNode::releaseParameters(PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements) 7974 { 7975 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::releaseParameters()", iNodeTypeId)); 7976 OSCL_UNUSED_ARG(aSession); 7977 7978 return DoCapConfigReleaseParameters(aParameters, aNumElements); 7979 } 7980 7981 7982 void PVMFOMXEncNode::createContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext) 7983 { 7984 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::createContext()", iNodeTypeId)); 7985 OSCL_UNUSED_ARG(aSession); 7986 OSCL_UNUSED_ARG(aContext); 7987 // This method is not supported so leave 7988 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::createContext() is not supported!", iNodeTypeId)); 7989 OSCL_LEAVE(PVMFErrNotSupported); 7990 } 7991 7992 7993 void PVMFOMXEncNode::setContextParameters(PvmiMIOSession aSession, PvmiCapabilityContext& aContext, PvmiKvp* aParameters, int aNumParamElements) 7994 { 7995 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::setContextParameters()", iNodeTypeId)); 7996 OSCL_UNUSED_ARG(aSession); 7997 OSCL_UNUSED_ARG(aContext); 7998 OSCL_UNUSED_ARG(aParameters); 7999 OSCL_UNUSED_ARG(aNumParamElements); 8000 // This method is not supported so leave 8001 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::setContextParameters() is not supported!", iNodeTypeId)); 8002 OSCL_LEAVE(PVMFErrNotSupported); 8003 } 8004 8005 8006 void PVMFOMXEncNode::DeleteContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext) 8007 { 8008 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DeleteContext()", iNodeTypeId)); 8009 OSCL_UNUSED_ARG(aSession); 8010 OSCL_UNUSED_ARG(aContext); 8011 // This method is not supported so leave 8012 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DeleteContext() is not supported!", iNodeTypeId)); 8013 OSCL_LEAVE(PVMFErrNotSupported); 8014 } 8015 8016 8017 void PVMFOMXEncNode::setParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements, PvmiKvp* &aRetKVP) 8018 { 8019 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::setParametersSync()", iNodeTypeId)); 8020 OSCL_UNUSED_ARG(aSession); 8021 8022 // Complete the request synchronously 8023 DoCapConfigSetParameters(aParameters, aNumElements, aRetKVP); 8024 } 8025 8026 8027 PVMFCommandId PVMFOMXEncNode::setParametersAsync(PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements, PvmiKvp*& aRetKVP, OsclAny* aContext) 8028 { 8029 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::setParametersAsync()", iNodeTypeId)); 8030 OSCL_UNUSED_ARG(aSession); 8031 OSCL_UNUSED_ARG(aParameters); 8032 OSCL_UNUSED_ARG(aNumElements); 8033 OSCL_UNUSED_ARG(aRetKVP); 8034 OSCL_UNUSED_ARG(aContext); 8035 8036 // This method is not supported so leave 8037 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::setParametersAsync() is not supported!", iNodeTypeId)); 8038 OSCL_LEAVE(PVMFErrNotSupported); 8039 return 0; 8040 } 8041 8042 8043 uint32 PVMFOMXEncNode::getCapabilityMetric(PvmiMIOSession aSession) 8044 { 8045 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::getCapabilityMetric()", iNodeTypeId)); 8046 OSCL_UNUSED_ARG(aSession); 8047 // Not supported so return 0 8048 return 0; 8049 } 8050 8051 8052 PVMFStatus PVMFOMXEncNode::verifyParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements) 8053 { 8054 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::verifyParametersSync()", iNodeTypeId)); 8055 OSCL_UNUSED_ARG(aSession); 8056 8057 return DoCapConfigVerifyParameters(aParameters, aNumElements); 8058 } 8059 8060 8061 ///////////////////////////////////////////////////////////////////////////// 8062 uint32 PVMFOMXEncNode::GetNumMetadataValues(PVMFMetadataList& aKeyList) 8063 { 8064 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::GetNumMetadataValues() called", iNodeTypeId)); 8065 8066 uint32 numkeys = aKeyList.size(); 8067 8068 if (numkeys <= 0) 8069 { 8070 // Don't do anything 8071 return 0; 8072 } 8073 8074 // Count the number of value entries for the provided key list 8075 uint32 numvalentries = 0; 8076 PVMF_MPEGVideoProfileType aProfile; 8077 PVMF_MPEGVideoLevelType aLevel; 8078 for (uint32 lcv = 0; lcv < numkeys; lcv++) 8079 { 8080 if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_WIDTH_KEY) == 0) && 8081 iYUVWidth > 0) 8082 { 8083 // Video width 8084 ++numvalentries; 8085 } 8086 else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_HEIGHT_KEY) == 0) && 8087 iYUVHeight > 0) 8088 { 8089 // Video height 8090 ++numvalentries; 8091 } 8092 else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_PROFILE_KEY) == 0) && 8093 (GetProfileAndLevel(aProfile, aLevel) == PVMFSuccess)) 8094 8095 { 8096 // Video profile 8097 ++numvalentries; 8098 } 8099 else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_LEVEL_KEY) == 0) && 8100 (GetProfileAndLevel(aProfile, aLevel) == PVMFSuccess)) 8101 { 8102 // Video level 8103 ++numvalentries; 8104 } 8105 else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_AVGBITRATE_KEY) == 0) && 8106 (iAvgBitrateValue > 0)) 8107 8108 { 8109 // Video average bitrate 8110 if (iAvgBitrateValue > 0) 8111 ++numvalentries; 8112 } 8113 else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXENCMETADATA_CODECINFO_VIDEO_FORMAT_KEY) == 0) && 8114 (((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)) 8115 { 8116 // Format 8117 ++numvalentries; 8118 } 8119 } 8120 8121 return numvalentries; 8122 } 8123 8124 ///////////////////////////////////////////////////////////////////////////// 8125 PVMFCommandId PVMFOMXEncNode::GetNodeMetadataKeys(PVMFSessionId aSessionId, PVMFMetadataList& aKeyList, uint32 starting_index, int32 max_entries, char* query_key, const OsclAny* aContext) 8126 { 8127 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNodeCommand::GetNodeMetadataKeys() called", iNodeTypeId)); 8128 8129 PVMFOMXEncNodeCommand cmd; 8130 cmd.PVMFOMXEncNodeCommand::Construct(aSessionId, PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_GETNODEMETADATAKEY, &aKeyList, starting_index, max_entries, query_key, aContext); 8131 return QueueCommandL(cmd); 8132 } 8133 8134 ///////////////////////////////////////////////////////////////////////////// 8135 PVMFCommandId PVMFOMXEncNode::GetNodeMetadataValues(PVMFSessionId aSessionId, PVMFMetadataList& aKeyList, Oscl_Vector<PvmiKvp, OsclMemAllocator>& aValueList, uint32 starting_index, int32 max_entries, const OsclAny* aContext) 8136 { 8137 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNodeCommand::GetNodeMetadataValue() called", iNodeTypeId)); 8138 8139 PVMFOMXEncNodeCommand cmd; 8140 cmd.PVMFOMXEncNodeCommand::Construct(aSessionId, PVMFOMXEncNodeCommand::PVOMXENC_NODE_CMD_GETNODEMETADATAVALUE, &aKeyList, &aValueList, starting_index, max_entries, aContext); 8141 return QueueCommandL(cmd); 8142 } 8143 8144 // From PVMFMetadataExtensionInterface 8145 ///////////////////////////////////////////////////////////////////////////// 8146 PVMFStatus PVMFOMXEncNode::ReleaseNodeMetadataKeys(PVMFMetadataList& , uint32 , uint32) 8147 { 8148 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::ReleaseNodeMetadataKeys() called", iNodeTypeId)); 8149 //nothing needed-- there's no dynamic allocation in this node's key list 8150 return PVMFSuccess; 8151 } 8152 8153 // From PVMFMetadataExtensionInterface 8154 ///////////////////////////////////////////////////////////////////////////// 8155 PVMFStatus PVMFOMXEncNode::ReleaseNodeMetadataValues(Oscl_Vector<PvmiKvp, OsclMemAllocator>& aValueList, uint32 start, uint32 end) 8156 { 8157 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::ReleaseNodeMetadataValues() called", iNodeTypeId)); 8158 8159 if (aValueList.size() == 0 || start > end) 8160 { 8161 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::ReleaseNodeMetadataValues() Invalid start/end index", iNodeTypeId)); 8162 return PVMFErrArgument; 8163 } 8164 8165 if (end >= aValueList.size()) 8166 { 8167 end = aValueList.size() - 1; 8168 } 8169 8170 for (uint32 i = start; i <= end; i++) 8171 { 8172 if (aValueList[i].key != NULL) 8173 { 8174 switch (GetValTypeFromKeyString(aValueList[i].key)) 8175 { 8176 case PVMI_KVPVALTYPE_CHARPTR: 8177 if (aValueList[i].value.pChar_value != NULL) 8178 { 8179 OSCL_ARRAY_DELETE(aValueList[i].value.pChar_value); 8180 aValueList[i].value.pChar_value = NULL; 8181 } 8182 break; 8183 8184 case PVMI_KVPVALTYPE_UINT32: 8185 case PVMI_KVPVALTYPE_UINT8: 8186 // No memory to free for these valtypes 8187 break; 8188 8189 default: 8190 // Should not get a value that wasn't created from here 8191 break; 8192 } 8193 8194 OSCL_ARRAY_DELETE(aValueList[i].key); 8195 aValueList[i].key = NULL; 8196 } 8197 } 8198 8199 return PVMFSuccess; 8200 } 8201 8202 8203 8204 8205 8206 8207 PVMFStatus PVMFOMXEncNode::GetProfileAndLevel(PVMF_MPEGVideoProfileType& aProfile, PVMF_MPEGVideoLevelType& aLevel) 8208 { 8209 8210 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::GetProfileAndLevel() In", iNodeTypeId)); 8211 8212 if (NULL == iOMXEncoder) 8213 { 8214 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::GetProfileAndLevel() iEncoder is Null", iNodeTypeId)); 8215 aProfile = PV_MPEG_VIDEO_RESERVED_PROFILE; 8216 aLevel = PV_MPEG_VIDEO_LEVEL_UNKNOWN; 8217 return PVMFFailure; 8218 } 8219 8220 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::GetProfileAndLevel() iEncoder is Null", iNodeTypeId)); 8221 aProfile = PV_MPEG_VIDEO_RESERVED_PROFILE; 8222 aLevel = PV_MPEG_VIDEO_LEVEL_UNKNOWN; 8223 // DV: FOR NOW, JUST RETURN FAILURE, WE DON'T SUPPORT THIS FEATURE YET 8224 return PVMFFailure; 8225 8226 8227 } 8228 8229 8230 ///////////////////////////////////////////////////////////////////////////// 8231 void PVMFOMXEncNode::LogDiagnostics() 8232 { 8233 if (iDiagnosticsLogged == false) 8234 { 8235 iDiagnosticsLogged = true; 8236 PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO, (0, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")); 8237 PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO, (0, "PVMFOMXEncNode-%s - Number of Media Msgs Sent = %d", iNodeTypeId, iSeqNum)); 8238 PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO, (0, "PVMFOMXEncNode-%s - TS of last encoded msg = %d", iNodeTypeId, ConvertOMXTicksIntoTimestamp(iTimeStampOut))); 8239 } 8240 } 8241 8242 8243 8244 ////////////////////////////////// 8245 /////EXTENSION INTERFACE 8246 //////////////////////////////////// 8247 //////////////////////////////////////////////////////////////////////////// 8248 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetNumLayers(uint32 aNumLayers) 8249 { 8250 switch (iInterfaceState) 8251 { 8252 case EPVMFNodeStarted: 8253 case EPVMFNodePaused: 8254 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8255 (0, "PVMFOMXEncNode-%s::SetNumLayers: Error iInterfaceState=%d", iNodeTypeId, iInterfaceState)); 8256 return false; 8257 8258 default: 8259 break; 8260 } 8261 8262 if (aNumLayers > MAX_LAYER) 8263 { 8264 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8265 (0, "PVMFOMXEncNode-%s::SetNumLayers: Error Max num layers is %d", iNodeTypeId, MAX_LAYER)); 8266 return false; 8267 } 8268 8269 iVideoEncodeParam.iNumLayer = aNumLayers; 8270 return true; 8271 } 8272 8273 //////////////////////////////////////////////////////////////////////////// 8274 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetOutputBitRate(uint32 aLayer, uint32 aBitRate) 8275 { 8276 switch (iInterfaceState) 8277 { 8278 case EPVMFNodeStarted: 8279 case EPVMFNodePaused: 8280 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::SetOutputBitRate: Error iInterfaceState=%d", iInterfaceState)); 8281 return false; 8282 8283 default: 8284 break; 8285 } 8286 8287 if ((int32)aLayer >= iVideoEncodeParam.iNumLayer) 8288 { 8289 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8290 (0, "PVMFOMXEncNode-%s::SetOutputBitRate: Error Invalid layer number", iNodeTypeId)); 8291 return false; 8292 } 8293 8294 iVideoEncodeParam.iBitRate[aLayer] = aBitRate; 8295 return true; 8296 } 8297 8298 //////////////////////////////////////////////////////////////////////////// 8299 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetOutputFrameSize(uint32 aLayer, uint32 aWidth, uint32 aHeight) 8300 { 8301 switch (iInterfaceState) 8302 { 8303 case EPVMFNodeStarted: 8304 case EPVMFNodePaused: 8305 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8306 (0, "PVMFOMXEncNode-%s::SetOutputFrameSize: Error iInterfaceState=%d", iNodeTypeId, iInterfaceState)); 8307 return false; 8308 8309 default: 8310 break; 8311 } 8312 8313 if ((int32)aLayer >= iVideoEncodeParam.iNumLayer) 8314 { 8315 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8316 (0, "PVMFOMXEncNode-%s::SetOutputFrameSize: Error Invalid layer number", iNodeTypeId)); 8317 return false; 8318 } 8319 8320 iVideoEncodeParam.iFrameWidth[aLayer] = aWidth; 8321 iVideoEncodeParam.iFrameHeight[aLayer] = aHeight; 8322 return true; 8323 } 8324 8325 //////////////////////////////////////////////////////////////////////////// 8326 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetOutputFrameRate(uint32 aLayer, OsclFloat aFrameRate) 8327 { 8328 switch (iInterfaceState) 8329 { 8330 case EPVMFNodeStarted: 8331 case EPVMFNodePaused: 8332 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8333 (0, "PVMFOMXEncNode-%s::SetOutputFrameRate: Error iInterfaceState=%d", iInterfaceState)); 8334 return false; 8335 8336 default: 8337 break; 8338 } 8339 8340 if ((int32)aLayer >= iVideoEncodeParam.iNumLayer) 8341 { 8342 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8343 (0, "PVMFOMXEncNode-%s::SetOutputFrameRate: Error Invalid layer number", iNodeTypeId)); 8344 return false; 8345 } 8346 8347 iVideoEncodeParam.iFrameRate[aLayer] = OSCL_STATIC_CAST(float, aFrameRate); 8348 return true; 8349 } 8350 8351 //////////////////////////////////////////////////////////////////////////// 8352 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetSegmentTargetSize(uint32 aLayer, uint32 aSizeBytes) 8353 { 8354 OSCL_UNUSED_ARG(aLayer); 8355 8356 switch (iInterfaceState) 8357 { 8358 case EPVMFNodeStarted: 8359 case EPVMFNodePaused: 8360 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8361 (0, "PVMFOMXEncNode-%s::SetSegmentTargetSize: Error iInterfaceState=%d", iNodeTypeId, iInterfaceState)); 8362 return false; 8363 8364 default: 8365 break; 8366 } 8367 8368 iVideoEncodeParam.iPacketSize = aSizeBytes; 8369 return true; 8370 } 8371 8372 //////////////////////////////////////////////////////////////////////////// 8373 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetRateControlType(uint32 aLayer, PVMFVENRateControlType aRateControl) 8374 { 8375 OSCL_UNUSED_ARG(aLayer); 8376 8377 switch (iInterfaceState) 8378 { 8379 case EPVMFNodeStarted: 8380 case EPVMFNodePaused: 8381 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8382 (0, "PVMFOMXEncNode-%s::SetRateControlType: Error iInterfaceState=%d", iNodeTypeId, iInterfaceState)); 8383 return false; 8384 8385 default: 8386 break; 8387 } 8388 8389 iVideoEncodeParam.iRateControlType = aRateControl; 8390 return true; 8391 } 8392 8393 //////////////////////////////////////////////////////////////////////////// 8394 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetDataPartitioning(bool aDataPartitioning) 8395 { 8396 switch (iInterfaceState) 8397 { 8398 case EPVMFNodeStarted: 8399 case EPVMFNodePaused: 8400 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8401 (0, "PVMFOMXEncNode-%s::SetDataPartitioning: Error iInterfaceState=%d", iNodeTypeId, iInterfaceState)); 8402 return false; 8403 8404 default: 8405 break; 8406 } 8407 8408 iVideoEncodeParam.iDataPartitioning = aDataPartitioning; 8409 8410 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 8411 (0, "PVMFOMXEncNode-%s::SetDataPartitioning Called", iNodeTypeId)); 8412 8413 return true; 8414 } 8415 8416 //////////////////////////////////////////////////////////////////////////// 8417 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetIFrameInterval(uint32 aIFrameInterval) 8418 { 8419 switch (iInterfaceState) 8420 { 8421 case EPVMFNodeStarted: 8422 case EPVMFNodePaused: 8423 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8424 (0, "PVMFOMXEncNode-%s::SetIFrameInterval: Error iInterfaceState=%d", iNodeTypeId, iInterfaceState)); 8425 return false; 8426 8427 default: 8428 break; 8429 } 8430 8431 iVideoEncodeParam.iIFrameInterval = aIFrameInterval; 8432 return true; 8433 } 8434 //////////////////////////////////////////////////////////////////////////// 8435 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetSceneDetection(bool aSCD) 8436 { 8437 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 8438 (0, "PVMFOMXEncNode-%s::SetSceneDetection to %d", iNodeTypeId, aSCD)); 8439 8440 8441 switch (iInterfaceState) 8442 { 8443 case EPVMFNodeStarted: 8444 case EPVMFNodePaused: 8445 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8446 (0, "PVMFOMXEncEncNode-%s::SetIFrameInterval: Error iInterfaceState=%d", iNodeTypeId, iInterfaceState)); 8447 return false; 8448 8449 default: 8450 break; 8451 } 8452 8453 iVideoEncodeParam.iSceneDetection = aSCD; 8454 8455 return true; 8456 } 8457 //////////////////////////////////////////////////////////////////////////// 8458 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetRVLC(bool aRVLC) 8459 { 8460 8461 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 8462 (0, "PVMFOMXEncNode-%s::SetRVLC", iNodeTypeId)); 8463 8464 switch (iInterfaceState) 8465 { 8466 case EPVMFNodeStarted: 8467 case EPVMFNodePaused: 8468 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8469 (0, "PVMFOMXEncEncNode-%s::SetRVLC: Error iInterfaceState=%d", iNodeTypeId, iInterfaceState)); 8470 return false; 8471 8472 default: 8473 break; 8474 } 8475 8476 iVideoEncodeParam.iRVLCEnable = aRVLC; 8477 8478 return true; 8479 } 8480 8481 //////////////////////////////////////////////////////////////////////////// 8482 OSCL_EXPORT_REF bool PVMFOMXEncNode::GetVolHeader(OsclRefCounterMemFrag& aVolHeader) 8483 { 8484 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 8485 (0, "PVMFOMXEncNode-%s::GetVolHeader", iNodeTypeId)); 8486 8487 #ifdef _TEST_AE_ERROR_HANDLING 8488 if (iErrorConfigHeader) 8489 { 8490 iInterfaceState = EPVMFNodeError; 8491 } 8492 #endif 8493 switch (iInterfaceState) 8494 { 8495 case EPVMFNodeInitialized: 8496 case EPVMFNodePrepared: 8497 case EPVMFNodeStarted: 8498 case EPVMFNodePaused: 8499 break; 8500 8501 default: 8502 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8503 (0, "PVMFOMXEncNode-%s::GetVolHeader: Error - Wrong state", iNodeTypeId)); 8504 return false; 8505 } 8506 8507 if (iOutFormat != PVMF_MIME_M4V) 8508 { 8509 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8510 (0, "PVMFOMXEncNode-%s::GetVolHeader: Error - VOL header only for M4V encode", iNodeTypeId)); 8511 return false; 8512 } 8513 8514 uint8 *ptr = (uint8 *) iVolHeader.getMemFragPtr(); 8515 //If data partioning mode 8516 if (iVideoEncodeParam.iDataPartitioning == true) 8517 { 8518 ptr[iVolHeader.getMemFragSize() - 1] = 0x8F; 8519 } 8520 //else combined mode 8521 else 8522 { 8523 ptr[iVolHeader.getMemFragSize() - 1] = 0x1F; 8524 } 8525 8526 aVolHeader = iVolHeader; 8527 8528 return true; 8529 } 8530 8531 //////////////////////////////////////////////////////////////////////////// 8532 OSCL_EXPORT_REF bool PVMFOMXEncNode::RequestIFrame() 8533 { 8534 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 8535 (0, "PVMFOMXEncNode-%s::RequestIFrame", iNodeTypeId)); 8536 8537 switch (iInterfaceState) 8538 { 8539 case EPVMFNodeStarted: 8540 case EPVMFNodePaused: 8541 break; 8542 default: 8543 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8544 (0, "PVMFOMXEncNode-%s::RequestIFrame: Error - Wrong state", iNodeTypeId)); 8545 return false; 8546 } 8547 8548 return true; 8549 } 8550 8551 //////////////////////////////////////////////////////////////////////////// 8552 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetCodec(PVMFFormatType aCodec) 8553 { 8554 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 8555 (0, "PVMFOMXEncNode-%s::SetCodec %s", iNodeTypeId, aCodec.getMIMEStrPtr())); 8556 8557 if (SetCodecType(aCodec) == PVMFSuccess) 8558 { 8559 return true; 8560 } 8561 else 8562 { 8563 return false; 8564 } 8565 8566 } 8567 8568 8569 8570 PVMFStatus PVMFOMXEncNode::SetCodecType(PVMFFormatType aCodec) 8571 { 8572 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 8573 (0, "PVMFOMXEncNode-%s::SetCodecType: aCodec=%s", iNodeTypeId, aCodec.getMIMEStrPtr())); 8574 8575 switch (iInterfaceState) 8576 { 8577 case EPVMFNodeStarted: 8578 case EPVMFNodePaused: 8579 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8580 (0, "PVMFOMXEncNode-%s::SetCodecType: Error iInterfaceState=%d", iNodeTypeId, iInterfaceState)); 8581 8582 return PVMFErrInvalidState; 8583 default: 8584 break; 8585 } 8586 8587 if (aCodec == PVMF_MIME_H2631998) 8588 { 8589 iOutFormat = PVMF_MIME_H2631998; 8590 } 8591 else if (aCodec == PVMF_MIME_H2632000) 8592 { 8593 iOutFormat = PVMF_MIME_H2632000; 8594 } 8595 else if (aCodec == PVMF_MIME_M4V) 8596 { 8597 iOutFormat = PVMF_MIME_M4V; 8598 } 8599 else if (aCodec == PVMF_MIME_H264_VIDEO_RAW || 8600 aCodec == PVMF_MIME_H264_VIDEO_MP4) 8601 { 8602 iOutFormat = aCodec; 8603 } 8604 else if (aCodec == PVMF_MIME_AMR_IETF || 8605 aCodec == PVMF_MIME_AMR_IF2 || 8606 aCodec == PVMF_MIME_AMRWB_IETF) 8607 { 8608 iOutFormat = aCodec; 8609 } 8610 else if (aCodec == PVMF_MIME_ADTS || 8611 aCodec == PVMF_MIME_ADIF || 8612 aCodec == PVMF_MIME_MPEG4_AUDIO) 8613 { 8614 iOutFormat = aCodec; 8615 } 8616 else 8617 { 8618 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 8619 (0, "PVMFOMXEncNode-%s::SetCodecType: ERROR Unsupported format aCodec=%s", iNodeTypeId, aCodec.getMIMEStrPtr())); 8620 8621 return PVMFErrNotSupported; 8622 } 8623 8624 return PVMFSuccess; 8625 } 8626 8627 //////////////////////////////////////////////////////////////////////////// 8628 OSCL_EXPORT_REF bool PVMFOMXEncNode::SetFSIParam(uint8* aFSIBuff, int aFSIBuffLength) 8629 { 8630 8631 8632 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8633 (0, "PVMFOMXEncNode-%s::SetFSIParam: Error- NOT IMPLEMENTED", iNodeTypeId)); 8634 OSCL_UNUSED_ARG(aFSIBuff); 8635 OSCL_UNUSED_ARG(aFSIBuffLength); 8636 8637 return true; 8638 } 8639 8640 8641 8642 // The input format methods are called from the port 8643 //////////////////////////////////////////////////////////////////////////// 8644 PVMFStatus PVMFOMXEncNode::SetInputFormat(PVMFFormatType aFormat) 8645 { 8646 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 8647 (0, "PVMFOMXEncNode-%s::SetInputFormat: aFormat=%s", iNodeTypeId, aFormat.getMIMEStrPtr())); 8648 8649 switch (iInterfaceState) 8650 { 8651 case EPVMFNodeStarted: 8652 case EPVMFNodePaused: 8653 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8654 (0, "PVMFOMXEncNode-%s::SetInputFormat: Error - iInterfaceState=%d", iNodeTypeId, iInterfaceState)); 8655 return PVMFErrInvalidState; 8656 default: 8657 break; 8658 } 8659 8660 iInFormat = aFormat; 8661 return PVMFSuccess; 8662 } 8663 8664 //////////////////////////////////////////////////////////////////////////// 8665 PVMFStatus PVMFOMXEncNode::SetInputFrameSize(uint32 aWidth, uint32 aHeight, uint8 aFrmOrient) 8666 { 8667 switch (iInterfaceState) 8668 { 8669 case EPVMFNodeStarted: 8670 case EPVMFNodePaused: 8671 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8672 (0, "PVMFOMXEncNode-%s::SetInputFrameSize: Error iInterfaceState=%d", iNodeTypeId, iInterfaceState)); 8673 return false; 8674 default: 8675 break; 8676 } 8677 8678 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 8679 (0, "PVMFOMXEncNode-%s::SetInputFrameSize: aWidth=%d, aHeight=%d, aFrmOrient=%d", iNodeTypeId, aWidth, aHeight, aFrmOrient)); 8680 8681 iVideoInputFormat.iFrameWidth = aWidth; 8682 iVideoInputFormat.iFrameHeight = aHeight; 8683 iVideoInputFormat.iFrameOrientation = aFrmOrient; 8684 return true; 8685 } 8686 8687 //////////////////////////////////////////////////////////////////////////// 8688 PVMFStatus PVMFOMXEncNode::SetInputFrameRate(OsclFloat aFrameRate) 8689 { 8690 switch (iInterfaceState) 8691 { 8692 case EPVMFNodeStarted: 8693 case EPVMFNodePaused: 8694 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8695 (0, "PVMFOMXEncNode-%s::SetInputFrameRate: Error iInterfaceState=%d", iNodeTypeId, iInterfaceState)); 8696 return false; 8697 default: 8698 break; 8699 } 8700 8701 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 8702 (0, "PVMFOMXEncNode-%s::SetInputFrameRate: aFrameRate=%d", iNodeTypeId, aFrameRate)); 8703 8704 iVideoInputFormat.iFrameRate = OSCL_STATIC_CAST(float, aFrameRate); 8705 iVideoEncodeParam.iNoFrameSkip = iVideoEncodeParam.iNoCurrentSkip = false; 8706 return true; 8707 } 8708 8709 //////////////////////////////////////////////////////////////////////////// 8710 PVMFFormatType PVMFOMXEncNode::GetCodecType() 8711 { 8712 return iOutFormat; 8713 } 8714 8715 //////////////////////////////////////////////////////////////////////////// 8716 // DV: Note - for video - there is an uint32 arg 8717 uint32 PVMFOMXEncNode::GetOutputBitRate(uint32 aLayer) 8718 { 8719 if ((int32)aLayer >= iVideoEncodeParam.iNumLayer) 8720 { 8721 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8722 (0, "PVMFOMXEncNode-%s::GetOutputBitRate: Error - Invalid layer number", iNodeTypeId)); 8723 return 0; 8724 } 8725 8726 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 8727 (0, "PVMFOMXEncNode-%s::GetOutputBitRate: =%d", iNodeTypeId, iVideoEncodeParam.iBitRate[aLayer])); 8728 8729 return iVideoEncodeParam.iBitRate[aLayer]; 8730 } 8731 8732 //////////////////////////////////////////////////////////////////////////// 8733 OsclFloat PVMFOMXEncNode::GetOutputFrameRate(uint32 aLayer) 8734 { 8735 if ((int32)aLayer >= iVideoEncodeParam.iNumLayer) 8736 { 8737 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8738 (0, "PVMFOMXEncNode-%s::GetOutputFrameRate: Error Invalid layer number", iNodeTypeId)); 8739 return 0; 8740 } 8741 8742 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 8743 (0, "PVMFOMXEncNode-%s::GetOutputFrameRate: =%f", iNodeTypeId, (OsclFloat) iVideoEncodeParam.iFrameRate[aLayer])); 8744 8745 return (OsclFloat)iVideoEncodeParam.iFrameRate[aLayer]; 8746 } 8747 8748 //////////////////////////////////////////////////////////////////////////// 8749 PVMFStatus PVMFOMXEncNode::GetOutputFrameSize(uint32 aLayer, uint32& aWidth, uint32& aHeight) 8750 { 8751 if ((int32)aLayer >= iVideoEncodeParam.iNumLayer) 8752 { 8753 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 8754 (0, "PVMFOMXEncNode-%s::GetOutputFrameSize: Error Invalid layer number", iNodeTypeId)); 8755 return PVMFFailure; 8756 } 8757 8758 aWidth = iVideoEncodeParam.iFrameWidth[aLayer]; 8759 aHeight = iVideoEncodeParam.iFrameHeight[aLayer]; 8760 return PVMFSuccess; 8761 } 8762 8763 //////////////////////////////////////////////////////////////////////////// 8764 uint32 PVMFOMXEncNode::GetIFrameInterval() 8765 { 8766 return iVideoEncodeParam.iIFrameInterval; 8767 } 8768 ///////////////////////////////////////////////////////////////////////////// 8769 8770 uint32 PVMFOMXEncNode::GetOutputSamplingRate() 8771 { 8772 8773 8774 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 8775 (0, "PVMFOMXEncNode-%s::GetOutputSamplingRate: =%d", iNodeTypeId, iAudioEncodeParam.iOutputSamplingRate)); 8776 8777 return (uint32) iAudioEncodeParam.iOutputSamplingRate; 8778 } 8779 ///////////////////////////////////////////////////////////////////////////// 8780 8781 uint32 PVMFOMXEncNode::GetOutputNumChannels() 8782 { 8783 8784 8785 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 8786 (0, "PVMFOMXEncNode-%s::GetOutputNumChannels: =%d", iNodeTypeId, iAudioEncodeParam.iOutputNumChannels)); 8787 8788 return (uint32) iAudioEncodeParam.iOutputNumChannels; 8789 } 8790 8791 /////////////////////////AMRENCInterfaceExtension ////////////////////////// 8792 OSCL_EXPORT_REF PVMFStatus PVMFOMXEncNode::SetOutputBitRate(PVMF_GSMAMR_Rate aBitRate) 8793 { 8794 // this particular API is used only for AMR (NB or WB) 8795 // do some error checking - make sure that NB (i.e. WB) bitrates correspond to NB (i.e. WB) codec 8796 if ((iOutFormat == PVMF_MIME_AMR_IF2) || 8797 (iOutFormat == PVMF_MIME_AMR_IETF) 8798 ) 8799 { 8800 8801 switch (aBitRate) 8802 { 8803 case GSM_AMR_4_75: 8804 case GSM_AMR_5_15: 8805 case GSM_AMR_5_90: 8806 case GSM_AMR_6_70: 8807 case GSM_AMR_7_40: 8808 case GSM_AMR_7_95: 8809 case GSM_AMR_10_2: 8810 case GSM_AMR_12_2: 8811 8812 iAudioEncodeParam.iAMRBitrate = aBitRate; 8813 8814 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, 8815 (0, "PVMFOMXEncNode-%s::SetOutputBitRate() OK - %d", iNodeTypeId, aBitRate)); 8816 8817 return PVMFSuccess; 8818 8819 case GSM_AMR_6_60: // AMR WB bitrates start here 8820 case GSM_AMR_8_85: 8821 case GSM_AMR_12_65: 8822 case GSM_AMR_14_25: 8823 case GSM_AMR_15_85: 8824 case GSM_AMR_18_25: 8825 case GSM_AMR_19_85: 8826 case GSM_AMR_23_05: 8827 case GSM_AMR_23_85: 8828 8829 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 8830 (0, "PVMFOMXEncNode-%s::SetOutputBitRate() failed - %d", iNodeTypeId, aBitRate)); 8831 8832 return PVMFFailure; 8833 8834 default: 8835 8836 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 8837 (0, "PVMFOMXEncNode-%s::SetOutputBitRate() failed - %d", iNodeTypeId, aBitRate)); 8838 8839 return PVMFFailure; 8840 } 8841 } 8842 8843 if (iOutFormat == PVMF_MIME_AMRWB_IETF) 8844 { 8845 switch (aBitRate) 8846 { 8847 case GSM_AMR_4_75: 8848 case GSM_AMR_5_15: 8849 case GSM_AMR_5_90: 8850 case GSM_AMR_6_70: 8851 case GSM_AMR_7_40: 8852 case GSM_AMR_7_95: 8853 case GSM_AMR_10_2: 8854 case GSM_AMR_12_2: 8855 8856 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 8857 (0, "PVMFOMXEncNode-%s::SetOutputBitRate() failed - %d", iNodeTypeId, aBitRate)); 8858 8859 return PVMFFailure; 8860 8861 case GSM_AMR_6_60: // AMR WB bitrates start here 8862 case GSM_AMR_8_85: 8863 case GSM_AMR_12_65: 8864 case GSM_AMR_14_25: 8865 case GSM_AMR_15_85: 8866 case GSM_AMR_18_25: 8867 case GSM_AMR_19_85: 8868 case GSM_AMR_23_05: 8869 case GSM_AMR_23_85: 8870 8871 iAudioEncodeParam.iAMRBitrate = aBitRate; 8872 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, 8873 (0, "PVMFOMXEncNode-%s::SetOutputBitRate() OK - %d", iNodeTypeId, aBitRate)); 8874 8875 return PVMFSuccess; 8876 8877 default: 8878 8879 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 8880 (0, "PVMFOMXEncNode-%s::SetOutputBitRate() failed - %d", iNodeTypeId, aBitRate)); 8881 8882 return PVMFFailure; 8883 } 8884 } 8885 8886 return PVMFSuccess; 8887 } 8888 8889 //////////////////////////////////////////////////////////////////////////// 8890 OSCL_EXPORT_REF PVMFStatus PVMFOMXEncNode::SetMaxNumOutputFramesPerBuffer(uint32 aNumOutputFrames) 8891 { 8892 iAudioEncodeParam.iMaxNumOutputFramesPerBuffer = aNumOutputFrames; 8893 return PVMFSuccess; 8894 } 8895 8896 //////////////////////////////////////////////////////////////////////////// 8897 OSCL_EXPORT_REF PVMFStatus PVMFOMXEncNode::SetOutputBitRate(uint32 aBitRate) 8898 { 8899 // this API is used for Non-AMR codecs 8900 iAudioEncodeParam.iOutputBitrate = aBitRate; 8901 return PVMFSuccess; 8902 } 8903 8904 //////////////////////////////////////////////////////////////////////////// 8905 OSCL_EXPORT_REF PVMFStatus PVMFOMXEncNode::SetOutputNumChannel(uint32 aNumChannels) 8906 { 8907 8908 iAudioEncodeParam.iOutputNumChannels = aNumChannels; 8909 return PVMFSuccess; 8910 } 8911 8912 //////////////////////////////////////////////////////////////////////////// 8913 OSCL_EXPORT_REF PVMFStatus PVMFOMXEncNode::SetOutputSamplingRate(uint32 aSamplingRate) 8914 { 8915 iAudioEncodeParam.iOutputSamplingRate = aSamplingRate; 8916 return PVMFSuccess; 8917 } 8918 8919 8920 //////////////////////////////////////////////////////////////////////////// 8921 PVMFStatus PVMFOMXEncNode::SetInputSamplingRate(uint32 aSamplingRate) 8922 { 8923 // do some error checking - make sure the input sampling rate is 8khz (i.e. 16khz) for AMRNB (i.e. WB) 8924 if (((iOutFormat == PVMF_MIME_AMR_IF2) || 8925 (iOutFormat == PVMF_MIME_AMR_IETF)) && 8926 (aSamplingRate != 8000) 8927 ) 8928 { 8929 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 8930 (0, "PVMFOMXEncNode-%s::SetInputBitsSamplingRate() failed - %d", iNodeTypeId, aSamplingRate)); 8931 8932 return PVMFFailure; 8933 } 8934 8935 if ((iOutFormat == PVMF_MIME_AMRWB_IETF) && (aSamplingRate != 16000)) 8936 { 8937 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 8938 (0, "PVMFOMXEncNode-%s::SetInputBitsSamplingRate() failed - %d", iNodeTypeId, aSamplingRate)); 8939 8940 return PVMFFailure; 8941 } 8942 8943 iAudioInputFormat.iInputSamplingRate = aSamplingRate; 8944 8945 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, 8946 (0, "PVMFOMXEncNode-%s::SetInputBitsSamplingRate() OK setting OutputSamplingRate as well - %d", iNodeTypeId, aSamplingRate)); 8947 8948 // set output as well 8949 iAudioEncodeParam.iOutputSamplingRate = aSamplingRate; 8950 return PVMFSuccess; 8951 } 8952 8953 //////////////////////////////////////////////////////////////////////////// 8954 PVMFStatus PVMFOMXEncNode::SetInputBitsPerSample(uint32 aBitsPerSample) 8955 { 8956 if (aBitsPerSample != 16) 8957 { 8958 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 8959 (0, "PVMFOMXEncNode-%s::SetInputBitsPerSample() failed - %d", iNodeTypeId, aBitsPerSample)); 8960 8961 return PVMFErrNotSupported; 8962 } 8963 8964 iAudioInputFormat.iInputBitsPerSample = aBitsPerSample; 8965 8966 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, 8967 (0, "PVMFOMXEncNode-%s::SetInputBitsPerSample() OK - %d", iNodeTypeId, aBitsPerSample)); 8968 8969 return PVMFSuccess; 8970 } 8971 8972 8973 //////////////////////////////////////////////////////////////////////////// 8974 PVMFStatus PVMFOMXEncNode::SetInputNumChannels(uint32 aNumChannels) 8975 { 8976 // do some error checking - make sure the number of INPUT channels is 1 for AMR (NB or WB) 8977 8978 if (((iOutFormat == PVMF_MIME_AMR_IF2) || 8979 (iOutFormat == PVMF_MIME_AMR_IETF) || 8980 (iOutFormat == PVMF_MIME_AMRWB_IETF)) && 8981 (aNumChannels > 1) 8982 ) 8983 { 8984 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 8985 (0, "PVMFOMXEncNode-%s::SetInputNumChannels() failed - %d", iNodeTypeId, aNumChannels)); 8986 return PVMFFailure; 8987 } 8988 8989 iAudioInputFormat.iInputNumChannels = aNumChannels; 8990 8991 //set output as well 8992 iAudioEncodeParam.iOutputNumChannels = aNumChannels; 8993 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, 8994 (0, "PVMFOMXEncNode-%s::SetInputNumChannels() OK - %d", iNodeTypeId, aNumChannels)); 8995 8996 return PVMFSuccess; 8997 } 8998 8999 //////////////////////////////////////////////////////////////////////////// 9000 uint32 PVMFOMXEncNode::GetOutputBitRate() 9001 { 9002 if ((iOutFormat == PVMF_MIME_AMR_IF2) || 9003 (iOutFormat == PVMF_MIME_AMR_IETF) || 9004 (iOutFormat == PVMF_MIME_AMRWB_IETF) 9005 ) 9006 { 9007 9008 switch (iAudioEncodeParam.iAMRBitrate) 9009 { 9010 case GSM_AMR_4_75: 9011 return 4750; 9012 case GSM_AMR_5_15: 9013 return 5150; 9014 case GSM_AMR_5_90: 9015 return 5900; 9016 case GSM_AMR_6_70: 9017 return 6700; 9018 case GSM_AMR_7_40: 9019 return 7400; 9020 case GSM_AMR_7_95: 9021 return 7950; 9022 case GSM_AMR_10_2: 9023 return 10200; 9024 case GSM_AMR_12_2: 9025 return 12200; 9026 case GSM_AMR_6_60: // AMR WB bitrates start here 9027 return 6600; 9028 case GSM_AMR_8_85: 9029 return 8850; 9030 case GSM_AMR_12_65: 9031 return 12650; 9032 case GSM_AMR_14_25: 9033 return 14250; 9034 case GSM_AMR_15_85: 9035 return 15850; 9036 case GSM_AMR_18_25: 9037 return 18250; 9038 case GSM_AMR_19_85: 9039 return 19850; 9040 case GSM_AMR_23_05: 9041 return 23050; 9042 case GSM_AMR_23_85: 9043 return 23850; 9044 default: 9045 return 0; 9046 } 9047 } 9048 else 9049 { 9050 return iAudioEncodeParam.iOutputBitrate; 9051 } 9052 } 9053 9054 9055 ///////////////////////// FROM CAP CONFIG IN VIDEO ENC NODE //////////////////// 9056 PVMFStatus PVMFOMXEncNode::GetConfigParameter(PvmiKvp*& aParameters, int& aNumParamElements, int32 aIndex, PvmiKvpAttr aReqattr) 9057 { 9058 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::GetConfigParameter() In", iNodeTypeId)); 9059 9060 aNumParamElements = 0; 9061 9062 // Allocate memory for the KVP 9063 aParameters = (PvmiKvp*)oscl_malloc(sizeof(PvmiKvp)); 9064 if (NULL == aParameters) 9065 { 9066 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::GetConfigParameter() Memory allocation for KVP failed", iNodeTypeId)); 9067 return PVMFErrNoMemory; 9068 } 9069 oscl_memset(aParameters, 0, sizeof(PvmiKvp)); 9070 // Allocate memory for the key string in KVP 9071 PvmiKeyType memblock = (PvmiKeyType)oscl_malloc(PVOMXENCNODECONFIG_KEYSTRING_SIZE * sizeof(char)); 9072 if (NULL == memblock) 9073 { 9074 oscl_free(aParameters); 9075 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::GetConfigParameter() Memory allocation for key string failed", iNodeTypeId)); 9076 return PVMFErrNoMemory; 9077 } 9078 oscl_strset(memblock, 0, PVOMXENCNODECONFIG_KEYSTRING_SIZE * sizeof(char)); 9079 // Assign the key string buffer to KVP 9080 aParameters[0].key = memblock; 9081 9082 // Copy the key string 9083 if (iInFormat == PVMF_MIME_PCM16) 9084 { 9085 // Copy the key string 9086 oscl_strncat(aParameters[0].key, _STRLIT_CHAR("x-pvmf/encoder/audio/"), 21); 9087 oscl_strncat(aParameters[0].key, PVOMXEncNodeConfigBaseKeys[aIndex].iString, oscl_strlen(PVOMXEncNodeConfigBaseKeys[aIndex].iString)); 9088 oscl_strncat(aParameters[0].key, _STRLIT_CHAR(";type=value;valtype="), 20); 9089 } 9090 else 9091 { 9092 oscl_strncat(aParameters[0].key, _STRLIT_CHAR("x-pvmf/encoder/video/"), 21); 9093 oscl_strncat(aParameters[0].key, PVOMXEncNodeConfigBaseKeys[aIndex].iString, oscl_strlen(PVOMXEncNodeConfigBaseKeys[aIndex].iString)); 9094 oscl_strncat(aParameters[0].key, _STRLIT_CHAR(";type=value;valtype="), 20); 9095 } 9096 switch (PVOMXEncNodeConfigBaseKeys[aIndex].iValueType) 9097 { 9098 case PVMI_KVPVALTYPE_BITARRAY32: 9099 oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_BITARRAY32_STRING), oscl_strlen(PVMI_KVPVALTYPE_BITARRAY32_STRING)); 9100 break; 9101 9102 case PVMI_KVPVALTYPE_KSV: 9103 oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_KSV_STRING), oscl_strlen(PVMI_KVPVALTYPE_KSV_STRING)); 9104 break; 9105 9106 case PVMI_KVPVALTYPE_BOOL: 9107 oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_BOOL_STRING), oscl_strlen(PVMI_KVPVALTYPE_BOOL_STRING)); 9108 break; 9109 9110 case PVMI_KVPVALTYPE_INT32: 9111 if (PVMI_KVPATTR_CUR == aReqattr) 9112 { 9113 oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_INT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_RANGE_UINT32_STRING)); 9114 } 9115 break; 9116 case PVMI_KVPVALTYPE_UINT32: 9117 default: 9118 if (PVMI_KVPATTR_CAP == aReqattr) 9119 { 9120 oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_RANGE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_RANGE_UINT32_STRING)); 9121 } 9122 else 9123 { 9124 oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING)); 9125 } 9126 break; 9127 } 9128 aParameters[0].key[PVOMXENCNODECONFIG_KEYSTRING_SIZE-1] = 0; 9129 9130 // Copy the requested info 9131 switch (aIndex) 9132 { 9133 9134 case SAMPLING_RATE: // "sampling_rate" 9135 if (PVMI_KVPATTR_CUR == aReqattr) 9136 { 9137 // get the parameter here 9138 aParameters[0].value.uint32_value = iAudioInputFormat.iInputSamplingRate; 9139 9140 } 9141 else if (PVMI_KVPATTR_DEF == aReqattr) 9142 { 9143 // Return default 9144 aParameters[0].value.uint32_value = PVMF_AMRENC_DEFAULT_SAMPLING_RATE; 9145 9146 } 9147 else 9148 { 9149 // Return capability 9150 } 9151 break; 9152 9153 case CHANNELS: // "channels" 9154 9155 if (PVMI_KVPATTR_CUR == aReqattr) 9156 { 9157 // get the par 9158 aParameters[0].value.uint32_value = iAudioInputFormat.iInputNumChannels; 9159 } 9160 else if (PVMI_KVPATTR_DEF == aReqattr) 9161 { 9162 // Return default 9163 aParameters[0].value.uint32_value = PVMF_AMRENC_DEFAULT_NUM_CHANNELS; 9164 } 9165 else 9166 { 9167 // Return capability 9168 } 9169 break; 9170 9171 case ENCODING_MODE: // "encoding_mode" 9172 if (PVMI_KVPATTR_CUR == aReqattr) 9173 { 9174 // Return current value 9175 aParameters[0].value.uint32_value = iVideoEncodeParam.iEncMode; 9176 } 9177 else if (PVMI_KVPATTR_DEF == aReqattr) 9178 { 9179 // Return default 9180 aParameters[0].value.uint32_value = EI_ENCMODE_RECORDER;//default setting 9181 } 9182 else 9183 { 9184 // Return capability 9185 } 9186 break; 9187 9188 #ifdef _TEST_AE_ERROR_HANDLING 9189 case ERROR_START_INIT://error_start_init 9190 if (PVMI_KVPATTR_CUR == aReqattr) 9191 { 9192 // Return current value 9193 aParameters[0].value.bool_value = iErrorHandlingInit; 9194 } 9195 else if (PVMI_KVPATTR_DEF == aReqattr) 9196 { 9197 // Return default 9198 aParameters[0].value.bool_value = true; 9199 } 9200 else 9201 { 9202 // Return capability 9203 } 9204 break; 9205 case ERROR_ENCODE://error_encode 9206 if (PVMI_KVPATTR_CUR == aReqattr) 9207 { 9208 // Return current value 9209 aParameters[0].value.uint32_value = iErrorHandlingEncodeCount; 9210 } 9211 else if (PVMI_KVPATTR_DEF == aReqattr) 9212 { 9213 // Return default 9214 aParameters[0].value.uint32_value = 1; 9215 } 9216 else 9217 { 9218 // Return capability 9219 } 9220 break; 9221 9222 #endif 9223 9224 default: 9225 // Invalid index 9226 oscl_free(aParameters[0].key); 9227 oscl_free(aParameters); 9228 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::GetConfigParameter() Invalid index to video enc node parameter", iNodeTypeId)); 9229 return PVMFErrNotSupported; 9230 } 9231 9232 aNumParamElements = 1; 9233 9234 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::GetConfigParameter() Out", iNodeTypeId)); 9235 return PVMFSuccess; 9236 } 9237 9238 PVMFStatus PVMFOMXEncNode::VerifyAndSetConfigParameter(PvmiKvp& aParameter, bool aSetParam) 9239 { 9240 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::VerifyAndSetConfigParameter() In", iNodeTypeId)); 9241 9242 // Determine the valtype 9243 PvmiKvpValueType keyvaltype = GetValTypeFromKeyString(aParameter.key); 9244 if (PVMI_KVPVALTYPE_UNKNOWN == keyvaltype) 9245 { 9246 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::VerifyAndSetConfigParameter() Valtype in key string unknown", iNodeTypeId)); 9247 return PVMFErrNotSupported; 9248 } 9249 // Retrieve the fourth component from the key string 9250 char* compstr = NULL; 9251 pv_mime_string_extract_type(3, aParameter.key, compstr); 9252 9253 int32 enccomp4ind; 9254 for (enccomp4ind = 0; enccomp4ind < PVOMXENCNODECONFIG_BASE_NUMKEYS; ++enccomp4ind) 9255 { 9256 // Go through each component string at 4th level 9257 if (pv_mime_strcmp(compstr, (char*)(PVOMXEncNodeConfigBaseKeys[enccomp4ind].iString)) >= 0) 9258 { 9259 // Break out of the for loop 9260 break; 9261 } 9262 } 9263 9264 if (PVOMXENCNODECONFIG_BASE_NUMKEYS <= enccomp4ind) 9265 { 9266 // Match couldn't be found or non-leaf node specified 9267 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::VerifyAndSetConfigParameter() Unsupported key or non-leaf node", iNodeTypeId)); 9268 return PVMFErrNotSupported; 9269 } 9270 9271 // Verify the valtype 9272 if (keyvaltype != PVOMXEncNodeConfigBaseKeys[enccomp4ind].iValueType) 9273 { 9274 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::VerifyAndSetConfigParameter() Valtype does not match for key", iNodeTypeId)); 9275 return PVMFErrNotSupported; 9276 } 9277 9278 switch (enccomp4ind) 9279 { 9280 9281 9282 case SAMPLING_RATE: // "sampling_rate" 9283 // Change the parameter 9284 if (aSetParam) 9285 { 9286 // set the parameter here 9287 iAudioInputFormat.iInputSamplingRate = aParameter.value.uint32_value; 9288 iAudioEncodeParam.iOutputSamplingRate = aParameter.value.uint32_value; 9289 } 9290 break; 9291 9292 case CHANNELS: // "channels" 9293 // change the parameter 9294 if (aSetParam) 9295 { 9296 // set the parameter here 9297 iAudioInputFormat.iInputNumChannels = aParameter.value.uint32_value; 9298 iAudioEncodeParam.iOutputNumChannels = aParameter.value.uint32_value; 9299 } 9300 break; 9301 case ENCODING_MODE: // "encoding_mode" 9302 // change the parameter 9303 if (aSetParam) 9304 { 9305 iVideoEncodeParam.iEncMode = (EncEncodingMode)aParameter.value.uint32_value; 9306 } 9307 break; 9308 9309 9310 9311 #ifdef _TEST_AE_ERROR_HANDLING 9312 case ERROR_START_INIT: // "error_start_init" 9313 // change the parameter 9314 if (aSetParam) 9315 { 9316 iErrorHandlingInit = aParameter.value.bool_value; 9317 } 9318 break; 9319 case ERROR_ENCODE: // "error_avcencode" 9320 // change the parameter 9321 if (aSetParam) 9322 { 9323 9324 char* paramstr = NULL; 9325 OSCL_HeapString<OsclMemAllocator> mode1 = "mode=duration"; 9326 OSCL_HeapString<OsclMemAllocator> mode2 = "mode=frames"; 9327 9328 if (pv_mime_string_parse_param(aParameter.key, mode1.get_str(), paramstr) > 0) 9329 { 9330 iErrorEncodeFlag = 1; 9331 iErrorHandlingEncodeCount = aParameter.value.uint32_value; 9332 9333 } 9334 9335 else if (pv_mime_string_parse_param(aParameter.key, mode2.get_str(), paramstr) > 0) 9336 { 9337 iErrorEncodeFlag = 2; 9338 iErrorHandlingEncodeCount = aParameter.value.uint32_value; 9339 9340 } 9341 } 9342 break; 9343 case ERROR_NODE_CMD: //"error-node-cmd" 9344 if (aSetParam) 9345 { 9346 iErrorNodeCmd = aParameter.value.uint32_value; 9347 } 9348 break; 9349 case ERROR_CONFIG_HEADER: 9350 if (aSetParam) 9351 { 9352 iErrorConfigHeader = aParameter.value.bool_value; 9353 } 9354 break; 9355 case ERROR_DATAPATH_STALL: 9356 if (aSetParam) 9357 { 9358 iErrorDataPathStall = aParameter.value.uint32_value; 9359 } 9360 break; 9361 #endif 9362 9363 default: 9364 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::VerifyAndSetConfigParameter() Invalid index for video enc node parameter", iNodeTypeId)); 9365 return PVMFErrNotSupported; 9366 } 9367 9368 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::VerifyAndSetConfigParameter() Out", iNodeTypeId)); 9369 return PVMFSuccess; 9370 } 9371 9372 //void PVMFOMXEncNode::setParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements, PvmiKvp*& aRetKVP) 9373 void PVMFOMXEncNode::DoCapConfigSetParameters(PvmiKvp* aParameters, int aNumElements, PvmiKvp*& aRetKVP) 9374 { 9375 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoCapConfigSetParameters()", iNodeTypeId)); 9376 //OSCL_UNUSED_ARG(aSession); 9377 9378 if (NULL == aParameters || aNumElements < 1) 9379 { 9380 if (aParameters) 9381 { 9382 aRetKVP = aParameters; 9383 } 9384 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigSetParameters() Passed in parameter invalid", iNodeTypeId)); 9385 return; 9386 } 9387 9388 // Go through each parameter 9389 for (int32 paramind = 0; paramind < aNumElements; ++paramind) 9390 { 9391 // Count the number of components and parameters in the key 9392 int compcount = pv_mime_string_compcnt(aParameters[paramind].key); 9393 // Retrieve the first component from the key string 9394 char* compstr = NULL; 9395 pv_mime_string_extract_type(0, aParameters[paramind].key, compstr); 9396 9397 9398 if (( 9399 (pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/video")) < 0) && 9400 (pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/audio")) < 0) 9401 ) || (compcount < 4)) 9402 { 9403 // First 3 components should be "x-pvmf/encoder/video" or "x-pvmf/encoder/audio" and there must 9404 // be at least 4 components 9405 aRetKVP = &aParameters[paramind]; 9406 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigSetParameters() Unsupported key", iNodeTypeId)); 9407 return; 9408 } 9409 9410 // check if audio parameters are asked from video enc instance or vice versa 9411 if (((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/video")) > 0) && (iInFormat == PVMF_MIME_PCM16)) || 9412 ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/audio")) > 0) && (iInFormat != PVMF_MIME_PCM16)) 9413 ) 9414 { 9415 9416 aRetKVP = &aParameters[paramind]; 9417 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigSetParameters() Unsupported key", iNodeTypeId)); 9418 return; 9419 } 9420 9421 if (4 == compcount) 9422 { 9423 // Verify and set the passed-in video enc node setting 9424 PVMFStatus retval = VerifyAndSetConfigParameter(aParameters[paramind], true); 9425 if (PVMFSuccess != retval) 9426 { 9427 aRetKVP = &aParameters[paramind]; 9428 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigSetParameters() Setting parameter %d failed", iNodeTypeId, paramind)); 9429 return; 9430 } 9431 } 9432 9433 else 9434 { 9435 // Do not support more than 4 components right now 9436 aRetKVP = &aParameters[paramind]; 9437 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigSetParameters() Unsupported key", iNodeTypeId)); 9438 return; 9439 } 9440 } 9441 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoCapConfigSetParameters() Out", iNodeTypeId)); 9442 } 9443 9444 9445 //PVMFStatus PVMFOMXEncNode::getParametersSync(PvmiMIOSession aSession, PvmiKeyType aIdentifier, PvmiKvp*& aParameters, int& aNumParamElements, PvmiCapabilityContext aContext) 9446 PVMFStatus PVMFOMXEncNode::DoCapConfigGetParametersSync(PvmiKeyType aIdentifier, PvmiKvp*& aParameters, int& aNumParamElements, PvmiCapabilityContext aContext) 9447 { 9448 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoCapConfigGetParametersSync()", iNodeTypeId)); 9449 //OSCL_UNUSED_ARG(aSession); 9450 OSCL_UNUSED_ARG(aContext); 9451 9452 // Initialize the output parameters 9453 aNumParamElements = 0; 9454 aParameters = NULL; 9455 9456 // Count the number of components and parameters in the key 9457 int compcount = pv_mime_string_compcnt(aIdentifier); 9458 // Retrieve the first component from the key string 9459 char* compstr = NULL; 9460 pv_mime_string_extract_type(0, aIdentifier, compstr); 9461 9462 if (( 9463 (pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/video")) < 0) && 9464 (pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/audio")) < 0) 9465 ) || (compcount < 4)) 9466 { 9467 // First 3 components should be "x-pvmf/encoder/video" or "x-pvmf/encoder/audio" and there must 9468 // be at least 4 components 9469 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigGetParametersSync() Invalid key string", iNodeTypeId)); 9470 return PVMFErrNotSupported; 9471 } 9472 9473 // check if audio parameters are asked from video enc instance or vice versa 9474 if (((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/video")) > 0) && (iInFormat == PVMF_MIME_PCM16)) || 9475 ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/audio")) > 0) && (iInFormat != PVMF_MIME_PCM16)) 9476 ) 9477 { 9478 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigGetParameters() Unsupported key", iNodeTypeId)); 9479 return PVMFErrNotSupported; 9480 } 9481 9482 // Retrieve the fourth component from the key string 9483 pv_mime_string_extract_type(3, aIdentifier, compstr); 9484 9485 for (int32 enccomp4ind = 0; enccomp4ind < PVOMXENCNODECONFIG_BASE_NUMKEYS; ++enccomp4ind) 9486 { 9487 // Go through each video enc component string at 4th level 9488 if (pv_mime_strcmp(compstr, (char*)(PVOMXEncNodeConfigBaseKeys[enccomp4ind].iString)) >= 0) 9489 { 9490 if (4 == compcount) 9491 { 9492 // Determine what is requested 9493 PvmiKvpAttr reqattr = GetAttrTypeFromKeyString(aIdentifier); 9494 if (PVMI_KVPATTR_UNKNOWN == reqattr) 9495 { 9496 reqattr = PVMI_KVPATTR_CUR; 9497 } 9498 9499 // Return the requested info 9500 PVMFStatus retval = GetConfigParameter(aParameters, aNumParamElements, enccomp4ind, reqattr); 9501 if (PVMFSuccess != retval) 9502 { 9503 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigGetParametersSync() Retrieving video enc node parameter failed", iNodeTypeId)); 9504 return retval; 9505 } 9506 } 9507 else 9508 { 9509 // Right now videoenc node doesn't support more than 4 components 9510 // for this sub-key string so error out 9511 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigGetParametersSync() Unsupported key", iNodeTypeId)); 9512 return PVMFErrNotSupported; 9513 } 9514 } 9515 } 9516 9517 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoCapConfigGetParametersSync() Out", iNodeTypeId)); 9518 if (aNumParamElements == 0) 9519 { 9520 // If no one could get the parameter, return error 9521 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigGetParametersSync() Unsupported key", iNodeTypeId)); 9522 return PVMFFailure; 9523 } 9524 else 9525 { 9526 return PVMFSuccess; 9527 } 9528 } 9529 9530 //PVMFStatus PVMFOMXEncNode::releaseParameters(PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements) 9531 PVMFStatus PVMFOMXEncNode::DoCapConfigReleaseParameters(PvmiKvp* aParameters, int aNumElements) 9532 { 9533 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::releaseParameters()", iNodeTypeId)); 9534 //OSCL_UNUSED_ARG(aSession); 9535 9536 if (aParameters == NULL || aNumElements < 1) 9537 { 9538 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigReleaseParameters() KVP list is NULL or number of elements is 0", iNodeTypeId)); 9539 return PVMFErrArgument; 9540 } 9541 9542 // Count the number of components and parameters in the key 9543 int compcount = pv_mime_string_compcnt(aParameters[0].key); 9544 // Retrieve the first component from the key string 9545 char* compstr = NULL; 9546 pv_mime_string_extract_type(0, aParameters[0].key, compstr); 9547 9548 if (( 9549 (pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/video")) < 0) && 9550 (pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/audio")) < 0) 9551 ) || (compcount < 3)) 9552 { 9553 // First 3 component should be "x-pvmf/encoder/video" or "x-pvmf/encoder/audio" and there must 9554 // be at least three components 9555 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigReleaseParameters() Unsupported key", iNodeTypeId)); 9556 return PVMFErrNotSupported; 9557 } 9558 9559 // check if audio parameters are asked from video enc instance or vice versa 9560 if (((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/video")) > 0) && (iInFormat == PVMF_MIME_PCM16)) || 9561 ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/audio")) > 0) && (iInFormat != PVMF_MIME_PCM16)) 9562 ) 9563 { 9564 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigReleaseParameters() Unsupported key", iNodeTypeId)); 9565 return PVMFErrNotSupported; 9566 } 9567 9568 // Retrieve the third component from the key string 9569 pv_mime_string_extract_type(2, aParameters[0].key, compstr); 9570 9571 // Go through each KVP and release memory for value if allocated from heap 9572 for (int32 ii = 0; ii < aNumElements; ++ii) 9573 { 9574 // Next check if it is a value type that allocated memory 9575 PvmiKvpType kvptype = GetTypeFromKeyString(aParameters[ii].key); 9576 if (PVMI_KVPTYPE_VALUE == kvptype || PVMI_KVPTYPE_UNKNOWN == kvptype) 9577 { 9578 PvmiKvpValueType keyvaltype = GetValTypeFromKeyString(aParameters[ii].key); 9579 if (PVMI_KVPVALTYPE_UNKNOWN == keyvaltype) 9580 { 9581 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigReleaseParameters() Valtype not specified in key string", iNodeTypeId)); 9582 return PVMFErrNotSupported; 9583 } 9584 9585 if (PVMI_KVPVALTYPE_CHARPTR == keyvaltype && NULL != aParameters[ii].value.pChar_value) 9586 { 9587 oscl_free(aParameters[ii].value.pChar_value); 9588 aParameters[ii].value.pChar_value = NULL; 9589 } 9590 else if (keyvaltype == PVMI_KVPVALTYPE_KSV && NULL != aParameters[ii].value.key_specific_value) 9591 { 9592 oscl_free(aParameters[ii].value.key_specific_value); 9593 aParameters[ii].value.key_specific_value = NULL; 9594 } 9595 else if (PVMI_KVPVALTYPE_RANGE_UINT32 == keyvaltype && NULL != aParameters[ii].value.key_specific_value) 9596 { 9597 range_uint32* rui32 = (range_uint32*)aParameters[ii].value.key_specific_value; 9598 aParameters[ii].value.key_specific_value = NULL; 9599 oscl_free(rui32); 9600 } 9601 // @TODO Add more types if video enc node starts returning more types 9602 } 9603 } 9604 9605 // Video enc node allocated its key strings in one chunk so just free the first key string ptr 9606 oscl_free(aParameters[0].key); 9607 9608 // Free memory for the parameter list 9609 oscl_free(aParameters); 9610 aParameters = NULL; 9611 9612 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoCapConfigReleaseParameters() Out", iNodeTypeId)); 9613 return PVMFSuccess; 9614 } 9615 9616 9617 //PVMFStatus PVMFOMXEncNode::verifyParametersSync (PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements) 9618 PVMFStatus PVMFOMXEncNode::DoCapConfigVerifyParameters(PvmiKvp* aParameters, int aNumElements) 9619 { 9620 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoCapConfigVerifyParameters()", iNodeTypeId)); 9621 //OSCL_UNUSED_ARG(aSession); 9622 9623 if (NULL == aParameters || aNumElements < 1) 9624 { 9625 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigVerifyParameters() Passed in parameter invalid", iNodeTypeId)); 9626 return PVMFErrArgument; 9627 } 9628 9629 // Go through each parameter 9630 for (int32 paramind = 0; paramind < aNumElements; ++paramind) 9631 { 9632 // Count the number of components and parameters in the key 9633 int compcount = pv_mime_string_compcnt(aParameters[paramind].key); 9634 // Retrieve the first component from the key string 9635 char* compstr = NULL; 9636 pv_mime_string_extract_type(0, aParameters[paramind].key, compstr); 9637 9638 if ( 9639 ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/video")) < 0) && 9640 (pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/audio")) < 0) 9641 ) || compcount < 3) 9642 { 9643 // First 3 components should be "x-pvmf/encoder/video" or 9644 // "x-pvmf/enoder/audio" and there must 9645 // be at least 3 components 9646 9647 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigVerifyParameters() Unsupported key", iNodeTypeId)); 9648 return PVMFErrNotSupported; 9649 } 9650 9651 // check if audio parameters are asked from video enc instance or vice versa 9652 if (((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/video")) > 0) && (iInFormat == PVMF_MIME_PCM16)) || 9653 ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/encoder/audio")) > 0) && (iInFormat != PVMF_MIME_PCM16)) 9654 ) 9655 { 9656 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigVerifyParameters() Unsupported key", iNodeTypeId)); 9657 return PVMFErrNotSupported; 9658 } 9659 9660 if (4 == compcount) 9661 { 9662 // Verify and set the passed-in video enc node setting 9663 PVMFStatus retval = VerifyAndSetConfigParameter(aParameters[paramind], false); 9664 if (retval != PVMFSuccess) 9665 { 9666 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigVerifyParameters() Setting parameter %d failed", iNodeTypeId, paramind)); 9667 return retval; 9668 } 9669 } 9670 else 9671 { 9672 // Do not support more than 4 components right now 9673 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXEncNode-%s::DoCapConfigVerifyParameters() Unsupported key", iNodeTypeId)); 9674 return PVMFErrNotSupported; 9675 } 9676 } 9677 9678 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXEncNode-%s::DoCapConfigVerifyParameters() Out", iNodeTypeId)); 9679 return PVMFSuccess; 9680 9681 } 9682 9683 int32 PVMFOMXEncNode::PushBackKeyVal(Oscl_Vector<PvmiKvp, OsclMemAllocator>*& aValueListPtr, PvmiKvp &aKeyVal) 9684 { 9685 int32 leavecode = 0; 9686 OSCL_TRY(leavecode, (*aValueListPtr).push_back(aKeyVal)); 9687 return leavecode; 9688 } 9689 9690 int32 PVMFOMXEncNode::Push_Back_MetadataKeys(const char* aMetadataKey) 9691 { 9692 int32 leavecode = 0; 9693 OSCL_TRY(leavecode, iAvailableMetadataKeys.push_back(aMetadataKey)); 9694 return leavecode; 9695 } 9696 9697 int32 PVMFOMXEncNode::Push_Back_MetadataKeys(PVMFMetadataList *&aKeylistptr, uint32 aLcv) 9698 { 9699 int32 leavecode = 0; 9700 OSCL_TRY(leavecode, aKeylistptr->push_back(iAvailableMetadataKeys[aLcv])); 9701 return leavecode; 9702 } 9703 9704 int32 PVMFOMXEncNode::CreateNewArray(char*& aPtr, int32 aLen) 9705 { 9706 int32 leavecode = 0; 9707 OSCL_TRY(leavecode, 9708 aPtr = OSCL_ARRAY_NEW(char, aLen);); 9709 return leavecode; 9710 } 9711 9712 int32 PVMFOMXEncNode::MemAllocate(OsclAny *&aPtr, OsclMemPoolFixedChunkAllocator *aMemPool, uint32 aAllocSize) 9713 { 9714 uint32 errcode = 0; 9715 OSCL_TRY(errcode, aPtr = (OsclAny *) aMemPool->allocate(aAllocSize)); 9716 return errcode; 9717 } 9718 9719 bool PVMFOMXEncNode::ParseFullAVCFramesIntoNALs(OMX_BUFFERHEADERTYPE* aOutputBuffer) 9720 { 9721 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVMFOMXEncNode-%s : ParseFullAVCFramesIntoNALs IN", iNodeTypeId)); 9722 9723 if (iOMXComponentUsesNALStartCodes && !(aOutputBuffer->nFlags & OMX_BUFFERFLAG_EXTRADATA)) 9724 { 9725 OMX_U32 offset = aOutputBuffer->nOffset; 9726 OMX_U32 length = aOutputBuffer->nFilledLen; 9727 OMX_U8* pBuffer = aOutputBuffer->pBuffer + offset; 9728 OMX_U8* pCurrNAL; 9729 OMX_U32 bytesConsumed; 9730 int32 nalSize; 9731 9732 iNumNALs = 0; 9733 9734 while (length > 0) 9735 { 9736 nalSize = length; 9737 9738 if (false == AVCAnnexBGetNALUnit(pBuffer, &pCurrNAL, &nalSize, false)) 9739 { 9740 break; 9741 } 9742 9743 bytesConsumed = nalSize + (int32)(pCurrNAL - pBuffer); 9744 length -= bytesConsumed; 9745 pBuffer += bytesConsumed; 9746 9747 if ((iNALSizeArrayMaxElems > iNumNALs) && (iNALSizeArray != NULL)) 9748 { 9749 iNALSizeArray[iNumNALs] = nalSize; 9750 iNALPtrArray[iNumNALs] = (uint8*)pCurrNAL; /* need store NAL ptrs since start code can be either 4 bytes or 3 bytes */ 9751 iNumNALs++; 9752 } 9753 else 9754 { 9755 iNumNALs++; 9756 9757 // count the number of NALs in the buffer 9758 while (length > 0) 9759 { 9760 nalSize = length; 9761 9762 if (false == AVCAnnexBGetNALUnit(pBuffer, &pCurrNAL, &nalSize, false)) 9763 { 9764 break; 9765 } 9766 9767 bytesConsumed = nalSize + (int32)(pCurrNAL - pBuffer); 9768 length -= bytesConsumed; 9769 pBuffer += bytesConsumed; 9770 9771 iNumNALs++; 9772 } 9773 9774 // reassign alloc size to new max. 9775 iNALSizeArrayMaxElems = iNumNALs; 9776 9777 // free memory and then reallocate 9778 if (iNALSizeArray != NULL) 9779 { 9780 oscl_free(iNALSizeArray); 9781 } 9782 iNALSizeArray = (uint32*) oscl_malloc(sizeof(uint32) * iNALSizeArrayMaxElems); 9783 9784 if (iNALPtrArray != NULL) 9785 { 9786 oscl_free(iNALPtrArray); 9787 } 9788 iNALPtrArray = (uint8**) oscl_malloc(sizeof(uint8*) * iNALSizeArrayMaxElems); 9789 9790 // reset parameters and start over 9791 iNumNALs = 0; 9792 length = aOutputBuffer->nFilledLen; 9793 pBuffer = aOutputBuffer->pBuffer + offset; 9794 9795 if (iNALSizeArray == NULL || iNALPtrArray == NULL) 9796 { 9797 iNALSizeArrayMaxElems = 0; 9798 9799 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVMFOMXEncNode-%s : ParseFullAVCFramesIntoNALs ERROR - Out of Memory", iNodeTypeId)); 9800 return false; 9801 } 9802 } 9803 } 9804 9805 if (iNumNALs <= 0) 9806 { 9807 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVMFOMXEncNode-%s : ParseFullAVCFramesIntoNALs ERROR", iNodeTypeId)); 9808 return false; 9809 } 9810 } 9811 else if (aOutputBuffer->nFlags & OMX_BUFFERFLAG_EXTRADATA) 9812 { 9813 // get extra data from end of buffer 9814 OMX_OTHER_EXTRADATATYPE *pExtra; 9815 OMX_U32 offset = aOutputBuffer->nOffset + aOutputBuffer->nFilledLen; 9816 OMX_U32 allocLen = aOutputBuffer->nAllocLen; 9817 OMX_U8* pTemp = aOutputBuffer->pBuffer + offset; 9818 9819 // align 9820 pExtra = (OMX_OTHER_EXTRADATATYPE *)(((OMX_U32) pTemp + 3) & ~3); 9821 offset += (OMX_U32) pExtra - (OMX_U32) pTemp; 9822 9823 while (pExtra->eType != OMX_ExtraDataNone) 9824 { 9825 if (pExtra->eType == OMX_ExtraDataNALSizeArray) 9826 { 9827 iNumNALs = pExtra->nDataSize >> 2; 9828 if ((iNALSizeArrayMaxElems > iNumNALs) && (iNALSizeArray != NULL)) 9829 { 9830 oscl_memcpy(iNALSizeArray, ((OMX_U8*)pExtra + 20), pExtra->nDataSize); // 20 is the size of the extra data struct (minus data hint) 9831 } 9832 else 9833 { 9834 // reassign alloc size to new max. 9835 iNALSizeArrayMaxElems = iNumNALs; 9836 9837 // free memory and then reallocate 9838 if (iNALSizeArray != NULL) 9839 { 9840 oscl_free(iNALSizeArray); 9841 } 9842 9843 iNALSizeArray = (uint32*) oscl_malloc(sizeof(uint32) * iNALSizeArrayMaxElems); 9844 if (iNALSizeArray == NULL) 9845 { 9846 iNALSizeArrayMaxElems = 0; 9847 9848 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVMFOMXEncNode-%s : ParseFullAVCFramesIntoNALs ERROR - Out of Memory", iNodeTypeId)); 9849 return false; 9850 } 9851 9852 oscl_memcpy(iNALSizeArray, ((OMX_U8*)pExtra + 20), pExtra->nDataSize); // 20 is the size of the extra data struct (minus data hint) 9853 } 9854 9855 break; 9856 } 9857 9858 offset += pExtra->nSize; 9859 /* 20 is size of extra data struct (minus data hint), 9860 * so if there isn't enough room for there to be a full struct, and we haven't reached an OMX_ExtraDataNone 9861 * the data is corrupt 9862 */ 9863 if (offset > (allocLen - 20)) 9864 { 9865 // corrupt data 9866 break; 9867 } 9868 else 9869 { 9870 pExtra = (OMX_OTHER_EXTRADATATYPE *)((OMX_U8*)pExtra + pExtra->nSize); 9871 } 9872 } 9873 9874 if (pExtra->eType != OMX_ExtraDataNALSizeArray) 9875 { 9876 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVMFOMXEncNode-%s : ParseFullAVCFramesIntoNALs ERROR", iNodeTypeId)); 9877 return false; 9878 } 9879 } 9880 else 9881 { 9882 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVMFOMXEncNode-%s : ParseFullAVCFramesIntoNALs ERROR", iNodeTypeId)); 9883 return false; 9884 } 9885 9886 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVMFOMXEncNode-%s : ParseFullAVCFramesIntoNALs OUT", iNodeTypeId)); 9887 return true; 9888 } 9889 9890 /* utility function copied from the AVC Decoder interface */ 9891 bool PVMFOMXEncNode::AVCAnnexBGetNALUnit(uint8 *bitstream, uint8 **nal_unit, int32 *size, bool getPtrOnly) 9892 { 9893 int32 i, j, FoundStartCode = 0; 9894 int32 end; 9895 9896 i = 0; 9897 while (bitstream[i] == 0 && i < *size) 9898 { 9899 i++; 9900 } 9901 if (i >= *size) 9902 { 9903 *nal_unit = bitstream; 9904 return false; /* cannot find any start_code_prefix. */ 9905 } 9906 else if (bitstream[i] != 0x1) 9907 { 9908 i = -1; /* start_code_prefix is not at the beginning, continue */ 9909 } 9910 9911 i++; 9912 *nal_unit = bitstream + i; /* point to the beginning of the NAL unit */ 9913 9914 if (getPtrOnly) 9915 { 9916 // size not needed, just return with ptr 9917 return true; 9918 } 9919 9920 j = end = i; 9921 while (!FoundStartCode) 9922 { 9923 while ((j + 1 < *size) && (bitstream[j] != 0 || bitstream[j+1] != 0)) /* see 2 consecutive zero bytes */ 9924 { 9925 j++; 9926 } 9927 end = j; /* stop and check for start code */ 9928 while (j + 2 < *size && bitstream[j+2] == 0) /* keep reading for zero byte */ 9929 { 9930 j++; 9931 } 9932 if (j + 2 >= *size) 9933 { 9934 *size -= i; 9935 return true; /* cannot find the second start_code_prefix */ 9936 } 9937 if (bitstream[j+2] == 0x1) 9938 { 9939 FoundStartCode = 1; 9940 } 9941 else 9942 { 9943 /* could be emulation code 0x3 */ 9944 j += 2; /* continue the search */ 9945 } 9946 } 9947 9948 *size = end - i; 9949 9950 return true; 9951 } 9952 9953 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9954 bool PVMFOMXEncNode::CheckM4vVopStartCode(uint8* data, int* len) 9955 { 9956 int32 count = 0; 9957 int32 i = *len; 9958 9959 if (i < 4) // at least the size of frame header 9960 { 9961 return false; 9962 } 9963 while (--i) 9964 { 9965 if ((count > 1) && (data[0] == 0x01) && (data[1] == 0xB6)) 9966 { 9967 i += 2; 9968 break; 9969 } 9970 9971 if (*data++) 9972 count = 0; 9973 else 9974 count++; 9975 } 9976 9977 // i is number of bytes left (including 00 00 01 B6) 9978 if (i > 0) 9979 { 9980 *len = (*len - i - 1); // len before finding VOP start code 9981 return true; 9982 } 9983 9984 return false; 9985 } 9986 9987 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9988 OMX_TICKS PVMFOMXEncNode::ConvertTimestampIntoOMXTicks(const MediaClockConverter& src) 9989 { 9990 // This is similar to mediaclockconverter set_value method - except without using the modulo for upper part of 64 bits 9991 9992 // Timescale value cannot be zero 9993 OSCL_ASSERT(src.get_timescale() != 0); 9994 if (src.get_timescale() == 0) 9995 { 9996 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 9997 (0, "PVMFOMXEncNode-%s::ConvertTimestampIntoOMXTicks Input timescale is 0", iNodeTypeId)); 9998 9999 SetState(EPVMFNodeError); 10000 ReportErrorEvent(PVMFErrResourceConfiguration); 10001 return (OMX_TICKS) 0; 10002 } 10003 10004 OSCL_ASSERT(iTimeScale != 0); 10005 if (0 == iTimeScale) 10006 { 10007 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 10008 (0, "PVMFOMXEncNode-%s::ConvertTimestampIntoOMXTicks target timescale is 0", iNodeTypeId)); 10009 10010 SetState(EPVMFNodeError); 10011 ReportErrorEvent(PVMFErrResourceConfiguration); 10012 return (OMX_TICKS) 0; 10013 } 10014 10015 uint64 value = (uint64(src.get_wrap_count())) << 32; 10016 value += src.get_current_timestamp(); 10017 // rounding up 10018 value = (uint64(value) * iTimeScale + uint64(src.get_timescale() - 1)) / src.get_timescale(); 10019 return (OMX_TICKS) value; 10020 10021 10022 } 10023 //////////////////////////////////////////////////////////////////////////////////// 10024 uint32 PVMFOMXEncNode::ConvertOMXTicksIntoTimestamp(const OMX_TICKS &src) 10025 { 10026 // omx ticks use microsecond timescale (iTimeScale = 1000000) 10027 // This is similar to mediaclockconverter set_value method 10028 10029 // Timescale value cannot be zero 10030 OSCL_ASSERT(iOutTimeScale != 0); 10031 if (0 == iOutTimeScale) 10032 { 10033 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 10034 (0, "PVMFOMXEncNode-%s::ConvertOMXTicksIntoTimestamp Output timescale is 0", iNodeTypeId)); 10035 10036 SetState(EPVMFNodeError); 10037 ReportErrorEvent(PVMFErrResourceConfiguration); 10038 return (uint32) 0; 10039 } 10040 10041 OSCL_ASSERT(iTimeScale != 0); 10042 if (0 == iTimeScale) 10043 { 10044 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 10045 (0, "PVMFOMXEncNode-%s::ConvertOMXTicksIntoTimestamp target timescale is 0", iNodeTypeId)); 10046 10047 SetState(EPVMFNodeError); 10048 ReportErrorEvent(PVMFErrResourceConfiguration); 10049 return (uint32) 0; 10050 } 10051 10052 uint32 current_ts; 10053 10054 uint64 value = (uint64) src; 10055 10056 // rounding up 10057 value = (uint64(value) * iOutTimeScale + uint64(iTimeScale - 1)) / iTimeScale; 10058 10059 current_ts = (uint32)(value & 0xFFFFFFFF); 10060 return (uint32) current_ts; 10061 10062 } 10063 10064 //////////////////////////////////////////////////////////////////////////////// 10065 bool PVMFOMXEncNode::CheckComponentForMultRoles(OMX_STRING aCompName, OMX_STRING aRole) 10066 { 10067 OMX_ERRORTYPE err = OMX_ErrorNone; 10068 10069 // find out how many roles the component supports 10070 OMX_U32 NumRoles; 10071 err = OMX_MasterGetRolesOfComponent(aCompName, &NumRoles, NULL); 10072 if (err != OMX_ErrorNone) 10073 { 10074 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 10075 (0, "PVMFOMXEncNode-%s::CheckComponentForMultRoles() Problem getting component roles", iNodeTypeId)); 10076 10077 return false; 10078 } 10079 10080 // if the component supports multiple roles, call OMX_SetParameter 10081 if (NumRoles > 1) 10082 { 10083 OMX_PARAM_COMPONENTROLETYPE RoleParam; 10084 CONFIG_SIZE_AND_VERSION(RoleParam); 10085 oscl_strncpy((OMX_STRING)RoleParam.cRole, aRole, OMX_MAX_STRINGNAME_SIZE); 10086 err = OMX_SetParameter(iOMXEncoder, OMX_IndexParamStandardComponentRole, &RoleParam); 10087 if (err != OMX_ErrorNone) 10088 { 10089 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 10090 (0, "PVMFOMXEncNode-%s::CheckComponentForMultRoles() Problem setting component role", iNodeTypeId)); 10091 10092 return false; 10093 } 10094 } 10095 10096 return true; 10097 } 10098 10099 //////////////////////////////////////////////////////////////////////////////// 10100 bool PVMFOMXEncNode::CheckComponentCapabilities(PVMFFormatType* aOutFormat) 10101 { 10102 OMX_ERRORTYPE err = OMX_ErrorNone; 10103 10104 // GET CAPABILITY FLAGS FROM PV COMPONENT, IF this fails, use defaults 10105 PV_OMXComponentCapabilityFlagsType Cap_flags; 10106 err = OMX_GetParameter(iOMXEncoder, (OMX_INDEXTYPE) PV_OMX_COMPONENT_CAPABILITY_TYPE_INDEX, &Cap_flags); 10107 if (err != OMX_ErrorNone) 10108 { 10109 SetDefaultCapabilityFlags(); 10110 } 10111 else 10112 { 10113 iIsOMXComponentMultiThreaded = (OMX_TRUE == Cap_flags.iIsOMXComponentMultiThreaded) ? true : false; 10114 iOMXComponentSupportsExternalInputBufferAlloc = (OMX_TRUE == Cap_flags.iOMXComponentSupportsExternalInputBufferAlloc) ? true : false; 10115 iOMXComponentSupportsExternalOutputBufferAlloc = (OMX_TRUE == Cap_flags.iOMXComponentSupportsExternalOutputBufferAlloc) ? true : false; 10116 iOMXComponentSupportsMovableInputBuffers = (OMX_TRUE == Cap_flags.iOMXComponentSupportsMovableInputBuffers) ? true : false; 10117 iOMXComponentSupportsPartialFrames = (OMX_TRUE == Cap_flags.iOMXComponentSupportsPartialFrames) ? true : false; 10118 iOMXComponentUsesNALStartCodes = (OMX_TRUE == Cap_flags.iOMXComponentUsesNALStartCodes) ? true : false; 10119 iOMXComponentCanHandleIncompleteFrames = (OMX_TRUE == Cap_flags.iOMXComponentCanHandleIncompleteFrames) ? true : false; 10120 iOMXComponentUsesFullAVCFrames = (OMX_TRUE == Cap_flags.iOMXComponentUsesFullAVCFrames) ? true : false; 10121 } 10122 10123 /* iOMXComponentUsesNALStartCodes: The component inserts start codes before NALs 10124 10125 iOMXComponentUsesFullAVCFrames 10126 && !iOMXComponentUsesNALStartCodes: The component outputs full frames, and stores NAL start codes using the 10127 OMX ExtraData structure in the output buffer 10128 10129 iOMXComponentUsesFullAVCFrames 10130 && iOMXComponentUsesNALStartCodes: The component outputs full frames, and delimits NALs by their start codes 10131 10132 aOutFormat == PVMF_MIME_H264_VIDEO_RAW 10133 && !iOMXComponentUsesNALStartCodes: The node inserts the start codes and hides them / exposes them when needed 10134 10135 aOutFormat == PVMF_MIME_H264_VIDEO_RAW 10136 && !iOMXComponentUsesNALStartCodes 10137 && iOMXComponentUsesFullAVCFrames: This is an invalid combination. If the node wants raw output, and the component 10138 uses full frames, and no start codes, then there is no way to detect the 10139 NAL boundaries. 10140 */ 10141 10142 if (*aOutFormat == PVMF_MIME_H264_VIDEO_RAW && 10143 iOMXComponentUsesFullAVCFrames && !iOMXComponentUsesNALStartCodes) 10144 { 10145 // This is an invalid combination (see above). Therefore, return an error. 10146 10147 10148 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 10149 (0, "PVMFOMXEncNode-%s::CheckComponentCapabilities() Component cannot support %s format", iNodeTypeId, PVMF_MIME_H264_VIDEO_RAW)); 10150 10151 return false; 10152 } 10153 10154 // find out about parameters 10155 if (aOutFormat->isAudio()) 10156 { 10157 if (!NegotiateAudioComponentParameters()) 10158 { 10159 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 10160 (0, "PVMFOMXEncNode-%s::CheckComponentCapabilities() Cannot get component parameters", iNodeTypeId)); 10161 10162 return false; 10163 } 10164 } 10165 else 10166 { 10167 10168 if (!NegotiateVideoComponentParameters()) 10169 { 10170 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 10171 (0, "PVMFOMXEncNode-%s::CheckComponentCapabilities() Cannot get component parameters", iNodeTypeId)); 10172 10173 return false; 10174 } 10175 } 10176 10177 return true; 10178 } 10179 10180 10181