/* ------------------------------------------------------------------
 * 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;
}

PVMFStatus PVMFAACFFParserNode::QueryInterfaceSync(PVMFSessionId aSession,
        const PVUuid& aUuid,
        PVInterface*& aInterfacePtr)
{
    OSCL_UNUSED_ARG(aSession);
    aInterfacePtr = NULL;
    if (queryInterface(aUuid, aInterfacePtr))
    {
        aInterfacePtr->addRef();
        return PVMFSuccess;
    }
    return PVMFErrNotSupported;
}

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;
    }
    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;
                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;
                    if (context->iFileHandle)
                    {

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

                        iCPMSourceData.iFileHandle = iFileHandle;
                    }
                    iCPMSourceData.iPreviewMode = iPreviewMode;
                    iCPMSourceData.iIntent = context->iIntent;
                }
            }
        }
        /*
        * create a CPM object here...
        */
        iUseCPMPluginRegistry = true;
        {
            //cleanup any prior instance
            if (iCPM)
            {
                iCPM->ThreadLogoff();
                PVMFCPMFactory::DestroyContentPolicyManager(iCPM);
                iCPM = NULL;
            }
            iCPM = PVMFCPMFactory::CreateContentPolicyManager(*this);
            //thread logon may leave if there are no plugins
            int32 err;
            OSCL_TRY(err, iCPM->ThreadLogon(););
            OSCL_FIRST_CATCH_ANY(err,
                                 iCPM->ThreadLogoff();
                                 PVMFCPMFactory::DestroyContentPolicyManager(iCPM);
                                 iCPM = NULL;
                                 iUseCPMPluginRegistry = false;
                                );
        }
        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;
    if (!iAACParser->RetrieveFileInfo(aacinfo)) 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_in = NULL;
    PVMFMetadataList* keylistptr = NULL;
    Oscl_Vector<PvmiKvp, OsclMemAllocator>* valuelistptr = NULL;
    uint32 starting_index;
    int32 max_entries;

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

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

    keylistptr = keylistptr_in;
    //If numkeys is one, just check to see if the request
    //is for ALL metadata
    if (keylistptr_in->size() == 1)
    {
        if (oscl_strncmp((*keylistptr)[0].get_cstr(),
                         PVAAC_ALL_METADATA_KEY,
                         oscl_strlen(PVAAC_ALL_METADATA_KEY)) == 0)
        {
            //use the complete metadata key list
            keylistptr = &iAvailableMetadataKeys;
        }
    }
    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_in),
                    (*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;
}

