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 /**
     19  *
     20  * @file pvmf_fileoutput_node.cpp
     21  * @brief Simple file output node. Writes incoming data to specified
     22  * file
     23  *
     24  */
     25 
     26 #include "pvmf_fileoutput_inport.h"
     27 #include "pvmf_fileoutput_node.h"
     28 #include "pvlogger.h"
     29 #include "oscl_error_codes.h"
     30 #include "pvmf_media_cmd.h"
     31 #include "pvmf_media_msg_format_ids.h"
     32 #include "pvmf_timedtext.h"
     33 
     34 ////////////////////////////////////////////////////////////////////////////
     35 PVMFFileOutputNode::PVMFFileOutputNode(int32 aPriority)
     36         : OsclActiveObject(aPriority, "PVMFFileOutputNode")
     37         , iCmdIdCounter(0)
     38         , iInPort(NULL)
     39         , iFileHandle(NULL)
     40         , iFileOpened(0)
     41         , iFirstMediaData(false)
     42         , iLogger(NULL)
     43         , iFormat(PVMF_MIME_FORMAT_UNKNOWN)
     44         , iExtensionRefCount(0)
     45         , iMaxFileSizeEnabled(false)
     46         , iMaxDurationEnabled(false)
     47         , iMaxFileSize(0)
     48         , iMaxDuration(0)
     49         , iFileSize(0)
     50         , iFileSizeReportEnabled(false)
     51         , iDurationReportEnabled(false)
     52         , iFileSizeReportFreq(0)
     53         , iDurationReportFreq(0)
     54         , iNextFileSizeReport(0)
     55         , iNextDurationReport(0)
     56         , iClock(NULL)
     57         , iEarlyMargin(DEFAULT_EARLY_MARGIN)
     58         , iLateMargin(DEFAULT_LATE_MARGIN)
     59 {
     60     ConstructL();
     61     int32 err;
     62     OSCL_TRY(err,
     63 
     64              //Create the input command queue.  Use a reserve to avoid lots of
     65              //dynamic memory allocation.
     66              iInputCommands.Construct(PVMF_FILE_OUTPUT_NODE_COMMAND_ID_START, PVMF_FILE_OUTPUT_NODE_COMMAND_VECTOR_RESERVE);
     67 
     68              //Create the "current command" queue.  It will only contain one
     69              //command at a time, so use a reserve of 1.
     70              iCurrentCommand.Construct(0, 1);
     71 
     72              //Create the port vector.
     73              iPortVector.Construct(PVMF_FILE_OUTPUT_NODE_PORT_VECTOR_RESERVE);
     74 
     75              //Set the node capability data.
     76              //This node can support an unlimited number of ports.
     77              iCapability.iCanSupportMultipleInputPorts = false;
     78              iCapability.iCanSupportMultipleOutputPorts = false;
     79              iCapability.iHasMaxNumberOfPorts = true;
     80              iCapability.iMaxNumberOfPorts = 1;
     81             );
     82 
     83     if (err != OsclErrNone)
     84     {
     85         //if a leave happened, cleanup and re-throw the error
     86         iInputCommands.clear();
     87         iCurrentCommand.clear();
     88         iPortVector.clear();
     89         iCapability.iInputFormatCapability.clear();
     90         iCapability.iOutputFormatCapability.clear();
     91         OSCL_CLEANUP_BASE_CLASS(PVMFNodeInterface);
     92         OSCL_CLEANUP_BASE_CLASS(OsclActiveObject);
     93         OSCL_LEAVE(err);
     94     }
     95     ChangeNodeState(EPVMFNodeCreated);
     96 }
     97 
     98 ////////////////////////////////////////////////////////////////////////////
     99 PVMFFileOutputNode::~PVMFFileOutputNode()
    100 {
    101     //thread logoff
    102     if (IsAdded())
    103         RemoveFromScheduler();
    104 
    105     //Cleanup allocated interfaces
    106 
    107 
    108     //Cleanup allocated ports
    109     if (iInPort)
    110     {
    111         OSCL_DELETE(((PVMFFileOutputInPort*)iInPort));
    112         iInPort = NULL;
    113     }
    114 
    115     //Cleanup commands
    116     //The command queues are self-deleting, but we want to
    117     //notify the observer of unprocessed commands.
    118     while (!iCurrentCommand.empty())
    119     {
    120         CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFFailure);
    121     }
    122     while (!iInputCommands.empty())
    123     {
    124         CommandComplete(iInputCommands, iInputCommands.front(), PVMFFailure);
    125     }
    126 
    127     //cleanup port activity events
    128     iPortActivityQueue.clear();
    129 
    130 
    131     if (iAlloc)
    132     {
    133         OSCL_DELETE(iAlloc);
    134     }
    135 }
    136 
    137 ////////////////////////////////////////////////////////////////////////////
    138 void PVMFFileOutputNode::ConstructL()
    139 {
    140     iAlloc = (Oscl_DefAlloc*)(new PVMFFileOutputAlloc());
    141 }
    142 
    143 ////////////////////////////////////////////////////////////////////////////
    144 PVMFStatus PVMFFileOutputNode::ThreadLogon()
    145 {
    146     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFFileOutputNode:ThreadLogon"));
    147 
    148     switch (iInterfaceState)
    149     {
    150         case EPVMFNodeCreated:
    151             if (!IsAdded())
    152                 AddToScheduler();
    153             iLogger = PVLogger::GetLoggerObject("PVMFFileOutputNode");
    154             SetState(EPVMFNodeIdle);
    155             return PVMFSuccess;
    156         default:
    157             return PVMFErrInvalidState;
    158     }
    159 }
    160 
    161 ////////////////////////////////////////////////////////////////////////////
    162 PVMFStatus PVMFFileOutputNode::ThreadLogoff()
    163 {
    164     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFFileOutputNode:ThreadLogoff"));
    165 
    166     switch (iInterfaceState)
    167     {
    168         case EPVMFNodeIdle:
    169             if (IsAdded())
    170                 RemoveFromScheduler();
    171             iLogger = NULL;
    172             SetState(EPVMFNodeCreated);
    173             return PVMFSuccess;
    174 
    175         default:
    176             return PVMFErrInvalidState;
    177     }
    178 }
    179 
    180 ////////////////////////////////////////////////////////////////////////////
    181 void PVMFFileOutputNode::CloseOutputFile()
    182 {
    183     // Close output file
    184     if (iFileOpened)
    185     {
    186         iOutputFile.Close();
    187         iFs.Close();
    188         iFileOpened = 0;
    189     }
    190 }
    191 
    192 ////////////////////////////////////////////////////////////////////////////
    193 PVMFCommandId PVMFFileOutputNode::Init(PVMFSessionId s, const OsclAny* aContext)
    194 {
    195     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFFileOutputNode:Init"));
    196     PVMFFileOutputNodeCommand cmd;
    197     cmd.PVMFFileOutputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_INIT, aContext);
    198     return QueueCommandL(cmd);
    199 }
    200 
    201 ////////////////////////////////////////////////////////////////////////////
    202 PVMFCommandId PVMFFileOutputNode::Prepare(PVMFSessionId s, const OsclAny* aContext)
    203 {
    204     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFFileOutputNode:Prepare"));
    205     PVMFFileOutputNodeCommand cmd;
    206     cmd.PVMFFileOutputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_PREPARE, aContext);
    207     return QueueCommandL(cmd);
    208 }
    209 
    210 ////////////////////////////////////////////////////////////////////////////
    211 PVMFStatus PVMFFileOutputNode::GetCapability(PVMFNodeCapability& aNodeCapability)
    212 {
    213     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFFileOutputNode:GetCapability"));
    214     iCapability.iInputFormatCapability.clear();
    215 
    216     if (iFormat != PVMF_MIME_FORMAT_UNKNOWN)
    217     {
    218         // Format is already set, so return only that one
    219         iCapability.iInputFormatCapability.push_back(iFormat);
    220     }
    221     else
    222     {
    223         iCapability.iInputFormatCapability.push_back(PVMF_MIME_AMR_IETF);
    224         iCapability.iInputFormatCapability.push_back(PVMF_MIME_AMRWB_IETF);
    225         iCapability.iInputFormatCapability.push_back(PVMF_MIME_M4V);
    226         iCapability.iInputFormatCapability.push_back(PVMF_MIME_PCM8);
    227         iCapability.iInputFormatCapability.push_back(PVMF_MIME_PCM16);
    228         iCapability.iInputFormatCapability.push_back(PVMF_MIME_YUV420);
    229         iCapability.iInputFormatCapability.push_back(PVMF_MIME_ADTS);
    230         iCapability.iInputFormatCapability.push_back(PVMF_MIME_H2631998);
    231         iCapability.iInputFormatCapability.push_back(PVMF_MIME_H2632000);
    232         iCapability.iInputFormatCapability.push_back(PVMF_MIME_H264_VIDEO_RAW);
    233         iCapability.iInputFormatCapability.push_back(PVMF_MIME_H264_VIDEO_MP4);
    234         iCapability.iInputFormatCapability.push_back(PVMF_MIME_H264_VIDEO);
    235         iCapability.iInputFormatCapability.push_back(PVMF_MIME_PCM);
    236         iCapability.iInputFormatCapability.push_back(PVMF_MIME_3GPP_TIMEDTEXT);
    237     }
    238     aNodeCapability = iCapability;
    239     return PVMFSuccess;
    240 }
    241 
    242 
    243 ////////////////////////////////////////////////////////////////////////////
    244 PVMFCommandId PVMFFileOutputNode::QueryUUID(PVMFSessionId s, const PvmfMimeString& aMimeType,
    245         Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids,
    246         bool aExactUuidsOnly,
    247         const OsclAny* aContext)
    248 {
    249     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFFileOutputNode:QueryUUID"));
    250 
    251     PVMFFileOutputNodeCommand cmd;
    252     cmd.PVMFFileOutputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_QUERYUUID, aMimeType, aUuids, aExactUuidsOnly, aContext);
    253     return QueueCommandL(cmd);
    254 }
    255 
    256 ////////////////////////////////////////////////////////////////////////////
    257 PVMFCommandId PVMFFileOutputNode::QueryInterface(PVMFSessionId s, const PVUuid& aUuid,
    258         PVInterface*& aInterfacePtr,
    259         const OsclAny* aContext)
    260 {
    261     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFFileOutputNode:QueryInterface"));
    262 
    263     PVMFFileOutputNodeCommand cmd;
    264     cmd.PVMFFileOutputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_QUERYINTERFACE, aUuid, aInterfacePtr, aContext);
    265     return QueueCommandL(cmd);
    266 }
    267 
    268 ////////////////////////////////////////////////////////////////////////////
    269 PVMFCommandId PVMFFileOutputNode::RequestPort(PVMFSessionId s, int32 aPortTag, const PvmfMimeString* aPortConfig, const OsclAny* aContext)
    270 {
    271     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFFileOutputNode:RequestPort"));
    272     PVMFFileOutputNodeCommand cmd;
    273     cmd.PVMFFileOutputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_REQUESTPORT, aPortTag, aPortConfig, aContext);
    274     return QueueCommandL(cmd);
    275 }
    276 
    277 
    278 ////////////////////////////////////////////////////////////////////////////
    279 PVMFCommandId PVMFFileOutputNode::ReleasePort(PVMFSessionId s, PVMFPortInterface& aPort, const OsclAny* aContext)
    280 {
    281     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFFileOutputNode:ReleasePort"));
    282     PVMFFileOutputNodeCommand cmd;
    283     cmd.PVMFFileOutputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_RELEASEPORT, aPort, aContext);
    284     return QueueCommandL(cmd);
    285 }
    286 
    287 
    288 ////////////////////////////////////////////////////////////////////////////
    289 PVMFPortIter* PVMFFileOutputNode::GetPorts(const PVMFPortFilter* aFilter)
    290 {
    291     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFFileOutputNode:GetPorts"));
    292 
    293     OSCL_UNUSED_ARG(aFilter);//port filter is not implemented.
    294     iPortVector.Reset();
    295     return &iPortVector;
    296 }
    297 
    298 
    299 ////////////////////////////////////////////////////////////////////////////
    300 PVMFCommandId PVMFFileOutputNode::Start(PVMFSessionId s, const OsclAny* aContext)
    301 {
    302     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFFileOutputNode:Start"));
    303     PVMFFileOutputNodeCommand cmd;
    304     cmd.PVMFFileOutputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_START, aContext);
    305     return QueueCommandL(cmd);
    306 }
    307 
    308 
    309 
    310 ////////////////////////////////////////////////////////////////////////////
    311 PVMFCommandId PVMFFileOutputNode::Stop(PVMFSessionId s, const OsclAny* aContext)
    312 {
    313     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFFileOutputNode:Stop"));
    314     PVMFFileOutputNodeCommand cmd;
    315     cmd.PVMFFileOutputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_STOP, aContext);
    316     return QueueCommandL(cmd);
    317 }
    318 
    319 ////////////////////////////////////////////////////////////////////////////
    320 /**
    321 //Queue an asynchronous node command
    322 */
    323 PVMFCommandId PVMFFileOutputNode::Flush(PVMFSessionId s, const OsclAny* aContext)
    324 {
    325     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFFileOutputNode:Flush"));
    326     PVMFFileOutputNodeCommand cmd;
    327     cmd.PVMFFileOutputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_FLUSH, aContext);
    328     return QueueCommandL(cmd);
    329 }
    330 
    331 ////////////////////////////////////////////////////////////////////////////
    332 PVMFCommandId PVMFFileOutputNode::Pause(PVMFSessionId s, const OsclAny* aContext)
    333 {
    334     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFFileOutputNode:Pause"));
    335     PVMFFileOutputNodeCommand cmd;
    336     cmd.PVMFFileOutputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_PAUSE, aContext);
    337     return QueueCommandL(cmd);
    338 }
    339 
    340 
    341 ////////////////////////////////////////////////////////////////////////////
    342 PVMFCommandId PVMFFileOutputNode::Reset(PVMFSessionId s, const OsclAny* aContext)
    343 {
    344     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFFileOutputNode:Reset"));
    345     PVMFFileOutputNodeCommand cmd;
    346     cmd.PVMFFileOutputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_RESET, aContext);
    347     return QueueCommandL(cmd);
    348 }
    349 
    350 
    351 ////////////////////////////////////////////////////////////////////////////
    352 PVMFCommandId PVMFFileOutputNode::CancelAllCommands(PVMFSessionId s, const OsclAny* aContext)
    353 {
    354     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFFileOutputNode:CancelAllCommands"));
    355     PVMFFileOutputNodeCommand cmd;
    356     cmd.PVMFFileOutputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_CANCELALLCOMMANDS, aContext);
    357     return QueueCommandL(cmd);
    358 }
    359 
    360 
    361 
    362 ////////////////////////////////////////////////////////////////////////////
    363 PVMFCommandId PVMFFileOutputNode::CancelCommand(PVMFSessionId s, PVMFCommandId aCmdId, const OsclAny* aContext)
    364 {
    365     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFFileOutputNode:CancelCommand"));
    366     PVMFFileOutputNodeCommand cmd;
    367     cmd.PVMFFileOutputNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_CANCELCOMMAND, aCmdId, aContext);
    368     return QueueCommandL(cmd);
    369 }
    370 
    371 ////////////////////////////////////////////////////////////////////////////
    372 void PVMFFileOutputNode::addRef()
    373 {
    374     ++iExtensionRefCount;
    375 }
    376 
    377 ////////////////////////////////////////////////////////////////////////////
    378 void PVMFFileOutputNode::removeRef()
    379 {
    380     if (iExtensionRefCount > 0)
    381         --iExtensionRefCount;
    382 }
    383 
    384 ////////////////////////////////////////////////////////////////////////////
    385 bool PVMFFileOutputNode::queryInterface(const PVUuid& uuid, PVInterface*& iface)
    386 {
    387     if (uuid == PvmfFileOutputNodeConfigUuid)
    388     {
    389         PvmfFileOutputNodeConfigInterface* myInterface = OSCL_STATIC_CAST(PvmfFileOutputNodeConfigInterface*, this);
    390         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
    391         ++iExtensionRefCount;
    392     }
    393     else if (uuid == PvmfComposerSizeAndDurationUuid)
    394     {
    395         PvmfComposerSizeAndDurationInterface* myInterface = OSCL_STATIC_CAST(PvmfComposerSizeAndDurationInterface*, this);
    396         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
    397         ++iExtensionRefCount;
    398     }
    399     else if (uuid == PvmfNodesSyncControlUuid)
    400     {
    401         PvmfNodesSyncControlInterface* myInterface = OSCL_STATIC_CAST(PvmfNodesSyncControlInterface*, this);
    402         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
    403         ++iExtensionRefCount;
    404     }
    405 
    406     else if (uuid == PVMI_CAPABILITY_AND_CONFIG_PVUUID)
    407     {
    408         PvmiCapabilityAndConfig* myInterface = OSCL_STATIC_CAST(PvmiCapabilityAndConfig*, this);
    409         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
    410         ++iExtensionRefCount;
    411     }
    412 
    413     else
    414     {
    415         iface = NULL;
    416         return false;
    417     }
    418 
    419     return true;
    420 }
    421 
    422 ////////////////////////////////////////////////////////////////////////////
    423 PVMFStatus PVMFFileOutputNode::SetOutputFileName(const OSCL_wString& aFileName)
    424 {
    425     if (iInterfaceState != EPVMFNodeIdle
    426             && iInterfaceState != EPVMFNodeInitialized
    427             && iInterfaceState != EPVMFNodeCreated
    428             && iInterfaceState != EPVMFNodePrepared)
    429         return false;
    430 
    431     iOutputFileName = aFileName;
    432     return PVMFSuccess;
    433 }
    434 
    435 ///////////////////////////////////////////////////////////////////////////
    436 PVMFStatus PVMFFileOutputNode::SetOutputFileDescriptor(const OsclFileHandle* aFileHandle)
    437 {
    438     if (iInterfaceState != EPVMFNodeIdle
    439             && iInterfaceState != EPVMFNodeInitialized
    440             && iInterfaceState != EPVMFNodeCreated
    441             && iInterfaceState != EPVMFNodePrepared)
    442         return false;
    443 
    444     iOutputFile.SetPVCacheSize(0);
    445     iOutputFile.SetAsyncReadBufferSize(0);
    446     iOutputFile.SetNativeBufferSize(0);
    447     iOutputFile.SetLoggingEnable(false);
    448     iOutputFile.SetSummaryStatsLoggingEnable(false);
    449     iOutputFile.SetFileHandle((OsclFileHandle*)aFileHandle);
    450 
    451     //call open
    452     int32 retval = iOutputFile.Open(_STRLIT_CHAR("dummy"),
    453                                     Oscl_File::MODE_READWRITE | Oscl_File::MODE_BINARY,
    454                                     iFs);
    455 
    456     if (retval == 0)
    457     {
    458         iFileOpened = 1;
    459         iFirstMediaData = true;
    460         return PVMFSuccess;
    461     }
    462     return PVMFFailure;
    463 }
    464 ////////////////////////////////////////////////////////////////////////////
    465 PVMFStatus PVMFFileOutputNode::SetMaxFileSize(bool aEnable, uint32 aMaxFileSizeBytes)
    466 {
    467     iMaxFileSizeEnabled = aEnable;
    468     if (iMaxFileSizeEnabled)
    469     {
    470         iMaxFileSize = aMaxFileSizeBytes;
    471     }
    472     else
    473     {
    474         iMaxFileSize = 0;
    475     }
    476 
    477     return PVMFSuccess;
    478 }
    479 
    480 ////////////////////////////////////////////////////////////////////////////
    481 void PVMFFileOutputNode::GetMaxFileSizeConfig(bool& aEnable, uint32& aMaxFileSizeBytes)
    482 {
    483     aEnable = iMaxFileSizeEnabled;
    484     aMaxFileSizeBytes = iMaxFileSize;
    485 }
    486 
    487 ////////////////////////////////////////////////////////////////////////////
    488 PVMFStatus PVMFFileOutputNode::SetMaxDuration(bool aEnable, uint32 aMaxDurationMilliseconds)
    489 {
    490     iMaxDurationEnabled = aEnable;
    491     if (iMaxDurationEnabled)
    492     {
    493         iMaxDuration = aMaxDurationMilliseconds;
    494     }
    495     else
    496     {
    497         iMaxDuration = 0;
    498     }
    499 
    500     return PVMFSuccess;
    501 }
    502 
    503 ////////////////////////////////////////////////////////////////////////////
    504 void PVMFFileOutputNode::GetMaxDurationConfig(bool& aEnable, uint32& aMaxDurationMilliseconds)
    505 {
    506     aEnable = iMaxDurationEnabled;
    507     aMaxDurationMilliseconds = iMaxDuration;
    508 }
    509 
    510 ////////////////////////////////////////////////////////////////////////////
    511 PVMFStatus PVMFFileOutputNode::SetFileSizeProgressReport(bool aEnable, uint32 aReportFrequency)
    512 {
    513     iFileSizeReportEnabled = aEnable;
    514     if (iFileSizeReportEnabled)
    515     {
    516         iFileSizeReportFreq = aReportFrequency;
    517     }
    518 
    519     return PVMFSuccess;
    520 }
    521 
    522 ////////////////////////////////////////////////////////////////////////////
    523 void PVMFFileOutputNode::GetFileSizeProgressReportConfig(bool& aEnable, uint32& aReportFrequency)
    524 {
    525     aEnable = iFileSizeReportEnabled;
    526     aReportFrequency = iFileSizeReportFreq;
    527 }
    528 
    529 ////////////////////////////////////////////////////////////////////////////
    530 PVMFStatus PVMFFileOutputNode::SetDurationProgressReport(bool aEnable, uint32 aReportFrequency)
    531 {
    532     iDurationReportEnabled = aEnable;
    533     if (iDurationReportEnabled)
    534     {
    535         iDurationReportFreq = aReportFrequency;
    536     }
    537 
    538     return PVMFSuccess;
    539 }
    540 
    541 ////////////////////////////////////////////////////////////////////////////
    542 void PVMFFileOutputNode::GetDurationProgressReportConfig(bool& aEnable, uint32& aReportFrequency)
    543 {
    544     aEnable = iDurationReportEnabled;
    545     aReportFrequency = iDurationReportFreq;
    546 }
    547 
    548 ////////////////////////////////////////////////////////////////////////////
    549 PVMFStatus PVMFFileOutputNode::SetClock(PVMFMediaClock* aClock)
    550 {
    551     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    552                     (0, "PVMFFileOutputNode::SetClock: aClock=0x%x", aClock));
    553 
    554     iClock = aClock;
    555     if (iInPort)
    556     {
    557         return ((PVMFFileOutputInPort*)iInPort)->SetClock(aClock);
    558     }
    559 
    560     return PVMFSuccess;
    561 }
    562 
    563 ///////////////////////////////////////////////////////////////////////////
    564 PVMFStatus PVMFFileOutputNode::ChangeClockRate(int32 aRate)
    565 {
    566     OSCL_UNUSED_ARG(aRate);
    567     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    568                     (0, "PVMFFileOutputNode::ChangeClockRate: aRate=%d", aRate));
    569 
    570     return PVMFSuccess;
    571 }
    572 
    573 ////////////////////////////////////////////////////////////////////////////
    574 PVMFStatus PVMFFileOutputNode::SetMargins(int32 aEarlyMargin, int32 aLateMargin)
    575 {
    576     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    577                     (0, "PVMFFileOutputNode::SetMargins: aEarlyMargin=%d, aLateMargin=%d", aEarlyMargin, aLateMargin));
    578 
    579     iEarlyMargin = aEarlyMargin;
    580     iLateMargin = aLateMargin;
    581     if (iInPort)
    582     {
    583         return ((PVMFFileOutputInPort*)iInPort)->SetMargins(aEarlyMargin, aLateMargin);
    584     }
    585 
    586     return PVMFSuccess;
    587 }
    588 
    589 ////////////////////////////////////////////////////////////////////////////
    590 void PVMFFileOutputNode::ClockStarted(void)
    591 {
    592     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    593                     (0, "PVMFFileOutputNode::ClockStarted"));
    594 
    595     if (iInPort)
    596     {
    597         ((PVMFFileOutputInPort*)iInPort)->Start();
    598     }
    599 }
    600 
    601 ////////////////////////////////////////////////////////////////////////////
    602 void PVMFFileOutputNode::ClockStopped(void)
    603 {
    604     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    605                     (0, "PVMFFileOutputNode::ClockStopped"));
    606 
    607     if (iInPort)
    608     {
    609         ((PVMFFileOutputInPort*)iInPort)->Pause();
    610     }
    611 }
    612 
    613 ////////////////////////////////////////////////////////////////////////////
    614 PVMFCommandId PVMFFileOutputNode::SkipMediaData(PVMFSessionId aSessionId,
    615         PVMFTimestamp aResumeTimestamp,
    616         uint32 aStreamID,
    617         bool aPlayBackPositionContinuous,
    618         OsclAny* aContext)
    619 {
    620     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    621                     (0, "PVMFFileOutputNode::SkipMediaData: aResumeTimestamp=%d, aContext=0x%x",
    622                      aResumeTimestamp, aContext));
    623 
    624     if (!iInPort)
    625     {
    626         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
    627                         (0, "PVMFFileOutputNode::SkipMediaData: Error - Input port has not been created"));
    628         OSCL_LEAVE(OsclErrNotReady);
    629         return 0;
    630     }
    631 
    632     switch (iInterfaceState)
    633     {
    634         case EPVMFNodeStarted:
    635         case EPVMFNodeInitialized:
    636         case EPVMFNodePaused:
    637             return ((PVMFFileOutputInPort*)iInPort)->SkipMediaData(aSessionId, aResumeTimestamp, aStreamID, aPlayBackPositionContinuous, aContext);
    638 
    639         default:
    640             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
    641                             (0, "PVMFFileOutputNode::SkipMediaData: Error - Wrong state"));
    642             OSCL_LEAVE(OsclErrInvalidState);
    643             return 0;
    644     }
    645 }
    646 
    647 ////////////////////////////////////////////////////////////////////////////
    648 void PVMFFileOutputNode::Run()
    649 {
    650     if (!iInputCommands.empty())
    651     {
    652         if (ProcessCommand(iInputCommands.front()))
    653         {
    654             //note: need to check the state before re-scheduling
    655             //since the node could have been reset in the ProcessCommand
    656             //call.
    657             if (iInterfaceState != EPVMFNodeCreated)
    658                 RunIfNotReady();
    659             return;
    660         }
    661     }
    662 
    663     // Process port activity
    664     if (!iPortActivityQueue.empty()
    665             && (iInterfaceState == EPVMFNodeStarted || FlushPending()))
    666     {
    667         // If the port activity cannot be processed because a port is
    668         // busy, discard the activity and continue to process the next
    669         // activity in queue until getting to one that can be processed.
    670         while (!iPortActivityQueue.empty())
    671         {
    672             if (ProcessPortActivity())
    673                 break; //processed a port
    674         }
    675         //Re-schedule
    676         RunIfNotReady();
    677         return;
    678     }
    679 
    680     //If we get here we did not process any ports or commands.
    681     //Check for completion of a flush command...
    682     if (FlushPending()
    683             && iPortActivityQueue.empty())
    684     {
    685         SetState(EPVMFNodePrepared);
    686         iInPort->ResumeInput();
    687         CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess);
    688         RunIfNotReady();
    689     }
    690 }
    691 
    692 void PVMFFileOutputNode::HandlePortActivity(const PVMFPortActivity &aActivity)
    693 {
    694     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    695                     (0, "0x%x PVMFFileOutputNode::PortActivity: port=0x%x, type=%d",
    696                      this, aActivity.iPort, aActivity.iType));
    697 
    698     switch (aActivity.iType)
    699     {
    700         case PVMF_PORT_ACTIVITY_OUTGOING_MSG:
    701             //An outgoing message was queued on this port.
    702             //We only need to queue a port activity event on the
    703             //first message.  Additional events will be queued during
    704             //the port processing as needed.
    705             if (aActivity.iPort->OutgoingMsgQueueSize() == 1)
    706                 QueuePortActivity(aActivity);
    707             break;
    708 
    709         case PVMF_PORT_ACTIVITY_INCOMING_MSG:
    710             if (aActivity.iPort->IncomingMsgQueueSize() == 1)
    711                 QueuePortActivity(aActivity);
    712             break;
    713 
    714         case PVMF_PORT_ACTIVITY_DELETED:
    715             //Report port deleted info event to the node.
    716             ReportInfoEvent(PVMFInfoPortDeleted
    717                             , (OsclAny*)aActivity.iPort);
    718             //Purge any port activity events already queued
    719             //for this port.
    720             {
    721                 for (uint32 i = 0; i < iPortActivityQueue.size();)
    722                 {
    723                     if (iPortActivityQueue[i].iPort == aActivity.iPort)
    724                         iPortActivityQueue.erase(&iPortActivityQueue[i]);
    725                     else
    726                         i++;
    727                 }
    728             }
    729             break;
    730 
    731         case PVMF_PORT_ACTIVITY_CONNECT:
    732             //nothing needed.
    733             break;
    734 
    735         case PVMF_PORT_ACTIVITY_DISCONNECT:
    736             //nothing needed.
    737             break;
    738         default:
    739             break;
    740     }
    741 }
    742 
    743 /////////////////////////////////////////////////////
    744 // Port Processing routines
    745 /////////////////////////////////////////////////////
    746 
    747 void PVMFFileOutputNode::QueuePortActivity(const PVMFPortActivity &aActivity)
    748 {
    749     //queue a new port activity event
    750     int32 err;
    751     OSCL_TRY(err, iPortActivityQueue.push_back(aActivity););
    752     if (err != OsclErrNone)
    753     {
    754         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
    755                         (0, "0x%x PVMFFileOutputNode::PortActivity: Error - iPortActivityQueue.push_back() failed", this));
    756         ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aActivity.iPort));
    757     }
    758     else
    759     {
    760         //wake up the AO to process the port activity event.
    761         RunIfNotReady();
    762     }
    763 }
    764 
    765 ////////////////////////////////////////////////////////////////////////////
    766 PVMFStatus PVMFFileOutputNode::ProcessIncomingData(PVMFSharedMediaDataPtr aMediaData)
    767 {
    768     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    769                     (0, "PVMFFileOutputNode::ProcessIncomingData()"));
    770 
    771     PVMFStatus status = PVMFSuccess;
    772 
    773     OsclRefCounterMemFrag frag;
    774     uint32 numFrags = aMediaData->getNumFragments();
    775     OsclRefCounterMemFrag formatSpecificInfo;
    776     aMediaData->getFormatSpecificInfo(formatSpecificInfo);
    777 
    778     for (uint32 i = 0; (i < numFrags) && status == PVMFSuccess; i++)
    779     {
    780         aMediaData->getMediaFragment(i, frag);
    781         switch (iInterfaceState)
    782         {
    783             case EPVMFNodeStarted:
    784                 if (iFirstMediaData)
    785                 {
    786                     status = WriteFormatSpecificInfo(formatSpecificInfo.getMemFragPtr(), formatSpecificInfo.getMemFragSize());
    787                     if (status != PVMFSuccess)
    788                     {
    789                         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
    790                                         (0, "PVMFFileOutputNode::ProcessIncomingData: Error - WriteFormatSpecificInfo failed"));
    791                         return PVMFFailure;
    792                     }
    793                 }
    794 
    795                 if (((PVMFFileOutputInPort*)iInPort)->iFormat == PVMF_MIME_3GPP_TIMEDTEXT)
    796                 {
    797                     PVMFTimedTextMediaData* textmediadata = (PVMFTimedTextMediaData*)(frag.getMemFragPtr());
    798                     // Output the text sample entry
    799                     if (textmediadata->iTextSampleEntry.GetRep() != NULL)
    800                     {
    801                         PVMFTimedTextMediaData* textmediadata = (PVMFTimedTextMediaData*)(frag.getMemFragPtr());
    802                         // Output the text sample entry
    803                         if (textmediadata->iTextSampleEntry.GetRep() != NULL)
    804                         {
    805                             // @TODO Write out the text sample entry in a better format
    806                             status = WriteData((OsclAny*)(textmediadata->iTextSampleEntry.GetRep()), sizeof(PVMFTimedTextSampleEntry));
    807                             if (status == PVMFFailure)
    808                             {
    809                                 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
    810                                                 (0, "PVMFFileOutputNode::ProcessIncomingData: Error - WriteData failed for text sample entry"));
    811                                 return PVMFFailure;
    812                             }
    813                         }
    814                         // Write out the raw text sample
    815                         status = WriteData((OsclAny*)(textmediadata->iTextSample), textmediadata->iTextSampleLength);
    816                         if (status == PVMFFailure)
    817                         {
    818                             PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
    819                                             (0, "PVMFFileOutputNode::ProcessIncomingData: Error - WriteData failed for text sample entry"));
    820                             return PVMFFailure;
    821                         }
    822                     }
    823                 }
    824                 else
    825                 {
    826                     status = WriteData(frag, aMediaData->getTimestamp());
    827                     if (status == PVMFFailure)
    828                     {
    829                         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
    830                                         (0, "PVMFFileOutputNode::ProcessIncomingData: Error - WriteData failed"));
    831                         return PVMFFailure;
    832                     }
    833                 }
    834 
    835                 break;
    836 
    837             case EPVMFNodeInitialized:
    838                 // Already stopped. Ignore incoming data.
    839                 break;
    840 
    841             default:
    842                 // Wrong state
    843                 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
    844                                 (0, "PVMFFileOutputNode::ProcessIncomingData: Error - Wrong state"));
    845                 status = PVMFFailure;
    846                 break;
    847         }
    848     }
    849 
    850     return status;
    851 }
    852 //////////////////////////////////////////////////////////////////////////////////
    853 PVMFStatus PVMFFileOutputNode::WriteFormatSpecificInfo(OsclAny* aPtr, uint32 aSize)
    854 {
    855     PVMFStatus status = PVMFSuccess;
    856 
    857     if (!iFileOpened)
    858     {
    859         if (iFs.Connect() != 0)
    860         {
    861             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
    862                             (0, "PVMFFileOutputNode::WriteFormatSpecificInfo: iFs.Connect Error."));
    863             status = PVMFErrNoResources;
    864             return status;
    865         }
    866 
    867         if (0 != iOutputFile.Open(iOutputFileName.get_cstr(), Oscl_File::MODE_READWRITE | Oscl_File::MODE_BINARY, iFs))
    868         {
    869             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
    870                             (0, "PVMFFileOutputNode::WriteFormatSpecificInfo: iOutputFile.Open Error."));
    871             status = PVMFErrNoResources;
    872             return status;
    873         }
    874 
    875         iFileOpened = 1;
    876 
    877         iFirstMediaData = true;
    878     }
    879 
    880     if (iFirstMediaData)
    881     {
    882         // Add the amr header if required
    883         if (((PVMFFileOutputInPort*)iInPort)->iFormat == PVMF_MIME_AMR_IETF)
    884         {
    885             // Check if the incoming data has "#!AMR\n" string
    886             if (aSize < AMR_HEADER_SIZE ||
    887                     oscl_strncmp((const char*)aPtr, AMR_HEADER, AMR_HEADER_SIZE) != 0)
    888             {
    889                 // AMR header not found, add AMR header to file first
    890                 status = WriteData((OsclAny*)AMR_HEADER, AMR_HEADER_SIZE);
    891                 if (status != PVMFSuccess)
    892                 {
    893                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
    894                                     (0, "PVMFFileOutputNode::WriteFormatSpecificInfo: Error - WriteData failed"));
    895                     return status;
    896                 }
    897             }
    898             iFirstMediaData = false;
    899         }
    900         // Add the amr-wb header if required
    901         else if (((PVMFFileOutputInPort*)iInPort)->iFormat == PVMF_MIME_AMRWB_IETF)
    902         {
    903             // Check if the incoming data has "#!AMR-WB\n" string
    904             if (aSize < AMRWB_HEADER_SIZE ||
    905                     oscl_strncmp((const char*)aPtr, AMRWB_HEADER, AMRWB_HEADER_SIZE) != 0)
    906             {
    907                 // AMR header not found, add AMR header to file first
    908                 status = WriteData((OsclAny*)AMRWB_HEADER, AMRWB_HEADER_SIZE);
    909                 if (status != PVMFSuccess)
    910                 {
    911                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
    912                                     (0, "PVMFFileOutputNode::WriteFormatSpecificInfo: Error - WriteData failed"));
    913                     return status;
    914                 }
    915             }
    916             iFirstMediaData = false;
    917         }
    918         else if (((PVMFFileOutputInPort*)iInPort)->iFormat == PVMF_MIME_M4V)
    919         {
    920             if (aSize > 0)
    921             {
    922                 status = WriteData(aPtr, aSize);
    923                 if (status != PVMFSuccess)
    924                 {
    925                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
    926                                     (0, "PVMFFileOutputNode::WriteFormatSpecificInfo: Error - WriteData failed"));
    927                     return status;
    928                 }
    929             }
    930             iFirstMediaData = false;
    931         }
    932         else if (((PVMFFileOutputInPort*)iInPort)->iFormat == PVMF_MIME_PCM8)
    933         {
    934             if (aSize > 0)
    935             {
    936                 status = WriteData(aPtr, aSize);
    937                 if (status != PVMFSuccess)
    938                 {
    939                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
    940                                     (0, "PVMFFileOutputNode::WriteFormatSpecificInfo: Error - WriteData failed"));
    941                     return status;
    942                 }
    943             }
    944             iFirstMediaData = false;
    945         }
    946         else if (((PVMFFileOutputInPort*)iInPort)->iFormat == PVMF_MIME_PCM16)
    947         {
    948             if (aSize > 0)
    949             {
    950                 status = WriteData(aPtr, aSize);
    951                 if (status != PVMFSuccess)
    952                 {
    953                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
    954                                     (0, "PVMFFileOutputNode::WriteFormatSpecificInfo: Error - WriteData failed"));
    955                     return status;
    956                 }
    957             }
    958             iFirstMediaData = false;
    959         }
    960         else if (((PVMFFileOutputInPort*)iInPort)->iFormat == PVMF_MIME_3GPP_TIMEDTEXT)
    961         {
    962             if (aSize > 0)
    963             {
    964                 // TODO Write out the text track level info in some formatted way
    965                 status = WriteData(aPtr, aSize);
    966                 if (status != PVMFSuccess)
    967                 {
    968                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
    969                                     (0, "PVMFFileOutputNode::WriteFormatSpecificInfo: Error - WriteData failed"));
    970                     return status;
    971                 }
    972             }
    973             iFirstMediaData = false;
    974         }
    975         else
    976         {
    977             iFirstMediaData = false;
    978         }
    979     }
    980     return status;
    981 }
    982 
    983 
    984 //////////////////////////////////////////////////////////////////////////////////
    985 PVMFStatus PVMFFileOutputNode::SendDurationProgress(uint32 aTimestamp)
    986 {
    987 
    988     if (iDurationReportEnabled &&
    989             aTimestamp >= iNextDurationReport)
    990     {
    991         iNextDurationReport = aTimestamp - (aTimestamp % iDurationReportFreq) + iDurationReportFreq;
    992         ReportInfoEvent(PVMF_COMPOSER_DURATION_PROGRESS, (OsclAny*)aTimestamp);
    993     }
    994     return PVMFSuccess;
    995 }
    996 
    997 //////////////////////////////////////////////////////////////////////////////////
    998 PVMFStatus PVMFFileOutputNode::SendFileSizeProgress()
    999 {
   1000     if (iFileSizeReportEnabled &&
   1001             iFileSize >= iNextFileSizeReport)
   1002     {
   1003         iNextFileSizeReport = iFileSize - (iFileSize % iFileSizeReportFreq) + iFileSizeReportFreq;
   1004         ReportInfoEvent(PVMF_COMPOSER_FILESIZE_PROGRESS, (OsclAny*)iFileSize);
   1005     }
   1006     return PVMFSuccess;
   1007 }
   1008 
   1009 //////////////////////////////////////////////////////////////////////////////////
   1010 PVMFStatus PVMFFileOutputNode::CheckMaxFileSize(uint32 aFrameSize)
   1011 {
   1012     if (iMaxFileSizeEnabled)
   1013     {
   1014         if ((iFileSize + aFrameSize) >= iMaxFileSize)
   1015         {
   1016             // Change state to initialized
   1017             ChangeNodeState(EPVMFNodeInitialized);
   1018 
   1019             // Clear all pending port activity
   1020             ClearPendingPortActivity();
   1021 
   1022             // Report max file size event
   1023             ReportInfoEvent(PVMF_COMPOSER_MAXFILESIZE_REACHED, NULL);
   1024             return PVMFSuccess;
   1025         }
   1026 
   1027         return PVMFPending;
   1028     }
   1029     return PVMFErrNotSupported;
   1030 }
   1031 
   1032 //////////////////////////////////////////////////////////////////////////////////
   1033 PVMFStatus PVMFFileOutputNode::CheckMaxDuration(uint32 aTimestamp)
   1034 {
   1035     if (iMaxDurationEnabled)
   1036     {
   1037         if (aTimestamp >= iMaxDuration)
   1038         {
   1039             // Change state to initialized
   1040             ChangeNodeState(EPVMFNodeInitialized);
   1041 
   1042             // Clear all pending port activity
   1043             ClearPendingPortActivity();
   1044 
   1045             // Report max duration event
   1046             ReportInfoEvent(PVMF_COMPOSER_MAXDURATION_REACHED, NULL);
   1047             return PVMFSuccess;
   1048         }
   1049 
   1050         return PVMFPending;
   1051     }
   1052     return PVMFErrNotSupported;
   1053 }
   1054 
   1055 //////////////////////////////////////////////////////////////////////////////////
   1056 PVMFStatus PVMFFileOutputNode::WriteData(OsclAny* aData, uint32 aSize)
   1057 {
   1058     if (!aData || aSize == 0)
   1059     {
   1060         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
   1061                         (0, "PVMFFileOutputNode::WriteData: Error - Invalid data or data size"));
   1062         return PVMFFailure;
   1063     }
   1064 
   1065     switch (CheckMaxFileSize(aSize))
   1066     {
   1067         case PVMFFailure:
   1068             PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
   1069                             (0, "PVMFFileOutputNode::WriteData: Error - CheckMaxFileSize failed"));
   1070             return PVMFFailure;
   1071 
   1072         case PVMFSuccess:
   1073             PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_DEBUG,
   1074                             (0, "PVMFFileOutputNode::WriteData: Maxmimum file size reached"));
   1075             return PVMFSuccess;
   1076 
   1077         default:
   1078             break;
   1079     }
   1080 
   1081     int32 wlength = 0;
   1082     if ((wlength = iOutputFile.Write(aData, sizeof(uint8), aSize)) != (int32)aSize)
   1083     {
   1084         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
   1085                         (0, "PVMFFileOutputNode::WriteData: Error - File write failed"));
   1086         ReportInfoEvent(PVMFInfoProcessingFailure);
   1087         return PVMFFailure;
   1088     }
   1089     else
   1090     {
   1091         iOutputFile.Flush();
   1092     }
   1093 
   1094     iFileSize += wlength;
   1095     return SendFileSizeProgress();
   1096 }
   1097 
   1098 //////////////////////////////////////////////////////////////////////////////////
   1099 PVMFStatus PVMFFileOutputNode::WriteData(OsclRefCounterMemFrag aMemFrag, uint32 aTimestamp)
   1100 {
   1101     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_STACK_TRACE,
   1102                     (0, "PVMFFileOutputNode::WriteData: aTimestamp=%d", aTimestamp));
   1103 
   1104     switch (CheckMaxDuration(aTimestamp))
   1105     {
   1106         case PVMFFailure:
   1107             PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
   1108                             (0, "PVMFFileOutputNode::WriteData: Error - CheckMaxDuration failed"));
   1109             return PVMFFailure;
   1110 
   1111         case PVMFSuccess:
   1112             PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_DEBUG,
   1113                             (0, "PVMFFileOutputNode::WriteData: Maxmimum duration reached"));
   1114             return PVMFSuccess;
   1115 
   1116         default:
   1117             break;
   1118     }
   1119 
   1120     if (WriteData(aMemFrag.getMemFragPtr(), aMemFrag.getMemFragSize()) == PVMFSuccess)
   1121         return SendDurationProgress(aTimestamp);
   1122     else
   1123         return PVMFFailure;
   1124 }
   1125 
   1126 //////////////////////////////////////////////////////////////////////////////////
   1127 void PVMFFileOutputNode::ClearPendingPortActivity()
   1128 {
   1129     // index starts at 1 because the current command (i.e. iCmdQueue[0]) will be erased inside Run
   1130     while (!iInputCommands.empty())
   1131     {
   1132         CommandComplete(iInputCommands, iInputCommands.front(), PVMFFailure);
   1133     }
   1134 }
   1135 
   1136 void PVMFFileOutputNode::ChangeNodeState(TPVMFNodeInterfaceState aNewState)
   1137 {
   1138     iInterfaceState = aNewState;
   1139 }
   1140 
   1141 /***********************************/
   1142 void PVMFFileOutputNode::CommandComplete(PVMFFileOutputNodeCmdQ& aCmdQ, PVMFFileOutputNodeCommand& aCmd, PVMFStatus aStatus, OsclAny* aEventData)
   1143 {
   1144     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFFileOutputNode:CommandComplete Id %d Cmd %d Status %d Context %d Data %d"
   1145                     , aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData));
   1146 
   1147     //create response
   1148     PVMFCmdResp resp(aCmd.iId, aCmd.iContext, aStatus, aEventData);
   1149     PVMFSessionId session = aCmd.iSession;
   1150 
   1151     //Erase the command from the queue.
   1152     aCmdQ.Erase(&aCmd);
   1153 
   1154     //Report completion to the session observer.
   1155     ReportCmdCompleteEvent(session, resp);
   1156 }
   1157 
   1158 PVMFCommandId PVMFFileOutputNode::QueueCommandL(PVMFFileOutputNodeCommand& aCmd)
   1159 {
   1160     PVMFCommandId id;
   1161 
   1162     id = iInputCommands.AddL(aCmd);
   1163 
   1164     //wakeup the AO
   1165     RunIfNotReady();
   1166 
   1167     return id;
   1168 }
   1169 
   1170 
   1171 /////////////////////////////////////////////////////
   1172 bool PVMFFileOutputNode::ProcessPortActivity()
   1173 {//called by the AO to process a port activity message
   1174     //Pop the queue...
   1175     PVMFPortActivity activity(iPortActivityQueue.front());
   1176     iPortActivityQueue.erase(&iPortActivityQueue.front());
   1177 
   1178     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1179                     (0, "0x%x PVMFFileOutputNode::ProcessPortActivity: port=0x%x, type=%d",
   1180                      this, activity.iPort, activity.iType));
   1181 
   1182     int32 err = OsclErrNone;
   1183 
   1184     PVMFStatus status = PVMFSuccess;
   1185     switch (activity.iType)
   1186     {
   1187         case PVMF_PORT_ACTIVITY_INCOMING_MSG:
   1188             status = ProcessIncomingMsg(activity.iPort);
   1189             //if there is still data, queue another port activity event.
   1190             if (activity.iPort->IncomingMsgQueueSize() > 0)
   1191             {
   1192                 OSCL_TRY(err, iPortActivityQueue.push_back(activity););
   1193             }
   1194             break;
   1195         case PVMF_PORT_ACTIVITY_OUTGOING_MSG:
   1196         default:
   1197             return false;
   1198     }
   1199 
   1200     return true;
   1201 }
   1202 
   1203 /////////////////////////////////////////////////////
   1204 PVMFStatus PVMFFileOutputNode::ProcessIncomingMsg(PVMFPortInterface* aPort)
   1205 {
   1206     //Called by the AO to process one buffer off the port's
   1207     //incoming data queue.  This routine will dequeue and
   1208     //dispatch the data.
   1209 
   1210     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1211                     (0, "0x%x PVMFFileOutputNode::ProcessIncomingMsg: aPort=0x%x", this, aPort));
   1212 
   1213     if (aPort->GetPortTag() != PVMF_FILE_OUTPUT_NODE_PORT_TYPE_SINK)
   1214     {
   1215         return PVMFFailure;
   1216     }
   1217     PVMFSharedMediaMsgPtr msg;
   1218     PVMFStatus status = aPort->DequeueIncomingMsg(msg);
   1219     if (status != PVMFSuccess)
   1220     {
   1221         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
   1222                         (0, "0x%x PVMFFileOutputNode::ProcessIncomingMsg: Error - DequeueIncomingMsg failed", this));
   1223         return status;
   1224     }
   1225     /*
   1226        INFORMATION!!!
   1227        The FileOutputNode is generally used by the engine unit tests as SinkNode
   1228        For now, most of the unit tests have OBSOLETED the use of FileOutputNode,
   1229        But still some of the tests are using the FileOutputNode in place of,
   1230        MIO (RefFileOutput).
   1231 
   1232        Since the usage FileOutputNode is not defined yet, we are adding support for
   1233        BOS Message as a NO-OP so that the node should be able to handle Any and all
   1234        the BOS Messages gracefully.
   1235 
   1236        IMPORTANT!!!,
   1237        For Complete support of BOS in the FileOutputNode, we need to make more changes.
   1238        Those changes will be done only once the life scope of FileOutputNode is defined.
   1239     */
   1240     if (msg->getFormatID() == PVMF_MEDIA_CMD_BOS_FORMAT_ID)
   1241     {
   1242         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1243                         (0, "PVFileOutputNode::ProcessIncomingMsg BOS Received"));
   1244         return PVMFSuccess;
   1245     }
   1246 
   1247     // Transfer to the port's sync queue to do synchronization
   1248     // This is temporary until data is directly saved to the sync queue
   1249     uint32 dropped;
   1250     uint32 skipped;
   1251     status = ((PVMFFileOutputInPort*)aPort)->iDataQueue.QueueMediaData(msg, &dropped, &skipped);
   1252     if (dropped > 0)
   1253     {
   1254         PVMFNodeInterface::ReportInfoEvent(PVMFInfoDataDiscarded);
   1255     }
   1256 
   1257     if (status == PVMFErrNoMemory)
   1258     {
   1259         return PVMFFailure;
   1260     }
   1261     else
   1262     {
   1263         return PVMFSuccess;
   1264     }
   1265 }
   1266 
   1267 bool PVMFFileOutputNode::ProcessCommand(PVMFFileOutputNodeCommand& aCmd)
   1268 {
   1269     //normally this node will not start processing one command
   1270     //until the prior one is finished.  However, a hi priority
   1271     //command such as Cancel must be able to interrupt a command
   1272     //in progress.
   1273     if (!iCurrentCommand.empty() && !aCmd.hipri())
   1274         return false;
   1275 
   1276     switch (aCmd.iCmd)
   1277     {
   1278         case PVMF_GENERIC_NODE_QUERYUUID:
   1279             DoQueryUuid(aCmd);
   1280             break;
   1281 
   1282         case PVMF_GENERIC_NODE_QUERYINTERFACE:
   1283             DoQueryInterface(aCmd);
   1284             break;
   1285 
   1286         case PVMF_GENERIC_NODE_REQUESTPORT:
   1287             DoRequestPort(aCmd);
   1288             break;
   1289 
   1290         case PVMF_GENERIC_NODE_RELEASEPORT:
   1291             DoReleasePort(aCmd);
   1292             break;
   1293 
   1294         case PVMF_GENERIC_NODE_INIT:
   1295             DoInit(aCmd);
   1296             break;
   1297 
   1298         case PVMF_GENERIC_NODE_PREPARE:
   1299             DoPrepare(aCmd);
   1300             break;
   1301 
   1302         case PVMF_GENERIC_NODE_START:
   1303             DoStart(aCmd);
   1304             break;
   1305 
   1306         case PVMF_GENERIC_NODE_STOP:
   1307             DoStop(aCmd);
   1308             break;
   1309 
   1310         case PVMF_GENERIC_NODE_FLUSH:
   1311             DoFlush(aCmd);
   1312             break;
   1313 
   1314         case PVMF_GENERIC_NODE_PAUSE:
   1315             DoPause(aCmd);
   1316             break;
   1317 
   1318         case PVMF_GENERIC_NODE_RESET:
   1319             DoReset(aCmd);
   1320             break;
   1321 
   1322         case PVMF_GENERIC_NODE_CANCELALLCOMMANDS:
   1323             DoCancelAllCommands(aCmd);
   1324             break;
   1325 
   1326         case PVMF_GENERIC_NODE_CANCELCOMMAND:
   1327             DoCancelCommand(aCmd);
   1328             break;
   1329 
   1330         default://unknown command type
   1331             CommandComplete(iInputCommands, aCmd, PVMFFailure);
   1332             break;
   1333     }
   1334 
   1335     return true;
   1336 }
   1337 
   1338 /**
   1339 //A routine to tell if a flush operation is in progress.
   1340 */
   1341 bool PVMFFileOutputNode::FlushPending()
   1342 {
   1343     return (iCurrentCommand.size() > 0
   1344             && iCurrentCommand.front().iCmd == PVMF_GENERIC_NODE_FLUSH);
   1345 }
   1346 
   1347 void PVMFFileOutputNode::DoQueryUuid(PVMFFileOutputNodeCommand& aCmd)
   1348 {
   1349     //This node supports Query UUID from any state
   1350 
   1351     OSCL_String* mimetype;
   1352     Oscl_Vector<PVUuid, OsclMemAllocator> *uuidvec;
   1353     bool exactmatch;
   1354     aCmd.PVMFFileOutputNodeCommandBase::Parse(mimetype, uuidvec, exactmatch);
   1355 
   1356     //Try to match the input mimetype against any of
   1357     //the custom interfaces for this node
   1358     //Match against custom interface1...
   1359     if (*mimetype == PVMF_FILE_OUTPUT_NODE_CUSTOM1_MIMETYPE
   1360             //also match against base mimetypes for custom interface1,
   1361             //unless exactmatch is set.
   1362             || (!exactmatch && *mimetype == PVMF_FILE_OUTPUT_NODE_MIMETYPE)
   1363             || (!exactmatch && *mimetype == PVMF_BASEMIMETYPE))
   1364     {
   1365         uuidvec->push_back(PvmfFileOutputNodeConfigUuid);
   1366         uuidvec->push_back(PvmfComposerSizeAndDurationUuid);
   1367         uuidvec->push_back(PvmfNodesSyncControlUuid);
   1368     }
   1369     CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   1370 }
   1371 
   1372 void PVMFFileOutputNode::DoQueryInterface(PVMFFileOutputNodeCommand&  aCmd)
   1373 {
   1374     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1375                     (0, "PVMFFileOutputNode::DoQueryInterface"));
   1376 
   1377     PVUuid* uuid;
   1378     PVInterface** ptr;
   1379     aCmd.PVMFFileOutputNodeCommandBase::Parse(uuid, ptr);
   1380 
   1381     if (queryInterface(*uuid, *ptr))
   1382     {
   1383         CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   1384     }
   1385     else
   1386     {
   1387         CommandComplete(iInputCommands, aCmd, PVMFFailure);
   1388     }
   1389 }
   1390 
   1391 void PVMFFileOutputNode::DoInit(PVMFFileOutputNodeCommand& aCmd)
   1392 {
   1393     PVMFStatus iRet = PVMFSuccess;
   1394     switch (iInterfaceState)
   1395     {
   1396         case EPVMFNodeIdle:
   1397             //this node doesn't need to do anything to get ready
   1398             //to start.
   1399             SetState(EPVMFNodeInitialized);
   1400             break;
   1401         case EPVMFNodeInitialized:
   1402             break;
   1403         default:
   1404             iRet = PVMFErrInvalidState;
   1405             break;
   1406     }
   1407     CommandComplete(iInputCommands, aCmd, iRet);
   1408 }
   1409 
   1410 /**
   1411 //Called by the command handler AO to do the node Prepare
   1412 */
   1413 void PVMFFileOutputNode::DoPrepare(PVMFFileOutputNodeCommand& aCmd)
   1414 {
   1415     PVMFStatus iRet = PVMFSuccess;
   1416     switch (iInterfaceState)
   1417     {
   1418         case EPVMFNodeInitialized:
   1419             //this node doesn't need to do anything to get ready
   1420             //to start.
   1421             SetState(EPVMFNodePrepared);
   1422             break;
   1423         case EPVMFNodePrepared:
   1424             break;
   1425         default:
   1426             iRet = PVMFErrInvalidState;
   1427             break;
   1428     }
   1429     CommandComplete(iInputCommands, aCmd, iRet);
   1430 }
   1431 
   1432 void PVMFFileOutputNode::DoStart(PVMFFileOutputNodeCommand& aCmd)
   1433 {
   1434     PVMFStatus status = PVMFSuccess;
   1435     switch (iInterfaceState)
   1436     {
   1437         case EPVMFNodePrepared:
   1438         case EPVMFNodePaused:
   1439         {
   1440             if (!iClock)
   1441             {
   1442                 // If not using sync clock, start processing incoming data
   1443                 ((PVMFFileOutputInPort*)iInPort)->Start();
   1444             }
   1445             if (!iFileOpened)
   1446             {
   1447                 if (iFs.Connect() != 0)
   1448                 {
   1449                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
   1450                                     (0, "PVMFFileOutputNode::DoStart: iFs.Connect Error."));
   1451                     status = PVMFErrNoResources;
   1452                     break;
   1453                 }
   1454 
   1455                 if (0 != iOutputFile.Open(iOutputFileName.get_cstr(), Oscl_File::MODE_READWRITE | Oscl_File::MODE_BINARY, iFs))
   1456                 {
   1457                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
   1458                                     (0, "PVMFFileOutputNode::DoStart: iOutputFile.Open Error."));
   1459                     status = PVMFErrNoResources;
   1460                     break;
   1461                 }
   1462 
   1463                 iFileOpened = 1;
   1464 
   1465                 iFirstMediaData = true;
   1466             }
   1467             SetState(EPVMFNodeStarted);
   1468 
   1469             break;
   1470         }
   1471         case EPVMFNodeStarted:
   1472             status = PVMFSuccess;
   1473             break;
   1474         default:
   1475             status = PVMFErrInvalidState;
   1476             break;
   1477     }
   1478 
   1479     CommandComplete(iInputCommands, aCmd, status);
   1480 }
   1481 
   1482 void PVMFFileOutputNode::DoStop(PVMFFileOutputNodeCommand& aCmd)
   1483 {
   1484     switch (iInterfaceState)
   1485     {
   1486         case EPVMFNodeStarted:
   1487         case EPVMFNodePaused:
   1488             // Stop data source
   1489             if (iInPort)
   1490             {
   1491 
   1492                 ((PVMFFileOutputInPort*)iInPort)->Stop();
   1493                 CloseOutputFile();
   1494             }
   1495 
   1496             // Clear queued messages in ports
   1497             uint32 i;
   1498             for (i = 0; i < iPortVector.size(); i++)
   1499                 iPortVector[i]->ClearMsgQueues();
   1500 
   1501             // Clear scheduled port activities
   1502             iPortActivityQueue.clear();
   1503 
   1504             //transition to Initialized state
   1505             SetState(EPVMFNodePrepared);
   1506             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   1507             break;
   1508         case EPVMFNodePrepared:
   1509             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   1510             break;
   1511         default:
   1512             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
   1513             break;
   1514     }
   1515 }
   1516 
   1517 void PVMFFileOutputNode::DoFlush(PVMFFileOutputNodeCommand& aCmd)
   1518 {
   1519     switch (iInterfaceState)
   1520     {
   1521         case EPVMFNodeStarted:
   1522         case EPVMFNodePaused:
   1523             //the flush is asynchronous.  move the command from
   1524             //the input command queue to the current command, where
   1525             //it will remain until the flush completes.
   1526             int32 err;
   1527             OSCL_TRY(err, iCurrentCommand.StoreL(aCmd););
   1528             if (err != OsclErrNone)
   1529             {
   1530                 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
   1531                 return;
   1532             }
   1533             iInputCommands.Erase(&aCmd);
   1534 
   1535             //Notify all ports to suspend their input
   1536             {
   1537                 for (uint32 i = 0; i < iPortVector.size(); i++)
   1538                     iPortVector[i]->SuspendInput();
   1539             }
   1540 
   1541             // Stop data source
   1542             break;
   1543 
   1544         default:
   1545             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
   1546             break;
   1547     }
   1548 }
   1549 
   1550 void PVMFFileOutputNode::DoPause(PVMFFileOutputNodeCommand& aCmd)
   1551 {
   1552     switch (iInterfaceState)
   1553     {
   1554         case EPVMFNodeStarted:
   1555         {
   1556             // Pause data source
   1557             if (!iClock)
   1558             {
   1559                 // If not using sync clock, pause processing of incoming data
   1560                 ((PVMFFileOutputInPort*)iInPort)->Pause();
   1561             }
   1562 
   1563             SetState(EPVMFNodePaused);
   1564             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   1565             break;
   1566         }
   1567         case EPVMFNodePaused:
   1568         {
   1569             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   1570         }
   1571         break;
   1572         default:
   1573             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
   1574             break;
   1575     }
   1576 }
   1577 
   1578 void PVMFFileOutputNode::DoReset(PVMFFileOutputNodeCommand& aCmd)
   1579 {
   1580     if (IsAdded())
   1581     {
   1582         if (iInPort)
   1583         {
   1584             OSCL_DELETE(((PVMFFileOutputInPort*)iInPort));
   1585             iInPort = NULL;
   1586         }
   1587 
   1588         //logoff & go back to Created state.
   1589         SetState(EPVMFNodeIdle);
   1590         CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   1591     }
   1592     else
   1593     {
   1594         OSCL_LEAVE(OsclErrInvalidState);
   1595     }
   1596 }
   1597 
   1598 
   1599 void PVMFFileOutputNode::DoRequestPort(PVMFFileOutputNodeCommand& aCmd)
   1600 {
   1601     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1602                     (0, "PVMFFileOutputNode::DoRequestPort"));
   1603     //This node supports port request from any state
   1604 
   1605     //retrieve port tag.
   1606     int32 tag;
   1607     OSCL_String* portconfig;
   1608 
   1609     aCmd.PVMFFileOutputNodeCommandBase::Parse(tag, portconfig);
   1610 
   1611     //validate the tag...
   1612     switch (tag)
   1613     {
   1614         case PVMF_FILE_OUTPUT_NODE_PORT_TYPE_SINK:
   1615             break;
   1616         default:
   1617             //bad port tag
   1618             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
   1619                             (0, "PVMFFileOutputNode::DoRequestPort: Error - Invalid port tag"));
   1620             CommandComplete(iInputCommands, aCmd, PVMFFailure);
   1621             return;
   1622     }
   1623 
   1624     if (iInPort)
   1625     {
   1626         // it's been taken for now, so reject this request
   1627         CommandComplete(iInputCommands, aCmd, PVMFFailure);
   1628         return;
   1629     }
   1630 
   1631     // Create and configure output port
   1632     int32 err;
   1633     PVMFFormatType fmt = PVMF_MIME_FORMAT_UNKNOWN;
   1634     if (portconfig)
   1635     {
   1636         fmt = portconfig->get_str();
   1637     }
   1638 
   1639     if (iFormat != PVMF_MIME_FORMAT_UNKNOWN &&
   1640             iFormat != fmt)
   1641     {
   1642         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
   1643                         (0, "PVMFFileOutputNode::DoRequestPort: Error - Format not supported (format was preset)"));
   1644         CommandComplete(iInputCommands, aCmd, PVMFErrArgument);
   1645         return;
   1646     }
   1647 
   1648     OSCL_TRY(err, iInPort = OSCL_NEW(PVMFFileOutputInPort, (tag, this)););
   1649     if (err != OsclErrNone || !iInPort)
   1650     {
   1651         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
   1652                         (0, "PVMFFileOutputNode::DoRequestPort: Error - PVMFFileOutputInPort::Create() failed"));
   1653         CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
   1654         return;
   1655     }
   1656 
   1657     ((PVMFFileOutputInPort*)iInPort)->SetClock(iClock);
   1658     ((PVMFFileOutputInPort*)iInPort)->SetMargins(iEarlyMargin, iLateMargin);
   1659 
   1660     //if format was provided in mimestring, set it now.
   1661     if (portconfig)
   1662     {
   1663         PVMFFormatType fmt = portconfig->get_str();
   1664         if (fmt != PVMF_MIME_FORMAT_UNKNOWN
   1665                 && ((PVMFFileOutputInPort*)iInPort)->IsFormatSupported(fmt))
   1666         {
   1667             ((PVMFFileOutputInPort*)iInPort)->iFormat = fmt;
   1668             ((PVMFFileOutputInPort*)iInPort)->FormatUpdated();
   1669         }
   1670     }
   1671 
   1672     //Return the port pointer to the caller.
   1673     CommandComplete(iInputCommands, aCmd, PVMFSuccess, (OsclAny*)iInPort);
   1674 }
   1675 
   1676 void PVMFFileOutputNode::DoReleasePort(PVMFFileOutputNodeCommand& aCmd)
   1677 {
   1678     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1679                     (0, "PVMFFileOutputNode::DoReleasePort"));
   1680 
   1681     if (iInPort)
   1682     {
   1683         OSCL_DELETE(((PVMFFileOutputInPort*)iInPort));
   1684         iInPort = NULL;
   1685         CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   1686         return;
   1687     }
   1688     CommandComplete(iInputCommands, aCmd, PVMFFailure);
   1689 }
   1690 
   1691 void PVMFFileOutputNode::DoCancelAllCommands(PVMFFileOutputNodeCommand& aCmd)
   1692 {
   1693     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1694                     (0, "PVMFFileOutputNode::DoCancelAllCommands"));
   1695     //first cancel the current command if any
   1696     {
   1697         while (!iCurrentCommand.empty())
   1698             CommandComplete(iCurrentCommand, iCurrentCommand[0], PVMFErrCancelled);
   1699     }
   1700 
   1701     //next cancel all queued commands
   1702     {
   1703         //start at element 1 since this cancel command is element 0.
   1704         while (iInputCommands.size() > 1)
   1705             CommandComplete(iInputCommands, iInputCommands[1], PVMFErrCancelled);
   1706     }
   1707 
   1708     //finally, report cancel complete.
   1709     CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   1710 }
   1711 
   1712 void PVMFFileOutputNode::DoCancelCommand(PVMFFileOutputNodeCommand& aCmd)
   1713 {
   1714     //extract the command ID from the parameters.
   1715     PVMFCommandId id;
   1716     aCmd.PVMFFileOutputNodeCommandBase::Parse(id);
   1717 
   1718     //first check "current" command if any
   1719     {
   1720         PVMFFileOutputNodeCommand* cmd = iCurrentCommand.FindById(id);
   1721         if (cmd)
   1722         {
   1723             //cancel the queued command
   1724             CommandComplete(iCurrentCommand, *cmd, PVMFErrCancelled);
   1725             //report cancel success
   1726             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   1727             return;
   1728         }
   1729     }
   1730 
   1731     //next check input queue.
   1732     {
   1733         //start at element 1 since this cancel command is element 0.
   1734         PVMFFileOutputNodeCommand* cmd = iInputCommands.FindById(id, 1);
   1735         if (cmd)
   1736         {
   1737             //cancel the queued command
   1738             CommandComplete(iInputCommands, *cmd, PVMFErrCancelled);
   1739             //report cancel success
   1740             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   1741             return;
   1742         }
   1743     }
   1744     //if we get here the command isn't queued so the cancel fails.
   1745     CommandComplete(iInputCommands, aCmd, PVMFFailure);
   1746 }
   1747