Home | History | Annotate | Download | only in src
      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