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_basedec_node.h" 19 #include "pvlogger.h" 20 #include "oscl_error_codes.h" 21 #ifndef OSCL_INT64_UTILS_H_INCLUDED 22 #include "oscl_int64_utils.h" 23 #endif 24 #include "pvmf_omx_basedec_port.h" 25 #include "pv_mime_string_utils.h" 26 #include "oscl_snprintf.h" 27 #include "pvmf_media_cmd.h" 28 #include "pvmf_media_msg_format_ids.h" 29 #include "pvmi_kvp_util.h" 30 31 #include "OMX_Core.h" 32 #include "pvmf_omx_basedec_callbacks.h" //used for thin AO in Decoder's callbacks 33 #include "pv_omxcore.h" 34 #include "pv_omx_config_parser.h" 35 #define CONFIG_SIZE_AND_VERSION(param) \ 36 param.nSize=sizeof(param); \ 37 param.nVersion.s.nVersionMajor = SPECVERSIONMAJOR; \ 38 param.nVersion.s.nVersionMinor = SPECVERSIONMINOR; \ 39 param.nVersion.s.nRevision = SPECREVISION; \ 40 param.nVersion.s.nStep = SPECSTEP; 41 42 #define PVOMXBASEDEC_MEDIADATA_CHUNKSIZE 128 43 #if 0 44 #include <utils/Log.h> 45 #undef LOG_TAG 46 #define LOG_TAG "SW_BASE" 47 48 #undef PVLOGGER_LOGMSG 49 #define PVLOGGER_LOGMSG(IL, LOGGER, LEVEL, MESSAGE) JJLOGE MESSAGE 50 #define JJLOGE(id, ...) LOGE(__VA_ARGS__) 51 #endif 52 53 // OMX CALLBACKS 54 // 1) AO OMX component running in the same thread as the OMX node 55 // In this case, the callbacks can be called directly from the component 56 // The callback: OMX Component->CallbackEventHandler->EventHandlerProcessing 57 // The callback can perform do RunIfNotReady 58 59 // 2) Multithreaded component 60 // In this case, the callback is made using the threadsafe callback (TSCB) AO 61 // Component thread : OMX Component->CallbackEventHandler->TSCB(ReceiveEvent) => event is queued 62 // Node thread : dequeue event => TSCB(ProcessEvent)->ProcessCallbackEventHandler->EventHandlerProcessing 63 64 65 66 // callback for Event Handler - in multithreaded case, event is queued to be processed later 67 // in AO case, event is processed immediately by calling EventHandlerProcessing 68 OMX_ERRORTYPE CallbackEventHandler(OMX_OUT OMX_HANDLETYPE aComponent, 69 OMX_OUT OMX_PTR aAppData, 70 OMX_OUT OMX_EVENTTYPE aEvent, 71 OMX_OUT OMX_U32 aData1, 72 OMX_OUT OMX_U32 aData2, 73 OMX_OUT OMX_PTR aEventData) 74 { 75 76 PVMFOMXBaseDecNode *Node = (PVMFOMXBaseDecNode *) aAppData; 77 78 if (Node->IsComponentMultiThreaded()) 79 { 80 // allocate the memory for the callback event specific data 81 //EventHandlerSpecificData* ED = (EventHandlerSpecificData*) oscl_malloc(sizeof (EventHandlerSpecificData)); 82 EventHandlerSpecificData* ED = (EventHandlerSpecificData*) Node->iThreadSafeHandlerEventHandler->iMemoryPool->allocate(sizeof(EventHandlerSpecificData)); 83 84 // pack the relevant data into the structure 85 ED->hComponent = aComponent; 86 ED->pAppData = aAppData; 87 ED->eEvent = aEvent; 88 ED->nData1 = aData1; 89 ED->nData2 = aData2; 90 ED->pEventData = aEventData; 91 92 // convert the pointer into OsclAny ptr 93 OsclAny* P = (OsclAny*) ED; 94 95 96 // CALL the generic callback AO API: 97 Node->iThreadSafeHandlerEventHandler->ReceiveEvent(P); 98 99 return OMX_ErrorNone; 100 } 101 else 102 { 103 104 OMX_ERRORTYPE status; 105 status = Node->EventHandlerProcessing(aComponent, aAppData, aEvent, aData1, aData2, aEventData); 106 return status; 107 } 108 109 } 110 111 // callback for EmptyBufferDone - in multithreaded case, event is queued to be processed later 112 // in AO case, event is processed immediately by calling EmptyBufferDoneProcessing 113 OMX_ERRORTYPE CallbackEmptyBufferDone(OMX_OUT OMX_HANDLETYPE aComponent, 114 OMX_OUT OMX_PTR aAppData, 115 OMX_OUT OMX_BUFFERHEADERTYPE* aBuffer) 116 { 117 118 PVMFOMXBaseDecNode *Node = (PVMFOMXBaseDecNode *) aAppData; 119 if (Node->IsComponentMultiThreaded()) 120 { 121 122 // allocate the memory for the callback event specific data 123 //EmptyBufferDoneSpecificData* ED = (EmptyBufferDoneSpecificData*) oscl_malloc(sizeof (EmptyBufferDoneSpecificData)); 124 EmptyBufferDoneSpecificData* ED = (EmptyBufferDoneSpecificData*) Node->iThreadSafeHandlerEmptyBufferDone->iMemoryPool->allocate(sizeof(EmptyBufferDoneSpecificData)); 125 126 // pack the relevant data into the structure 127 ED->hComponent = aComponent; 128 ED->pAppData = aAppData; 129 ED->pBuffer = aBuffer; 130 131 // convert the pointer into OsclAny ptr 132 OsclAny* P = (OsclAny*) ED; 133 134 // CALL the generic callback AO API: 135 Node->iThreadSafeHandlerEmptyBufferDone->ReceiveEvent(P); 136 137 return OMX_ErrorNone; 138 } 139 else 140 { 141 OMX_ERRORTYPE status; 142 status = Node->EmptyBufferDoneProcessing(aComponent, aAppData, aBuffer); 143 return status; 144 } 145 146 } 147 148 // callback for FillBufferDone - in multithreaded case, event is queued to be processed later 149 // in AO case, event is processed immediately by calling FillBufferDoneProcessing 150 OMX_ERRORTYPE CallbackFillBufferDone(OMX_OUT OMX_HANDLETYPE aComponent, 151 OMX_OUT OMX_PTR aAppData, 152 OMX_OUT OMX_BUFFERHEADERTYPE* aBuffer) 153 { 154 PVMFOMXBaseDecNode *Node = (PVMFOMXBaseDecNode *) aAppData; 155 if (Node->IsComponentMultiThreaded()) 156 { 157 158 // allocate the memory for the callback event specific data 159 //FillBufferDoneSpecificData* ED = (FillBufferDoneSpecificData*) oscl_malloc(sizeof (FillBufferDoneSpecificData)); 160 FillBufferDoneSpecificData* ED = (FillBufferDoneSpecificData*) Node->iThreadSafeHandlerFillBufferDone->iMemoryPool->allocate(sizeof(FillBufferDoneSpecificData)); 161 162 // pack the relevant data into the structure 163 ED->hComponent = aComponent; 164 ED->pAppData = aAppData; 165 ED->pBuffer = aBuffer; 166 167 // convert the pointer into OsclAny ptr 168 OsclAny* P = (OsclAny*) ED; 169 170 // CALL the generic callback AO API: 171 Node->iThreadSafeHandlerFillBufferDone->ReceiveEvent(P); 172 173 return OMX_ErrorNone; 174 } 175 else 176 { 177 OMX_ERRORTYPE status; 178 status = Node->FillBufferDoneProcessing(aComponent, aAppData, aBuffer); 179 return status; 180 } 181 182 } 183 184 // Callback processing in multithreaded case - dequeued event - call EventHandlerProcessing 185 OSCL_EXPORT_REF OsclReturnCode PVMFOMXBaseDecNode::ProcessCallbackEventHandler_MultiThreaded(OsclAny* P) 186 { 187 188 // re-cast the pointer 189 190 EventHandlerSpecificData* ED = (EventHandlerSpecificData*) P; 191 192 OMX_HANDLETYPE aComponent = ED->hComponent; 193 OMX_PTR aAppData = ED->pAppData; 194 OMX_EVENTTYPE aEvent = ED->eEvent; 195 OMX_U32 aData1 = ED->nData1; 196 OMX_U32 aData2 = ED->nData2; 197 OMX_PTR aEventData = ED->pEventData; 198 199 200 EventHandlerProcessing(aComponent, aAppData, aEvent, aData1, aData2, aEventData); 201 202 203 // release the allocated memory when no longer needed 204 205 iThreadSafeHandlerEventHandler->iMemoryPool->deallocate(ED); 206 ED = NULL; 207 208 return OsclSuccess; 209 } 210 211 212 213 // Callback processing in multithreaded case - dequeued event - call EmptyBufferDoneProcessing 214 OSCL_EXPORT_REF OsclReturnCode PVMFOMXBaseDecNode::ProcessCallbackEmptyBufferDone_MultiThreaded(OsclAny* P) 215 { 216 217 218 // re-cast the pointer 219 EmptyBufferDoneSpecificData* ED = (EmptyBufferDoneSpecificData*) P; 220 221 OMX_HANDLETYPE aComponent = ED->hComponent; 222 OMX_PTR aAppData = ED->pAppData; 223 OMX_BUFFERHEADERTYPE* aBuffer = ED->pBuffer; 224 225 EmptyBufferDoneProcessing(aComponent, aAppData, aBuffer); 226 227 // release the allocated memory when no longer needed 228 229 iThreadSafeHandlerEmptyBufferDone->iMemoryPool->deallocate(ED); 230 ED = NULL; 231 232 return OsclSuccess; 233 } 234 235 236 // Callback processing in multithreaded case - dequeued event - call FillBufferDoneProcessing 237 OSCL_EXPORT_REF OsclReturnCode PVMFOMXBaseDecNode::ProcessCallbackFillBufferDone_MultiThreaded(OsclAny* P) 238 { 239 240 // re-cast the pointer 241 FillBufferDoneSpecificData* ED = (FillBufferDoneSpecificData*) P; 242 243 OMX_HANDLETYPE aComponent = ED->hComponent; 244 OMX_PTR aAppData = ED->pAppData; 245 OMX_BUFFERHEADERTYPE* aBuffer = ED->pBuffer; 246 247 248 FillBufferDoneProcessing(aComponent, aAppData, aBuffer); 249 250 251 // release the allocated memory when no longer needed 252 253 iThreadSafeHandlerFillBufferDone->iMemoryPool->deallocate(ED); 254 ED = NULL; 255 256 return OsclSuccess; 257 } 258 259 ///////////////////////////////////////////////////////////////////////////// 260 // Class Destructor 261 ///////////////////////////////////////////////////////////////////////////// 262 OSCL_EXPORT_REF PVMFOMXBaseDecNode::~PVMFOMXBaseDecNode() 263 { 264 LogDiagnostics(); 265 266 //Clearup decoder 267 DeleteOMXBaseDecoder(); 268 269 // Cleanup callback AOs and Mempools 270 if (iThreadSafeHandlerEventHandler) 271 { 272 OSCL_DELETE(iThreadSafeHandlerEventHandler); 273 iThreadSafeHandlerEventHandler = NULL; 274 } 275 if (iThreadSafeHandlerEmptyBufferDone) 276 { 277 OSCL_DELETE(iThreadSafeHandlerEmptyBufferDone); 278 iThreadSafeHandlerEmptyBufferDone = NULL; 279 } 280 if (iThreadSafeHandlerFillBufferDone) 281 { 282 OSCL_DELETE(iThreadSafeHandlerFillBufferDone); 283 iThreadSafeHandlerFillBufferDone = NULL; 284 } 285 286 if (iMediaDataMemPool) 287 { 288 iMediaDataMemPool->removeRef(); 289 iMediaDataMemPool = NULL; 290 } 291 292 if (iOutBufMemoryPool) 293 { 294 iOutBufMemoryPool->removeRef(); 295 iOutBufMemoryPool = NULL; 296 } 297 if (iInBufMemoryPool) 298 { 299 iInBufMemoryPool->removeRef(); 300 iInBufMemoryPool = NULL; 301 } 302 303 //Thread logoff 304 if (IsAdded()) 305 { 306 RemoveFromScheduler(); 307 iIsAdded = false; 308 } 309 310 //Cleanup commands 311 //The command queues are self-deleting, but we want to 312 //notify the observer of unprocessed commands. 313 while (!iCurrentCommand.empty()) 314 { 315 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFFailure); 316 } 317 while (!iInputCommands.empty()) 318 { 319 CommandComplete(iInputCommands, iInputCommands.front(), PVMFFailure); 320 } 321 322 //Release Input buffer 323 iDataIn.Unbind(); 324 } 325 326 ///////////////////////////////////////////////////////////////////////////// 327 // Remove AO from the scheduler 328 ///////////////////////////////////////////////////////////////////////////// 329 OSCL_EXPORT_REF PVMFStatus PVMFOMXBaseDecNode::ThreadLogoff() 330 { 331 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "%s:ThreadLogoff", iName.Str())); 332 333 switch (iInterfaceState) 334 { 335 case EPVMFNodeIdle: 336 if (IsAdded()) 337 { 338 RemoveFromScheduler(); 339 iIsAdded = false; 340 } 341 iLogger = NULL; 342 SetState(EPVMFNodeCreated); 343 return PVMFSuccess; 344 // break; This break statement was removed to avoid compiler warning for Unreachable Code 345 346 347 default: 348 return PVMFErrInvalidState; 349 // break; This break statement was removed to avoid compiler warning for Unreachable Code 350 351 } 352 } 353 354 ///////////////////////////////////////////////////////////////////////////// 355 OSCL_EXPORT_REF PVMFStatus PVMFOMXBaseDecNode::GetCapability(PVMFNodeCapability& aNodeCapability) 356 { 357 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::GetCapability() called", iName.Str())); 358 359 aNodeCapability = iCapability; 360 return PVMFSuccess; 361 } 362 363 ///////////////////////////////////////////////////////////////////////////// 364 OSCL_EXPORT_REF PVMFPortIter* PVMFOMXBaseDecNode::GetPorts(const PVMFPortFilter* aFilter) 365 { 366 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::GetPorts() called", iName.Str())); 367 368 OSCL_UNUSED_ARG(aFilter); 369 370 return NULL; 371 } 372 373 ///////////////////////////////////////////////////////////////////////////// 374 OSCL_EXPORT_REF PVMFCommandId PVMFOMXBaseDecNode::QueueCommandL(PVMFOMXBaseDecNodeCommand& aCmd) 375 { 376 PVMFCommandId id; 377 378 id = iInputCommands.AddL(aCmd); 379 380 if (iInputCommands.size() == 1) 381 { 382 //wakeup the AO all the rest of input commands will reschedule the AO in Run 383 RunIfNotReady(); 384 } 385 return id; 386 } 387 388 ///////////////////////////////////////////////////////////////////////////// 389 OSCL_EXPORT_REF PVMFCommandId PVMFOMXBaseDecNode::QueryUUID(PVMFSessionId s, const PvmfMimeString& aMimeType, 390 Oscl_Vector<PVUuid, PVMFOMXBaseDecNodeAllocator>& aUuids, 391 bool aExactUuidsOnly, 392 const OsclAny* aContext) 393 { 394 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::QueryUUID() called", iName.Str())); 395 PVMFOMXBaseDecNodeCommand cmd; 396 cmd.PVMFOMXBaseDecNodeCommandBase::Construct(s, PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_QUERYUUID, aMimeType, aUuids, aExactUuidsOnly, aContext); 397 return QueueCommandL(cmd); 398 } 399 400 ///////////////////////////////////////////////////////////////////////////// 401 OSCL_EXPORT_REF PVMFCommandId PVMFOMXBaseDecNode::QueryInterface(PVMFSessionId s, const PVUuid& aUuid, 402 PVInterface*& aInterfacePtr, 403 const OsclAny* aContext) 404 { 405 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::QueryInterface() called", iName.Str())); 406 PVMFOMXBaseDecNodeCommand cmd; 407 cmd.PVMFOMXBaseDecNodeCommandBase::Construct(s, PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_QUERYINTERFACE, aUuid, aInterfacePtr, aContext); 408 return QueueCommandL(cmd); 409 } 410 411 ///////////////////////////////////////////////////////////////////////////// 412 OSCL_EXPORT_REF PVMFCommandId PVMFOMXBaseDecNode::RequestPort(PVMFSessionId s, int32 aPortTag, const PvmfMimeString* /* aPortConfig */, const OsclAny* aContext) 413 { 414 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::RequestPort() called", iName.Str())); 415 PVMFOMXBaseDecNodeCommand cmd; 416 cmd.PVMFOMXBaseDecNodeCommandBase::Construct(s, PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_REQUESTPORT, aPortTag, aContext); 417 return QueueCommandL(cmd); 418 } 419 420 ///////////////////////////////////////////////////////////////////////////// 421 OSCL_EXPORT_REF PVMFStatus PVMFOMXBaseDecNode::ReleasePort(PVMFSessionId s, PVMFPortInterface& aPort, const OsclAny* aContext) 422 { 423 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::ReleasePort() called", iName.Str())); 424 PVMFOMXBaseDecNodeCommand cmd; 425 cmd.PVMFOMXBaseDecNodeCommandBase::Construct(s, PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_RELEASEPORT, aPort, aContext); 426 return QueueCommandL(cmd); 427 } 428 429 ///////////////////////////////////////////////////////////////////////////// 430 OSCL_EXPORT_REF PVMFCommandId PVMFOMXBaseDecNode::Init(PVMFSessionId s, const OsclAny* aContext) 431 { 432 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::Init() called", iName.Str())); 433 PVMFOMXBaseDecNodeCommand cmd; 434 cmd.PVMFOMXBaseDecNodeCommandBase::Construct(s, PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_INIT, aContext); 435 return QueueCommandL(cmd); 436 } 437 438 ///////////////////////////////////////////////////////////////////////////// 439 OSCL_EXPORT_REF PVMFCommandId PVMFOMXBaseDecNode::Prepare(PVMFSessionId s, const OsclAny* aContext) 440 { 441 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::Prepare() called", iName.Str())); 442 PVMFOMXBaseDecNodeCommand cmd; 443 cmd.PVMFOMXBaseDecNodeCommandBase::Construct(s, PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_PREPARE, aContext); 444 return QueueCommandL(cmd); 445 } 446 447 ///////////////////////////////////////////////////////////////////////////// 448 OSCL_EXPORT_REF PVMFCommandId PVMFOMXBaseDecNode::Start(PVMFSessionId s, const OsclAny* aContext) 449 { 450 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::Start() called", iName.Str())); 451 PVMFOMXBaseDecNodeCommand cmd; 452 cmd.PVMFOMXBaseDecNodeCommandBase::Construct(s, PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_START, aContext); 453 return QueueCommandL(cmd); 454 } 455 456 ///////////////////////////////////////////////////////////////////////////// 457 OSCL_EXPORT_REF PVMFCommandId PVMFOMXBaseDecNode::Stop(PVMFSessionId s, const OsclAny* aContext) 458 { 459 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::Stop() called", iName.Str())); 460 PVMFOMXBaseDecNodeCommand cmd; 461 cmd.PVMFOMXBaseDecNodeCommandBase::Construct(s, PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_STOP, aContext); 462 return QueueCommandL(cmd); 463 } 464 465 ///////////////////////////////////////////////////////////////////////////// 466 OSCL_EXPORT_REF PVMFCommandId PVMFOMXBaseDecNode::Flush(PVMFSessionId s, const OsclAny* aContext) 467 { 468 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::Flush() called", iName.Str())); 469 PVMFOMXBaseDecNodeCommand cmd; 470 cmd.PVMFOMXBaseDecNodeCommandBase::Construct(s, PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_FLUSH, aContext); 471 return QueueCommandL(cmd); 472 } 473 474 ///////////////////////////////////////////////////////////////////////////// 475 OSCL_EXPORT_REF PVMFCommandId PVMFOMXBaseDecNode::Pause(PVMFSessionId s, const OsclAny* aContext) 476 { 477 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::Pause() called", iName.Str())); 478 PVMFOMXBaseDecNodeCommand cmd; 479 cmd.PVMFOMXBaseDecNodeCommandBase::Construct(s, PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_PAUSE, aContext); 480 return QueueCommandL(cmd); 481 } 482 483 ///////////////////////////////////////////////////////////////////////////// 484 OSCL_EXPORT_REF PVMFCommandId PVMFOMXBaseDecNode::Reset(PVMFSessionId s, const OsclAny* aContext) 485 { 486 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::Reset() called", iName.Str())); 487 PVMFOMXBaseDecNodeCommand cmd; 488 cmd.PVMFOMXBaseDecNodeCommandBase::Construct(s, PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_RESET, aContext); 489 return QueueCommandL(cmd); 490 } 491 492 ///////////////////////////////////////////////////////////////////////////// 493 OSCL_EXPORT_REF PVMFCommandId PVMFOMXBaseDecNode::CancelAllCommands(PVMFSessionId s, const OsclAny* aContext) 494 { 495 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::CancelAllCommands() called", iName.Str())); 496 PVMFOMXBaseDecNodeCommand cmd; 497 cmd.PVMFOMXBaseDecNodeCommandBase::Construct(s, PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_CANCELALL, aContext); 498 return QueueCommandL(cmd); 499 } 500 501 ///////////////////////////////////////////////////////////////////////////// 502 OSCL_EXPORT_REF PVMFCommandId PVMFOMXBaseDecNode::CancelCommand(PVMFSessionId s, PVMFCommandId aCmdId, const OsclAny* aContext) 503 { 504 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::CancelCommand() called", iName.Str())); 505 PVMFOMXBaseDecNodeCommand cmd; 506 cmd.PVMFOMXBaseDecNodeCommandBase::Construct(s, PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_CANCELCMD, aCmdId, aContext); 507 return QueueCommandL(cmd); 508 } 509 510 ///////////////////////////////////////////////////////////////////////////// 511 OSCL_EXPORT_REF PVMFStatus PVMFOMXBaseDecNode::SetDecoderNodeConfiguration(PVMFOMXBaseDecNodeConfig& aNodeConfig) 512 { 513 iNodeConfig = aNodeConfig; 514 return PVMFSuccess; 515 } 516 517 518 ///////////////////// 519 // Private Section // 520 ///////////////////// 521 522 ///////////////////////////////////////////////////////////////////////////// 523 // Class Constructor 524 ///////////////////////////////////////////////////////////////////////////// 525 OSCL_EXPORT_REF PVMFOMXBaseDecNode::PVMFOMXBaseDecNode(int32 aPriority, const char aAOName[], bool accelerated) : 526 OsclActiveObject(aPriority, aAOName), 527 iInPort(NULL), 528 iOutPort(NULL), 529 iOutBufMemoryPool(NULL), 530 iMediaDataMemPool(NULL), 531 iOMXComponentOutputBufferSize(0), 532 iOutputAllocSize(0), 533 iProcessingState(EPVMFOMXBaseDecNodeProcessingState_Idle), 534 iOMXDecoder(NULL), 535 iSendBOS(false), 536 iStreamID(0), 537 iBOSTimestamp(0), 538 iSeqNum(0), 539 iSeqNum_In(0), 540 iIsAdded(true), 541 iLogger(NULL), 542 iDataPathLogger(NULL), 543 iClockLogger(NULL), 544 iExtensionRefCount(0), 545 iEndOfDataReached(false), 546 iEndOfDataTimestamp(0), 547 iDiagnosticsLogger(NULL), 548 iDiagnosticsLogged(false), 549 iAvgBitrateValue(0), 550 iResetInProgress(false), 551 iResetMsgSent(false), 552 iStopInResetMsgSent(false), 553 iCompactFSISettingSucceeded(false), 554 bHWAccelerated(accelerated? OMX_TRUE: OMX_FALSE) 555 { 556 iThreadSafeHandlerEventHandler = NULL; 557 iThreadSafeHandlerEmptyBufferDone = NULL; 558 iThreadSafeHandlerFillBufferDone = NULL; 559 560 iInBufMemoryPool = NULL; 561 iOutBufMemoryPool = NULL; 562 563 // init to some value 564 iOMXComponentOutputBufferSize = 0; 565 iNumOutputBuffers = 0; 566 iNumOutstandingOutputBuffers = 0; 567 iOMXComponentInputBufferSize = 0; 568 iNumInputBuffers = 0; 569 570 iDoNotSendOutputBuffersDownstreamFlag = false; 571 iDoNotSaveInputBuffersFlag = false; 572 573 iOutputBuffersFreed = true;// buffers have not been created yet, so they can be considered freed 574 iInputBuffersFreed = true; 575 576 // dynamic port reconfig init vars 577 iSecondPortReportedChange = false; 578 iDynamicReconfigInProgress = false; 579 iPauseCommandWasSentToComponent = false; 580 iStopCommandWasSentToComponent = false; 581 582 // capability related, set to default values 583 iOMXComponentSupportsExternalOutputBufferAlloc = false; 584 iOMXComponentSupportsExternalInputBufferAlloc = false; 585 iOMXComponentSupportsMovableInputBuffers = false; 586 iIsOMXComponentMultiThreaded = true; 587 iOMXComponentSupportsPartialFrames = false; 588 iOMXComponentUsesNALStartCodes = true; 589 iOMXComponentUsesFullAVCFrames = false; 590 iOMXComponentCanHandleIncompleteFrames = true; 591 592 // EOS flag init 593 iIsEOSSentToComponent = false; 594 iIsEOSReceivedFromComponent = false; 595 596 // reset repositioning related flags 597 iIsRepositioningRequestSentToComponent = false; 598 iIsRepositionDoneReceivedFromComponent = false; 599 iIsOutputPortFlushed = false; 600 iIsInputPortFlushed = false; 601 602 // init state of component 603 iCurrentDecoderState = OMX_StateInvalid; 604 605 iOutTimeStamp = 0; 606 607 //if timescale value is 1 000 000 - it means that 608 //timestamp is expressed in units of 1/10^6 (i.e. microseconds) 609 610 iTimeScale = 1000000; 611 iInTimeScale = 1000; 612 iOutTimeScale = 1000; 613 614 615 iInputTimestampClock.set_timescale(iInTimeScale); // keep the timescale set to input timestamp 616 617 618 // counts output frames (for logging) 619 iFrameCounter = 0; 620 iInputBufferUnderConstruction = NULL; // for partial frame assembly 621 iFirstPieceOfPartialFrame = true; 622 iObtainNewInputBuffer = true; 623 iFirstDataMsgAfterBOS = true; 624 iKeepDroppingMsgsUntilMarkerBit = false; 625 626 } 627 628 ///////////////////////////////////////////////////////////////////////////// 629 // Local Run Routine 630 ///////////////////////////////////////////////////////////////////////////// 631 OSCL_EXPORT_REF void PVMFOMXBaseDecNode::Run() 632 { 633 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::Run() In", iName.Str())); 634 635 // if reset is in progress, call DoReset again until Reset Msg is sent 636 if ((iResetInProgress == true) && 637 (iResetMsgSent == false) && 638 (iCurrentCommand.size() > 0) && 639 (iCurrentCommand.front().iCmd == PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_RESET) 640 ) 641 { 642 DoReset(iCurrentCommand.front()); 643 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "%s::Run() - Calling DoReset", iName.Str())); 644 return; // don't do anything else 645 } 646 //Check for NODE commands... 647 if (!iInputCommands.empty()) 648 { 649 if (ProcessCommand(iInputCommands.front())) 650 { 651 if (iInterfaceState != EPVMFNodeCreated 652 && (!iInputCommands.empty() || (iInPort && (iInPort->IncomingMsgQueueSize() > 0)) || 653 (iDataIn.GetRep() != NULL) || (iDynamicReconfigInProgress == true) || 654 ((iNumOutstandingOutputBuffers < iNumOutputBuffers) && 655 (iProcessingState == EPVMFOMXBaseDecNodeProcessingState_ReadyToDecode)) 656 )) 657 { 658 // reschedule if more data is available, or if port reconfig needs to be finished (even if there is no new data) 659 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "%s::Run() - rescheduling after process command", iName.Str())); 660 RunIfNotReady(); 661 } 662 return; 663 } 664 665 if (!iInputCommands.empty()) 666 { 667 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "%s::Run() - rescheduling to process more commands", iName.Str())); 668 RunIfNotReady(); 669 } 670 } 671 else 672 { 673 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "%s::Run() - Input commands empty", iName.Str())); 674 } 675 676 if (((iCurrentCommand.size() == 0) && (iInterfaceState != EPVMFNodeStarted)) || 677 ((iCurrentCommand.size() > 0) && (iCurrentCommand.front().iCmd == PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_START) && (iInterfaceState != EPVMFNodeStarted))) 678 { 679 // rescheduling because of input data will be handled in Command Processing Part 680 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "%s::Run() - Node not in Started state yet", iName.Str())); 681 return; 682 } 683 684 685 // Process port activity, push out all outgoing messages 686 if (iOutPort) 687 { 688 while (iOutPort->OutgoingMsgQueueSize()) 689 { 690 // if port is busy it is going to wakeup from port ready event 691 if (!ProcessOutgoingMsg(iOutPort)) 692 { 693 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "%s::Run() - Outgoing Port Busy, cannot send more msgs", iName.Str())); 694 break; 695 } 696 } 697 } 698 int loopCount = 0; 699 #if (PVLOGGER_INST_LEVEL >= PVLOGMSG_INST_REL) 700 uint32 startticks = OsclTickCount::TickCount(); 701 uint32 starttime = OsclTickCount::TicksToMsec(startticks); 702 #endif 703 do // Try to consume all the data from the Input port 704 { 705 // Process port activity if there is no input data that is being processed 706 // Do not accept any input if EOS needs to be sent out 707 if (iInPort && (iInPort->IncomingMsgQueueSize() > 0) && (iDataIn.GetRep() == NULL) && 708 (!iEndOfDataReached) && 709 (!iDynamicReconfigInProgress) && 710 (!iIsRepositioningRequestSentToComponent) 711 ) 712 713 { 714 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "%s::Run() - Getting more input", iName.Str())); 715 if (!ProcessIncomingMsg(iInPort)) 716 { 717 //Re-schedule 718 RunIfNotReady(); 719 return; 720 } 721 } 722 723 if (iSendBOS) 724 { 725 726 // this routine may be re-entered multiple times in multiple Run's before the component goes through cycle execute->idle->execute 727 if (!HandleRepositioning()) 728 { 729 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "%s::Run() - Repositioning not done yet", iName.Str())); 730 731 return; 732 } 733 734 SendBeginOfMediaStreamCommand(); 735 736 737 } 738 // If in init or ready to decode state, process data in the input port if there is input available and input buffers are present 739 // (note: at EOS, iDataIn will not be available) 740 741 if ((iDataIn.GetRep() != NULL) || 742 ((iNumOutstandingOutputBuffers < iNumOutputBuffers) && 743 (iProcessingState == EPVMFOMXBaseDecNodeProcessingState_ReadyToDecode) && 744 (iResetMsgSent == false)) || 745 ((iDynamicReconfigInProgress == true) && (iResetMsgSent == false)) 746 747 ) 748 { 749 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 750 (0, "%s::Run() - Calling HandleProcessingState", iName.Str())); 751 752 // input data is available, that means there is input data to be decoded 753 if (HandleProcessingState() != PVMFSuccess) 754 { 755 // If HandleProcessingState does not return Success, we must wait for an event 756 // no point in rescheduling 757 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 758 (0, "%s::Run() - HandleProcessingState did not return Success", iName.Str())); 759 760 return; 761 } 762 } 763 764 loopCount++; 765 } 766 while (iInPort && 767 (((iInPort->IncomingMsgQueueSize() > 0) || (iDataIn.GetRep() != NULL)) && (iNumOutstandingInputBuffers < iNumInputBuffers)) 768 && (!iEndOfDataReached) 769 && (iResetMsgSent == false) 770 ); 771 #if (PVLOGGER_INST_LEVEL >= PVLOGMSG_INST_REL) 772 uint32 endticks = OsclTickCount::TickCount(); 773 uint32 endtime = OsclTickCount::TicksToMsec(endticks); 774 uint32 timeinloop; 775 timeinloop = (endtime - starttime); 776 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iRunlLogger, PVLOGMSG_INFO, 777 (0, "%s::Run() - LoopCount = %d, Time spent in loop(in ms) = %d, iNumOutstandingInputBuffers = %d, iNumOutstandingOutputBuffers = %d ", 778 iName.Str(), loopCount, timeinloop, iNumOutstandingInputBuffers, iNumOutstandingOutputBuffers)); 779 #endif 780 781 // EOS processing: 782 // first send an empty buffer to OMX component and mark the EOS flag 783 // wait for the OMX component to send async event to indicate that it has reached this EOS buffer 784 // then, create and send the EOS message downstream 785 786 if (iEndOfDataReached && !iDynamicReconfigInProgress) 787 { 788 789 // if EOS was not sent yet and we have an available input buffer, send EOS buffer to component 790 if (!iIsEOSSentToComponent && (iNumOutstandingInputBuffers < iNumInputBuffers)) 791 { 792 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 793 (0, "%s::Run() - Sending EOS marked buffer To Component ", iName.Str())); 794 795 iIsEOSSentToComponent = true; 796 797 // if the component is not yet initialized or if it's in the middle of port reconfig, 798 // don't send EOS buffer to component. It does not care. Just set the flag as if we received 799 // EOS from the component to enable sending EOS downstream 800 if (iProcessingState != EPVMFOMXBaseDecNodeProcessingState_ReadyToDecode) 801 { 802 803 iIsEOSReceivedFromComponent = true; 804 } 805 else if (!SendEOSBufferToOMXComponent()) 806 807 { 808 // for some reason, Component can't receive the EOS buffer 809 // it could be that it is not initialized yet (because EOS could be the first msg). In this case, 810 // send the EOS downstream anyway 811 iIsEOSReceivedFromComponent = true; 812 } 813 } 814 815 // DV: we must wait for event (acknowledgment from component) 816 // before sending EOS downstream. This is because OMX Component will send 817 // the EOS event only after processing remaining buffers 818 819 if (iIsEOSReceivedFromComponent) 820 { 821 822 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 823 (0, "%s::Run() - Received EOS from component, Sending EOS msg downstream ", iName.Str())); 824 825 if (iOutPort && iOutPort->IsOutgoingQueueBusy()) 826 { 827 // note: we already tried to empty the outgoing q. If it's still busy, 828 // it means that output port is busy. Just return and wait for the port to become free. 829 // this will wake up the node and it will send out a msg from the q etc. 830 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 831 (0, "%s::Run() - - EOS cannot be sent downstream, outgoing queue busy - wait", iName.Str())); 832 return; 833 } 834 835 if (SendEndOfTrackCommand()) // this will only q the EOS 836 { 837 // EOS send downstream OK, so reset the flag 838 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 839 (0, "%s::Run() - EOS was queued to be sent downstream", iName.Str())); 840 841 iEndOfDataReached = false; // to resume normal processing, reset the flags 842 iIsEOSSentToComponent = false; 843 iIsEOSReceivedFromComponent = false; 844 845 RunIfNotReady(); // Run again to send out the EOS msg from the outgoing q, and resume 846 // normal processing 847 ReportInfoEvent(PVMFInfoEndOfData); 848 } 849 } 850 else 851 { 852 // keep sending output buffers, it's possible that the component needs to flush output 853 // data at the end 854 while (iNumOutstandingOutputBuffers < iNumOutputBuffers) 855 { 856 if (!SendOutputBufferToOMXComponent()) 857 break; 858 } 859 } 860 861 } 862 863 864 //Check for flash command complition... 865 if (iInPort && iOutPort && (iCurrentCommand.size() > 0) && 866 (iCurrentCommand.front().iCmd == PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_FLUSH) && 867 (iInPort->IncomingMsgQueueSize() == 0) && 868 (iOutPort->OutgoingMsgQueueSize() == 0) && 869 (iDataIn.GetRep() == NULL)) 870 { 871 //flush command is complited 872 //Debug check-- all the port queues should be empty at this point. 873 874 OSCL_ASSERT(iInPort->IncomingMsgQueueSize() == 0 && iOutPort->OutgoingMsgQueueSize() == 0); 875 876 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "%s::Run() - Flush pending", iName.Str())); 877 iEndOfDataReached = false; 878 iIsEOSSentToComponent = false; 879 iIsEOSReceivedFromComponent = false; 880 881 882 //Flush is complete. Go to initialized state. 883 SetState(EPVMFNodePrepared); 884 //resume port input so the ports can be re-started. 885 iInPort->ResumeInput(); 886 iOutPort->ResumeInput(); 887 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess); 888 RunIfNotReady(); 889 } 890 891 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::Run() Out", iName.Str())); 892 } 893 894 ///////////////////////////////////////////////////////////////////////////// 895 // This routine will dispatch recived commands 896 ///////////////////////////////////////////////////////////////////////////// 897 bool PVMFOMXBaseDecNode::ProcessCommand(PVMFOMXBaseDecNodeCommand& aCmd) 898 { 899 //normally this node will not start processing one command 900 //until the prior one is finished. However, a hi priority 901 //command such as Cancel must be able to interrupt a command 902 //in progress. 903 if (!iCurrentCommand.empty() && !aCmd.hipri()) 904 return false; 905 906 switch (aCmd.iCmd) 907 { 908 case PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_QUERYUUID: 909 DoQueryUuid(aCmd); 910 break; 911 912 case PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_QUERYINTERFACE: 913 DoQueryInterface(aCmd); 914 break; 915 916 case PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_REQUESTPORT: 917 DoRequestPort(aCmd); 918 break; 919 920 case PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_RELEASEPORT: 921 DoReleasePort(aCmd); 922 break; 923 924 case PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_INIT: 925 DoInit(aCmd); 926 break; 927 928 case PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_PREPARE: 929 DoPrepare(aCmd); 930 break; 931 932 case PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_START: 933 DoStart(aCmd); 934 break; 935 936 case PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_STOP: 937 DoStop(aCmd); 938 break; 939 940 case PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_FLUSH: 941 DoFlush(aCmd); 942 break; 943 944 case PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_PAUSE: 945 DoPause(aCmd); 946 break; 947 948 case PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_RESET: 949 DoReset(aCmd); 950 break; 951 952 case PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_CANCELCMD: 953 DoCancelCommand(aCmd); 954 break; 955 956 case PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_CANCELALL: 957 DoCancelAllCommands(aCmd); 958 break; 959 960 case PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_GETNODEMETADATAKEY: 961 { 962 PVMFStatus retval = DoGetNodeMetadataKey(aCmd); 963 CommandComplete(iInputCommands, aCmd, retval); 964 } 965 break; 966 967 case PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_GETNODEMETADATAVALUE: 968 { 969 PVMFStatus retval = DoGetNodeMetadataValue(aCmd); 970 CommandComplete(iInputCommands, aCmd, retval); 971 } 972 break; 973 974 default://unknown command type 975 CommandComplete(iInputCommands, aCmd, PVMFFailure); 976 break; 977 } 978 979 return true; 980 } 981 982 ///////////////////////////////////////////////////////////////////////////// 983 // This routine will process incomming message from the port 984 ///////////////////////////////////////////////////////////////////////////// 985 OSCL_EXPORT_REF bool PVMFOMXBaseDecNode::ProcessIncomingMsg(PVMFPortInterface* aPort) 986 { 987 //Called by the AO to process one buffer off the port's 988 //incoming data queue. This routine will dequeue and 989 //dispatch the data. 990 991 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 992 (0, "0x%x %s::ProcessIncomingMsg: aPort=0x%x", this, iName.Str(), aPort)); 993 994 PVMFStatus status = PVMFFailure; 995 996 997 //#define SIMULATE_BOS 998 #ifdef SIMULATE_BOS 999 1000 if (((PVMFOMXDecPort*)aPort)->iNumFramesConsumed == 6)) 1001 { 1002 1003 PVMFSharedMediaCmdPtr BOSCmdPtr = PVMFMediaCmd::createMediaCmd(); 1004 1005 // Set the format ID to BOS 1006 BOSCmdPtr->setFormatID(PVMF_MEDIA_CMD_BOS_FORMAT_ID); 1007 1008 // Set the timestamp 1009 BOSCmdPtr->setTimestamp(201); 1010 BOSCmdPtr->setStreamID(0); 1011 1012 // Convert to media message and send it out 1013 PVMFSharedMediaMsgPtr mediaMsgOut; 1014 convertToPVMFMediaCmdMsg(mediaMsgOut, BOSCmdPtr); 1015 1016 //store the stream id and time stamp of bos message 1017 iStreamID = mediaMsgOut->getStreamID(); 1018 iBOSTimestamp = mediaMsgOut->getTimestamp(); 1019 1020 iInputTimestampClock.set_clock(iBOSTimestamp, 0); 1021 iOMXTicksTimestamp = ConvertTimestampIntoOMXTicks(iInputTimestampClock); 1022 1023 iSendBOS = true; 1024 1025 ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++; 1026 return true; 1027 1028 } 1029 #endif 1030 //#define SIMULATE_PREMATURE_EOS 1031 #ifdef SIMULATE_PREMATURE_EOS 1032 if (((PVMFOMXDecPort*)aPort)->iNumFramesConsumed == 5) 1033 { 1034 PVMFSharedMediaCmdPtr EOSCmdPtr = PVMFMediaCmd::createMediaCmd(); 1035 1036 // Set the format ID to EOS 1037 EOSCmdPtr->setFormatID(PVMF_MEDIA_CMD_EOS_FORMAT_ID); 1038 1039 // Set the timestamp 1040 EOSCmdPtr->setTimestamp(200); 1041 1042 // Convert to media message and send it out 1043 PVMFSharedMediaMsgPtr mediaMsgOut; 1044 convertToPVMFMediaCmdMsg(mediaMsgOut, EOSCmdPtr); 1045 1046 ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++; 1047 1048 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1049 (0, "%s::ProcessIncomingMsg: SIMULATED EOS", iName.Str())); 1050 1051 // Set EOS flag 1052 iEndOfDataReached = true; 1053 // Save the timestamp for the EOS cmd 1054 iEndOfDataTimestamp = mediaMsgOut->getTimestamp(); 1055 1056 return true; 1057 } 1058 1059 #endif 1060 1061 1062 1063 PVMFSharedMediaMsgPtr msg; 1064 1065 status = aPort->DequeueIncomingMsg(msg); 1066 if (status != PVMFSuccess) 1067 { 1068 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 1069 (0, "0x%x %s::ProcessIncomingMsg: Error - DequeueIncomingMsg failed", this, iName.Str())); 1070 return false; 1071 } 1072 1073 if (msg->getFormatID() == PVMF_MEDIA_CMD_BOS_FORMAT_ID) 1074 { 1075 //store the stream id and time stamp of bos message 1076 iStreamID = msg->getStreamID(); 1077 iBOSTimestamp = msg->getTimestamp(); 1078 iSendBOS = true; 1079 1080 // we need to initialize the timestamp here - so that updates later on are accurate (in terms of rollover etc) 1081 iInputTimestampClock.set_clock(iBOSTimestamp, 0); 1082 iOMXTicksTimestamp = ConvertTimestampIntoOMXTicks(iInputTimestampClock); 1083 1084 // if new BOS arrives, and 1085 //if we're in the middle of a partial frame assembly 1086 // abandon it and start fresh 1087 if (iObtainNewInputBuffer == false) 1088 { 1089 if (iInputBufferUnderConstruction != NULL) 1090 { 1091 if (iInBufMemoryPool != NULL) 1092 { 1093 iInBufMemoryPool->deallocate((OsclAny *)iInputBufferUnderConstruction); 1094 } 1095 iInputBufferUnderConstruction = NULL; 1096 } 1097 iObtainNewInputBuffer = true; 1098 1099 } 1100 1101 // needed to init the sequence numbers and timestamp for partial frame assembly 1102 iFirstDataMsgAfterBOS = true; 1103 iKeepDroppingMsgsUntilMarkerBit = false; 1104 1105 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1106 (0, "%s::ProcessIncomingMsg: Received BOS stream %d, timestamp %d", iName.Str(), iStreamID, iBOSTimestamp)); 1107 ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++; 1108 return true; 1109 } 1110 else if (msg->getFormatID() == PVMF_MEDIA_CMD_EOS_FORMAT_ID) 1111 { 1112 // Set EOS flag 1113 iEndOfDataReached = true; 1114 // Save the timestamp for the EOS cmd 1115 iEndOfDataTimestamp = msg->getTimestamp(); 1116 1117 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1118 (0, "%s::ProcessIncomingMsg: Received EOS", iName.Str())); 1119 1120 ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++; 1121 return true; // do not do conversion into media data, just set the flag and leave 1122 } 1123 1124 convertToPVMFMediaData(iDataIn, msg); 1125 1126 1127 iCurrFragNum = 0; // for new message, reset the fragment counter 1128 iIsNewDataFragment = true; 1129 1130 ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++; 1131 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::ProcessIncomingMsg() Received %d frames", iName.Str(), ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed)); 1132 1133 //return true if we processed an activity... 1134 return true; 1135 } 1136 1137 ///////////////////////////////////////////////////////////////////////////// 1138 // This routine will process outgoing message by sending it into output the port 1139 ///////////////////////////////////////////////////////////////////////////// 1140 bool PVMFOMXBaseDecNode::ProcessOutgoingMsg(PVMFPortInterface* aPort) 1141 { 1142 //Called by the AO to process one message off the outgoing 1143 //message queue for the given port. This routine will 1144 //try to send the data to the connected port. 1145 1146 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1147 (0, "0x%x %s::ProcessOutgoingMsg: aPort=0x%x", this, iName.Str(), aPort)); 1148 1149 PVMFStatus status = aPort->Send(); 1150 if (status == PVMFErrBusy) 1151 { 1152 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 1153 (0, "0x%x %s::ProcessOutgoingMsg: Connected port goes into busy state", this, iName.Str())); 1154 } 1155 1156 //Report any unexpected failure in port processing... 1157 //(the InvalidState error happens when port input is suspended, 1158 //so don't report it.) 1159 if (status != PVMFErrBusy 1160 && status != PVMFSuccess 1161 && status != PVMFErrInvalidState) 1162 { 1163 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 1164 (0, "0x%x %s::Run: Error - ProcessPortActivity failed. port=0x%x, type=%d", 1165 this, iName.Str(), iOutPort, PVMF_PORT_ACTIVITY_OUTGOING_MSG)); 1166 ReportErrorEvent(PVMFErrPortProcessing); 1167 } 1168 1169 //return true if we processed an activity... 1170 return (status != PVMFErrBusy); 1171 } 1172 1173 ///////////////////////////////////////////////////////////////////////////// 1174 // This routine will process received data usign State Machine 1175 ///////////////////////////////////////////////////////////////////////////// 1176 PVMFStatus PVMFOMXBaseDecNode::HandleProcessingState() 1177 { 1178 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::HandleProcessingState() In", iName.Str())); 1179 1180 PVMFStatus status = PVMFSuccess; 1181 1182 switch (iProcessingState) 1183 { 1184 case EPVMFOMXBaseDecNodeProcessingState_InitDecoder: 1185 { 1186 // do init only if input data is available 1187 if (iDataIn.GetRep() != NULL) 1188 { 1189 if (!InitDecoder(iDataIn)) 1190 { 1191 // Decoder initialization failed. Fatal error 1192 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 1193 (0, "%s::HandleProcessingState() Decoder initialization failed", iName.Str())); 1194 ReportErrorEvent(PVMFErrResourceConfiguration); 1195 ChangeNodeState(EPVMFNodeError); 1196 break; 1197 } 1198 1199 // if a callback already happened, continue to decoding. If not, wait 1200 // it is also possible that port settings changed event may occur. 1201 //DV: temp 1202 //if(iProcessingState != EPVMFOMXBaseDecNodeProcessingState_ReadyToDecode) 1203 // iProcessingState = EPVMFOMXBaseDecNodeProcessingState_WaitForInitCompletion; 1204 1205 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_ReadyToDecode; 1206 // spin once to send output buffers 1207 RunIfNotReady(); 1208 status = PVMFSuccess; // allow rescheduling 1209 } 1210 break; 1211 } 1212 1213 case EPVMFOMXBaseDecNodeProcessingState_WaitForInitCompletion: 1214 { 1215 1216 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1217 (0, "%s::HandleProcessingState() WaitForInitCompletion -> wait for config buffer to return", iName.Str())); 1218 1219 1220 status = PVMFPending; // prevent rescheduling 1221 break; 1222 } 1223 // The FOLLOWING 4 states handle Dynamic Port Reconfiguration 1224 #if 0 //QCOM WORKAROUND JJDBG. Disable this QCOM workaround as i) it has side effects; ii) QCOM HW decoder is NOT used for m4v and h263 in Cupcake. JJ 03/25/09 1225 case EPVMFOMXBaseDecNodeProcessingState_PortReconfig: 1226 { 1227 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1228 (0, "%s::HandleProcessingState() Port Reconfiguration -> Sending Flush Command", iName.Str())); 1229 1230 1231 1232 // port reconfiguration is required. Only one port at a time is disabled and then re-enabled after buffer resizing 1233 OMX_SendCommand(iOMXDecoder, OMX_CommandPortDisable, iPortIndexForDynamicReconfig, NULL); 1234 1235 // the port will now start returning outstanding buffers 1236 // set the flag to prevent output from going downstream (in case of output port being reconfigd) 1237 // set the flag to prevent input from being saved and returned to component (in case of input port being reconfigd) 1238 // set the state to wait for port saying it is disabled 1239 if (iPortIndexForDynamicReconfig == iOutputPortIndex) 1240 { 1241 iDoNotSendOutputBuffersDownstreamFlag = true; 1242 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1243 (0, "%s::HandleProcessingState() Port Reconfiguration -> Output Port", iName.Str())); 1244 1245 } 1246 else if (iPortIndexForDynamicReconfig == iInputPortIndex) 1247 { 1248 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1249 (0, "%s::HandleProcessingState() Port Reconfiguration -> Input Port", iName.Str())); 1250 1251 iDoNotSaveInputBuffersFlag = true; 1252 } 1253 else 1254 { 1255 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1256 (0, "%s::HandleProcessingState() Port Reconfiguration -> UNKNOWN PORT", iName.Str())); 1257 1258 //sState = OMX_StateInvalid; 1259 ReportErrorEvent(PVMFErrResourceConfiguration); 1260 ChangeNodeState(EPVMFNodeError); 1261 status = PVMFFailure; 1262 break; 1263 1264 } 1265 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_WaitForBufferReturn; 1266 1267 1268 // fall through to the next case to check if all buffers are already back 1269 1270 1271 1272 } 1273 1274 case EPVMFOMXBaseDecNodeProcessingState_WaitForBufferReturn: 1275 { 1276 // as buffers are coming back, Run may be called, wait until all buffers are back, then Free them all 1277 1278 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1279 (0, "%s::HandleProcessingState() Port Reconfiguration -> WaitForBufferReturn ", iName.Str())); 1280 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s:: Ln %d iPortIndexForDynamicReconfig %d iNumOutstandingInputBuffers %d iNumOutstandingOutputBuffers %d", iName.Str(), __LINE__, iPortIndexForDynamicReconfig, iNumOutstandingInputBuffers , iNumOutstandingOutputBuffers)); 1281 1282 // check if it's output port being reconfigured 1283 if (iPortIndexForDynamicReconfig == iOutputPortIndex) 1284 { 1285 // if all buffers have returned, free them 1286 if (iNumOutstandingOutputBuffers == 0) 1287 { 1288 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1289 (0, "%s::HandleProcessingState() Port Reconfiguration -> all output buffers are back, free them", iName.Str())); 1290 1291 if (false == iOutputBuffersFreed) 1292 { 1293 if (!FreeBuffersFromComponent(iOutBufMemoryPool, // allocator 1294 iOutputAllocSize, // size to allocate from pool (hdr only or hdr+ buffer) 1295 iNumOutputBuffers, // number of buffers 1296 iOutputPortIndex, // port idx 1297 false // this is not input 1298 )) 1299 { 1300 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 1301 (0, "%s::HandleProcessingState() Port Reconfiguration -> Cannot free output buffers ", iName.Str())); 1302 1303 SetState(EPVMFNodeError); 1304 ReportErrorEvent(PVMFErrNoMemory); 1305 return PVMFErrNoMemory; 1306 } 1307 } 1308 // if the callback (that port is disabled) has not arrived yet, wait for it 1309 // if it has arrived, it will set the state to PortReEnable 1310 if (iProcessingState != EPVMFOMXBaseDecNodeProcessingState_PortReEnable) 1311 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_WaitForPortDisable; 1312 1313 status = PVMFSuccess; // allow rescheduling of the node potentially 1314 } 1315 else 1316 status = PVMFPending; // must wait for buffers to come back. No point in automatic rescheduling 1317 // but each buffer will reschedule the node when it comes in 1318 } 1319 else 1320 { 1321 // this is input port 1322 1323 // if all buffers have returned, free them 1324 if (iNumOutstandingInputBuffers == 0) 1325 { 1326 1327 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1328 (0, "%s::HandleProcessingState() Port Reconfiguration -> all input buffers are back, free them", iName.Str())); 1329 1330 // port reconfiguration is required. Only one port at a time is disabled and then re-enabled after buffer resizing 1331 OMX_SendCommand(iOMXDecoder, OMX_CommandPortDisable, iPortIndexForDynamicReconfig, NULL); 1332 1333 if (false == iInputBuffersFreed) 1334 { 1335 if (!FreeBuffersFromComponent(iInBufMemoryPool, // allocator 1336 iInputAllocSize, // size to allocate from pool (hdr only or hdr+ buffer) 1337 iNumInputBuffers, // number of buffers 1338 iInputPortIndex, // port idx 1339 true // this is input 1340 )) 1341 { 1342 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 1343 (0, "%s::HandleProcessingState() Port Reconfiguration -> Cannot free input buffers ", iName.Str())); 1344 1345 SetState(EPVMFNodeError); 1346 ReportErrorEvent(PVMFErrNoMemory); 1347 return PVMFErrNoMemory; 1348 1349 } 1350 } 1351 // if the callback (that port is disabled) has not arrived yet, wait for it 1352 // if it has arrived, it will set the state to PortReEnable 1353 if (iProcessingState != EPVMFOMXBaseDecNodeProcessingState_PortReEnable) 1354 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_WaitForPortDisable; 1355 1356 status = PVMFSuccess; // allow rescheduling of the node 1357 } 1358 else 1359 status = PVMFPending; // must wait for buffers to come back. No point in automatic 1360 // rescheduling. Each buffer will reschedule the node 1361 // when it comes in 1362 } 1363 1364 1365 // the state will be changed to PortReEnable once we get confirmation that Port was actually disabled 1366 break; 1367 } 1368 #else 1369 case EPVMFOMXBaseDecNodeProcessingState_PortReconfig: 1370 { 1371 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1372 (0, "%s::HandleProcessingState() Port Reconfiguration -> Sending Flush Command", iName.Str())); 1373 1374 1375 // Collect all buffers first (before starting the portDisable command) 1376 // FIRST send a flush command. This will return all buffers from the component. Any outstanding buffers are in MIO 1377 // Then wait for all buffers to come back from MIO. If we haven't sent port disable, we'll be able to process 1378 // other commands in the copmponent (such as pause, stop etc.) 1379 OMX_ERRORTYPE err = OMX_ErrorNone; 1380 OMX_STATETYPE sState; 1381 1382 // first check the state (if executing or paused, continue) 1383 err = OMX_GetState(iOMXDecoder, &sState); 1384 if (err != OMX_ErrorNone) 1385 { 1386 //Error condition report 1387 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 1388 (0, "%s::HandleProcessingState (): PortReconfig Can't get State of decoder - trying to send port flush request!", iName.Str())); 1389 1390 sState = OMX_StateInvalid; 1391 ReportErrorEvent(PVMFErrResourceConfiguration); 1392 ChangeNodeState(EPVMFNodeError); 1393 status = PVMFFailure; 1394 break; 1395 } 1396 1397 if (((sState != OMX_StateExecuting) && (sState != OMX_StatePause)) || iStopCommandWasSentToComponent) 1398 { 1399 1400 // possibly as a consequence of a previously queued cmd to go to Idle state? 1401 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1402 (0, "%s::HandleProcessingState (): PortReconfig: Component State is not executing or paused, do not proceed with port flush", iName.Str())); 1403 1404 1405 } 1406 else 1407 { 1408 1409 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1410 (0, "%s::HandleProcessingState (): PortReconfig Sending Flush command to component", iName.Str())); 1411 1412 1413 // the port will now start returning outstanding buffers 1414 // set the flag to prevent output from going downstream (in case of output port being reconfigd) 1415 // set the flag to prevent input from being saved and returned to component (in case of input port being reconfigd) 1416 // set the state to wait for port saying it is disabled 1417 if (iPortIndexForDynamicReconfig == iOutputPortIndex) 1418 { 1419 iDoNotSendOutputBuffersDownstreamFlag = true; 1420 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1421 (0, "%s::HandleProcessingState() Port Reconfiguration -> Output Port", iName.Str())); 1422 1423 } 1424 else if (iPortIndexForDynamicReconfig == iInputPortIndex) 1425 { 1426 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1427 (0, "%s::HandleProcessingState() Port Reconfiguration -> Input Port", iName.Str())); 1428 1429 iDoNotSaveInputBuffersFlag = true; 1430 } 1431 else 1432 { 1433 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1434 (0, "%s::HandleProcessingState() Port Reconfiguration -> UNKNOWN PORT", iName.Str())); 1435 1436 sState = OMX_StateInvalid; 1437 ReportErrorEvent(PVMFErrResourceConfiguration); 1438 ChangeNodeState(EPVMFNodeError); 1439 status = PVMFFailure; 1440 break; 1441 1442 } 1443 1444 // send command to flush appropriate port 1445 err = OMX_SendCommand(iOMXDecoder, OMX_CommandFlush, iPortIndexForDynamicReconfig, NULL); 1446 if (err != OMX_ErrorNone) 1447 { 1448 //Error condition report 1449 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 1450 (0, "%s::HandleProcessingState (): PortReconfig : Can't send flush command !", iName.Str())); 1451 1452 sState = OMX_StateInvalid; 1453 ReportErrorEvent(PVMFErrResourceConfiguration); 1454 ChangeNodeState(EPVMFNodeError); 1455 status = PVMFFailure; 1456 break; 1457 } 1458 1459 1460 1461 } 1462 1463 // now sit back and wait for buffers to return 1464 // if there is a pause/stop cmd in the meanwhile, component will process it 1465 // and the node will end up in pause/stop state (so this internal state does not matter) 1466 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_WaitForBufferReturn; 1467 1468 1469 // fall through to the next case to check if all buffers are already back 1470 1471 1472 1473 } 1474 1475 case EPVMFOMXBaseDecNodeProcessingState_WaitForBufferReturn: 1476 { 1477 // as buffers are coming back, Run may be called, wait until all buffers are back, then Free them all 1478 1479 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1480 (0, "%s::HandleProcessingState() Port Reconfiguration -> WaitForBufferReturn ", iName.Str())); 1481 // check if it's output port being reconfigured 1482 if (iPortIndexForDynamicReconfig == iOutputPortIndex) 1483 { 1484 // if all buffers have returned, free them 1485 if (iNumOutstandingOutputBuffers == 0) 1486 { 1487 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1488 (0, "%s::HandleProcessingState() Port Reconfiguration -> all output buffers are back, free them", iName.Str())); 1489 1490 // port reconfiguration is required. Only one port at a time is disabled and then re-enabled after buffer resizing 1491 OMX_SendCommand(iOMXDecoder, OMX_CommandPortDisable, iPortIndexForDynamicReconfig, NULL); 1492 1493 1494 if (false == iOutputBuffersFreed) 1495 { 1496 if (!FreeBuffersFromComponent(iOutBufMemoryPool, // allocator 1497 iOutputAllocSize, // size to allocate from pool (hdr only or hdr+ buffer) 1498 iNumOutputBuffers, // number of buffers 1499 iOutputPortIndex, // port idx 1500 false // this is not input 1501 )) 1502 { 1503 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 1504 (0, "%s::HandleProcessingState() Port Reconfiguration -> Cannot free output buffers ", iName.Str())); 1505 1506 SetState(EPVMFNodeError); 1507 ReportErrorEvent(PVMFErrNoMemory); 1508 return PVMFErrNoMemory; 1509 } 1510 } 1511 // if the callback (that port is disabled) has not arrived yet, wait for it 1512 // if it has arrived, it will set the state to PortReEnable 1513 if (iProcessingState != EPVMFOMXBaseDecNodeProcessingState_PortReEnable) 1514 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_WaitForPortDisable; 1515 1516 status = PVMFSuccess; // allow rescheduling of the node potentially 1517 } 1518 else 1519 status = PVMFPending; // must wait for buffers to come back. No point in automatic rescheduling 1520 // but each buffer will reschedule the node when it comes in 1521 } 1522 else 1523 { 1524 // this is input port 1525 1526 // if all buffers have returned, free them 1527 if (iNumOutstandingInputBuffers == 0) 1528 { 1529 1530 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1531 (0, "%s::HandleProcessingState() Port Reconfiguration -> all input buffers are back, free them", iName.Str())); 1532 1533 // port reconfiguration is required. Only one port at a time is disabled and then re-enabled after buffer resizing 1534 OMX_SendCommand(iOMXDecoder, OMX_CommandPortDisable, iPortIndexForDynamicReconfig, NULL); 1535 1536 if (false == iInputBuffersFreed) 1537 { 1538 if (!FreeBuffersFromComponent(iInBufMemoryPool, // allocator 1539 iInputAllocSize, // size to allocate from pool (hdr only or hdr+ buffer) 1540 iNumInputBuffers, // number of buffers 1541 iInputPortIndex, // port idx 1542 true // this is input 1543 )) 1544 { 1545 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 1546 (0, "%s::HandleProcessingState() Port Reconfiguration -> Cannot free input buffers ", iName.Str())); 1547 1548 SetState(EPVMFNodeError); 1549 ReportErrorEvent(PVMFErrNoMemory); 1550 return PVMFErrNoMemory; 1551 1552 } 1553 } 1554 // if the callback (that port is disabled) has not arrived yet, wait for it 1555 // if it has arrived, it will set the state to PortReEnable 1556 if (iProcessingState != EPVMFOMXBaseDecNodeProcessingState_PortReEnable) 1557 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_WaitForPortDisable; 1558 1559 status = PVMFSuccess; // allow rescheduling of the node 1560 } 1561 else 1562 status = PVMFPending; // must wait for buffers to come back. No point in automatic 1563 // rescheduling. Each buffer will reschedule the node 1564 // when it comes in 1565 } 1566 1567 1568 // the state will be changed to PortReEnable once we get confirmation that Port was actually disabled 1569 break; 1570 } 1571 #endif //QCOM WORKAROUND JJDBG 1572 1573 case EPVMFOMXBaseDecNodeProcessingState_WaitForPortDisable: 1574 { 1575 1576 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1577 (0, "%s::HandleProcessingState() Port Reconfiguration -> wait for port disable callback", iName.Str())); 1578 // do nothing. Just wait for the port to become disabled (we'll get event from component, which will 1579 // transition the state to PortReEnable 1580 status = PVMFPending; // prevent Rescheduling the node 1581 break; 1582 } 1583 1584 case EPVMFOMXBaseDecNodeProcessingState_PortReEnable: 1585 { 1586 1587 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1588 (0, "%s::HandleProcessingState() Port Reconfiguration -> Sending reenable port command", iName.Str())); 1589 1590 status = HandlePortReEnable(); 1591 break; 1592 } 1593 1594 case EPVMFOMXBaseDecNodeProcessingState_WaitForPortEnable: 1595 { 1596 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1597 (0, "%s::HandleProcessingState() Port Reconfiguration -> wait for port enable callback", iName.Str())); 1598 // do nothing. Just wait for the port to become enabled (we'll get event from component, which will 1599 // transition the state to ReadyToDecode 1600 status = PVMFPending; // prevent ReScheduling 1601 break; 1602 } 1603 1604 // NORMAL DATA FLOW STATE: 1605 case EPVMFOMXBaseDecNodeProcessingState_ReadyToDecode: 1606 { 1607 1608 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1609 (0, "%s::HandleProcessingState() Ready To Decode start", iName.Str())); 1610 // In normal data flow and decoding state 1611 // Send all available output buffers to the decoder 1612 1613 while (iNumOutstandingOutputBuffers < iNumOutputBuffers) 1614 { 1615 // grab buffer header from the mempool if possible, and send to component 1616 if (!SendOutputBufferToOMXComponent()) 1617 1618 break; 1619 1620 } 1621 1622 1623 // next, see if partially consumed input buffer needs to be resent back to OMX component 1624 // NOTE: it is not allowed that the component returns more than 1 partially consumed input buffers 1625 // i.e. if a partially consumed input buffer is returned, it is assumed that the OMX component 1626 // will be waiting to get data 1627 1628 if (iInputBufferToResendToComponent != NULL) 1629 { 1630 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 1631 (0, "%s::HandleProcessingState() Sending previous - partially consumed input back to the OMX component", iName.Str())); 1632 1633 OMX_EmptyThisBuffer(iOMXDecoder, iInputBufferToResendToComponent); 1634 iInputBufferToResendToComponent = NULL; // do this only once 1635 } 1636 else if ((iNumOutstandingInputBuffers < iNumInputBuffers) && (iDataIn.GetRep() != NULL)) 1637 { 1638 // try to get an input buffer header 1639 // and send the input data over to the component 1640 SendInputBufferToOMXComponent(); 1641 } 1642 1643 status = PVMFSuccess; 1644 break; 1645 1646 1647 } 1648 case EPVMFOMXBaseDecNodeProcessingState_Stopping: 1649 { 1650 1651 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1652 (0, "%s::HandleProcessingState() Stopping -> wait for Component to move from Executing->Idle", iName.Str())); 1653 1654 1655 status = PVMFPending; // prevent rescheduling 1656 break; 1657 } 1658 1659 case EPVMFOMXBaseDecNodeProcessingState_Pausing: 1660 { 1661 1662 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1663 (0, "%s::HandleProcessingState() Pausing -> wait for Component to move from Executing->Pause", iName.Str())); 1664 1665 1666 status = PVMFPending; // prevent rescheduling 1667 break; 1668 } 1669 1670 1671 case EPVMFOMXBaseDecNodeProcessingState_WaitForOutgoingQueue: 1672 status = PVMFPending; 1673 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::HandleProcessingState() Do nothing since waiting for output port queue to become available", iName.Str())); 1674 break; 1675 1676 default: 1677 break; 1678 } 1679 1680 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::HandleProcessingState() Out", iName.Str())); 1681 1682 return status; 1683 1684 } 1685 ///////////////////////////////////////////////////////////////////////////// 1686 bool PVMFOMXBaseDecNode::SendOutputBufferToOMXComponent() 1687 { 1688 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1689 (0, "%s::SendOutputBufferToOMXComponent() In", iName.Str())); 1690 1691 1692 OutputBufCtrlStruct *output_buf = NULL; 1693 int32 errcode = OsclErrNone; 1694 uint32 ii; 1695 1696 // try to get output buffer header 1697 OSCL_TRY(errcode, output_buf = (OutputBufCtrlStruct *) iOutBufMemoryPool->allocate(iOutputAllocSize)); 1698 1699 if (OsclErrNone != errcode) 1700 { 1701 if (OsclErrNoResources == errcode) 1702 { 1703 1704 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, 1705 PVLOGMSG_DEBUG, (0, "%s::SendOutputBufferToOMXComponent() No more output buffers in the mempool", iName.Str())); 1706 1707 iOutBufMemoryPool->notifyfreechunkavailable(*this, (OsclAny *) iOutBufMemoryPool); // To signal when next deallocate() is called on mempool 1708 1709 return false; 1710 } 1711 else 1712 { 1713 // Memory allocation for the pool failed 1714 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 1715 (0, "%s::SendOutputBufferToOMXComponent() Output mempool error", iName.Str())); 1716 1717 1718 SetState(EPVMFNodeError); 1719 ReportErrorEvent(PVMFErrNoMemory); 1720 return false; 1721 } 1722 1723 } 1724 1725 1726 //for every allocated buffer, make sure you notify when buffer is released. Keep track of allocated buffers 1727 // use mempool as context to recognize which buffer (input or output) was returned 1728 iOutBufMemoryPool->notifyfreechunkavailable(*this, (OsclAny *)iOutBufMemoryPool); 1729 iNumOutstandingOutputBuffers++; 1730 1731 for (ii = 0; ii < iNumOutputBuffers; ii++) 1732 { 1733 if (output_buf == out_ctrl_struct_ptr[ii]) 1734 { 1735 break; 1736 } 1737 } 1738 1739 if (ii == iNumOutputBuffers) 1740 return false; 1741 1742 output_buf->pBufHdr = (OMX_BUFFERHEADERTYPE *)out_buff_hdr_ptr[ii]; 1743 1744 output_buf->pBufHdr->nFilledLen = 0; // make sure you tell OMX component buffer is empty 1745 output_buf->pBufHdr->nOffset = 0; 1746 output_buf->pBufHdr->pAppPrivate = output_buf; // set pAppPrivate to be pointer to output_buf 1747 // (this is context for future release of this buffer to the mempool) 1748 // this was done during buffer creation, but still repeat just in case 1749 1750 output_buf->pBufHdr->nFlags = 0; // zero out the flags 1751 1752 OMX_FillThisBuffer(iOMXDecoder, output_buf->pBufHdr); 1753 1754 1755 1756 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1757 (0, "%s::SendOutputBufferToOMXComponent() Out", iName.Str())); 1758 1759 return true; 1760 } 1761 //////////////////////////////////////////////////////////////////////////////// 1762 bool PVMFOMXBaseDecNode::SetDefaultCapabilityFlags() 1763 { 1764 1765 iIsOMXComponentMultiThreaded = true; 1766 1767 iOMXComponentSupportsExternalOutputBufferAlloc = false; 1768 iOMXComponentSupportsExternalInputBufferAlloc = false; 1769 iOMXComponentSupportsMovableInputBuffers = false; 1770 iOMXComponentUsesNALStartCodes = true; 1771 iOMXComponentSupportsPartialFrames = false; 1772 iOMXComponentCanHandleIncompleteFrames = true; 1773 iOMXComponentUsesFullAVCFrames = false; 1774 1775 return true; 1776 } 1777 1778 1779 1780 bool PVMFOMXBaseDecNode::SendEOSBufferToOMXComponent() 1781 { 1782 1783 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1784 (0, "%s::SendEOSBufferToOMXComponent() In", iName.Str())); 1785 1786 1787 // first of all, check if the component is running. EOS could be sent prior to component/decoder 1788 // even being initialized 1789 1790 // returning false will ensure that the EOS will be sent downstream anyway without waiting for the 1791 // Component to respond 1792 if (iCurrentDecoderState != OMX_StateExecuting) 1793 return false; 1794 1795 // get an input buffer. Without a buffer, no point in proceeding 1796 InputBufCtrlStruct *input_buf = NULL; 1797 int32 errcode = OsclErrNone; 1798 1799 // we already checked that the number of buffers is OK, so we don't expect problems 1800 // try to get input buffer header 1801 OSCL_TRY(errcode, input_buf = (InputBufCtrlStruct *) iInBufMemoryPool->allocate(iInputAllocSize)); 1802 if (OsclErrNone != errcode) 1803 { 1804 if (OsclErrNoResources == errcode) 1805 { 1806 1807 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, 1808 PVLOGMSG_DEBUG, (0, "%s::SendEOSBufferToOMXComponent() No more buffers in the mempool - unexpected", iName.Str())); 1809 1810 iInBufMemoryPool->notifyfreechunkavailable(*this, (OsclAny*) iInBufMemoryPool); // To signal when next deallocate() is called on mempool 1811 1812 return false; 1813 } 1814 else 1815 { 1816 // Memory allocation for the pool failed 1817 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 1818 (0, "%s::SendEOSBufferToOMXComponent() Input mempool error", iName.Str())); 1819 1820 1821 SetState(EPVMFNodeError); 1822 ReportErrorEvent(PVMFErrNoMemory); 1823 return false; 1824 } 1825 1826 } 1827 1828 // keep track of buffers. When buffer is deallocated/released, the counter will be decremented 1829 iInBufMemoryPool->notifyfreechunkavailable(*this, (OsclAny*) iInBufMemoryPool); 1830 iNumOutstandingInputBuffers++; 1831 1832 // in this case, no need to use input msg refcounter. Make sure its unbound 1833 (input_buf->pMediaData).Unbind(); 1834 1835 // THIS IS AN EMPTY BUFFER. FLAGS ARE THE ONLY IMPORTANT THING 1836 input_buf->pBufHdr->nFilledLen = 0; 1837 input_buf->pBufHdr->nOffset = 0; 1838 1839 iInputTimestampClock.update_clock(iEndOfDataTimestamp); // this will also take into consideration the rollover 1840 // convert TS in input timescale into OMX_TICKS 1841 iOMXTicksTimestamp = ConvertTimestampIntoOMXTicks(iInputTimestampClock); 1842 input_buf->pBufHdr->nTimeStamp = iOMXTicksTimestamp; 1843 1844 // set ptr to input_buf structure for Context (for when the buffer is returned) 1845 input_buf->pBufHdr->pAppPrivate = (OMX_PTR) input_buf; 1846 1847 // do not use Mark here (but init to NULL to prevent problems) 1848 input_buf->pBufHdr->hMarkTargetComponent = NULL; 1849 input_buf->pBufHdr->pMarkData = NULL; 1850 1851 1852 // init buffer flags 1853 input_buf->pBufHdr->nFlags = 0; 1854 1855 input_buf->pBufHdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; 1856 // most importantly, set the EOS flag: 1857 input_buf->pBufHdr->nFlags |= OMX_BUFFERFLAG_EOS; 1858 1859 // send buffer to component 1860 OMX_EmptyThisBuffer(iOMXDecoder, input_buf->pBufHdr); 1861 1862 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1863 (0, "%s::SendEOSBufferToOMXComponent() Out", iName.Str())); 1864 1865 return true; 1866 1867 } 1868 1869 // this method is called under certain conditions only if the node is doing partial frame assembly 1870 OSCL_EXPORT_REF void PVMFOMXBaseDecNode::DropCurrentBufferUnderConstruction() 1871 { 1872 if (iObtainNewInputBuffer == false) 1873 { 1874 if (iInputBufferUnderConstruction != NULL) 1875 { 1876 if (iInBufMemoryPool != NULL) 1877 { 1878 iInBufMemoryPool->deallocate((OsclAny *)iInputBufferUnderConstruction); 1879 } 1880 1881 iInputBufferUnderConstruction = NULL; 1882 } 1883 iObtainNewInputBuffer = true; 1884 1885 } 1886 } 1887 1888 // this method is called under certain conditions only if the node is doing partial frame assembly 1889 OSCL_EXPORT_REF void PVMFOMXBaseDecNode::SendIncompleteBufferUnderConstruction() 1890 { 1891 1892 // this should never be the case, but check anyway 1893 if (iInputBufferUnderConstruction != NULL) 1894 { 1895 // mark as end of frame (the actual end piece is missing) 1896 iInputBufferUnderConstruction->pBufHdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; 1897 1898 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1899 (0, "%s::SendIncompleteBufferUnderConstruction() - Sending Incomplete Buffer 0x%x to OMX Component MARKER field set to %x, TS=%d, Ticks=%L", iName.Str(), iInputBufferUnderConstruction->pBufHdr->pBuffer, iInputBufferUnderConstruction->pBufHdr->nFlags, iInTimestamp, iOMXTicksTimestamp)); 1900 1901 OMX_EmptyThisBuffer(iOMXDecoder, iInputBufferUnderConstruction->pBufHdr); 1902 1903 1904 iInputBufferUnderConstruction = NULL; 1905 iObtainNewInputBuffer = true; 1906 1907 } 1908 } 1909 1910 OSCL_EXPORT_REF bool PVMFOMXBaseDecNode::SendInputBufferToOMXComponent() 1911 { 1912 1913 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1914 (0, "%s::SendInputBufferToOMXComponent() In", iName.Str())); 1915 1916 1917 // first need to take care of missing packets if node is assembling partial frames. 1918 // The action depends whether the component (I) can handle incomplete frames/NALs or (II) cannot handle incomplete frames/NALs 1919 if (!iOMXComponentSupportsPartialFrames) 1920 { 1921 1922 // there are 4 cases after receiving a media msg and realizing there were missing packet(s): 1923 1924 // a) TS remains the same - i.e. missing 1 or more pieces in the middle of the same frame 1925 // I) basically ignore - keep assembling the same frame (middle will be missing) 1926 // II) drop current buffer, drop msgs until next msg with marker bit arrives 1927 1928 1929 // b) TS is different than previous frame. Previous frame was sent OK (had marker bit). 1930 // New frame assembly has not started yet. one or more pieces are missing from 1931 // the beginning of the frame 1932 // I) basically ignore - get a new buffer and start assembling new frame (beginning will be missing) 1933 // II) no buffer to drop, but keep dropping msgs until next msg with marker bit arrives 1934 1935 // c) TS is different than previous frame. Frame assembly has started (we were in the middle of a frame) 1936 // but only 1 piece is missing => We know that the missing frame must have had the marker bit 1937 1938 // I) send out current buffer (last piece will be missing), get a new buffer and start assembling new frame (which is OK) 1939 // II) just drop current buffer. Get a new buffer and start assembling new frame (no need to wait for marker bit) 1940 1941 // d) TS is different than previous frame. Frame assembly has started ( we were in the middle of a frame) 1942 // multiple pieces are missing => The last piece of the frame with the marker bit is missing for sure, but 1943 // there could be also other frames missing or the beginning of the next frame is missing etc. 1944 1945 // I) send out current bufer (last piece will be missing). Get a new buffer and start assembling new frame (beginning COULD BE missing as well) 1946 // II) drop current buffer. Keep dropping msgs until next msg with marker bit arrives 1947 1948 1949 // extract info from the media message 1950 1951 uint32 current_msg_seq_num = iDataIn->getSeqNum(); 1952 uint32 current_msg_ts = iDataIn->getTimestamp(); 1953 uint32 current_msg_marker; 1954 if (iSetMarkerBitForEveryFrag == true) // PV AVC case 1955 { 1956 current_msg_marker = iDataIn->getMarkerInfo() & PVMF_MEDIA_DATA_MARKER_INFO_END_OF_NAL_BIT; 1957 current_msg_marker |= iDataIn->getMarkerInfo() & PVMF_MEDIA_DATA_MARKER_INFO_M_BIT; 1958 } 1959 else 1960 { 1961 current_msg_marker = iDataIn->getMarkerInfo() & PVMF_MEDIA_DATA_MARKER_INFO_M_BIT; 1962 } 1963 1964 //Force marker bit for AMR streaming formats (marker bit may not be set even though full frames are present) 1965 if (iInPort && ( 1966 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR) || 1967 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMRWB) 1968 )) 1969 { 1970 // FIXME: This could have unintended side effects if other bits in this value are used in the future 1971 current_msg_marker = PVMF_MEDIA_DATA_MARKER_INFO_M_BIT; 1972 } 1973 1974 // check if this is the very first data msg 1975 if (iFirstDataMsgAfterBOS) 1976 { 1977 iFirstDataMsgAfterBOS = false; 1978 //init the sequence number & ts to make sure dropping logic does not kick in 1979 iInPacketSeqNum = current_msg_seq_num - 1; 1980 iInTimestamp = current_msg_ts - 10; 1981 } 1982 1983 1984 // first check if we need to keep dropping msgs 1985 if (iKeepDroppingMsgsUntilMarkerBit) 1986 { 1987 // drop this message 1988 iDataIn.Unbind(); 1989 1990 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1991 (0, "%s::SendInputBufferToOMXComponent() Dropping input msg with seqnum %d until marker bit", iName.Str(), current_msg_seq_num)); 1992 1993 //if msg has marker bit, stop dropping msgs 1994 if ((current_msg_marker != 0 && !iOMXComponentUsesFullAVCFrames) || // frame or NAL boundaries 1995 ((current_msg_marker & PVMF_MEDIA_DATA_MARKER_INFO_M_BIT) && iOMXComponentUsesFullAVCFrames)) // only frame boundaries 1996 { 1997 iKeepDroppingMsgsUntilMarkerBit = false; 1998 // also remember the sequence number & timestamp so that we have reference 1999 iInPacketSeqNum = current_msg_seq_num; 2000 iInTimestamp = current_msg_ts; 2001 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2002 (0, "%s::SendInputBufferToOMXComponent() Input msg with seqnum %d has marker bit set. Stop dropping msgs", iName.Str(), current_msg_seq_num)); 2003 2004 } 2005 return true; 2006 } 2007 2008 // is there something missing? 2009 // compare current and saved sequence number - difference should be exactly 1 2010 // if it is more, there is something missing 2011 if ((current_msg_seq_num - iInPacketSeqNum) > 1) 2012 { 2013 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2014 (0, "%s::SendInputBufferToOMXComponent() - MISSING PACKET DETECTED. Input msg with seqnum %d, TS=%d. Previous seqnum: %d, Previous TS: %d", iName.Str(), current_msg_seq_num, iInPacketSeqNum, current_msg_ts, iInTimestamp)); 2015 2016 // find out which case it is by comparing TS 2017 if (current_msg_ts == iInTimestamp) 2018 { 2019 2020 // this is CASE a) 2021 // same ts, i.e. pieces are missing from the middle of the current frame 2022 if (!iOMXComponentCanHandleIncompleteFrames) 2023 { 2024 // drop current buffer, drop msgs until you hit msg with marker bit 2025 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2026 (0, "%s::SendInputBufferToOMXComponent() - Drop current buffer under construction. Keep dropping msgs until marker bit", iName.Str())); 2027 2028 DropCurrentBufferUnderConstruction(); 2029 iKeepDroppingMsgsUntilMarkerBit = true; 2030 } 2031 else 2032 { 2033 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2034 (0, "%s::SendInputBufferToOMXComponent() - Continue processing", iName.Str())); 2035 2036 } 2037 } 2038 else // new ts and old ts are different 2039 { 2040 // are we at the beginning of the new frame assembly? 2041 if (iObtainNewInputBuffer) 2042 { 2043 // CASE b) 2044 // i.e. we sent out previous frame, but have not started assembling a new frame. Pieces are missing from the beginning 2045 if (!iOMXComponentCanHandleIncompleteFrames) 2046 { 2047 // there is no current buffer to drop, but drop msgs until you hit msg with marker bit 2048 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2049 (0, "%s::SendInputBufferToOMXComponent() - No current buffer under construction. Keep dropping msgs until marker bit", iName.Str())); 2050 2051 iKeepDroppingMsgsUntilMarkerBit = true; 2052 } 2053 else 2054 { 2055 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2056 (0, "%s::SendInputBufferToOMXComponent() - Continue processing", iName.Str())); 2057 } 2058 } 2059 else // no, we are in the middle of a frame assembly, but new ts is different 2060 { 2061 // is only 1 msg missing? 2062 if ((current_msg_seq_num - iInPacketSeqNum) == 2) 2063 { 2064 // CASE c) 2065 // only the last piece of the previous frame is missing 2066 if (iOMXComponentCanHandleIncompleteFrames) 2067 { 2068 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2069 (0, "%s::SendInputBufferToOMXComponent() - Send incomplete buffer under construction. Start assembling new frame", iName.Str())); 2070 2071 SendIncompleteBufferUnderConstruction(); 2072 } 2073 else 2074 { 2075 // drop current frame only, but no need to wait until next marker bit. 2076 // start assembling new frame 2077 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2078 (0, "%s::SendInputBufferToOMXComponent() - Drop current buffer under construction. It's OK to start assembling new frame. Only 1 packet is missing", iName.Str())); 2079 2080 DropCurrentBufferUnderConstruction(); 2081 } 2082 } 2083 else 2084 { 2085 // CASE d) 2086 // (multiple) final piece(s) of the previous frame are missing and possibly pieces at the 2087 // beginning of a new frame are also missing 2088 if (iOMXComponentCanHandleIncompleteFrames) 2089 { 2090 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2091 (0, "%s::SendInputBufferToOMXComponent() - Send incomplete buffer under construction. Start assembling new frame (potentially damaged)", iName.Str())); 2092 2093 SendIncompleteBufferUnderConstruction(); 2094 } 2095 else 2096 { 2097 // drop current frame. start assembling new frame, but first keep dropping 2098 // until you hit msg with marker bit. 2099 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2100 (0, "%s::SendInputBufferToOMXComponent() - Drop current buffer under construction. Keep dropping msgs until marker bit", iName.Str())); 2101 2102 DropCurrentBufferUnderConstruction(); 2103 iKeepDroppingMsgsUntilMarkerBit = true; 2104 } 2105 } 2106 }// end of if(obtainNewInputBuffer)/else 2107 }// end of if(curr_msg_ts == iInTimestamp) 2108 }//end of if(deltaseqnum>1)/else 2109 2110 // check if we need to keep dropping msgs 2111 if (iKeepDroppingMsgsUntilMarkerBit) 2112 { 2113 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2114 (0, "%s::SendInputBufferToOMXComponent() Dropping input msg with seqnum %d until marker bit", iName.Str(), current_msg_seq_num)); 2115 2116 // drop this message 2117 iDataIn.Unbind(); 2118 2119 //if msg has marker bit, stop dropping msgs 2120 if ((current_msg_marker != 0 && !iOMXComponentUsesFullAVCFrames) || // frame or NAL boundaries 2121 ((current_msg_marker & PVMF_MEDIA_DATA_MARKER_INFO_M_BIT) && iOMXComponentUsesFullAVCFrames)) // only frame boundaries 2122 { 2123 iKeepDroppingMsgsUntilMarkerBit = false; 2124 // also remember the sequence number & timestamp so that we have reference 2125 iInPacketSeqNum = current_msg_seq_num; 2126 iInTimestamp = current_msg_ts; 2127 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2128 (0, "%s::SendInputBufferToOMXComponent() Input msg with seqnum %d has marker bit set. Stop dropping msgs", iName.Str(), current_msg_seq_num)); 2129 2130 } 2131 return true; 2132 } 2133 2134 }// end of if/else (iOMXSUpportsPartialFrames) 2135 2136 InputBufCtrlStruct *input_buf = NULL; 2137 int32 errcode = OsclErrNone; 2138 uint32 ii; 2139 2140 // NOTE: a) if NAL start codes must be inserted i.e. iOMXComponentUsesNALStartCodess is TRUE, then iOMXComponentSupportsMovableInputBuffers must be set to FALSE. 2141 // b) if iOMXComponentSupportsPartialFrames is FALSE, then iOMXComponentSupportsMovableInputBuffers must be FALSE as well 2142 // c) if iOMXCOmponentSupportsPartialFrames is FALSE, and the input frame/NAL size is larger than the buffer size, the frame/NAL is discarded 2143 2144 do 2145 { 2146 // do loop to loop over all fragments 2147 // first of all , get an input buffer. Without a buffer, no point in proceeding 2148 if (iObtainNewInputBuffer == true) // if partial frames are being reconstructed, we may be copying data into 2149 //existing buffer, so we don't need the new buffer 2150 { 2151 // try to get input buffer header 2152 OsclAny* temp; 2153 errcode = AllocateChunkFromMemPool(temp, iInBufMemoryPool, iInputAllocSize); 2154 input_buf = (InputBufCtrlStruct*) temp; 2155 if (OsclErrNone != errcode) 2156 { 2157 if (OsclErrNoResources == errcode) 2158 { 2159 2160 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, 2161 PVLOGMSG_DEBUG, (0, "%s::SendInputBufferToOMXComponent() No more buffers in the mempool", iName.Str())); 2162 2163 iInBufMemoryPool->notifyfreechunkavailable(*this, (OsclAny*) iInBufMemoryPool); // To signal when next deallocate() is called on mempool 2164 2165 return false; 2166 } 2167 else 2168 { 2169 // Memory allocation for the pool failed 2170 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 2171 (0, "%s::SendInputBufferToOMXComponent() Input mempool error", iName.Str())); 2172 2173 2174 SetState(EPVMFNodeError); 2175 ReportErrorEvent(PVMFErrNoMemory); 2176 return false; 2177 } 2178 2179 } 2180 2181 // keep track of buffers. When buffer is deallocated/released, the counter will be decremented 2182 iInBufMemoryPool->notifyfreechunkavailable(*this, (OsclAny*) iInBufMemoryPool); 2183 iNumOutstandingInputBuffers++; 2184 2185 for (ii = 0; ii < iNumInputBuffers; ii++) 2186 { 2187 if (input_buf == in_ctrl_struct_ptr[ii]) 2188 { 2189 break; 2190 } 2191 } 2192 2193 if (ii == iNumInputBuffers) 2194 return false; 2195 2196 input_buf->pBufHdr = (OMX_BUFFERHEADERTYPE *)in_buff_hdr_ptr[ii]; 2197 2198 // Now we have the buffer header (i.e. a buffer) to send to component: 2199 // Depending on OMX component capabilities, either pass the input msg fragment(s) directly 2200 // into OMX component without copying (and update the input msg refcount) 2201 // or memcopy the content of input msg memfrag(s) into OMX component allocated buffers 2202 input_buf->pBufHdr->nFilledLen = 0; // init this for now 2203 // save this in a class member 2204 iInputBufferUnderConstruction = input_buf; 2205 // set flags 2206 if (iOMXComponentSupportsPartialFrames == true) 2207 { 2208 // if partial frames can be sent, then send them 2209 // but we'll always need the new buffer for the new fragment 2210 iObtainNewInputBuffer = true; 2211 } 2212 else 2213 { 2214 // if we need to assemble partial frames, then obtain a new buffer 2215 // only after assembling the partial frame 2216 iObtainNewInputBuffer = false; 2217 } 2218 2219 if (iOMXComponentUsesFullAVCFrames) 2220 { 2221 // reset NAL counters 2222 oscl_memset(iNALSizeArray, 0, sizeof(uint32) * iNALCount); 2223 iNALCount = 0; 2224 } 2225 2226 iIncompleteFrame = false; 2227 iFirstPieceOfPartialFrame = true; 2228 } 2229 else 2230 { 2231 input_buf = iInputBufferUnderConstruction; 2232 } 2233 2234 // When copying content, a special case is when the input fragment is larger than the buffer and has to 2235 // be fragmented here and broken over 2 or more buffers. Potential problem with available buffers etc. 2236 2237 // if this is the first fragment in a new message, extract some info: 2238 if (iCurrFragNum == 0) 2239 { 2240 2241 // NOTE: SeqNum differ in Codec and in Node because of the fact that 2242 // one msg can contain multiple fragments that are sent to the codec as 2243 // separate buffers. Node tracks msgs and codec tracks even separate fragments 2244 2245 iCodecSeqNum += (iDataIn->getSeqNum() - iInPacketSeqNum); // increment the codec seq. # by the same 2246 // amount that the input seq. number increased 2247 2248 iInPacketSeqNum = iDataIn->getSeqNum(); // remember input sequence number 2249 iInTimestamp = iDataIn->getTimestamp(); 2250 iInDuration = iDataIn->getDuration(); 2251 iInNumFrags = iDataIn->getNumFragments(); 2252 2253 if (iSetMarkerBitForEveryFrag == true) // PV AVC case 2254 { 2255 iCurrentMsgMarkerBit = iDataIn->getMarkerInfo() & PVMF_MEDIA_DATA_MARKER_INFO_END_OF_NAL_BIT; 2256 iCurrentMsgMarkerBit |= iDataIn->getMarkerInfo() & PVMF_MEDIA_DATA_MARKER_INFO_M_BIT; 2257 } 2258 else 2259 { 2260 iCurrentMsgMarkerBit = iDataIn->getMarkerInfo() & PVMF_MEDIA_DATA_MARKER_INFO_M_BIT; 2261 } 2262 2263 //Force marker bit for AMR streaming formats (marker bit may not be set even though full frames are present) 2264 if (iInPort && ( 2265 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR) || 2266 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMRWB) 2267 )) 2268 { 2269 iCurrentMsgMarkerBit = PVMF_MEDIA_DATA_MARKER_INFO_M_BIT; 2270 } 2271 2272 2273 // logging info: 2274 if (iDataIn->getNumFragments() > 1) 2275 { 2276 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2277 (0, "%s::SendInputBufferToOMXComponent() - New msg has MULTI-FRAGMENTS", iName.Str())); 2278 } 2279 2280 if (!(iDataIn->getMarkerInfo() & PVMF_MEDIA_DATA_MARKER_INFO_M_BIT) && !(iDataIn->getMarkerInfo() & PVMF_MEDIA_DATA_MARKER_INFO_END_OF_NAL_BIT)) 2281 { 2282 2283 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2284 (0, "%s::SendInputBufferToOMXComponent() - New msg has NO MARKER BIT", iName.Str())); 2285 } 2286 } 2287 2288 2289 // get a memfrag from the message 2290 OsclRefCounterMemFrag frag; 2291 iDataIn->getMediaFragment(iCurrFragNum, frag); 2292 2293 2294 if (iOMXComponentSupportsMovableInputBuffers) 2295 { 2296 // no copying required 2297 2298 // increment the RefCounter of the message associated with the mem fragment/buffer 2299 // when sending this buffer to OMX component. (When getting the buffer back, the refcounter 2300 // will be decremented. Thus, when the last fragment is returned, the input mssage is finally released 2301 2302 iDataIn.GetRefCounter()->addRef(); 2303 2304 // associate the buffer ctrl structure with the message ref counter and ptr 2305 input_buf->pMediaData = PVMFSharedMediaDataPtr(iDataIn.GetRep(), iDataIn.GetRefCounter()); 2306 2307 2308 // set pointer to the data, length, offset 2309 input_buf->pBufHdr->pBuffer = (uint8 *)frag.getMemFragPtr(); 2310 input_buf->pBufHdr->nFilledLen = frag.getMemFragSize(); 2311 2312 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2313 (0, "%s::SendInputBufferToOMXComponent() - Buffer 0x%x of size %d, %d frag out of tot. %d, TS=%d", iName.Str(), input_buf->pBufHdr->pBuffer, frag.getMemFragSize(), iCurrFragNum + 1, iDataIn->getNumFragments(), iInTimestamp)); 2314 2315 iCurrFragNum++; // increment fragment number and move on to the next 2316 iIsNewDataFragment = true; // update the flag 2317 2318 } 2319 else 2320 { 2321 2322 // in this case, no need to use input msg refcounter, each buffer fragment is copied over and treated separately 2323 (input_buf->pMediaData).Unbind(); 2324 2325 if (iOMXComponentUsesNALStartCodes == true && iFirstPieceOfPartialFrame == true) 2326 { 2327 oscl_memcpy(input_buf->pBufHdr->pBuffer + input_buf->pBufHdr->nFilledLen, 2328 (void *) NAL_START_CODE, 2329 NAL_START_CODE_SIZE); 2330 input_buf->pBufHdr->nFilledLen += NAL_START_CODE_SIZE; 2331 iFirstPieceOfPartialFrame = false; 2332 2333 } 2334 2335 // is this a new data fragment or are we still working on separating the old one? 2336 if (iIsNewDataFragment == true) 2337 { 2338 // if fragment size is larger than the buffer size, 2339 // need to break up the fragment even further into smaller chunks 2340 2341 // init variables needed for fragment separation 2342 iCopyPosition = 0; 2343 iFragmentSizeRemainingToCopy = frag.getMemFragSize(); 2344 2345 } 2346 2347 // can the remaining fragment fit into the buffer? 2348 uint32 bytes_remaining_in_buffer; 2349 2350 if (iOMXComponentUsesFullAVCFrames && !iOMXComponentUsesNALStartCodes) 2351 { 2352 // need to keep to account the extra data appended at the end of the buffer 2353 int32 temp = (input_buf->pBufHdr->nAllocLen - input_buf->pBufHdr->nFilledLen - (20 + 4 * (iNALCount + 1) + 20 + 6));//(sizeOfExtraDataStruct_NAL + sizeOfExTraData + sizeOfExtraDataStruct_terminator + padding); 2354 bytes_remaining_in_buffer = (uint32)((temp < 0) ? 0 : temp); 2355 } 2356 else 2357 { 2358 bytes_remaining_in_buffer = (input_buf->pBufHdr->nAllocLen - input_buf->pBufHdr->nFilledLen); 2359 } 2360 2361 if (iFragmentSizeRemainingToCopy <= bytes_remaining_in_buffer) 2362 { 2363 2364 oscl_memcpy(input_buf->pBufHdr->pBuffer + input_buf->pBufHdr->nFilledLen, 2365 (void *)((uint8 *)frag.getMemFragPtr() + iCopyPosition), 2366 iFragmentSizeRemainingToCopy); 2367 2368 input_buf->pBufHdr->nFilledLen += iFragmentSizeRemainingToCopy; 2369 2370 if (iOMXComponentUsesFullAVCFrames) 2371 { 2372 iNALSizeArray[iNALCount] += iFragmentSizeRemainingToCopy; 2373 2374 if ((iCurrentMsgMarkerBit & PVMF_MEDIA_DATA_MARKER_INFO_END_OF_NAL_BIT) && 2375 (1 == iDataIn->getNumFragments())) 2376 { 2377 // streaming case (and 1 nal per frame file format case) 2378 iNALCount++; 2379 // we have a full NAL now, so insert a start code (if it needs it) for the next NAL, the next time through the loop 2380 iFirstPieceOfPartialFrame = true; 2381 } 2382 else if (iDataIn->getNumFragments() > 1) 2383 { 2384 // multiple nals per frame file format case 2385 iNALCount = iCurrFragNum + 1; 2386 // we have a full NAL now, so insert a start code for the next NAL, the next time through the loop 2387 iFirstPieceOfPartialFrame = true; 2388 } 2389 } 2390 2391 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2392 (0, "%s::SendInputBufferToOMXComponent() - Copied %d bytes of fragment %d out of %d into buffer 0x%x of size %d, TS=%d ", iName.Str(), iFragmentSizeRemainingToCopy, iCurrFragNum + 1, iDataIn->getNumFragments(), input_buf->pBufHdr->pBuffer, input_buf->pBufHdr->nFilledLen, iInTimestamp)); 2393 2394 iCopyPosition += iFragmentSizeRemainingToCopy; 2395 iFragmentSizeRemainingToCopy = 0; 2396 2397 iIsNewDataFragment = true; // done with this fragment. Get a new one 2398 iCurrFragNum++; 2399 2400 } 2401 else 2402 { 2403 // copy as much as you can of the current fragment into the current buffer 2404 if (bytes_remaining_in_buffer > 0) 2405 { 2406 oscl_memcpy(input_buf->pBufHdr->pBuffer + input_buf->pBufHdr->nFilledLen, 2407 (void *)((uint8 *)frag.getMemFragPtr() + iCopyPosition), 2408 bytes_remaining_in_buffer); 2409 2410 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2411 (0, "%s::SendInputBufferToOMXComponent() - Copied %d bytes of fragment %d out of %d into buffer 0x%x of size %d, TS=%d", iName.Str(), bytes_remaining_in_buffer, iCurrFragNum + 1, iDataIn->getNumFragments(), input_buf->pBufHdr->pBuffer, input_buf->pBufHdr->nFilledLen, iInTimestamp)); 2412 } 2413 2414 input_buf->pBufHdr->nFilledLen += bytes_remaining_in_buffer; 2415 2416 if (iOMXComponentUsesFullAVCFrames && (bytes_remaining_in_buffer > 0)) 2417 { 2418 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2419 (0, "%s::SendInputBufferToOMXComponent() - Reconstructing partial frame (iOMXComponentUsesFullAVCFrames) - more data cannot fit in buffer 0x%x, TS=%d.Skipping data.", iName.Str(), input_buf->pBufHdr->pBuffer, iInTimestamp)); 2420 2421 iNALSizeArray[iNALCount] += bytes_remaining_in_buffer; 2422 2423 // increment NAL count regardless if market bit is present or not since it is a fragment 2424 iNALCount++; 2425 } 2426 2427 iCopyPosition += bytes_remaining_in_buffer; // move current position within fragment forward 2428 iFragmentSizeRemainingToCopy -= bytes_remaining_in_buffer; 2429 iIncompleteFrame = true; 2430 iIsNewDataFragment = false; // set the flag to indicate we're still working on the "old" fragment 2431 if (!iOMXComponentSupportsPartialFrames) 2432 { 2433 // if partial frames are not supported, and data cannot fit into the buffer, i.e. the buffer is full at this point 2434 // simply go through remaining fragments if they exist and "drop" them 2435 // i.e. send what data is alrady copied in the buffer and ingore the rest 2436 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2437 (0, "%s::SendInputBufferToOMXComponent() - Reconstructing partial frame - more data cannot fit in buffer 0x%x, TS=%d.Skipping data.", iName.Str(), input_buf->pBufHdr->pBuffer, iInTimestamp)); 2438 2439 iIsNewDataFragment = true; // done with this fragment, get a new one 2440 iCurrFragNum++; 2441 } 2442 } 2443 2444 } 2445 2446 2447 // set buffer fields (this is the same regardless of whether the input is movable or not 2448 input_buf->pBufHdr->nOffset = 0; 2449 2450 iInputTimestampClock.update_clock(iInTimestamp); // this will also take into consideration the timestamp rollover 2451 2452 // convert TS in input timescale into OMX_TICKS 2453 iOMXTicksTimestamp = ConvertTimestampIntoOMXTicks(iInputTimestampClock); 2454 2455 input_buf->pBufHdr->nTimeStamp = iOMXTicksTimestamp; 2456 2457 2458 2459 // set ptr to input_buf structure for Context (for when the buffer is returned) 2460 input_buf->pBufHdr->pAppPrivate = (OMX_PTR) input_buf; 2461 2462 // do not use Mark here (but init to NULL to prevent problems) 2463 input_buf->pBufHdr->hMarkTargetComponent = NULL; 2464 input_buf->pBufHdr->pMarkData = NULL; 2465 2466 2467 // init buffer flags 2468 input_buf->pBufHdr->nFlags = 0; 2469 2470 // set marker bit on or off 2471 // Audio: 2472 // a) AAC - file playback - each fragment is a complete frame (1 msg may contain multiple fragments/frames) 2473 // AAC - streaming - 1 msg may contain a partial frame, but LATM parser will assemble a full frame 2474 // (when LATM parser is done, we attach a marker bit to the data it produces) 2475 2476 // b) AMR - file playback - each msg is N whole frames (marker bit is always set) 2477 // AMR - streaming - each msg is N whole frames (marker bit is missing from incoming msgs -set it here) 2478 2479 // c) MP3 - file playback - 1 msg is N whole frames 2480 // 2481 // Video: 2482 // a) AVC - file playback - each fragment is a complete NAL (1 or more frags i.e. NALs per msg) 2483 // AVC - streaming - 1 msg contains 1 full NAL or a portion of a NAL 2484 // NAL may be broken up over multiple msgs. Frags are not allowed in streaming 2485 // b) M4V - file playback - each msg is 1 frame 2486 // M4V - streaming - 1 frame may be broken up into multiple messages and fragments 2487 2488 // c) WMV - file playback - 1 frame is 1 msg 2489 // WMV - streaming - 1 frame may be broken up into multiple messages and fragments 2490 2491 2492 if (iSetMarkerBitForEveryFrag == true) 2493 { 2494 2495 2496 if (iIsNewDataFragment) 2497 { 2498 if ((iDataIn->getNumFragments() > 1)) 2499 { 2500 // if more than 1 fragment in the message and we have not broken it up 2501 //(i.e. this is the last piece of a broken up piece), put marker bit on it unconditionally 2502 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2503 (0, "%s::SendInputBufferToOMXComponent() - END OF FRAGMENT - Multifragmented msg AVC case, Buffer 0x%x MARKER bit set to 1", iName.Str(), input_buf->pBufHdr->pBuffer)); 2504 2505 if (!iOMXComponentUsesFullAVCFrames) 2506 { 2507 // NAL mode, (uses OMX_BUFFERFLAG_ENDOFFRAME flag to mark end of NAL instead of end of frame) 2508 // once NAL is complete, make sure you send it and obtain new buffer 2509 input_buf->pBufHdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; 2510 iObtainNewInputBuffer = true; 2511 } 2512 else if (iCurrentMsgMarkerBit & PVMF_MEDIA_DATA_MARKER_INFO_M_BIT) 2513 { 2514 // frame mode (send out full AVC frames) 2515 if (iCurrFragNum == iDataIn->getNumFragments()) 2516 { 2517 input_buf->pBufHdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; 2518 iObtainNewInputBuffer = true; 2519 } 2520 } 2521 } 2522 else if ((iDataIn->getNumFragments() == 1)) 2523 { 2524 // this is (the last piece of broken up by us) single-fragmented message. This can be a piece of a NAL (streaming) or a full NAL (file ) 2525 // apply marker bit if the message carries one 2526 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2527 (0, "%s::SendInputBufferToOMXComponent() - END OF FRAGMENT - Buffer 0x%x MARKER bit set to %d", iName.Str(), input_buf->pBufHdr->pBuffer, iCurrentMsgMarkerBit)); 2528 2529 // if either PVMF_MEDIA_DATA_MARKER_INFO_END_OF_NAL_BIT or PVMF_MEDIA_DATA_MARKER_INFO_M_BIT 2530 // and we're not in "frame" mode, then set OMX_BUFFERFLAG_ENDOFFRAME 2531 if (iCurrentMsgMarkerBit && !iOMXComponentUsesFullAVCFrames) 2532 { 2533 // NAL mode, (uses OMX_BUFFERFLAG_ENDOFFRAME flag to mark end of NAL instead of end of frame) 2534 // once NAL is complete, make sure you send it and obtain new buffer 2535 input_buf->pBufHdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; 2536 iObtainNewInputBuffer = true; 2537 } 2538 else if (iCurrentMsgMarkerBit & PVMF_MEDIA_DATA_MARKER_INFO_M_BIT) 2539 { 2540 // frame mode 2541 input_buf->pBufHdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; 2542 iObtainNewInputBuffer = true; 2543 } 2544 } 2545 } 2546 else 2547 { 2548 // we are separating fragments that are too big, i.e. bigger than 2549 // what 1 buffer can hold, this fragment Can NEVER have marker bit 2550 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2551 (0, "%s::SendInputBufferToOMXComponent() - NOT END OF FRAGMENT - Buffer 0x%x MARKER bit set to 0", iName.Str(), input_buf->pBufHdr->pBuffer)); 2552 2553 } 2554 } 2555 else 2556 { 2557 // "normal" case, i.e. only fragments at ends of msgs may have marker bit set 2558 // fragments in the middle of a message never have marker bit set 2559 // there is also a (slight) possibility we broke up the fragment into more fragments 2560 // because they can't fit into input buffer. In this case, make sure you apply 2561 // the marker bit (if necessary) only to the very last piece of the very last fragment 2562 2563 // for all other cases, clear the marker bit flag for the buffer 2564 if ((iCurrFragNum == iDataIn->getNumFragments()) && iIsNewDataFragment) 2565 { 2566 // if all the fragments have been exhausted, and this is the last piece 2567 // of the (possibly broken up) last fragment 2568 2569 // use the marker bit from the end of message 2570 if (iCurrentMsgMarkerBit) 2571 { 2572 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2573 (0, "%s::SendInputBufferToOMXComponent() - END OF MESSAGE - Buffer 0x%x MARKER bit set to 1, TS=%d, Ticks=%L", iName.Str(), input_buf->pBufHdr->pBuffer, iInTimestamp, iOMXTicksTimestamp)); 2574 2575 input_buf->pBufHdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; 2576 // once frame is complete, make sure you send it and obtain new buffer 2577 2578 iObtainNewInputBuffer = true; 2579 } 2580 else 2581 { 2582 2583 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2584 (0, "%s::SendInputBufferToOMXComponent() - END OF MESSAGE - Buffer 0x%x MARKER bit set to 0, TS=%d, Ticks=%L", iName.Str(), input_buf->pBufHdr->pBuffer, iInTimestamp, iOMXTicksTimestamp)); 2585 } 2586 } 2587 else 2588 { 2589 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2590 (0, "%s::SendInputBufferToOMXComponent() - NOT END OF MESSAGE - Buffer 0x%x MARKER bit set to 0, TS=%d, Ticks=%L", iName.Str(), input_buf->pBufHdr->pBuffer, iInTimestamp, iOMXTicksTimestamp)); 2591 } 2592 2593 2594 }// end of else(setmarkerbitforeveryfrag) 2595 2596 2597 // set the key frame flag if necessary (mark every fragment that belongs to it) 2598 if (iDataIn->getMarkerInfo() & PVMF_MEDIA_DATA_MARKER_INFO_RANDOM_ACCESS_POINT_BIT) 2599 input_buf->pBufHdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; 2600 2601 if (iObtainNewInputBuffer == true) 2602 { 2603 // if partial frames are supported, this flag will always be set 2604 // if partial frames are not supported, this flag will be set only 2605 // if the partial frame/NAL has been assembled, so we can send it 2606 2607 // if incomplete frames are not supported then let go of this buffer, and move on 2608 if (iIncompleteFrame && !iOMXComponentCanHandleIncompleteFrames) 2609 { 2610 DropCurrentBufferUnderConstruction(); 2611 } 2612 else 2613 { 2614 // append extra data for "frame" mode 2615 if (iOMXComponentUsesFullAVCFrames && !iOMXComponentUsesNALStartCodes) 2616 { 2617 if (!AppendExtraDataToBuffer(input_buf, (OMX_EXTRADATATYPE) OMX_ExtraDataNALSizeArray, (uint8*) iNALSizeArray, 4 * iNALCount)) 2618 { 2619 // if AppendExtraDataToBuffer returns false, that means there wasn't enough room to write the data, so drop the buffer 2620 DropCurrentBufferUnderConstruction(); 2621 } 2622 } 2623 2624 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2625 (0, "%s::SendInputBufferToOMXComponent() - Sending Buffer 0x%x to OMX Component MARKER field set to %x, TS=%d, Ticks=%L", iName.Str(), input_buf->pBufHdr->pBuffer, input_buf->pBufHdr->nFlags, iInTimestamp, iOMXTicksTimestamp)); 2626 2627 OMX_EmptyThisBuffer(iOMXDecoder, input_buf->pBufHdr); 2628 iInputBufferUnderConstruction = NULL; // this buffer is gone to OMX component now 2629 } 2630 } 2631 2632 // if we sent all fragments to OMX component, decouple the input message from iDataIn 2633 // Input message is "decoupled", so that we can get a new message for processing into iDataIn 2634 // However, the actual message is released completely to upstream mempool once all of its fragments 2635 // are returned by the OMX component 2636 2637 if (iCurrFragNum == iDataIn->getNumFragments()) 2638 { 2639 iDataIn.Unbind(); 2640 2641 } 2642 2643 2644 } 2645 while (iCurrFragNum < iInNumFrags); //iDataIn->getNumFragments()); 2646 2647 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2648 (0, "%s::SendInputBufferToOMXComponent() Out", iName.Str())); 2649 2650 return true; 2651 2652 } 2653 2654 ///////////////////////////////////////////////////////////////////////////// 2655 OSCL_EXPORT_REF bool PVMFOMXBaseDecNode::AppendExtraDataToBuffer(InputBufCtrlStruct* aInputBuffer, 2656 OMX_EXTRADATATYPE aType, 2657 uint8* aExtraData, 2658 uint8 aDataLength) 2659 2660 { 2661 // This function is used to append AVC NAL info to the buffer using the OMX_EXTRADATA_TYPE structure, when 2662 // a component requires buffers with full AVC frames rather than just NALs 2663 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2664 (0, "%s::AppendExtraDataToBuffer() In", iName.Str())); 2665 2666 2667 if ((aType != OMX_ExtraDataNone) && (aExtraData != NULL) && (aInputBuffer->pBufHdr->pBuffer != NULL)) 2668 { 2669 const uint32 sizeOfExtraDataStruct = 20; // 20 is the number of bytes for the OMX_OTHER_EXTRADATATYPE structure (minus the data hint member) 2670 2671 OMX_OTHER_EXTRADATATYPE extra; 2672 OMX_OTHER_EXTRADATATYPE terminator; 2673 2674 CONFIG_SIZE_AND_VERSION(extra); 2675 CONFIG_SIZE_AND_VERSION(terminator); 2676 2677 extra.nPortIndex = iInputPortIndex; 2678 terminator.nPortIndex = iInputPortIndex; 2679 2680 extra.eType = aType; 2681 extra.nSize = (sizeOfExtraDataStruct + aDataLength + 3) & ~3; // size + padding for byte alignment 2682 extra.nDataSize = aDataLength; 2683 2684 // fill in fields for terminator 2685 terminator.eType = OMX_ExtraDataNone; 2686 terminator.nDataSize = 0; 2687 2688 // make sure there is enough room in the buffer 2689 if (aInputBuffer->pBufHdr->nAllocLen < (aInputBuffer->pBufHdr->nFilledLen + sizeOfExtraDataStruct + aDataLength + terminator.nSize + 6)) 2690 { 2691 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2692 (0, "%s::AppendExtraDataToBuffer() - Error (not enough room in buffer) appending extra data to Buffer 0x%x to OMX Component, TS=%d, Ticks=%L", iName.Str(), aInputBuffer->pBufHdr->pBuffer, iInTimestamp, iOMXTicksTimestamp)); 2693 2694 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2695 (0, "%s::AppendExtraDataToBuffer() Out", iName.Str())); 2696 2697 return false; 2698 } 2699 2700 // copy extra data into buffer 2701 // need to align to 4 bytes 2702 OMX_U8* buffer = aInputBuffer->pBufHdr->pBuffer + aInputBuffer->pBufHdr->nOffset + aInputBuffer->pBufHdr->nFilledLen; 2703 buffer = (OMX_U8*)(((OMX_U32) buffer + 3) & ~3); 2704 2705 oscl_memcpy(buffer, &extra, sizeOfExtraDataStruct); 2706 oscl_memcpy(buffer + sizeOfExtraDataStruct, aExtraData, aDataLength); 2707 buffer += extra.nSize; 2708 2709 oscl_memcpy(buffer, &terminator, terminator.nSize); 2710 2711 // flag buffer 2712 aInputBuffer->pBufHdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA; 2713 2714 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2715 (0, "%s::AppendExtraDataToBuffer() - Appending extra data to Buffer 0x%x to OMX Component, TS=%d, Ticks=%L", iName.Str(), aInputBuffer->pBufHdr->pBuffer, iInTimestamp, iOMXTicksTimestamp)); 2716 2717 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2718 (0, "%s::AppendExtraDataToBuffer() Out", iName.Str())); 2719 2720 return true; 2721 } 2722 else 2723 { 2724 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2725 (0, "%s::AppendExtraDataToBuffer() Out", iName.Str())); 2726 2727 return false; 2728 } 2729 } 2730 2731 ///////////////////////////////////////////////////////////////////////////// 2732 OSCL_EXPORT_REF bool PVMFOMXBaseDecNode::SendConfigBufferToOMXComponent(uint8 *initbuffer, uint32 initbufsize) 2733 2734 { 2735 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2736 (0, "%s::SendConfigBufferToOMXComponent() In", iName.Str())); 2737 2738 2739 // first of all , get an input buffer. Without a buffer, no point in proceeding 2740 InputBufCtrlStruct *input_buf = NULL; 2741 int32 errcode = OsclErrNone; 2742 2743 // try to get input buffer header 2744 OSCL_TRY(errcode, input_buf = (InputBufCtrlStruct *) iInBufMemoryPool->allocate(iInputAllocSize)); 2745 if (OsclErrNone != errcode) 2746 { 2747 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 2748 (0, "%s::SendConfigBufferToOMXComponent() Input buffer mempool problem -unexpected at init", iName.Str())); 2749 2750 return false; 2751 } 2752 2753 // Got a buffer OK 2754 // keep track of buffers. When buffer is deallocated/released, the counter will be decremented 2755 iInBufMemoryPool->notifyfreechunkavailable(*this, (OsclAny*) iInBufMemoryPool); 2756 iNumOutstandingInputBuffers++; 2757 2758 input_buf->pBufHdr->nFilledLen = 0; //init this to 0 2759 2760 // Now we have the buffer header (i.e. a buffer) to send to component: 2761 // Depending on OMX component capabilities, either pass the input msg fragment(s) directly 2762 // into OMX component without copying (and update the input msg refcount) 2763 // or memcopy the content of input msg memfrag(s) into OMX component allocated buffers 2764 2765 // When copying content, a special case is when the input fragment is larger than the buffer and has to 2766 // be fragmented here and broken over 2 or more buffers. Potential problem with available buffers etc. 2767 2768 iCodecSeqNum += (iDataIn->getSeqNum() - iInPacketSeqNum); // increment the codec seq. # by the same 2769 // amount that the input seq. number increased 2770 2771 iInPacketSeqNum = iDataIn->getSeqNum(); // remember input sequence number 2772 iInTimestamp = iDataIn->getTimestamp(); 2773 iInDuration = iDataIn->getDuration(); 2774 2775 2776 if (!(iDataIn->getMarkerInfo() & PVMF_MEDIA_DATA_MARKER_INFO_M_BIT)) 2777 { 2778 2779 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2780 (0, "%s::SendConfigBufferToOMXComponent() - New msg has NO MARKER BIT", iName.Str())); 2781 } 2782 2783 2784 if (iOMXComponentSupportsMovableInputBuffers) 2785 { 2786 // no copying required 2787 2788 // increment the RefCounter of the message associated with the mem fragment/buffer 2789 // when sending this buffer to OMX component. (When getting the buffer back, the refcounter 2790 // will be decremented. Thus, when the last fragment is returned, the input mssage is finally released 2791 2792 iDataIn.GetRefCounter()->addRef(); 2793 2794 // associate the buffer ctrl structure with the message ref counter and ptr 2795 input_buf->pMediaData = PVMFSharedMediaDataPtr(iDataIn.GetRep(), iDataIn.GetRefCounter()); 2796 2797 2798 // set pointer to the data, length, offset 2799 input_buf->pBufHdr->pBuffer = initbuffer; 2800 input_buf->pBufHdr->nFilledLen = initbufsize; 2801 2802 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2803 (0, "%s::SendConfigBufferToOMXComponent() - Config Buffer 0x%x of size %d", iName.Str(), initbuffer, initbufsize)); 2804 2805 } 2806 else 2807 { 2808 2809 // in this case, no need to use input msg refcounter, each buffer fragment is copied over and treated separately 2810 (input_buf->pMediaData).Unbind(); 2811 2812 // we assume the buffer is large enough to fit the config data 2813 2814 iCopyPosition = 0; 2815 iFragmentSizeRemainingToCopy = initbufsize; 2816 2817 if (iOMXComponentUsesNALStartCodes == true) 2818 { 2819 oscl_memcpy(input_buf->pBufHdr->pBuffer, 2820 (void *) NAL_START_CODE, 2821 NAL_START_CODE_SIZE); 2822 input_buf->pBufHdr->nFilledLen += NAL_START_CODE_SIZE; 2823 2824 } 2825 2826 // can the remaining fragment fit into the buffer? 2827 uint32 bytes_remaining_in_buffer = (input_buf->pBufHdr->nAllocLen - input_buf->pBufHdr->nFilledLen); 2828 2829 if (iFragmentSizeRemainingToCopy <= bytes_remaining_in_buffer) 2830 { 2831 2832 oscl_memcpy(input_buf->pBufHdr->pBuffer + input_buf->pBufHdr->nFilledLen, 2833 (void *)(initbuffer + iCopyPosition), 2834 iFragmentSizeRemainingToCopy); 2835 2836 input_buf->pBufHdr->nFilledLen += iFragmentSizeRemainingToCopy; 2837 2838 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2839 (0, "%s::SendConfigBufferToOMXComponent() - Copied %d bytes into buffer 0x%x of size %d", iName.Str(), iFragmentSizeRemainingToCopy, input_buf->pBufHdr->pBuffer, input_buf->pBufHdr->nFilledLen)); 2840 2841 iCopyPosition += iFragmentSizeRemainingToCopy; 2842 iFragmentSizeRemainingToCopy = 0; 2843 2844 2845 } 2846 else 2847 { 2848 2849 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 2850 (0, "%s::SendConfigBufferToOMXComponent() Config buffer too large problem -unexpected at init", iName.Str())); 2851 2852 return false; 2853 } 2854 2855 } 2856 2857 2858 // set buffer fields (this is the same regardless of whether the input is movable or not 2859 input_buf->pBufHdr->nOffset = 0; 2860 2861 iInputTimestampClock.update_clock(iInTimestamp); // this will also take into consideration the timestamp rollover 2862 iOMXTicksTimestamp = ConvertTimestampIntoOMXTicks(iInputTimestampClock); // make a conversion into OMX ticks 2863 input_buf->pBufHdr->nTimeStamp = iOMXTicksTimestamp; 2864 2865 // set ptr to input_buf structure for Context (for when the buffer is returned) 2866 input_buf->pBufHdr->pAppPrivate = (OMX_PTR) input_buf; 2867 2868 // do not use Mark here (but init to NULL to prevent problems) 2869 input_buf->pBufHdr->hMarkTargetComponent = NULL; 2870 input_buf->pBufHdr->pMarkData = NULL; 2871 2872 2873 // init buffer flags 2874 input_buf->pBufHdr->nFlags = 0; 2875 2876 // set marker bit on 2877 2878 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2879 (0, "%s::SendConfigBufferToOMXComponent() - END OF FRAGMENT - Buffer 0x%x MARKER bit set to 1", iName.Str(), input_buf->pBufHdr->pBuffer)); 2880 2881 input_buf->pBufHdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; 2882 2883 // set buffer flag indicating buffer contains codec config data 2884 input_buf->pBufHdr->nFlags |= OMX_BUFFERFLAG_CODECCONFIG; 2885 2886 OMX_EmptyThisBuffer(iOMXDecoder, input_buf->pBufHdr); 2887 2888 return true; 2889 2890 } 2891 2892 2893 2894 ///////////////////////////////////////////////////////////////////////////// 2895 OSCL_EXPORT_REF bool PVMFOMXBaseDecNode::CreateOutMemPool(uint32 num_buffers) 2896 { 2897 2898 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2899 (0, "%s::CreateOutMemPool() start", iName.Str())); 2900 // In the case OMX component wants to allocate its own buffers, 2901 // mempool only contains OutputBufCtrlStructures (i.e. ptrs to buffer headers) 2902 // In case OMX component uses pre-allocated buffers (here), 2903 // mempool allocates OutputBufCtrlStructure (i.e. ptrs to buffer hdrs), followed by actual buffers 2904 2905 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2906 (0, "%s::CreateOutMemPool() Allocating output buffer header pointers", iName.Str())); 2907 2908 iOutputAllocSize = oscl_mem_aligned_size((uint32)sizeof(OutputBufCtrlStruct)); 2909 2910 if (iOMXComponentSupportsExternalOutputBufferAlloc) 2911 { 2912 // In case of an external output buffer allocator interface, output buffer memory will be allocated 2913 // outside the node and hence iOutputAllocSize need not be incremented here 2914 2915 if (NULL == ipExternalOutputBufferAllocatorInterface) 2916 { 2917 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2918 (0, "%s::CreateOutMemPool() Allocating output buffers of size %d as well", iName.Str(), iOMXComponentOutputBufferSize)); 2919 //pre-negotiated output buffer size 2920 iOutputAllocSize += iOMXComponentOutputBufferSize; 2921 } 2922 } 2923 2924 // for media data wrapper 2925 if (iMediaDataMemPool) 2926 { 2927 iMediaDataMemPool->removeRef(); 2928 iMediaDataMemPool = NULL; 2929 } 2930 2931 if (iOutBufMemoryPool) 2932 { 2933 iOutBufMemoryPool->removeRef(); 2934 iOutBufMemoryPool = NULL; 2935 } 2936 2937 int32 leavecode = OsclErrNone; 2938 OSCL_TRY(leavecode, iOutBufMemoryPool = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (num_buffers));); 2939 if (leavecode || iOutBufMemoryPool == NULL) 2940 { 2941 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, 2942 PVLOGMSG_ERR, (0, "%s::CreateOutMemPool() Memory pool structure for output buffers failed to allocate", iName.Str())); 2943 return false; 2944 } 2945 2946 2947 2948 // allocate a dummy buffer to actually create the mempool 2949 OsclAny *dummy_alloc = NULL; // this dummy buffer will be released at end of scope 2950 leavecode = OsclErrNone; 2951 OSCL_TRY(leavecode, dummy_alloc = iOutBufMemoryPool->allocate(iOutputAllocSize)); 2952 if (leavecode || dummy_alloc == NULL) 2953 { 2954 2955 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, 2956 PVLOGMSG_ERR, (0, "%s::CreateOutMemPool() Memory pool for output buffers failed to allocate", iName.Str())); 2957 return false; 2958 } 2959 iOutBufMemoryPool->deallocate(dummy_alloc); 2960 // init the counter 2961 iNumOutstandingOutputBuffers = 0; 2962 2963 // allocate mempool for media data message wrapper 2964 leavecode = OsclErrNone; 2965 OSCL_TRY(leavecode, iMediaDataMemPool = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (num_buffers, PVOMXBASEDEC_MEDIADATA_CHUNKSIZE))); 2966 if (leavecode || iMediaDataMemPool == NULL) 2967 { 2968 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "%s::CreateOutMemPool() Media Data Buffer pool for output buffers failed to allocate", iName.Str())); 2969 return false; 2970 } 2971 2972 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::CreateOutMemPool() done", iName.Str())); 2973 return true; 2974 } 2975 ///////////////////////////////////////////////////////////////////////////////////////////////////// 2976 ///////////////////////////// Creates memory pool for input buffer management /////////////////////// 2977 ///////////////////////////////////////////////////////////////////////////////////////////////////// 2978 OSCL_EXPORT_REF bool PVMFOMXBaseDecNode::CreateInputMemPool(uint32 num_buffers) 2979 { 2980 // 3 cases in order of preference and simplicity 2981 2982 // Case 1 (buffers allocated upstream - no memcpy needed): 2983 // PV OMX Component - We use buffers allocated outside the OMX node (i.e. allocated upstream) 2984 // Mempool contains InputBufCtrlStructures (ptrs to buffer headers and PMVFMediaData ptrs - to keep track of when to unbind input msgs) 2985 2986 // NOTE: in this case, when providing input buffers to OMX component, 2987 // OMX_UseBuffer calls will provide some initial pointers and sizes of buffers, but these 2988 // are dummy values. Actual buffer pointers and filled sizes will be obtained from the input msg fragments. 2989 // The PV OMX component will use the buffers even if the ptrs differ from the ones during initialization 2990 // 3rd party OMX components can also use this case if they are capable of ignoring the actual buffer pointers in 2991 // buffer header field (i.e. if after OMX_UseBuffer(...) call, they allow the ptr to actual buffer data to change at a later time 2992 2993 // CASE 2 (buffers allocated in the node - memcpy needed) 2994 // If 3rd party OMX component can use buffers allocated outside the OMX component, but it cannot 2995 // change buffer ptr allocations dynamically (i.e. after initialization with OMX_UseBuffer call is complete) 2996 2997 // Mempool contains InputBufCtrlStructures (ptrs to buffer headers, PVMFMediaData ptrs to keep track of when to unbind input msgs) + 2998 // actual buffers. 2999 // NOTE: Data must be copied from input message into the local buffer before the buffer is given to the OMX component 3000 3001 // CASE 3 (buffers allocated in the component - memcpy needed) 3002 // If 3rd party OMX component must allocate its own buffers 3003 // Mempool only contains InputBufCtrlStruct (ptrs to buffer headers + PMVFMediaData ptrs to keep track of when to unbind input msgs) 3004 // 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) 3005 3006 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3007 (0, "%s::CreateInputMemPool() start ", iName.Str())); 3008 3009 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3010 (0, "%s::CreateInputMemPool() allocating buffer header pointers and shared media data ptrs ", iName.Str())); 3011 3012 3013 3014 iInputAllocSize = oscl_mem_aligned_size((uint32) sizeof(InputBufCtrlStruct)); //aligned_size_buffer_header_ptr+aligned_size_media_data_ptr; 3015 3016 // Need to allocate buffers in the node either if component supports external buffers buffers 3017 // but they are not movable 3018 3019 if ((iOMXComponentSupportsExternalInputBufferAlloc && !iOMXComponentSupportsMovableInputBuffers)) 3020 { 3021 //pre-negotiated input buffer size 3022 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3023 (0, "%s::CreateOutMemPool() Allocating input buffers of size %d as well", iName.Str(), iOMXComponentInputBufferSize)); 3024 3025 iInputAllocSize += iOMXComponentInputBufferSize; 3026 } 3027 3028 if (iInBufMemoryPool) 3029 { 3030 iInBufMemoryPool->removeRef(); 3031 iInBufMemoryPool = NULL; 3032 } 3033 3034 int32 leavecode = OsclErrNone; 3035 OSCL_TRY(leavecode, iInBufMemoryPool = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (num_buffers));); 3036 if (leavecode || iInBufMemoryPool == NULL) 3037 { 3038 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, 3039 PVLOGMSG_ERR, (0, "%s::CreateInputMemPool() Memory pool structure for input buffers failed to allocate", iName.Str())); 3040 return false; 3041 } 3042 // try to allocate a dummy buffer to actually create the mempool and allocate the needed memory 3043 // allocate a dummy buffer to actually create the mempool, this dummy buffer will be released at end of scope of this method 3044 OsclAny *dummy_alloc = NULL; 3045 leavecode = OsclErrNone; 3046 OSCL_TRY(leavecode, dummy_alloc = iInBufMemoryPool->allocate(iInputAllocSize)); 3047 if (leavecode || dummy_alloc == NULL) 3048 { 3049 3050 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, 3051 PVLOGMSG_ERR, (0, "%s::CreateInputMemPool() Memory pool for input buffers failed to allocate", iName.Str())); 3052 return false; 3053 } 3054 3055 // init the counter 3056 iNumOutstandingInputBuffers = 0; 3057 3058 3059 iInputBufferToResendToComponent = NULL; // nothing to resend yet 3060 iInBufMemoryPool->deallocate(dummy_alloc); 3061 3062 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::CreateInputMemPool() done", iName.Str())); 3063 return true; 3064 } 3065 //////////////////////////////////////////////////////////////////////////// 3066 OSCL_EXPORT_REF bool PVMFOMXBaseDecNode::ProvideBuffersToComponent(OsclMemPoolFixedChunkAllocator *aMemPool, // allocator 3067 uint32 aAllocSize, // size to allocate from pool (hdr only or hdr+ buffer) 3068 uint32 aNumBuffers, // number of buffers 3069 uint32 aActualBufferSize, // aactual buffer size 3070 uint32 aPortIndex, // port idx 3071 bool aUseBufferOK, // can component use OMX_UseBuffer or should it use OMX_AllocateBuffer 3072 bool aIsThisInputBuffer // is this input or output 3073 ) 3074 { 3075 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::ProvideBuffersToComponent() enter", iName.Str())); 3076 3077 uint32 ii = 0; 3078 OMX_ERRORTYPE err = OMX_ErrorNone; 3079 OsclAny **ctrl_struct_ptr = NULL; // temporary array to keep the addresses of buffer ctrl structures and buffers 3080 3081 3082 ctrl_struct_ptr = (OsclAny **) oscl_malloc(aNumBuffers * sizeof(OsclAny *)); 3083 if (ctrl_struct_ptr == NULL) 3084 { 3085 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3086 (0, "%s::ProvideBuffersToComponent ctrl_struct_ptr == NULL", iName.Str())); 3087 return false; 3088 } 3089 3090 3091 3092 // Now, go through all buffers and tell component to 3093 // either use a buffer, or to allocate its own buffer 3094 for (ii = 0; ii < aNumBuffers; ii++) 3095 { 3096 3097 int32 errcode = OsclErrNone; 3098 // get the address where the buf hdr ptr will be stored 3099 errcode = AllocateChunkFromMemPool(ctrl_struct_ptr[ii], aMemPool, aAllocSize); 3100 if ((OsclErrNone != errcode) || (ctrl_struct_ptr[ii] == NULL)) 3101 { 3102 if (OsclErrNoResources == errcode) 3103 { 3104 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3105 (0, "%s::ProvideBuffersToComponent ->allocate() failed for no mempool chunk available", iName.Str())); 3106 } 3107 else 3108 { 3109 // General error 3110 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 3111 (0, "%s::ProvideBuffersToComponent ->allocate() failed due to some general error", iName.Str())); 3112 3113 ReportErrorEvent(PVMFFailure); 3114 ChangeNodeState(EPVMFNodeError); 3115 } 3116 3117 return false; 3118 } 3119 3120 if (aUseBufferOK) 3121 { 3122 // Buffers are already allocated outside OMX component. 3123 // In case of output buffers, the buffer itself is located 3124 // just after the buffer header pointer. 3125 3126 // In case of input buffers, the buffer header pointer is followed by a MediaDataSharedPtr 3127 // which is used to ensure proper unbinding of the input messages. The buffer itself is either: 3128 // a) allocated upstream (and the ptr to the buffer 3129 // is a dummy pointer to which the component does not pay attention - PV OMX component) 3130 // b) located just after the buffer header pointer and MediaDataSharedPtr 3131 3132 uint8 *pB = ((uint8*) ctrl_struct_ptr[ii]); 3133 3134 3135 // in case of input buffers, initialize also MediaDataSharedPtr structure 3136 if (aIsThisInputBuffer) 3137 { 3138 3139 InputBufCtrlStruct *temp = (InputBufCtrlStruct *) ctrl_struct_ptr[ii]; 3140 oscl_memset(&(temp->pMediaData), 0, sizeof(PVMFSharedMediaDataPtr)); 3141 temp->pMediaData = PVMFSharedMediaDataPtr(NULL, NULL); 3142 3143 // advance ptr to skip the structure 3144 pB += oscl_mem_aligned_size(sizeof(InputBufCtrlStruct)); 3145 3146 err = OMX_UseBuffer(iOMXDecoder, // hComponent 3147 &(temp->pBufHdr), // address where ptr to buffer header will be stored 3148 aPortIndex, // port index (for port for which buffer is provided) 3149 ctrl_struct_ptr[ii], // App. private data = pointer to beginning of allocated data 3150 // to have a context when component returns with a callback (i.e. to know 3151 // what to free etc. 3152 (OMX_U32)aActualBufferSize, // buffer size 3153 pB); // buffer data ptr 3154 3155 in_ctrl_struct_ptr[ii] = ctrl_struct_ptr[ii]; 3156 in_buff_hdr_ptr[ii] = temp->pBufHdr; 3157 3158 } 3159 else 3160 { 3161 if (ipExternalOutputBufferAllocatorInterface) 3162 { 3163 // Actual buffer memory will be allocated outside the node from 3164 // an external output buffer allocator interface 3165 3166 uint8 *pB = (uint8*) ipFixedSizeBufferAlloc->allocate(); 3167 if (NULL == pB) 3168 { 3169 // error 3170 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 3171 (0, "%s::ProvideBuffersToComponent ->allocate() failed due to some general error", iName.Str())); 3172 ReportErrorEvent(PVMFFailure); 3173 ChangeNodeState(EPVMFNodeError); 3174 return false; 3175 } 3176 3177 OutputBufCtrlStruct *temp = (OutputBufCtrlStruct *)ctrl_struct_ptr[ii]; 3178 3179 err = OMX_UseBuffer(iOMXDecoder, // hComponent 3180 &(temp->pBufHdr), // address where ptr to buffer header will be stored 3181 aPortIndex, // port index (for port for which buffer is provided) 3182 ctrl_struct_ptr[ii], // App. private data = pointer to beginning of allocated data 3183 // to have a context when component returns with a callback (i.e. to know 3184 // what to free etc. 3185 (OMX_U32)aActualBufferSize, // buffer size 3186 pB); // buffer data ptr 3187 3188 out_ctrl_struct_ptr[ii] = ctrl_struct_ptr[ii]; 3189 out_buff_hdr_ptr[ii] = temp->pBufHdr; 3190 3191 } 3192 else 3193 { 3194 OutputBufCtrlStruct *temp = (OutputBufCtrlStruct *) ctrl_struct_ptr[ii]; 3195 // advance buffer ptr to skip the structure 3196 pB += oscl_mem_aligned_size(sizeof(OutputBufCtrlStruct)); 3197 3198 err = OMX_UseBuffer(iOMXDecoder, // hComponent 3199 &(temp->pBufHdr), // address where ptr to buffer header will be stored 3200 aPortIndex, // port index (for port for which buffer is provided) 3201 ctrl_struct_ptr[ii], // App. private data = pointer to beginning of allocated data 3202 // to have a context when component returns with a callback (i.e. to know 3203 // what to free etc. 3204 (OMX_U32)aActualBufferSize, // buffer size 3205 pB); // buffer data ptr 3206 3207 out_ctrl_struct_ptr[ii] = ctrl_struct_ptr[ii]; 3208 out_buff_hdr_ptr[ii] = temp->pBufHdr; 3209 } 3210 3211 } 3212 3213 3214 } 3215 else 3216 { 3217 // the component must allocate its own buffers. 3218 if (aIsThisInputBuffer) 3219 { 3220 3221 InputBufCtrlStruct *temp = (InputBufCtrlStruct *) ctrl_struct_ptr[ii]; 3222 // make sure to init all this to NULL 3223 oscl_memset(&(temp->pMediaData), 0, sizeof(PVMFSharedMediaDataPtr)); 3224 temp->pMediaData = PVMFSharedMediaDataPtr(NULL, NULL); 3225 3226 err = OMX_AllocateBuffer(iOMXDecoder, 3227 &(temp->pBufHdr), 3228 aPortIndex, 3229 ctrl_struct_ptr[ii], 3230 (OMX_U32)aActualBufferSize); 3231 3232 in_ctrl_struct_ptr[ii] = ctrl_struct_ptr[ii]; 3233 in_buff_hdr_ptr[ii] = temp->pBufHdr; 3234 } 3235 else 3236 { 3237 OutputBufCtrlStruct *temp = (OutputBufCtrlStruct *) ctrl_struct_ptr[ii]; 3238 err = OMX_AllocateBuffer(iOMXDecoder, 3239 &(temp->pBufHdr), 3240 aPortIndex, 3241 ctrl_struct_ptr[ii], 3242 (OMX_U32)aActualBufferSize); 3243 3244 out_ctrl_struct_ptr[ii] = ctrl_struct_ptr[ii]; 3245 out_buff_hdr_ptr[ii] = temp->pBufHdr; 3246 } 3247 3248 } 3249 3250 if (err != OMX_ErrorNone) 3251 { 3252 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 3253 (0, "%s::ProvideBuffersToComponent() Problem using/allocating a buffer", iName.Str())); 3254 3255 3256 return false; 3257 } 3258 3259 } 3260 3261 for (ii = 0; ii < aNumBuffers; ii++) 3262 { 3263 // after initializing the buffer hdr ptrs, return them 3264 // to the mempool 3265 aMemPool->deallocate((OsclAny*) ctrl_struct_ptr[ii]); 3266 } 3267 3268 oscl_free(ctrl_struct_ptr); 3269 3270 // set the flags 3271 if (aIsThisInputBuffer) 3272 { 3273 iInputBuffersFreed = false; 3274 } 3275 else 3276 { 3277 iOutputBuffersFreed = false; 3278 } 3279 3280 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::ProvideBuffersToComponent() done", iName.Str())); 3281 return true; 3282 } 3283 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// 3284 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// 3285 bool PVMFOMXBaseDecNode::FreeBuffersFromComponent(OsclMemPoolFixedChunkAllocator *aMemPool, // allocator 3286 uint32 aAllocSize, // size to allocate from pool (hdr only or hdr+ buffer) 3287 uint32 aNumBuffers, // number of buffers 3288 uint32 aPortIndex, // port idx 3289 bool aIsThisInputBuffer // is this input or output 3290 ) 3291 { 3292 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::FreeBuffersToComponent() enter", iName.Str())); 3293 3294 uint32 ii = 0; 3295 OMX_ERRORTYPE err = OMX_ErrorNone; 3296 OsclAny **ctrl_struct_ptr = NULL; // temporary array to keep the addresses of buffer ctrl structures and buffers 3297 3298 3299 ctrl_struct_ptr = (OsclAny **) oscl_malloc(aNumBuffers * sizeof(OsclAny *)); 3300 if (ctrl_struct_ptr == NULL) 3301 { 3302 return false; 3303 } 3304 3305 3306 // Now, go through all buffers and tell component to free them 3307 for (ii = 0; ii < aNumBuffers; ii++) 3308 { 3309 3310 int32 errcode = OsclErrNone; 3311 // get the address where the buf hdr ptr will be stored 3312 3313 errcode = AllocateChunkFromMemPool(ctrl_struct_ptr[ii], aMemPool, aAllocSize); 3314 if ((OsclErrNone != errcode) || (ctrl_struct_ptr[ii] == NULL)) 3315 { 3316 if (OsclErrNoResources == errcode) 3317 { 3318 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3319 (0, "%s::FreeBuffersFromComponent ->allocate() failed for no mempool chunk available", iName.Str())); 3320 } 3321 else 3322 { 3323 // General error 3324 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 3325 (0, "%s::FreeBuffersFromComponent ->allocate() failed due to some general error", iName.Str())); 3326 3327 ReportErrorEvent(PVMFFailure); 3328 ChangeNodeState(EPVMFNodeError); 3329 } 3330 3331 return false; 3332 } 3333 // to maintain correct count 3334 aMemPool->notifyfreechunkavailable((*this), (OsclAny*) aMemPool); 3335 3336 if (aIsThisInputBuffer) 3337 { 3338 3339 iNumOutstandingInputBuffers++; 3340 // get the buf hdr pointer 3341 InputBufCtrlStruct *temp = (InputBufCtrlStruct *) ctrl_struct_ptr[ii]; 3342 err = OMX_FreeBuffer(iOMXDecoder, 3343 aPortIndex, 3344 temp->pBufHdr); 3345 3346 } 3347 else 3348 { 3349 if (ipExternalOutputBufferAllocatorInterface) 3350 { 3351 //Deallocate the output buffer memory that was allocated outside the node 3352 //using an external output buffer allocator interface 3353 3354 iNumOutstandingOutputBuffers++; 3355 OutputBufCtrlStruct *temp = (OutputBufCtrlStruct *) ctrl_struct_ptr[ii]; 3356 ipFixedSizeBufferAlloc->deallocate((OsclAny*) temp->pBufHdr->pBuffer); 3357 3358 err = OMX_FreeBuffer(iOMXDecoder, 3359 aPortIndex, 3360 temp->pBufHdr); 3361 } 3362 else 3363 { 3364 iNumOutstandingOutputBuffers++; 3365 OutputBufCtrlStruct *temp = (OutputBufCtrlStruct *) ctrl_struct_ptr[ii]; 3366 err = OMX_FreeBuffer(iOMXDecoder, 3367 aPortIndex, 3368 temp->pBufHdr); 3369 } 3370 } 3371 3372 if (err != OMX_ErrorNone) 3373 { 3374 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 3375 (0, "%s::FreeBuffersFromComponent() Problem freeing a buffer", iName.Str())); 3376 3377 return false; 3378 } 3379 3380 } 3381 3382 for (ii = 0; ii < aNumBuffers; ii++) 3383 { 3384 // after freeing the buffer hdr ptrs, return them 3385 // to the mempool (which will itself then be deleted promptly) 3386 aMemPool->deallocate((OsclAny*) ctrl_struct_ptr[ii]); 3387 } 3388 3389 oscl_free(ctrl_struct_ptr); 3390 3391 // mark buffers as freed (so as not to do it twice) 3392 if (aIsThisInputBuffer) 3393 { 3394 oscl_free(in_ctrl_struct_ptr); 3395 oscl_free(in_buff_hdr_ptr); 3396 3397 in_ctrl_struct_ptr = NULL; 3398 in_buff_hdr_ptr = NULL; 3399 iInputBuffersFreed = true; 3400 } 3401 else 3402 { 3403 oscl_free(out_ctrl_struct_ptr); 3404 oscl_free(out_buff_hdr_ptr); 3405 3406 out_ctrl_struct_ptr = NULL; 3407 out_buff_hdr_ptr = NULL; 3408 iOutputBuffersFreed = true; 3409 3410 if (ipExternalOutputBufferAllocatorInterface) 3411 { 3412 ipExternalOutputBufferAllocatorInterface->removeRef(); 3413 ipExternalOutputBufferAllocatorInterface = NULL; 3414 } 3415 } 3416 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::FreeBuffersFromComponent() done", iName.Str())); 3417 return true; 3418 } 3419 3420 ///////////////////////////////////////////////////////////////////////////// 3421 // This function handles the event of OMX component state change 3422 ///////////////////////////////////////////////////////////////////////////// 3423 OSCL_EXPORT_REF void PVMFOMXBaseDecNode::HandleComponentStateChange(OMX_U32 decoder_state) 3424 { 3425 switch (decoder_state) 3426 { 3427 case OMX_StateIdle: 3428 { 3429 iCurrentDecoderState = OMX_StateIdle; 3430 3431 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3432 (0, "%s::HandleComponentStateChange: OMX_StateIdle reached", iName.Str())); 3433 3434 // this state can be reached either going from OMX_Loaded->OMX_Idle (preparing) 3435 // or going from OMX_Executing->OMX_Idle (stopping) 3436 3437 3438 if ((iCurrentCommand.size() > 0) && 3439 (iCurrentCommand.front().iCmd == PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_PREPARE)) 3440 { 3441 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_InitDecoder; 3442 SetState(EPVMFNodePrepared); 3443 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess); 3444 RunIfNotReady(); 3445 } 3446 else if ((iCurrentCommand.size() > 0) && 3447 (iCurrentCommand.front().iCmd == PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_STOP)) 3448 { 3449 // if we are stopped, we won't start until the node gets DoStart command. 3450 // in this case, we are ready to start sending buffers 3451 if (iProcessingState == EPVMFOMXBaseDecNodeProcessingState_Stopping) 3452 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_ReadyToDecode; 3453 // if the processing state was not stopping, leave the state as it was (continue port reconfiguration) 3454 SetState(EPVMFNodePrepared); 3455 iStopCommandWasSentToComponent = false; 3456 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess); 3457 3458 RunIfNotReady(); 3459 } 3460 else if ((iCurrentCommand.size() > 0) && 3461 (iCurrentCommand.front().iCmd == PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_RESET)) 3462 { 3463 // State change to Idle was initiated due to Reset. First need to reach idle, and then loaded 3464 // Once Idle is reached, we need to initiate idle->loaded transition 3465 iStopInResetMsgSent = false; 3466 RunIfNotReady(); 3467 } 3468 break; 3469 }//end of case OMX_StateIdle 3470 3471 case OMX_StateExecuting: 3472 { 3473 iCurrentDecoderState = OMX_StateExecuting; 3474 3475 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3476 (0, "%s::HandleComponentStateChange: OMX_StateExecuting reached", iName.Str())); 3477 3478 // this state can be reached going from OMX_Idle -> OMX_Executing (preparing) 3479 // or going from OMX_Pause -> OMX_Executing (coming from pause) 3480 // either way, this is a response to "DoStart" command 3481 3482 if ((iCurrentCommand.size() > 0) && 3483 (iCurrentCommand.front().iCmd == PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_START)) 3484 { 3485 SetState(EPVMFNodeStarted); 3486 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess); 3487 3488 RunIfNotReady(); 3489 } 3490 3491 break; 3492 }//end of case OMX_StateExecuting 3493 3494 case OMX_StatePause: 3495 { 3496 iCurrentDecoderState = OMX_StatePause; 3497 3498 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3499 (0, "%s::HandleComponentStateChange: OMX_StatePause reached", iName.Str())); 3500 3501 // if we are paused, we won't start until the node gets DoStart command. 3502 // in this case, we are ready to start sending buffers 3503 if (iProcessingState == EPVMFOMXBaseDecNodeProcessingState_Pausing) 3504 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_ReadyToDecode; 3505 3506 // This state can be reached going from OMX_Executing-> OMX_Pause 3507 if ((iCurrentCommand.size() > 0) && 3508 (iCurrentCommand.front().iCmd == PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_PAUSE)) 3509 { 3510 3511 // if we are paused, we won't start until the node gets DoStart command. 3512 // in this case, we are ready to start sending buffers 3513 if (iProcessingState == EPVMFOMXBaseDecNodeProcessingState_Pausing) 3514 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_ReadyToDecode; 3515 // if the processing state was not pausing, leave the state as it was (continue port reconfiguration) 3516 3517 3518 SetState(EPVMFNodePaused); 3519 iPauseCommandWasSentToComponent = false; 3520 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess); 3521 RunIfNotReady(); 3522 } 3523 3524 break; 3525 }//end of case OMX_StatePause 3526 3527 case OMX_StateLoaded: 3528 { 3529 iCurrentDecoderState = OMX_StateLoaded; 3530 3531 // this state can be reached only going from OMX_Idle ->OMX_Loaded (stopped to reset) 3532 // 3533 3534 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3535 (0, "%s::HandleComponentStateChange: OMX_StateLoaded reached", iName.Str())); 3536 //Check if command's responce is pending 3537 if ((iCurrentCommand.size() > 0) && 3538 (iCurrentCommand.front().iCmd == PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_RESET)) 3539 { 3540 3541 // move this here 3542 if (iInPort) 3543 { 3544 OSCL_DELETE(((PVMFOMXDecPort*)iInPort)); 3545 iInPort = NULL; 3546 } 3547 3548 if (iOutPort) 3549 { 3550 OSCL_DELETE(((PVMFOMXDecPort*)iOutPort)); 3551 iOutPort = NULL; 3552 } 3553 3554 iDataIn.Unbind(); 3555 3556 // Reset the metadata key list 3557 iAvailableMetadataKeys.clear(); 3558 3559 3560 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_Idle; 3561 //logoff & go back to Created state. 3562 SetState(EPVMFNodeIdle); 3563 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess); 3564 iResetInProgress = false; 3565 iResetMsgSent = false; 3566 } 3567 3568 break; 3569 }//end of case OMX_StateLoaded 3570 3571 case OMX_StateInvalid: 3572 default: 3573 { 3574 iCurrentDecoderState = OMX_StateInvalid; 3575 3576 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 3577 (0, "%s::HandleComponentStateChange: OMX_StateInvalid reached", iName.Str())); 3578 if (iOMXDecoder == NULL) 3579 { 3580 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 3581 (0, "%s::HandleComponentStateChange: cleanup already done. Do nothing", iName.Str())); 3582 return; 3583 } 3584 3585 //Cleanup encoder 3586 DeleteOMXBaseDecoder(); 3587 //Stop using OMX component 3588 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_Idle; 3589 3590 if (iCurrentCommand.size() > 0) 3591 {// CANNOT be CANCEL or CANCEL_ALL. Just to cmd completion for the reset 3592 if (iCurrentCommand.front().iCmd == PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_RESET) 3593 { 3594 //delete all ports and notify observer. 3595 if (iInPort) 3596 { 3597 OSCL_DELETE(((PVMFOMXDecPort*)iInPort)); 3598 iInPort = NULL; 3599 } 3600 3601 if (iOutPort) 3602 { 3603 OSCL_DELETE(((PVMFOMXDecPort*)iOutPort)); 3604 iOutPort = NULL; 3605 } 3606 3607 iDataIn.Unbind(); 3608 3609 // Reset the metadata key list 3610 iAvailableMetadataKeys.clear(); 3611 3612 iEndOfDataReached = false; 3613 iIsEOSSentToComponent = false; 3614 iIsEOSReceivedFromComponent = false; 3615 3616 //logoff & go back to Created state. 3617 SetState(EPVMFNodeIdle); 3618 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess); 3619 } 3620 else 3621 { 3622 SetState(EPVMFNodeError); 3623 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFErrResource); 3624 } 3625 } 3626 else 3627 { 3628 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 3629 (0, "%s::HandleComponentStateChange: ERROR state transition event while OMX client does NOT have any pending state transition request", iName.Str())); 3630 SetState(EPVMFNodeError); 3631 ReportErrorEvent(PVMFErrResourceConfiguration); 3632 } 3633 3634 break; 3635 }//end of case OMX_StateInvalid 3636 3637 }//end of switch(decoder_state) 3638 3639 } 3640 3641 3642 3643 3644 3645 3646 ///////////////////////////////////////////////////////////////////////////// 3647 ////////////////////// CALLBACK PROCESSING FOR EMPTY BUFFER DONE - input buffer was consumed 3648 ///////////////////////////////////////////////////////////////////////////// 3649 OMX_ERRORTYPE PVMFOMXBaseDecNode::EmptyBufferDoneProcessing(OMX_OUT OMX_HANDLETYPE aComponent, 3650 OMX_OUT OMX_PTR aAppData, 3651 OMX_OUT OMX_BUFFERHEADERTYPE* aBuffer) 3652 { 3653 OSCL_UNUSED_ARG(aComponent); 3654 OSCL_UNUSED_ARG(aAppData); 3655 3656 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3657 (0, "%s::EmptyBufferDoneProcessing: In", iName.Str())); 3658 3659 OSCL_ASSERT((void*) aComponent == (void*) iOMXDecoder); // component should match the component 3660 OSCL_ASSERT(aAppData == (OMX_PTR)(this)); // AppData should represent this node ptr 3661 3662 // first, get the buffer "context", i.e. pointer to application private data that contains the 3663 // address of the mempool buffer (so that it can be released) 3664 InputBufCtrlStruct *pContext = (InputBufCtrlStruct *)(aBuffer->pAppPrivate); 3665 3666 3667 3668 // if a buffer is not empty, log a msg, but release anyway 3669 if ((aBuffer->nFilledLen > 0) && (iDoNotSaveInputBuffersFlag == false)) 3670 // if dynamic port reconfig is in progress for input port, don't keep the buffer 3671 { 3672 3673 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3674 (0, "%s::EmptyBufferDoneProcessing: Input buffer returned non-empty with %d bytes still in it", iName.Str(), aBuffer->nFilledLen)); 3675 3676 3677 } 3678 3679 3680 iInputBufferToResendToComponent = NULL; 3681 3682 // input buffer is to be released, 3683 // refcount needs to be decremented (possibly - the input msg associated with the buffer will be unbound) 3684 // NOTE: in case of "moveable" input buffers (passed into component without copying), unbinding decrements a refcount which eventually results 3685 // in input message being released back to upstream mempool once all its fragments are returned 3686 // in case of input buffers passed into component by copying, unbinding has no effect 3687 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3688 (0, "%s::EmptyBufferDoneProcessing: Release input buffer with Ticks=%d (with %d refcount remaining of input message)", iName.Str(), aBuffer->nTimeStamp, (pContext->pMediaData).get_count() - 1)); 3689 3690 3691 (pContext->pMediaData).Unbind(); 3692 3693 3694 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3695 (0, "%s::EmptyBufferDoneProcessing: Release input buffer %x back to mempool - pointing to buffer %x", iName.Str(), pContext, aBuffer->pBuffer)); 3696 3697 iInBufMemoryPool->deallocate((OsclAny *) pContext); 3698 3699 3700 // the OMX spec says that no error is to be returned 3701 return OMX_ErrorNone; 3702 3703 } 3704 3705 3706 3707 ///////////////////////////////////////////////////////////////////////////// 3708 ////////////////////// CALLBACK PROCESSING FOR FILL BUFFER DONE - output buffer is ready 3709 ///////////////////////////////////////////////////////////////////////////// 3710 OMX_ERRORTYPE PVMFOMXBaseDecNode::FillBufferDoneProcessing(OMX_OUT OMX_HANDLETYPE aComponent, 3711 OMX_OUT OMX_PTR aAppData, 3712 OMX_OUT OMX_BUFFERHEADERTYPE* aBuffer) 3713 { 3714 OSCL_UNUSED_ARG(aComponent); 3715 OSCL_UNUSED_ARG(aAppData); 3716 3717 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3718 (0, "%s::FillBufferDoneProcessing: In", iName.Str())); 3719 3720 OSCL_ASSERT((void*) aComponent == (void*) iOMXDecoder); // component should match the component 3721 OSCL_ASSERT(aAppData == (OMX_PTR)(this)); // AppData should represent this node ptr 3722 3723 // first, get the buffer "context", i.e. pointer to application private data that contains the 3724 // address of the mempool buffer (so that it can be released) 3725 OsclAny *pContext = (OsclAny*) aBuffer->pAppPrivate; 3726 3727 3728 // check for EOS flag 3729 if ((aBuffer->nFlags & OMX_BUFFERFLAG_EOS)) 3730 { 3731 // EOS received - enable sending EOS msg 3732 iIsEOSReceivedFromComponent = true; 3733 3734 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3735 (0, "%s::FillBufferDoneProcessing: Output buffer has EOS set", iName.Str())); 3736 3737 } 3738 3739 // if a buffer is empty, or if it should not be sent downstream (say, due to state change) 3740 // release the buffer back to the pool 3741 if ((aBuffer->nFilledLen == 0) || (iDoNotSendOutputBuffersDownstreamFlag == true)) 3742 { 3743 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3744 (0, "%s::FillBufferDoneProcessing: Release output buffer %x back to mempool - buffer empty or not to be sent downstream", iName.Str(), pContext)); 3745 3746 iOutBufMemoryPool->deallocate(pContext); 3747 3748 } 3749 else 3750 { 3751 3752 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3753 (0, "%s::FillBufferDoneProcessing: Output frame %d received", iName.Str(), iFrameCounter++)); 3754 3755 // get pointer to actual buffer data 3756 uint8 *pBufdata = ((uint8*) aBuffer->pBuffer); 3757 // move the data pointer based on offset info 3758 pBufdata += aBuffer->nOffset; 3759 3760 iOutTimeStamp = ConvertOMXTicksIntoTimestamp(aBuffer->nTimeStamp); 3761 3762 ipPrivateData = (OsclAny *) aBuffer->pPlatformPrivate; // record the pointer 3763 3764 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3765 (0, "%s::FillBufferDoneProcessing: Wrapping buffer %x of size %d", iName.Str(), pBufdata, aBuffer->nFilledLen)); 3766 // wrap the buffer into the MediaDataImpl wrapper, and queue it for sending downstream 3767 // wrapping will create a refcounter. When refcounter goes to 0 i.e. when media data 3768 // is released in downstream components, the custom deallocator will automatically release the buffer back to the 3769 // mempool. To do that, the deallocator needs to have info about Context 3770 // NOTE: we had to wait until now to wrap the buffer data because we only know 3771 // now where the actual data is located (based on buffer offset) 3772 OsclSharedPtr<PVMFMediaDataImpl> MediaDataOut = WrapOutputBuffer(pBufdata, (uint32)(aBuffer->nFilledLen), pContext); 3773 3774 // if you can't get the MediaDataOut, release the buffer back to the pool 3775 if (MediaDataOut.GetRep() == NULL) 3776 { 3777 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3778 (0, "%s::FillBufferDoneProcessing: Problem wrapping buffer %x of size %d - releasing the buffer", iName.Str(), pBufdata, aBuffer->nFilledLen)); 3779 3780 iOutBufMemoryPool->deallocate(pContext); 3781 } 3782 else 3783 { 3784 3785 // if there's a problem queuing output buffer, MediaDataOut will expire at end of scope and 3786 // release buffer back to the pool, (this should not be the case) 3787 if (QueueOutputBuffer(MediaDataOut, aBuffer->nFilledLen)) 3788 { 3789 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3790 (0, "%s::FillBufferDoneProcessing: Buffer %x of size %d queued - reschedule the node to send out", iName.Str(), pBufdata, aBuffer->nFilledLen)); 3791 3792 // if queing went OK, 3793 // re-schedule the node so that outgoing queue can be emptied (unless the outgoing port is busy) 3794 if ((iOutPort) && !(iOutPort->IsConnectedPortBusy())) 3795 RunIfNotReady(); 3796 } 3797 else 3798 { 3799 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3800 (0, "%s::FillBufferDoneProcessing: Problem queing buffer %x of size %d - releasing the buffer", iName.Str(), pBufdata, aBuffer->nFilledLen)); 3801 } 3802 3803 3804 } 3805 3806 } 3807 // the OMX spec says that no error is to be returned 3808 return OMX_ErrorNone; 3809 3810 } 3811 3812 ////////////////////////////////////////////////////////////////////////////////////////////// 3813 ///////////////////////////// Attach a MediaDataImpl wrapper (refcount, deallocator etc.) 3814 /////////////////////////////// to the output buffer ///////////////////////////////////////// 3815 OsclSharedPtr<PVMFMediaDataImpl> PVMFOMXBaseDecNode::WrapOutputBuffer(uint8 *pData, uint32 aDataLen, OsclAny *pContext) 3816 { 3817 // wrap output buffer into a mediadataimpl 3818 uint32 aligned_class_size = oscl_mem_aligned_size(sizeof(PVMFSimpleMediaBuffer)); 3819 uint32 aligned_cleanup_size = oscl_mem_aligned_size(sizeof(PVOMXDecBufferSharedPtrWrapperCombinedCleanupDA)); 3820 uint32 aligned_refcnt_size = oscl_mem_aligned_size(sizeof(OsclRefCounterDA)); 3821 uint8 *my_ptr = (uint8*) oscl_malloc(aligned_refcnt_size + aligned_cleanup_size + aligned_class_size); 3822 3823 if (my_ptr == NULL) 3824 { 3825 OsclSharedPtr<PVMFMediaDataImpl> null_buff(NULL, NULL); 3826 return null_buff; 3827 } 3828 // create a deallocator and pass the buffer_allocator to it as well as pointer to data that needs to be returned to the mempool 3829 PVOMXDecBufferSharedPtrWrapperCombinedCleanupDA *cleanup_ptr = 3830 OSCL_PLACEMENT_NEW(my_ptr + aligned_refcnt_size, PVOMXDecBufferSharedPtrWrapperCombinedCleanupDA(iOutBufMemoryPool, pContext)); 3831 3832 //ModifiedPvciBufferCombinedCleanup* cleanup_ptr = OSCL_PLACEMENT_NEW(my_ptr + aligned_refcnt_size,ModifiedPvciBufferCombinedCleanup(aOutput.GetRefCounter()) ); 3833 3834 // create the ref counter after the cleanup object (refcount is set to 1 at creation) 3835 OsclRefCounterDA *my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterDA(my_ptr, cleanup_ptr)); 3836 3837 my_ptr += aligned_refcnt_size + aligned_cleanup_size; 3838 3839 PVMFMediaDataImpl* media_data_ptr = OSCL_PLACEMENT_NEW(my_ptr, PVMFSimpleMediaBuffer((void *) pData, // ptr to data 3840 aDataLen, // capacity 3841 my_refcnt)); // ref counter 3842 3843 OsclSharedPtr<PVMFMediaDataImpl> MediaDataImplOut(media_data_ptr, my_refcnt); 3844 3845 MediaDataImplOut->setMediaFragFilledLen(0, aDataLen); 3846 3847 return MediaDataImplOut; 3848 3849 } 3850 ////////////////////////////////////////////////////////////////////////////// 3851 bool PVMFOMXBaseDecNode::SendBeginOfMediaStreamCommand() 3852 { 3853 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3854 (0, "%s::SendBeginOfMediaStreamCommand() In", iName.Str())); 3855 3856 PVMFSharedMediaCmdPtr sharedMediaCmdPtr = PVMFMediaCmd::createMediaCmd(); 3857 // Set the formatID, timestamp, sequenceNumber and streamID for the media message 3858 sharedMediaCmdPtr->setFormatID(PVMF_MEDIA_CMD_BOS_FORMAT_ID); 3859 sharedMediaCmdPtr->setTimestamp(iBOSTimestamp); 3860 //reset the sequence number 3861 uint32 seqNum = 0; 3862 sharedMediaCmdPtr->setSeqNum(seqNum); 3863 sharedMediaCmdPtr->setStreamID(iStreamID); 3864 3865 PVMFSharedMediaMsgPtr mediaMsgOut; 3866 convertToPVMFMediaCmdMsg(mediaMsgOut, sharedMediaCmdPtr); 3867 if (iOutPort->QueueOutgoingMsg(mediaMsgOut) != PVMFSuccess) 3868 { 3869 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3870 (0, "%s::SendBeginOfMediaStreamCommand() Outgoing queue busy", iName.Str())); 3871 return false; 3872 } 3873 3874 iSendBOS = false; 3875 3876 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3877 (0, "%s::SendBeginOfMediaStreamCommand() BOS Sent StreamID %d", iName.Str(), iStreamID)); 3878 return true; 3879 } 3880 //////////////////////////////////// 3881 bool PVMFOMXBaseDecNode::SendEndOfTrackCommand(void) 3882 { 3883 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3884 (0, "%s::SendEndOfTrackCommand() In", iName.Str())); 3885 3886 PVMFSharedMediaCmdPtr sharedMediaCmdPtr = PVMFMediaCmd::createMediaCmd(); 3887 3888 sharedMediaCmdPtr->setFormatID(PVMF_MEDIA_CMD_EOS_FORMAT_ID); 3889 3890 // Set the timestamp 3891 sharedMediaCmdPtr->setTimestamp(iEndOfDataTimestamp); 3892 3893 // Set Streamid 3894 sharedMediaCmdPtr->setStreamID(iStreamID); 3895 3896 // Set the sequence number 3897 sharedMediaCmdPtr->setSeqNum(iSeqNum++); 3898 3899 PVMFSharedMediaMsgPtr mediaMsgOut; 3900 convertToPVMFMediaCmdMsg(mediaMsgOut, sharedMediaCmdPtr); 3901 if (iOutPort->QueueOutgoingMsg(mediaMsgOut) != PVMFSuccess) 3902 { 3903 // this should not happen because we check for queue busy before calling this function 3904 return false; 3905 } 3906 3907 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3908 (0, "%s::SendEndOfTrackCommand() Out", iName.Str())); 3909 return true; 3910 } 3911 3912 ///////////////////////////////////////////////////////////////////////////// 3913 //The various command handlers call this routine when a command is complete. 3914 ///////////////////////////////////////////////////////////////////////////// 3915 OSCL_EXPORT_REF void PVMFOMXBaseDecNode::CommandComplete(PVMFOMXBaseDecNodeCmdQ& aCmdQ, PVMFOMXBaseDecNodeCommand& aCmd, PVMFStatus aStatus, OsclAny* aEventData) 3916 { 3917 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s:CommandComplete Id %d Cmd %d Status %d Context %d Data %d", 3918 iName.Str(), aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData)); 3919 3920 //create response 3921 PVMFCmdResp resp(aCmd.iId, aCmd.iContext, aStatus, aEventData); 3922 PVMFSessionId session = aCmd.iSession; 3923 3924 //Erase the command from the queue. 3925 aCmdQ.Erase(&aCmd); 3926 3927 //Report completion to the session observer. 3928 ReportCmdCompleteEvent(session, resp); 3929 } 3930 3931 ///////////////////////////////////////////////////////////////////////////// 3932 void PVMFOMXBaseDecNode::DoInit(PVMFOMXBaseDecNodeCommand& aCmd) 3933 { 3934 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::DoInit() In", iName.Str())); 3935 switch (iInterfaceState) 3936 { 3937 case EPVMFNodeIdle: 3938 { 3939 SetState(EPVMFNodeInitialized); 3940 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 3941 break; 3942 } 3943 3944 default: 3945 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 3946 break; 3947 } 3948 } 3949 3950 ///////////////////////////////////////////////////////////////////////////// 3951 void PVMFOMXBaseDecNode::DoPrepare(PVMFOMXBaseDecNodeCommand& aCmd) 3952 { 3953 OMX_ERRORTYPE err = OMX_ErrorNone; 3954 OMXConfigParserInputs aInputParameters; 3955 aInputParameters.cComponentRole = NULL; 3956 OMX_PTR aOutputParameters = NULL; 3957 3958 switch (iInterfaceState) 3959 { 3960 case EPVMFNodeInitialized: 3961 { 3962 if (NULL == iInPort) 3963 { 3964 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "%s::DoPrepare() Input port not initialized", iName.Str())); 3965 CommandComplete(iInputCommands, aCmd, PVMFFailure); 3966 return; 3967 } 3968 3969 // Check format of input data 3970 PVMFFormatType format = ((PVMFOMXDecPort*)iInPort)->iFormat; 3971 // AAC 3972 if (format == PVMF_MIME_MPEG4_AUDIO || 3973 format == PVMF_MIME_3640 || 3974 format == PVMF_MIME_LATM || 3975 format == PVMF_MIME_ADIF || 3976 format == PVMF_MIME_ASF_MPEG4_AUDIO || 3977 format == PVMF_MIME_AAC_SIZEHDR) 3978 { 3979 aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.aac"; 3980 aOutputParameters = (AudioOMXConfigParserOutputs *)oscl_malloc(sizeof(AudioOMXConfigParserOutputs)); 3981 } 3982 // AMR 3983 else if (format == PVMF_MIME_AMR_IF2 || 3984 format == PVMF_MIME_AMR_IETF || 3985 format == PVMF_MIME_AMR) 3986 { 3987 aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.amrnb"; 3988 aOutputParameters = (AudioOMXConfigParserOutputs *)oscl_malloc(sizeof(AudioOMXConfigParserOutputs)); 3989 } 3990 else if (format == PVMF_MIME_AMRWB_IETF || 3991 format == PVMF_MIME_AMRWB) 3992 { 3993 aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.amrwb"; 3994 aOutputParameters = (AudioOMXConfigParserOutputs *)oscl_malloc(sizeof(AudioOMXConfigParserOutputs)); 3995 } 3996 else if (format == PVMF_MIME_MP3) 3997 { 3998 aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.mp3"; 3999 aOutputParameters = (AudioOMXConfigParserOutputs *)oscl_malloc(sizeof(AudioOMXConfigParserOutputs)); 4000 } 4001 else if (format == PVMF_MIME_WMA) 4002 { 4003 aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.wma"; 4004 aOutputParameters = (AudioOMXConfigParserOutputs *)oscl_malloc(sizeof(AudioOMXConfigParserOutputs)); 4005 } 4006 else if (format == PVMF_MIME_H264_VIDEO || 4007 format == PVMF_MIME_H264_VIDEO_MP4 || 4008 format == PVMF_MIME_H264_VIDEO_RAW) 4009 { 4010 aInputParameters.cComponentRole = (OMX_STRING)"video_decoder.avc"; 4011 aOutputParameters = (VideoOMXConfigParserOutputs *)oscl_malloc(sizeof(VideoOMXConfigParserOutputs)); 4012 } 4013 else if (format == PVMF_MIME_M4V) 4014 { 4015 aInputParameters.cComponentRole = (OMX_STRING)"video_decoder.mpeg4"; 4016 aOutputParameters = (VideoOMXConfigParserOutputs *)oscl_malloc(sizeof(VideoOMXConfigParserOutputs)); 4017 } 4018 else if (format == PVMF_MIME_H2631998 || 4019 format == PVMF_MIME_H2632000) 4020 { 4021 aInputParameters.cComponentRole = (OMX_STRING)"video_decoder.h263"; 4022 aOutputParameters = (VideoOMXConfigParserOutputs *)oscl_malloc(sizeof(VideoOMXConfigParserOutputs)); 4023 } 4024 else if (format == PVMF_MIME_WMV) 4025 { 4026 aInputParameters.cComponentRole = (OMX_STRING)"video_decoder.wmv"; 4027 aOutputParameters = (VideoOMXConfigParserOutputs *)oscl_malloc(sizeof(VideoOMXConfigParserOutputs)); 4028 } 4029 else 4030 { 4031 // Illegal codec specified. 4032 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "%s::DoPrepare() Input port format other then codec type", iName.Str())); 4033 CommandComplete(iInputCommands, aCmd, PVMFErrArgument); 4034 return; 4035 } 4036 if (aOutputParameters == NULL) 4037 { 4038 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4039 (0, "%s::Can't allocate memory for OMXConfigParser output!", iName.Str())); 4040 CommandComplete(iInputCommands, aCmd, PVMFErrResource); 4041 return; 4042 } 4043 4044 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_DEBUG, 4045 (0, "%s::Initializing OMX component and decoder for role %s", iName.Str(), aInputParameters.cComponentRole)); 4046 4047 /* Set callback structure */ 4048 iCallbacks.EventHandler = CallbackEventHandler; //event_handler; 4049 iCallbacks.EmptyBufferDone = CallbackEmptyBufferDone; //empty_buffer_done; 4050 iCallbacks.FillBufferDone = CallbackFillBufferDone; //fill_buffer_done; 4051 4052 4053 // determine components which can fit the role 4054 // then, create the component. If multiple components fit the role, 4055 // the first one registered will be selected. If that one fails to 4056 // be created, the second one in the list is selected etc. 4057 OMX_BOOL status; 4058 OMX_U32 num_comps = 0; 4059 OMX_STRING *CompOfRole; 4060 OMX_S8 CompName[PV_OMX_MAX_COMPONENT_NAME_LENGTH]; 4061 4062 //AudioOMXConfigParserOutputs aOutputParameters; 4063 aInputParameters.inPtr = (uint8*)((PVMFOMXDecPort*)iInPort)->iTrackConfig; 4064 aInputParameters.inBytes = (int32)((PVMFOMXDecPort*)iInPort)->iTrackConfigSize; 4065 4066 if (aInputParameters.inBytes == 0 || aInputParameters.inPtr == NULL) 4067 { 4068 if (format == PVMF_MIME_WMA || 4069 format == PVMF_MIME_MPEG4_AUDIO || 4070 format == PVMF_MIME_3640 || 4071 format == PVMF_MIME_LATM || 4072 format == PVMF_MIME_ADIF || 4073 format == PVMF_MIME_ASF_MPEG4_AUDIO || 4074 format == PVMF_MIME_AAC_SIZEHDR) 4075 { 4076 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4077 (0, "%s::DoPrepare() Cannot get component parameters", iName.Str())); 4078 oscl_free(aOutputParameters); 4079 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources); 4080 return; 4081 4082 } 4083 } 4084 // call once to find out the number of components that can fit the role 4085 OMX_MasterGetComponentsOfRole(aInputParameters.cComponentRole, &num_comps, NULL); 4086 uint32 ii; 4087 4088 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 4089 (0, "%s::DoPrepare(): There are %d components of role %s ", iName.Str(), num_comps, aInputParameters.cComponentRole)); 4090 4091 if (num_comps > 0) 4092 { 4093 CompOfRole = (OMX_STRING *)oscl_malloc(num_comps * sizeof(OMX_STRING)); 4094 4095 for (ii = 0; ii < num_comps; ii++) 4096 CompOfRole[ii] = (OMX_STRING) oscl_malloc(PV_OMX_MAX_COMPONENT_NAME_LENGTH * sizeof(OMX_U8)); 4097 4098 // call 2nd time to get the component names 4099 OMX_MasterGetComponentsOfRole(aInputParameters.cComponentRole, &num_comps, (OMX_U8 **)CompOfRole); 4100 4101 for (ii = 0; ii < num_comps; ii++) 4102 { 4103 aInputParameters.cComponentName = CompOfRole[ii]; 4104 status = OMX_MasterConfigParser(&aInputParameters, aOutputParameters); 4105 if (status == OMX_TRUE) 4106 { 4107 // but also needs to valid long enough to use it when getting the number of roles later on 4108 oscl_strncpy((OMX_STRING)CompName, (OMX_STRING) CompOfRole[ii], PV_OMX_MAX_COMPONENT_NAME_LENGTH); 4109 //JJDBG 4110 #if 0 4111 if ((0 == oscl_strncmp(aInputParameters.cComponentName, "OMX.qcom.video.decoder.mpeg4", PV_OMX_MAX_COMPONENT_NAME_LENGTH)) 4112 || (0 == oscl_strncmp(aInputParameters.cComponentName, "OMX.qcom.video.decoder.h263", PV_OMX_MAX_COMPONENT_NAME_LENGTH))) 4113 { 4114 LOGE("%s::DoPrepare(): Cannot get component %s handle, try another component if available", iName.Str(), aInputParameters.cComponentName); 4115 continue; 4116 //err = OMX_ErrorUndefined ; 4117 } 4118 else 4119 #endif 4120 // try to create component 4121 err = OMX_MasterGetHandle(&iOMXDecoder, (OMX_STRING) aInputParameters.cComponentName, (OMX_PTR) this, (OMX_CALLBACKTYPE *) & iCallbacks, bHWAccelerated); 4122 // if successful, no need to continue 4123 if ((err == OMX_ErrorNone) && (iOMXDecoder != NULL)) 4124 { 4125 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 4126 (0, "%s::DoPrepare(): Got Component %s handle ", iName.Str(), aInputParameters.cComponentName)); 4127 break; 4128 } 4129 else 4130 { 4131 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 4132 (0, "%s::DoPrepare(): Cannot get component %s handle, try another component if available", iName.Str(), aInputParameters.cComponentName)); 4133 } 4134 } 4135 else 4136 { 4137 status = OMX_FALSE; 4138 } 4139 4140 4141 } 4142 // whether successful or not, need to free CompOfRoles 4143 for (ii = 0; ii < num_comps; ii++) 4144 { 4145 oscl_free(CompOfRole[ii]); 4146 CompOfRole[ii] = NULL; 4147 } 4148 4149 oscl_free(CompOfRole); 4150 4151 // check if there was a problem 4152 if ((err != OMX_ErrorNone) || (iOMXDecoder == NULL)) 4153 { 4154 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4155 (0, "%s::Can't get handle for decoder!", iName.Str())); 4156 iOMXDecoder = NULL; 4157 oscl_free(aOutputParameters); 4158 CommandComplete(iInputCommands, aCmd, PVMFErrResource); 4159 return; 4160 } 4161 } 4162 else 4163 { 4164 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4165 (0, "%s::No component can handle role %s !", iName.Str(), aInputParameters.cComponentRole)); 4166 iOMXDecoder = NULL; 4167 oscl_free(aOutputParameters); 4168 CommandComplete(iInputCommands, aCmd, PVMFErrResource); 4169 return; 4170 } 4171 4172 4173 4174 if (!iOMXDecoder) 4175 { 4176 oscl_free(aOutputParameters); 4177 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources); 4178 return; 4179 } 4180 4181 // find out how many roles the component supports 4182 OMX_U32 NumRoles; 4183 err = OMX_MasterGetRolesOfComponent((OMX_STRING)CompName, &NumRoles, NULL); 4184 if (err != OMX_ErrorNone) 4185 { 4186 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4187 (0, "%s::DoPrepare() Problem getting component roles", iName.Str())); 4188 4189 CommandComplete(iInputCommands, aCmd, PVMFErrResource); 4190 return; 4191 } 4192 4193 // if the component supports multiple roles, call OMX_SetParameter 4194 if (NumRoles > 1) 4195 { 4196 OMX_PARAM_COMPONENTROLETYPE RoleParam; 4197 CONFIG_SIZE_AND_VERSION(RoleParam); 4198 oscl_strncpy((OMX_STRING)RoleParam.cRole, (OMX_STRING)aInputParameters.cComponentRole, OMX_MAX_STRINGNAME_SIZE); 4199 err = OMX_SetParameter(iOMXDecoder, OMX_IndexParamStandardComponentRole, &RoleParam); 4200 if (err != OMX_ErrorNone) 4201 { 4202 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4203 (0, "%s::DoPrepare() Problem setting component role", iName.Str())); 4204 4205 #if 0 //QCOM WORKAROUND JJDBG 4206 CommandComplete(iInputCommands, aCmd, PVMFErrResource); 4207 return; 4208 #endif 4209 } 4210 } 4211 4212 // GET CAPABILITY FLAGS FROM PV COMPONENT, IF this fails, use defaults 4213 PV_OMXComponentCapabilityFlagsType Cap_flags; 4214 err = OMX_GetParameter(iOMXDecoder, (OMX_INDEXTYPE) PV_OMX_COMPONENT_CAPABILITY_TYPE_INDEX, &Cap_flags); 4215 if (err != OMX_ErrorNone) 4216 { 4217 SetDefaultCapabilityFlags(); 4218 } 4219 else 4220 { 4221 iIsOMXComponentMultiThreaded = (OMX_TRUE == Cap_flags.iIsOMXComponentMultiThreaded) ? true : false; 4222 iOMXComponentSupportsExternalInputBufferAlloc = (OMX_TRUE == Cap_flags.iOMXComponentSupportsExternalInputBufferAlloc) ? true : false; 4223 iOMXComponentSupportsExternalOutputBufferAlloc = (OMX_TRUE == Cap_flags.iOMXComponentSupportsExternalOutputBufferAlloc) ? true : false; 4224 iOMXComponentSupportsMovableInputBuffers = (OMX_TRUE == Cap_flags.iOMXComponentSupportsMovableInputBuffers) ? true : false; 4225 iOMXComponentSupportsPartialFrames = (OMX_TRUE == Cap_flags.iOMXComponentSupportsPartialFrames) ? true : false; 4226 iOMXComponentUsesNALStartCodes = (OMX_TRUE == Cap_flags.iOMXComponentUsesNALStartCodes) ? true : false; 4227 iOMXComponentCanHandleIncompleteFrames = (OMX_TRUE == Cap_flags.iOMXComponentCanHandleIncompleteFrames) ? true : false; 4228 iOMXComponentUsesFullAVCFrames = (OMX_TRUE == Cap_flags.iOMXComponentUsesFullAVCFrames) ? true : false; 4229 } 4230 4231 // do some sanity checking 4232 4233 if ((format != PVMF_MIME_H264_VIDEO) && (format != PVMF_MIME_H264_VIDEO_MP4) && (format != PVMF_MIME_H264_VIDEO_RAW)) 4234 { 4235 iOMXComponentUsesNALStartCodes = false; 4236 iOMXComponentUsesFullAVCFrames = false; 4237 } 4238 4239 if (iOMXComponentUsesFullAVCFrames) 4240 { 4241 iNALCount = 0; 4242 oscl_memset(iNALSizeArray, 0, sizeof(uint32) * MAX_NAL_PER_FRAME); // 100 is max number of NALs 4243 } 4244 4245 // make sure that copying is used where necessary 4246 if (!iOMXComponentSupportsPartialFrames || iOMXComponentUsesNALStartCodes || iOMXComponentUsesFullAVCFrames) 4247 { 4248 iOMXComponentSupportsMovableInputBuffers = false; 4249 } 4250 4251 // find out about parameters 4252 4253 if (!NegotiateComponentParameters(aOutputParameters)) 4254 { 4255 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4256 (0, "%s::DoPrepare() Cannot get component parameters", iName.Str())); 4257 4258 oscl_free(aOutputParameters); 4259 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources); 4260 return; 4261 } 4262 oscl_free(aOutputParameters); 4263 4264 // create active objects to handle callbacks in case of multithreaded implementation 4265 4266 // NOTE: CREATE THE THREADSAFE CALLBACK AOs REGARDLESS OF WHETHER MULTITHREADED COMPONENT OR NOT 4267 // If it is not multithreaded, we won't use them 4268 // The Flag iIsComponentMultiThreaded decides which mechanism is used for callbacks. 4269 // This flag is set by looking at component capabilities (or to true by default) 4270 4271 if (iThreadSafeHandlerEventHandler) 4272 { 4273 OSCL_DELETE(iThreadSafeHandlerEventHandler); 4274 iThreadSafeHandlerEventHandler = NULL; 4275 } 4276 // substitute default parameters: observer(this node),queuedepth(3),nameAO for logging 4277 // Get the priority of the dec node, and set the threadsafe callback AO priority to 1 higher 4278 iThreadSafeHandlerEventHandler = OSCL_NEW(EventHandlerThreadSafeCallbackAO, (this, 10, "EventHandlerAO", Priority() + 2)); 4279 4280 if (iThreadSafeHandlerEmptyBufferDone) 4281 { 4282 OSCL_DELETE(iThreadSafeHandlerEmptyBufferDone); 4283 iThreadSafeHandlerEmptyBufferDone = NULL; 4284 } 4285 // use queue depth of iNumInputBuffers to prevent deadlock 4286 iThreadSafeHandlerEmptyBufferDone = OSCL_NEW(EmptyBufferDoneThreadSafeCallbackAO, (this, iNumInputBuffers, "EmptyBufferDoneAO", Priority() + 1)); 4287 4288 if (iThreadSafeHandlerFillBufferDone) 4289 { 4290 OSCL_DELETE(iThreadSafeHandlerFillBufferDone); 4291 iThreadSafeHandlerFillBufferDone = NULL; 4292 } 4293 // use queue depth of iNumOutputBuffers to prevent deadlock 4294 iThreadSafeHandlerFillBufferDone = OSCL_NEW(FillBufferDoneThreadSafeCallbackAO, (this, iNumOutputBuffers, "FillBufferDoneAO", Priority() + 1)); 4295 4296 if ((iThreadSafeHandlerEventHandler == NULL) || 4297 (iThreadSafeHandlerEmptyBufferDone == NULL) || 4298 (iThreadSafeHandlerFillBufferDone == NULL) 4299 ) 4300 { 4301 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4302 (0, "%s::Can't get threadsafe callbacks for decoder!", iName.Str())); 4303 iOMXDecoder = NULL; 4304 } 4305 4306 // ONLY FOR AVC FILE PLAYBACK WILL 1 FRAGMENT CONTAIN ONE FULL NAL 4307 if ((format == PVMF_MIME_H264_VIDEO) || (format == PVMF_MIME_H264_VIDEO_MP4)) 4308 { 4309 // every memory fragment in case of AVC is a full NAL 4310 iSetMarkerBitForEveryFrag = true; 4311 } 4312 else 4313 { 4314 iSetMarkerBitForEveryFrag = false; 4315 } 4316 4317 4318 // Init Decoder 4319 iCurrentDecoderState = OMX_StateLoaded; 4320 4321 /* Change state to OMX_StateIdle from OMX_StateLoaded. */ 4322 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 4323 (0, "%s::DoPrepare(): Changing Component state Loaded -> Idle ", iName.Str())); 4324 4325 err = OMX_SendCommand(iOMXDecoder, OMX_CommandStateSet, OMX_StateIdle, NULL); 4326 if (err != OMX_ErrorNone) 4327 { 4328 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4329 (0, "%s::DoPrepare() Can't send StateSet command!", iName.Str())); 4330 4331 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources); 4332 return; 4333 } 4334 4335 4336 /* Allocate input buffers */ 4337 if (!CreateInputMemPool(iNumInputBuffers)) 4338 { 4339 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4340 (0, "%s::DoPrepare() Can't allocate mempool for input buffers!", iName.Str())); 4341 4342 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources); 4343 return; 4344 } 4345 4346 in_ctrl_struct_ptr = NULL; 4347 in_buff_hdr_ptr = NULL; 4348 4349 in_ctrl_struct_ptr = (OsclAny **) oscl_malloc(iNumInputBuffers * sizeof(OsclAny *)); 4350 4351 if (in_ctrl_struct_ptr == NULL) 4352 { 4353 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4354 (0, "%s::DoPrepare() in_ctrl_struct_ptr == NULL")); 4355 4356 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources); 4357 return ; 4358 } 4359 4360 in_buff_hdr_ptr = (OsclAny **) oscl_malloc(iNumInputBuffers * sizeof(OsclAny *)); 4361 4362 if (in_buff_hdr_ptr == NULL) 4363 { 4364 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4365 (0, "%s::DoPrepare() in_buff_hdr_ptr == NULL")); 4366 4367 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources); 4368 return ; 4369 } 4370 4371 if (!ProvideBuffersToComponent(iInBufMemoryPool, // allocator 4372 iInputAllocSize, // size to allocate from pool (hdr only or hdr+ buffer) 4373 iNumInputBuffers, // number of buffers 4374 iOMXComponentInputBufferSize, // actual buffer size 4375 iInputPortIndex, // port idx 4376 iOMXComponentSupportsExternalInputBufferAlloc, // can component use OMX_UseBuffer 4377 true // this is input 4378 )) 4379 { 4380 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4381 (0, "%s::DoPrepare() Component can't use input buffers!", iName.Str())); 4382 4383 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources); 4384 return; 4385 } 4386 4387 4388 /* Allocate output buffers */ 4389 if (!CreateOutMemPool(iNumOutputBuffers)) 4390 { 4391 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4392 (0, "%s::DoPrepare() Can't allocate mempool for output buffers!", iName.Str())); 4393 4394 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources); 4395 return; 4396 } 4397 4398 out_ctrl_struct_ptr = NULL; 4399 out_buff_hdr_ptr = NULL; 4400 4401 out_ctrl_struct_ptr = (OsclAny **) oscl_malloc(iNumOutputBuffers * sizeof(OsclAny *)); 4402 4403 if (out_ctrl_struct_ptr == NULL) 4404 { 4405 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4406 (0, "%s::DoPrepare() out_ctrl_struct_ptr == NULL")); 4407 4408 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources); 4409 return ; 4410 } 4411 4412 out_buff_hdr_ptr = (OsclAny **) oscl_malloc(iNumOutputBuffers * sizeof(OsclAny *)); 4413 4414 if (out_buff_hdr_ptr == NULL) 4415 { 4416 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4417 (0, "%s::DoPrepare() out_buff_hdr_ptr == NULL")); 4418 4419 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources); 4420 return ; 4421 } 4422 4423 4424 if (!ProvideBuffersToComponent(iOutBufMemoryPool, // allocator 4425 iOutputAllocSize, // size to allocate from pool (hdr only or hdr+ buffer) 4426 iNumOutputBuffers, // number of buffers 4427 iOMXComponentOutputBufferSize, // actual buffer size 4428 iOutputPortIndex, // port idx 4429 iOMXComponentSupportsExternalOutputBufferAlloc, // can component use OMX_UseBuffer 4430 false // this is not input 4431 )) 4432 { 4433 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4434 (0, "%s::DoPrepare() Component can't use output buffers!", iName.Str())); 4435 4436 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources); 4437 return; 4438 } 4439 4440 4441 //this command is asynchronous. move the command from 4442 //the input command queue to the current command, where 4443 //it will remain until it completes. We have to wait for 4444 // OMX component state transition to complete 4445 4446 int32 err; 4447 OSCL_TRY(err, iCurrentCommand.StoreL(aCmd);); 4448 if (err != OsclErrNone) 4449 { 4450 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory); 4451 return; 4452 } 4453 iInputCommands.Erase(&aCmd); 4454 4455 } 4456 break; 4457 case EPVMFNodePrepared: 4458 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 4459 break; 4460 default: 4461 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 4462 break; 4463 } 4464 4465 } 4466 4467 ///////////////////////////////////////////////////////////////////////////// 4468 void PVMFOMXBaseDecNode::DoStart(PVMFOMXBaseDecNodeCommand& aCmd) 4469 { 4470 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::DoStart() In", iName.Str())); 4471 4472 iDiagnosticsLogged = false; 4473 4474 PVMFStatus status = PVMFSuccess; 4475 4476 OMX_ERRORTYPE err; 4477 OMX_STATETYPE sState; 4478 4479 switch (iInterfaceState) 4480 { 4481 case EPVMFNodePrepared: 4482 case EPVMFNodePaused: 4483 { 4484 //Get state of OpenMAX decoder 4485 err = OMX_GetState(iOMXDecoder, &sState); 4486 if (err != OMX_ErrorNone) 4487 { 4488 //Error condition report 4489 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4490 4491 (0, "%s::DoStart(): Can't get State of decoder!", iName.Str())); 4492 4493 sState = OMX_StateInvalid; 4494 } 4495 4496 if ((sState == OMX_StateIdle) || (sState == OMX_StatePause)) 4497 { 4498 /* Change state to OMX_StateExecuting form OMX_StateIdle. */ 4499 // init the flag 4500 if (!iDynamicReconfigInProgress) 4501 { 4502 4503 iDoNotSendOutputBuffersDownstreamFlag = false; // or if output was not being sent downstream due to state changes 4504 // re-anable sending output 4505 4506 iDoNotSaveInputBuffersFlag = false; 4507 4508 } 4509 4510 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4511 (0, "%s::DoStart() Changing Component state Idle->Executing", iName.Str())); 4512 4513 err = OMX_SendCommand(iOMXDecoder, OMX_CommandStateSet, OMX_StateExecuting, NULL); 4514 if (err != OMX_ErrorNone) 4515 { 4516 //Error condition report 4517 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4518 (0, "%s::DoStart(): Can't send StateSet command to decoder!", iName.Str())); 4519 4520 status = PVMFErrInvalidState; 4521 } 4522 4523 } 4524 else 4525 { 4526 //Error condition report 4527 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4528 (0, "%s::DoStart(): Decoder is not in the Idle or Pause state!", iName.Str())); 4529 4530 status = PVMFErrInvalidState; 4531 } 4532 4533 4534 } 4535 break; 4536 4537 default: 4538 status = PVMFErrInvalidState; 4539 break; 4540 } 4541 4542 if (status == PVMFErrInvalidState) 4543 { 4544 CommandComplete(iInputCommands, aCmd, status); 4545 } 4546 else 4547 { 4548 //this command is asynchronous. move the command from 4549 //the input command queue to the current command, where 4550 //it will remain until it completes. 4551 int32 err; 4552 OSCL_TRY(err, iCurrentCommand.StoreL(aCmd);); 4553 if (err != OsclErrNone) 4554 { 4555 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory); 4556 } 4557 iInputCommands.Erase(&aCmd); 4558 } 4559 } 4560 4561 ///////////////////////////////////////////////////////////////////////////// 4562 void PVMFOMXBaseDecNode::DoStop(PVMFOMXBaseDecNodeCommand& aCmd) 4563 { 4564 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::DoStop() In", iName.Str())); 4565 4566 LogDiagnostics(); 4567 4568 OMX_ERRORTYPE err; 4569 OMX_STATETYPE sState; 4570 4571 switch (iInterfaceState) 4572 { 4573 case EPVMFNodeStarted: 4574 case EPVMFNodePaused: 4575 case EPVMFNodePrepared: 4576 // Stop data source 4577 // This will also prevent execution of HandleProcessingState 4578 4579 iDataIn.Unbind(); 4580 // Clear queued messages in ports 4581 if (iInPort) 4582 { 4583 iInPort->ClearMsgQueues(); 4584 } 4585 4586 if (iOutPort) 4587 { 4588 iOutPort->ClearMsgQueues(); 4589 } 4590 4591 // Clear the data flags 4592 4593 iEndOfDataReached = false; 4594 iIsEOSSentToComponent = false; 4595 iIsEOSReceivedFromComponent = false; 4596 4597 4598 iDoNotSendOutputBuffersDownstreamFlag = true; // stop sending output buffers downstream 4599 iDoNotSaveInputBuffersFlag = true; 4600 4601 //if we're in the middle of a partial frame assembly 4602 // abandon it and start fresh 4603 if (iObtainNewInputBuffer == false) 4604 { 4605 if (iInputBufferUnderConstruction != NULL) 4606 { 4607 if (iInBufMemoryPool != NULL) 4608 { 4609 iInBufMemoryPool->deallocate((OsclAny *)iInputBufferUnderConstruction); 4610 } 4611 iInputBufferUnderConstruction = NULL; 4612 } 4613 iObtainNewInputBuffer = true; 4614 4615 } 4616 4617 iFirstDataMsgAfterBOS = true; 4618 4619 //Get state of OpenMAX decoder 4620 err = OMX_GetState(iOMXDecoder, &sState); 4621 if (err != OMX_ErrorNone) 4622 { 4623 //Error condition report 4624 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4625 (0, "%s::DoStop(): Can't get State of decoder!", iName.Str())); 4626 4627 sState = OMX_StateInvalid; 4628 } 4629 4630 if ((sState == OMX_StateExecuting) || (sState == OMX_StatePause)) 4631 { 4632 /* Change state to OMX_StateIdle from OMX_StateExecuting or OMX_StatePause. */ 4633 4634 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4635 (0, "%s::DoStop() Changing Component State Executing->Idle or Pause->Idle", iName.Str())); 4636 4637 err = OMX_SendCommand(iOMXDecoder, OMX_CommandStateSet, OMX_StateIdle, NULL); 4638 if (err != OMX_ErrorNone) 4639 { 4640 //Error condition report 4641 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4642 (0, "%s::DoStop(): Can't send StateSet command to decoder!", iName.Str())); 4643 4644 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 4645 break; 4646 } 4647 4648 // prevent the node from sending more buffers etc. 4649 // if port reconfiguration is in process, let the state remain one of the port config states 4650 // if there is a start command, we can do it seemlessly (by continuing the port reconfig) 4651 if (iProcessingState == EPVMFOMXBaseDecNodeProcessingState_ReadyToDecode) 4652 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_Stopping; 4653 4654 // indicate that stop cmd was sent 4655 4656 4657 iStopCommandWasSentToComponent = true; 4658 4659 4660 4661 } 4662 else 4663 { 4664 //Error condition report 4665 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4666 (0, "%s::DoStop(): Decoder is not in the Executing or Pause state!", iName.Str())); 4667 4668 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 4669 break; 4670 } 4671 4672 //this command is asynchronous. move the command from 4673 //the input command queue to the current command, where 4674 //it will remain until it completes. 4675 int32 err; 4676 OSCL_TRY(err, iCurrentCommand.StoreL(aCmd);); 4677 if (err != OsclErrNone) 4678 { 4679 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory); 4680 return; 4681 } 4682 iInputCommands.Erase(&aCmd); 4683 4684 break; 4685 4686 default: 4687 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 4688 break; 4689 } 4690 } 4691 4692 ///////////////////////////////////////////////////////////////////////////// 4693 void PVMFOMXBaseDecNode::DoFlush(PVMFOMXBaseDecNodeCommand& aCmd) 4694 { 4695 switch (iInterfaceState) 4696 { 4697 case EPVMFNodeStarted: 4698 case EPVMFNodePaused: 4699 //the flush is asynchronous. move the command from 4700 //the input command queue to the current command, where 4701 //it will remain until the flush completes. 4702 int32 err; 4703 OSCL_TRY(err, iCurrentCommand.StoreL(aCmd);); 4704 if (err != OsclErrNone) 4705 { 4706 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory); 4707 return; 4708 } 4709 iInputCommands.Erase(&aCmd); 4710 4711 //Notify all ports to suspend their input 4712 if (iInPort) 4713 { 4714 iInPort->SuspendInput(); 4715 } 4716 if (iOutPort) 4717 { 4718 iOutPort->SuspendInput(); 4719 } 4720 // Stop data source 4721 4722 // DV: Sending "OMX_CommandFlush" to the decoder: Not supported yet 4723 4724 break; 4725 4726 default: 4727 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 4728 break; 4729 } 4730 } 4731 4732 ///////////////////////////////////////////////////////////////////////////// 4733 void PVMFOMXBaseDecNode::DoPause(PVMFOMXBaseDecNodeCommand& aCmd) 4734 { 4735 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::DoPause() In", iName.Str())); 4736 4737 OMX_ERRORTYPE err; 4738 OMX_STATETYPE sState; 4739 4740 switch (iInterfaceState) 4741 { 4742 case EPVMFNodeStarted: 4743 4744 4745 //Get state of OpenMAX decoder 4746 err = OMX_GetState(iOMXDecoder, &sState); 4747 if (err != OMX_ErrorNone) 4748 { 4749 //Error condition report 4750 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4751 (0, "%s::DoPause(): Can't get State of decoder!", iName.Str())); 4752 4753 sState = OMX_StateInvalid; 4754 } 4755 4756 if (sState == OMX_StateExecuting) 4757 { 4758 /* Change state to OMX_StatePause from OMX_StateExecuting. */ 4759 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4760 (0, "%s::DoPause() Changing Component State Executing->Idle", iName.Str())); 4761 4762 4763 // prevent the node from sending more buffers etc. 4764 // if port reconfiguration is in process, let the state remain one of the port config states 4765 // if there is a start command, we can do it seemlessly (by continuing the port reconfig) 4766 if (iProcessingState == EPVMFOMXBaseDecNodeProcessingState_ReadyToDecode) 4767 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_Pausing; 4768 4769 // indicate that pause cmd was sent 4770 4771 iPauseCommandWasSentToComponent = true; 4772 4773 4774 err = OMX_SendCommand(iOMXDecoder, OMX_CommandStateSet, OMX_StatePause, NULL); 4775 if (err != OMX_ErrorNone) 4776 { 4777 //Error condition report 4778 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4779 (0, "%s::DoPause(): Can't send StateSet command to decoder!", iName.Str())); 4780 4781 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 4782 break; 4783 } 4784 4785 } 4786 else 4787 { 4788 //Error condition report 4789 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4790 (0, "%s::DoPause(): Decoder is not in the Executing state!", iName.Str())); 4791 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 4792 break; 4793 } 4794 4795 //this command is asynchronous. move the command from 4796 //the input command queue to the current command, where 4797 //it will remain until it completes. 4798 int32 err; 4799 OSCL_TRY(err, iCurrentCommand.StoreL(aCmd);); 4800 if (err != OsclErrNone) 4801 { 4802 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory); 4803 return; 4804 } 4805 iInputCommands.Erase(&aCmd); 4806 4807 break; 4808 default: 4809 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 4810 break; 4811 } 4812 } 4813 4814 ///////////////////////////////////////////////////////////////////////////// 4815 void PVMFOMXBaseDecNode::DoReset(PVMFOMXBaseDecNodeCommand& aCmd) 4816 { 4817 4818 OMX_ERRORTYPE err; 4819 OMX_STATETYPE sState; 4820 4821 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4822 (0, "%s::DoReset() In", iName.Str())); 4823 4824 LogDiagnostics(); 4825 4826 switch (iInterfaceState) 4827 { 4828 case EPVMFNodeIdle: 4829 case EPVMFNodeInitialized: 4830 case EPVMFNodePrepared: 4831 case EPVMFNodeStarted: 4832 case EPVMFNodePaused: 4833 case EPVMFNodeError: 4834 { 4835 //Check if decoder is initilized 4836 if (iOMXDecoder != NULL) 4837 { 4838 4839 //if we're in the middle of a partial frame assembly 4840 // abandon it and start fresh 4841 if (iObtainNewInputBuffer == false) 4842 { 4843 if (iInputBufferUnderConstruction != NULL) 4844 { 4845 if (iInBufMemoryPool != NULL) 4846 { 4847 iInBufMemoryPool->deallocate((OsclAny *)iInputBufferUnderConstruction); 4848 } 4849 iInputBufferUnderConstruction = NULL; 4850 } 4851 iObtainNewInputBuffer = true; 4852 4853 } 4854 4855 iFirstDataMsgAfterBOS = true; 4856 iKeepDroppingMsgsUntilMarkerBit = false; 4857 4858 //Get state of OpenMAX decoder 4859 err = OMX_GetState(iOMXDecoder, &sState); 4860 if (err != OMX_ErrorNone) 4861 { 4862 sState = OMX_StateInvalid; 4863 } 4864 4865 if (sState == OMX_StateLoaded) 4866 { 4867 // this is a value obtained by synchronous call to component. Either the component was 4868 // already in this state without node issuing any commands, 4869 // or perhaps we started the Reset, but the callback notification has not yet arrived. 4870 if (iResetInProgress) 4871 { 4872 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4873 (0, "%s::DoReset() OMX comp is in loaded state. Wait for official callback to change variables etc.", iName.Str())); 4874 return; 4875 } 4876 } 4877 else if (sState == OMX_StateIdle) 4878 { 4879 //this command is asynchronous. move the command from 4880 //the input command queue to the current command, where 4881 //it will remain until it is completed. 4882 if (!iResetInProgress) 4883 { 4884 int32 err; 4885 OSCL_TRY(err, iCurrentCommand.StoreL(aCmd);); 4886 if (err != OsclErrNone) 4887 { 4888 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory); 4889 return; 4890 } 4891 iInputCommands.Erase(&aCmd); 4892 4893 iResetInProgress = true; 4894 } 4895 4896 // if buffers aren't all back (due to timing issues with different callback AOs 4897 // state change can be reported before all buffers are returned) 4898 if (iNumOutstandingInputBuffers > 0 || iNumOutstandingOutputBuffers > 0) 4899 { 4900 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4901 (0, "%s::DoReset() Waiting for %d input and-or %d output buffers", iName.Str(), iNumOutstandingInputBuffers, iNumOutstandingOutputBuffers)); 4902 4903 return; 4904 } 4905 4906 if (!iResetMsgSent) 4907 { 4908 // We can come here only if all buffers are already back 4909 // Don't repeat any of this twice. 4910 /* Change state to OMX_StateLoaded form OMX_StateIdle. */ 4911 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4912 (0, "%s::DoReset() Changing Component State Idle->Loaded", iName.Str())); 4913 4914 err = OMX_SendCommand(iOMXDecoder, OMX_CommandStateSet, OMX_StateLoaded, NULL); 4915 if (err != OMX_ErrorNone) 4916 { 4917 //Error condition report 4918 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4919 (0, "%s::DoReset(): Can't send StateSet command to decoder!", iName.Str())); 4920 } 4921 4922 iResetMsgSent = true; 4923 4924 4925 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4926 (0, "%s::DoReset() freeing output buffers", iName.Str())); 4927 4928 if (false == iOutputBuffersFreed) 4929 { 4930 if (!FreeBuffersFromComponent(iOutBufMemoryPool, // allocator 4931 iOutputAllocSize, // size to allocate from pool (hdr only or hdr+ buffer) 4932 iNumOutputBuffers, // number of buffers 4933 iOutputPortIndex, // port idx 4934 false // this is not input 4935 )) 4936 { 4937 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4938 (0, "%s::DoReset() Cannot free output buffers ", iName.Str())); 4939 4940 if (iResetInProgress) 4941 { 4942 iResetInProgress = false; 4943 if ((iCurrentCommand.size() > 0) && 4944 (iCurrentCommand.front().iCmd == PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_RESET) 4945 ) 4946 { 4947 CommandComplete(iCurrentCommand, iCurrentCommand.front() , PVMFErrResource); 4948 } 4949 } 4950 4951 } 4952 4953 } 4954 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4955 (0, "%s::DoReset() freeing input buffers ", iName.Str())); 4956 if (false == iInputBuffersFreed) 4957 { 4958 if (!FreeBuffersFromComponent(iInBufMemoryPool, // allocator 4959 iInputAllocSize, // size to allocate from pool (hdr only or hdr+ buffer) 4960 iNumInputBuffers, // number of buffers 4961 iInputPortIndex, // port idx 4962 true // this is input 4963 )) 4964 { 4965 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 4966 (0, "%s::DoReset() Cannot free input buffers ", iName.Str())); 4967 4968 if (iResetInProgress) 4969 { 4970 iResetInProgress = false; 4971 if ((iCurrentCommand.size() > 0) && 4972 (iCurrentCommand.front().iCmd == PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_RESET) 4973 ) 4974 { 4975 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFErrResource); 4976 } 4977 } 4978 4979 4980 } 4981 } 4982 4983 4984 4985 iEndOfDataReached = false; 4986 iIsEOSSentToComponent = false; 4987 iIsEOSReceivedFromComponent = false; 4988 4989 4990 4991 // also, perform Port deletion when the component replies with the command 4992 // complete, not right here 4993 } // end of if(iResetMsgSent) 4994 4995 4996 return; 4997 4998 } 4999 else if ((sState == OMX_StateExecuting) || (sState == OMX_StatePause)) 5000 { 5001 //this command is asynchronous. move the command from 5002 //the input command queue to the current command, where 5003 //it will remain until it is completed. 5004 if (!iResetInProgress) 5005 { 5006 int32 err; 5007 OSCL_TRY(err, iCurrentCommand.StoreL(aCmd);); 5008 if (err != OsclErrNone) 5009 { 5010 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory); 5011 return; 5012 } 5013 iInputCommands.Erase(&aCmd); 5014 5015 iResetInProgress = true; 5016 } 5017 5018 /* Change state to OMX_StateIdle from OMX_StateExecuting or OMX_StatePause. */ 5019 5020 if (!iStopInResetMsgSent) 5021 { 5022 // replicate behavior of stop cmd 5023 iDataIn.Unbind(); 5024 // Clear queued messages in ports 5025 if (iInPort) 5026 { 5027 iInPort->ClearMsgQueues(); 5028 } 5029 5030 if (iOutPort) 5031 { 5032 iOutPort->ClearMsgQueues(); 5033 } 5034 5035 // Clear the data flags 5036 5037 iEndOfDataReached = false; 5038 iIsEOSSentToComponent = false; 5039 iIsEOSReceivedFromComponent = false; 5040 5041 5042 iDoNotSendOutputBuffersDownstreamFlag = true; // stop sending output buffers downstream 5043 iDoNotSaveInputBuffersFlag = true; 5044 5045 5046 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5047 (0, "%s::DoReset() Changing Component State Executing->Idle or Pause->Idle", iName.Str())); 5048 5049 err = OMX_SendCommand(iOMXDecoder, OMX_CommandStateSet, OMX_StateIdle, NULL); 5050 if (err != OMX_ErrorNone) 5051 { 5052 //Error condition report 5053 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 5054 (0, "%s::DoReset(): Can't send StateSet command to decoder!", iName.Str())); 5055 5056 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 5057 break; 5058 } 5059 5060 iStopInResetMsgSent = true; 5061 // prevent the node from sending more buffers etc. 5062 // if port reconfiguration is in process, let the state remain one of the port config states 5063 // if there is a start command, we can do it seemlessly (by continuing the port reconfig) 5064 if (iProcessingState == EPVMFOMXBaseDecNodeProcessingState_ReadyToDecode) 5065 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_Stopping; 5066 } 5067 5068 return; 5069 5070 } 5071 else 5072 { 5073 //Error condition report 5074 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 5075 (0, "%s::DoReset(): Decoder is not in the Idle state! %d", iName.Str(), sState)); 5076 //do it here rather than relying on DTOR to avoid node reinit problems. 5077 DeleteOMXBaseDecoder(); 5078 //still return success. 5079 }//end of if (sState == OMX_StateLoaded) 5080 }//end of if (iOMXDecoder != NULL) 5081 5082 //delete all ports and notify observer. 5083 if (iInPort) 5084 { 5085 OSCL_DELETE(((PVMFOMXDecPort*)iInPort)); 5086 iInPort = NULL; 5087 } 5088 5089 if (iOutPort) 5090 { 5091 OSCL_DELETE(((PVMFOMXDecPort*)iOutPort)); 5092 iOutPort = NULL; 5093 } 5094 5095 iDataIn.Unbind(); 5096 5097 5098 // Reset the metadata key list 5099 iAvailableMetadataKeys.clear(); 5100 5101 iEndOfDataReached = false; 5102 iIsEOSSentToComponent = false; 5103 iIsEOSReceivedFromComponent = false; 5104 5105 if (iOMXComponentUsesFullAVCFrames) 5106 { 5107 iNALCount = 0; 5108 oscl_memset(iNALSizeArray, 0, sizeof(uint32) * MAX_NAL_PER_FRAME); // 100 is max number of NALs 5109 } 5110 5111 // reset dynamic port reconfig flags - no point continuing with port reconfig 5112 // if we start again - we'll have to do prepare and send new config etc. 5113 iSecondPortReportedChange = false; 5114 iDynamicReconfigInProgress = false; 5115 5116 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_Idle; 5117 //logoff & go back to Created state. 5118 SetState(EPVMFNodeIdle); 5119 5120 5121 if (iResetInProgress) 5122 { 5123 iResetInProgress = false; 5124 if ((iCurrentCommand.size() > 0) && 5125 (iCurrentCommand.front().iCmd == PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_RESET) 5126 ) 5127 { 5128 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess); 5129 } 5130 } 5131 else 5132 { 5133 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 5134 } 5135 5136 } 5137 break; 5138 5139 default: 5140 CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState); 5141 break; 5142 } 5143 } 5144 5145 ///////////////////////////////////////////////////////////////////////////// 5146 // Clean Up Decoder 5147 ///////////////////////////////////////////////////////////////////////////// 5148 bool PVMFOMXBaseDecNode::DeleteOMXBaseDecoder() 5149 { 5150 OMX_ERRORTYPE err; 5151 5152 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5153 (0, "%s::DeleteOMXBaseDecoder() In", iName.Str())); 5154 5155 if (iOMXDecoder != NULL) 5156 { 5157 /* Free Component handle. */ 5158 err = OMX_MasterFreeHandle(iOMXDecoder); 5159 if (err != OMX_ErrorNone) 5160 { 5161 //Error condition report 5162 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 5163 (0, "%s::DeleteOMXBaseDecoder(): Can't free decoder's handle!", iName.Str())); 5164 } 5165 iOMXDecoder = NULL; 5166 5167 }//end of if (iOMXDecoder != NULL) 5168 5169 5170 return true; 5171 } 5172 5173 ///////////////////////////////////////////////////////////////////////////// 5174 OSCL_EXPORT_REF void PVMFOMXBaseDecNode::ChangeNodeState(TPVMFNodeInterfaceState aNewState) 5175 { 5176 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::ChangeNodeState() Changing state from %d to %d", iName.Str(), iInterfaceState, aNewState)); 5177 iInterfaceState = aNewState; 5178 } 5179 5180 ///////////////////////////////////////////////////////////////////////////// 5181 OSCL_EXPORT_REF void PVMFOMXBaseDecNode::freechunkavailable(OsclAny *aContext) 5182 { 5183 5184 // check context to see whether input or output buffer was returned to the mempool 5185 if (aContext == (OsclAny *) iInBufMemoryPool) 5186 { 5187 5188 iNumOutstandingInputBuffers--; 5189 5190 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5191 (0, "%s::freechunkavailable() Memory chunk in INPUT mempool was deallocated, %d out of %d now available", iName.Str(), iNumInputBuffers - iNumOutstandingInputBuffers, iNumInputBuffers)); 5192 5193 // notification only works once. 5194 // If there are multiple buffers coming back in a row, make sure to set the notification 5195 // flag in the mempool again, so that next buffer also causes notification 5196 iInBufMemoryPool->notifyfreechunkavailable(*this, aContext); 5197 5198 } 5199 else if (aContext == (OsclAny *) iOutBufMemoryPool) 5200 { 5201 5202 iNumOutstandingOutputBuffers--; 5203 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5204 (0, "%s::freechunkavailable() Memory chunk in OUTPUT mempool was deallocated, %d out of %d now available", iName.Str(), iNumOutputBuffers - iNumOutstandingOutputBuffers, iNumOutputBuffers)); 5205 5206 // notification only works once. 5207 // If there are multiple buffers coming back in a row, make sure to set the notification 5208 // flag in the mempool again, so that next buffer also causes notification 5209 iOutBufMemoryPool->notifyfreechunkavailable(*this, aContext); 5210 5211 } 5212 else 5213 { 5214 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5215 (0, "%s::freechunkavailable() UNKNOWN mempool ", iName.Str())); 5216 5217 } 5218 5219 // reschedule 5220 if (IsAdded()) 5221 RunIfNotReady(); 5222 5223 5224 } 5225 5226 ///////////////////////////////////////////////////////////////////////////// 5227 OSCL_EXPORT_REF void PVMFOMXBaseDecNode::HandlePortActivity(const PVMFPortActivity &aActivity) 5228 { 5229 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5230 (0, "0x%x PVMFOMXBaseDecNode::PortActivity: port=0x%x, type=%d", 5231 this, aActivity.iPort, aActivity.iType)); 5232 5233 switch (aActivity.iType) 5234 { 5235 case PVMF_PORT_ACTIVITY_OUTGOING_MSG: 5236 //An outgoing message was queued on this port. 5237 //We only need to queue a port activity event on the 5238 //first message. Additional events will be queued during 5239 //the port processing as needed. 5240 if (aActivity.iPort->OutgoingMsgQueueSize() == 1) 5241 { 5242 //wake up the AO to process the port activity event. 5243 RunIfNotReady(); 5244 } 5245 break; 5246 5247 case PVMF_PORT_ACTIVITY_INCOMING_MSG: 5248 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 5249 (0, "%s::PortActivity: IncomingMsgQueueSize=%d", iName.Str(), aActivity.iPort->IncomingMsgQueueSize())); 5250 if (aActivity.iPort->IncomingMsgQueueSize() == 1) 5251 { 5252 //wake up the AO to process the port activity event. 5253 RunIfNotReady(); 5254 } 5255 break; 5256 5257 case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY: 5258 if (iProcessingState == EPVMFOMXBaseDecNodeProcessingState_WaitForOutgoingQueue) 5259 { 5260 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_ReadyToDecode; 5261 RunIfNotReady(); 5262 } 5263 break; 5264 5265 case PVMF_PORT_ACTIVITY_CONNECT: 5266 //nothing needed. 5267 break; 5268 5269 case PVMF_PORT_ACTIVITY_DISCONNECT: 5270 //clear the node input data when either port is disconnected. 5271 5272 iDataIn.Unbind(); 5273 break; 5274 5275 case PVMF_PORT_ACTIVITY_CONNECTED_PORT_BUSY: 5276 // The connected port has become busy (its incoming queue is 5277 // busy). 5278 // No action is needed here-- the port processing code 5279 // checks for connected port busy during data processing. 5280 break; 5281 5282 case PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY: 5283 // The connected port has transitioned from Busy to Ready to Receive. 5284 // It's time to start processing outgoing messages again. 5285 5286 //iProcessingState should transition from WaitForOutputPort to ReadyToDecode 5287 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 5288 (0, "0x%x PVMFOMXBaseDecNode::PortActivity: Connected port is now ready", this)); 5289 RunIfNotReady(); 5290 break; 5291 5292 default: 5293 break; 5294 } 5295 } 5296 5297 ///////////////////////////////////////////////////////////////////////////// 5298 void PVMFOMXBaseDecNode::DoCancelAllCommands(PVMFOMXBaseDecNodeCommand& aCmd) 5299 { 5300 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5301 (0, "%s::DoCancelAllCommands", iName.Str())); 5302 5303 //first cancel the current command if any 5304 { 5305 while (!iCurrentCommand.empty()) 5306 { 5307 CommandComplete(iCurrentCommand, iCurrentCommand[0], PVMFErrCancelled); 5308 } 5309 5310 } 5311 5312 //next cancel all queued commands 5313 { 5314 //start at element 1 since this cancel command is element 0. 5315 while (iInputCommands.size() > 1) 5316 { 5317 CommandComplete(iInputCommands, iInputCommands[1], PVMFErrCancelled); 5318 } 5319 } 5320 5321 if (iResetInProgress && !iResetMsgSent) 5322 { 5323 // if reset is started but reset msg has not been sent, we can cancel reset 5324 // as if nothing happened. Otherwise, the callback will set the flag back to false 5325 iResetInProgress = false; 5326 } 5327 //finally, report cancel complete. 5328 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 5329 } 5330 5331 ///////////////////////////////////////////////////////////////////////////// 5332 void PVMFOMXBaseDecNode::DoCancelCommand(PVMFOMXBaseDecNodeCommand& aCmd) 5333 { 5334 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5335 (0, "%s::DoCancelCommand", iName.Str())); 5336 5337 //extract the command ID from the parameters. 5338 PVMFCommandId id; 5339 aCmd.PVMFOMXBaseDecNodeCommandBase::Parse(id); 5340 5341 //first check "current" command if any 5342 { 5343 PVMFOMXBaseDecNodeCommand* cmd = iCurrentCommand.FindById(id); 5344 if (cmd) 5345 { 5346 5347 // if reset is being canceled: 5348 if (cmd->iCmd == PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_RESET) 5349 { 5350 if (iResetInProgress && !iResetMsgSent) 5351 { 5352 // if reset is started but reset msg has not been sent, we can cancel reset 5353 // as if nothing happened. Otherwise, the callback will set the flag back to false 5354 iResetInProgress = false; 5355 } 5356 } 5357 //cancel the queued command 5358 CommandComplete(iCurrentCommand, *cmd, PVMFErrCancelled); 5359 //report cancel success 5360 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 5361 return; 5362 } 5363 } 5364 5365 //next check input queue. 5366 { 5367 //start at element 1 since this cancel command is element 0. 5368 PVMFOMXBaseDecNodeCommand* cmd = iInputCommands.FindById(id, 1); 5369 if (cmd) 5370 { 5371 //cancel the queued command 5372 CommandComplete(iInputCommands, *cmd, PVMFErrCancelled); 5373 //report cancel success 5374 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 5375 return; 5376 } 5377 } 5378 //if we get here the command isn't queued so the cancel fails. 5379 CommandComplete(iInputCommands, aCmd, PVMFErrArgument); 5380 } 5381 5382 ///////////////////////////////////////////////////////////////////////////// 5383 void PVMFOMXBaseDecNode::DoQueryInterface(PVMFOMXBaseDecNodeCommand& aCmd) 5384 { 5385 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5386 (0, "%s::DoQueryInterface", iName.Str())); 5387 PVUuid* uuid; 5388 PVInterface** ptr; 5389 aCmd.PVMFOMXBaseDecNodeCommandBase::Parse(uuid, ptr); 5390 5391 if (*uuid == PVUuid(PVMF_OMX_BASE_DEC_NODE_CUSTOM1_UUID)) 5392 { 5393 addRef(); 5394 *ptr = (PVMFOMXBaseDecNodeExtensionInterface*)this; 5395 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 5396 } 5397 else if (*uuid == PVUuid(KPVMFMetadataExtensionUuid)) 5398 { 5399 addRef(); 5400 *ptr = (PVMFMetadataExtensionInterface*)this; 5401 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 5402 } 5403 else if (*uuid == PVUuid(PVMI_CAPABILITY_AND_CONFIG_PVUUID)) 5404 { 5405 addRef(); 5406 *ptr = (PvmiCapabilityAndConfig*)this; 5407 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 5408 } 5409 else 5410 { 5411 //not supported 5412 *ptr = NULL; 5413 CommandComplete(iInputCommands, aCmd, PVMFFailure); 5414 } 5415 } 5416 5417 5418 ///////////////////////////////////////////////////////////////////////////// 5419 OSCL_EXPORT_REF void PVMFOMXBaseDecNode::addRef() 5420 { 5421 ++iExtensionRefCount; 5422 } 5423 5424 ///////////////////////////////////////////////////////////////////////////// 5425 OSCL_EXPORT_REF void PVMFOMXBaseDecNode::removeRef() 5426 { 5427 --iExtensionRefCount; 5428 } 5429 5430 ///////////////////////////////////////////////////////////////////////////// 5431 OSCL_EXPORT_REF bool PVMFOMXBaseDecNode::queryInterface(const PVUuid& uuid, PVInterface*& iface) 5432 { 5433 PVUuid my_uuid(PVMF_OMX_BASE_DEC_NODE_CUSTOM1_UUID); 5434 if (uuid == my_uuid) 5435 { 5436 PVMFOMXBaseDecNodeExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFOMXBaseDecNodeExtensionInterface*, this); 5437 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 5438 ++iExtensionRefCount; 5439 return true; 5440 } 5441 else if (uuid == KPVMFMetadataExtensionUuid) 5442 { 5443 PVMFMetadataExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFMetadataExtensionInterface*, this); 5444 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 5445 ++iExtensionRefCount; 5446 return true; 5447 } 5448 return false; 5449 } 5450 5451 ////////////////////////////////////////////////////////////////////////////////////// 5452 bool PVMFOMXBaseDecNode::HandleRepositioning() 5453 { 5454 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5455 (0, "%s::HandleRepositioning() IN", iName.Str())); 5456 5457 5458 // 1) Send Flush command to component for both input and output ports 5459 // 2) "Wait" until component flushes both ports 5460 // 3) Resume 5461 OMX_ERRORTYPE err = OMX_ErrorNone; 5462 OMX_STATETYPE sState = OMX_StateInvalid; 5463 5464 5465 if (!iIsRepositioningRequestSentToComponent) 5466 { 5467 5468 // first check the state (if executing or paused, continue) 5469 err = OMX_GetState(iOMXDecoder, &sState); 5470 if (err != OMX_ErrorNone) 5471 { 5472 //Error condition report 5473 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 5474 (0, "%s::HandleRepositioning(): Can't get State of decoder - trying to send reposition request!", iName.Str())); 5475 5476 sState = OMX_StateInvalid; 5477 ReportErrorEvent(PVMFErrResourceConfiguration); 5478 ChangeNodeState(EPVMFNodeError); 5479 return false; 5480 } 5481 5482 if ((sState != OMX_StateExecuting) && (sState != OMX_StatePause)) 5483 { 5484 5485 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5486 (0, "%s::HandleRepositioning() Component State is not executing or paused, do not proceed with repositioning", iName.Str())); 5487 5488 return true; 5489 5490 } 5491 5492 5493 iIsRepositioningRequestSentToComponent = true; // prevent sending requests multiple times 5494 iIsInputPortFlushed = false; // flag that will be set to true once component flushes the port 5495 iIsOutputPortFlushed = false; 5496 iDoNotSendOutputBuffersDownstreamFlag = true; 5497 5498 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5499 (0, "%s::HandleRepositioning() Sending Flush command to component", iName.Str())); 5500 5501 // send command to flush all ports (arg is OMX_ALL) 5502 err = OMX_SendCommand(iOMXDecoder, OMX_CommandFlush, OMX_ALL, NULL); 5503 if (err != OMX_ErrorNone) 5504 { 5505 //Error condition report 5506 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 5507 (0, "%s::HandleRepositioning(): Can't send flush command - trying to send reposition request!", iName.Str())); 5508 5509 sState = OMX_StateInvalid; 5510 ReportErrorEvent(PVMFErrResourceConfiguration); 5511 ChangeNodeState(EPVMFNodeError); 5512 return false; 5513 } 5514 5515 } 5516 5517 if (iIsRepositionDoneReceivedFromComponent) 5518 { 5519 5520 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5521 (0, "%s::HandleRepositioning() Component has flushed both ports, and is done repositioning", iName.Str())); 5522 5523 iIsRepositioningRequestSentToComponent = false; // enable sending requests again 5524 iIsRepositionDoneReceivedFromComponent = false; 5525 iIsInputPortFlushed = false; 5526 iIsOutputPortFlushed = false; 5527 5528 iDoNotSendOutputBuffersDownstreamFlag = false; 5529 return true; 5530 } 5531 5532 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5533 (0, "%s::HandleRepositioning() Component is not yet done repositioning ", iName.Str())); 5534 5535 return false; 5536 5537 } 5538 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 5539 OSCL_EXPORT_REF OMX_TICKS PVMFOMXBaseDecNode::ConvertTimestampIntoOMXTicks(const MediaClockConverter& src) 5540 { 5541 // This is similar to mediaclockconverter set_value method - except without using the modulo for upper part of 64 bits 5542 5543 // Timescale value cannot be zero 5544 OSCL_ASSERT(src.get_timescale() != 0); 5545 if (src.get_timescale() == 0) 5546 { 5547 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 5548 (0, "%s::ConvertTimestampIntoOMXTicks Input timescale is 0", iName.Str())); 5549 5550 SetState(EPVMFNodeError); 5551 ReportErrorEvent(PVMFErrResourceConfiguration); 5552 return (OMX_TICKS) 0; 5553 } 5554 5555 OSCL_ASSERT(iTimeScale != 0); 5556 if (0 == iTimeScale) 5557 { 5558 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 5559 (0, "%s::ConvertTimestampIntoOMXTicks target timescale is 0", iName.Str())); 5560 5561 SetState(EPVMFNodeError); 5562 ReportErrorEvent(PVMFErrResourceConfiguration); 5563 return (OMX_TICKS) 0; 5564 } 5565 5566 uint64 value = (uint64(src.get_wrap_count())) << 32; 5567 value += src.get_current_timestamp(); 5568 // rounding up 5569 value = (uint64(value) * iTimeScale + uint64(src.get_timescale() - 1)) / src.get_timescale(); 5570 return (OMX_TICKS) value; 5571 5572 5573 } 5574 //////////////////////////////////////////////////////////////////////////////////// 5575 uint32 PVMFOMXBaseDecNode::ConvertOMXTicksIntoTimestamp(const OMX_TICKS &src) 5576 { 5577 // omx ticks use microsecond timescale (iTimeScale = 1000000) 5578 // This is similar to mediaclockconverter set_value method 5579 5580 // Timescale value cannot be zero 5581 OSCL_ASSERT(iOutTimeScale != 0); 5582 if (0 == iOutTimeScale) 5583 { 5584 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 5585 (0, "%s::ConvertOMXTicksIntoTimestamp Output timescale is 0", iName.Str())); 5586 5587 SetState(EPVMFNodeError); 5588 ReportErrorEvent(PVMFErrResourceConfiguration); 5589 return (uint32) 0; 5590 } 5591 5592 OSCL_ASSERT(iTimeScale != 0); 5593 if (0 == iTimeScale) 5594 { 5595 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 5596 (0, "%s::ConvertOMXTicksIntoTimestamp target timescale is 0", iName.Str())); 5597 5598 SetState(EPVMFNodeError); 5599 ReportErrorEvent(PVMFErrResourceConfiguration); 5600 return (uint32) 0; 5601 } 5602 5603 uint32 current_ts; 5604 5605 uint64 value = (uint64) src; 5606 5607 // rounding up 5608 value = (uint64(value) * iOutTimeScale + uint64(iTimeScale - 1)) / iTimeScale; 5609 5610 current_ts = (uint32)(value & 0xFFFFFFFF); 5611 return current_ts; 5612 5613 } 5614 /////////////////////////////////////////////////////////////////////////////////////// 5615 OSCL_EXPORT_REF void PVMFOMXBaseDecNode::setObserver(PvmiConfigAndCapabilityCmdObserver* aObserver) 5616 { 5617 OSCL_UNUSED_ARG(aObserver); 5618 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::setObserver()", iName.Str())); 5619 // This method is not supported so leave 5620 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "%s::setObserver() is not supported!", iName.Str())); 5621 OSCL_LEAVE(PVMFErrNotSupported); 5622 } 5623 5624 5625 OSCL_EXPORT_REF PVMFStatus PVMFOMXBaseDecNode::getParametersSync(PvmiMIOSession aSession, PvmiKeyType aIdentifier, PvmiKvp*& aParameters, int& aNumParamElements, PvmiCapabilityContext aContext) 5626 { 5627 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::getParametersSync()", iName.Str())); 5628 OSCL_UNUSED_ARG(aSession); 5629 5630 return DoCapConfigGetParametersSync(aIdentifier, aParameters, aNumParamElements, aContext); 5631 } 5632 5633 5634 OSCL_EXPORT_REF PVMFStatus PVMFOMXBaseDecNode::releaseParameters(PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements) 5635 { 5636 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::releaseParameters()", iName.Str())); 5637 OSCL_UNUSED_ARG(aSession); 5638 5639 return DoCapConfigReleaseParameters(aParameters, aNumElements); 5640 } 5641 5642 5643 OSCL_EXPORT_REF void PVMFOMXBaseDecNode::createContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext) 5644 { 5645 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::createContext()", iName.Str())); 5646 OSCL_UNUSED_ARG(aSession); 5647 OSCL_UNUSED_ARG(aContext); 5648 // This method is not supported so leave 5649 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "%s::createContext() is not supported!", iName.Str())); 5650 OSCL_LEAVE(PVMFErrNotSupported); 5651 } 5652 5653 5654 OSCL_EXPORT_REF void PVMFOMXBaseDecNode::setContextParameters(PvmiMIOSession aSession, PvmiCapabilityContext& aContext, PvmiKvp* aParameters, int aNumParamElements) 5655 { 5656 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::setContextParameters()", iName.Str())); 5657 OSCL_UNUSED_ARG(aSession); 5658 OSCL_UNUSED_ARG(aContext); 5659 OSCL_UNUSED_ARG(aParameters); 5660 OSCL_UNUSED_ARG(aNumParamElements); 5661 // This method is not supported so leave 5662 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "%s::setContextParameters() is not supported!", iName.Str())); 5663 OSCL_LEAVE(PVMFErrNotSupported); 5664 } 5665 5666 5667 OSCL_EXPORT_REF void PVMFOMXBaseDecNode::DeleteContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext) 5668 { 5669 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::DeleteContext()", iName.Str())); 5670 OSCL_UNUSED_ARG(aSession); 5671 OSCL_UNUSED_ARG(aContext); 5672 // This method is not supported so leave 5673 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "%s::DeleteContext() is not supported!", iName.Str())); 5674 OSCL_LEAVE(PVMFErrNotSupported); 5675 } 5676 5677 5678 OSCL_EXPORT_REF void PVMFOMXBaseDecNode::setParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements, PvmiKvp* &aRetKVP) 5679 { 5680 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::setParametersSync()", iName.Str())); 5681 OSCL_UNUSED_ARG(aSession); 5682 5683 // Complete the request synchronously 5684 DoCapConfigSetParameters(aParameters, aNumElements, aRetKVP); 5685 } 5686 5687 5688 OSCL_EXPORT_REF PVMFCommandId PVMFOMXBaseDecNode::setParametersAsync(PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements, PvmiKvp*& aRetKVP, OsclAny* aContext) 5689 { 5690 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::setParametersAsync()", iName.Str())); 5691 OSCL_UNUSED_ARG(aSession); 5692 OSCL_UNUSED_ARG(aParameters); 5693 OSCL_UNUSED_ARG(aNumElements); 5694 OSCL_UNUSED_ARG(aRetKVP); 5695 OSCL_UNUSED_ARG(aContext); 5696 5697 // This method is not supported so leave 5698 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "%s::setParametersAsync() is not supported!", iName.Str())); 5699 OSCL_LEAVE(PVMFErrNotSupported); 5700 return 0; 5701 } 5702 5703 5704 OSCL_EXPORT_REF uint32 PVMFOMXBaseDecNode::getCapabilityMetric(PvmiMIOSession aSession) 5705 { 5706 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::getCapabilityMetric()", iName.Str())); 5707 OSCL_UNUSED_ARG(aSession); 5708 // Not supported so return 0 5709 return 0; 5710 } 5711 5712 5713 OSCL_EXPORT_REF PVMFStatus PVMFOMXBaseDecNode::verifyParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements) 5714 { 5715 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::verifyParametersSync()", iName.Str())); 5716 OSCL_UNUSED_ARG(aSession); 5717 5718 return DoCapConfigVerifyParameters(aParameters, aNumElements); 5719 } 5720 5721 ///////////////////////////////////////////////////////////////////////////// 5722 OSCL_EXPORT_REF PVMFCommandId PVMFOMXBaseDecNode::GetNodeMetadataKeys(PVMFSessionId aSessionId, PVMFMetadataList& aKeyList, uint32 starting_index, int32 max_entries, char* query_key, const OsclAny* aContext) 5723 { 5724 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%sCommand::GetNodeMetadataKeys() called", iName.Str())); 5725 5726 PVMFOMXBaseDecNodeCommand cmd; 5727 cmd.PVMFOMXBaseDecNodeCommand::Construct(aSessionId, PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_GETNODEMETADATAKEY, &aKeyList, starting_index, max_entries, query_key, aContext); 5728 return QueueCommandL(cmd); 5729 } 5730 5731 ///////////////////////////////////////////////////////////////////////////// 5732 OSCL_EXPORT_REF PVMFCommandId PVMFOMXBaseDecNode::GetNodeMetadataValues(PVMFSessionId aSessionId, PVMFMetadataList& aKeyList, Oscl_Vector<PvmiKvp, OsclMemAllocator>& aValueList, uint32 starting_index, int32 max_entries, const OsclAny* aContext) 5733 { 5734 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%sCommand::GetNodeMetadataValue() called", iName.Str())); 5735 5736 PVMFOMXBaseDecNodeCommand cmd; 5737 cmd.PVMFOMXBaseDecNodeCommand::Construct(aSessionId, PVMFOMXBaseDecNodeCommand::PVOMXBASEDEC_NODE_CMD_GETNODEMETADATAVALUE, &aKeyList, &aValueList, starting_index, max_entries, aContext); 5738 return QueueCommandL(cmd); 5739 } 5740 5741 // From PVMFMetadataExtensionInterface 5742 ///////////////////////////////////////////////////////////////////////////// 5743 OSCL_EXPORT_REF PVMFStatus PVMFOMXBaseDecNode::ReleaseNodeMetadataKeys(PVMFMetadataList& , uint32 , uint32) 5744 { 5745 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::ReleaseNodeMetadataKeys() called", iName.Str())); 5746 //nothing needed-- there's no dynamic allocation in this node's key list 5747 return PVMFSuccess; 5748 } 5749 5750 // From PVMFMetadataExtensionInterface 5751 ///////////////////////////////////////////////////////////////////////////// 5752 OSCL_EXPORT_REF PVMFStatus PVMFOMXBaseDecNode::ReleaseNodeMetadataValues(Oscl_Vector<PvmiKvp, OsclMemAllocator>& aValueList, uint32 start, uint32 end) 5753 { 5754 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::ReleaseNodeMetadataValues() called", iName.Str())); 5755 5756 if (aValueList.size() == 0 || start > end) 5757 { 5758 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "%s::ReleaseNodeMetadataValues() Invalid start/end index", iName.Str())); 5759 return PVMFErrArgument; 5760 } 5761 5762 if (end >= aValueList.size()) 5763 { 5764 end = aValueList.size() - 1; 5765 } 5766 5767 for (uint32 i = start; i <= end; i++) 5768 { 5769 if (aValueList[i].key != NULL) 5770 { 5771 switch (GetValTypeFromKeyString(aValueList[i].key)) 5772 { 5773 case PVMI_KVPVALTYPE_CHARPTR: 5774 if (aValueList[i].value.pChar_value != NULL) 5775 { 5776 OSCL_ARRAY_DELETE(aValueList[i].value.pChar_value); 5777 aValueList[i].value.pChar_value = NULL; 5778 } 5779 break; 5780 5781 case PVMI_KVPVALTYPE_UINT32: 5782 case PVMI_KVPVALTYPE_UINT8: 5783 // No memory to free for these valtypes 5784 break; 5785 5786 default: 5787 // Should not get a value that wasn't created from here 5788 break; 5789 } 5790 5791 OSCL_ARRAY_DELETE(aValueList[i].key); 5792 aValueList[i].key = NULL; 5793 } 5794 } 5795 5796 return PVMFSuccess; 5797 } 5798 5799 //////////////////////////////////////////////////////////////////////////////////////////////// 5800 //////////////////////////////////////////////////////////////////////////////////////////////// 5801 // CAPABILITY CONFIG PRIVATE 5802 OSCL_EXPORT_REF PVMFStatus PVMFOMXBaseDecNode::DoCapConfigGetParametersSync(PvmiKeyType aIdentifier, PvmiKvp*& aParameters, int& aNumParamElements, PvmiCapabilityContext aContext) 5803 { 5804 OSCL_UNUSED_ARG(aParameters); 5805 OSCL_UNUSED_ARG(aIdentifier); 5806 OSCL_UNUSED_ARG(aNumParamElements); 5807 OSCL_UNUSED_ARG(aContext); 5808 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::DoCapConfigGetParametersSync() In", iName.Str())); 5809 5810 return PVMFFailure; 5811 } 5812 5813 5814 OSCL_EXPORT_REF PVMFStatus PVMFOMXBaseDecNode::DoCapConfigReleaseParameters(PvmiKvp* aParameters, int aNumElements) 5815 { 5816 OSCL_UNUSED_ARG(aParameters); 5817 OSCL_UNUSED_ARG(aNumElements); 5818 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::DoCapConfigReleaseParameters() Out", iName.Str())); 5819 return PVMFSuccess; 5820 } 5821 5822 5823 OSCL_EXPORT_REF void PVMFOMXBaseDecNode::DoCapConfigSetParameters(PvmiKvp* aParameters, int aNumElements, PvmiKvp* &aRetKVP) 5824 { 5825 OSCL_UNUSED_ARG(aParameters); 5826 OSCL_UNUSED_ARG(aNumElements); 5827 OSCL_UNUSED_ARG(aRetKVP); 5828 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::DoCapConfigSetParameters() Out", iName.Str())); 5829 } 5830 5831 5832 OSCL_EXPORT_REF PVMFStatus PVMFOMXBaseDecNode::DoCapConfigVerifyParameters(PvmiKvp* aParameters, int aNumElements) 5833 { 5834 OSCL_UNUSED_ARG(aParameters); 5835 OSCL_UNUSED_ARG(aNumElements); 5836 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::DoCapConfigVerifyParameters() In", iName.Str())); 5837 5838 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "%s::DoCapConfigVerifyParameters() Out", iName.Str())); 5839 return PVMFSuccess; 5840 } 5841 5842 5843 ///////////////////////////////////////////////////////////////////////////// 5844 void PVMFOMXBaseDecNode::LogDiagnostics() 5845 { 5846 if (iDiagnosticsLogged == false) 5847 { 5848 iDiagnosticsLogged = true; 5849 PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO, (0, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")); 5850 PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO, (0, "%s - Number of Frames Sent = %d", iName.Str(), iSeqNum)); 5851 PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iDiagnosticsLogger, PVLOGMSG_INFO, (0, "%s - TS of last decoded frame = %d", iName.Str(), iOutTimeStamp)); 5852 } 5853 } 5854 5855 5856 OSCL_EXPORT_REF OsclAny* PVMFOMXBaseDecNode::AllocateKVPKeyArray(int32& aLeaveCode, PvmiKvpValueType aValueType, int32 aNumElements) 5857 { 5858 int32 leaveCode = OsclErrNone; 5859 OsclAny* aBuffer = NULL; 5860 switch (aValueType) 5861 { 5862 case PVMI_KVPVALTYPE_WCHARPTR: 5863 OSCL_TRY(leaveCode, 5864 aBuffer = (oscl_wchar*) OSCL_ARRAY_NEW(oscl_wchar, aNumElements); 5865 ); 5866 break; 5867 5868 case PVMI_KVPVALTYPE_CHARPTR: 5869 OSCL_TRY(leaveCode, 5870 aBuffer = (char*) OSCL_ARRAY_NEW(char, aNumElements); 5871 ); 5872 break; 5873 case PVMI_KVPVALTYPE_UINT8PTR: 5874 OSCL_TRY(leaveCode, 5875 aBuffer = (uint8*) OSCL_ARRAY_NEW(uint8, aNumElements); 5876 ); 5877 break; 5878 default: 5879 break; 5880 } 5881 aLeaveCode = leaveCode; 5882 return aBuffer; 5883 } 5884 5885 #undef PVLOGGER_LOGMSG 5886 #define PVLOGGER_LOGMSG(IL, LOGGER, LEVEL, MESSAGE) OSCL_UNUSED_ARG(LOGGER); 5887 5888 5889 5890 5891