/* ------------------------------------------------------------------
 * Copyright (C) 1998-2009 PacketVideo
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 * -------------------------------------------------------------------
 */
#include "pvmf_aacffparser_node.h"
#include "pvmf_aacffparser_outport.h"
#include "aacfileparser.h"
#include "media_clock_converter.h"
#include "pv_gau.h"
#include "pvlogger.h"
#include "oscl_error_codes.h"
#include "pvmf_fileformat_events.h"
#include "pvmf_basic_errorinfomessage.h"
#include "pvmf_errorinfomessage_extension.h"
#include "pvmf_media_cmd.h"
#include "pvmf_media_msg_format_ids.h"
#include "pv_mime_string_utils.h"
#include "pvmf_local_data_source.h"
#include "oscl_utf8conv.h"
#include "pvmi_kvp_util.h"
#include "oscl_exclusive_ptr.h"
#include "oscl_int64_utils.h"
#include "aacfileparser.h"
#include "pvmf_source_context_data.h"

#define PVAACFF_MEDIADATA_POOLNUM 8
#define PVAACFF_MEDIADATA_CHUNKSIZE 128


PVMFAACFFParserNode::PVMFAACFFParserNode(int32 aPriority)
        : OsclTimerObject(aPriority, "PVMFAACFFParserNode")
{
    iOutPort = NULL;
    iCurrentCmdId = 0;
    iAACParser = NULL;
    iUseCPMPluginRegistry = false;
    iFileHandle = NULL;
    iLogger = NULL;
    iExtensionRefCount = 0;
    iFirstFrame = true;
    iDataPathLogger			   = NULL;
    iClockLogger			   = NULL;
    iClientClock			   = NULL;

    iCPM                       = NULL;
    iCPMSessionID              = 0xFFFFFFFF;
    iCPMContentType            = PVMF_CPM_CONTENT_FORMAT_UNKNOWN;
    iCPMContentAccessFactory   = NULL;
    iCPMInitCmdId              = 0;
    iCPMOpenSessionCmdId       = 0;
    iCPMRegisterContentCmdId   = 0;
    iCPMRequestUsageId         = 0;
    iCPMUsageCompleteCmdId     = 0;
    iCPMCloseSessionCmdId      = 0;
    iCPMResetCmdId             = 0;
    iRequestedUsage.key        = NULL;
    iApprovedUsage.key         = NULL;
    iAuthorizationDataKvp.key  = NULL;
    iPreviewMode               = false;
    oSourceIsCurrent           = false;
    iPortDataLog               = false;

    iCPMMetaDataExtensionInterface = NULL;
    iCPMGetMetaDataKeysCmdId       = 0;
    iCPMGetMetaDataValuesCmdId     = 0;
    iCPMGetLicenseInterfaceCmdId   = 0;
    iCPMGetLicenseCmdId            = 0;
    iCPMCancelGetLicenseCmdId	   = 0;
    iAACParserNodeMetadataValueCount = 0;

    iGenreIndex = 0;
    iLyricsIndex = 0;

    iDownloadProgressInterface = NULL;
    iDownloadFileSize          = 0;
    iAACHeaderSize             = 0;
    iDataStreamInterface       = NULL;
    iDataStreamReadCapacityObserver = NULL;
    iDataStreamFactory         = NULL;
    iAutoPaused                = false;

    iStreamID				   = 0;
    int32 err;
    OSCL_TRY(err, ConstructL());

    if (err != OsclErrNone)
    {
        //if a leave happened, cleanup and re-throw the error
        iInputCommands.clear();
        iCurrentCommand.clear();
        iCancelCommand.clear();
        iCapability.iInputFormatCapability.clear();
        iCapability.iOutputFormatCapability.clear();
        OSCL_CLEANUP_BASE_CLASS(PVMFNodeInterface);
        OSCL_CLEANUP_BASE_CLASS(OsclTimerObject);
        OSCL_LEAVE(err);
    }
    iFileServer.Connect();
    iInterfaceState = EPVMFNodeCreated;
}



void PVMFAACFFParserNode::ConstructL()
{
    //Create the input command queue.  Use a reserve to avoid lots of
    //dynamic memory allocation.
    iInputCommands.Construct(1, 5);

    //Create the "current command" queue.  It will only contain one
    //command at a time, so use a reserve of 1.
    iCurrentCommand.Construct(0, 1);
    iCancelCommand.Construct(0, 1);

    //Create the port vector.
    //iPortVector.Construct(PVMF_SAMPLE_NODE_PORT_VECTOR_RESERVE);

    //Set the node capability data.
    //This node can support an unlimited number of ports.
    iCapability.iCanSupportMultipleInputPorts = false;
    iCapability.iCanSupportMultipleOutputPorts = false;
    iCapability.iHasMaxNumberOfPorts = true;
    iCapability.iMaxNumberOfPorts = 2;//no maximum
    iCapability.iInputFormatCapability.push_back(PVMFFormatType(PVMF_MIME_AACFF));
    iCapability.iOutputFormatCapability.push_back(PVMFFormatType(PVMF_MIME_MPEG4_AUDIO));



    iAvailableMetadataKeys.reserve(PVMF_AAC_NUM_METADATA_VALUES);
    iAvailableMetadataKeys.clear();
}

PVMFAACFFParserNode::~PVMFAACFFParserNode()
{
    Cancel();
    if (iCPM != NULL)
    {
        iCPM->ThreadLogoff();
        PVMFCPMFactory::DestroyContentPolicyManager(iCPM);
        iCPM = NULL;
    }

    if (IsAdded())
    {
        RemoveFromScheduler();
    }

    //Cleanup commands
    //The command queues are self-deleting, but we want to
    //notify the observer of unprocessed commands.
    while (!iCurrentCommand.empty())
    {
        CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFFailure);
    }
    while (!iCancelCommand.empty())
    {
        CommandComplete(iCancelCommand, iCancelCommand.front(), PVMFFailure);
    }
    while (!iInputCommands.empty())
    {
        CommandComplete(iInputCommands, iInputCommands.front(), PVMFFailure);
    }

    //Cleanup allocated ports
    ReleaseTrack();
    CleanupFileSource();
    iFileServer.Close();

    if (iRequestedUsage.key)
    {
        OSCL_ARRAY_DELETE(iRequestedUsage.key);
        iRequestedUsage.key = NULL;
    }

    if (iApprovedUsage.key)
    {
        OSCL_ARRAY_DELETE(iApprovedUsage.key);
        iApprovedUsage.key = NULL;
    }

    if (iAuthorizationDataKvp.key)
    {
        OSCL_ARRAY_DELETE(iAuthorizationDataKvp.key);
        iAuthorizationDataKvp.key = NULL;
    }

    if (iFileHandle != NULL)
    {
        OSCL_ARRAY_DELETE(iFileHandle);
        iFileHandle = NULL;

    }

    if (iDownloadProgressInterface != NULL)
    {
        iDownloadProgressInterface->cancelResumeNotification();
        iDownloadProgressInterface->removeRef();
    }
}

PVMFStatus PVMFAACFFParserNode::ThreadLogon()
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::ThreadLogon() Called"));
    if (iInterfaceState == EPVMFNodeCreated)
    {
        if (!IsAdded())
        {
            AddToScheduler();
        }
        iLogger = PVLogger::GetLoggerObject("PVMFAACParserNode");
        iDataPathLogger = PVLogger::GetLoggerObject("datapath.sourcenode.aacparsernode");
        iClockLogger = PVLogger::GetLoggerObject("clock");
        iFileServer.Connect();
        SetState(EPVMFNodeIdle);
        return PVMFSuccess;
    }
    PVMF_AACPARSERNODE_LOGERROR((0, "PVMFAACParserNode::ThreadLogon() - Invalid State"));
    return PVMFErrInvalidState;

}

/**
//Do thread-specific node cleanup and go to "Created" state.
*/
PVMFStatus PVMFAACFFParserNode::ThreadLogoff()
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::ThreadLogoff() Called"));
    if (iInterfaceState == EPVMFNodeIdle)
    {
        CleanupFileSource();
        iFileServer.Close();

        if (IsAdded())
        {
            RemoveFromScheduler();
        }
        iLogger = NULL;
        iDataPathLogger = NULL;
        iClockLogger = NULL;
        SetState(EPVMFNodeCreated);
        return PVMFSuccess;
    }
    PVMF_AACPARSERNODE_LOGERROR((0, "PVMFAACParserNode::ThreadLogoff() - Invalid State"));
    return PVMFErrInvalidState;


}

PVMFStatus PVMFAACFFParserNode::GetCapability(PVMFNodeCapability& aNodeCapability)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::GetCapability() called"));

    // TODO: Return the appropriate format capability
    aNodeCapability = iCapability;
    return PVMFSuccess;
}


PVMFPortIter* PVMFAACFFParserNode::GetPorts(const PVMFPortFilter* aFilter)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::GetPorts() called"));
    OSCL_UNUSED_ARG(aFilter);//port filter is not implemented.
    PVMF_AACPARSERNODE_LOGERROR((0, "PVMFAACParserNode::GetPorts() Not Implemented"));

    return NULL;
}


PVMFCommandId PVMFAACFFParserNode::QueryUUID(PVMFSessionId s, const PvmfMimeString& aMimeType,
        Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids,
        bool aExactUuidsOnly,
        const OsclAny* aContext)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::QueryUUID called"));
    PVMFAACFFParserNodeCommand cmd;
    cmd.PVMFAACFFParserNodeCommandBase::Construct(s, PVMF_AAC_PARSER_NODE_QUERYUUID, aMimeType, aUuids, aExactUuidsOnly, aContext);
    return QueueCommandL(cmd);
}

PVMFCommandId PVMFAACFFParserNode::QueryInterface(PVMFSessionId s, const PVUuid& aUuid,
        PVInterface*& aInterfacePtr,
        const OsclAny* aContext)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::QueryInterface called"));
    PVMFAACFFParserNodeCommand cmd;
    cmd.PVMFAACFFParserNodeCommandBase::Construct(s, PVMF_AAC_PARSER_NODE_QUERYINTERFACE, aUuid, aInterfacePtr, aContext);
    return QueueCommandL(cmd);
}


PVMFCommandId PVMFAACFFParserNode::RequestPort(PVMFSessionId s, int32 aPortTag, const PvmfMimeString* aPortConfig, const OsclAny* aContext)
{
    OSCL_UNUSED_ARG(aPortConfig);

    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::RequestPort called"));
    PVMFAACFFParserNodeCommand cmd;
    cmd.PVMFAACFFParserNodeCommandBase::Construct(s, PVMF_AAC_PARSER_NODE_REQUESTPORT, aPortTag, aContext);
    return QueueCommandL(cmd);
}


PVMFCommandId PVMFAACFFParserNode::ReleasePort(PVMFSessionId s, PVMFPortInterface& aPort, const OsclAny* aContext)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::ReleasePort called"));
    PVMFAACFFParserNodeCommand cmd;
    cmd.PVMFAACFFParserNodeCommandBase::Construct(s, PVMF_AAC_PARSER_NODE_RELEASEPORT, aPort, aContext);
    return QueueCommandL(cmd);
}

PVMFCommandId PVMFAACFFParserNode::Init(PVMFSessionId s, const OsclAny* aContext)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::Init called"));
    PVMFAACFFParserNodeCommand cmd;
    cmd.PVMFAACFFParserNodeCommandBase::Construct(s, PVMF_AAC_PARSER_NODE_INIT, aContext);
    return QueueCommandL(cmd);
}

PVMFCommandId PVMFAACFFParserNode::Prepare(PVMFSessionId s, const OsclAny* aContext)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::Prepare called"));
    PVMFAACFFParserNodeCommand cmd;
    cmd.PVMFAACFFParserNodeCommandBase::Construct(s, PVMF_AAC_PARSER_NODE_PREPARE, aContext);
    return QueueCommandL(cmd);
}

PVMFCommandId PVMFAACFFParserNode::Start(PVMFSessionId s, const OsclAny* aContext)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::Start called"));
    PVMFAACFFParserNodeCommand cmd;
    cmd.PVMFAACFFParserNodeCommandBase::Construct(s, PVMF_AAC_PARSER_NODE_START, aContext);
    return QueueCommandL(cmd);
}

PVMFCommandId PVMFAACFFParserNode::Stop(PVMFSessionId s, const OsclAny* aContext)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::Stop called"));
    PVMFAACFFParserNodeCommand cmd;
    cmd.PVMFAACFFParserNodeCommandBase::Construct(s, PVMF_AAC_PARSER_NODE_STOP, aContext);
    return QueueCommandL(cmd);
}

PVMFCommandId PVMFAACFFParserNode::Flush(PVMFSessionId s, const OsclAny* aContext)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::Flush called"));
    PVMFAACFFParserNodeCommand cmd;
    cmd.PVMFAACFFParserNodeCommandBase::Construct(s, PVMF_AAC_PARSER_NODE_FLUSH, aContext);
    return QueueCommandL(cmd);
}

PVMFCommandId PVMFAACFFParserNode::Pause(PVMFSessionId s, const OsclAny* aContext)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::Pause called"));
    PVMFAACFFParserNodeCommand cmd;
    cmd.PVMFAACFFParserNodeCommandBase::Construct(s, PVMF_AAC_PARSER_NODE_PAUSE, aContext);
    return QueueCommandL(cmd);
}

PVMFCommandId PVMFAACFFParserNode::Reset(PVMFSessionId s, const OsclAny* aContext)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::Reset called"));
    PVMFAACFFParserNodeCommand cmd;
    cmd.PVMFAACFFParserNodeCommandBase::Construct(s, PVMF_AAC_PARSER_NODE_RESET, aContext);
    return QueueCommandL(cmd);
}

PVMFCommandId PVMFAACFFParserNode::CancelAllCommands(PVMFSessionId s, const OsclAny* aContext)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::CancelAllCommands called"));
    PVMFAACFFParserNodeCommand cmd;
    cmd.PVMFAACFFParserNodeCommandBase::Construct(s, PVMF_AAC_PARSER_NODE_CANCELALLCOMMANDS, aContext);
    return QueueCommandL(cmd);
}

PVMFCommandId PVMFAACFFParserNode::CancelCommand(PVMFSessionId s, PVMFCommandId aCmdId, const OsclAny* aContext)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::CancelCommand called"));
    PVMFAACFFParserNodeCommand cmd;
    cmd.PVMFAACFFParserNodeCommandBase::Construct(s, PVMF_AAC_PARSER_NODE_CANCELCOMMAND, aCmdId, aContext);
    return QueueCommandL(cmd);
}

// From PVMFMetadataExtensionInterface
uint32 PVMFAACFFParserNode::GetNumMetadataKeys(char* aQueryKeyString)
{
    uint32 num_entries = 0;

    if (aQueryKeyString == NULL)
    {
        num_entries = iAvailableMetadataKeys.size();
    }
    else
    {
        for (uint32 i = 0; i < iAvailableMetadataKeys.size(); i++)
        {
            if (pv_mime_strcmp(iAvailableMetadataKeys[i].get_cstr(), aQueryKeyString) >= 0)
            {
                num_entries++;
            }
        }

        for (uint32 j = 0; j < iCPMMetadataKeys.size(); j++)
        {
            /* Check if the key matches the query key */
            if (pv_mime_strcmp(iCPMMetadataKeys[j].get_cstr(),
                               aQueryKeyString) >= 0)
            {
                num_entries++;
            }
        }
    }
    if ((iCPMMetaDataExtensionInterface != NULL))
    {
        num_entries +=
            iCPMMetaDataExtensionInterface->GetNumMetadataKeys(aQueryKeyString);
    }

    return num_entries;
}

// From PVMFMetadataExtensionInterface
uint32 PVMFAACFFParserNode::GetNumMetadataValues(PVMFMetadataList& aKeyList)
{
    uint32 numkeys = aKeyList.size();
    if (iAACParser == NULL || numkeys == 0)
    {
        return 0;
    }

    uint32 numvalentries = 0;
    for (uint32 lcv = 0; lcv < numkeys; lcv++)
    {

        if (iAACParser->IsID3Frame(aKeyList[lcv]))
        {
            ++numvalentries;
        }
        else if (!oscl_strcmp(aKeyList[lcv].get_cstr(), PVAACMETADATA_DURATION_KEY) &&
                 iAACFileInfo.iDuration > 0)
        {
            // Duration
            // Increment the counter for the number of values found so far
            ++numvalentries;
        }
        else if (!oscl_strcmp(aKeyList[lcv].get_cstr(),  PVAACMETADATA_RANDOM_ACCESS_DENIED_KEY))
        {
            // random-acess-denied
            // Increment the counter for the number of values found so far
            ++numvalentries;
        }
        else if (!oscl_strcmp(aKeyList[lcv].get_cstr(),  PVAACMETADATA_NUMTRACKS_KEY))
        {
            // Number of tracks
            // Increment the counter for the number of values found so far
            ++numvalentries;
        }
        else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVAACMETADATA_TRACKINFO_BITRATE_KEY) == 0) &&
                 iAACFileInfo.iBitrate > 0)
        {
            // Bitrate
            // Increment the counter for the number of values found so far
            ++numvalentries;
        }
        else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVAACMETADATA_TRACKINFO_SAMPLERATE_KEY) == 0) &&
                 iAACFileInfo.iSampleFrequency > 0)
        {
            // Sampling rate
            // Increment the counter for the number of values found so far
            ++numvalentries;
        }
        else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVAACMETADATA_TRACKINFO_AUDIO_FORMAT_KEY) == 0) &&
                 iAACFileInfo.iFormat != EAACUnrecognized)
        {
            // Format
            // Increment the counter for the number of values found so far
            ++numvalentries;
        }
    }
    if ((iCPMMetaDataExtensionInterface != NULL))
    {
        numvalentries +=
            iCPMMetaDataExtensionInterface->GetNumMetadataValues(aKeyList);
    }

    return numvalentries;
}

// From PVMFMetadataExtensionInterface
PVMFCommandId PVMFAACFFParserNode::GetNodeMetadataKeys(PVMFSessionId aSessionId, PVMFMetadataList& aKeyList,
        uint32 starting_index, int32 max_entries, char* query_key, const OsclAny* aContext)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::GetNodeMetadataKeys called"));

    PVMFAACFFParserNodeCommand cmd;
    cmd.PVMFAACFFParserNodeCommand::Construct(aSessionId, PVMF_AAC_PARSER_NODE_GETNODEMETADATAKEYS, aKeyList, starting_index, max_entries, query_key, aContext);
    return QueueCommandL(cmd);
}


// From PVMFMetadataExtensionInterface
PVMFCommandId PVMFAACFFParserNode::GetNodeMetadataValues(PVMFSessionId aSessionId, PVMFMetadataList& aKeyList,
        Oscl_Vector<PvmiKvp, OsclMemAllocator>& aValueList, uint32 starting_index, int32 max_entries, const OsclAny* aContext)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::GetNodeMetadataValues called"));

    PVMFAACFFParserNodeCommand cmd;
    cmd.PVMFAACFFParserNodeCommand::Construct(aSessionId, PVMF_AAC_PARSER_NODE_GETNODEMETADATAVALUES, aKeyList, aValueList, starting_index, max_entries, aContext);
    return QueueCommandL(cmd);
}


// From PVMFMetadataExtensionInterface
PVMFStatus PVMFAACFFParserNode::ReleaseNodeMetadataKeys(PVMFMetadataList& , uint32 , uint32)
{

    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::ReleaseNodeMetadataKeys called"));
    //nothing needed-- there's no dynamic allocation in this node's key list
    return PVMFSuccess;
}


// From PVMFMetadataExtensionInterface
PVMFStatus PVMFAACFFParserNode::ReleaseNodeMetadataValues(Oscl_Vector<PvmiKvp, OsclMemAllocator>& aValueList, uint32 start, uint32 end)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::ReleaseNodeMetadataValues called"));

    if (start > end || aValueList.size() == 0)
    {
        PVMF_AACPARSERNODE_LOGERROR((0, "PVMFAACFFParserNode::ReleaseNodeMetadataValues() Invalid start/end index"));
        return PVMFErrArgument;
    }

    end = OSCL_MIN(aValueList.size(), iAACParserNodeMetadataValueCount);

    for (uint32 i = start; i < end; i++)
    {
        if (aValueList[i].key != NULL)
        {
            switch (GetValTypeFromKeyString(aValueList[i].key))
            {
                case PVMI_KVPVALTYPE_WCHARPTR:
                    if (aValueList[i].value.pWChar_value != NULL)
                    {
                        OSCL_ARRAY_DELETE(aValueList[i].value.pWChar_value);
                        aValueList[i].value.pWChar_value = NULL;
                    }
                    break;

                case PVMI_KVPVALTYPE_CHARPTR:
                    if (aValueList[i].value.pChar_value != NULL)
                    {
                        OSCL_ARRAY_DELETE(aValueList[i].value.pChar_value);
                        aValueList[i].value.pChar_value = NULL;
                    }
                    break;

                case PVMI_KVPVALTYPE_UINT32:
                case PVMI_KVPVALTYPE_UINT8:
                    // No memory to free for these valtypes
                    break;

                default:
                    // Should not get a value that wasn't created from here
                    break;
            }

            OSCL_ARRAY_DELETE(aValueList[i].key);
            aValueList[i].key = NULL;
        }
    }

    return PVMFSuccess;
}

// From PvmfDataSourcePlaybackControlInterface
PVMFCommandId PVMFAACFFParserNode::SetDataSourcePosition(PVMFSessionId aSessionId
        , PVMFTimestamp aTargetNPT
        , PVMFTimestamp& aActualNPT
        , PVMFTimestamp& aActualMediaDataTS
        , bool aSeekToSyncPoint
        , uint32 aStreamID
        , OsclAny* aContext)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::SetDataSourcePosition called"));

    PVMFAACFFParserNodeCommand cmd;
    cmd.PVMFAACFFParserNodeCommand::Construct(aSessionId, PVMF_AAC_PARSER_NODE_SET_DATASOURCE_POSITION, aTargetNPT, aActualNPT,
            aActualMediaDataTS, aSeekToSyncPoint, aStreamID, aContext);
    return QueueCommandL(cmd);
}


// From PvmfDataSourcePlaybackControlInterface
PVMFCommandId PVMFAACFFParserNode::QueryDataSourcePosition(PVMFSessionId aSessionId
        , PVMFTimestamp aTargetNPT
        , PVMFTimestamp& aActualNPT
        , bool aSeekToSyncPoint
        , OsclAny* aContext)
{

    PVMFAACFFParserNodeCommand cmd;
    cmd.PVMFAACFFParserNodeCommand::Construct(aSessionId, PVMF_AAC_PARSER_NODE_QUERY_DATASOURCE_POSITION, aTargetNPT, aActualNPT, aSeekToSyncPoint, aContext);
    return QueueCommandL(cmd);
}

PVMFCommandId PVMFAACFFParserNode::QueryDataSourcePosition(PVMFSessionId aSessionId
        , PVMFTimestamp aTargetNPT
        , PVMFTimestamp& aSeekPointBeforeTargetNPT
        , PVMFTimestamp& aSeekPointAfterTargetNPT
        , OsclAny* aContext
        , bool aSeekToSyncPoint)
{
    OSCL_UNUSED_ARG(aSeekPointAfterTargetNPT);
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVMFAACFFParserNode::QueryDataSourcePosition: aTargetNPT=%d, aSeekToSyncPoint=%d, aContext=0x%x",
                     aTargetNPT, aSeekToSyncPoint, aContext));

    PVMFAACFFParserNodeCommand cmd;
    // Construct not changes. aSeekPointBeforeTargetNPT will act as aActualtNPT
    cmd.PVMFAACFFParserNodeCommand::Construct(aSessionId, PVAACFF_NODE_CMD_QUERYDATASOURCEPOSITION, aTargetNPT, aSeekPointBeforeTargetNPT, aSeekToSyncPoint, aContext);
    return QueueCommandL(cmd);

}

// From PvmfDataSourcePlaybackControlInterface
PVMFCommandId PVMFAACFFParserNode::SetDataSourceRate(PVMFSessionId aSessionId
        , int32 aRate
        , PVMFTimebase* aTimebase
        , OsclAny* aContext)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::SetDataSourceRate called"));


    PVMFAACFFParserNodeCommand cmd;
    cmd.PVMFAACFFParserNodeCommand::Construct(aSessionId, PVMF_AAC_PARSER_NODE_SET_DATASOURCE_RATE, aRate, aTimebase, aContext);
    return QueueCommandL(cmd);
}
void
PVMFAACFFParserNode::MoveCmdToCurrentQueue(PVMFAACFFParserNodeCommand& aCmd)
{
    int32 err;
    OSCL_TRY(err, iCurrentCommand.StoreL(aCmd););
    if (err != OsclErrNone)
    {
        CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
        return;
    }
    iInputCommands.Erase(&aCmd);
    return;
}

void
PVMFAACFFParserNode::MoveCmdToCancelQueue(PVMFAACFFParserNodeCommand& aCmd)
{
    /*
     * note: the StoreL cannot fail since the queue is never more than 1 deep
     * and we reserved space.
     */
    iCancelCommand.StoreL(aCmd);
    iInputCommands.Erase(&aCmd);
}

void PVMFAACFFParserNode::Run()
{
    //Process async node commands.
    if (!iInputCommands.empty())
    {
        ProcessCommand();
        /*
         * note: need to check the state before re-scheduling
         * since the node could have been reset in the ProcessCommand
         * call.
         */
        if (iInterfaceState != EPVMFNodeCreated)
        {
            RunIfNotReady();
        }
        return;
    }

    // Send outgoing messages
    if (iInterfaceState == EPVMFNodeStarted || FlushPending())
    {
        PVAACFFNodeTrackPortInfo* trackPortInfoPtr = NULL;

        if (!GetTrackInfo(iOutPort, trackPortInfoPtr))
        {
            PVMF_AACPARSERNODE_LOGERROR((0, "PVAACParserNode::Run: Error - GetTrackInfo failed"));
            return;
        }
        ProcessPortActivity(trackPortInfoPtr);

        if (CheckForPortRescheduling())
        {
            /*
             * Re-schedule since there is atleast one port that needs processing
             */
            RunIfNotReady();
        }
    }

    // Detect Flush command completion.
    if (FlushPending()
            && iOutPort
            && iOutPort->OutgoingMsgQueueSize() == 0)
    {
        SetState(EPVMFNodePrepared);
        //Flush is complete.
        //resume port input so the ports can be re-started.
        iOutPort->ResumeInput();
        CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess);
    }
}

bool PVMFAACFFParserNode::RetrieveTrackConfigInfo(PVAACFFNodeTrackPortInfo& aTrackPortInfo)
{
    // Check if the track has decoder config info
    uint32 specinfosize = iAACParser->GetTrackDecoderSpecificInfoSize();
    if (specinfosize == 0)
    {
        // There is no decoder specific info so return as error. AAC requires audio config header
        return false;
    }

    // Create mem frag for decoder specific config
    OsclMemAllocDestructDealloc<uint8> my_alloc;
    OsclRefCounter* my_refcnt;
    uint aligned_refcnt_size = oscl_mem_aligned_size(sizeof(OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >));
    uint8* my_ptr = NULL;
    int32 errcode = 0;
    OSCL_TRY(errcode, my_ptr = (uint8*) my_alloc.ALLOCATE(aligned_refcnt_size + specinfosize));
    OSCL_FIRST_CATCH_ANY(errcode, return false);

    my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >(my_ptr));
    my_ptr += aligned_refcnt_size;

    OsclMemoryFragment memfrag;
    memfrag.len = specinfosize;
    memfrag.ptr = my_ptr;

    OsclRefCounterMemFrag configinfo_refcntmemfrag(memfrag, my_refcnt, specinfosize);

    // Retrieve the decoder specific info from file parser
    uint8* specinfoptr = iAACParser->GetTrackDecoderSpecificInfoContent();

    if (specinfoptr == NULL)
    {
        // Error
        return false;
    }

    // Copy the decoder specific info to the memory fragment
    oscl_memcpy(memfrag.ptr, specinfoptr, specinfosize);

    // Save format specific info
    aTrackPortInfo.iFormatSpecificConfig = configinfo_refcntmemfrag;

    return true;
}

PVMFStatus PVMFAACFFParserNode::RetrieveMediaSample(PVAACFFNodeTrackPortInfo* aTrackInfoPtr,
        PVMFSharedMediaDataPtr& aMediaDataOut)
{

    // Create a data buffer from pool
    int errcode = OsclErrNoResources;
    OsclSharedPtr<PVMFMediaDataImpl> mediaDataImplOut;
    mediaDataImplOut = aTrackInfoPtr->iResizableSimpleMediaMsgAlloc->allocate(MAXTRACKDATASIZE);

    if (mediaDataImplOut.GetRep() != NULL)
    {
        errcode = OsclErrNone;
    }

    OsclMemPoolResizableAllocatorObserver* resizableAllocObs =
        OSCL_STATIC_CAST(OsclMemPoolResizableAllocatorObserver*, aTrackInfoPtr);

    // Enable flag to receive event when next deallocate() is called on pool
    if (errcode != OsclErrNone)
    {
        aTrackInfoPtr->iTrackDataMemoryPool->notifyfreeblockavailable(*resizableAllocObs);
        return PVMFErrBusy;
    }

    // Now create a PVMF media data from pool
    errcode = OsclErrNoResources;
    aMediaDataOut = PVMFMediaData::createMediaData(mediaDataImplOut, aTrackInfoPtr->iMediaDataMemPool);

    if (aMediaDataOut.GetRep() != NULL)
    {
        errcode = OsclErrNone;
    }

    OsclMemPoolFixedChunkAllocatorObserver* fixedChunkObs =
        OSCL_STATIC_CAST(OsclMemPoolFixedChunkAllocatorObserver*, aTrackInfoPtr);

    // Enable flag to receive event when next deallocate() is called on pool
    if (errcode != OsclErrNone)
    {
        aTrackInfoPtr->iMediaDataMemPool->notifyfreechunkavailable(*fixedChunkObs);
        return PVMFErrBusy;
    }



    // Retrieve memory fragment to write to
    OsclRefCounterMemFrag refCtrMemFragOut;
    OsclMemoryFragment memFragOut;
    aMediaDataOut->getMediaFragment(0, refCtrMemFragOut);
    memFragOut.ptr = refCtrMemFragOut.getMemFrag().ptr;

    Oscl_Vector<uint32, OsclMemAllocator> payloadSizeVec;

    uint32 numsamples = NUM_AAC_FRAMES;
    // Set up the GAU structure
    GAU gau;
    gau.numMediaSamples = numsamples;
    gau.buf.num_fragments = 1;
    gau.buf.buf_states[0] = NULL;
    gau.buf.fragments[0].ptr = refCtrMemFragOut.getMemFrag().ptr;
    gau.buf.fragments[0].len = refCtrMemFragOut.getCapacity();

    bool oIncludeADTSHeaders = false;
    if ((aTrackInfoPtr->oADTS == true) &&
            (PVMF_AAC_PARSER_NODE_INCLUDE_ADTS_HEADERS == 1))
    {
        oIncludeADTSHeaders = true;
    }

    int32 retval = iAACParser->GetNextBundledAccessUnits(&numsamples, &gau, oIncludeADTSHeaders);
    uint32 actualdatasize = 0;
    for (uint32 i = 0; i < numsamples; i++)
    {
        actualdatasize += gau.info[i].len;
    }

    if (retval == AACBitstreamObject::EVERYTHING_OK)
    {
        memFragOut.len = actualdatasize;

        // Set Actual size
        aMediaDataOut->setMediaFragFilledLen(0, actualdatasize);

        // Resize memory fragment
        aTrackInfoPtr->iResizableSimpleMediaMsgAlloc->ResizeMemoryFragment(mediaDataImplOut);

        // Compute the continous timestamp
        aTrackInfoPtr->iContinuousTimeStamp = gau.info[0].ts + aTrackInfoPtr->iTimestampOffset;

        uint32 timestamp = 0xFFFFFFFF;

        if (gau.info[0].ts != 0xFFFFFFFF)
        {
            // Retrieve timestamp and convert to milliseconds
            aTrackInfoPtr->iClockConverter->update_clock(gau.info[0].ts + aTrackInfoPtr->iTimestampOffset);
            timestamp = aTrackInfoPtr->iClockConverter->get_converted_ts(1000);
        }

        // Set the media data's timestamp
        aTrackInfoPtr->iPrevSampleTimeStamp = gau.info[0].ts;
        aMediaDataOut->setTimestamp(timestamp);
        aMediaDataOut->setSeqNum(aTrackInfoPtr->iSeqNum);
        aMediaDataOut->setStreamID(iStreamID);
        if (aTrackInfoPtr->iSeqNum == 0)
        {
            aMediaDataOut->setFormatSpecificInfo(aTrackInfoPtr->iFormatSpecificConfig);
        }
        aTrackInfoPtr->iSeqNum += 1;

        // Set M bit to 1 always - ASF FF only outputs complete frames
        uint32 markerInfo = 0;
        markerInfo |= PVMF_MEDIA_DATA_MARKER_INFO_M_BIT;

        // Set Key Frame bit
        if (iFirstFrame)
        {
            markerInfo |= PVMF_MEDIA_DATA_MARKER_INFO_RANDOM_ACCESS_POINT_BIT;
            iFirstFrame = false;
        }
        mediaDataImplOut->setMarkerInfo(markerInfo);
    }
    else if (retval == AACBitstreamObject::READ_ERROR)
    {
        payloadSizeVec.clear();
        if (iDownloadProgressInterface != NULL)
        {
            iDownloadProgressInterface->requestResumeNotification(aTrackInfoPtr->iPrevSampleTimeStamp,
                    iDownloadComplete);
            iAutoPaused = true;
            PVMF_AACPARSERNODE_LOGERROR((0, "PVMFAACParserNode::RetrieveMediaSample() - Auto Pause Triggered - TS=%d", aTrackInfoPtr->iPrevSampleTimeStamp));
            PVMF_AACPARSERNODE_LOGDATATRAFFIC((0, "PVMFAACParserNode::RetrieveMediaSample() - Auto Pause Triggered - TS=%d", aTrackInfoPtr->iPrevSampleTimeStamp));
            return PVMFErrBusy;
        }
        else
        {
            PVMF_AACPARSERNODE_LOGERROR((0, "PVMFAACParserNode::RetrieveMediaSample() - Sample Retrieval Failed - Insufficient Data In File"));
            return PVMFFailure;
        }
    }
    else if (retval == AACBitstreamObject::END_OF_FILE)
    {
        PVMF_AACPARSERNODE_LOGDATATRAFFIC((0, "PVMFAACParserNode::RetrieveMediaSample() - END_OF_FILE Reached"));
        aTrackInfoPtr->oEOSReached = true;
        return PVMFInfoEndOfData;
    }
    else
    {
        PVMF_AACPARSERNODE_LOGERROR((0, "PVMFAACParserNode::RetrieveMediaSample() - Sample Retrieval Failed"));
        return PVMFFailure;
    }

    return PVMFSuccess;
}

void PVMFAACFFParserNode::PushToAvailableMetadataKeysList(const char* aKeystr, char* aOptionalParam)
{
    if (aKeystr == NULL)
    {
        return;
    }

    int32 leavecode = 0;
    if (aOptionalParam)
    {
        OSCL_TRY(leavecode, iAvailableMetadataKeys.push_front(aKeystr);
                 iAvailableMetadataKeys[0] += aOptionalParam;);
    }
    else
    {
        OSCL_TRY(leavecode, iAvailableMetadataKeys.push_front(aKeystr));
    }
}

void PVMFAACFFParserNode::DoInit(PVMFAACFFParserNodeCommand& aCmd)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::DoInit() Called"));

    if (iInterfaceState != EPVMFNodeIdle)
    {
        CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
        return;
    }

    MoveCmdToCurrentQueue(aCmd);
    if (iCPM)
    {
        /*
         * Go thru CPM commands before parsing the file in case
         * of a new source file.
         * - Init CPM
         * - Open Session
         * - Register Content
         * - Get Content Type
         * - Approve Usage
         * In case the source file has already been parsed skip to
         * - Approve Usage
         */
        if (oSourceIsCurrent == false)
        {
            InitCPM();
        }
        else
        {
            RequestUsage();
        }
    }
    else
    {
        PVMFStatus status = CheckForAACHeaderAvailability();
        if (status == PVMFSuccess)
        {
            status = ParseAACFile();
            SetState(EPVMFNodeInitialized);
        }
        CommandComplete(iCurrentCommand,
                        iCurrentCommand.front(),
                        status);
    }

}

PVMFStatus PVMFAACFFParserNode::CheckForAACHeaderAvailability()
{
    if (iDataStreamInterface != NULL)
    {
        /*
         * First check if we have minimum number of bytes to recognize
         * the file and determine the header size.
         */
        uint32 currCapacity = 0;
        iDataStreamInterface->QueryReadCapacity(iDataStreamSessionID,
                                                currCapacity);

        if (currCapacity <  AAC_MIN_DATA_SIZE_FOR_RECOGNITION)
        {
            iRequestReadCapacityNotificationID =
                iDataStreamInterface->RequestReadCapacityNotification(iDataStreamSessionID,
                        *this,
                        AAC_MIN_DATA_SIZE_FOR_RECOGNITION);
            return PVMFPending;
        }
        CAACFileParser* iAACParserTemp;
        PVMF_AAC_PARSER_NODE_NEW(NULL, CAACFileParser, (), iAACParserTemp);

        uint32 headerSize32 = 0;
        if (OK == iAACParserTemp->getAACHeaderLen(iSourceURL, false, &iFileServer ,
                iDataStreamFactory, iFileHandle, &headerSize32))
        {
            if (currCapacity < headerSize32)
            {
                iRequestReadCapacityNotificationID =
                    iDataStreamInterface->RequestReadCapacityNotification(iDataStreamSessionID,
                            *this,
                            headerSize32);
                return PVMFPending;
            }
        }
        else
        {
            return PVMFFailure;
        }

        PVMF_AAC_PARSER_NODE_DELETE(NULL, CAACFileParser, iAACParserTemp);
    }
    return PVMFSuccess;
}


PVMFStatus PVMFAACFFParserNode::ParseAACFile()
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACFFParserNode::ParseFile() In"));

    PVMF_AAC_PARSER_NODE_NEW(NULL, CAACFileParser, (), iAACParser);
    if (iAACParser == NULL)
    {
        PVMF_AACPARSERNODE_LOGINFOHI((0, "PVMFAACFFParserNode::ParseFile() Instantion of AAC file parser failed"));
        return PVMFErrNoMemory;
    }

    bool oParseCompleteFile = true;
    if (iDownloadProgressInterface != NULL)
    {
        //a PDL session
        oParseCompleteFile = false;
    }

    PVMFDataStreamFactory* dsFactory = iCPMContentAccessFactory;
    if ((dsFactory == NULL) && (iDataStreamFactory != NULL))
    {
        dsFactory = iDataStreamFactory;
    }

    if (!(iAACParser->InitAACFile(iSourceURL, oParseCompleteFile, &iFileServer , dsFactory, iFileHandle)))
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFAACFFParserNode::ParseFile() Parsing of AAC file parser failed"));
        OSCL_DELETE(iAACParser);
        iAACParser = NULL;
        return PVMFErrNoResources;
    }

    // Retrieve the file info from the parser
    iAACFileInfoValid = iAACParser->RetrieveFileInfo(iAACFileInfo);

    // Retrieve the ID3 metadata from the file if available
    PvmiKvpSharedPtrVector iID3Data;
    iID3DataValid = iAACParser->RetrieveID3Info(iID3Data);
    // Initialize the meta-data keys
    iAvailableMetadataKeys.clear();

    int32 leavecode = 0;

    if (iAACFileInfoValid || iID3DataValid)
    {
        // Following keys are available when the AAC file has been parsed
        if (iAACFileInfo.iDuration > 0)
        {
            leavecode = 0;
            OSCL_TRY(leavecode, iAvailableMetadataKeys.push_back(PVAACMETADATA_DURATION_KEY));
        }

        leavecode = 0;
        OSCL_TRY(leavecode, iAvailableMetadataKeys.push_back(PVAACMETADATA_NUMTRACKS_KEY));

        leavecode = 0;
        OSCL_TRY(leavecode, iAvailableMetadataKeys.push_back(PVAACMETADATA_RANDOM_ACCESS_DENIED_KEY));

        if (iAACFileInfo.iBitrate > 0)
        {
            leavecode = 0;
            OSCL_TRY(leavecode, iAvailableMetadataKeys.push_back(PVAACMETADATA_TRACKINFO_BITRATE_KEY));
        }

        if (iAACFileInfo.iSampleFrequency > 0)
        {
            leavecode = 0;
            OSCL_TRY(leavecode, iAvailableMetadataKeys.push_back(PVAACMETADATA_TRACKINFO_SAMPLERATE_KEY));
        }

        leavecode = 0;
        OSCL_TRY(leavecode, iAvailableMetadataKeys.push_back(PVAACMETADATA_TRACKINFO_AUDIO_FORMAT_KEY));
    }

    if (iID3DataValid)
    {
        leavecode = 0;
        OSCL_TRY(leavecode,
                 for (uint s = 0; s < iID3Data.size(); s++)
    {
        OSCL_HeapString<OsclMemAllocator> keystr((const char *)((*iID3Data[s]).key), oscl_strlen((const char *)((*iID3Data[s]).key)));
            iAvailableMetadataKeys.push_back(keystr);
        }
                );
    }

    //set clip duration on download progress interface
    //applicable to PDL sessions
    {
        if (iAACFileInfoValid)
        {
            if ((iDownloadProgressInterface != NULL) && (iAACFileInfo.iDuration != 0))
            {
                iDownloadProgressInterface->setClipDuration(OSCL_CONST_CAST(uint32, iAACFileInfo.iDuration));
            }
        }
    }
    return PVMFSuccess;
}

void PVMFAACFFParserNode::DoPrepare(PVMFAACFFParserNodeCommand& aCmd)
{
    switch (iInterfaceState)
    {
        case EPVMFNodeInitialized:
            //this node doesn't need to do anything to get ready
            //to start.
            SetState(EPVMFNodePrepared);
            CommandComplete(iInputCommands, aCmd, PVMFSuccess);
            return;

        default:
            CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
            return;
    }
}

void PVMFAACFFParserNode::DoStart(PVMFAACFFParserNodeCommand& aCmd)
{
    switch (iInterfaceState)
    {
        case EPVMFNodePrepared:
        case EPVMFNodePaused:
            //nothing needed
            SetState(EPVMFNodeStarted);
            CommandComplete(iInputCommands, aCmd, PVMFSuccess);
            return;

        default:
            CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
            return;
    }
}

void PVMFAACFFParserNode::DoStop(PVMFAACFFParserNodeCommand& aCmd)
{
    iStreamID = 0;
    switch (iInterfaceState)
    {
        case EPVMFNodeStarted:
        case EPVMFNodePaused:
            if (iDataStreamInterface != NULL)
            {
                PVInterface* iFace = OSCL_STATIC_CAST(PVInterface*, iDataStreamInterface);
                PVUuid uuid = PVMIDataStreamSyncInterfaceUuid;
                iDataStreamFactory->DestroyPVMFCPMPluginAccessInterface(uuid, iFace);
                iDataStreamInterface = NULL;
            }
            // Stop data source

            // Clear queued messages in ports
            if (iOutPort)
            {

                iOutPort->ClearMsgQueues();
            }

            // stop and reset position to beginning
            ResetAllTracks();
            iTrack.iTimestampOffset = 0;
            // Reset the AAC FF to beginning
            if (iAACParser)
            {
                uint32 tmpuint32 = 0;
                iAACParser->ResetPlayback(0, tmpuint32);
            }
            SetState(EPVMFNodePrepared);
            CommandComplete(iInputCommands, aCmd, PVMFSuccess);
            return;

        default:
            CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
            return;
    }
}

void PVMFAACFFParserNode::DoPause(PVMFAACFFParserNodeCommand& aCmd)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::DoPauseNode() Called"));

    if (iInterfaceState != EPVMFNodeStarted)
    {
        CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
        return;
    }
    SetState(EPVMFNodePaused);
    CommandComplete(iInputCommands, aCmd, PVMFSuccess);
    return;
}

void PVMFAACFFParserNode::DoReset(PVMFAACFFParserNodeCommand& aCmd)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::DoReset() Called"));

    MoveCmdToCurrentQueue(aCmd);

    if (iDownloadProgressInterface != NULL)
    {
        iDownloadProgressInterface->cancelResumeNotification();
    }

    if (iFileHandle != NULL)
    {
        /* Indicates that the init was successfull */
        if ((iCPM))
        {
            SendUsageComplete();
        }
        else
        {
            CompleteReset();
        }
    }
    else
    {
        /*
         * Reset without init completing, so just reset the parser node,
         * no CPM stuff necessary
         */
        CompleteReset();
    }



}

void PVMFAACFFParserNode::CompleteReset()
{
    /* stop and cleanup */
    ReleaseTrack();
    CleanupFileSource();
    SetState(EPVMFNodeIdle);
    CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess);
}

void PVMFAACFFParserNode::DoRequestPort(PVMFAACFFParserNodeCommand& aCmd, PVMFPortInterface*& aPort)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFAACFFParserNode::DoRequestPort() In"));

    aPort = NULL;

    int32 tag;
    OSCL_String* mimetype;
    aCmd.PVMFAACFFParserNodeCommandBase::Parse(tag, mimetype);


    //validate the tag...
    switch (tag)
    {
        case PVMF_AAC_PARSER_NODE_PORT_TYPE_SOURCE:
            break;

        default:
            //bad port tag
            PVMF_AACPARSERNODE_LOGERROR((0, "PVMFAACFFParserNode::DoRequestPort: Error - Invalid port tag"));
            CommandComplete(iInputCommands, aCmd, PVMFFailure);
            return;
    }

    //Allocate a new port
    int32 leavecode = 0;
    OSCL_TRY(leavecode, iOutPort = OSCL_NEW(PVMFAACFFParserOutPort, (PVMF_AAC_PARSER_NODE_PORT_TYPE_SOURCE, this)););
    if (leavecode != OsclErrNone || !iOutPort)
    {
        PVMF_AACPARSERNODE_LOGERROR((0, "PVMFAACFFParserNode::DoRequestPort: Error - Out of memory"));
        CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
        return;

    }

    //validate the requested format
    if (mimetype)
    {
        PVMFFormatType fmt = mimetype->get_str();
        if (!iOutPort->IsFormatSupported(fmt))
        {
            PVMF_AACPARSERNODE_LOGERROR((0, "PVMFAACFFParserNode::DoRequestPort: Error - Invalid Format!"));
            PVMF_AAC_PARSER_NODE_DELETE(NULL, PVMFAACFFParserOutPort, iOutPort);
            iOutPort = NULL;
            CommandComplete(iInputCommands, aCmd, PVMFFailure);
            return;
        }
    }

    {
        if (!iAACParser)
        {
            CommandComplete(iInputCommands, aCmd, PVMFFailure);
            return;

        }

        TPVAacFileInfo aacinfo;
        oscl_memset(&aacinfo, 0, sizeof(TPVAacFileInfo));
        if (!iAACParser->RetrieveFileInfo(aacinfo))
        {
            CommandComplete(iInputCommands, aCmd, PVMFFailure);
            return;
        }

        MediaClockConverter* clockconv = NULL;
        OsclMemPoolResizableAllocator* trackdatamempool = NULL;
        TrackDataMemPoolProxyAlloc* trackdatamempoolproxy = NULL;
        PVMFSimpleMediaBufferCombinedAlloc* mediadataimplalloc = NULL;
        PVMFMemPoolFixedChunkAllocator* mediadatamempool = NULL;

        PVMF_AAC_PARSER_NODE_NEW(NULL, MediaClockConverter, (aacinfo.iTimescale), clockconv);

        PVMF_AAC_PARSER_NODE_NEW(NULL, OsclMemPoolResizableAllocator, (2*MAXTRACKDATASIZE), trackdatamempool);

        PVMF_AAC_PARSER_NODE_NEW(NULL, TrackDataMemPoolProxyAlloc, (*trackdatamempool), trackdatamempoolproxy);

        PVMF_AAC_PARSER_NODE_NEW(NULL, PVMFSimpleMediaBufferCombinedAlloc, (trackdatamempoolproxy), mediadataimplalloc);
        OSCL_TRY(leavecode,

                 mediadatamempool = OSCL_NEW(PVMFMemPoolFixedChunkAllocator, ("AacFFPar", PVAACFF_MEDIADATA_POOLNUM, PVAACFF_MEDIADATA_CHUNKSIZE));
                );

        if (leavecode || !clockconv || !trackdatamempool || !trackdatamempoolproxy || !mediadataimplalloc || !mediadatamempool)
        {
            PVMF_AAC_PARSER_NODE_DELETE(NULL, PVMFAACFFParserOutPort, ((PVMFAACFFParserOutPort*)iOutPort));
            iOutPort = NULL;

            if (clockconv)
            {
                PVMF_AAC_PARSER_NODE_DELETE(NULL, MediaClockConverter, clockconv);
            }
            if (trackdatamempool)
            {
                trackdatamempool->removeRef();
            }

            if (trackdatamempoolproxy)
            {
                PVMF_AAC_PARSER_NODE_DELETE(NULL, TrackDataMemPoolProxyAlloc, trackdatamempoolproxy)
            }
            if (mediadataimplalloc)
            {
                PVMF_AAC_PARSER_NODE_DELETE(NULL, PVMFSimpleMediaBufferCombinedAlloc, mediadataimplalloc);
            }
            if (mediadatamempool)
            {
                PVMF_AAC_PARSER_NODE_DELETE(NULL, PVMFMemPoolFixedChunkAllocator, mediadatamempool);
            }

            CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
            return;
        }

        trackdatamempool->enablenullpointerreturn();
        mediadatamempool->enablenullpointerreturn();

        // Construct iTrack
        iTrack.iTrackId = 0;  // Only support 1 channel so far
        iTrack.iPort = iOutPort;
        iTrack.iClockConverter = clockconv;
        iTrack.iTrackDataMemoryPool = trackdatamempool;
        iTrack.iTrackDataMemoryPoolProxy = trackdatamempoolproxy;
        iTrack.iMediaDataImplAlloc = mediadataimplalloc;
        iTrack.iMediaDataMemPool = mediadatamempool;
        iTrack.iNode = OSCL_STATIC_CAST(OsclTimerObject*, this);
        aPort = iOutPort;
        if (aacinfo.iFormat == EAACADTS)
        {
            iTrack.oADTS = true;
        }
    }
    PVMFResizableSimpleMediaMsgAlloc* resizableSimpleMediaDataImplAlloc = NULL;
    OsclExclusivePtr<PVMFResizableSimpleMediaMsgAlloc> resizableSimpleMediaDataImplAllocAutoPtr;
    PVMF_AAC_PARSER_NODE_NEW(NULL,
                             PVMFResizableSimpleMediaMsgAlloc,
                             (iTrack.iTrackDataMemoryPool),
                             resizableSimpleMediaDataImplAlloc);

    iTrack.iResizableSimpleMediaMsgAlloc = resizableSimpleMediaDataImplAlloc;

    RetrieveTrackConfigInfo(iTrack);

//Return the port pointer to the caller.

    CommandComplete(iInputCommands, aCmd, PVMFSuccess, (OsclAny*)aPort);
    return;

}


void PVMFAACFFParserNode::ResetAllTracks()
{
    iTrack.iMediaData.Unbind();
    iTrack.iSeqNum = 0;
    iFirstFrame = false;
    iTrack.oEOSReached = false;
    iTrack.oEOSSent = false;
    iTrack.oProcessOutgoingMessages = true;
    iTrack.oQueueOutgoingMessages = true;
}


bool PVMFAACFFParserNode::ReleaseTrack()
{
    if (iOutPort)
    {
        iOutPort->Disconnect();
        PVMF_AAC_PARSER_NODE_DELETE(NULL, PVMFAACFFParserOutPort, ((PVMFAACFFParserOutPort*)iOutPort));
        iOutPort = NULL;
    }

    iTrack.iMediaData.Unbind();

    if (iTrack.iClockConverter)
    {
        PVMF_AAC_PARSER_NODE_DELETE(NULL, MediaClockConverter, iTrack.iClockConverter);
        iTrack.iClockConverter = NULL;
    }

    if (iTrack.iTrackDataMemoryPool)
    {
        iTrack.iTrackDataMemoryPool->removeRef();
        iTrack.iTrackDataMemoryPool = NULL;
    }
    if (iTrack.iTrackDataMemoryPoolProxy)
    {
        PVMF_AAC_PARSER_NODE_DELETE(NULL, TrackDataMemPoolProxyAlloc, iTrack.iTrackDataMemoryPoolProxy);

        iTrack.iTrackDataMemoryPoolProxy = NULL;
    }
    if (iTrack.iMediaDataImplAlloc)
    {
        PVMF_AAC_PARSER_NODE_DELETE(NULL, PVMFSimpleMediaBufferCombinedAlloc, iTrack.iMediaDataImplAlloc);
        iTrack.iMediaDataImplAlloc = NULL;
    }

    if (iTrack.iMediaDataMemPool != NULL)
    {
        iTrack.iMediaDataMemPool->CancelFreeChunkAvailableCallback();
        iTrack.iMediaDataMemPool->removeRef();
        iTrack.iMediaDataMemPool = NULL;
    }
    if (iTrack.iResizableSimpleMediaMsgAlloc)
    {
        PVMF_AAC_PARSER_NODE_DELETE(NULL,
                                    PVMFResizableSimpleMediaMsgAlloc,
                                    iTrack.iResizableSimpleMediaMsgAlloc);
        iTrack.iResizableSimpleMediaMsgAlloc = NULL;
    }

    return true;
}


void PVMFAACFFParserNode::CleanupFileSource()
{
    iAvailableMetadataKeys.clear();

    if (iAACParser)
    {
        PVMF_AAC_PARSER_NODE_DELETE(NULL, CAACFileParser, iAACParser);
    }
    iAACParser = NULL;
    iAACParserNodeMetadataValueCount = 0;
    iUseCPMPluginRegistry = false;
    iCPMSourceData.iFileHandle = NULL;
    if (iCPMContentAccessFactory != NULL)
    {
        iCPMContentAccessFactory->removeRef();
        iCPMContentAccessFactory = NULL;
    }
    if (iDataStreamFactory != NULL)
    {
        iDataStreamFactory->removeRef();
        iDataStreamFactory = NULL;
    }

    iCPMContentType = PVMF_CPM_CONTENT_FORMAT_UNKNOWN;
    iPreviewMode = false;
    oSourceIsCurrent = false;
    if (iFileHandle)
    {
        OSCL_DELETE(iFileHandle);
    }
    iFileHandle = NULL;

}

void PVMFAACFFParserNode::SetState(TPVMFNodeInterfaceState s)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACFFParserNode::SetState() %d", s));
    PVMFNodeInterface::SetState(s);
}

void PVMFAACFFParserNode::ReportAACFFParserErrorEvent(PVMFEventType aEventType, OsclAny* aEventData, PVUuid* aEventUUID, int32* aEventCode)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACFFParserNode:ReportAACFFParserErrorEvent Type %d Data %d"
                                      , aEventType, aEventData));

    if (aEventUUID && aEventCode)
    {
        PVMFBasicErrorInfoMessage* eventmsg;
        PVMF_AAC_PARSER_NODE_NEW(NULL,
                                 PVMFBasicErrorInfoMessage,
                                 (*aEventCode, *aEventUUID, NULL),
                                 eventmsg);
        PVMFAsyncEvent asyncevent(PVMFErrorEvent, aEventType, NULL, eventmsg, aEventData, NULL, 0);
        PVMFNodeInterface::ReportErrorEvent(asyncevent);
        eventmsg->removeRef();
    }
    else
    {
        PVMFNodeInterface::ReportErrorEvent(aEventType, aEventData);
    }
}

void PVMFAACFFParserNode::ReportAACFFParserInfoEvent(PVMFEventType aEventType, OsclAny* aEventData, PVUuid* aEventUUID, int32* aEventCode)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACFFParserNode:ReportAACFFParserInfoEvent Type %d Data %d"
                                      , aEventType, aEventData));

    if (aEventUUID && aEventCode)
    {
        PVMFBasicErrorInfoMessage* eventmsg;
        PVMF_AAC_PARSER_NODE_NEW(NULL,
                                 PVMFBasicErrorInfoMessage,
                                 (*aEventCode, *aEventUUID, NULL),
                                 eventmsg);
        PVMFAsyncEvent asyncevent(PVMFInfoEvent, aEventType, NULL, eventmsg, aEventData, NULL, 0);
        PVMFNodeInterface::ReportInfoEvent(asyncevent);
        eventmsg->removeRef();
    }
    else
    {
        PVMFNodeInterface::ReportInfoEvent(aEventType, aEventData);
    }
}

void PVMFAACFFParserNode::HandlePortActivity(const PVMFPortActivity &aActivity)
{

    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACFFParserNode::PortActivity: port=0x%x, type=%d",
                                      aActivity.iPort, aActivity.iType));

    /*
     * A port is reporting some activity or state change.  This code
     * figures out whether we need to queue a processing event
     * for the AO, and/or report a node event to the observer.
     */
    switch (aActivity.iType)
    {
        case PVMF_PORT_ACTIVITY_CREATED:
            /*
             * Report port created info event to the node.
             */
            ReportInfoEvent(PVMFInfoPortCreated, (OsclAny*)aActivity.iPort);
            break;

        case PVMF_PORT_ACTIVITY_DELETED:
        {
            /*
             * Report port deleted info event to the node.
             */
            ReportInfoEvent(PVMFInfoPortDeleted, (OsclAny*)aActivity.iPort);
        }
        break;

        case PVMF_PORT_ACTIVITY_CONNECT:
            break;

        case PVMF_PORT_ACTIVITY_DISCONNECT:
            break;

        case PVMF_PORT_ACTIVITY_OUTGOING_MSG:
        {
            /*
             * An outgoing message was queued on this port.
             * Wakeup the node to process the same.
             */
            RunIfNotReady();
        }
        break;

        case PVMF_PORT_ACTIVITY_INCOMING_MSG:
        {
            /*
             * There are no input ports to this node
             */
            OSCL_ASSERT(false);
        }
        break;

        case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_BUSY:
        {
            /*
             * This implies that this output port cannot accept any more
             * msgs on its outgoing queue. This implies that we should stop
             * retrieving samples from file to queue.
             */
            PVAACFFNodeTrackPortInfo* trackInfoPtr = NULL;
            if (!GetTrackInfo(aActivity.iPort, trackInfoPtr))
            {
                ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aActivity.iPort));
                PVMF_AACPARSERNODE_LOGERROR((0, "0x%x PVMFAACFFParserNode::HandlePortActivity: Error - GetTrackInfo failed", this));
                return;
            }
            trackInfoPtr->oQueueOutgoingMessages = false;
        }
        break;

        case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY:
        {
            /*
             * Outgoing queue was previously busy, but is now ready.
             * We are ready to send new samples from file.
             */
            PVAACFFNodeTrackPortInfo* trackInfoPtr = NULL;
            if (!GetTrackInfo(aActivity.iPort, trackInfoPtr))
            {
                ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aActivity.iPort));
                PVMF_AACPARSERNODE_LOGERROR((0, "0x%x PVMFAACFFParserNode::HandlePortActivity: Error - GetTrackInfo failed", this));
                return;
            }
            trackInfoPtr->oQueueOutgoingMessages = true;
            RunIfNotReady();
        }
        break;

        case PVMF_PORT_ACTIVITY_CONNECTED_PORT_BUSY:
        {
            /*
             * The connected port has become busy (its incoming queue is
             * busy). There is nothing to do but to wait for connected port
             * ready.
             */
            PVAACFFNodeTrackPortInfo* trackInfoPtr = NULL;
            if (!GetTrackInfo(aActivity.iPort, trackInfoPtr))
            {
                ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aActivity.iPort));
                PVMF_AACPARSERNODE_LOGERROR((0, "0x%x PVMFAACFFParserNode::HandlePortActivity: Error - GetTrackInfo failed", this));
                return;
            }
            trackInfoPtr->oProcessOutgoingMessages = false;
        }
        break;

        case PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY:
        {
            /*
             * The connected port has transitioned from Busy to Ready.
             * It's time to start sending messages again.
             */
            PVAACFFNodeTrackPortInfo* trackInfoPtr = NULL;
            if (!GetTrackInfo(aActivity.iPort, trackInfoPtr))
            {
                ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aActivity.iPort));
                PVMF_AACPARSERNODE_LOGERROR((0, "0x%x PVMFAACFFParserNode::HandlePortActivity: Error - GetTrackInfo failed", this));
                return;
            }
            trackInfoPtr->oProcessOutgoingMessages = true;
            RunIfNotReady();
        }
        break;


        default:
            break;
    }
}

PVMFCommandId PVMFAACFFParserNode::QueueCommandL(PVMFAACFFParserNodeCommand& aCmd)
{
    if (IsAdded())
    {
        PVMFCommandId id;
        id = iInputCommands.AddL(aCmd);
        /* Wakeup the AO */
        RunIfNotReady();
        return id;
    }
    OSCL_LEAVE(OsclErrInvalidState);
    return -1;
}


/**
//A routine to tell if a flush operation is in progress.
*/
bool PVMFAACFFParserNode::FlushPending()
{
    return (iCurrentCommand.size() > 0
            && iCurrentCommand.front().iCmd == PVMF_AAC_PARSER_NODE_FLUSH);
}


/**
//Called by the command handler AO to process a command from
//the input queue.
//Return true if a command was processed, false if the command
//processor is busy and can't process another command now.
*/
void PVMFAACFFParserNode::ProcessCommand()
{
    //This call will process the first node command in the input queue.

    //Can't do anything when an asynchronous cancel is in progress-- just
    //need to wait on completion.
    if (!iCancelCommand.empty())
    {
        return; //keep waiting.
    }

    //If a command is in progress, only a hi-pri command can interrupt it.
    if (!iCurrentCommand.empty()
            && !iInputCommands.front().hipri() && iInputCommands.front().iCmd != PVMF_AAC_PARSER_NODE_CANCEL_GET_LICENSE)
    {
        return; //keep waiting
    }

    //The newest or highest pri command is in the front of the queue.
    OSCL_ASSERT(!iInputCommands.empty());
    PVMFAACFFParserNodeCommand& aCmd = iInputCommands.front();

    PVMFStatus cmdstatus;
    OsclAny* eventdata = NULL;
    if (aCmd.hipri() || aCmd.iCmd == PVMF_AAC_PARSER_NODE_CANCEL_GET_LICENSE)
    {
        //Process the Hi-Pri commands.
        switch (aCmd.iCmd)
        {
            case PVMF_AAC_PARSER_NODE_CANCELALLCOMMANDS:
                DoCancelAllCommands(aCmd);
                break;

            case PVMF_AAC_PARSER_NODE_CANCELCOMMAND:
                DoCancelCommand(aCmd);
                break;

            case PVMF_AAC_PARSER_NODE_CANCEL_GET_LICENSE:
                DoCancelGetLicense(aCmd);
                break;

            default:
                OSCL_ASSERT(false);
                CommandComplete(iInputCommands, aCmd, PVMFErrNotSupported);
                break;
        }
    }
    else
    {
        //Process the normal pri commands.
        switch (aCmd.iCmd)
        {
            case PVMF_AAC_PARSER_NODE_QUERYUUID:
                DoQueryUuid(aCmd);
                break;

            case PVMF_AAC_PARSER_NODE_QUERYINTERFACE:
                DoQueryInterface(aCmd);
                break;

            case PVMF_AAC_PARSER_NODE_REQUESTPORT:
            {
                PVMFPortInterface*port;
                DoRequestPort(aCmd, port);
                eventdata = (OsclAny*)port;
            }
            break;

            case PVMF_AAC_PARSER_NODE_RELEASEPORT:
                DoReleasePort(aCmd);
                break;

            case PVMF_AAC_PARSER_NODE_INIT:
                DoInit(aCmd);
                break;

            case PVMF_AAC_PARSER_NODE_PREPARE:
                DoPrepare(aCmd);
                break;

            case PVMF_AAC_PARSER_NODE_START:
                DoStart(aCmd);
                break;

            case PVMF_AAC_PARSER_NODE_STOP:
                DoStop(aCmd);
                break;

            case PVMF_AAC_PARSER_NODE_FLUSH:
                DoFlush(aCmd);
                break;

            case PVMF_AAC_PARSER_NODE_PAUSE:
                DoPause(aCmd);
                break;

            case PVMF_AAC_PARSER_NODE_RESET:
                DoReset(aCmd);
                break;

            case PVMF_AAC_PARSER_NODE_GETNODEMETADATAKEYS:
            {
                cmdstatus = DoGetMetadataKeys(aCmd);
                if (cmdstatus != PVMFPending)
                {
                    CommandComplete(iInputCommands, aCmd, cmdstatus);
                }
                else
                {
                    MoveCmdToCurrentQueue(aCmd);
                }
            }
            break;

            case PVMF_AAC_PARSER_NODE_GETNODEMETADATAVALUES:
            {
                cmdstatus = DoGetMetadataValues(aCmd);
                if (cmdstatus != PVMFPending)
                {
                    CommandComplete(iInputCommands, aCmd, cmdstatus);
                }
                else
                {
                    MoveCmdToCurrentQueue(aCmd);
                }
            }
            break;

            case PVMF_AAC_PARSER_NODE_SET_DATASOURCE_POSITION:
            {
                cmdstatus = DoSetDataSourcePosition(aCmd);
                if (cmdstatus != PVMFPending)
                {
                    CommandComplete(iInputCommands, aCmd, cmdstatus);
                }
                else
                {
                    MoveCmdToCurrentQueue(aCmd);
                }
            }
            break;

            case PVMF_AAC_PARSER_NODE_QUERY_DATASOURCE_POSITION:
            {
                cmdstatus = DoQueryDataSourcePosition(aCmd);
                if (cmdstatus != PVMFPending)
                {
                    CommandComplete(iInputCommands, aCmd, cmdstatus);
                }
                else
                {
                    MoveCmdToCurrentQueue(aCmd);
                }
            }
            break;

            case PVMF_AAC_PARSER_NODE_SET_DATASOURCE_RATE:
                cmdstatus = DoSetDataSourceRate(aCmd);
                if (cmdstatus != PVMFPending)
                {
                    CommandComplete(iInputCommands, aCmd, cmdstatus);
                }
                else
                {
                    MoveCmdToCurrentQueue(aCmd);
                }

                break;

            case PVMF_AAC_PARSER_NODE_GET_LICENSE_W:
            {
                PVMFStatus status = DoGetLicense(aCmd, true);
                if (status == PVMFPending)
                {
                    MoveCmdToCurrentQueue(aCmd);
                }
                else
                {
                    CommandComplete(iInputCommands, aCmd, status);
                }
            }
            break;

            case PVMF_AAC_PARSER_NODE_GET_LICENSE:
            {
                PVMFStatus status = DoGetLicense(aCmd);
                if (status == PVMFPending)
                {
                    MoveCmdToCurrentQueue(aCmd);
                }
                else
                {
                    CommandComplete(iInputCommands, aCmd, status);
                }
            }
            break;

            default:
                OSCL_ASSERT(false);
                CommandComplete(iInputCommands, aCmd, PVMFErrNotSupported);
                break;
        }
    }
}

PVMFStatus PVMFAACFFParserNode::ProcessOutgoingMsg(PVAACFFNodeTrackPortInfo* aTrackInfoPtr)
{
    //Called by the AO to process one message off the outgoing
    //message queue for the given port.  This routine will
    //try to send the data to the connected port.


    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::ProcessOutgoingMsg() Called aPort=0x%x", aTrackInfoPtr->iPort));
    PVMFStatus status = aTrackInfoPtr->iPort->Send();
    if (status == PVMFErrBusy)
    {
        /* Connected port is busy */
        aTrackInfoPtr->oProcessOutgoingMessages = false;
        PVMF_AACPARSERNODE_LOGDATATRAFFIC((0, "PVMFAACParserNode::ProcessOutgoingMsg() Connected port is in busy state"));
    }
    else if (status != PVMFSuccess)
    {
        PVMF_AACPARSERNODE_LOGERROR((0, "PVMFAACParserNode::ProcessOutgoingMsg() - aTrackInfoPtr->iPort->Send() Failed"));
    }
    return status;
}

void PVMFAACFFParserNode::DoCancelAllCommands(PVMFAACFFParserNodeCommand& aCmd)
{
    //first cancel the current command if any
    while (!iCurrentCommand.empty())
    {
        MoveCmdToCancelQueue(aCmd);
        //	CommandComplete(iCurrentCommand,iCurrentCommand[0],PVMFErrCancelled);
    }

    //next cancel all queued commands
    //start at element 1 since this cancel command is element 0.
    while (iInputCommands.size() > 1)
    {
        CommandComplete(iInputCommands, iInputCommands[1], PVMFErrCancelled);
    }

    //finally, report cancel complete.
    CommandComplete(iInputCommands, iInputCommands[0], PVMFSuccess);
    return;
}
/**
//Called by the command handler AO to do the Cancel single command
*/
void PVMFAACFFParserNode::DoCancelCommand(PVMFAACFFParserNodeCommand& aCmd)
{
    //extract the command ID from the parameters.
    PVMFCommandId id;
    aCmd.PVMFAACFFParserNodeCommandBase::Parse(id);

    //first check "current" command if any
    PVMFAACFFParserNodeCommand* cmd = iCurrentCommand.FindById(id);
    if (cmd)
    {
        MoveCmdToCancelQueue(*cmd);
        CommandComplete(iCurrentCommand, *cmd, PVMFErrCancelled);
        return;
    }

    //next check input queue.
    //start at element 1 since this cancel command is element 0.
    cmd = iInputCommands.FindById(id, 1);
    if (cmd)
    {
        //cancel the queued command
        CommandComplete(iInputCommands, *cmd, PVMFErrCancelled);
        //report cancel success
        CommandComplete(iInputCommands, aCmd, PVMFSuccess);
        return;
    }

    //if we get here the command isn't queued so the cancel fails.
    CommandComplete(iInputCommands, aCmd, PVMFErrArgument);
}

void PVMFAACFFParserNode::DoFlush(PVMFAACFFParserNodeCommand& aCmd)
{

    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::DoFlushNode() Called"));

    if (iInterfaceState != EPVMFNodeStarted &&
            iInterfaceState != EPVMFNodePaused)
    {
        CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
        return;
    }

    /*
     * the flush is asynchronous.  move the command from
     * the input command queue to the current command, where
     * it will remain until the flush completes.
     */
    MoveCmdToCurrentQueue(aCmd);
    return;
}

void PVMFAACFFParserNode::DoReleasePort(PVMFAACFFParserNodeCommand& aCmd)
{
    //This node supports release port from any state

    //Find the port in the port vector
    PVMFPortInterface* p = NULL;
    aCmd.PVMFAACFFParserNodeCommandBase::Parse(p);

    PVMFAACFFParserOutPort* port = (PVMFAACFFParserOutPort*)p;

    if (iOutPort == port)
    {
        iTrack.iMediaData.Unbind();
        OSCL_DELETE(((PVMFAACFFParserOutPort*)iTrack.iPort));
        iTrack.iPort = NULL;
        iOutPort = NULL;

        ReleaseTrack();
        CommandComplete(iInputCommands, aCmd, PVMFSuccess);
        return;

    }
    else
    {
        //port not found.
        CommandComplete(iInputCommands, aCmd, PVMFFailure);
        return;

    }
}

void PVMFAACFFParserNode::DoQueryUuid(PVMFAACFFParserNodeCommand& aCmd)
{
    //This node supports Query UUID from any state
    OSCL_String* mimetype;
    Oscl_Vector<PVUuid, OsclMemAllocator> *uuidvec;
    bool exactmatch;
    aCmd.PVMFAACFFParserNodeCommandBase::Parse(mimetype, uuidvec, exactmatch);

    if (*mimetype == PVMF_DATA_SOURCE_INIT_INTERFACE_MIMETYPE)
    {
        PVUuid uuid(PVMF_DATA_SOURCE_INIT_INTERFACE_UUID);
        uuidvec->push_back(uuid);
    }
    else if (*mimetype == PVMF_TRACK_SELECTION_INTERFACE_MIMETYPE)
    {
        PVUuid uuid(PVMF_TRACK_SELECTION_INTERFACE_UUID);
        uuidvec->push_back(uuid);
    }
    else if (*mimetype == PVMF_DATA_SOURCE_PLAYBACK_CONTROL_INTERFACE_MIMETYPE)
    {
        PVUuid uuid(PvmfDataSourcePlaybackControlUuid);
        uuidvec->push_back(uuid);
    }
    else if (*mimetype == PVMF_META_DATA_EXTENSION_INTERFACE_MIMETYPE)
    {
        PVUuid uuid(KPVMFMetadataExtensionUuid);
        uuidvec->push_back(uuid);
    }
    CommandComplete(iInputCommands, aCmd, PVMFSuccess);
    return;
}


void PVMFAACFFParserNode::DoQueryInterface(PVMFAACFFParserNodeCommand&  aCmd)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::DoQueryInterface() Called"));


    PVUuid* uuid;
    PVInterface** ptr;
    aCmd.PVMFAACFFParserNodeCommandBase::Parse(uuid, ptr);

    if (queryInterface(*uuid, *ptr))
    {
        (*ptr)->addRef();
        CommandComplete(iInputCommands, aCmd, PVMFSuccess);
    }
    else
    {
        //not supported
        *ptr = NULL;
        CommandComplete(iInputCommands, aCmd, PVMFErrNotSupported);
    }
}

void PVMFAACFFParserNode::addRef()
{
    ++iExtensionRefCount;
}

void PVMFAACFFParserNode::removeRef()
{
    --iExtensionRefCount;
}


bool PVMFAACFFParserNode::queryInterface(const PVUuid& uuid, PVInterface*& iface)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::queryInterface called"));
    if (uuid == PVMF_DATA_SOURCE_INIT_INTERFACE_UUID)
    {
        PVMFDataSourceInitializationExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFDataSourceInitializationExtensionInterface*, this);
        iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
    }
    else if (uuid == PVMF_TRACK_SELECTION_INTERFACE_UUID)
    {
        PVMFTrackSelectionExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFTrackSelectionExtensionInterface*, this);
        iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
    }
    else if (uuid == KPVMFMetadataExtensionUuid)
    {
        PVMFMetadataExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFMetadataExtensionInterface*, this);
        iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
    }
    else if (uuid == PvmfDataSourcePlaybackControlUuid)
    {
        PvmfDataSourcePlaybackControlInterface* myInterface = OSCL_STATIC_CAST(PvmfDataSourcePlaybackControlInterface*, this);
        iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
    }
    else if (uuid == PVMIDatastreamuserInterfaceUuid)
    {
        PVMIDatastreamuserInterface* myInterface = OSCL_STATIC_CAST(PVMIDatastreamuserInterface*, this);
        iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
    }
    else if (uuid == PVMF_FF_PROGDOWNLOAD_SUPPORT_INTERFACE_UUID)
    {
        PVMFFormatProgDownloadSupportInterface* myInterface = OSCL_STATIC_CAST(PVMFFormatProgDownloadSupportInterface*, this);
        iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
    }
    else if (uuid == PVMFCPMPluginLicenseInterfaceUuid)
    {
        PVMFCPMPluginLicenseInterface* myInterface = OSCL_STATIC_CAST(PVMFCPMPluginLicenseInterface*, this);
        iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
    }
    else
    {
        return false;
    }

    ++iExtensionRefCount;
    return true;

}

PVMFStatus PVMFAACFFParserNode::SetSourceInitializationData(OSCL_wString& aSourceURL, PVMFFormatType& aSourceFormat, OsclAny* aSourceData)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::SetSourceInitializationData called"));

    if (aSourceFormat == PVMF_MIME_AACFF)
    {
        /* Clean up any previous sources */
        CleanupFileSource();
        iSourceFormat = aSourceFormat;
        iSourceURL = aSourceURL;

        if (aSourceData)
        {

            // Old context object? query for local datasource availability
            PVInterface* pvInterface =
                OSCL_STATIC_CAST(PVInterface*, aSourceData);

            PVInterface* localDataSrc = NULL;
            PVUuid localDataSrcUuid(PVMF_LOCAL_DATASOURCE_UUID);

            if (pvInterface->queryInterface(localDataSrcUuid, localDataSrc))
            {
                PVMFLocalDataSource* context =
                    OSCL_STATIC_CAST(PVMFLocalDataSource*, localDataSrc);

                iPreviewMode = context->iPreviewMode;
                iUseCPMPluginRegistry = context->iUseCPMPluginRegistry;
                if (context->iFileHandle)
                {

                    PVMF_AAC_PARSER_NODE_NEW(NULL,
                                             OsclFileHandle,
                                             (*(context->iFileHandle)),
                                             iFileHandle);

                    iCPMSourceData.iFileHandle = iFileHandle;
                }
                iCPMSourceData.iPreviewMode = iPreviewMode;
                iCPMSourceData.iIntent = context->iIntent;

            }
            else
            {
                // New context object ?
                PVInterface* sourceDataContext = NULL;
                PVInterface* commonDataContext = NULL;
                PVUuid sourceContextUuid(PVMF_SOURCE_CONTEXT_DATA_UUID);
                PVUuid commonContextUuid(PVMF_SOURCE_CONTEXT_DATA_COMMON_UUID);
                if (pvInterface->queryInterface(sourceContextUuid, sourceDataContext) &&
                        sourceDataContext->queryInterface(commonContextUuid, commonDataContext))
                {
                    PVMFSourceContextDataCommon* context =
                        OSCL_STATIC_CAST(PVMFSourceContextDataCommon*, commonDataContext);

                    iPreviewMode = context->iPreviewMode;
                    iUseCPMPluginRegistry = context->iUseCPMPluginRegistry;
                    if (context->iFileHandle)
                    {

                        PVMF_AAC_PARSER_NODE_NEW(NULL,
                                                 OsclFileHandle,
                                                 (*(context->iFileHandle)),
                                                 iFileHandle);

                        iCPMSourceData.iFileHandle = iFileHandle;
                    }
                    iCPMSourceData.iPreviewMode = iPreviewMode;
                    iCPMSourceData.iIntent = context->iIntent;
                }
            }
        }
        /*
        	 * If a CPM flag is provided in the source data, then
        	 * create a CPM object here...
        	 */
        if (iUseCPMPluginRegistry)
        {
            //cleanup any prior instance
            if (iCPM)
            {
                iCPM->ThreadLogoff();
                PVMFCPMFactory::DestroyContentPolicyManager(iCPM);
                iCPM = NULL;
            }
            iCPM = PVMFCPMFactory::CreateContentPolicyManager(*this);
            iCPM->ThreadLogon();
        }
        return PVMFSuccess;
    }
    PVMF_AACPARSERNODE_LOGERROR((0, "PVMFAACParserNode::SetSourceInitializationData - Unsupported Format"));
    return PVMFFailure;
}

PVMFStatus PVMFAACFFParserNode::SetClientPlayBackClock(PVMFMediaClock* aClientClock)
{
    OSCL_UNUSED_ARG(aClientClock);
    return PVMFSuccess;
}
PVMFStatus PVMFAACFFParserNode::SetEstimatedServerClock(PVMFMediaClock* aClientClock)
{
    OSCL_UNUSED_ARG(aClientClock);
    return PVMFSuccess;
}

//From PVMFTrackSelectionExtensionInterface
PVMFStatus PVMFAACFFParserNode::GetMediaPresentationInfo(PVMFMediaPresentationInfo& aInfo)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFAACFFParserNode::GetMediaPresentationInfo() called"));

    // Check to make sure the AAC file has been parsed
    if (!iAACParser)  return PVMFFailure;

    aInfo.setDurationValue(iAACFileInfo.iDuration);
    // Current version of AAC parser is limited to 1 channel
    PVMFTrackInfo tmpTrackInfo;

    // set the port tag for this track
    tmpTrackInfo.setPortTag(PVMF_AAC_PARSER_NODE_PORT_TYPE_SOURCE);

    // track id
    tmpTrackInfo.setTrackID(0);

    TPVAacFileInfo aacinfo;
    iAACParser->RetrieveFileInfo(aacinfo);
    if (aacinfo.iFormat == EAACUnrecognized) return PVMFErrNotSupported;

    // bitrate
    tmpTrackInfo.setTrackBitRate(aacinfo.iBitrate);

    // timescale
    tmpTrackInfo.setTrackDurationTimeScale((uint64)aacinfo.iTimescale);

    // config info

    // mime type
    OSCL_FastString mime_type;
    switch (aacinfo.iFormat)
    {
        case EAACADIF:
        case EAACRaw:
            mime_type = PVMF_MIME_ADIF;
            break;

        case EAACADTS:
            mime_type = PVMF_MIME_MPEG4_AUDIO;
            break;
        default:
            mime_type = "";
            break;
    }

    tmpTrackInfo.setTrackMimeType(mime_type);

    OsclRefCounterMemFrag config;
    PVAACFFNodeTrackPortInfo trackPortInfo;
    if (!RetrieveTrackConfigInfo(trackPortInfo))
    {
        return PVMFFailure;
    }
    config = trackPortInfo.iFormatSpecificConfig;

    tmpTrackInfo.setTrackConfigInfo(config);

    // add the track
    aInfo.addTrackInfo(tmpTrackInfo);

    return PVMFSuccess;
}

PVMFStatus PVMFAACFFParserNode::SelectTracks(PVMFMediaPresentationInfo& aInfo)
{
    OSCL_UNUSED_ARG(aInfo);
    return PVMFSuccess;
}

PVMFStatus PVMFAACFFParserNode::DoGetMetadataKeys(PVMFAACFFParserNodeCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFAACFFParserNode::DoGetMetadataKeys() In"));

    /* Get Metadata keys from CPM for protected content only */
    if ((iCPMMetaDataExtensionInterface != NULL))
    {
        GetCPMMetaDataKeys();
        return PVMFPending;
    }
    return (CompleteGetMetadataKeys(aCmd));
}

PVMFStatus
PVMFAACFFParserNode::CompleteGetMetadataKeys(PVMFAACFFParserNodeCommand& aCmd)
{

    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::CompleteGetMetadataKeys Called"));
    // File must be parsed
    if (!iAACParser)
    {
        return PVMFErrInvalidState;
    }

    PVMFMetadataList* keylistptr = NULL;
    uint32 starting_index;
    int32 max_entries;
    char* query_key = NULL;

    aCmd.PVMFAACFFParserNodeCommand::Parse(keylistptr, starting_index, max_entries, query_key);

    // Check parameters
    if (keylistptr == NULL)
    {
        // The list pointer is invalid
        return PVMFErrArgument;
    }

    if ((starting_index > (iAvailableMetadataKeys.size() - 1)) || max_entries == 0)
    {
        // Invalid starting index and/or max entries
        return PVMFErrArgument;
    }

    // Copy the requested keys
    uint32 num_entries = 0;
    int32 num_added = 0;
    uint32 lcv = 0;
    for (lcv = 0; lcv < iAvailableMetadataKeys.size(); lcv++)
    {
        if (query_key == NULL)
        {
            // No query key so this key is counted
            ++num_entries;
            if (num_entries > starting_index)
            {
                // Past the starting index so copy the key
                PVMFStatus status = PushValueToList(iAvailableMetadataKeys, keylistptr, lcv);
                if (PVMFErrNoMemory == status)
                {
                    return status;
                }
                num_added++;
            }
        }
        else
        {
            // Check if the key matche the query key
            if (pv_mime_strcmp(iAvailableMetadataKeys[lcv].get_cstr(), query_key) >= 0)
            {
                // This key is counted
                ++num_entries;
                if (num_entries > starting_index)
                {
                    // Past the starting index so copy the key
                    PVMFStatus status = PushValueToList(iAvailableMetadataKeys, keylistptr, lcv);
                    if (PVMFErrNoMemory == status)
                    {
                        return status;
                    }
                    num_added++;
                }
            }
        }

        // Check if max number of entries have been copied
        if (max_entries > 0 && num_added >= max_entries)
        {
            break;
        }
    }
    for (lcv = 0; lcv < iCPMMetadataKeys.size(); lcv++)
    {
        if (query_key == NULL)
        {
            /* No query key so this key is counted */
            ++num_entries;
            if (num_entries > (uint32)starting_index)
            {
                /* Past the starting index so copy the key */
                PVMFStatus status = PushValueToList(iCPMMetadataKeys, keylistptr, lcv);
                if (PVMFErrNoMemory == status)
                {
                    return status;
                }
                num_added++;
            }
        }
        else
        {
            /* Check if the key matches the query key */
            if (pv_mime_strcmp(iCPMMetadataKeys[lcv].get_cstr(), query_key) >= 0)
            {
                /* This key is counted */
                ++num_entries;
                if (num_entries > (uint32)starting_index)
                {
                    /* Past the starting index so copy the key */
                    PVMFStatus status = PushValueToList(iCPMMetadataKeys, keylistptr, lcv);
                    if (PVMFErrNoMemory == status)
                    {
                        return status;
                    }
                    num_added++;
                }
            }
        }
        /* Check if max number of entries have been copied */
        if ((max_entries > 0) && (num_added >= max_entries))
        {
            break;
        }
    }

    return PVMFSuccess;
}

void PVMFAACFFParserNode::ReleaseMetadataValue(PvmiKvp& aValueKVP)
{
    switch (GetValTypeFromKeyString(aValueKVP.key))
    {
        case PVMI_KVPVALTYPE_CHARPTR:
            if (aValueKVP.value.pChar_value != NULL)
            {
                OSCL_ARRAY_DELETE(aValueKVP.value.pChar_value);
                aValueKVP.value.pChar_value = NULL;
            }
            break;

        case PVMI_KVPVALTYPE_WCHARPTR:
            if (aValueKVP.value.pWChar_value != NULL)
            {
                OSCL_ARRAY_DELETE(aValueKVP.value.pWChar_value);
                aValueKVP.value.pWChar_value = NULL;
            }
            break;

        default:
            // Add more case statements if other value types are returned
            break;
    }

    OSCL_ARRAY_DELETE(aValueKVP.key);
    aValueKVP.key = NULL;


}

PVMFStatus PVMFAACFFParserNode::DoGetMetadataValues(PVMFAACFFParserNodeCommand& aCmd)
{
    int32 leavecode = 0;
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::DoGetMetaDataValues Called"));

    // File must be parsed
    if (!iAACParser)
    {
        return PVMFErrInvalidState;
    }

    PVMFMetadataList* keylistptr = NULL;
    Oscl_Vector<PvmiKvp, OsclMemAllocator>* valuelistptr = NULL;
    uint32 starting_index;
    int32 max_entries;

    aCmd.PVMFAACFFParserNodeCommand::Parse(keylistptr, valuelistptr, starting_index, max_entries);

    // Check the parameters
    if (keylistptr == NULL || valuelistptr == NULL)
    {
        return PVMFErrArgument;
    }

    uint32 numkeys = keylistptr->size();

    if (starting_index > (numkeys - 1) || numkeys <= 0 || max_entries == 0)
    {
        // Don't do anything
        return PVMFErrArgument;
    }

    uint32 numvalentries = 0;
    int32 numentriesadded = 0;
    uint32 lcv = 0;
    PvmiKvpSharedPtrVector iFrame;

    //add ID3 Data
    for (lcv = 0; lcv < numkeys; lcv++)
    {
        iAACParser->GetID3Frame((*keylistptr)[lcv], iFrame);
        if (iFrame.size() > 0)
        {

            PvmiKvp KeyVal;
            KeyVal.key = NULL;
            KeyVal.length = 0;
            char *key = (*(iFrame.back())).key;
            int32 len = (*(iFrame.back())).length;

            ++numvalentries;

            leavecode = CreateNewArray(KeyVal.key, key);
            oscl_strncpy(KeyVal.key , key, oscl_strlen(key) + 1);
            KeyVal.length = len;
            KeyVal.capacity = (*(iFrame.back())).capacity;

            PvmiKvpValueType ValueType = GetValTypeFromKeyString(key);

            switch (ValueType)
            {

                case PVMI_KVPVALTYPE_WCHARPTR:
                    leavecode = CreateNewArray(KeyVal.value.pWChar_value, len);
                    oscl_strncpy(KeyVal.value.pWChar_value , (*(iFrame.back())).value.pWChar_value, len);
                    break;

                case PVMI_KVPVALTYPE_CHARPTR:
                    leavecode = CreateNewArray(KeyVal.value.pChar_value, len);

                    oscl_strncpy(KeyVal.value.pChar_value , (*(iFrame.back())).value.pChar_value, len);
                    break;

                case PVMI_KVPVALTYPE_UINT32:
                    KeyVal.value.uint32_value = (*(iFrame.back())).value.uint32_value;
                    break;

                default:
                    break;
            }

            leavecode = PushBackKeyVal(valuelistptr, KeyVal);
            OSCL_FIRST_CATCH_ANY(leavecode, ReleaseMetadataValue(KeyVal);
                                 break;);

            ++numentriesadded;

            iFrame.pop_back();
        }
    }

    //add rest of the data
    for (lcv = 0; lcv < numkeys; lcv++)
    {
        int32 leavecode = 0;
        PvmiKvp KeyVal;
        KeyVal.key = NULL;

        if (!oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVAACMETADATA_DURATION_KEY) &&
                iAACFileInfo.iDuration > 0)
        {
            // Duration
            // Increment the counter for the number of values found so far
            ++numvalentries;

            // Create a value entry if past the starting index
            if (numvalentries > starting_index)
            {
                uint32 duration = (uint32)iAACFileInfo.iDuration;
                PVMFStatus retval =
                    PVMFCreateKVPUtils::CreateKVPForUInt32Value(KeyVal,
                            PVAACMETADATA_DURATION_KEY,
                            duration,
                            (char *)PVAACMETADATA_TIMESCALE1000);

                if (retval != PVMFSuccess && retval != PVMFErrArgument)
                {
                    break;
                }

            }

        }
        else if (!oscl_strcmp((*keylistptr)[lcv].get_cstr(),  PVAACMETADATA_RANDOM_ACCESS_DENIED_KEY))
        {
            /*
             * Random Access
             * Increment the counter for the number of values found so far
             */
            ++numvalentries;

            /* Create a value entry if past the starting index */
            if (numvalentries > (uint32)starting_index)
            {
                bool random_access_denied = false;
                if (iAACFileInfo.iFormat == EAACADIF || iAACFileInfo.iFormat == EAACRaw)
                {
                    random_access_denied = true;
                }
                PVMFStatus retval =
                    PVMFCreateKVPUtils::CreateKVPForBoolValue(KeyVal,
                            PVAACMETADATA_RANDOM_ACCESS_DENIED_KEY,
                            random_access_denied,
                            NULL);
                if (retval != PVMFSuccess && retval != PVMFErrArgument)
                {
                    break;
                }
            }
        }
        else if (!oscl_strcmp((*keylistptr)[lcv].get_cstr(),  PVAACMETADATA_NUMTRACKS_KEY))
        {
            // Number of tracks
            // Increment the counter for the number of values found so far
            ++numvalentries;

            // Create a value entry if past the starting index
            if (numvalentries > starting_index)
            {
                uint32 numtracksuint32 = 1;
                PVMFStatus retval = PVMFCreateKVPUtils::CreateKVPForUInt32Value(KeyVal,
                                    PVAACMETADATA_NUMTRACKS_KEY,
                                    numtracksuint32,
                                    NULL);
                if (retval != PVMFSuccess && retval != PVMFErrArgument)
                {
                    break;
                }
            }
        }
        else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVAACMETADATA_TRACKINFO_BITRATE_KEY) == 0) &&
                 iAACFileInfo.iBitrate > 0)
        {
            // Bitrate
            // Increment the counter for the number of values found so far
            ++numvalentries;

            // Create a value entry if past the starting index
            if (numvalentries > starting_index)
            {
                uint32 bitRate = (uint32)iAACFileInfo.iBitrate;
                PVMFStatus retval = PVMFCreateKVPUtils::CreateKVPForUInt32Value(KeyVal,
                                    PVAACMETADATA_TRACKINFO_BITRATE_KEY,
                                    bitRate,
                                    NULL);
                if (retval != PVMFSuccess && retval != PVMFErrArgument)
                {
                    break;
                }

            }
        }
        else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVAACMETADATA_TRACKINFO_SAMPLERATE_KEY) == 0) &&
                 iAACFileInfo.iSampleFrequency > 0)
        {
            // Sampling rate
            // Increment the counter for the number of values found so far
            ++numvalentries;

            // Create a value entry if past the starting index
            if (numvalentries > starting_index)
            {
                uint32 sampleFreq = (uint32)iAACFileInfo.iSampleFrequency;
                PVMFStatus retval = PVMFCreateKVPUtils::CreateKVPForUInt32Value(KeyVal,
                                    PVAACMETADATA_TRACKINFO_BITRATE_KEY,
                                    sampleFreq,
                                    NULL);
                if (retval != PVMFSuccess && retval != PVMFErrArgument)
                {
                    break;
                }
            }
        }
        else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVAACMETADATA_TRACKINFO_AUDIO_FORMAT_KEY) == 0) &&
                 iAACFileInfo.iFormat != EAACUnrecognized)
        {
            // Format
            // Increment the counter for the number of values found so far
            ++numvalentries;

            // Create a value entry if past the starting index
            if (numvalentries > starting_index)
            {
                PVMFStatus retval = PVMFSuccess;
                switch (iAACFileInfo.iFormat)
                {
                    case EAACADTS:
                        retval = PVMFCreateKVPUtils::CreateKVPForCharStringValue(KeyVal,
                                 PVAACMETADATA_TRACKINFO_AUDIO_FORMAT_KEY,
                                 _STRLIT_CHAR(PVMF_MIME_ADTS));
                        break;

                    case EAACADIF:
                        retval = PVMFCreateKVPUtils::CreateKVPForCharStringValue(KeyVal,
                                 PVAACMETADATA_TRACKINFO_AUDIO_FORMAT_KEY,
                                 _STRLIT_CHAR(PVMF_MIME_ADIF));

                        break;

                    case EAACRaw:
                        retval = PVMFCreateKVPUtils::CreateKVPForCharStringValue(KeyVal,
                                 PVAACMETADATA_TRACKINFO_AUDIO_FORMAT_KEY,
                                 _STRLIT_CHAR(PVMF_MIME_MPEG4_AUDIO));

                        break;

                    default:
                        break;
                }
            }
            else
            {
                // Memory allocation failed so clean up
                if (KeyVal.key)
                {
                    OSCL_ARRAY_DELETE(KeyVal.key);
                    KeyVal.key = NULL;
                }
                if (KeyVal.value.pChar_value)
                {
                    OSCL_ARRAY_DELETE(KeyVal.value.pChar_value);
                }
                break;
            }
        }

        // Add the KVP to the list if the key string was created
        if (KeyVal.key != NULL)
        {
            leavecode = PushBackKeyVal(valuelistptr, KeyVal);
            OSCL_FIRST_CATCH_ANY(leavecode, ReleaseMetadataValue(KeyVal);
                                 break;);

            // Increment the counter for number of value entries added to the list
            ++numentriesadded;

            // Check if the max number of value entries were added
            if (max_entries > 0 && numentriesadded >= max_entries)
            {
                // Maximum number of values added so break out of the loop
                break;
            }
        }
    }

    iAACParserNodeMetadataValueCount = (*valuelistptr).size();

    if ((iCPMMetaDataExtensionInterface != NULL))

    {
        iCPMGetMetaDataValuesCmdId =
            iCPMMetaDataExtensionInterface->GetNodeMetadataValues(iCPMSessionID,
                    (*keylistptr),
                    (*valuelistptr),
                    0);
        return PVMFPending;
    }

    return PVMFSuccess;
}

PVMFStatus
PVMFAACFFParserNode::DoSetDataSourcePosition(PVMFAACFFParserNodeCommand& aCmd)
{
    //file must be parsed
    if (!iAACParser)
    {
        return PVMFErrInvalidState;
    }

    if (!iOutPort)
    {
        return PVMFErrInvalidState;
    }

    uint32 targetNPT = 0;
    uint32* actualNPT = NULL;
    uint32* actualMediaDataTS = NULL;
    bool jumpToIFrame = false;
    uint32 streamID = 0;

    ResetAllTracks();
    iFirstFrame = true;
    aCmd.PVMFAACFFParserNodeCommand::Parse(targetNPT, actualNPT, actualMediaDataTS, jumpToIFrame, streamID);

    // validate the parameters
    if (actualNPT == NULL || actualMediaDataTS == NULL)
    {
        return PVMFErrArgument;
    }

    //store to send the BOS
    iTrack.iSendBOS = true;
    //save the stream id for next media segment
    iStreamID = streamID;

    *actualNPT = 0;
    *actualMediaDataTS = 0;

    int32 result;

    // check if passed targetNPT is greater than or equal to clip duration.
    if ((targetNPT >= (uint32)iAACFileInfo.iDuration) && (iAACFileInfo.iFormat != EAACRaw))
    {
        if (iAACFileInfo.iFormat == EAACADIF)
        {
            uint32 tmpuint32 = 0;
            result = iAACParser->ResetPlayback(0, tmpuint32);
            if (result != AACBitstreamObject::EVERYTHING_OK)
            {
                return PVMFErrResource;
            }

            // Adjust the offset so the timestamp after reposition would begin past the current position for sure
            iTrack.iTimestampOffset += iAACFileInfo.iDuration;

            // Reset the clock to time 0
            iTrack.iClockConverter->set_clock(0, 0);

            // Set the return parameters
            *actualNPT = iAACFileInfo.iDuration;
            *actualMediaDataTS = iTrack.iTimestampOffset;
            iTrack.oEOSReached = true;
        }
        else
        {
            // Peek the next sample to get the duration of the last sample
            uint32 timestamp;
            result = iAACParser->PeekNextTimestamp(timestamp);
            if (result != AACBitstreamObject::EVERYTHING_OK)
            {
                return PVMFErrResource;
            }

            uint32 millisecTS = iTrack.iClockConverter->get_converted_ts(1000);
            *actualMediaDataTS = millisecTS;

            // Reset the track to begining of clip.
            uint32 tmpuint32 = 0;
            result = iAACParser->ResetPlayback(0, tmpuint32);
            if (result != AACBitstreamObject::EVERYTHING_OK)
            {
                return PVMFErrResource;
            }

            //Peek new position to get the actual new timestamp
            uint32 newtimestamp;
            result = iAACParser->PeekNextTimestamp(newtimestamp);
            if (result != AACBitstreamObject::EVERYTHING_OK)
            {
                return PVMFErrResource;
            }
            *actualNPT = iAACFileInfo.iDuration;

            //Adjust the offset to add to future timestamps.
            iTrack.iTimestampOffset += (timestamp - newtimestamp);

            MediaClockConverter mcc(1000);
            uint32 delta = PVMF_AAC_PARSER_NODE_TS_DELTA_DURING_REPOS_IN_MS;
            uint32 wrap_count = 0;
            mcc.set_clock(delta, wrap_count);
            uint32 deltaintimescale = mcc.get_converted_ts(iTrack.iClockConverter->get_timescale());
            iTrack.iTimestampOffset += deltaintimescale;

            iTrack.oEOSReached = true;
        }
        return PVMFSuccess;
    }

    if (iAACFileInfo.iFormat == EAACADIF)
    {
        // ADIF has no timestamp and repositioning is limited to beginning of file
        // Reposition to time 0
        uint32 tmpuint32 = 0;
        result = iAACParser->ResetPlayback(0, tmpuint32);
        if (result != AACBitstreamObject::EVERYTHING_OK)
        {
            return PVMFErrResource;
        }

        // Adjust the offset so the timestamp after reposition would begin past the current position for sure
        iTrack.iTimestampOffset += iAACFileInfo.iDuration;

        // Reset the clock to time 0
        iTrack.iClockConverter->set_clock(0, 0);

        // Set the return parameters
        *actualNPT = 0;
        *actualMediaDataTS = iTrack.iTimestampOffset;

        PVMF_AACPARSERNODE_LOGDATATRAFFIC((0, "PVMFAACParserNode::DoSetDataSourcePosition - ADIF -targetNPT=%d, actualNPT=%d, actualMediaDataTS=%d",
                                           targetNPT, *actualNPT, *actualMediaDataTS));

    }
    else if (iAACFileInfo.iFormat == EAACRaw)
    {
        // Raw AAC has no timestamp and repositioning is limited to beginning of file
        // Reposition to time 0
        uint32 tmpuint32 = 0;
        result = iAACParser->ResetPlayback(0, tmpuint32);
        if (result != AACBitstreamObject::EVERYTHING_OK)
        {
            return PVMFErrResource;
        }

        // Adjust the offset so the timestamp after reposition would begin past the current position for sure
        // Since duration of raw AAC bitstream file is unknown use a hardcoded value of 1 hour
        iTrack.iTimestampOffset += 3600000;

        // Reset the clock to time 0
        iTrack.iClockConverter->set_clock(0, 0);

        // Set the return parameters
        *actualNPT = 0;
        *actualMediaDataTS = iTrack.iTimestampOffset;

        PVMF_AACPARSERNODE_LOGDATATRAFFIC((0, "PVMFAACParserNode::DoSetDataSourcePosition - RAWAAC - targetNPT=%d, actualNPT=%d, actualMediaDataTS=%d",
                                           targetNPT, *actualNPT, *actualMediaDataTS));
    }
    else
    {
        // The media data timestamp of the next sample will start from the maximum
        // of timestamp on all selected tracks.  This media data timestamp will
        // correspond to the actual NPT.

        // Peek the next sample to get the duration of the last sample
        uint32 timestamp;
        result = iAACParser->PeekNextTimestamp(timestamp);
        if (result != AACBitstreamObject::EVERYTHING_OK)
        {
            return PVMFErrResource;
        }

        // Adjust the timestamp to the end of the last sample, i.e. adding the delta to next sample
        //	iTrack.iClockConverter->update_clock(timestamp);

        uint32 millisecTS = iTrack.iClockConverter->get_converted_ts(1000);
        *actualMediaDataTS = millisecTS;

        // Reset the clock to this new starting point.
        //	iTrack.iClockConverter->set_clock(timestamp,0);
        // Reposition
        // If new position is past the end of clip, AAC FF should set the position to the last frame
        uint32 tmpuint32 = 0;
        result = iAACParser->ResetPlayback(targetNPT, tmpuint32);
        if (result != AACBitstreamObject::EVERYTHING_OK)
        {
            if (AACBitstreamObject::END_OF_FILE == result)
            {
                uint32 timestamp;
                result = iAACParser->PeekNextTimestamp(timestamp);
                if (result != AACBitstreamObject::EVERYTHING_OK)
                {
                    return PVMFErrResource;
                }

                // Adjust the timestamp to the end of the last sample, i.e. adding the delta to next sample
                // iTrack.iClockConverter->update_clock(timestamp);

                uint32 millisecTS = iTrack.iClockConverter->get_converted_ts(1000);
                *actualMediaDataTS = millisecTS;

                // Reset the track to begining of clip.
                uint32 tmpuint32 = 0;
                result = iAACParser->ResetPlayback(0, tmpuint32);
                if (result != AACBitstreamObject::EVERYTHING_OK)
                {
                    return PVMFErrResource;
                }

                //Peek new position to get the actual new timestamp
                uint32 newtimestamp;
                result = iAACParser->PeekNextTimestamp(newtimestamp);
                if (result != AACBitstreamObject::EVERYTHING_OK)
                {
                    return PVMFErrResource;
                }
                *actualNPT = newtimestamp;

                //Adjust the offset to add to future timestamps.
                iTrack.iTimestampOffset += (timestamp - newtimestamp);

                MediaClockConverter mcc(1000);
                uint32 delta = PVMF_AAC_PARSER_NODE_TS_DELTA_DURING_REPOS_IN_MS;
                uint32 wrap_count = 0;
                mcc.set_clock(delta, wrap_count);
                uint32 deltaintimescale = mcc.get_converted_ts(iTrack.iClockConverter->get_timescale());
                iTrack.iTimestampOffset += deltaintimescale;

                iTrack.oEOSReached = true;
                return PVMFSuccess;
            }
            else
            {
                return PVMFErrResource;
            }
        }

        //Peek new position to get the actual new timestamp
        uint32 newtimestamp;
        result = iAACParser->PeekNextTimestamp(newtimestamp);
        if (result != AACBitstreamObject::EVERYTHING_OK)
        {
            return PVMFErrResource;
        }
        *actualNPT = newtimestamp;

        //Adjust the offset to add to future timestamps.
        iTrack.iTimestampOffset += (timestamp - newtimestamp);

        MediaClockConverter mcc(1000);
        uint32 delta = PVMF_AAC_PARSER_NODE_TS_DELTA_DURING_REPOS_IN_MS;
        uint32 wrap_count = 0;
        mcc.set_clock(delta, wrap_count);
        uint32 deltaintimescale = mcc.get_converted_ts(iTrack.iClockConverter->get_timescale());
        iTrack.iTimestampOffset += deltaintimescale;

        PVMF_AACPARSERNODE_LOGDATATRAFFIC((0, "PVMFAACParserNode::DoSetDataSourcePosition - ADTS - targetNPT=%d, actualNPT=%d, actualMediaDataTS=%d",
                                           targetNPT, *actualNPT, *actualMediaDataTS));
    }


    return PVMFSuccess;
}


PVMFStatus PVMFAACFFParserNode::DoQueryDataSourcePosition(PVMFAACFFParserNodeCommand& aCmd)
{
    //file must be parsed
    if (!iAACParser)
    {
        return PVMFErrInvalidState;
    }

    if (!iOutPort)
    {
        return PVMFErrInvalidState;
    }

    uint32 targetNPT = 0;
    uint32* actualNPT = NULL;
    bool jumpToIFrame = false;

    aCmd.PVMFAACFFParserNodeCommand::Parse(targetNPT, actualNPT, jumpToIFrame);

    if (actualNPT == NULL)
    {
        return PVMFErrArgument;
    }

    *actualNPT = 0;

    // Query
    // If new position is past the end of clip, AAC FF should set the position to the last frame
    *actualNPT = iAACParser->SeekPointFromTimestamp(targetNPT);

    return PVMFSuccess;
}


PVMFStatus PVMFAACFFParserNode::DoSetDataSourceRate(PVMFAACFFParserNodeCommand& aCmd)
{
    OSCL_UNUSED_ARG(aCmd);
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::DoSetDataSourceRate() In"));
    return PVMFSuccess;
}



/* CPM related */
void PVMFAACFFParserNode::InitCPM()
{
    iCPMInitCmdId = iCPM->Init();
}

void PVMFAACFFParserNode::OpenCPMSession()
{
    iCPMOpenSessionCmdId = iCPM->OpenSession(iCPMSessionID);
}

void PVMFAACFFParserNode::CPMRegisterContent()
{
    iCPMRegisterContentCmdId = iCPM->RegisterContent(iCPMSessionID,
                               iSourceURL,
                               iSourceFormat,
                               (OsclAny*) & iCPMSourceData);
}

void PVMFAACFFParserNode::GetCPMLicenseInterface()
{
    iCPMLicenseInterfacePVI = NULL;
    iCPMGetLicenseInterfaceCmdId =
        iCPM->QueryInterface(iCPMSessionID,
                             PVMFCPMPluginLicenseInterfaceUuid,
                             iCPMLicenseInterfacePVI);
}

bool PVMFAACFFParserNode::GetCPMContentAccessFactory()
{
    PVMFStatus status = iCPM->GetContentAccessFactory(iCPMSessionID,
                        iCPMContentAccessFactory);
    if (status != PVMFSuccess)
    {
        return false;
    }
    return true;
}

bool PVMFAACFFParserNode::GetCPMMetaDataExtensionInterface()
{
    PVInterface* temp = NULL;
    bool retVal =
        iCPM->queryInterface(KPVMFMetadataExtensionUuid, temp);
    iCPMMetaDataExtensionInterface = OSCL_STATIC_CAST(PVMFMetadataExtensionInterface*, temp);

    return retVal;
}

void PVMFAACFFParserNode::RequestUsage()
{
    PopulateDRMInfo();

    if (iDataStreamReadCapacityObserver != NULL)
    {
        iCPMContentAccessFactory->SetStreamReadCapacityObserver(iDataStreamReadCapacityObserver);
    }

    iCPMRequestUsageId = iCPM->ApproveUsage(iCPMSessionID,
                                            iRequestedUsage,
                                            iApprovedUsage,
                                            iAuthorizationDataKvp,
                                            iUsageID,
                                            iCPMContentAccessFactory);

    /** Logic for playing after acquired license */
    oSourceIsCurrent = true;
}

void PVMFAACFFParserNode::PopulateDRMInfo()
{
    /* Cleanup any old key */
    if (iRequestedUsage.key)
    {
        OSCL_ARRAY_DELETE(iRequestedUsage.key);
        iRequestedUsage.key = NULL;
    }

    if (iApprovedUsage.key)
    {
        OSCL_ARRAY_DELETE(iApprovedUsage.key);
        iApprovedUsage.key = NULL;
    }

    if (iAuthorizationDataKvp.key)
    {
        OSCL_ARRAY_DELETE(iAuthorizationDataKvp.key);
        iAuthorizationDataKvp.key = NULL;
    }

    if ((iCPMContentType == PVMF_CPM_FORMAT_OMA1) ||
            (iCPMContentType == PVMF_CPM_FORMAT_AUTHORIZE_BEFORE_ACCESS))
    {
        int32 UseKeyLen = oscl_strlen(_STRLIT_CHAR(PVMF_CPM_REQUEST_USE_KEY_STRING));
        int32 AuthKeyLen = oscl_strlen(_STRLIT_CHAR(PVMF_CPM_AUTHORIZATION_DATA_KEY_STRING));
        int32 leavecode = 0;

        OSCL_TRY(leavecode,
                 iRequestedUsage.key = OSCL_ARRAY_NEW(char, UseKeyLen + 1);
                 iApprovedUsage.key = OSCL_ARRAY_NEW(char, UseKeyLen + 1);
                 iAuthorizationDataKvp.key = OSCL_ARRAY_NEW(char, AuthKeyLen + 1);
                );
        if (leavecode || !iRequestedUsage.key || !iApprovedUsage.key || !iAuthorizationDataKvp.key)
        {
            if (iRequestedUsage.key)
            {
                OSCL_ARRAY_DELETE(iRequestedUsage.key);
                iRequestedUsage.key = NULL;
            }
            if (iApprovedUsage.key)
            {
                OSCL_ARRAY_DELETE(iApprovedUsage.key);
                iApprovedUsage.key = NULL;
            }
            if (iAuthorizationDataKvp.key)
            {
                OSCL_ARRAY_DELETE(iAuthorizationDataKvp.key);
                iAuthorizationDataKvp.key = NULL;
            }

            return;
        }

        oscl_strncpy(iRequestedUsage.key,
                     _STRLIT_CHAR(PVMF_CPM_REQUEST_USE_KEY_STRING),
                     UseKeyLen);
        iRequestedUsage.key[UseKeyLen] = 0;
        iRequestedUsage.length = 0;
        iRequestedUsage.capacity = 0;
        if (iPreviewMode)
        {
            iRequestedUsage.value.uint32_value =
                (BITMASK_PVMF_CPM_DRM_INTENT_PREVIEW |
                 BITMASK_PVMF_CPM_DRM_INTENT_PAUSE |
                 BITMASK_PVMF_CPM_DRM_INTENT_SEEK_FORWARD |
                 BITMASK_PVMF_CPM_DRM_INTENT_SEEK_BACK);
        }
        else
        {
            iRequestedUsage.value.uint32_value =
                (BITMASK_PVMF_CPM_DRM_INTENT_PLAY |
                 BITMASK_PVMF_CPM_DRM_INTENT_PAUSE |
                 BITMASK_PVMF_CPM_DRM_INTENT_SEEK_FORWARD |
                 BITMASK_PVMF_CPM_DRM_INTENT_SEEK_BACK);
        }
        oscl_strncpy(iApprovedUsage.key,
                     _STRLIT_CHAR(PVMF_CPM_REQUEST_USE_KEY_STRING),
                     UseKeyLen);
        iApprovedUsage.key[UseKeyLen] = 0;
        iApprovedUsage.length = 0;
        iApprovedUsage.capacity = 0;
        iApprovedUsage.value.uint32_value = 0;

        oscl_strncpy(iAuthorizationDataKvp.key,
                     _STRLIT_CHAR(PVMF_CPM_AUTHORIZATION_DATA_KEY_STRING),
                     AuthKeyLen);
        iAuthorizationDataKvp.key[AuthKeyLen] = 0;
        iAuthorizationDataKvp.length = 0;
        iAuthorizationDataKvp.capacity = 0;
        iAuthorizationDataKvp.value.pUint8_value = NULL;
    }
    else
    {
        //Error
        OSCL_ASSERT(false);
    }
}

void PVMFAACFFParserNode::SendUsageComplete()
{
    iCPMUsageCompleteCmdId = iCPM->UsageComplete(iCPMSessionID, iUsageID);
}

void PVMFAACFFParserNode::CloseCPMSession()
{
    iCPMCloseSessionCmdId = iCPM->CloseSession(iCPMSessionID);
}

void PVMFAACFFParserNode::ResetCPM()
{
    iCPMResetCmdId = iCPM->Reset();
}

void PVMFAACFFParserNode::GetCPMMetaDataKeys()
{
    if (iCPMMetaDataExtensionInterface != NULL)
    {
        iCPMMetadataKeys.clear();
        iCPMGetMetaDataKeysCmdId =
            iCPMMetaDataExtensionInterface->GetNodeMetadataKeys(iCPMSessionID,
                    iCPMMetadataKeys,
                    0,
                    PVMF_AAC_PARSER_NODE_MAX_CPM_METADATA_KEYS);
    }
}

PVMFStatus
PVMFAACFFParserNode::CheckCPMCommandCompleteStatus(PVMFCommandId aID,
        PVMFStatus aStatus)
{
    PVMFStatus status = aStatus;
    if (aID == iCPMGetLicenseInterfaceCmdId)
    {
        if (aStatus == PVMFErrNotSupported)
        {
            /* License Interface is Optional */
            status = PVMFSuccess;
        }
    }
    else if (aID == iCPMRegisterContentCmdId)
    {
        if (aStatus == PVMFErrNotSupported)
        {
            /* CPM doesnt care about this content */
            status = PVMFErrNotSupported;
        }
    }
    else if (aID == iCPMRequestUsageId)
    {
        if (iCPMSourceData.iIntent & BITMASK_PVMF_SOURCE_INTENT_GETMETADATA)
        {
            if (aStatus != PVMFSuccess)
            {
                /*
                 * If we are doing metadata only then we don't care
                 * if license is not available
                 */
                status = PVMFSuccess;
            }
        }
    }
    return status;
}

void PVMFAACFFParserNode::CPMCommandCompleted(const PVMFCmdResp& aResponse)
{
    PVMFCommandId id = aResponse.GetCmdId();
    PVMFStatus status =
        CheckCPMCommandCompleteStatus(id, aResponse.GetCmdStatus());

    if (id == iCPMCancelGetLicenseCmdId)
    {
        /*
         * if this command is CancelGetLicense, we will return success or fail here.
         */
        OSCL_ASSERT(!iCancelCommand.empty());
        CommandComplete(iCancelCommand,
                        iCancelCommand.front(),
                        status);
        return;
    }
    //if CPM comes back as PVMFErrNotSupported then by pass rest of the CPM
    //sequence. Fake success here so that node doesnt treat this as an error
    else if (id == iCPMRegisterContentCmdId && status == PVMFErrNotSupported)
    {
        /* CPM does not care about this content, so treat it as unprotected */
        PVMFStatus status = CheckForAACHeaderAvailability();
        if (status == PVMFSuccess)
        {
            status = ParseAACFile();
            SetState(EPVMFNodeInitialized);
        }
        /* End of Node Init sequence. */
        OSCL_ASSERT(!iCurrentCommand.empty());
        OSCL_ASSERT(iCurrentCommand.front().iCmd == PVMF_AAC_PARSER_NODE_INIT);
        CommandComplete(iCurrentCommand,
                        iCurrentCommand.front(),
                        status);
        return;
    }

    if (status != PVMFSuccess)
    {
        /*
         * If any command fails, the sequence fails.
         */
        CommandComplete(iCurrentCommand,
                        iCurrentCommand.front(),
                        aResponse.GetCmdStatus(),
                        NULL,
                        NULL,
                        NULL,
                        aResponse.GetEventExtensionInterface());
    }
    else
    {
        /*
         * process the response, and issue the next command in
         * the sequence.
         */
        if (id == iCPMInitCmdId)
        {
            OpenCPMSession();
        }
        else if (id == iCPMOpenSessionCmdId)
        {
            CPMRegisterContent();
        }
        else if (id == iCPMRegisterContentCmdId)
        {
            GetCPMLicenseInterface();
        }
        else if (id == iCPMGetLicenseInterfaceCmdId)
        {
            iCPMLicenseInterface = OSCL_STATIC_CAST(PVMFCPMPluginLicenseInterface*, iCPMLicenseInterfacePVI);
            iCPMLicenseInterfacePVI = NULL;
            GetCPMMetaDataExtensionInterface();
            iCPMContentType = iCPM->GetCPMContentType(iCPMSessionID);
            if ((iCPMContentType == PVMF_CPM_FORMAT_OMA1) ||
                    (iCPMContentType == PVMF_CPM_FORMAT_AUTHORIZE_BEFORE_ACCESS))
            {
                RequestUsage();
            }
            else
            {
                /* CPM does not care about this content, so treat it as unprotected */
                PVMFStatus status = CheckForAACHeaderAvailability();
                if (status == PVMFSuccess)
                {
                    status = ParseAACFile();
                    SetState(EPVMFNodeInitialized);
                }
                /* End of Node Init sequence. */
                OSCL_ASSERT(!iCurrentCommand.empty());
                OSCL_ASSERT(iCurrentCommand.front().iCmd == PVMF_AAC_PARSER_NODE_INIT);
                CommandComplete(iCurrentCommand,
                                iCurrentCommand.front(),
                                status);
            }
        }
        else if (id == iCPMRequestUsageId)
        {
            /** Logic for playing after acquired license */
            oSourceIsCurrent = false;
            if ((iCPMContentType == PVMF_CPM_FORMAT_OMA1) ||
                    (iCPMContentType == PVMF_CPM_FORMAT_AUTHORIZE_BEFORE_ACCESS))
            {
                GetCPMContentAccessFactory();
                if (CheckForAACHeaderAvailability() == PVMFSuccess)
                {
                    if (ParseAACFile())
                    {
                        /* End of Node Init sequence. */
                        OSCL_ASSERT(!iCurrentCommand.empty());
                        OSCL_ASSERT(iCurrentCommand.front().iCmd == PVMF_AAC_PARSER_NODE_INIT);
                        CompleteInit();
                    }
                }
            }
            else
            {
                /* Unknown format - should never get here */
                OSCL_ASSERT(false);
            }
        }
        else if (id == iCPMGetMetaDataKeysCmdId)
        {
            /* End of GetNodeMetaDataKeys */
            PVMFStatus status =
                CompleteGetMetadataKeys(iCurrentCommand.front());
            CommandComplete(iCurrentCommand,
                            iCurrentCommand.front(),
                            status,
                            NULL,
                            NULL,
                            NULL,
                            NULL);
        }
        else if (id == iCPMUsageCompleteCmdId)
        {
            CloseCPMSession();
        }
        else if (id == iCPMCloseSessionCmdId)
        {
            ResetCPM();
        }
        else if (id == iCPMResetCmdId)
        {
            /* End of Node Reset sequence */
            OSCL_ASSERT(!iCurrentCommand.empty());
            OSCL_ASSERT(iCurrentCommand.front().iCmd == PVMF_AAC_PARSER_NODE_RESET);
            CompleteReset();
        }
        else if (id == iCPMGetMetaDataValuesCmdId)
        {
            /* End of GetNodeMetaDataValues */
            OSCL_ASSERT(!iCurrentCommand.empty());
            OSCL_ASSERT(iCurrentCommand.front().iCmd == PVMF_AAC_PARSER_NODE_GETNODEMETADATAVALUES);
            CompleteGetMetaDataValues();
        }
        else if (id == iCPMGetLicenseCmdId)
        {
            CompleteGetLicense();
        }
        else
        {
            /* Unknown cmd ?? - error */
            CommandComplete(iCurrentCommand,
                            iCurrentCommand.front(),
                            PVMFFailure);
        }
    }

    /*
     * if there was any pending cancel, it was waiting on
     * this command to complete-- so the cancel is now done.
     */
    if (!iCancelCommand.empty())
    {
        if (iCancelCommand.front().iCmd != PVMF_AAC_PARSER_NODE_CANCEL_GET_LICENSE)
        {
            CommandComplete(iCancelCommand,
                            iCancelCommand.front(),
                            PVMFSuccess);
        }
    }
}

void PVMFAACFFParserNode::PassDatastreamFactory(PVMFDataStreamFactory& aFactory,
        int32 aFactoryTag,
        const PvmfMimeString* aFactoryConfig)
{
    OSCL_UNUSED_ARG(aFactoryTag);
    OSCL_UNUSED_ARG(aFactoryConfig);

    iDataStreamFactory = &aFactory;
    PVUuid uuid = PVMIDataStreamSyncInterfaceUuid;
    PVInterface* iFace =
        iDataStreamFactory->CreatePVMFCPMPluginAccessInterface(uuid);
    if (iFace != NULL)
    {
        iDataStreamInterface = OSCL_STATIC_CAST(PVMIDataStreamSyncInterface*, iFace);
        iDataStreamInterface->OpenSession(iDataStreamSessionID, PVDS_READ_ONLY);
    }
}

void
PVMFAACFFParserNode::PassDatastreamReadCapacityObserver(PVMFDataStreamReadCapacityObserver* aObserver)
{
    iDataStreamReadCapacityObserver = aObserver;
}


void PVMFAACFFParserNode::CompleteInit()
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::CompleteInit() Called"));

    if (iCPM)
    {
        if (iApprovedUsage.value.uint32_value !=
                iRequestedUsage.value.uint32_value)
        {
            CommandComplete(iCurrentCommand,
                            iCurrentCommand.front(),
                            PVMFErrAccessDenied,
                            NULL, NULL, NULL);
            return;
        }
    }

    SetState(EPVMFNodeInitialized);
    CommandComplete(iCurrentCommand,
                    iCurrentCommand.front(),
                    PVMFSuccess);
    return;
}


void PVMFAACFFParserNode::CompleteGetMetaDataValues()
{
    CommandComplete(iCurrentCommand,
                    iCurrentCommand.front(),
                    PVMFSuccess);
}

bool PVMFAACFFParserNode::GetTrackInfo(PVMFPortInterface* aPort,
                                       PVAACFFNodeTrackPortInfo*& aTrackInfoPtr)
{
    if (iTrack.iPort == aPort)
    {
        aTrackInfoPtr = &iTrack;
        return true;
    }
    return false;
}

bool PVMFAACFFParserNode::GetTrackInfo(int32 aTrackID,
                                       PVAACFFNodeTrackPortInfo*& aTrackInfoPtr)
{
    if (iTrack.iTrackId == aTrackID)
    {
        aTrackInfoPtr = &iTrack;
        return true;
    }
    return false;
}

bool PVMFAACFFParserNode::CheckForPortRescheduling()
{


    PVAACFFNodeTrackPortInfo* trackInfoPtr = NULL;
    if (!GetTrackInfo(iOutPort, trackInfoPtr))
    {
        PVMF_AACPARSERNODE_LOGERROR((0, "PVMFAACParserNode::CheckForPortRescheduling: Error - GetPortContainer failed"));
        return false;
    }

    if ((trackInfoPtr->oProcessOutgoingMessages) ||
            (trackInfoPtr->oQueueOutgoingMessages))
    {
        /*
         * Found a port that has outstanding activity and
         * is not busy.
         */
        return true;
    }

    /*
     * No port processing needed - either all port activity queues are empty
     * or the ports are backed up due to flow control.
     */
    return false;
}


void PVMFAACFFParserNode::CommandComplete(PVMFAACFFParserNodeCmdQ& aCmdQ,
        PVMFAACFFParserNodeCommand& aCmd,
        PVMFStatus aStatus,
        OsclAny* aEventData,
        PVUuid* aEventUUID,
        int32* aEventCode,
        PVInterface* aExtMsg)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::CommandComplete() In Id %d Cmd %d Status %d Context %d Data %d",
                                      aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData));

    PVInterface* extif = NULL;
    PVMFBasicErrorInfoMessage* errormsg = NULL;
    if (aExtMsg)
    {
        extif = aExtMsg;
    }
    else if (aEventUUID && aEventCode)
    {
        PVMF_AAC_PARSER_NODE_NEW(NULL,
                                 PVMFBasicErrorInfoMessage,
                                 (*aEventCode, *aEventUUID, NULL),
                                 errormsg);
        extif = OSCL_STATIC_CAST(PVInterface*, errormsg);
    }

    PVMFCmdResp resp(aCmd.iId, aCmd.iContext, aStatus, extif, aEventData);
    PVMFSessionId session = aCmd.iSession;

    /* Erase the command from the queue. */
    aCmdQ.Erase(&aCmd);

    /* Report completion to the session observer.*/
    ReportCmdCompleteEvent(session, resp);

    if (errormsg)
    {
        errormsg->removeRef();
    }
}

bool PVMFAACFFParserNode::ProcessPortActivity(PVAACFFNodeTrackPortInfo* aTrackInfoPtr)
{
    /*
     * called by the AO to process a port activity message
     */
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::ProcessPortActivity() Called"));

    PVMFStatus status;
    if (aTrackInfoPtr->oQueueOutgoingMessages)
    {
        status = QueueMediaSample(aTrackInfoPtr);

        if ((status != PVMFErrBusy) &&
                (status != PVMFSuccess) &&
                (status != PVMFErrInvalidState))
        {
            PVMF_AACPARSERNODE_LOGERROR((0, "PVMFAACParserNode::ProcessPortActivity() QueueMediaSample Failed - Err=%d", status));
            return false;
        }


        if (iAutoPaused == true)
        {
            aTrackInfoPtr->oQueueOutgoingMessages = false;
            PVMF_AACPARSERNODE_LOGDATATRAFFIC((0, "PVMFAACParserNode::QueueMediaSample() - Auto Paused"));
            return PVMFErrBusy;
        }
        if (aTrackInfoPtr->iPort->IsOutgoingQueueBusy())
        {
            aTrackInfoPtr->oQueueOutgoingMessages = false;
            PVMF_AACPARSERNODE_LOGDATATRAFFIC((0, "PVMFAACParserNode::QueueMediaSample() Port Outgoing Queue Busy"));
            return PVMFErrBusy;
        }

    }
    if (aTrackInfoPtr->oProcessOutgoingMessages)
    {
        if (aTrackInfoPtr->iPort->OutgoingMsgQueueSize() > 0)
        {
            status = ProcessOutgoingMsg(aTrackInfoPtr);
            /*
             * Report any unexpected failure in port processing...
             * (the InvalidState error happens when port input is suspended,
             * so don't report it.)
             */
            if ((status != PVMFErrBusy) &&
                    (status != PVMFSuccess) &&
                    (status != PVMFErrInvalidState))
            {
                PVMF_AACPARSERNODE_LOGERROR((0, "PVMFAACParserNode::ProcessPortActivity() ProcessOutgoingMsg Failed - Err=%d", status));
                ReportErrorEvent(PVMFErrPortProcessing);
            }
        }
        else
        {
            /* Nothing to send - wait for more data */
            aTrackInfoPtr->oProcessOutgoingMessages = false;
        }
    }
    return true;
}


PVMFStatus PVMFAACFFParserNode::QueueMediaSample(PVAACFFNodeTrackPortInfo* aTrackInfoPtr)
{
    if (iAutoPaused == true)
    {
        aTrackInfoPtr->oQueueOutgoingMessages = false;
        PVMF_AACPARSERNODE_LOGDATATRAFFIC((0, "PVMFAACParserNode::QueueMediaSample() - Auto Paused"));
        return PVMFErrBusy;
    }
    if (aTrackInfoPtr->iPort->IsOutgoingQueueBusy())
    {
        aTrackInfoPtr->oQueueOutgoingMessages = false;
        PVMF_AACPARSERNODE_LOGDATATRAFFIC((0, "PVMFAACParserNode::QueueMediaSample() Port Outgoing Queue Busy"));
        return PVMFErrBusy;
    }
    if (aTrackInfoPtr->oQueueOutgoingMessages)
    {
        PVMFStatus status;
        if (aTrackInfoPtr->iSendBOS == true)
        {
            status = SendBeginOfMediaStreamCommand(aTrackInfoPtr);
            return status;
        }
        if ((aTrackInfoPtr->oEOSReached == false) && (aTrackInfoPtr->oEOSSent == false))
        {
            PVMFSharedMediaDataPtr mediaDataOut;
            status = RetrieveMediaSample(&iTrack, mediaDataOut);
            if (status == PVMFErrBusy)
            {
                aTrackInfoPtr->oQueueOutgoingMessages = false;
                if (iAutoPaused == true)
                {
                    PauseAllMediaRetrieval();
                }
                return status;
            }
            else if (status == PVMFSuccess)
            {
                if (aTrackInfoPtr->oEOSReached == false)
                {
                    PVMFSharedMediaMsgPtr msgOut;
                    convertToPVMFMediaMsg(msgOut, mediaDataOut);

                    /* For logging purposes */
                    uint32 markerInfo = mediaDataOut->getMarkerInfo();
                    uint32 noRender = 0;
                    uint32 keyFrameBit = 0;
                    if (markerInfo & PVMF_MEDIA_DATA_MARKER_INFO_NO_RENDER_BIT)
                    {
                        noRender = 1;
                    }
                    if (markerInfo & PVMF_MEDIA_DATA_MARKER_INFO_RANDOM_ACCESS_POINT_BIT)
                    {
                        keyFrameBit = 1;
                    }
                    uint32 nptTS32 = 0;
                    nptTS32 = Oscl_Int64_Utils::get_uint64_lower32(aTrackInfoPtr->iPrevSampleTimeStamp);
                    PVMF_AACPARSERNODE_LOGDATATRAFFIC((0, "PVMFAACParserNode::QueueMediaSample() TrackID=%d, SeqNum=%d, SampleLen=%d, NptTS=%d, SampleTS=%d, NR=%d, KEY=%d, MimeType=%s",
                                                       aTrackInfoPtr->iTrackId,
                                                       msgOut->getSeqNum(),
                                                       mediaDataOut->getFilledSize(),
                                                       nptTS32,
                                                       msgOut->getTimestamp(),
                                                       noRender,
                                                       keyFrameBit,
                                                       aTrackInfoPtr->iTrackMimeType.get_cstr()));

                    status = aTrackInfoPtr->iPort->QueueOutgoingMsg(msgOut);
                    if (status != PVMFSuccess)
                    {
                        PVMF_AACPARSERNODE_LOGERROR((0, "PVMFAACParserNode::QueueMediaSample: Error - QueueOutgoingMsg failed"));
                        ReportErrorEvent(PVMFErrPortProcessing);
                    }
                    /* This flag will get reset to false if the connected port is busy */
                    aTrackInfoPtr->oProcessOutgoingMessages = true;
                    return status;
                }
            }
            else if (status == PVMFInfoEndOfData)
            {
                status = GenerateAndSendEOSCommand(aTrackInfoPtr);
                return status;
            }
            else
            {
                PVMF_AACPARSERNODE_LOGERROR((0, "PVMFAACParserNode::QueueMediaSample() - Sample Retrieval Failed"));
                ReportErrorEvent(PVMFErrCorrupt);
                return PVMFFailure;
            }
        }
        else if (aTrackInfoPtr->oEOSReached == true)
        {
            status = GenerateAndSendEOSCommand(aTrackInfoPtr);
            return status;
        }
    }
    return PVMFSuccess;
}

PVMFStatus PVMFAACFFParserNode:: GenerateAndSendEOSCommand(PVAACFFNodeTrackPortInfo* aTrackInfoPtr)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACParserNode::GenerateAndSendEOSCommand Called"));
    if (aTrackInfoPtr->iPort->IsOutgoingQueueBusy() == true)
    {
        /* come back later */
        PVMF_AACPARSERNODE_LOGDATATRAFFIC((0, "PVMFAACParserNode::GenerateAndSendEOSCommand: Waiting - Output Queue Busy"));
        return PVMFErrBusy;
    }

    if ((aTrackInfoPtr->oEOSSent == false) && (aTrackInfoPtr->oEOSReached == true))
    {
        PVMFSharedMediaCmdPtr sharedMediaCmdPtr = PVMFMediaCmd::createMediaCmd();

        sharedMediaCmdPtr->setFormatID(PVMF_MEDIA_CMD_EOS_FORMAT_ID);

        sharedMediaCmdPtr->setStreamID(iStreamID);

        sharedMediaCmdPtr->setSeqNum(aTrackInfoPtr->iSeqNum++);

        aTrackInfoPtr->iContinuousTimeStamp += PVMF_AAC_PARSER_NODE_TS_DELTA_DURING_REPOS_IN_MS;
        uint32 ts32 = Oscl_Int64_Utils::get_uint64_lower32(aTrackInfoPtr->iContinuousTimeStamp);
        sharedMediaCmdPtr->setTimestamp(ts32);

        PVMFSharedMediaMsgPtr msg;
        convertToPVMFMediaCmdMsg(msg, sharedMediaCmdPtr);

        PVMFStatus status = aTrackInfoPtr->iPort->QueueOutgoingMsg(msg);
        if (status != PVMFSuccess)
        {
            ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aTrackInfoPtr->iPort));
            PVMF_AACPARSERNODE_LOGERROR((0, "PVMFAACParserNode::GenerateAndSendEOSCommand: Error Sending EOS"));
            return status;
        }
        aTrackInfoPtr->oEOSSent = true;
        aTrackInfoPtr->oQueueOutgoingMessages = false;
        aTrackInfoPtr->oProcessOutgoingMessages = true;
        return (status);
    }
    aTrackInfoPtr->oQueueOutgoingMessages = false;
    return PVMFFailure;

}


void PVMFAACFFParserNode::DataStreamCommandCompleted(const PVMFCmdResp& aResponse)
{
    if (aResponse.GetCmdId() == iRequestReadCapacityNotificationID)
    {
        PVMFStatus cmdStatus = aResponse.GetCmdStatus();
        if (cmdStatus == PVMFSuccess)
        {
            if (CheckForAACHeaderAvailability() == PVMFSuccess)
            {
                if (iCPMContentType == PVMF_CPM_FORMAT_AUTHORIZE_BEFORE_ACCESS)
                {
                    if (ParseAACFile())
                    {
                        {
                            /* End of Node Init sequence. */
                            OSCL_ASSERT(!iCurrentCommand.empty());
                            OSCL_ASSERT(iCurrentCommand.front().iCmd == PVMF_AAC_PARSER_NODE_INIT);
                            CompleteInit();
                        }
                    }
                }
                else
                {
                    if (ParseAACFile())
                    {
                        /* End of Node Init sequence. */
                        OSCL_ASSERT(!iCurrentCommand.empty());
                        OSCL_ASSERT(iCurrentCommand.front().iCmd == PVMF_AAC_PARSER_NODE_INIT);
                        CompleteInit();
                    }
                }
            }
        }
        else
        {
            PVMF_AACPARSERNODE_LOGERROR((0, "PVMFAACParserNode::DataStreamCommandCompleted() Failed %d", cmdStatus));
            CommandComplete(iCurrentCommand,
                            iCurrentCommand.front(),
                            PVMFErrResource);

        }
    }
    else
    {
        OSCL_ASSERT(false);
    }
}

void PVMFAACFFParserNode::playResumeNotification(bool aDownloadComplete)
{
    OSCL_UNUSED_ARG(aDownloadComplete);

    iAutoPaused = false;
    PVAACFFNodeTrackPortInfo* trackInfoPtr = NULL;
    if (!GetTrackInfo(iOutPort, trackInfoPtr))
    {
        PVMF_AACPARSERNODE_LOGERROR((0, "PVMFAACParserNode::playResumeNotification: Error - GetPortContainer failed"));
        return;
    }
    if (trackInfoPtr->oQueueOutgoingMessages == false)
    {
        trackInfoPtr->oQueueOutgoingMessages = true;
    }

    PVMF_AACPARSERNODE_LOGERROR((0, "PVMFAACParserNode::playResumeNotification() - Auto Resume Triggered - FileSize = %d, NPT = %d", iFileSizeLastConvertedToTime, iLastNPTCalcInConvertSizeToTime));
    PVMF_AACPARSERNODE_LOGDATATRAFFIC((0, "PVMFAACParserNode::playResumeNotification() - Auto Resume Triggered - FileSize = %d, NPT = %d", iFileSizeLastConvertedToTime, iLastNPTCalcInConvertSizeToTime));
    RunIfNotReady();

}

void PVMFAACFFParserNode::setFileSize(const uint32 aFileSize)
{
    iDownloadFileSize = aFileSize;
}

void PVMFAACFFParserNode::setDownloadProgressInterface(PVMFDownloadProgressInterface* aInterface)
{
    if (aInterface == NULL)
    {
        OSCL_ASSERT(false);
    }
    iDownloadProgressInterface = aInterface;
}

int32 PVMFAACFFParserNode::convertSizeToTime(uint32 aFileSize, uint32& aNPTInMS)
{
    OSCL_UNUSED_ARG(aFileSize);
    OSCL_UNUSED_ARG(aNPTInMS);
    return -1;
}

void PVMFAACFFParserNode::DataStreamInformationalEvent(const PVMFAsyncEvent& aEvent)
{
    OSCL_UNUSED_ARG(aEvent);
    OSCL_LEAVE(OsclErrNotSupported);
}

void PVMFAACFFParserNode::DataStreamErrorEvent(const PVMFAsyncEvent& aEvent)
{
    OSCL_UNUSED_ARG(aEvent);
    OSCL_LEAVE(OsclErrNotSupported);
}

void PVMFAACFFParserNode::PauseAllMediaRetrieval()
{
    PVAACFFNodeTrackPortInfo* trackInfoPtr = NULL;
    if (!GetTrackInfo(iOutPort, trackInfoPtr))
    {
        PVMF_AACPARSERNODE_LOGERROR((0, "PVMFAACParserNode::PauseAllMediaRetrieval: Error - GetPortContainer failed"));
        return;
    }
    trackInfoPtr->oQueueOutgoingMessages = false;

    return;
}

bool PVMFAACFFParserNode::SendBeginOfMediaStreamCommand(PVAACFFNodeTrackPortInfo* aTrackInfoPtr)
{
    PVMFSharedMediaCmdPtr sharedMediaCmdPtr = PVMFMediaCmd::createMediaCmd();
    sharedMediaCmdPtr->setFormatID(PVMF_MEDIA_CMD_BOS_FORMAT_ID);

    sharedMediaCmdPtr->setTimestamp(aTrackInfoPtr->iTimestampOffset);
    uint32 seqNum = 0;
    sharedMediaCmdPtr->setSeqNum(seqNum);

    PVMFSharedMediaMsgPtr mediaMsgOut;
    convertToPVMFMediaCmdMsg(mediaMsgOut, sharedMediaCmdPtr);
    mediaMsgOut->setStreamID(iStreamID);

    PVMFStatus status = aTrackInfoPtr->iPort->QueueOutgoingMsg(mediaMsgOut);
    if (status != PVMFSuccess)
    {
        // Output queue is busy, so wait for the output queue being ready
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                        (0, "PVMFAACFFParserNode::SendBeginOfMediaStreamCommand: Outgoing queue busy. "));
        return PVMFFailure;
    }
    aTrackInfoPtr->iSendBOS = false;

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFAACFFParserNode::SendBeginOfMediaStreamCommand() Out StreamId %d ", iStreamID));
    return PVMFSuccess;
}


PVMFCommandId
PVMFAACFFParserNode::GetLicense(PVMFSessionId aSessionId,
                                OSCL_wString& aContentName,
                                OsclAny* aData,
                                uint32 aDataSize,
                                int32 aTimeoutMsec,
                                OsclAny* aContextData)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACFFParserNode::GetLicense - Wide called"));
    PVMFAACFFParserNodeCommand cmd;
    cmd.PVMFAACFFParserNodeCommand::Construct(aSessionId,
            PVMF_AAC_PARSER_NODE_GET_LICENSE_W,
            aContentName,
            aData,
            aDataSize,
            aTimeoutMsec,
            aContextData);
    return QueueCommandL(cmd);
}

PVMFCommandId
PVMFAACFFParserNode::GetLicense(PVMFSessionId aSessionId,
                                OSCL_String&  aContentName,
                                OsclAny* aData,
                                uint32 aDataSize,
                                int32 aTimeoutMsec,
                                OsclAny* aContextData)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACFFParserNode::GetLicense - Wide called"));
    PVMFAACFFParserNodeCommand cmd;
    cmd.PVMFAACFFParserNodeCommand::Construct(aSessionId,
            PVMF_AAC_PARSER_NODE_GET_LICENSE,
            aContentName,
            aData,
            aDataSize,
            aTimeoutMsec,
            aContextData);
    return QueueCommandL(cmd);
}

PVMFCommandId
PVMFAACFFParserNode::CancelGetLicense(PVMFSessionId aSessionId
                                      , PVMFCommandId aCmdId
                                      , OsclAny* aContextData)
{
    PVMFAACFFParserNodeCommand cmd;
    cmd.PVMFAACFFParserNodeCommandBase::Construct(aSessionId,
            PVMF_AAC_PARSER_NODE_CANCEL_GET_LICENSE,
            aCmdId,
            aContextData);
    return QueueCommandL(cmd);
}

PVMFStatus
PVMFAACFFParserNode::GetLicenseStatus(PVMFCPMLicenseStatus& aStatus)
{
    if (iCPMLicenseInterface)
        return iCPMLicenseInterface->GetLicenseStatus(aStatus);
    return PVMFFailure;
}

PVMFStatus
PVMFAACFFParserNode::DoGetLicense(PVMFAACFFParserNodeCommand& aCmd,
                                  bool aWideCharVersion)
{
    if (iCPMLicenseInterface == NULL)
    {
        return PVMFErrNotSupported;
    }

    if (aWideCharVersion == true)
    {
        OSCL_wString* contentName = NULL;
        OsclAny* data = NULL;
        uint32 dataSize = 0;
        int32 timeoutMsec = 0;
        aCmd.PVMFAACFFParserNodeCommand::Parse(contentName,
                                               data,
                                               dataSize,
                                               timeoutMsec);
        iCPMGetLicenseCmdId =
            iCPMLicenseInterface->GetLicense(iCPMSessionID,
                                             *contentName,
                                             data,
                                             dataSize,
                                             timeoutMsec);
    }
    else
    {
        OSCL_String* contentName = NULL;
        OsclAny* data = NULL;
        uint32 dataSize = 0;
        int32 timeoutMsec = 0;
        aCmd.PVMFAACFFParserNodeCommand::Parse(contentName,
                                               data,
                                               dataSize,
                                               timeoutMsec);
        iCPMGetLicenseCmdId =
            iCPMLicenseInterface->GetLicense(iCPMSessionID,
                                             *contentName,
                                             data,
                                             dataSize,
                                             timeoutMsec);
    }
    return PVMFPending;
}

void PVMFAACFFParserNode::CompleteGetLicense()
{
    CommandComplete(iCurrentCommand,
                    iCurrentCommand.front(),
                    PVMFSuccess);
}

void PVMFAACFFParserNode::DoCancelGetLicense(PVMFAACFFParserNodeCommand& aCmd)
{
    PVMF_AACPARSERNODE_LOGSTACKTRACE((0, "PVMFAACFFParserNode::DoCancelGetLicense() Called"));
    PVMFStatus status = PVMFErrArgument;

    if (iCPMLicenseInterface == NULL)
    {
        status = PVMFErrNotSupported;
    }
    else
    {
        /* extract the command ID from the parameters.*/
        PVMFCommandId id;
        aCmd.PVMFAACFFParserNodeCommandBase::Parse(id);

        /* first check "current" command if any */
        PVMFAACFFParserNodeCommand* cmd = iCurrentCommand.FindById(id);
        if (cmd)
        {
            if (cmd->iCmd == PVMF_AAC_PARSER_NODE_GET_LICENSE_W || cmd->iCmd == PVMF_AAC_PARSER_NODE_GET_LICENSE)
            {
                iCPMCancelGetLicenseCmdId =
                    iCPMLicenseInterface->CancelGetLicense(iCPMSessionID, iCPMGetLicenseCmdId);

                /*
                 * the queued commands are all asynchronous commands to the
                 * CPM module. CancelGetLicense can cancel only for GetLicense cmd.
                 * We need to wait CPMCommandCompleted.
                 */
                MoveCmdToCancelQueue(aCmd);
                return;
            }
        }

        /*
         * next check input queue.
         * start at element 1 since this cancel command is element 0.
         */
        cmd = iInputCommands.FindById(id, 1);
        if (cmd)
        {
            if (cmd->iCmd == PVMF_AAC_PARSER_NODE_GET_LICENSE_W || cmd->iCmd == PVMF_AAC_PARSER_NODE_GET_LICENSE)
            {
                /* cancel the queued command */
                CommandComplete(iInputCommands, *cmd, PVMFErrCancelled, NULL, NULL);
                /* report cancel success */
                CommandComplete(iInputCommands, aCmd, PVMFSuccess);
                return;
            }
        }
    }
    /* if we get here the command isn't queued so the cancel fails */
    CommandComplete(iInputCommands, aCmd, status);
    return;
}

int32 PVMFAACFFParserNode::CreateNewArray(char*& aPtr, char *aKey)
{
    int32 leavecode = 0;
    OSCL_TRY(leavecode,
             aPtr = OSCL_ARRAY_NEW(char, oscl_strlen(aKey) + 1););
    return leavecode;
}

int32 PVMFAACFFParserNode::CreateNewArray(char*& aPtr, int32 aLen)
{
    int32 leavecode = 0;
    OSCL_TRY(leavecode,
             aPtr = OSCL_ARRAY_NEW(char, aLen););
    return leavecode;
}

int32 PVMFAACFFParserNode::CreateNewArray(oscl_wchar*& aPtr, int32 aLen)
{
    int32 leavecode = 0;
    OSCL_TRY(leavecode,
             aPtr = OSCL_ARRAY_NEW(oscl_wchar, aLen););
    return leavecode;
}

int32 PVMFAACFFParserNode::PushBackKeyVal(Oscl_Vector<PvmiKvp, OsclMemAllocator>*& aValueListPtr, PvmiKvp &aKeyVal)
{
    int32 leavecode = 0;
    OSCL_TRY(leavecode, (*aValueListPtr).push_back(aKeyVal));
    return leavecode;
}

PVMFStatus PVMFAACFFParserNode::PushValueToList(Oscl_Vector<OSCL_HeapString<OsclMemAllocator>, OsclMemAllocator> &aRefMetaDataKeys, PVMFMetadataList *&aKeyListPtr, uint32 aLcv)
{
    int32 leavecode = 0;
    OSCL_TRY(leavecode, aKeyListPtr->push_back(aRefMetaDataKeys[aLcv]));
    OSCL_FIRST_CATCH_ANY(leavecode, PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFAACFFParserNode::PushValueToList() Memory allocation failure when copying metadata key"));return PVMFErrNoMemory);
    return PVMFSuccess;
}

