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 #ifndef PVMF_DUMMY_FILEINPUT_NODE_H_INCLUDED
     19 #include "pvmf_dummy_fileinput_node.h"
     20 #endif
     21 #ifndef PVMF_FILEINPUT_NODE_INTERNAL_H_INCLUDED
     22 #include "pvmf_fileinput_node_internal.h"
     23 #endif
     24 #ifndef PVLOGGER_H_INCLUDED
     25 #include "pvlogger.h"
     26 #endif
     27 #ifndef PVMF_COMMON_AUDIO_DECNODE_H_INCLUDE
     28 #include "pvmf_common_audio_decnode.h"
     29 #endif
     30 #ifndef PVMF_VIDEO_H_INCLUDED
     31 #include "pvmf_video.h"
     32 #endif
     33 #ifndef OSCL_DLL_H_INCLUDED
     34 #include "oscl_dll.h"
     35 #endif
     36 #ifndef PVMF_VIDEO_H_INCLUDED
     37 #include "pvmf_video.h"
     38 #endif
     39 #ifndef PVMF_DUMMY_FILEINPUT_NODE_FACTORY_H_INCLUDED
     40 #include "pvmf_dummy_fileinput_node_factory.h"
     41 #endif
     42 #include "pvmf_media_cmd.h"
     43 #include "pvmf_media_msg_format_ids.h"
     44 
     45 // also defined in the pvmf_fileinput_node.h:
     46 // This test splits each frame into two pieces and sends them in 2 separate messages.
     47 // the first message has no marker bit set, the 2nd message has marker bit set
     48 //#define FRAGMENTATION_TEST
     49 
     50 OSCL_DLL_ENTRY_POINT_DEFAULT()
     51 
     52 #define GetUnalignedDword( pb, dw ) \
     53             (dw) = ((uint32) *(pb + 3) << 24) + \
     54                    ((uint32) *(pb + 2) << 16) + \
     55                    ((uint16) *(pb + 1) << 8) + *pb;
     56 
     57 #define GetUnalignedDwordEx( pb, dw )   GetUnalignedDword( pb, dw ); (pb) += sizeof(uint32);
     58 #define LoadDWORD( dw, p )  GetUnalignedDwordEx( p, dw )
     59 
     60 /**
     61 //Macros for calling PVLogger
     62 */
     63 #define LOGERROR(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_ERR,m);
     64 #define LOGINFOHI(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG,iLogger,PVLOGMSG_INFO,m);
     65 #define LOGINFOMED(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG,iLogger,PVLOGMSG_INFO,m);
     66 #define LOGINFOLOW(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iLogger,PVLOGMSG_INFO,m);
     67 #define LOGINFO(m) LOGINFOMED(m)
     68 
     69 
     70 #define PVFILEIN_MEDIADATA_POOLNUM 16
     71 #define PVFILEIN_MEDIADATA_CHUNKSIZE 128
     72 
     73 //#define SEND_CONFIGINFO_SEPARATELY
     74 const uint32 AMR_FRAME_DELAY = 20; // 20ms
     75 
     76 
     77 /** Factory class */
     78 OSCL_EXPORT_REF PVMFNodeInterface* PVMFDummyFileInputNodeFactory::CreateDummyFileInputNode(PVMFFileInputSettings* aSettings,
     79         int32 aPriority)
     80 {
     81     PVMFDummyFileInputNode* node = NULL;
     82     int32 err = 0;
     83     OSCL_TRY(err, node = OSCL_NEW(PVMFDummyFileInputNode, (aSettings, aPriority)););
     84     OSCL_FIRST_CATCH_ANY(err, return NULL;);
     85     return node;
     86 }
     87 
     88 OSCL_EXPORT_REF bool PVMFDummyFileInputNodeFactory::DeleteDummyFileInputNode(PVMFNodeInterface*& aNode)
     89 {
     90     if (!aNode)
     91         return false;
     92     PVMFDummyFileInputNode* node = (PVMFDummyFileInputNode*)aNode;
     93     OSCL_DELETE(node);
     94     aNode = NULL;
     95     return true;
     96 }
     97 
     98 /**
     99 //////////////////////////////////////////////////
    100 // Node Constructor & Destructor
    101 //////////////////////////////////////////////////
    102 */
    103 
    104 OSCL_EXPORT_REF PVMFDummyFileInputNode::PVMFDummyFileInputNode(PVMFFileInputSettings* aSettings, int32 aPriority)
    105         : OsclTimerObject(aPriority, "PVMFDummyFileInputNode")
    106         , iMediaBufferMemPool(NULL)
    107         , iMediaDataAlloc(NULL)
    108         , iMediaDataMemPool(PVFILEIN_MEDIADATA_POOLNUM, PVFILEIN_MEDIADATA_CHUNKSIZE)
    109         , iAudioData(NULL)
    110         , iVideoData(NULL)
    111         , iLogger(NULL)
    112         , iFormatSpecificInfoSize(0)
    113         , iSetFormatSpecificInfo(false)
    114         , iFileHeaderSize(0)
    115         , iFsOpen(false)
    116         , iFileOpen(false)
    117         , iDataEventCounter(0)
    118         , iTotalNumFrames(0)
    119         , iMilliSecondsPerDataEvent(0)
    120         , iMicroSecondsPerDataEvent(0)
    121         , iTSForRunIfInactive(0)
    122         , iTimeStamp(0)
    123         , iExtensionRefCount(0)
    124         , iWaitingOnFreeChunk(false)
    125         , iEndOfFileReached(false)
    126 {
    127     int32 err;
    128     OSCL_TRY(err,
    129 
    130              //Create the input command queue.  Use a reserve to avoid lots of
    131              //dynamic memory allocation.
    132              iInputCommands.Construct(PVMF_FILEINPUT_NODE_COMMAND_ID_START, PVMF_FILEINPUT_NODE_COMMAND_VECTOR_RESERVE);
    133 
    134              //Create the "current command" queue.  It will only contain one
    135              //command at a time, so use a reserve of 1.
    136              iCurrentCommand.Construct(0, 1);
    137 
    138              //Create the port vector.
    139              iPortVector.Construct(PVMF_FILEINPUT_NODE_PORT_VECTOR_RESERVE);
    140 
    141              //Set the node capability data.
    142              //This node can support an unlimited number of ports.
    143              iCapability.iCanSupportMultipleInputPorts = true;
    144              iCapability.iCanSupportMultipleOutputPorts = true;
    145              iCapability.iHasMaxNumberOfPorts = false;
    146              iCapability.iMaxNumberOfPorts = 0;//no maximum
    147              // chesterc: The node only supports the format of the input file, not
    148              // all formats that the node could parse.
    149              iCapability.iOutputFormatCapability.push_back(aSettings->iMediaFormat);
    150 
    151              // construct iSettings
    152              ConstructInputSettings(aSettings);
    153             );
    154 
    155     if (err != OsclErrNone)
    156     {
    157         //if a leave happened, cleanup and re-throw the error
    158         iInputCommands.clear();
    159         iCurrentCommand.clear();
    160         iPortVector.clear();
    161         iCapability.iInputFormatCapability.clear();
    162         iCapability.iOutputFormatCapability.clear();
    163         OSCL_CLEANUP_BASE_CLASS(PVMFNodeInterface);
    164         OSCL_CLEANUP_BASE_CLASS(OsclTimerObject);
    165         OSCL_LEAVE(err);
    166     }
    167 }
    168 
    169 OSCL_EXPORT_REF PVMFDummyFileInputNode::~PVMFDummyFileInputNode()
    170 {
    171     //thread logoff
    172     if (IsAdded())
    173         RemoveFromScheduler();
    174 
    175     //Cleanup allocated interfaces
    176 
    177     //Cleanup allocated ports
    178     while (!iPortVector.empty())
    179         iPortVector.Erase(&iPortVector.front());
    180 
    181     //Cleanup commands
    182     //The command queues are self-deleting, but we want to
    183     //notify the observer of unprocessed commands.
    184     while (!iCurrentCommand.empty())
    185     {
    186         CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFFailure);
    187     }
    188     while (!iInputCommands.empty())
    189     {
    190         CommandComplete(iInputCommands, iInputCommands.front(), PVMFFailure);
    191     }
    192 
    193     CloseInputFile();
    194     iAlloc.deallocate((OsclAny*)iAudioData);
    195     iAlloc.deallocate((OsclAny*)iVideoData);
    196 
    197     if (iMediaBufferMemPool)
    198     {
    199         OSCL_DELETE(iMediaBufferMemPool);
    200         iMediaBufferMemPool = NULL;
    201     }
    202 
    203     if (iMediaDataAlloc)
    204     {
    205         OSCL_DELETE(iMediaDataAlloc);
    206         iMediaDataAlloc = NULL;
    207     }
    208 }
    209 
    210 /**
    211 //////////////////////////////////////////////////
    212 // Public Node API implementation
    213 //////////////////////////////////////////////////
    214 */
    215 
    216 /**
    217 //Do thread-specific node creation and go to "Idle" state.
    218 */
    219 OSCL_EXPORT_REF PVMFStatus PVMFDummyFileInputNode::ThreadLogon()
    220 {
    221     LOGINFO((0, "FileInputNode:ThreadLogon"));
    222     switch (iInterfaceState)
    223     {
    224         case EPVMFNodeCreated:
    225             if (!IsAdded())
    226                 AddToScheduler();
    227             iLogger = PVLogger::GetLoggerObject("PVMFDummyFileInputNode");
    228             SetState(EPVMFNodeIdle);
    229             return PVMFSuccess;
    230             break;
    231         default:
    232             return PVMFErrInvalidState;
    233             break;
    234     }
    235 }
    236 
    237 /**
    238 //Do thread-specific node cleanup and go to "Created" state.
    239 */
    240 OSCL_EXPORT_REF PVMFStatus PVMFDummyFileInputNode::ThreadLogoff()
    241 {
    242     LOGINFO((0, "FileInputNode:ThreadLogoff"));
    243     switch (iInterfaceState)
    244     {
    245         case EPVMFNodeIdle:
    246             if (IsAdded())
    247                 RemoveFromScheduler();
    248             iLogger = NULL;
    249             SetState(EPVMFNodeCreated);
    250             return PVMFSuccess;
    251             break;
    252 
    253         default:
    254             return PVMFErrInvalidState;
    255             break;
    256     }
    257 }
    258 
    259 /**
    260 //retrieve node capabilities.
    261 */
    262 OSCL_EXPORT_REF PVMFStatus PVMFDummyFileInputNode::GetCapability(PVMFNodeCapability& aNodeCapability)
    263 {
    264     LOGINFO((0, "FileInputNode:GetCapability"));
    265     aNodeCapability = iCapability;
    266     return PVMFSuccess;
    267 }
    268 
    269 /**
    270 //retrive a port iterator.
    271 */
    272 OSCL_EXPORT_REF PVMFPortIter* PVMFDummyFileInputNode::GetPorts(const PVMFPortFilter* aFilter)
    273 {
    274     LOGINFO((0, "FileInputNode:GetPorts"));
    275     OSCL_UNUSED_ARG(aFilter);//port filter is not implemented.
    276     iPortVector.Reset();
    277     return &iPortVector;
    278 }
    279 
    280 /**
    281 //Queue an asynchronous node command
    282 */
    283 OSCL_EXPORT_REF PVMFCommandId PVMFDummyFileInputNode::QueryUUID(PVMFSessionId s, const PvmfMimeString& aMimeType,
    284         Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids,
    285         bool aExactUuidsOnly,
    286         const OsclAny* aContext)
    287 {
    288     LOGINFO((0, "FileInputNode:QueryUUID"));
    289     PVMFFileInputNodeCommand cmd;
    290     cmd.PVMFFileInputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_QUERYUUID, aMimeType, aUuids, aExactUuidsOnly, aContext);
    291     return QueueCommandL(cmd);
    292 }
    293 
    294 /**
    295 //Queue an asynchronous node command
    296 */
    297 OSCL_EXPORT_REF PVMFCommandId PVMFDummyFileInputNode::QueryInterface(PVMFSessionId s, const PVUuid& aUuid,
    298         PVInterface*& aInterfacePtr,
    299         const OsclAny* aContext)
    300 {
    301     LOGINFO((0, "FileInputNode:QueryInterface"));
    302     PVMFFileInputNodeCommand cmd;
    303     cmd.PVMFFileInputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_QUERYINTERFACE, aUuid, aInterfacePtr, aContext);
    304     return QueueCommandL(cmd);
    305 }
    306 
    307 /**
    308 //Queue an asynchronous node command
    309 */
    310 OSCL_EXPORT_REF PVMFCommandId PVMFDummyFileInputNode::RequestPort(PVMFSessionId s, int32 aPortTag, const PvmfMimeString* aPortConfig, const OsclAny* aContext)
    311 {
    312     OSCL_UNUSED_ARG(aPortConfig);
    313     LOGINFO((0, "FileInputNode:RequestPort"));
    314     PVMFFileInputNodeCommand cmd;
    315     cmd.PVMFFileInputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_REQUESTPORT, aPortTag, aPortConfig, aContext);
    316     return QueueCommandL(cmd);
    317 }
    318 
    319 /**
    320 //Queue an asynchronous node command
    321 */
    322 OSCL_EXPORT_REF PVMFCommandId PVMFDummyFileInputNode::ReleasePort(PVMFSessionId s, PVMFPortInterface& aPort, const OsclAny* aContext)
    323 {
    324     LOGINFO((0, "FileInputNode:ReleasePort"));
    325     PVMFFileInputNodeCommand cmd;
    326     cmd.PVMFFileInputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_RELEASEPORT, aPort, aContext);
    327     return QueueCommandL(cmd);
    328 }
    329 
    330 /**
    331 //Queue an asynchronous node command
    332 */
    333 OSCL_EXPORT_REF PVMFCommandId PVMFDummyFileInputNode::Init(PVMFSessionId s, const OsclAny* aContext)
    334 {
    335     LOGINFO((0, "FileInputNode:Init"));
    336     PVMFFileInputNodeCommand cmd;
    337     cmd.PVMFFileInputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_INIT, aContext);
    338     return QueueCommandL(cmd);
    339 }
    340 
    341 /**
    342 //Queue an asynchronous node command
    343 */
    344 OSCL_EXPORT_REF PVMFCommandId PVMFDummyFileInputNode::Prepare(PVMFSessionId s, const OsclAny* aContext)
    345 {
    346     LOGINFO((0, "FileInputNode:Prepare"));
    347     PVMFFileInputNodeCommand cmd;
    348     cmd.PVMFFileInputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_PREPARE, aContext);
    349     return QueueCommandL(cmd);
    350 }
    351 
    352 /**
    353 //Queue an asynchronous node command
    354 */
    355 OSCL_EXPORT_REF PVMFCommandId PVMFDummyFileInputNode::Start(PVMFSessionId s, const OsclAny* aContext)
    356 {
    357     LOGINFO((0, "FileInputNode:Start"));
    358     PVMFFileInputNodeCommand cmd;
    359     cmd.PVMFFileInputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_START, aContext);
    360     return QueueCommandL(cmd);
    361 }
    362 
    363 /**
    364 //Queue an asynchronous node command
    365 */
    366 OSCL_EXPORT_REF PVMFCommandId PVMFDummyFileInputNode::Stop(PVMFSessionId s, const OsclAny* aContext)
    367 {
    368     LOGINFO((0, "FileInputNode:Stop"));
    369     PVMFFileInputNodeCommand cmd;
    370     cmd.PVMFFileInputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_STOP, aContext);
    371     return QueueCommandL(cmd);
    372 }
    373 
    374 /**
    375 //Queue an asynchronous node command
    376 */
    377 OSCL_EXPORT_REF PVMFCommandId PVMFDummyFileInputNode::Flush(PVMFSessionId s, const OsclAny* aContext)
    378 {
    379     LOGINFO((0, "FileInputNode:Flush"));
    380     PVMFFileInputNodeCommand cmd;
    381     cmd.PVMFFileInputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_FLUSH, aContext);
    382     return QueueCommandL(cmd);
    383 }
    384 
    385 /**
    386 //Queue an asynchronous node command
    387 */
    388 OSCL_EXPORT_REF PVMFCommandId PVMFDummyFileInputNode::Pause(PVMFSessionId s, const OsclAny* aContext)
    389 {
    390     LOGINFO((0, "FileInputNode:Pause"));
    391     PVMFFileInputNodeCommand cmd;
    392     cmd.PVMFFileInputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_PAUSE, aContext);
    393     return QueueCommandL(cmd);
    394 }
    395 
    396 /**
    397 //Queue an asynchronous node command
    398 */
    399 OSCL_EXPORT_REF PVMFCommandId PVMFDummyFileInputNode::Reset(PVMFSessionId s, const OsclAny* aContext)
    400 {
    401     LOGINFO((0, "FileInputNode:Reset"));
    402     PVMFFileInputNodeCommand cmd;
    403     cmd.PVMFFileInputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_RESET, aContext);
    404     return QueueCommandL(cmd);
    405 }
    406 
    407 /**
    408 //Queue an asynchronous node command
    409 */
    410 OSCL_EXPORT_REF PVMFCommandId PVMFDummyFileInputNode::CancelAllCommands(PVMFSessionId s, const OsclAny* aContext)
    411 {
    412     LOGINFO((0, "FileInputNode:CancelAllCommands"));
    413     PVMFFileInputNodeCommand cmd;
    414     cmd.PVMFFileInputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_CANCELALLCOMMANDS, aContext);
    415     return QueueCommandL(cmd);
    416 }
    417 
    418 /**
    419 //Queue an asynchronous node command
    420 */
    421 OSCL_EXPORT_REF PVMFCommandId PVMFDummyFileInputNode::CancelCommand(PVMFSessionId s, PVMFCommandId aCmdId, const OsclAny* aContext)
    422 {
    423     LOGINFO((0, "FileInputNode:CancelCommand"));
    424     PVMFFileInputNodeCommand cmd;
    425     cmd.PVMFFileInputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_CANCELCOMMAND, aCmdId, aContext);
    426     return QueueCommandL(cmd);
    427 }
    428 
    429 ////////////////////////////////////////////////////////////////////////////
    430 OSCL_EXPORT_REF void PVMFDummyFileInputNode::addRef()
    431 {
    432     ++iExtensionRefCount;
    433 }
    434 
    435 ////////////////////////////////////////////////////////////////////////////
    436 OSCL_EXPORT_REF void PVMFDummyFileInputNode::removeRef()
    437 {
    438     --iExtensionRefCount;
    439 }
    440 
    441 ////////////////////////////////////////////////////////////////////////////
    442 OSCL_EXPORT_REF bool PVMFDummyFileInputNode::queryInterface(const PVUuid& uuid, PVInterface*& iface)
    443 {
    444     if (uuid == KPVMFFileInputNodeExtensionUuid)
    445     {
    446         PVMFFileInputNodeExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFFileInputNodeExtensionInterface*, this);
    447         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
    448         ++iExtensionRefCount;
    449         return true;
    450     }
    451 
    452     return false;
    453 }
    454 
    455 ////////////////////////////////////////////////////////////////////////////
    456 OSCL_EXPORT_REF bool PVMFDummyFileInputNode::GetBitstreamConfig(OsclRefCounterMemFrag& aConfig)
    457 {
    458     if (!iFormatSpecificInfo.getMemFragPtr())
    459         return false;
    460 
    461     aConfig = iFormatSpecificInfo;
    462     return true;
    463 }
    464 
    465 
    466 /**
    467 //This routine is called by various command APIs to queue an
    468 //asynchronous command for processing by the command handler AO.
    469 //This function may leave if the command can't be queued due to
    470 //memory allocation failure.
    471 */
    472 PVMFCommandId PVMFDummyFileInputNode::QueueCommandL(PVMFFileInputNodeCommand& aCmd)
    473 {
    474     PVMFCommandId id;
    475 
    476     id = iInputCommands.AddL(aCmd);
    477 
    478     //wakeup the AO
    479     RunIfNotReady();
    480 
    481     return id;
    482 }
    483 
    484 /**
    485 /////////////////////////////////////////////////////
    486 // Asynchronous Command processing routines.
    487 // These routines are all called under the AO.
    488 /////////////////////////////////////////////////////
    489 */
    490 
    491 /**
    492 //Called by the command handler AO to process a command from
    493 //the input queue.
    494 //Return true if a command was processed, false if the command
    495 //processor is busy and can't process another command now.
    496 */
    497 bool PVMFDummyFileInputNode::ProcessCommand(PVMFFileInputNodeCommand& aCmd)
    498 {
    499     //normally this node will not start processing one command
    500     //until the prior one is finished.  However, a hi priority
    501     //command such as Cancel must be able to interrupt a command
    502     //in progress.
    503     if (!iCurrentCommand.empty() && !aCmd.hipri())
    504         return false;
    505 
    506     switch (aCmd.iCmd)
    507     {
    508         case PVMF_GENERIC_NODE_QUERYUUID:
    509             DoQueryUuid(aCmd);
    510             break;
    511 
    512         case PVMF_GENERIC_NODE_QUERYINTERFACE:
    513             DoQueryInterface(aCmd);
    514             break;
    515 
    516         case PVMF_GENERIC_NODE_REQUESTPORT:
    517             DoRequestPort(aCmd);
    518             break;
    519 
    520         case PVMF_GENERIC_NODE_RELEASEPORT:
    521             DoReleasePort(aCmd);
    522             break;
    523 
    524         case PVMF_GENERIC_NODE_INIT:
    525             DoInit(aCmd);
    526             break;
    527 
    528         case PVMF_GENERIC_NODE_PREPARE:
    529             DoPrepare(aCmd);
    530             break;
    531 
    532         case PVMF_GENERIC_NODE_START:
    533             DoStart(aCmd);
    534             break;
    535 
    536         case PVMF_GENERIC_NODE_STOP:
    537             DoStop(aCmd);
    538             break;
    539 
    540         case PVMF_GENERIC_NODE_FLUSH:
    541             DoFlush(aCmd);
    542             break;
    543 
    544         case PVMF_GENERIC_NODE_PAUSE:
    545             DoPause(aCmd);
    546             break;
    547 
    548         case PVMF_GENERIC_NODE_RESET:
    549             DoReset(aCmd);
    550             break;
    551 
    552         case PVMF_GENERIC_NODE_CANCELALLCOMMANDS:
    553             DoCancelAllCommands(aCmd);
    554             break;
    555 
    556         case PVMF_GENERIC_NODE_CANCELCOMMAND:
    557             DoCancelCommand(aCmd);
    558             break;
    559 
    560         default://unknown command type
    561             CommandComplete(iInputCommands, aCmd, PVMFFailure);
    562             break;
    563     }
    564 
    565     return true;
    566 }
    567 
    568 /**
    569 //The various command handlers call this when a command is complete.
    570 */
    571 void PVMFDummyFileInputNode::CommandComplete(PVMFFileInputNodeCmdQ& aCmdQ, PVMFFileInputNodeCommand& aCmd, PVMFStatus aStatus, OsclAny* aEventData)
    572 {
    573     LOGINFO((0, "FileInputNode:CommandComplete Id %d Cmd %d Status %d Context %d Data %d"
    574              , aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData));
    575 
    576     //create response
    577     PVMFCmdResp resp(aCmd.iId, aCmd.iContext, aStatus, aEventData);
    578     PVMFSessionId session = aCmd.iSession;
    579 
    580     //Erase the command from the queue.
    581     aCmdQ.Erase(&aCmd);
    582 
    583     //Report completion to the session observer.
    584     ReportCmdCompleteEvent(session, resp);
    585 }
    586 
    587 /**
    588 //Called by the command handler AO to do the node Reset.
    589 */
    590 void PVMFDummyFileInputNode::DoReset(PVMFFileInputNodeCommand& aCmd)
    591 {
    592     //This example node allows a reset from any idle state.
    593     switch (iInterfaceState)
    594     {
    595         case EPVMFNodeCreated:
    596         case EPVMFNodeIdle:
    597         case EPVMFNodeInitialized:
    598         case EPVMFNodePrepared:
    599         {
    600             //delete all ports and notify observer.
    601             while (!iPortVector.empty())
    602                 iPortVector.Erase(&iPortVector.front());
    603 
    604             //restore original port vector reserve.
    605             iPortVector.Reconstruct();
    606 
    607             // close the input file
    608             CloseInputFile();
    609 
    610             //logoff & go back to Created state.
    611             SetState(EPVMFNodeIdle);
    612             PVMFStatus status = ThreadLogoff();
    613 
    614             CommandComplete(iInputCommands, aCmd, status);
    615         }
    616         break;
    617 
    618         default:
    619             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
    620             break;
    621     }
    622 }
    623 
    624 /**
    625 //Called by the command handler AO to do the Query UUID
    626 */
    627 void PVMFDummyFileInputNode::DoQueryUuid(PVMFFileInputNodeCommand& aCmd)
    628 {
    629     //This node supports Query UUID from any state
    630 
    631     OSCL_String* mimetype;
    632     Oscl_Vector<PVUuid, OsclMemAllocator> *uuidvec;
    633     bool exactmatch;
    634     aCmd.PVMFFileInputNodeCommandBase::Parse(mimetype, uuidvec, exactmatch);
    635 
    636     //Try to match the input mimetype against any of
    637     //the custom interfaces for this node
    638 
    639     //Match against extension interface...
    640     if (*mimetype == PVMF_FILEINPUT_NODE_EXTENSION_INTERFACE_MIMETYPE
    641             //also match against base mimetypes for custom interface1,
    642             //unless exactmatch is set.
    643             || (!exactmatch && *mimetype == PVMF_FILEINPUT_NODE_MIMETYPE)
    644             || (!exactmatch && *mimetype == PVMF_BASEMIMETYPE))
    645     {
    646 
    647         PVUuid uuid(KPVMFFileInputNodeExtensionUuid);
    648         uuidvec->push_back(uuid);
    649     }
    650     CommandComplete(iInputCommands, aCmd, PVMFSuccess);
    651 }
    652 
    653 /**
    654 //Called by the command handler AO to do the Query Interface.
    655 */
    656 void PVMFDummyFileInputNode::DoQueryInterface(PVMFFileInputNodeCommand& aCmd)
    657 {
    658     //This node supports Query Interface from any state
    659 
    660     PVUuid* uuid;
    661     PVInterface** ptr;
    662     aCmd.PVMFFileInputNodeCommandBase::Parse(uuid, ptr);
    663 
    664     if (*uuid == PVUuid(KPVMFFileInputNodeExtensionUuid))
    665     {
    666         queryInterface(*uuid, *ptr);
    667         CommandComplete(iInputCommands, aCmd, PVMFSuccess);
    668     }
    669     else
    670     {//not supported
    671         *ptr = NULL;
    672         CommandComplete(iInputCommands, aCmd, PVMFFailure);
    673     }
    674 }
    675 
    676 /**
    677 //Called by the command handler AO to do the port request
    678 */
    679 void PVMFDummyFileInputNode::DoRequestPort(PVMFFileInputNodeCommand& aCmd)
    680 {
    681     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    682                     (0, "PVMFDummyFileInputNode::DoRequestPort"));
    683 
    684     //This node supports port request from any state
    685 
    686     //this node is limited to one port
    687     if (iPortVector.size() > 0)
    688     {
    689         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
    690                         (0, "PVMFDummyFileInputNode::DoRequestPort: Multiple port request!"));
    691         CommandComplete(iInputCommands, aCmd, PVMFFailure);
    692     }
    693 
    694     //retrieve port tag.
    695     int32 tag;
    696     OSCL_String* mimetype;
    697     aCmd.PVMFFileInputNodeCommandBase::Parse(tag, mimetype);
    698 
    699     //(mimetype is not used on this node)
    700 
    701     //validate the tag...
    702     switch (tag)
    703     {
    704         case PVMF_DUMMY_FILEINPUT_NODE_PORT_TYPE_SOURCE:
    705             break;
    706         default:
    707         {
    708             //bad port tag
    709             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
    710                             (0, "PVMFDummyFileInputNode::DoRequestPort: Error - Invalid port tag"));
    711             CommandComplete(iInputCommands, aCmd, PVMFFailure);
    712             return;
    713         }
    714         break;
    715     }
    716 
    717     //Allocate a new port
    718     OsclAny *ptr = NULL;
    719     int32 err;
    720     OSCL_TRY(err, ptr = iPortVector.Allocate(););
    721     if (err != OsclErrNone || !ptr)
    722     {
    723         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
    724                         (0, "PVMFDummyFileInputNode::DoRequestPort: Error - iPortVector Out of memory"));
    725         CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
    726         return;
    727     }
    728 
    729     //create base port
    730     PVMFFileDummyInputPort*port = NULL;
    731     port = new(ptr) PVMFFileDummyInputPort(tag
    732                                            , this //the node handles port activity.
    733                                            , INPORT_CAPACITY, INPORT_RESERVE, INPORT_THRESOLD //no input queue needed.
    734                                            , OUTPORT_CAPACITY, OUTPORT_RESERVE, OUTPORT_THRESOLD);//output queue has a limit of 10 with no reserve
    735 
    736     //if format was provided in mimestring, set it now.
    737     if (mimetype)
    738     {
    739         PVMFFormatType fmt = mimetype->get_str();
    740         if (fmt != PVMF_MIME_FORMAT_UNKNOWN
    741                 && port->IsFormatSupported(fmt))
    742         {
    743             port->iFormat = fmt;
    744             port->FormatUpdated();
    745         }
    746     }
    747 
    748     //Add the port to the port vector.
    749     OSCL_TRY(err, iPortVector.AddL(port););
    750     if (err != OsclErrNone)
    751     {
    752         CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
    753         return;
    754     }
    755 
    756     //Return the port pointer to the caller.
    757     CommandComplete(iInputCommands, aCmd, PVMFSuccess, (OsclAny*)port);
    758 }
    759 
    760 /**
    761 //Called by the command handler AO to do the port release
    762 */
    763 void PVMFDummyFileInputNode::DoReleasePort(PVMFFileInputNodeCommand& aCmd)
    764 {
    765     //This node supports release port from any state
    766 
    767     //Find the port in the port vector
    768     PVMFFileDummyInputPort *port;
    769     PVMFPortInterface * tempInterface = NULL;
    770 
    771     aCmd.PVMFFileInputNodeCommandBase::Parse(tempInterface);
    772     port = OSCL_STATIC_CAST(PVMFFileDummyInputPort*, tempInterface);
    773 
    774     PVMFFileDummyInputPort** portPtr = iPortVector.FindByValue(port);
    775     if (portPtr)
    776     {
    777         //delete the port.
    778         iPortVector.Erase(portPtr);
    779         CommandComplete(iInputCommands, aCmd, PVMFSuccess);
    780     }
    781     else
    782     {
    783         //port not found.
    784         CommandComplete(iInputCommands, aCmd, PVMFFailure);
    785     }
    786 }
    787 
    788 /**
    789 //Called by the command handler AO to do the node Init
    790 */
    791 void PVMFDummyFileInputNode::DoInit(PVMFFileInputNodeCommand& aCmd)
    792 {
    793     switch (iInterfaceState)
    794     {
    795         case EPVMFNodeIdle:
    796         {
    797             //this node doesn't need to do anything
    798             PVMFStatus status = Initialize();
    799             if (status == PVMFSuccess)
    800                 SetState(EPVMFNodeInitialized);
    801             //else
    802             //  SetState(EPVMFNodeError);
    803 
    804             CommandComplete(iInputCommands, aCmd, status);
    805         }
    806         break;
    807 
    808         default:
    809             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
    810             break;
    811     }
    812 }
    813 
    814 /**
    815 //Called by the command handler AO to do the node Prepare
    816 */
    817 void PVMFDummyFileInputNode::DoPrepare(PVMFFileInputNodeCommand& aCmd)
    818 {
    819     switch (iInterfaceState)
    820     {
    821         case EPVMFNodeInitialized:
    822             //this node doesn't need to do anything to get ready
    823             //to start.
    824             SetState(EPVMFNodePrepared);
    825             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
    826             break;
    827 
    828         default:
    829             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
    830             break;
    831     }
    832 }
    833 
    834 /**
    835 //Called by the command handler AO to do the node Start
    836 */
    837 void PVMFDummyFileInputNode::DoStart(PVMFFileInputNodeCommand& aCmd)
    838 {
    839     PVMFStatus status = PVMFSuccess;
    840     switch (iInterfaceState)
    841     {
    842         case EPVMFNodePrepared:
    843             iTimeStamp = 0;
    844             // Don't break here. Continue to process start command
    845 
    846         case EPVMFNodePaused:
    847             // If it's a start from stopped or initialized state, iInputFile
    848             // object will be NULL and output file will be opened and read
    849             // from the beginning.
    850             if (!iFileOpen)
    851             {
    852                 if (iFs.Connect() != 0) return;
    853                 iFsOpen = true;
    854 
    855                 if (iInputFile.Open(iSettings.iFileName.get_cstr(), Oscl_File::MODE_READ | Oscl_File::MODE_BINARY, iFs))
    856                     status = PVMFFailure;
    857 
    858                 if (status == PVMFSuccess)
    859                 {
    860                     iFileOpen = true;
    861                     if (iInputFile.Seek(iFileHeaderSize + iFormatSpecificInfoSize, Oscl_File::SEEKSET))
    862                         status = PVMFFailure;
    863                 }
    864             }
    865 
    866             if (status == PVMFSuccess)
    867             {
    868                 //transition to Started
    869                 SetState(EPVMFNodeStarted);
    870             }
    871             //else
    872             //  SetState(EPVMFNodeError);
    873 
    874             break;
    875 
    876         default:
    877             status = PVMFErrInvalidState;
    878             break;
    879     }
    880 
    881     CommandComplete(iInputCommands, aCmd, status);
    882 }
    883 
    884 /**
    885 //Called by the command handler AO to do the node Stop
    886 */
    887 void PVMFDummyFileInputNode::DoStop(PVMFFileInputNodeCommand& aCmd)
    888 {
    889     switch (iInterfaceState)
    890     {
    891         case EPVMFNodeStarted:
    892         case EPVMFNodePaused:
    893 
    894             // Clear queued messages in ports
    895             uint32 i;
    896             for (i = 0; i < iPortVector.size(); i++)
    897                 iPortVector[i]->ClearMsgQueues();
    898 
    899             // Close the input file
    900             CloseInputFile();
    901             iDataEventCounter = 0;
    902 
    903             //transition to Prepared state
    904             SetState(EPVMFNodePrepared);
    905             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
    906             break;
    907 
    908         default:
    909             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
    910             break;
    911     }
    912 }
    913 
    914 /**
    915 //Called by the command handler AO to do the node Flush
    916 */
    917 void PVMFDummyFileInputNode::DoFlush(PVMFFileInputNodeCommand& aCmd)
    918 {
    919     switch (iInterfaceState)
    920     {
    921         case EPVMFNodeStarted:
    922         case EPVMFNodePaused:
    923             //the flush is asynchronous.  move the command from
    924             //the input command queue to the current command, where
    925             //it will remain until the flush completes.
    926             int32 err;
    927             OSCL_TRY(err, iCurrentCommand.StoreL(aCmd););
    928             if (err != OsclErrNone)
    929             {
    930                 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
    931                 return;
    932             }
    933             iInputCommands.Erase(&aCmd);
    934 
    935             //Notify all ports to suspend their input
    936             {
    937                 for (uint32 i = 0; i < iPortVector.size(); i++)
    938                     iPortVector[i]->SuspendInput();
    939             }
    940 
    941             // Close the input file
    942             CloseInputFile();
    943             break;
    944 
    945         default:
    946             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
    947             break;
    948     }
    949 }
    950 
    951 /**
    952 //A routine to tell if a flush operation is in progress.
    953 */
    954 bool PVMFDummyFileInputNode::FlushPending()
    955 {
    956     return (iCurrentCommand.size() > 0
    957             && iCurrentCommand.front().iCmd == PVMF_GENERIC_NODE_FLUSH);
    958 }
    959 
    960 
    961 /**
    962 //Called by the command handler AO to do the node Pause
    963 */
    964 void PVMFDummyFileInputNode::DoPause(PVMFFileInputNodeCommand& aCmd)
    965 {
    966     switch (iInterfaceState)
    967     {
    968         case EPVMFNodeStarted:
    969 
    970             SetState(EPVMFNodePaused);
    971             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
    972             break;
    973         default:
    974             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
    975             break;
    976     }
    977 }
    978 
    979 /**
    980 //Called by the command handler AO to do the Cancel All
    981 */
    982 void PVMFDummyFileInputNode::DoCancelAllCommands(PVMFFileInputNodeCommand& aCmd)
    983 {
    984     //first cancel the current command if any
    985     {
    986         while (!iCurrentCommand.empty())
    987             CommandComplete(iCurrentCommand, iCurrentCommand[0], PVMFErrCancelled);
    988     }
    989 
    990     //next cancel all queued commands
    991     {
    992         //start at element 1 since this cancel command is element 0.
    993         while (iInputCommands.size() > 1)
    994             CommandComplete(iInputCommands, iInputCommands[1], PVMFErrCancelled);
    995     }
    996 
    997     //finally, report cancel complete.
    998     CommandComplete(iInputCommands, aCmd, PVMFSuccess);
    999 }
   1000 
   1001 /**
   1002 //Called by the command handler AO to do the Cancel single command
   1003 */
   1004 void PVMFDummyFileInputNode::DoCancelCommand(PVMFFileInputNodeCommand& aCmd)
   1005 {
   1006     //extract the command ID from the parameters.
   1007     PVMFCommandId id;
   1008     aCmd.PVMFFileInputNodeCommandBase::Parse(id);
   1009 
   1010     //first check "current" command if any
   1011     {
   1012         PVMFFileInputNodeCommand* cmd = iCurrentCommand.FindById(id);
   1013         if (cmd)
   1014         {
   1015             //cancel the queued command
   1016             CommandComplete(iCurrentCommand, *cmd, PVMFErrCancelled);
   1017             //report cancel success
   1018             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   1019             return;
   1020         }
   1021     }
   1022 
   1023     //next check input queue.
   1024     {
   1025         //start at element 1 since this cancel command is element 0.
   1026         PVMFFileInputNodeCommand* cmd = iInputCommands.FindById(id, 1);
   1027         if (cmd)
   1028         {
   1029             //cancel the queued command
   1030             CommandComplete(iInputCommands, *cmd, PVMFErrCancelled);
   1031             //report cancel success
   1032             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   1033             return;
   1034         }
   1035     }
   1036     //if we get here the command isn't queued so the cancel fails.
   1037     CommandComplete(iInputCommands, aCmd, PVMFFailure);
   1038 }
   1039 
   1040 /////////////////////////////////////////////////////
   1041 // Event reporting routines.
   1042 /////////////////////////////////////////////////////
   1043 void PVMFDummyFileInputNode::SetState(TPVMFNodeInterfaceState s)
   1044 {
   1045     LOGINFO((0, "FileInputNode:SetState %d", s));
   1046     PVMFNodeInterface::SetState(s);
   1047 }
   1048 
   1049 void PVMFDummyFileInputNode::ReportErrorEvent(PVMFEventType aEventType, OsclAny* aEventData)
   1050 {
   1051     LOGINFO((0, "FileInputNode:NodeErrorEvent Type %d Data %d"
   1052              , aEventType, aEventData));
   1053 
   1054     PVMFNodeInterface::ReportErrorEvent(aEventType, aEventData);
   1055 }
   1056 
   1057 void PVMFDummyFileInputNode::ReportInfoEvent(PVMFEventType aEventType, OsclAny* aEventData)
   1058 {
   1059     LOGINFO((0, "FileInputNode:NodeInfoEvent Type %d Data %d"
   1060              , aEventType, aEventData));
   1061 
   1062     PVMFNodeInterface::ReportInfoEvent(aEventType, aEventData);
   1063 }
   1064 
   1065 /////////////////////////////////////////////////////
   1066 // Port Processing routines
   1067 /////////////////////////////////////////////////////
   1068 
   1069 void PVMFDummyFileInputNode::HandlePortActivity(const PVMFPortActivity &aActivity)
   1070 {
   1071     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1072                     (0, "0x%x PVMFDummyFileInputNode::PortActivity: port=0x%x, type=%d",
   1073                      this, aActivity.iPort, aActivity.iType));
   1074 
   1075     //A port is reporting some activity or state change.  This code
   1076     //figures out whether we need to queue a processing event
   1077     //for the AO, and/or report a node event to the observer.
   1078 
   1079     //int32 err = 0;
   1080     switch (aActivity.iType)
   1081     {
   1082         case PVMF_PORT_ACTIVITY_CREATED:
   1083             //Report port created info event to the node.
   1084             PVMFNodeInterface::ReportInfoEvent(PVMFInfoPortCreated
   1085                                                , (OsclAny*)aActivity.iPort);
   1086             break;
   1087 
   1088         case PVMF_PORT_ACTIVITY_DELETED:
   1089             //Report port deleted info event to the node.
   1090             PVMFNodeInterface::ReportInfoEvent(PVMFInfoPortDeleted
   1091                                                , (OsclAny*)aActivity.iPort);
   1092             break;
   1093 
   1094         case PVMF_PORT_ACTIVITY_CONNECT:
   1095             break;
   1096 
   1097         case PVMF_PORT_ACTIVITY_DISCONNECT:
   1098             break;
   1099 
   1100         case PVMF_PORT_ACTIVITY_OUTGOING_MSG:
   1101             // chesterc: No RunIfNotReady here. It will be called in Run after SendNewMediaMessage.
   1102             // Calling RunIfNotReady here would screw up frame rate simulation
   1103             break;
   1104 
   1105         case PVMF_PORT_ACTIVITY_INCOMING_MSG:
   1106             break;
   1107 
   1108         case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_BUSY:
   1109             break;
   1110 
   1111         case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY:
   1112             //wakeup to resume queueing outgoing messages.
   1113             RunIfNotReady();
   1114             break;
   1115 
   1116         case PVMF_PORT_ACTIVITY_CONNECTED_PORT_BUSY:
   1117             break;
   1118 
   1119         case PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY:
   1120             //wakeup to resume sending outgoing data.
   1121             RunIfNotReady();
   1122             break;
   1123 
   1124         default:
   1125             break;
   1126     }
   1127 }
   1128 
   1129 
   1130 /**
   1131 /////////////////////////////////////////////////////
   1132 // Active object implementation
   1133 /////////////////////////////////////////////////////
   1134 */
   1135 
   1136 /**
   1137 //Example of a single-AO node implementation.  This AO handles
   1138 //both API commands and port activity.
   1139 //
   1140 //The AO will either process one command, send one outgoing message,
   1141 //or create one new outgoing message per call.
   1142 //It will re-schedule itself and run continuously
   1143 //until it runs out of things to do.
   1144 */
   1145 void PVMFDummyFileInputNode::Run()
   1146 {
   1147     /*
   1148     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
   1149         (0, "0x%x PVMFDummyFileInputNode::Run: ENTER - iInputCommands.size=%d, iPortActivityQueue.size=%d",
   1150         this, iInputCommands.size(), iPortActivityQueue.size()));
   1151     */
   1152 
   1153     //Process commands.
   1154     if (!iInputCommands.empty())
   1155     {
   1156         if (ProcessCommand(iInputCommands.front()))
   1157         {
   1158             //note:it's possible the node could be reset so
   1159             //check isAdded here to avoid scheduler panic.
   1160             if (IsAdded())
   1161                 RunIfNotReady();
   1162             return;
   1163         }
   1164     }
   1165 
   1166     //Process ports
   1167     if (iPortVector.size() > 0)
   1168     {
   1169         //Send output data.
   1170         if (iInterfaceState == EPVMFNodeStarted || FlushPending())
   1171         {
   1172             if (iPortVector[0]->OutgoingMsgQueueSize() > 0
   1173                     && !iPortVector[0]->IsConnectedPortBusy())
   1174             {
   1175                 PVMFStatus status = iPortVector[0]->Send();
   1176                 if (status == PVMFSuccess)
   1177                 {
   1178                     //increment timestamp and frame counter
   1179                     IncTimestamp();
   1180                     ++iDataEventCounter;
   1181                     RunIfNotReady();
   1182                     return;
   1183                 }
   1184                 else if (status == PVMFErrBusy)
   1185                 {
   1186                     return;//wait on port ready callback
   1187                 }
   1188             }
   1189             while (iPortVector[0]->IncomingMsgQueueSize() > 0)
   1190             {
   1191                 // Just purge this data so that we
   1192                 // don't have a memory lockup
   1193                 PVMFSharedMediaMsgPtr aMsg;
   1194                 iPortVector[0]->DequeueIncomingMsg(aMsg);
   1195             }
   1196         }
   1197 
   1198         // Create new data and send to the output queue.
   1199         // chesterc: In flush state, don't queue new data
   1200         if (iInterfaceState == EPVMFNodeStarted && !FlushPending())
   1201         {
   1202             if (!iPortVector[0]->IsOutgoingQueueBusy())
   1203             {
   1204                 PVMFStatus status = SendNewMediaMessage();
   1205                 if (status == PVMFSuccess)
   1206                 {
   1207                     //Re-schedule if not end of file.
   1208                     RunIfNotReady(iTSForRunIfInactive);
   1209                     return;
   1210                 }
   1211             }
   1212         }
   1213 
   1214         //Monitor completion of flush command.
   1215         if (FlushPending())
   1216         {
   1217             if (iPortVector[0]->IncomingMsgQueueSize() > 0
   1218                     || iPortVector[0]->OutgoingMsgQueueSize() > 0)
   1219             {
   1220                 RunIfNotReady();
   1221                 return;//wait on queues to empty.
   1222             }
   1223 
   1224             //Flush is complete.  Go to prepared state.
   1225             SetState(EPVMFNodePrepared);
   1226 
   1227             //resume port input so the ports can be re-started.
   1228             iPortVector[0]->ResumeInput();
   1229 
   1230             CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess);
   1231             RunIfNotReady();
   1232         }
   1233     }
   1234 }
   1235 
   1236 PVMFStatus PVMFDummyFileInputNode::SendNewMediaMessage()
   1237 {
   1238 #ifdef FRAGMENTATION_TEST
   1239     PVMFSharedMediaMsgPtr mediaMsg;
   1240     PVMFSharedMediaMsgPtr mediaMsg2;
   1241     PVMFStatus status = GenerateMediaMessage2(mediaMsg, mediaMsg2);
   1242 #else
   1243     PVMFSharedMediaMsgPtr mediaMsg;
   1244     PVMFStatus status = GenerateMediaMessage(mediaMsg);
   1245 #endif
   1246 
   1247     if (status == PVMFSuccess)
   1248     {
   1249         status = iPortVector[0]->QueueOutgoingMsg(mediaMsg);
   1250 
   1251         if (status == PVMFSuccess)
   1252         {
   1253             //keep count of the number of source
   1254             //frames generated on this port.
   1255             iPortVector[0]->iNumFramesGenerated++;
   1256         }
   1257         else
   1258         {
   1259             //just discard the data...
   1260             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
   1261                             (0, "PVMFDummyFileInputNode::SendNewMediaMessage: Data lost!. "));
   1262         }
   1263 #ifdef FRAGMENTATION_TEST
   1264         if (!iEndOfFileReached)
   1265         {
   1266             // 2nd message exists unless EOF
   1267             status = iPortVector[0]->QueueOutgoingMsg(mediaMsg2);
   1268 
   1269             if (status == PVMFSuccess)
   1270             {
   1271                 //keep count of the number of source
   1272                 //frames generated on this port.
   1273                 iPortVector[0]->iNumFramesGenerated++;
   1274             }
   1275             else
   1276             {
   1277                 //just discard the data...
   1278                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
   1279                                 (0, "PVMFDummyFileInputNode::SendNewMediaMessage: Data lost!. "));
   1280             }
   1281         }
   1282 #endif
   1283 
   1284     }
   1285     else if (iEndOfFileReached)
   1286     {
   1287         // end of file
   1288     }
   1289     else if (status != PVMFErrNoMemory) // excluding the case that memory pool runs out of memory
   1290     {
   1291         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
   1292                         (0, "PVMFDummyFileInputNode::SendNewMediaMessage: Error - GenerateData failed"));
   1293         PVMFNodeInterface* node = OSCL_STATIC_CAST(PVMFNodeInterface*, this);
   1294         ReportErrorEvent(PVMF_FILEINPUT_NODE_ERROR_DATA_GENERATING_ERROR, (OsclAny*)node);
   1295     }
   1296 
   1297     return status;
   1298 }
   1299 
   1300 void PVMFDummyFileInputNode::DoCancel()
   1301 {//the base class cancel operation is sufficient.
   1302     OsclTimerObject::DoCancel();
   1303 }
   1304 
   1305 
   1306 ////////////////////////////////////////////////////////////////////////////
   1307 void PVMFDummyFileInputNode::ConstructInputSettings(PVMFFileInputSettings* aSettings)
   1308 {
   1309     iSettings.iFileName = aSettings->iFileName;
   1310     iSettings.iFrameHeight = aSettings->iFrameHeight;
   1311     iSettings.iFrameRate = aSettings->iFrameRate;
   1312     iSettings.iFrameWidth = aSettings->iFrameWidth;
   1313     iSettings.iLoopInputFile = aSettings->iLoopInputFile;
   1314     iSettings.iMediaFormat = aSettings->iMediaFormat;
   1315     iSettings.iNumChannels = aSettings->iNumChannels;
   1316     iSettings.iSamplingFrequency = aSettings->iSamplingFrequency;
   1317     iSettings.iTimescale = aSettings->iTimescale;
   1318     iSettings.iNum20msFramesPerChunk = aSettings->iNum20msFramesPerChunk;
   1319     iSettings.iFrameRateSimulation = aSettings->iFrameRateSimulation;
   1320     iSettings.iFirstFrameTimestamp = aSettings->iFirstFrameTimestamp;
   1321     iSettings.iBitrate = aSettings->iBitrate;
   1322 }
   1323 
   1324 ////////////////////////////////////////////////////////////////////////////
   1325 void PVMFDummyFileInputNode::CloseInputFile()
   1326 {
   1327     if (iFileOpen)
   1328     {
   1329         iInputFile.Close();
   1330         iFileOpen = false;
   1331     }
   1332 
   1333     if (iFsOpen)
   1334     {
   1335         iFs.Close();
   1336         iFsOpen = false;
   1337     }
   1338 }
   1339 
   1340 ////////////////////////////////////////////////////////////////////////////
   1341 PVMFStatus PVMFDummyFileInputNode::Initialize()
   1342 {
   1343     if (iFs.Connect() != 0) return 0;
   1344 
   1345     iFsOpen = true;
   1346 
   1347     if (0 != iInputFile.Open(iSettings.iFileName.get_cstr(), Oscl_File::MODE_READ | Oscl_File::MODE_BINARY, iFs))
   1348     {
   1349         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
   1350                         (0, "PVMFDummyFileInputNode::HandleCmdInit: Error - iInputFile.Open failed"));
   1351         return PVMFFailure;
   1352     }
   1353 
   1354 
   1355     iFileOpen = true;
   1356     uint32 maxFrameSize = 0;
   1357 
   1358     if (iSettings.iMediaFormat == PVMF_MIME_H2632000)
   1359     {
   1360         int32 fileStart = iInputFile.Tell();
   1361         iInputFile.Seek(0, Oscl_File::SEEKEND);
   1362         int32 fileEnd = iInputFile.Tell();
   1363         iInputFile.Seek(fileStart, Oscl_File::SEEKSET);
   1364         int32 fileSize = fileEnd - fileStart;
   1365 
   1366         // Validate settings
   1367         if (iSettings.iFrameHeight <= 0 || iSettings.iFrameWidth <= 0 ||
   1368                 iSettings.iFrameRate <= 0 || iSettings.iTimescale <= 0)
   1369         {
   1370             CloseInputFile();
   1371             return PVMFErrArgument;
   1372         }
   1373 
   1374         fileStart = iInputFile.Tell();
   1375         iInputFile.Seek(0, Oscl_File::SEEKEND);
   1376         fileEnd = iInputFile.Tell();
   1377         iInputFile.Seek(fileStart, Oscl_File::SEEKSET);
   1378         fileSize = fileEnd - fileStart;
   1379         iVideoData = (uint8*)iAlloc.allocate(fileSize);
   1380         if (!iVideoData)
   1381         {
   1382             CloseInputFile();
   1383             return PVMFErrNoMemory;
   1384         }
   1385 
   1386         // Read the whole file to data buffer then go back to front
   1387         iInputFile.Read((OsclAny*)iVideoData, sizeof(uint8), fileSize);
   1388         iInputFile.Seek(fileStart, Oscl_File::SEEKSET);
   1389         iMilliSecondsPerDataEvent = (int32)(1000 / iSettings.iFrameRate);
   1390         iMicroSecondsPerDataEvent = iMilliSecondsPerDataEvent * 1000;
   1391 
   1392     }
   1393 
   1394     else if (iSettings.iMediaFormat == PVMF_MIME_AMR_IF2)
   1395     {
   1396         int32 fileStart, fileEnd, fileSize;
   1397         fileStart = iInputFile.Tell();
   1398         iInputFile.Seek(0, Oscl_File::SEEKEND);
   1399         fileEnd = iInputFile.Tell();
   1400         iInputFile.Seek(fileStart, Oscl_File::SEEKSET);
   1401         fileSize = fileEnd - fileStart;
   1402         iAudioData = (uint8*)iAlloc.allocate(fileSize);
   1403         if (!iAudioData)
   1404         {
   1405             CloseInputFile();
   1406             return PVMFErrNoMemory;
   1407         }
   1408 
   1409         // Read the whole file to data buffer then go back to front
   1410         iInputFile.Read((OsclAny*)iAudioData, sizeof(uint8), fileSize);
   1411         iInputFile.Seek(fileStart, Oscl_File::SEEKSET);
   1412 
   1413     }
   1414     else
   1415         CloseInputFile();
   1416     return PVMFErrArgument;
   1417 
   1418     iDataEventCounter = 0;
   1419     CloseInputFile();
   1420 
   1421     // Create memory pool for the media data, using the maximum frame size found earlier
   1422     int32 err = 0;
   1423     OSCL_TRY(err,
   1424              if (iMediaBufferMemPool)
   1425 {
   1426     OSCL_DELETE(iMediaBufferMemPool);
   1427         iMediaBufferMemPool = NULL;
   1428     }
   1429     iMediaBufferMemPool = OSCL_NEW(OsclMemPoolFixedChunkAllocator,
   1430                                    (PVFILEIN_MEDIADATA_POOLNUM));
   1431     if (!iMediaBufferMemPool)
   1432     OSCL_LEAVE(OsclErrNoMemory);
   1433 
   1434     if (iMediaDataAlloc)
   1435     {
   1436         OSCL_DELETE(iMediaDataAlloc);
   1437             iMediaDataAlloc = NULL;
   1438         }
   1439     iMediaDataAlloc = OSCL_NEW(PVMFSimpleMediaBufferCombinedAlloc, (iMediaBufferMemPool));
   1440     if (!iMediaDataAlloc)
   1441     OSCL_LEAVE(OsclErrNoMemory);
   1442 
   1443     // The first allocate call will set the chunk size of the memory pool. Use the max
   1444     // frame size calculated earlier to set the chunk size.  The allocated data will be
   1445     // deallocated automatically as tmpPtr goes out of scope.
   1446     OsclSharedPtr<PVMFMediaDataImpl> tmpPtr = iMediaDataAlloc->allocate(maxFrameSize);
   1447             );
   1448     if (err != OsclErrNone)
   1449         return PVMFFailure;
   1450 
   1451     return PVMFSuccess;
   1452 }
   1453 
   1454 void PVMFDummyFileInputNode::IncTimestamp()
   1455 {
   1456     //Increment running timestamp if needed.
   1457     if (iSettings.iMediaFormat == PVMF_MIME_AMR_IF2)
   1458     {
   1459         iTimeStamp += iMilliSecondsPerDataEvent;
   1460     }
   1461 }
   1462 
   1463 void PVMFDummyFileInputNode::freechunkavailable(OsclAny* aContextData)
   1464 {
   1465     OSCL_UNUSED_ARG(aContextData);
   1466     if (iWaitingOnFreeChunk)
   1467     {
   1468         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
   1469                         (0, "PVMFDummyFileInputNode::freechunkavailable: Resuming processing, free chunk available."));
   1470         iWaitingOnFreeChunk = false;
   1471         if (IsAdded())
   1472         {
   1473             RunIfNotReady();
   1474         }
   1475     }
   1476 }
   1477 
   1478 
   1479 PVMFStatus PVMFDummyFileInputNode::GenerateMediaMessage(PVMFSharedMediaMsgPtr& aMediaMsg)
   1480 {
   1481 
   1482     if (iInterfaceState != EPVMFNodeStarted)
   1483     {
   1484         return PVMFSuccess;
   1485     }
   1486 
   1487     uint32 bytesToRead = 0;
   1488     uint32 timeStamp = 0;
   1489 
   1490     //Find the frame...
   1491     if (!((iSettings.iMediaFormat == PVMF_MIME_H2632000) || (iSettings.iMediaFormat == PVMF_MIME_AMR_IF2)))
   1492     {
   1493         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
   1494                         (0, "PVMFDummyFileInputNode::HandleEventPortActivity: Error - Unsupported media format"));
   1495         return PVMFFailure;
   1496     }
   1497 
   1498     if (timeStamp < iSettings.iFirstFrameTimestamp)
   1499     {
   1500         // Search for the first frame greater than the specified start time
   1501         iTSForRunIfInactive = 0;
   1502         return PVMFSuccess;
   1503     }
   1504 
   1505     // Create new media data buffer
   1506 
   1507     PVMFSharedMediaDataPtr mediaData;
   1508     int32 err = 0;
   1509     OSCL_TRY(err,
   1510              OsclSharedPtr<PVMFMediaDataImpl> mediaDataImpl = iMediaDataAlloc->allocate(bytesToRead);
   1511              mediaData = PVMFMediaData::createMediaData(mediaDataImpl, &iMediaDataMemPool);
   1512             );
   1513     if (err != OsclErrNone)
   1514     {
   1515         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
   1516                         (0, "PVMFDummyFileInputNode::HandleEventPortActivity: Mempool empty-- calling notifyfreechunkavailable"));
   1517         //register to receive notice when memory is available.
   1518         iMediaBufferMemPool->notifyfreechunkavailable(*this);
   1519         iWaitingOnFreeChunk = true;
   1520         return PVMFErrNoMemory;
   1521     }
   1522 
   1523     // Retrieve memory fragment to write to
   1524 
   1525     OsclRefCounterMemFrag refCtrMemFrag;
   1526     mediaData->getMediaFragment(0, refCtrMemFrag);
   1527     if (refCtrMemFrag.getCapacity() < bytesToRead)
   1528         return PVMFFailure;
   1529 
   1530 
   1531     // For AAC Latm, read the marker info before reading the data
   1532 
   1533     // Read the frame from file
   1534 
   1535     //uint32 len = iInputFile.Read(refCtrMemFrag.getMemFragPtr(), sizeof(uint8), bytesToRead );
   1536     if (iSettings.iMediaFormat == PVMF_MIME_H2632000)
   1537     {
   1538         oscl_memcpy(refCtrMemFrag.getMemFragPtr(), iVideoData, sizeof(iVideoData));
   1539         // update the filled length of the fragment
   1540         mediaData->setMediaFragFilledLen(0, sizeof(iVideoData));
   1541     }
   1542     else
   1543     {
   1544         oscl_memcpy(refCtrMemFrag.getMemFragPtr(), iAudioData, sizeof(iAudioData));
   1545         // update the filled length of the fragment
   1546         mediaData->setMediaFragFilledLen(0, sizeof(iAudioData));
   1547     }
   1548 
   1549     // Set timestamp
   1550     mediaData->setTimestamp(timeStamp);
   1551     // Set sequence number
   1552     mediaData->setSeqNum(iDataEventCounter);
   1553 
   1554     if (iSettings.iMediaFormat == PVMF_MIME_H2632000)
   1555 
   1556     {
   1557         // For M4V and H263 data always set the marker bit to 1
   1558         OsclSharedPtr<PVMFMediaDataImpl> media_data_impl;
   1559         mediaData->getMediaDataImpl(media_data_impl);
   1560         media_data_impl->setMarkerInfo(1);
   1561     }
   1562 
   1563 
   1564     // Set format specific info in media data message
   1565 #ifndef SEND_CONFIGINFO_SEPARATELY
   1566     mediaData->setFormatSpecificInfo(iFormatSpecificInfo);
   1567 #else
   1568     if (iSetFormatSpecificInfo)
   1569     {
   1570         // Create new media data buffer
   1571         OsclSharedPtr<PVMFMediaDataImpl> emptyImpl = iMediaDataAlloc.allocate(0);
   1572         PVMFSharedMediaDataPtr volData;
   1573         int errcode = 0;
   1574         OSCL_TRY(errcode, volData = PVMFMediaData::createMediaData(emptyImpl, &iMediaDataMemPool));
   1575         OSCL_FIRST_CATCH_ANY(errcode, return PVMFErrNoMemory);
   1576 
   1577         // Set format specific info in media data message
   1578         volData->setFormatSpecificInfo(iFormatSpecificInfo);
   1579 
   1580         // Send VOL header to downstream node
   1581         PVMFSharedMediaMsgPtr volMsg;
   1582         convertToPVMFMediaMsg(volMsg, volData);
   1583         iSetFormatSpecificInfo = false;
   1584 
   1585         ++iDataEventCounter;
   1586         return PVMFSuccess;
   1587     }
   1588 #endif
   1589 
   1590     // Send frame to downstream node
   1591 
   1592     convertToPVMFMediaMsg(aMediaMsg, mediaData);
   1593 
   1594     // Queue the next data event
   1595     if (iSettings.iFrameRateSimulation)
   1596         iTSForRunIfInactive = iMicroSecondsPerDataEvent;
   1597     else
   1598         iTSForRunIfInactive = 0;
   1599 
   1600     return PVMFSuccess;
   1601 }
   1602 
   1603 
   1604 int32 PVMFDummyFileInputNode::GetIF2FrameSize(uint8 aFrameType)
   1605 {
   1606     // Last 4 bits of first byte of the package is frame type
   1607     uint8 frameType = (uint8)(0x0f & aFrameType);
   1608 
   1609     // Find frame size for each frame type
   1610     switch (frameType)
   1611     {
   1612         case 0: // AMR 4.75 Kbps
   1613             return 13;
   1614         case 1: // AMR 5.15 Kbps
   1615             return 14;
   1616         case 2: // AMR 5.90 Kbps
   1617             return 16;
   1618         case 3: // AMR 6.70 Kbps
   1619             return 18;
   1620         case 4: // AMR 7.40 Kbps
   1621             return 19;
   1622         case 5: // AMR 7.95 Kbps
   1623             return 21;
   1624         case 6: // AMR 10.2 Kbps
   1625             return 26;
   1626         case 7: // AMR 12.2 Kbps
   1627             return 31;
   1628         case 8: // AMR Frame SID
   1629         case 9: // AMR Frame GSM EFR SID
   1630         case 10: // AMR Frame TDMA EFR SID
   1631         case 11: // AMR Frame PDC EFR SID
   1632             return 6;
   1633         case 15: // AMR Frame No Data
   1634             return 1;
   1635         default: // Error - For Future Use
   1636             return -1;
   1637     }
   1638 }
   1639 
   1640 int32 PVMFDummyFileInputNode::LocateH263FrameHeader(uint8 *video_buffer, int32 vop_size)
   1641 {
   1642     int32 idx;
   1643     uint8 *ptr;
   1644 
   1645     idx = 1;
   1646     ptr = video_buffer + 1;
   1647     vop_size -= 4;
   1648     do
   1649     {
   1650         ptr--;
   1651         idx--;
   1652         for (;;)
   1653         {
   1654             if (ptr[1])
   1655             {
   1656                 ptr += 2;
   1657                 idx += 2;
   1658             }
   1659             else if (ptr[0])
   1660             {
   1661                 ptr++;
   1662                 idx++;
   1663             }
   1664             else
   1665             {
   1666                 break;
   1667             }
   1668             if (idx >= vop_size) return -1;
   1669         }
   1670         ptr += 2;
   1671         idx += 2;
   1672     }
   1673     while ((video_buffer[idx] & 0xfc) != 0x80);
   1674 
   1675     return idx - 2;
   1676 }
   1677