/* ------------------------------------------------------------------
 * Copyright (C) 1998-2010 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 "pv_player_engine.h"

#include "pv_player_config.h"

#include "pv_player_sdkinfo.h"

#include "pvmf_node_interface.h"

#include "pvmf_ffparsernode_extension.h"

#include "pvmf_data_source_init_extension.h"

#include "pvmf_track_selection_extension.h"

#include "pvmf_data_source_playback_control.h"

#include "pvmf_data_source_direction_control.h"

#include "pvmf_track_level_info_extension.h"

#include "pvmf_nodes_sync_control.h"

#include "pvlogger.h"

#include "oscl_error_codes.h"

#include "pvmf_basic_errorinfomessage.h"

#include "pvmf_duration_infomessage.h"

#include "pvmf_metadata_infomessage.h"

#include "pv_mime_string_utils.h"

#include "pvmi_kvp_util.h"

#include "oscl_string_utils.h"

#include "media_clock_converter.h"

#include "time_comparison_utils.h"

#include "pvmf_local_data_source.h"

#include "pvmf_cpmplugin_license_interface.h"

#include "oscl_registry_access_client.h"

#include "pvmf_source_context_data.h"

#include "pv_player_node_registry.h"
#include "pv_player_registry_interface.h"

// For recognizer registry
#include "pvmf_recognizer_registry.h"

#include "pvmi_datastreamsyncinterface_ref_factory.h"

#include "pvmf_recognizer_plugin.h"

//


#define PVPLAYERENGINE_NUM_COMMANDS 10

#define PVPLAYERENGINE_TIMERID_ENDTIMECHECK 1

#define PVP_MIN_PLAYSTATUS_PERCENT_OVERFLOW_THRESHOLD 1000



PVPlayerEngine* PVPlayerEngine::New(PVCommandStatusObserver* aCmdStatusObserver,
                                    PVErrorEventObserver *aErrorEventObserver,
                                    PVInformationalEventObserver *aInfoEventObserver)
{
    PVPlayerEngine* engine = NULL;
    engine = OSCL_NEW(PVPlayerEngine, ());
    if (engine)
    {
        engine->Construct(aCmdStatusObserver,
                          aErrorEventObserver,
                          aInfoEventObserver);
    }

    return engine;
}


PVPlayerEngine::~PVPlayerEngine()
{
    iCurrentPlaybackClipId = 0xFFFFFFFF;

    Cancel();

    if (iCPM)
    {
        iCPM->ThreadLogoff();
        PVMFCPMFactory::DestroyContentPolicyManager(iCPM);
        iCPM = NULL;
    }

    // Clear the Track selection List
    iTrackSelectionList.clear();

    // Clear the Metadata value release List
    iMetadataValueReleaseList.clear();

    // Remove Stored KVP Values
    DeleteKVPValues();

    if (!iPendingCmds.empty())
    {
        iPendingCmds.pop();
    }

    // Clean up the datapaths
    for (uint32 i = 0; i < iDatapathList.size(); ++i)
    {
        DoEngineDatapathCleanup(iDatapathList[i]);
    }
    iDatapathList.clear();

    // Clean up the source node
    DoSourceNodeCleanup();

    // Shutdown and destroy the timer
    if (iPollingCheckTimer)
    {
        iPollingCheckTimer->Clear();
    }

    if (iWatchDogTimer)
    {
        iWatchDogTimer->Cancel();
        OSCL_DELETE(iWatchDogTimer);
    }

    OSCL_DELETE(iPollingCheckTimer);

    //Destroy media clock notifications interface
    if (iClockNotificationsInf != NULL)
    {
        iPlaybackClock.DestroyMediaClockNotificationsInterface(iClockNotificationsInf);
        iClockNotificationsInf = NULL;
    }

    // Return all engine contexts to pool
    while (!iCurrentContextList.empty())
    {
        FreeEngineContext(iCurrentContextList[0]);
    }

    PVPlayerRegistryPopulator::Depopulate(iPlayerNodeRegistry, iPlayerRecognizerRegistry);

    iNodeUuids.clear();

    iCommandIdMut.Close();
    iOOTSyncCommandSem.Close();

    iStartIssuedOnEngine = false;
}


PVCommandId PVPlayerEngine::GetSDKInfo(PVSDKInfo &aSDKInfo, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::GetSDKInfo()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(1);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pOsclAny_value = (OsclAny*) & aSDKInfo;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_GET_SDK_INFO, (OsclAny*)aContextData, &paramvec);
}


PVCommandId PVPlayerEngine::GetSDKModuleInfo(PVSDKModuleInfo &aSDKModuleInfo, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::GetSDKModuleInfo()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(1);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pOsclAny_value = (OsclAny*) & aSDKModuleInfo;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_GET_SDK_MODULE_INFO, (OsclAny*)aContextData, &paramvec);
}


PVCommandId PVPlayerEngine::SetLogAppender(const char* aTag, OsclSharedPtr<PVLoggerAppender>& aAppender, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::SetLogAppender()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(2);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pChar_value = (char*)aTag;
    paramvec.push_back(param);
    param.pOsclAny_value = (OsclAny*) & aAppender;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_SET_LOG_APPENDER, (OsclAny*)aContextData, &paramvec);
}


PVCommandId PVPlayerEngine::RemoveLogAppender(const char* aTag, OsclSharedPtr<PVLoggerAppender>& aAppender, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::RemoveLogAppender()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(2);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pChar_value = (char*)aTag;
    paramvec.push_back(param);
    param.pOsclAny_value = (OsclAny*) & aAppender;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_REMOVE_LOG_APPENDER, (OsclAny*)aContextData, &paramvec);
}


PVCommandId PVPlayerEngine::SetLogLevel(const char* aTag, int32 aLevel, bool aSetSubtree, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::SetLogLevel()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(3);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pChar_value = (char*)aTag;
    paramvec.push_back(param);
    param.int32_value = aLevel;
    paramvec.push_back(param);
    param.bool_value = aSetSubtree;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_SET_LOG_LEVEL, (OsclAny*)aContextData, &paramvec);
}


PVCommandId PVPlayerEngine::GetLogLevel(const char* aTag, PVLogLevelInfo& aLogInfo, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::GetLogLevel()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(2);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pChar_value = (char*)aTag;
    paramvec.push_back(param);
    param.pOsclAny_value = (OsclAny*) & aLogInfo;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_GET_LOG_LEVEL, (OsclAny*)aContextData, &paramvec);
}


PVCommandId PVPlayerEngine::QueryInterface(const PVUuid& aUuid, PVInterface*& aInterfacePtr, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::QueryInterface()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(1);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pOsclAny_value = (OsclAny*) & aInterfacePtr;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_QUERY_INTERFACE, (OsclAny*)aContextData, &paramvec, &aUuid);
}


PVCommandId PVPlayerEngine::CancelCommand(PVCommandId aCancelCmdId, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::CancelCommand()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(1);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.int32_value = aCancelCmdId;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_CANCEL_COMMAND, (OsclAny*)aContextData, &paramvec);
}


PVCommandId PVPlayerEngine::CancelAllCommands(const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::CancelAllCommands()"));
    return AddCommandToQueue(PVP_ENGINE_COMMAND_CANCEL_ALL_COMMANDS, (OsclAny*)aContextData);
}


PVCommandId PVPlayerEngine::GetPVPlayerState(PVPlayerState& aState, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::GetPVPlayerState()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(1);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pOsclAny_value = (OsclAny*) & aState;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_GET_PVPLAYER_STATE, (OsclAny*)aContextData, &paramvec);
}


PVMFStatus PVPlayerEngine::GetPVPlayerStateSync(PVPlayerState& aState)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::GetPVPlayerStateSync()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(1);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pOsclAny_value = (OsclAny*) & aState;
    paramvec.push_back(param);
    if (iThreadSafeQueue.IsInThread())
    {
        PVPlayerEngineCommand cmd(PVP_ENGINE_COMMAND_GET_PVPLAYER_STATE, -1, NULL, &paramvec);
        return DoGetPVPlayerState(cmd, true);
    }
    else
    {
        return DoOOTSyncCommand(PVP_ENGINE_COMMAND_GET_PVPLAYER_STATE_OOTSYNC, &paramvec);
    }
}


PVCommandId PVPlayerEngine::AddDataSource(PVPlayerDataSource& aDataSource, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::AddDataSource()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(1);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pOsclAny_value = (OsclAny*) & aDataSource;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_ADD_DATA_SOURCE, (OsclAny*)aContextData, &paramvec);
}

PVCommandId PVPlayerEngine::UpdateDataSource(PVPlayerDataSource& aDataSource, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateDataSource()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(1);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pOsclAny_value = (OsclAny*) & aDataSource;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_UPDATE_DATA_SOURCE, (OsclAny*)aContextData, &paramvec);
}

PVCommandId PVPlayerEngine::Init(const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Init()"));
    return AddCommandToQueue(PVP_ENGINE_COMMAND_INIT, (OsclAny*)aContextData);
}


PVCommandId PVPlayerEngine::GetMetadataKeys(PVPMetadataList& aKeyList, int32 aStartingIndex, int32 aMaxEntries,
        char* aQueryKey, const OsclAny* aContextData, uint32 aClipIndex)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::GetMetadataKeys()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(5);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;

    param.pOsclAny_value = (OsclAny*) & aKeyList;
    paramvec.push_back(param);
    param.int32_value = aStartingIndex;
    paramvec.push_back(param);
    param.int32_value = aMaxEntries;
    paramvec.push_back(param);
    param.pChar_value = aQueryKey;
    paramvec.push_back(param);
    param.uint32_value = aClipIndex;
    paramvec.push_back(param);

    return AddCommandToQueue(PVP_ENGINE_COMMAND_GET_METADATA_KEY, (OsclAny*)aContextData, &paramvec);
}

PVCommandId PVPlayerEngine::GetMetadataValues(PVPMetadataList& aKeyList, int32 aStartingValueIndex, int32 aMaxValueEntries, int32& aNumAvailableValueEntries,
        Oscl_Vector<PvmiKvp, OsclMemAllocator>& aValueList, const OsclAny* aContextData, bool aMetadataValuesCopiedInCallBack, uint32 aClipIndex)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::GetMetadataValues()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(7);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;

    param.pOsclAny_value = (OsclAny*) & aKeyList;
    paramvec.push_back(param);
    param.int32_value = aStartingValueIndex;
    paramvec.push_back(param);
    param.int32_value = aMaxValueEntries;
    paramvec.push_back(param);
    param.pOsclAny_value = (OsclAny*) & aNumAvailableValueEntries;
    paramvec.push_back(param);
    param.pOsclAny_value = (OsclAny*) & aValueList;
    paramvec.push_back(param);
    param.bool_value = aMetadataValuesCopiedInCallBack;
    paramvec.push_back(param);
    param.uint32_value = aClipIndex;
    paramvec.push_back(param);

    return AddCommandToQueue(PVP_ENGINE_COMMAND_GET_METADATA_VALUE, (OsclAny*)aContextData, &paramvec);
}

PVCommandId PVPlayerEngine::ReleaseMetadataValues(Oscl_Vector<PvmiKvp, OsclMemAllocator>& aValueList, const OsclAny* aContextData, uint32 aClipIndex)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::ReleaseMetadataValues()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(1);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;

    param.pOsclAny_value = (OsclAny*) & aValueList;
    paramvec.push_back(param);
    param.uint32_value = aClipIndex;
    paramvec.push_back(param);

    return AddCommandToQueue(PVP_ENGINE_COMMAND_RELEASE_METADATA_VALUE, (OsclAny*)aContextData, &paramvec);
}

PVCommandId PVPlayerEngine::AddDataSink(PVPlayerDataSink& aDataSink, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::AddDataSink()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(1);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pOsclAny_value = (OsclAny*) & aDataSink;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_ADD_DATA_SINK, (OsclAny*)aContextData, &paramvec);
}


PVCommandId PVPlayerEngine::SetPlaybackRange(PVPPlaybackPosition aBeginPos, PVPPlaybackPosition aEndPos, bool aQueueRange, const OsclAny* aContextData,
        bool aSkipToRequestedPosition, bool aSeekToSyncPoint)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::SetPlaybackRange()"));
    PVPPlaybackPosition curpos;
    curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC;

    // Additional checks to ensure a valid mode is
    // used for the begin position.
    // Assumes: aBegin.iPosUnit is always valid (when applicable).

    // Check 1 || Check 2
    // Check 1: Is the begin position indeterminate?
    // Check 2: Is the position unit something other than playlist?
    // If so, set mode to NOW.
    if ((aBeginPos.iIndeterminate) || (aBeginPos.iPosUnit != PVPPBPOSUNIT_PLAYLIST))
    {
        aBeginPos.iMode = PVPPBPOS_MODE_NOW;
    }
    // Check 3: Is the position unit playlist and the mode something other than the three valid
    // modes? If so, set mode to NOW.
    else if (aBeginPos.iPosUnit == PVPPBPOSUNIT_PLAYLIST)
    {
        switch (aBeginPos.iMode)
        {
            case PVPPBPOS_MODE_NOW:
            case PVPPBPOS_MODE_END_OF_CURRENT_PLAY_ELEMENT:
            case PVPPBPOS_MODE_END_OF_CURRENT_PLAY_SESSION:
            case PVPPBPOS_MODE_3GPP_FCS:
                break;
            case PVPPBPOS_MODE_UNKNOWN:
            default:
                aBeginPos.iMode = PVPPBPOS_MODE_NOW;
                break;
        }
    }
    iPlaybackPositionMode = aBeginPos.iMode;
    GetPlaybackClockPosition(curpos);
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(5);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.playbackpos_value = aBeginPos;
    paramvec.push_back(param);
    param.playbackpos_value = aEndPos;
    paramvec.push_back(param);
    param.bool_value = aQueueRange;
    paramvec.push_back(param);
    param.bool_value = aSkipToRequestedPosition;
    paramvec.push_back(param);
    param.bool_value = aSeekToSyncPoint;
    paramvec.push_back(param);
    if (!iOverflowFlag)
    {
        return AddCommandToQueue(PVP_ENGINE_COMMAND_SET_PLAYBACK_RANGE, (OsclAny*)aContextData, &paramvec);
    }
    else
    {
        return AddCommandToQueue(PVP_ENGINE_COMMAND_SET_PLAYBACK_RANGE, (OsclAny*)aContextData, &paramvec, NULL, false);
    }
}


PVCommandId PVPlayerEngine::GetPlaybackRange(PVPPlaybackPosition &aBeginPos, PVPPlaybackPosition &aEndPos, bool aQueued, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::GetPlaybackRange()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(3);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pPlaybackpos_value = &aBeginPos;
    paramvec.push_back(param);
    param.pPlaybackpos_value = &aEndPos;
    paramvec.push_back(param);
    param.bool_value = aQueued;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_GET_PLAYBACK_RANGE, (OsclAny*)aContextData, &paramvec);
}


PVCommandId PVPlayerEngine::GetCurrentPosition(PVPPlaybackPosition &aPos, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::GetCurrentPosition()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pPlaybackpos_value = &aPos;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_GET_CURRENT_POSITION, (OsclAny*)aContextData, &paramvec);
}


PVMFStatus PVPlayerEngine::GetCurrentPositionSync(PVPPlaybackPosition &aPos)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::GetCurrentPositionSync()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(1);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pPlaybackpos_value = &aPos;
    paramvec.push_back(param);
    if (iThreadSafeQueue.IsInThread())
    {
        PVPlayerEngineCommand cmd(PVP_ENGINE_COMMAND_GET_CURRENT_POSITION, -1, NULL, &paramvec);
        return DoGetCurrentPosition(cmd, true);
    }
    else
    {
        return DoOOTSyncCommand(PVP_ENGINE_COMMAND_GET_CURRENT_POSITION_OOTSYNC, &paramvec);
    }
}


PVCommandId PVPlayerEngine::SetPlaybackRate(int32 aRate, PVMFTimebase* aTimebase, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::SetPlaybackRate()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(2);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.int32_value = aRate;
    paramvec.push_back(param);
    param.pOsclAny_value = (OsclAny*)aTimebase;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_SET_PLAYBACK_RATE, (OsclAny*)aContextData, &paramvec);
}


PVCommandId PVPlayerEngine::GetPlaybackRate(int32& aRate, PVMFTimebase*& aTimebase, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::GetPlaybackRate()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(2);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pInt32_value = &aRate;
    paramvec.push_back(param);
    param.pOsclAny_value = (OsclAny*) & aTimebase;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_GET_PLAYBACK_RATE, (OsclAny*)aContextData, &paramvec);
}


PVCommandId PVPlayerEngine::GetPlaybackMinMaxRate(int32& aMinRate, int32& aMaxRate, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::GetPlaybackMinMaxRate()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(2);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pInt32_value = &aMinRate;
    paramvec.push_back(param);
    param.pInt32_value = &aMaxRate;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_GET_PLAYBACK_MINMAX_RATE, (OsclAny*)aContextData, &paramvec);
}


PVCommandId PVPlayerEngine::Prepare(const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Prepare()"));
    return AddCommandToQueue(PVP_ENGINE_COMMAND_PREPARE, (OsclAny*)aContextData);
}


PVCommandId PVPlayerEngine::Start(const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Start() "));
    return AddCommandToQueue(PVP_ENGINE_COMMAND_START, (OsclAny*)aContextData);
}


PVCommandId PVPlayerEngine::Pause(const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Pause()"));
    return AddCommandToQueue(PVP_ENGINE_COMMAND_PAUSE, (OsclAny*)aContextData);
}


PVCommandId PVPlayerEngine::Resume(const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Resume()"));
    return AddCommandToQueue(PVP_ENGINE_COMMAND_RESUME, (OsclAny*)aContextData);
}


PVCommandId PVPlayerEngine::Stop(const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Stop()"));
    return AddCommandToQueue(PVP_ENGINE_COMMAND_STOP, (OsclAny*)aContextData);
}


PVCommandId PVPlayerEngine::RemoveDataSink(PVPlayerDataSink& aDataSink, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::RemoveDataSink()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(1);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pOsclAny_value = (OsclAny*) & aDataSink;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_REMOVE_DATA_SINK, (OsclAny*)aContextData, &paramvec);
}


PVCommandId PVPlayerEngine::Reset(const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Reset()"));
    return AddCommandToQueue(PVP_ENGINE_COMMAND_RESET, (OsclAny*)aContextData);
}


PVCommandId PVPlayerEngine::RemoveDataSource(PVPlayerDataSource& aDataSource, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::RemoveDataSource()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(1);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pOsclAny_value = (OsclAny*) & aDataSource;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_REMOVE_DATA_SOURCE, (OsclAny*)aContextData, &paramvec);
}


void PVPlayerEngine::setObserver(PvmiConfigAndCapabilityCmdObserver* aObserver)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::setObserver()"));

    if (iThreadSafeQueue.IsInThread())
    {
        iCfgCapCmdObserver = aObserver;
    }
    else
    {
        Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
        paramvec.reserve(2);
        paramvec.clear();
        PVPlayerEngineCommandParamUnion param;
        param.pOsclAny_value = aObserver;
        paramvec.push_back(param);
        DoOOTSyncCommand(PVP_ENGINE_COMMAND_CAPCONFIG_SET_OBSERVER_OOTSYNC, &paramvec);
    }
}

PVMFStatus PVPlayerEngine::DoSetObserverSync(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetObserverSync() In"));

    iCfgCapCmdObserver = (PvmiConfigAndCapabilityCmdObserver*)(aCmd.GetParam(0).pOsclAny_value);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetObserverSync() Out"));
    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::getParametersSync(PvmiMIOSession aSession, PvmiKeyType aIdentifier, PvmiKvp*& aParameters, int& aNumParamElements, PvmiCapabilityContext aContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::getParametersSync()"));
    OSCL_UNUSED_ARG(aSession);

    if (iThreadSafeQueue.IsInThread())
    {
        return DoCapConfigGetParametersSync(aIdentifier, aParameters, aNumParamElements, aContext);
    }
    else
    {
        Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
        paramvec.reserve(5);
        paramvec.clear();
        PVPlayerEngineCommandParamUnion param;
        param.pOsclAny_value = &aIdentifier;
        paramvec.push_back(param);
        param.pOsclAny_value = &aParameters;
        paramvec.push_back(param);
        param.pOsclAny_value = &aNumParamElements;
        paramvec.push_back(param);
        param.pOsclAny_value = &aContext;
        paramvec.push_back(param);
        return DoOOTSyncCommand(PVP_ENGINE_COMMAND_CAPCONFIG_GET_PARAMETERS_OOTSYNC, &paramvec);
    }
}


PVMFStatus PVPlayerEngine::DoGetParametersSync(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetParametersSync() In"));

    PVMFStatus status = DoCapConfigGetParametersSync(
                            *((PvmiKeyType*)aCmd.GetParam(0).pOsclAny_value)
                            , *((PvmiKvp**)aCmd.GetParam(1).pOsclAny_value)
                            , *((int*)aCmd.GetParam(2).pOsclAny_value)
                            , *((PvmiCapabilityContext*)aCmd.GetParam(3).pOsclAny_value));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetParametersSync() Out"));
    return status;
}


PVMFStatus PVPlayerEngine::releaseParameters(PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::releaseParameters()"));
    OSCL_UNUSED_ARG(aSession);

    if (iThreadSafeQueue.IsInThread())
    {
        return DoCapConfigReleaseParameters(aParameters, aNumElements);
    }
    else
    {
        Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
        paramvec.reserve(3);
        paramvec.clear();
        PVPlayerEngineCommandParamUnion param;
        param.pOsclAny_value = aParameters;
        paramvec.push_back(param);
        param.int32_value = aNumElements;
        paramvec.push_back(param);
        return DoOOTSyncCommand(PVP_ENGINE_COMMAND_CAPCONFIG_RELEASE_PARAMETERS_OOTSYNC, &paramvec);
    }
}

PVMFStatus PVPlayerEngine::DoReleaseParametersSync(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoReleaseParametersSync() In"));

    PVMFStatus status = DoCapConfigReleaseParameters(
                            (PvmiKvp*)aCmd.GetParam(0).pOsclAny_value
                            , aCmd.GetParam(1).int32_value);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoReleaseParametersSync() Out"));
    return status;
}

void PVPlayerEngine::createContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::createContext()"));
    OSCL_UNUSED_ARG(aSession);
    // Context is not really supported so just return some member variable pointer
    // If this function is changed, do not forget to change DeleteContext() below
    aContext = (PvmiCapabilityContext) & iCapConfigContext;
}


void PVPlayerEngine::setParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements, PvmiKvp* &aRetKVP)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::setParametersSync()"));
    OSCL_UNUSED_ARG(aSession);

    if (oscl_strcmp(aParameters->key, PVMF_IFRAME_ONLY_RENDERING_MODE) == 0)
    {
        if ((iState != PVP_ENGINE_STATE_INITIALIZED) && (iState != PVP_ENGINE_STATE_PREPARED))
            return;
    }

    // Save the parameters in an engine command object
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(3);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pOsclAny_value = (OsclAny*)aParameters;
    paramvec.push_back(param);
    param.int32_value = (int32) aNumElements;
    paramvec.push_back(param);
    param.pOsclAny_value = (OsclAny*) & aRetKVP;
    paramvec.push_back(param);
    if (iThreadSafeQueue.IsInThread())
    {
        PVPlayerEngineCommand cmd(PVP_ENGINE_COMMAND_CAPCONFIG_SET_PARAMETERS, -1, NULL, &paramvec);

        // Complete the request synchronously
        DoCapConfigSetParameters(cmd, true);
    }
    else
    {
        DoOOTSyncCommand(PVP_ENGINE_COMMAND_CAPCONFIG_SET_PARAMETERS_OOTSYNC, &paramvec);
    }
}


PVMFCommandId PVPlayerEngine::setParametersAsync(PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements, PvmiKvp*& aRetKVP, OsclAny* aContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::setParametersAsync()"));
    OSCL_UNUSED_ARG(aSession);

    // Save the parameters in an engine command object
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(3);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pOsclAny_value = (OsclAny*)aParameters;
    paramvec.push_back(param);
    param.int32_value = (int32) aNumElements;
    paramvec.push_back(param);
    param.pOsclAny_value = (OsclAny*) & aRetKVP;
    paramvec.push_back(param);

    // Push it to command queue to be processed asynchronously
    return AddCommandToQueue(PVP_ENGINE_COMMAND_CAPCONFIG_SET_PARAMETERS, (OsclAny*)aContext, &paramvec, NULL, false);
}


PVMFStatus PVPlayerEngine::verifyParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::verifyParametersSync()"));
    OSCL_UNUSED_ARG(aSession);

    if (iThreadSafeQueue.IsInThread())
    {
        return DoCapConfigVerifyParameters(aParameters, aNumElements);
    }
    else
    {
        Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
        paramvec.reserve(3);
        paramvec.clear();
        PVPlayerEngineCommandParamUnion param;
        param.pOsclAny_value = aParameters;
        paramvec.push_back(param);
        param.int32_value = aNumElements;
        paramvec.push_back(param);
        return DoOOTSyncCommand(PVP_ENGINE_COMMAND_CAPCONFIG_VERIFY_PARAMETERS_OOTSYNC, &paramvec);
    }
}

PVMFStatus PVPlayerEngine::DoVerifyParametersSync(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoVerifyParametersSync() In"));

    PVMFStatus status = DoCapConfigVerifyParameters(
                            (PvmiKvp*)aCmd.GetParam(0).pOsclAny_value
                            , aCmd.GetParam(1).int32_value);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoVerifyParametersSync() Out"));
    return status;
}

PVMFCommandId PVPlayerEngine::AcquireLicense(OsclAny* aLicenseData, uint32 aDataSize, oscl_wchar* aContentName, int32 aTimeoutMsec, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::AcquireLicense() wchar"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(3);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pOsclAny_value = aLicenseData;
    paramvec.push_back(param);
    param.uint32_value = aDataSize;
    paramvec.push_back(param);
    param.pWChar_value = aContentName;
    paramvec.push_back(param);
    param.int32_value = aTimeoutMsec;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_WCHAR, (OsclAny*)aContextData, &paramvec);
}


PVMFCommandId PVPlayerEngine::AcquireLicense(OsclAny* aLicenseData, uint32 aDataSize, char* aContentName, int32 aTimeoutMsec, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::AcquireLicense() char"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(3);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pOsclAny_value = aLicenseData;
    paramvec.push_back(param);
    param.uint32_value = aDataSize;
    paramvec.push_back(param);
    param.pChar_value = aContentName;
    paramvec.push_back(param);
    param.int32_value = aTimeoutMsec;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_CHAR, (OsclAny*)aContextData, &paramvec);
}

PVMFCommandId PVPlayerEngine::CancelAcquireLicense(PVMFCommandId aCmdId, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::CancelAcquireLicense()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(1);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.int32_value = aCmdId;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_CANCEL_ACQUIRE_LICENSE, (OsclAny*)aContextData, &paramvec);
}

PVMFCommandId PVPlayerEngine::JoinDomain(const PVMFCPMDomainJoinData& aJoinData, int32 aTimeoutMsec, const OsclAny* aContextData)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::JoinDomain()"));
    Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
    paramvec.reserve(2);
    paramvec.clear();
    PVPlayerEngineCommandParamUnion param;
    param.pOsclAny_value = (OsclAny *) & aJoinData;
    paramvec.push_back(param);
    param.int32_value = aTimeoutMsec;
    paramvec.push_back(param);
    return AddCommandToQueue(PVP_ENGINE_COMMAND_JOIN_DOMAIN, (OsclAny*)aContextData, &paramvec);
}

PVMFStatus PVPlayerEngine::GetLicenseStatus(PVMFCPMLicenseStatus& aStatus)
{
    if (iThreadSafeQueue.IsInThread())
    {
        if (iCPMLicenseIF)
        {
            return iCPMLicenseIF->GetLicenseStatus(aStatus);
        }
        return PVMFFailure;
    }
    else
    {
        Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
        paramvec.reserve(2);
        paramvec.clear();
        PVPlayerEngineCommandParamUnion param;
        param.pOsclAny_value = &aStatus;
        paramvec.push_back(param);
        return DoOOTSyncCommand(PVP_ENGINE_COMMAND_GET_LICENSE_STATUS_OOTSYNC, &paramvec);
    }
}

PVMFStatus PVPlayerEngine::DoGetLicenseStatusSync(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetLicenseStatusSync() In"));

    PVMFStatus status = PVMFFailure;
    if (iCPMLicenseIF)
    {
        PVMFCPMLicenseStatus* licstatus = (PVMFCPMLicenseStatus*)(aCmd.GetParam(0).pOsclAny_value);
        if (licstatus)
        {
            status = iCPMLicenseIF->GetLicenseStatus(*licstatus);
        }
    }
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetLicenseStatusSync() Out - status = %d", status));
    return status;
}

void PVPlayerEngine::addRef()
{
}


void PVPlayerEngine::removeRef()
{
}


bool PVPlayerEngine::queryInterface(const PVUuid& uuid, PVInterface*& iface)
{
    bool status = true;

    if (uuid == PVMI_CAPABILITY_AND_CONFIG_PVUUID)
    {
        PvmiCapabilityAndConfig* capconfigiface = OSCL_STATIC_CAST(PvmiCapabilityAndConfig*, this);
        iface = OSCL_STATIC_CAST(PVInterface*, capconfigiface);
    }
    else if (uuid == PVPlayerLicenseAcquisitionInterfaceUuid)
    {
        PVPlayerLicenseAcquisitionInterface* licacqiface = OSCL_STATIC_CAST(PVPlayerLicenseAcquisitionInterface*, this);
        iface = OSCL_STATIC_CAST(PVInterface*, licacqiface);
    }
    // Check if track level info IF from source node was requested
    else if (uuid == PVMF_TRACK_LEVEL_INFO_INTERFACE_UUID && iSourceNodeTrackLevelInfoIF)
    {
        iface = OSCL_STATIC_CAST(PVInterface*, iSourceNodeTrackLevelInfoIF);
    }
    //Check if track selection IF from source node was requested
    else if (uuid == PVPlayerTrackSelectionInterfaceUuid)
    {
        PVPlayerTrackSelectionInterface* tseliface = OSCL_STATIC_CAST(PVPlayerTrackSelectionInterface*, this);
        iface = OSCL_STATIC_CAST(PVInterface*, tseliface);
    }
    else
    {
        //check to see if we can query the interface from CPM
        //we would still like to complete queryinterface in a single AO run
        //therefore we will rely on sync queryinterface of CPM to query for the interface
        //In future if we want to asynchronously query for interfaces from CPM, source node, datapath etc
        //then in addition to holding back QueryInterface cmd complete till modules underneath have completed
        //their async QueryInterface cmds, we also need to update the cancel command processing to make sure we handle
        //cancel of async QueryInterface properly. These are not handled / untested as of today.
        //Also please note that this CPM instance is different from the one that is used inside source nodes.
        //Ability to interact with CPM plugins outside of source nodes is possible via such extension interfaces. That
        //said, the users of these interfaces should be well aware of the usecase. These usecase typically involve
        //drm maintenance related stuff, things like device activation, metering, cleaning up license stores etc etc.
        if (iCPM == NULL)
        {
            //create CPM and do threadlogon
            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;
                                 status = false;
                                );
            //we will destroy CPM as part of engine destructor
            //(not reset since technically init is not required to query for interfaces).
            //in case we happen to provide an interface from CPM, CPM needs to
            //persist till we are done with the interface
        }
        if (status)
        {
            //go ahead and query the CPM for interface
            status = iCPM->queryInterface(uuid, iface);
        }
        if (!status)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::queryInterface() Unsupported interface UUID."));
        }
    }
    return status;
}



PVPlayerEngine::PVPlayerEngine() :
        OsclTimerObject(OsclActiveObject::EPriorityNominal, "PVPlayerEngine"),
        iCommandId(0),
        iState(PVP_ENGINE_STATE_IDLE),
        iCmdStatusObserver(NULL),
        iErrorEventObserver(NULL),
        iInfoEventObserver(NULL),
        iCfgCapCmdObserver(NULL),
        iPollingCheckTimer(NULL),
        iCommandCompleteStatusInErrorHandling(PVMFSuccess),
        iCommandCompleteErrMsgInErrorHandling(NULL),
        iCapConfigContext(0),
        iNumPendingNodeCmd(0),
        iNumPendingSkipCompleteEvent(0),
        iNumPendingDatapathCmd(0),
        iNumPVMFInfoStartOfDataPending(0),
        iDataSource(NULL),
        iRemoveDataSource(false),
        iSourceFormatType(PVMF_MIME_FORMAT_UNKNOWN),
        iSourceNode(NULL),
        iSourceNodeSessionId(0),
        iSourceNodeInitIF(NULL),
        iSourceNodeTrackSelIF(NULL),
        iSourceNodePBCtrlIF(NULL),
        iSourceNodeDirCtrlIF(NULL),
        iSourceNodeTrackLevelInfoIF(NULL),
        iSourceNodeMetadataExtIF(NULL),
        iSourceNodeCapConfigIF(NULL),
        iSourceNodeRegInitIF(NULL),
        iCPMLicenseIF(NULL),
        iSourceNodePVInterfaceInit(NULL),
        iSourceNodePVInterfaceTrackSel(NULL),
        iSourceNodePVInterfacePBCtrl(NULL),
        iSourceNodePVInterfaceDirCtrl(NULL),
        iSourceNodePVInterfaceTrackLevelInfo(NULL),
        iSourceNodePVInterfaceMetadataExt(NULL),
        iSourceNodePVInterfaceCapConfig(NULL),
        iSourceNodePVInterfaceRegInit(NULL),
        iPVInterfaceCPMLicense(NULL),
        iCPMGetLicenseCmdId(0),
        iCPMCancelGetLicenseCmdId(0),
        iCPMJoinDomainCmdId(0),
        iMetadataValuesCopiedInCallBack(true),
        iReleaseMetadataValuesPending(false),
        iCurrentContextListMemPool(12),
        iNumberCancelCmdPending(0),
        iLogger(NULL),
        iReposLogger(NULL),
        iPerfLogger(NULL),
        iClockNotificationsInf(NULL),
        iPlayStatusCallbackTimerID(0),
        iPlayStatusCallbackTimerMarginWindow(0),
        iPlaybackClockRate(100000),
        iOutsideTimebase(NULL),
        iPlaybackClockRate_New(100000),
        iOutsideTimebase_New(NULL),
        iPlaybackDirection(1),
        iPlaybackDirection_New(1),
        iChangePlaybackDirectionWhenResuming(false),
        iEndTimeCheckEnabled(false),
        iQueuedRangePresent(false),
        iChangePlaybackPositionWhenResuming(false),
        iActualNPT(0),
        iTargetNPT(0),
        iActualMediaDataTS(0),
        iSkipMediaDataTS(0),
        iStartNPT(0),
        iStartMediaDataTS(0),
        iWatchDogTimerInterval(0),
        iSeekPointBeforeTargetNPT(0),
        iSeekPointAfterTargetNPT(0),
        iForwardReposFlag(false),
        iBackwardReposFlag(false),
        iPlayStatusTimerEnabled(false),
        iDataReadySent(false),
        iPlaybackPausedDueToEndOfClip(false),
        iPlaybackPausedDueToEndOfTimeReached(false),
        iSourceDurationAvailable(false),
        iSourceDurationInMS(0),
        iPBPosEnable(true),
        iPBPosStatusUnit(PVPLAYERENGINE_CONFIG_PBPOSSTATUSUNIT_DEF),
        iPBPosStatusInterval(PVPLAYERENGINE_CONFIG_PBPOSSTATUSINTERVAL_DEF),
        iEndTimeCheckInterval(PVPLAYERENGINE_CONFIG_ENDTIMECHECKINTERVAL_DEF),
        iSeekToSyncPoint(true),
        iSkipToRequestedPosition(true),
        iBackwardRepos(false),
        iSyncPointSeekWindow(PVPLAYERENGINE_CONFIG_SEEKTOSYNCPOINTWINDOW_DEF),
        iNodeCmdTimeout(PVPLAYERENGINE_CONFIG_NODECMDTIMEOUT_DEF),
        iNodeDataQueuingTimeout(PVPLAYERENGINE_CONFIG_NODEDATAQUEUINGTIMEOUT_DEF),
        iSilenceInsertionEnable(true),
        iGracefulDegradationEnable(PVPLAYERENGINE_CONFIG_GRACEFULDEGRADATIONENABLE_DEF),
        iProdInfoProdName(_STRLIT_CHAR(PVPLAYERENGINE_PRODINFO_PRODNAME_STRING)),
        iProdInfoPartNum(_STRLIT_CHAR(PVPLAYERENGINE_PRODINFO_PARTNUM_STRING)),
        iProdInfoHWPlatform(_STRLIT_CHAR(PVPLAYERENGINE_PRODINFO_HWPLATFORM_STRING)),
        iProdInfoSWPlatform(_STRLIT_CHAR(PVPLAYERENGINE_PRODINFO_SWPLATFORM_STRING)),
        iProdInfoDevice(_STRLIT_CHAR(PVPLAYERENGINE_PRODINFO_DEVICE_STRING)),
        iStreamID(0),
        iAlternateSrcFormatIndex(0),
        iRollOverState(RollOverStateIdle),
        iTrackSelectionHelper(NULL),
        iPlaybackPositionMode(PVPPBPOS_MODE_UNKNOWN),
        iOverflowFlag(false),
        iClipsCompleted(0),
        iClipsCorrupted(0),
        iCurrentPlaybackClipId(0xFFFFFFFF),
        iNumClipsQueued(0),
        iStartIssuedOnEngine(false)
{
    iCurrentBeginPosition.iIndeterminate = true;
    iCurrentEndPosition.iIndeterminate = true;
    iCurrentBeginPosition.iPlayListUri = NULL;
    iQueuedBeginPosition.iIndeterminate = true;
    iQueuedEndPosition.iIndeterminate = true;
    iChangeDirectionNPT.iIndeterminate = true;

    iSyncMarginVideo.min = PVPLAYERENGINE_CONFIG_SYNCMARGIN_EARLY_DEF;
    iSyncMarginVideo.max = PVPLAYERENGINE_CONFIG_SYNCMARGIN_LATE_DEF;
    iSyncMarginAudio.min = PVPLAYERENGINE_CONFIG_SYNCMARGIN_EARLY_DEF;
    iSyncMarginAudio.max = PVPLAYERENGINE_CONFIG_SYNCMARGIN_LATE_DEF;
    iSyncMarginText.min = PVPLAYERENGINE_CONFIG_SYNCMARGIN_EARLY_DEF;
    iSyncMarginText.max = PVPLAYERENGINE_CONFIG_SYNCMARGIN_LATE_DEF;

    iNodeUuids.clear();
}


void PVPlayerEngine::Construct(PVCommandStatusObserver* aCmdStatusObserver,
                               PVErrorEventObserver *aErrorEventObserver,
                               PVInformationalEventObserver *aInfoEventObserver)
{
    iCommandIdMut.Create();
    iOOTSyncCommandSem.Create();
    iThreadSafeQueue.Configure(this);

    iCmdStatusObserver = aCmdStatusObserver;
    iInfoEventObserver = aInfoEventObserver;
    iErrorEventObserver = aErrorEventObserver;

    // Allocate memory for vectors
    // If a leave occurs, let it bubble up
    iCurrentCmd.reserve(1);
    iCmdToCancel.reserve(1);
    iCmdToDlaCancel.reserve(1);
    iPendingCmds.reserve(PVPLAYERENGINE_NUM_COMMANDS);
    iPvmiKvpCapNConfig.reserve(20);

    iDatapathList.reserve(3);

    iCurrentContextList.reserve(12);

    iMetadataIFList.reserve(6);
    iMetadataIFList.clear();

    iMetadataKeyReleaseList.reserve(6);
    iMetadataKeyReleaseList.clear();

    iMetadataValueReleaseList.reserve(6);
    iMetadataValueReleaseList.clear();

    iCPM = NULL;

    iSourceDurationVector.reserve(5);
    iSourceDurationVector.clear();

    AddToScheduler();

    // Retrieve the logger object
    iLogger = PVLogger::GetLoggerObject("PVPlayerEngine");
    iPerfLogger = PVLogger::GetLoggerObject("pvplayerdiagnostics.perf.engine");
    iReposLogger = PVLogger::GetLoggerObject("pvplayerrepos.engine");

    // Initialize the playback clock to use tickcount timebase
    iPlaybackClock.SetClockTimebase(iPlaybackTimebase);
    uint32 starttime = 0;
    bool overflow = 0;
    iPlaybackClock.SetStartTime32(starttime, PVMF_MEDIA_CLOCK_MSEC, overflow);
    iPlaybackClock.ConstructMediaClockNotificationsInterface(iClockNotificationsInf, *this);

    // Initialize the OSCL timer for polling checks
    iPollingCheckTimer = OSCL_NEW(OsclTimer<OsclMemAllocator>, ("playerengine_pollingcheck"));
    iPollingCheckTimer->SetObserver(this);
    iPollingCheckTimer->SetFrequency(10);  // 100 ms resolution

    iWatchDogTimer = OSCL_NEW(PVPlayerWatchdogTimer, (this));

    PVPlayerRegistryPopulator::Populate(iPlayerNodeRegistry, iPlayerRecognizerRegistry);

    return;
}


void PVPlayerEngine::Run()
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Run() In"));
    int32 leavecode = 0;

    /* Engine AO will execute commands in the following sequence:
     * 1) If Engine state is Resetting, which will happen when Engine does ErrorHandling,
     *    or is processing Reset or CancelAllCommands issued by the app, engine will NOT execute
     *    any other command during this state.
     * 2) If Engine is not in Resetting state, then it will process commands in the following order,
     *    which ever is true:
     *      (i) If Engine needs to do Error handling because of some error from Source Node or Datapath,
     *          either start error handling or complete it.
     *     (ii) If Engine has Reset or CancelAllCommands in CurrentCommandQueue,
     *          Engine will do CommandComplete for the CurrentCommand.
     *    (iii) If Engine has Prepare in CurrentCommandQueue, Engine will call DoPrepare again
     *          as a part of track selection logic.
     *     (iv) If Engine has CancelAllCommands or CancelAcquireLicense in Pending CommandQueue,
     *          Engine will start Cancel commands.
     *      (v) Go for Rollover if in Init State and Roll-over is ongoing.
     *     (vi) Process which ever command is pushed in Pending queue.
     * Engine will process any one of the command as listed above in the same order.
     * Every time engine AO is scheduled, engine will go through these steps.
     */

    if (iState == PVP_ENGINE_STATE_RESETTING)
    {
        //This means error handling, reset or cancelall is still in progress.
        //Please note that the state will be set to idle
        //in either HandleSourceNodeReset or HandleDataPathReset
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::Run() Return engine in resetting state, No processing until engine is in Idle state"));
        return;
    }

    /* Check if ErrorHandling request was made */
    if (!iPendingCmds.empty())
    {
        switch (iPendingCmds.top().GetCmdType())
        {
            case PVP_ENGINE_COMMAND_ERROR_HANDLING_ADD_DATA_SOURCE:
            case PVP_ENGINE_COMMAND_ERROR_HANDLING_INIT:
            case PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE:
            case PVP_ENGINE_COMMAND_ERROR_HANDLING_PAUSE:
            case PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME:
            case PVP_ENGINE_COMMAND_ERROR_HANDLING_SET_PLAYBACK_RANGE:
            case PVP_ENGINE_COMMAND_ERROR_HANDLING_SET_PLAYBACK_RATE:
            case PVP_ENGINE_COMMAND_ERROR_HANDLING_STOP:
            case PVP_ENGINE_COMMAND_ERROR_HANDLING_CANCEL_ALL_COMMANDS:
            case PVP_ENGINE_COMMAND_ERROR_HANDLING_GENERAL:
            {
                // go in error handling right away
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Run() Processing Error Handling request"));
                PVMFStatus retVal = DoErrorHandling();
                if (retVal == PVMFSuccess)
                {
                    iPendingCmds.pop();
                    RunIfNotReady(); // schedule the engine AO to process other commands in queue if any.
                }
                return;
            }

            default:
                break;
        }
    }

    // if current command being processed is reset or cancelAll and
    // Player engine state is idle then remove the data source
    // and do reset/cancelAll command complete
    // OR
    // if current command being processed is prepare, need to call
    // DoPrepare again because of track selection
    // OR
    // for commands SetPlaybackRange, Resume, or Pause that immediately
    // follow a SetPlaybackRange command, we would want to wait till
    // the PVMFInfoStartOfData events are received for all the tracks.
    // So, we donot process the command immediately and get rescheduled.
    if (!iCurrentCmd.empty())
    {
        if ((iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_RESET) ||
                (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_CANCEL_COMMAND) ||
                (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_CANCEL_ALL_COMMANDS))
        {
            if (iState != PVP_ENGINE_STATE_IDLE)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() Engine not in Idle State, asserting"));
                OSCL_ASSERT(false);
            }
            // First destroy all datapaths.
            DoRemoveAllSinks();
            // Remove the datasource
            iRemoveDataSource = true;
            EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), PVMFSuccess);
        }
        else if (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_PREPARE)
        {
            PVMFStatus cmdstatus = DoPrepare(iCurrentCmd[0]);

            if (cmdstatus != PVMFSuccess && cmdstatus != PVMFPending)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() Command failed CmdId %d Status %d",
                                iCurrentCmd[0].GetCmdId(), cmdstatus));
                EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), cmdstatus);
            }
        }
        else if (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_RESUME)
        {
            PVMFStatus cmdstatus = DoResume(iCurrentCmd[0]);

            if (cmdstatus != PVMFSuccess && cmdstatus != PVMFPending)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() Command failed CmdId %d Status %d",
                                iCurrentCmd[0].GetCmdId(), cmdstatus));
                EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), cmdstatus);
            }
        }
        else if (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_SET_PLAYBACK_RANGE)
        {
            PVMFStatus cmdstatus = DoSetPlaybackRange(iCurrentCmd[0]);

            if (cmdstatus != PVMFSuccess && cmdstatus != PVMFPending)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() Command failed CmdId %d Status %d",
                                iCurrentCmd[0].GetCmdId(), cmdstatus));
                EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), cmdstatus);
            }
        }
        else if ((iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_PAUSE)
                 || (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_PAUSE_DUE_TO_SET_PLAYBACK_RANGE)
                 || (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_PAUSE_DUE_TO_ENDTIME_REACHED)
                 || (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_PAUSE_DUE_TO_ENDOFCLIP))
        {
            PVMFStatus cmdstatus = DoPause(iCurrentCmd[0]);

            if (cmdstatus != PVMFSuccess && cmdstatus != PVMFPending)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() Command failed CmdId %d Status %d",
                                iCurrentCmd[0].GetCmdId(), cmdstatus));
                EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), cmdstatus);
            }
        }
    }

    /* Check if Cancel()/CancelAll()/CancelAcquireLicense request was made */
    if (!iPendingCmds.empty())
    {
        if (iPendingCmds.top().GetCmdType() == PVP_ENGINE_COMMAND_CANCEL_COMMAND)
        {
            // Process it right away
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Run() Processing Cancel() request"));
            PVPlayerEngineCommand cmd(iPendingCmds.top());
            iPendingCmds.pop();
            if ((!iCurrentCmd.empty()) && (iCurrentCmd[0].GetCmdId() == cmd.GetParam(0).int32_value))
            {
                // We need to cancel the ongoing command. In this case issue cancelAll
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                                (0, "PVPlayerEngine::Run: Command to Cancel is ongoing so issue CancelAll"));
                DoCancelAllCommands(cmd);
            }
            else
            {
                // The command to be cancelled is in the pending queue
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                                (0, "PVPlayerEngine::Run: Command to Cancel is pending so just Cancel"));
                DoCancelCommand(cmd);
            }
            return;
        }
        else if (iPendingCmds.top().GetCmdType() == PVP_ENGINE_COMMAND_CANCEL_ALL_COMMANDS)
        {
            // Process it right away
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Run() Processing CancelAll() request"));
            PVPlayerEngineCommand cmd(iPendingCmds.top());
            iPendingCmds.pop();
            DoCancelAllCommands(cmd);
            return;
        }
        else if (iPendingCmds.top().GetCmdType() == PVP_ENGINE_COMMAND_CANCEL_ACQUIRE_LICENSE)
        {
            // Process it right away
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Run() Processing CancelAcquireLicesense() request"));
            PVPlayerEngineCommand cmd(iPendingCmds.top());
            iPendingCmds.pop();
            DoCancelAcquireLicense(cmd);
            return;
        }
    }

    if (iRollOverState == RollOverStateStart)
    {
        if (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_INIT)
        {
            //implies that we are doing a source rollover
            PVMFStatus status =
                DoSourceNodeRollOver(iCurrentCmd[0].iCmdId,
                                     iCurrentCmd[0].iContextData);

            if (status != PVMFPending)
            {
                if (CheckForSourceRollOver())
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                    (0, "PVPlayerEngine::Run() DoSourceNodeRollOver Failed, alternate source node for rollover is available"));
                    RunIfNotReady();
                    return;
                }
                // roll over failed
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() DoSourceNodeRollOver Failed, go in error handling"));
                AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_INIT, status, NULL);
                iRollOverState = RollOverStateIdle;
                return;
            }
            else
            {
                iRollOverState = RollOverStateInProgress;
            }
        }
        else
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() Source Roll Over In Progress But Incorrect Engine Cmd"));
            EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), PVMFErrInvalidState);
        }
        return;
    }

    if (iRollOverState == RollOverStateInProgress)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::RunL() Source Roll Over In Progress "));
        return;
    }

    // Handle other requests normally
    if (!iPendingCmds.empty() && iCurrentCmd.empty())
    {
        // Retrieve the first pending command from queue
        PVPlayerEngineCommand cmd(iPendingCmds.top());
        iPendingCmds.pop();

        // Put in on the current command queue
        leavecode = 0;
        OSCL_TRY(leavecode, iCurrentCmd.push_front(cmd));
        OSCL_FIRST_CATCH_ANY(leavecode,
                             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() Command could not be pushed onto iCurrentCmd vector"));
                             EngineCommandCompleted(cmd.GetCmdId(), cmd.GetContext(), PVMFErrNoMemory);
                             return;);

        // Process the command according to the cmd type
        PVMFStatus cmdstatus = PVMFSuccess;
        bool ootsync = false;
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Run() Processing command with type=%d", cmd.GetCmdType()));
        switch (cmd.GetCmdType())
        {
            case PVP_ENGINE_COMMAND_GET_SDK_INFO:
                cmdstatus = DoGetSDKInfo(cmd);
                break;

            case PVP_ENGINE_COMMAND_GET_SDK_MODULE_INFO:
                // GetSDKModuleInfo is currently not supported
                cmdstatus = PVMFErrNotSupported;
                break;

            case PVP_ENGINE_COMMAND_SET_LOG_APPENDER:
                cmdstatus = DoSetLogAppender(cmd);
                break;

            case PVP_ENGINE_COMMAND_REMOVE_LOG_APPENDER:
                cmdstatus = DoRemoveLogAppender(cmd);
                break;

            case PVP_ENGINE_COMMAND_SET_LOG_LEVEL:
                cmdstatus = DoSetLogLevel(cmd);
                break;

            case PVP_ENGINE_COMMAND_GET_LOG_LEVEL:
                cmdstatus = DoGetLogLevel(cmd);
                break;

            case PVP_ENGINE_COMMAND_QUERY_INTERFACE:
                cmdstatus = DoQueryInterface(cmd);
                break;

            case PVP_ENGINE_COMMAND_GET_PVPLAYER_STATE:
                cmdstatus = DoGetPVPlayerState(cmd, false);
                break;

            case PVP_ENGINE_COMMAND_GET_PVPLAYER_STATE_OOTSYNC:
                ootsync = true;
                cmdstatus = DoGetPVPlayerState(cmd, true);
                break;

            case PVP_ENGINE_COMMAND_ADD_DATA_SOURCE:
                cmdstatus = DoAddDataSource(cmd);
                break;

            case PVP_ENGINE_COMMAND_UPDATE_DATA_SOURCE:
                cmdstatus = DoUpdateDataSource(cmd);
                break;

            case PVP_ENGINE_COMMAND_INIT:
                cmdstatus = DoInit(cmd);
                break;

            case PVP_ENGINE_COMMAND_GET_METADATA_KEY:
                cmdstatus = DoGetMetadataKey(cmd);
                break;

            case PVP_ENGINE_COMMAND_GET_METADATA_VALUE:
                cmdstatus = DoGetMetadataValue(cmd);
                break;

            case PVP_ENGINE_COMMAND_RELEASE_METADATA_VALUE:
                cmdstatus = DoReleaseMetadataValues(cmd);
                break;

            case PVP_ENGINE_COMMAND_ADD_DATA_SINK:
                cmdstatus = DoAddDataSink(cmd);
                break;

            case PVP_ENGINE_COMMAND_GET_CURRENT_POSITION:
                cmdstatus = DoGetCurrentPosition(cmd, false);
                break;

            case PVP_ENGINE_COMMAND_GET_CURRENT_POSITION_OOTSYNC:
                ootsync = true;
                cmdstatus = DoGetCurrentPosition(cmd, true);
                break;

            case PVP_ENGINE_COMMAND_SET_PLAYBACK_RANGE:
                cmdstatus = DoSetPlaybackRange(cmd);
                break;

            case PVP_ENGINE_COMMAND_GET_PLAYBACK_RANGE:
                cmdstatus = DoGetPlaybackRange(cmd);
                break;

            case PVP_ENGINE_COMMAND_SET_PLAYBACK_RATE:
                cmdstatus = DoSetPlaybackRate(cmd);
                break;

            case PVP_ENGINE_COMMAND_GET_PLAYBACK_RATE:
                cmdstatus = DoGetPlaybackRate(cmd);
                break;

            case PVP_ENGINE_COMMAND_GET_PLAYBACK_MINMAX_RATE:
                cmdstatus = DoGetPlaybackMinMaxRate(cmd);
                break;

            case PVP_ENGINE_COMMAND_PREPARE:
                cmdstatus = DoPrepare(cmd);
                break;

            case PVP_ENGINE_COMMAND_START:
                cmdstatus = DoStart(cmd);
                break;

            case PVP_ENGINE_COMMAND_PAUSE:
            case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_ENDOFCLIP:
            case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_ENDTIME_REACHED:
            case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_SET_PLAYBACK_RANGE:
                cmdstatus = DoPause(cmd);
                break;

            case PVP_ENGINE_COMMAND_RESUME:
                cmdstatus = DoResume(cmd);
                break;

            case PVP_ENGINE_COMMAND_STOP:
                cmdstatus = DoStop(cmd);
                break;

            case PVP_ENGINE_COMMAND_REMOVE_DATA_SINK:
                cmdstatus = DoRemoveDataSink(cmd);
                break;

            case PVP_ENGINE_COMMAND_RESET:
                cmdstatus = DoReset(cmd);
                break;

            case PVP_ENGINE_COMMAND_REMOVE_DATA_SOURCE:
                cmdstatus = DoRemoveDataSource(cmd);
                break;

            case PVP_ENGINE_COMMAND_CAPCONFIG_SET_PARAMETERS:
                cmdstatus = DoCapConfigSetParameters(cmd, false);
                break;

            case PVP_ENGINE_COMMAND_CAPCONFIG_SET_PARAMETERS_OOTSYNC:
                ootsync = true;
                cmdstatus = DoCapConfigSetParameters(cmd, true);
                break;

            case PVP_ENGINE_COMMAND_CAPCONFIG_GET_PARAMETERS_OOTSYNC:
                ootsync = true;
                cmdstatus = DoGetParametersSync(cmd);
                break;

            case PVP_ENGINE_COMMAND_CAPCONFIG_RELEASE_PARAMETERS_OOTSYNC:
                ootsync = true;
                cmdstatus = DoReleaseParametersSync(cmd);
                break;

            case PVP_ENGINE_COMMAND_CAPCONFIG_VERIFY_PARAMETERS_OOTSYNC:
                ootsync = true;
                cmdstatus = DoVerifyParametersSync(cmd);
                break;

            case PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_WCHAR:
            case PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_CHAR:
                cmdstatus = DoAcquireLicense(cmd);
                break;

            case PVP_ENGINE_COMMAND_JOIN_DOMAIN:
                cmdstatus = DoJoinDomain(cmd);
                break;

            case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_BUFFER_UNDERFLOW:
                cmdstatus = DoSourceUnderflowAutoPause(cmd);
                break;

            case PVP_ENGINE_COMMAND_RESUME_DUE_TO_BUFFER_DATAREADY:
                cmdstatus = DoSourceDataReadyAutoResume(cmd);
                break;

            case PVP_ENGINE_COMMAND_CAPCONFIG_SET_OBSERVER_OOTSYNC:
                ootsync = true;
                cmdstatus = DoSetObserverSync(cmd);
                break;

            case PVP_ENGINE_COMMAND_GET_LICENSE_STATUS_OOTSYNC:
                ootsync = true;
                cmdstatus = DoGetLicenseStatusSync(cmd);
                break;

            case PVP_ENGINE_COMMAND_CANCEL_COMMAND:
                // Cancel() should not be handled here
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() CancelCommand should be not handled in here. Return Failure"));
                cmdstatus = PVMFFailure;
                break;

            case PVP_ENGINE_COMMAND_CANCEL_ALL_COMMANDS:
                // CancelAll() should not be handled here
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() CancelAllCommands should be not handled in here. Return Failure"));
                cmdstatus = PVMFFailure;
                break;

            default:
                // Just handle as "not supported"
                cmdstatus = PVMFErrNotSupported;
                break;
        }

        if (ootsync)
        {
            OOTSyncCommandComplete(cmd, cmdstatus);
            // Empty out the current cmd vector and set active if there are other pending commands
            iCurrentCmd.erase(iCurrentCmd.begin());
            if (!iPendingCmds.empty())
            {
                RunIfNotReady();
            }
        }
        else if (cmdstatus != PVMFSuccess && cmdstatus != PVMFPending)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() Command failed CmdId %d Status %d",
                            cmd.GetCmdId(), cmdstatus));
            EngineCommandCompleted(cmd.GetCmdId(), cmd.GetContext(), cmdstatus);
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Run() Out"));
}

bool PVPlayerEngine::FindNodeTypeByNode(PVMFNodeInterface* aUnknownNode, PVPlayerNodeType& aNodeType, int32& aDatapathListIndex)
{
    if (aUnknownNode == NULL)
    {
        // Cannot check with node pointer being NULL
        // Might bring up false positives
        aNodeType = PVP_NODETYPE_UNKNOWN;
        aDatapathListIndex = -1;
        return false;
    }

    // Go through each engine datapath and find whether
    // the specified node is a dec node or sink node
    for (uint32 i = 0; i < iDatapathList.size(); ++i)
    {
        if (iDatapathList[i].iDecNode == aUnknownNode)
        {
            aNodeType = PVP_NODETYPE_DECODER;
            aDatapathListIndex = i;
            return true;
        }
        else if (iDatapathList[i].iSinkNode == aUnknownNode)
        {
            aNodeType = PVP_NODETYPE_SINK;
            aDatapathListIndex = i;
            return true;
        }
    }

    // Could not determine the types
    aNodeType = PVP_NODETYPE_UNKNOWN;
    aDatapathListIndex = -1;
    return false;
}

bool PVPlayerEngine::FindTrackForDatapathUsingMimeString(bool& aVideoTrack, bool& aAudioTrack, bool& aTextTrack, PVPlayerEngineDatapath* aDatapath)
{
    if (aDatapath->iTrackInfo)
    {
        char* mimeString = aDatapath->iTrackInfo->getTrackMimeType().get_str();

        if ((pv_mime_strcmp(mimeString, PVMF_MIME_YUV420) == 0) ||
                (pv_mime_strcmp(mimeString, PVMF_MIME_YUV422) == 0) ||
                (pv_mime_strcmp(mimeString, PVMF_MIME_RGB8) == 0) ||
                (pv_mime_strcmp(mimeString, PVMF_MIME_RGB12) == 0) ||
                (pv_mime_strcmp(mimeString, PVMF_MIME_RGB16) == 0) ||
                (pv_mime_strcmp(mimeString, PVMF_MIME_RGB24) == 0) ||
                (pv_mime_strcmp(mimeString, PVMF_MIME_M4V) == 0) ||
                (pv_mime_strcmp(mimeString, PVMF_MIME_H2631998) == 0) ||
                (pv_mime_strcmp(mimeString, PVMF_MIME_H2632000) == 0) ||
                (pv_mime_strcmp(mimeString, PVMF_MIME_H264_VIDEO_RAW) == 0) ||
                (pv_mime_strcmp(mimeString, PVMF_MIME_H264_VIDEO_MP4) == 0) ||
                (pv_mime_strcmp(mimeString, PVMF_MIME_H264_VIDEO) == 0) ||
                (pv_mime_strcmp(mimeString, PVMF_MIME_WMV) == 0) ||
                (pv_mime_strcmp(mimeString, PVMF_MIME_REAL_VIDEO) == 0))
        {
            aVideoTrack = true;
            aAudioTrack = false;
            aTextTrack = false;
            return true;
        }
        else if (pv_mime_strcmp(mimeString, PVMF_MIME_3GPP_TIMEDTEXT) == 0)
        {
            aVideoTrack = false;
            aAudioTrack = false;
            aTextTrack = true;
            return true;
        }
        else if ((pv_mime_strcmp(mimeString, PVMF_MIME_PCM) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_PCM8) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_PCM16) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_PCM16_BE) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_ULAW) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_ALAW) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_AMR) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_AMRWB) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_AMR_IETF) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_AMRWB_IETF) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_AMR_IF2) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_EVRC) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_MP3) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_ADIF) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_ADTS) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_LATM) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_MPEG4_AUDIO) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_G723) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_G726) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_WMA) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_ASF_AMR) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_REAL_AUDIO) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_ASF_MPEG4_AUDIO) == 0) ||
                 (pv_mime_strcmp(mimeString, PVMF_MIME_3640) == 0))
        {
            aVideoTrack = false;
            aAudioTrack = true;
            aTextTrack = false;
            return true;
        }
    }

    aVideoTrack = false;
    aAudioTrack = false;
    aTextTrack = false;
    return false;
}

bool PVPlayerEngine::FindDatapathForTrackUsingMimeString(bool aVideoTrack, bool aAudioTrack, bool aTextTrack, int32& aDatapathListIndex)
{
    for (uint32 i = 0; i < iDatapathList.size(); i++)
    {
        if (iDatapathList[i].iTrackInfo)
        {
            char* mimeString = iDatapathList[i].iTrackInfo->getTrackMimeType().get_str();
            if (aVideoTrack)
            {
                // find a datapath using the mime string for Video track
                if ((pv_mime_strcmp(mimeString, PVMF_MIME_YUV420) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_YUV422) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_RGB8) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_RGB12) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_RGB16) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_RGB24) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_M4V) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_H2631998) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_H2632000) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_H264_VIDEO_RAW) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_H264_VIDEO_MP4) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_H264_VIDEO) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_WMV) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_REAL_VIDEO) == 0))
                {
                    aDatapathListIndex = i;
                    return true;
                }
            }
            else if (aAudioTrack)
            {
                // find a datapath using the mime string for Audio track
                if ((pv_mime_strcmp(mimeString, PVMF_MIME_PCM) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_PCM8) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_PCM16) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_PCM16_BE) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_ULAW) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_ALAW) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_AMR) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_AMRWB) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_AMR_IETF) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_AMRWB_IETF) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_AMR_IF2) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_EVRC) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_MP3) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_ADIF) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_ADTS) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_LATM) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_MPEG4_AUDIO) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_G723) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_G726) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_WMA) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_ASF_AMR) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_REAL_AUDIO) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_ASF_MPEG4_AUDIO) == 0) ||
                        (pv_mime_strcmp(mimeString, PVMF_MIME_3640) == 0))
                {
                    aDatapathListIndex = i;
                    return true;
                }
            }
            else if (aTextTrack)
            {
                // find a datapath using the mime string for Text track
                if (pv_mime_strcmp(mimeString, PVMF_MIME_3GPP_TIMEDTEXT) == 0)
                {
                    aDatapathListIndex = i;
                    return true;
                }
            }
            else
            {
                break;
            }
        }
    }

    // Unknown track
    aDatapathListIndex = -1;
    return false;
}


void PVPlayerEngine::NodeCommandCompleted(const PVMFCmdResp& aResponse)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::NodeCommandCompleted() In"));

    int32 leavecode = 0;

    // Check if a cancel command completed
    uint32* context_uint32 = (uint32*)(aResponse.GetContext());
    if (context_uint32 == &iNumberCancelCmdPending)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                        (0, "PVPlayerEngine::NodeCommandCompleted() Cancel in node completed for cancel command. Pending %d", iNumberCancelCmdPending));
        --iNumberCancelCmdPending;

        // If cmd to cancel was GetMetadataKeys() or GetMetadataValues() and if these commands return with
        // success then first release the memory for the node which return with success.
        if (iCmdToCancel[0].GetCmdType() == PVP_ENGINE_COMMAND_GET_METADATA_KEY &&
                aResponse.GetCmdStatus() == PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                            (0, "PVPlayerEngine::NodeCommandCompleted() Cancel in node completed for GetMetadataKeys with success, release memory."));
            // Release the memory allocated for the metadata keys
            uint32 numkeysadded = iGetMetadataKeysParam.iKeyList->size() - iGetMetadataKeysParam.iNumKeyEntriesInList;
            uint32 start = iGetMetadataKeysParam.iNumKeyEntriesInList;
            uint32 end = iGetMetadataKeysParam.iNumKeyEntriesInList + numkeysadded - 1;

            PVMFMetadataExtensionInterface* mdif = iMetadataIFList[iGetMetadataKeysParam.iCurrentInterfaceIndex].iInterface;
            OSCL_ASSERT(mdif != NULL);
            mdif->ReleaseNodeMetadataKeys(*(iGetMetadataKeysParam.iKeyList), start, end);
        }
        else if (iCmdToCancel[0].GetCmdType() == PVP_ENGINE_COMMAND_GET_METADATA_VALUE &&
                 aResponse.GetCmdStatus() == PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                            (0, "PVPlayerEngine::NodeCommandCompleted() Cancel in node completed for GetMetadataValue with success, release memory."));
            // Release the memory allocated for the metadata values
            uint32 numkeysadded = iGetMetadataValuesParam.iKeyList->size() - iGetMetadataValuesParam.iNumValueEntriesInList;
            uint32 start = iGetMetadataValuesParam.iNumValueEntriesInList;
            uint32 end = iGetMetadataValuesParam.iNumValueEntriesInList + numkeysadded - 1;

            PVMFMetadataExtensionInterface* mdif = iMetadataIFList[iGetMetadataValuesParam.iCurrentInterfaceIndex].iInterface;
            OSCL_ASSERT(mdif != NULL);
            mdif->ReleaseNodeMetadataValues(*(iGetMetadataValuesParam.iValueList), start, end);

            iReleaseMetadataValuesPending = false;
        }

        if (iNumberCancelCmdPending == 0)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                            (0, "PVPlayerEngine::NodeCommandCompleted() Cancelling of all node/datapath commands complete, now reset all nodes"));
            // Clear the CancelCmd queue as the cmd has been cancelled.
            iCmdToCancel.clear();

            DereferenceLicenseInterface();
            RemoveDatapathContextFromList(); // empty left over contexts from cancelled datapath commands
            // Now reset the source node
            PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, -1, NULL, -1);

            PVMFCommandId cmdid = -1;
            int32 leavecode = 0;
            OSCL_TRY(leavecode, cmdid = iSourceNode->Reset(iSourceNodeSessionId, (OsclAny*)context));
            OSCL_FIRST_CATCH_ANY(leavecode,
                                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::NodeCommandCompleted() Reset on iSourceNode did a leave!"));
                                 FreeEngineContext(context);
                                 OSCL_ASSERT(false);
                                 return);

            SetEngineState(PVP_ENGINE_STATE_RESETTING);
        }
        return;
    }

    PVPlayerEngineContext* nodecontext = (PVPlayerEngineContext*)(aResponse.GetContext());
    OSCL_ASSERT(nodecontext);

    // Ignore other node completion if cancelling
    if (!iCmdToCancel.empty() || (CheckForPendingErrorHandlingCmd() && aResponse.GetCmdStatus() == PVMFErrCancelled))
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                        (0, "PVPlayerEngine::NodeCommandCompleted() Node command completion ignored due to cancel process, id=%d", aResponse.GetCmdId()));
        // Remove the context from the list
        FreeEngineContext(nodecontext);
        return;
    }

    // Process according to cmd type in the engine context data, node type, or engine state
    if (nodecontext->iCmdType == PVP_CMD_SinkNodeSkipMediaData)
    {
        HandleSinkNodeSkipMediaData(*nodecontext, aResponse);
    }
    else if (nodecontext->iCmdType == PVP_CMD_SinkNodeSkipMediaDataDuringPlayback)
    {
        HandleSinkNodeSkipMediaDataDuringPlayback(*nodecontext, aResponse);
    }
    else if (nodecontext->iCmdType == PVP_CMD_SinkNodeAutoPause)
    {
        HandleSinkNodePause(*nodecontext, aResponse);
    }
    else if (nodecontext->iCmdType == PVP_CMD_SinkNodeAutoResume)
    {
        HandleSinkNodeResume(*nodecontext, aResponse);
    }
    else if (nodecontext->iCmdType == PVP_CMD_DecNodeReset)
    {
        HandleDecNodeReset(*nodecontext, aResponse);
    }
    else if (nodecontext->iCmdType == PVP_CMD_SinkNodeReset)
    {
        HandleSinkNodeReset(*nodecontext, aResponse);
    }
    else if (nodecontext->iCmdType == PVP_CMD_GetNodeMetadataKey)
    {
        // Ignore the command status since it does not matter and continue going through the metadata interface list

        // Determine the number of keys were added
        uint32 numkeysadded = iGetMetadataKeysParam.iKeyList->size() - iGetMetadataKeysParam.iNumKeyEntriesInList;
        if (numkeysadded > 0)
        {
            // Create an entry for the metadata key release list
            PVPlayerEngineMetadataReleaseEntry releaseentry;
            releaseentry.iMetadataIFListIndex = iGetMetadataKeysParam.iCurrentInterfaceIndex;
            // Save the start and end indices into the key list for keys that this node added
            releaseentry.iStartIndex = iGetMetadataKeysParam.iNumKeyEntriesInList;
            releaseentry.iEndIndex = iGetMetadataKeysParam.iNumKeyEntriesInList + numkeysadded - 1;

            leavecode = 0;
            OSCL_TRY(leavecode, iMetadataKeyReleaseList.push_back(releaseentry));
            if (leavecode != 0)
            {
                // An element could not be added to the release list vector
                // so notify completion of GetMetadataKey() command with memory failure
                EngineCommandCompleted(nodecontext->iCmdId, (OsclAny*)nodecontext->iCmdContext, PVMFErrNoMemory);

                // Release the last requested keys
                PVMFMetadataExtensionInterface* mdif = iMetadataIFList[releaseentry.iMetadataIFListIndex].iInterface;
                OSCL_ASSERT(mdif != NULL);
                mdif->ReleaseNodeMetadataKeys(*(iGetMetadataKeysParam.iKeyList), releaseentry.iStartIndex, releaseentry.iEndIndex);

                // Release the memory allocated for rest of the metadata keys
                while (iMetadataKeyReleaseList.empty() == false)
                {
                    mdif = iMetadataIFList[iMetadataKeyReleaseList[0].iMetadataIFListIndex].iInterface;
                    OSCL_ASSERT(mdif != NULL);
                    mdif->ReleaseNodeMetadataKeys(*(iGetMetadataKeysParam.iKeyList), iMetadataKeyReleaseList[0].iStartIndex, iMetadataKeyReleaseList[0].iEndIndex);
                    iMetadataKeyReleaseList.erase(iMetadataKeyReleaseList.begin());
                }

                // Remove the context from the list
                // Need to do this since we're calling return from here
                FreeEngineContext(nodecontext);
                return;
            }

            // Update the variables tracking the key list
            if (iGetMetadataKeysParam.iNumKeyEntriesToFill != -1)
            {
                iGetMetadataKeysParam.iNumKeyEntriesToFill -= numkeysadded;
            }
            iGetMetadataKeysParam.iNumKeyEntriesInList += numkeysadded;
        }

        // Update the interface index to the next one
        ++iGetMetadataKeysParam.iCurrentInterfaceIndex;

        // Loop until GetNodeMetadataKeys() is called or command is completed
        bool endloop = false;
        while (endloop == false)
        {
            // Check if there is another metadata interface to check
            if (iGetMetadataKeysParam.iCurrentInterfaceIndex < iMetadataIFList.size())
            {
                PVMFMetadataExtensionInterface* mdif = iMetadataIFList[iGetMetadataKeysParam.iCurrentInterfaceIndex].iInterface;
                OSCL_ASSERT(mdif != NULL);
                PVMFSessionId sessionid = iMetadataIFList[iGetMetadataKeysParam.iCurrentInterfaceIndex].iSessionId;

                // Determine the number of keys available for the specified query key
                int32 numkeys = mdif->GetNumMetadataKeys(iGetMetadataKeysParam.iQueryKey);
                if (numkeys <= 0)
                {
                    // Since there is no keys from this node, go to the next one
                    ++iGetMetadataKeysParam.iCurrentInterfaceIndex;
                    continue;
                }

                // If more key entries can be added, retrieve from the node
                if (iGetMetadataKeysParam.iNumKeyEntriesToFill > 0 || iGetMetadataKeysParam.iNumKeyEntriesToFill == -1)
                {
                    int32 leavecode = 0;
                    PVMFCommandId cmdid = -1;
                    PVPlayerEngineContext* newcontext = AllocateEngineContext(iMetadataIFList[iGetMetadataKeysParam.iCurrentInterfaceIndex].iEngineDatapath,
                                                        iMetadataIFList[iGetMetadataKeysParam.iCurrentInterfaceIndex].iNode,
                                                        NULL, nodecontext->iCmdId, nodecontext->iCmdContext, PVP_CMD_GetNodeMetadataKey);
                    OSCL_TRY(leavecode, cmdid = mdif->GetNodeMetadataKeys(sessionid,
                                                *(iGetMetadataKeysParam.iKeyList),
                                                0,
                                                iGetMetadataKeysParam.iNumKeyEntriesToFill,
                                                iGetMetadataKeysParam.iQueryKey,
                                                (OsclAny*)newcontext));
                    OSCL_FIRST_CATCH_ANY(leavecode,
                                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::NodeCommandCompleted() GetNodeMetadataKeys on a node did a leave!"));
                                         FreeEngineContext(newcontext);
                                         // Go to the next metadata IF in the list and continue
                                         ++iGetMetadataKeysParam.iCurrentInterfaceIndex;
                                         continue;);

                    // End the loop since GetNodeMetadataKeys() was called
                    endloop = true;
                }
                else
                {
                    // Retrieved the requested number of keys so notify completion of GetMetadataKey() command
                    EngineCommandCompleted(nodecontext->iCmdId, (OsclAny*)nodecontext->iCmdContext, aResponse.GetCmdStatus());

                    // Release the memory allocated for the metadata keys
                    while (iMetadataKeyReleaseList.empty() == false)
                    {
                        mdif = iMetadataIFList[iMetadataKeyReleaseList[0].iMetadataIFListIndex].iInterface;
                        OSCL_ASSERT(mdif != NULL);
                        mdif->ReleaseNodeMetadataKeys(*(iGetMetadataKeysParam.iKeyList), iMetadataKeyReleaseList[0].iStartIndex, iMetadataKeyReleaseList[0].iEndIndex);
                        iMetadataKeyReleaseList.erase(iMetadataKeyReleaseList.begin());
                    }

                    // End the loop since finished command
                    endloop = true;
                }
            }
            else
            {
                // No more so notify completion of GetMetadataKey() command
                EngineCommandCompleted(nodecontext->iCmdId, (OsclAny*)nodecontext->iCmdContext, aResponse.GetCmdStatus());

                // Release the memory allocated for the metadata keys
                while (iMetadataKeyReleaseList.empty() == false)
                {
                    PVMFMetadataExtensionInterface* mdif = iMetadataIFList[iMetadataKeyReleaseList[0].iMetadataIFListIndex].iInterface;
                    OSCL_ASSERT(mdif != NULL);
                    mdif->ReleaseNodeMetadataKeys(*(iGetMetadataKeysParam.iKeyList), iMetadataKeyReleaseList[0].iStartIndex, iMetadataKeyReleaseList[0].iEndIndex);
                    iMetadataKeyReleaseList.erase(iMetadataKeyReleaseList.begin());
                }

                // End the loop since reached the end of the metadata IF list
                endloop = true;
            }
        }
    }
    else if (nodecontext->iCmdType == PVP_CMD_GetNodeMetadataValue)
    {
        // Ignore the command status since it does not matter and continue going through the metadata interface list

        // Determine the number of values were added
        uint32 numvaluesadded = iGetMetadataValuesParam.iValueList->size() - iGetMetadataValuesParam.iNumValueEntriesInList;
        if (numvaluesadded > 0)
        {
            // Create an entry for the metadata value release list
            PVPlayerEngineMetadataReleaseEntry releaseentry;
            releaseentry.iMetadataIFListIndex = iGetMetadataValuesParam.iCurrentInterfaceIndex;
            // Save the start and end indices into the value list for values that this node added
            releaseentry.iStartIndex = iGetMetadataValuesParam.iNumValueEntriesInList;
            releaseentry.iEndIndex = iGetMetadataValuesParam.iNumValueEntriesInList + numvaluesadded - 1;

            leavecode = 0;
            OSCL_TRY(leavecode, iMetadataValueReleaseList.push_back(releaseentry));
            if (leavecode != 0)
            {
                // An element could not be added to the release list vector
                // so notify completion of GetMetadataValue() command with memory failure
                EngineCommandCompleted(nodecontext->iCmdId, (OsclAny*)nodecontext->iCmdContext, PVMFErrNoMemory);

                // Release the last requested values
                PVMFMetadataExtensionInterface* mdif = iMetadataIFList[releaseentry.iMetadataIFListIndex].iInterface;
                OSCL_ASSERT(mdif != NULL);
                mdif->ReleaseNodeMetadataValues(*(iGetMetadataValuesParam.iValueList), releaseentry.iStartIndex, releaseentry.iEndIndex);

                // Release the memory allocated for rest of the metadata values
                while (iMetadataValueReleaseList.empty() == false)
                {
                    mdif = iMetadataIFList[iMetadataValueReleaseList[0].iMetadataIFListIndex].iInterface;
                    OSCL_ASSERT(mdif != NULL);
                    mdif->ReleaseNodeMetadataValues(*(iGetMetadataValuesParam.iValueList), iMetadataValueReleaseList[0].iStartIndex, iMetadataValueReleaseList[0].iEndIndex);
                    iMetadataValueReleaseList.erase(iMetadataValueReleaseList.begin());
                }

                // Remove the context from the list
                // Need to do this since we're calling return from here
                FreeEngineContext(nodecontext);
                return;
            }

            // Update the variables tracking the value list
            if (iGetMetadataValuesParam.iNumValueEntriesToFill != -1)
            {
                iGetMetadataValuesParam.iNumValueEntriesToFill -= numvaluesadded;
            }
            iGetMetadataValuesParam.iNumValueEntriesInList += numvaluesadded;
        }

        // Update the interface index to the next one
        ++iGetMetadataValuesParam.iCurrentInterfaceIndex;

        // Loop until GetNodeMetadataValues() is called or command is completed
        bool endloop = false;
        while (endloop == false)
        {
            // Check if there is another metadata interface to check
            if (iGetMetadataValuesParam.iCurrentInterfaceIndex < iMetadataIFList.size())
            {
                PVMFMetadataExtensionInterface* mdif = iMetadataIFList[iGetMetadataValuesParam.iCurrentInterfaceIndex].iInterface;
                OSCL_ASSERT(mdif != NULL);
                PVMFSessionId sessionid = iMetadataIFList[iGetMetadataValuesParam.iCurrentInterfaceIndex].iSessionId;

                // Determine the number of values available for the specified key list
                int32 numvalues = mdif->GetNumMetadataValues(*(iGetMetadataValuesParam.iKeyList));
                if (numvalues > 0)
                {
                    // Add it to the total available
                    *(iGetMetadataValuesParam.iNumAvailableValues) += numvalues;
                }
                else
                {
                    // Since there is no values from this node, go to the next one
                    ++iGetMetadataValuesParam.iCurrentInterfaceIndex;
                    continue;
                }

                // If more value entries can be added, retrieve from the node
                if (iGetMetadataValuesParam.iNumValueEntriesToFill > 0 || iGetMetadataValuesParam.iNumValueEntriesToFill == -1)
                {
                    int32 leavecode = 0;
                    PVMFCommandId cmdid = -1;
                    PVPlayerEngineContext* newcontext = AllocateEngineContext(iMetadataIFList[iGetMetadataValuesParam.iCurrentInterfaceIndex].iEngineDatapath,
                                                        iMetadataIFList[iGetMetadataValuesParam.iCurrentInterfaceIndex].iNode,
                                                        NULL, nodecontext->iCmdId, nodecontext->iCmdContext, PVP_CMD_GetNodeMetadataValue);
                    OSCL_TRY(leavecode, cmdid = mdif->GetNodeMetadataValues(sessionid,
                                                *(iGetMetadataValuesParam.iKeyList),
                                                *(iGetMetadataValuesParam.iValueList),
                                                0,
                                                iGetMetadataValuesParam.iNumValueEntriesToFill,
                                                (OsclAny*)newcontext));
                    OSCL_FIRST_CATCH_ANY(leavecode,
                                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::NodeCommandCompleted() GetNodeMetadataValues on a node did a leave!"));
                                         FreeEngineContext(newcontext);
                                         // Go to the next metadata IF in the list and continue
                                         ++iGetMetadataValuesParam.iCurrentInterfaceIndex;
                                         continue;);

                    // End the loop since GetNodeMetadataValues() was called
                    endloop = true;
                }
                else
                {
                    // Retrieved requested number of values so notify completion of GetMetadataValue() command
                    EngineCommandCompleted(nodecontext->iCmdId, (OsclAny*)nodecontext->iCmdContext, aResponse.GetCmdStatus());

                    if (iMetadataValuesCopiedInCallBack)
                    {
                        // Release the memory allocated for the metadata values
                        while (iMetadataValueReleaseList.empty() == false)
                        {
                            mdif = iMetadataIFList[iMetadataValueReleaseList[0].iMetadataIFListIndex].iInterface;
                            OSCL_ASSERT(mdif != NULL);
                            mdif->ReleaseNodeMetadataValues(*(iGetMetadataValuesParam.iValueList),
                                                            iMetadataValueReleaseList[0].iStartIndex,
                                                            iMetadataValueReleaseList[0].iEndIndex);
                            iMetadataValueReleaseList.erase(iMetadataValueReleaseList.begin());
                        }
                    }
                    else
                    {
                        iReleaseMetadataValuesPending = true;
                    }

                    // End the loop since finished command
                    endloop = true;
                }
            }
            else
            {
                // No more so notify completion of GetMetadataValue() command
                EngineCommandCompleted(nodecontext->iCmdId, (OsclAny*)nodecontext->iCmdContext, aResponse.GetCmdStatus());

                if (iMetadataValuesCopiedInCallBack)
                {
                    // Release the memory allocated for the metadata values
                    while (iMetadataValueReleaseList.empty() == false)
                    {
                        PVMFMetadataExtensionInterface* mdif = iMetadataIFList[iMetadataValueReleaseList[0].iMetadataIFListIndex].iInterface;
                        OSCL_ASSERT(mdif != NULL);
                        mdif->ReleaseNodeMetadataValues(*(iGetMetadataValuesParam.iValueList),
                                                        iMetadataValueReleaseList[0].iStartIndex,
                                                        iMetadataValueReleaseList[0].iEndIndex);
                        iMetadataValueReleaseList.erase(iMetadataValueReleaseList.begin());
                    }
                }
                else
                {
                    iReleaseMetadataValuesPending = true;
                }

                // End the loop since reached the end of the metadata IF list
                endloop = true;
            }
        }
    }
    else if (nodecontext->iNode == iSourceNode)
    {
        if (nodecontext->iCmdType == PVP_CMD_SourceNodeQueryDataSourcePositionDuringPlayback)
        {
            HandleSourceNodeQueryDataSourcePositionDuringPlayback(*nodecontext, aResponse);
        }
        else if (nodecontext->iCmdType == PVP_CMD_SourceNodeSetDataSourcePositionDuringPlayback)
        {
            HandleSourceNodeSetDataSourcePositionDuringPlayback(*nodecontext, aResponse);
        }
        else if (nodecontext->iCmdType == PVP_CMD_SourceNodeSetDataSourceDirection)
        {
            HandleSourceNodeSetDataSourceDirection(*nodecontext, aResponse);
        }
        else if (nodecontext->iCmdType == PVP_CMD_SourceNodeSetDataSourceRate)
        {
            HandleSourceNodeSetDataSourceRate(*nodecontext, aResponse);
        }
        else if (nodecontext->iCmdType == PVP_CMD_SourceNodeQueryCPMLicenseIF)
        {
            HandleSourceNodeQueryCPMLicenseInterface(*nodecontext, aResponse);
        }
        else
        {
            switch (iState)
            {
                case PVP_ENGINE_STATE_IDLE:
                    switch (nodecontext->iCmdType)
                    {
                        case PVP_CMD_SourceNodeQueryInitIF:
                            HandleSourceNodeQueryInitIF(*nodecontext, aResponse);
                            break;

                        case PVP_CMD_SourceNodeQueryTrackSelIF:
                            HandleSourceNodeQueryTrackSelIF(*nodecontext, aResponse);
                            break;

                        case PVP_CMD_SourceNodeQueryTrackLevelInfoIF:
                        case PVP_CMD_SourceNodeQueryPBCtrlIF:
                        case PVP_CMD_SourceNodeQueryDirCtrlIF:
                        case PVP_CMD_SourceNodeQueryMetadataIF:
                        case PVP_CMD_SourceNodeQueryCapConfigIF:
                        case PVP_CMD_SourceNodeQuerySrcNodeRegInitIF:
                            HandleSourceNodeQueryInterfaceOptional(*nodecontext, aResponse);
                            break;

                        default:
                            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                            (0, "PVPlayerEngine::NodeCommandCompleted() Invalid source node command type in PVP_ENGINE_STATE_IDLE. Asserting"));
                            OSCL_ASSERT(false);
                            break;
                    }
                    break;

                case PVP_ENGINE_STATE_INITIALIZING:
                    switch (nodecontext->iCmdType)
                    {
                        case PVP_CMD_SourceNodeInit:
                            HandleSourceNodeInit(*nodecontext, aResponse);
                            break;

                        case PVP_CMD_SourceNodeGetDurationValue:
                            HandleSourceNodeGetDurationValue(*nodecontext, aResponse);
                            break;

                        default:
                            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                            (0, "PVPlayerEngine::NodeCommandCompleted() Invalid source node command type in PVP_ENGINE_STATE_INITIALIZING. Asserting"));
                            OSCL_ASSERT(false);
                            break;
                    }
                    break;

                case PVP_ENGINE_STATE_PREPARING:
                    switch (nodecontext->iCmdType)
                    {
                        case PVP_CMD_SourceNodePrepare:
                            HandleSourceNodePrepare(*nodecontext, aResponse);
                            break;

                        case PVP_CMD_SourceNodeQueryDataSourcePosition:
                            HandleSourceNodeQueryDataSourcePosition(*nodecontext, aResponse);
                            break;

                        case PVP_CMD_SourceNodeSetDataSourcePosition:
                            HandleSourceNodeSetDataSourcePosition(*nodecontext, aResponse);
                            break;

                        case PVP_CMD_SourceNodeSetDataSourceDirection:
                            //currently not allowed
                            break;

                        case PVP_CMD_SourceNodeStart:
                            HandleSourceNodeStart(*nodecontext, aResponse);
                            break;

                        default:
                            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                            (0, "PVPlayerEngine::NodeCommandCompleted() Invalid source node command type in PVP_ENGINE_STATE_PREPARING. Asserting"));
                            OSCL_ASSERT(false);
                            break;
                    }
                    break;

                case PVP_ENGINE_STATE_PAUSING:
                    HandleSourceNodePause(*nodecontext, aResponse);
                    break;

                case PVP_ENGINE_STATE_RESUMING:
                    switch (nodecontext->iCmdType)
                    {
                        case PVP_CMD_SourceNodeStart:
                            HandleSourceNodeStart(*nodecontext, aResponse);
                            break;

                        case PVP_CMD_SourceNodeQueryDataSourcePosition:
                            HandleSourceNodeQueryDataSourcePosition(*nodecontext, aResponse);
                            break;

                        case PVP_CMD_SourceNodeSetDataSourcePosition:
                            HandleSourceNodeSetDataSourcePosition(*nodecontext, aResponse);
                            break;

                        case PVP_CMD_SourceNodeSetDataSourceDirection:
                            HandleSourceNodeSetDataSourceDirection(*nodecontext, aResponse);
                            break;

                        case PVP_CMD_SourceNodePause:
                            // There is no handling required here.
                            // We would reach here in case of Pause -- SetPlaybackRange -- Resume.
                            // If Resume is called before source node pause completes, then we would
                            // reach here.
                            break;

                        default:
                            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                            (0, "PVPlayerEngine::NodeCommandCompleted() Invalid source node command type in PVP_ENGINE_STATE_RESUMING. Asserting"));
                            OSCL_ASSERT(false);
                            break;
                    }
                    break;

                case PVP_ENGINE_STATE_PAUSED:
                    switch (nodecontext->iCmdType)
                    {
                        case PVP_CMD_SourceNodeStart:
                            HandleSourceNodeStart(*nodecontext, aResponse);
                            break;

                        case PVP_CMD_SourceNodePause:
                            HandleSourceNodePause(*nodecontext, aResponse);
                            break;

                        default:
                            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                            (0, "PVPlayerEngine::NodeCommandCompleted() Invalid source node command type in PVP_ENGINE_STATE_PAUSED. Asserting"));
                            OSCL_ASSERT(false);
                            break;
                    }
                    break;

                case PVP_ENGINE_STATE_STOPPING:
                    HandleSourceNodeStop(*nodecontext, aResponse);
                    break;

                case PVP_ENGINE_STATE_RESETTING:
                    HandleSourceNodeReset(*nodecontext, aResponse);
                    break;

                default:
                    break;
            }
        }
    }
    else if (iState == PVP_ENGINE_STATE_PREPARING)
    {
        switch (nodecontext->iCmdType)
        {
            case PVP_CMD_SinkNodeQuerySyncCtrlIF:
            case PVP_CMD_SinkNodeQueryCapConfigIF:
                HandleSinkNodeQueryInterfaceMandatory(*nodecontext, aResponse);
                break;

            case PVP_CMD_SinkNodeInit:
                HandleSinkNodeInit(*nodecontext, aResponse);
                break;

            case PVP_CMD_DecNodeQueryCapConfigIF:
                HandleDecNodeQueryCapConfigIF(*nodecontext, aResponse);
                break;

            case PVP_CMD_DecNodeInit:
                HandleDecNodeInit(*nodecontext, aResponse);
                break;

            case PVP_CMD_SinkNodeDecNodeReset:
                HandleSinkNodeDecNodeReset(*nodecontext, aResponse);
                break;

            case PVP_CMD_SinkNodeQueryMetadataIF:
                HandleSinkNodeQueryInterfaceOptional(*nodecontext, aResponse);
                break;

            case PVP_CMD_DecNodeQueryMetadataIF:
                HandleDecNodeQueryInterfaceOptional(*nodecontext, aResponse);
                break;

            default:
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "PVPlayerEngine::NodeCommandCompleted() Invalid node command type in PVP_ENGINE_STATE_PREPARING. Asserting"));
                OSCL_ASSERT(false);
                break;
        }
    }
    else
    {
        // Unknown node command completion. Assert
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::NodeCommandCompleted() Unknown node command completion"));
        OSCL_ASSERT(false);
    }

    // Remove the context from the list
    FreeEngineContext(nodecontext);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::NodeCommandCompleted() Out"));
}


void PVPlayerEngine::HandleNodeInformationalEvent(const PVMFAsyncEvent& aEvent)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleNodeInformationalEvent() In"));

    PVMFNodeInterface* nodeorigin = (PVMFNodeInterface*)(aEvent.GetContext());

    PVPlayerNodeType nodetype = PVP_NODETYPE_UNKNOWN;
    int32 datapathindex = -1;

    // Process the info event based on the node type reporting the event
    if (nodeorigin == iSourceNode)
    {
        HandleSourceNodeInfoEvent(aEvent);
    }
    else if (FindNodeTypeByNode(nodeorigin, nodetype, datapathindex) == true)
    {
        if (nodetype == PVP_NODETYPE_SINK)
        {
            HandleSinkNodeInfoEvent(aEvent, datapathindex);
        }
        else // FindNodeTypeByNode when returning true, can point to only SINK or DECODER.
            // So, if not SINK, it is PVP_NODETYPE_DECODER
        {
            HandleDecNodeInfoEvent(aEvent, datapathindex);
        }
    }
    else
    {
        // Event from unknown node or component. Do nothing but log it
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::HandleNodeInformationalEvent() Info event from unknown node Event type 0x%x Context 0x%x Data 0x%x",
                         aEvent.GetEventType(), aEvent.GetContext(), aEvent.GetEventData()));
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleNodeInformationalEvent() Out"));
}


void PVPlayerEngine::HandleNodeErrorEvent(const PVMFAsyncEvent& aEvent)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleNodeErrorEvent() In"));

    PVMFNodeInterface* nodeorigin = (PVMFNodeInterface*)(aEvent.GetContext());

    PVPlayerNodeType nodetype = PVP_NODETYPE_UNKNOWN;
    int32 datapathindex = -1;

    // Process the error event based on the node type reporting the event
    if (nodeorigin == iSourceNode)
    {
        HandleSourceNodeErrorEvent(aEvent);
    }
    else if (FindNodeTypeByNode(nodeorigin, nodetype, datapathindex) == true)
    {
        if (nodetype == PVP_NODETYPE_SINK)
        {
            HandleSinkNodeErrorEvent(aEvent, datapathindex);
        }
        else // FindNodeTypeByNode when returning true, can point to only SINK or DECODER.
            // So, if not SINK, it is PVP_NODETYPE_DECODER
        {
            HandleDecNodeErrorEvent(aEvent, datapathindex);
        }
    }
    else
    {
        // Event from unknown node or component. Do nothing but log it
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::HandleNodeErrorEvent() Error event from unknown node Event type 0x%x Context 0x%x Data 0x%x",
                         aEvent.GetEventType(), aEvent.GetContext(), aEvent.GetEventData()));
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleNodeErrorEvent() Out"));
}

void PVPlayerEngine::RemoveDatapathContextFromList()
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVPlayerEngine::RemoveDatapathContextFromList(): Erasing from ContextList iCurrentContextList.size() in : %d",
                     iCurrentContextList.size()));
    for (int32 i = iCurrentContextList.size() - 1; i >= 0; --i)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                        (0, "PVPlayerEngine::RemoveDatapathContextFromList(): iCurrentContextList[i]->iCmdType %d",
                         iCurrentContextList[i]->iCmdType));

        switch (iCurrentContextList[i]->iCmdType)
        {
            case PVP_CMD_DPPrepare:
            case PVP_CMD_DPStart:
            case PVP_CMD_DPPause:
            case PVP_CMD_DPStop:
            case PVP_CMD_DPTeardown:
            case PVP_CMD_DPReset:
                FreeEngineContext(iCurrentContextList[i]);
                break;
            default:
                break;
        }
    }
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::RemoveDatapathContextFromList(): iCurrentContextList.size() out : %d",
                    iCurrentContextList.size()));
}


void PVPlayerEngine::HandlePlayerDatapathEvent(int32 /*aDatapathEvent*/, PVMFStatus aEventStatus, OsclAny* aContext, PVMFCmdResp* aCmdResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandlePlayerDatapathEvent() In"));

    // Check if a cancel command completed
    uint32* context_uint32 = (uint32*)aContext;
    if (context_uint32 == &iNumberCancelCmdPending)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                        (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Cancel in datapath completed for cancel command. Pending %d", iNumberCancelCmdPending));
        --iNumberCancelCmdPending;
        if (iNumberCancelCmdPending == 0)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                            (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Cancelling of all node/datapath commands complete, now reset all nodes"));
            // Clear the CancelCmd queue as the cmd has been cancelled.
            iCmdToCancel.clear();

            DereferenceLicenseInterface();
            RemoveDatapathContextFromList(); // empty left over contexts from cancelled datapath commands
            // Now reset the source node
            PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, -1, NULL, -1);

            PVMFCommandId cmdid = -1;
            int32 leavecode = 0;
            OSCL_TRY(leavecode, cmdid = iSourceNode->Reset(iSourceNodeSessionId, (OsclAny*)context));
            OSCL_FIRST_CATCH_ANY(leavecode,
                                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Reset on iSourceNode did a leave!"));
                                 FreeEngineContext(context);
                                 OSCL_ASSERT(false);
                                 return);

            SetEngineState(PVP_ENGINE_STATE_RESETTING);
        }
        return;
    }

    PVPlayerEngineContext* datapathcontext = (PVPlayerEngineContext*)aContext;
    OSCL_ASSERT(datapathcontext);

    // Ignore other datapath event if cancelling
    if (!iCmdToCancel.empty() || (CheckForPendingErrorHandlingCmd() && (aCmdResp && aCmdResp->GetCmdStatus() == PVMFErrCancelled)))
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Datapath event ignored due to cancel process"));
        // Remove the context from the list
        FreeEngineContext(datapathcontext);
        return;
    }

    // Process the datapath event based on the engine state
    if (iState == PVP_ENGINE_STATE_PREPARING)
    {
        switch (datapathcontext->iCmdType)
        {
            case PVP_CMD_DPPrepare:
                HandleDatapathPrepare(*datapathcontext, aEventStatus, aCmdResp);
                break;

            case PVP_CMD_DPStart:
                HandleDatapathStart(*datapathcontext, aEventStatus, aCmdResp);
                break;

            default:
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Invalid datapath command type in PVP_ENGINE_STATE_PREPARING."));
                break;
        }
    }
    else if ((iState == PVP_ENGINE_STATE_PAUSING)
             || (iState == PVP_ENGINE_STATE_PAUSED))
    {
        switch (datapathcontext->iCmdType)
        {
            case PVP_CMD_DPPause:
                HandleDatapathPause(*datapathcontext, aEventStatus, aCmdResp);
                break;

            case PVP_CMD_DPStart:
                HandleDatapathResume(*datapathcontext, aEventStatus, aCmdResp);
                break;

            default:
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Invalid datapath command type in PVP_ENGINE_STATE_PAUSING of PVP_ENGINE_STATE_PAUSED."));
                break;
        }
    }
    else if (iState == PVP_ENGINE_STATE_RESUMING)
    {
        HandleDatapathResume(*datapathcontext, aEventStatus, aCmdResp);
    }
    else if (iState == PVP_ENGINE_STATE_STOPPING)
    {
        switch (datapathcontext->iCmdType)
        {
            case PVP_CMD_DPStop:
                HandleDatapathStop(*datapathcontext, aEventStatus, aCmdResp);
                break;

            case PVP_CMD_DPTeardown:
                HandleDatapathTeardown(*datapathcontext, aEventStatus, aCmdResp);
                break;

            case PVP_CMD_DPReset:
                HandleDatapathReset(*datapathcontext, aEventStatus, aCmdResp);
                break;

            default:
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Invalid datapath command type in PVP_ENGINE_STATE_STOPPING."));
                break;
        }
    }
    else if (iState == PVP_ENGINE_STATE_RESETTING)
    {
        switch (datapathcontext->iCmdType)
        {
            case PVP_CMD_DPReset:
                HandleDatapathReset(*datapathcontext, aEventStatus, aCmdResp);
                break;

            default:
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Invalid datapath command type in PVP_ENGINE_STATE_RESETTING"));
                break;
        }
    }
    else
    {
        // Unknown datapath.
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Invalid state for datapath command completion."));
    }

    // Remove the context from the list
    FreeEngineContext(datapathcontext);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Out"));
}

void PVPlayerEngine::NotificationsInterfaceDestroyed()
{
    iClockNotificationsInf = NULL;
}

void PVPlayerEngine::ProcessCallBack(uint32 aCallBackID, PVTimeComparisonUtils::MediaTimeStatus aTimerAccuracy, uint32 aDelta,
                                     const OsclAny* acontextData, PVMFStatus aStatus)
{
    OSCL_UNUSED_ARG(aTimerAccuracy);
    OSCL_UNUSED_ARG(aDelta);
    OSCL_UNUSED_ARG(acontextData);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::TimeoutOccurred() Timer for PlayStatus event triggered"));

    if (aCallBackID == iPlayStatusCallbackTimerID)
    {
        //Callback timer needs to be restarted if status is success
        if ((PVMFSuccess == aStatus) && iPlayStatusTimerEnabled)
        {
            SendPositionStatusUpdate();
            iPlayStatusTimerEnabled = false;
            iPlayStatusCallbackTimerID = 0;

            StartPlaybackStatusTimer();
        }
        else
        {
            if (aStatus == PVMFErrCallbackClockStopped)
            {
                iPlayStatusTimerEnabled = false;
                iPlayStatusCallbackTimerID = 0;
            }
        }
    }
}
void PVPlayerEngine::SendPositionStatusUpdate(void)
{
    PVPPlaybackPosition curpos;
    curpos.iPosUnit = iPBPosStatusUnit;
    GetPlaybackClockPosition(curpos);

    uint8 poslocalbuffer[8];
    oscl_memset(poslocalbuffer, 0, 8);
    poslocalbuffer[0] = 1;
    switch (iPBPosStatusUnit)
    {
        case PVPPBPOSUNIT_SEC:
            oscl_memcpy(&poslocalbuffer[4], &(curpos.iPosValue.sec_value), sizeof(uint32));
            break;

        case PVPPBPOSUNIT_MIN:
            oscl_memcpy(&poslocalbuffer[4], &(curpos.iPosValue.min_value), sizeof(uint32));
            break;

        case PVPPBPOSUNIT_MILLISEC:
        default:
            oscl_memcpy(&poslocalbuffer[4], &(curpos.iPosValue.millisec_value), sizeof(uint32));
            break;
    }

    PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
    PVMFBasicErrorInfoMessage* infomsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoPlaybackPositionStatus, puuid, NULL));
    // EventData parameter will be deprecated, and curpos will not be sent through EventData in future.
    SendInformationalEvent(PVMFInfoPositionStatus, OSCL_STATIC_CAST(PVInterface*, infomsg), (OsclAny*)&curpos, poslocalbuffer, 8);
    infomsg->removeRef();
}


void PVPlayerEngine::TimeoutOccurred(int32 timerID, int32 /*timeoutInfo*/)
{
    if (timerID == PVPLAYERENGINE_TIMERID_ENDTIMECHECK)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::TimeoutOccurred() Timer for EndTime check triggered"));

        PVPPlaybackPosition curpos;
        curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC;
        GetPlaybackClockPosition(curpos);

        if (iCurrentEndPosition.iIndeterminate || iCurrentEndPosition.iPosUnit != PVPPBPOSUNIT_MILLISEC)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::TimeoutOccurred() End time unit is invalid. Disabling end time check."));
            iEndTimeCheckEnabled = false;
            iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_ENDTIMECHECK);
            OSCL_ASSERT(false);
            return;
        }

        if (curpos.iPosValue.millisec_value >= iCurrentEndPosition.iPosValue.millisec_value)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::TimeoutOccurred() Specified end time reached so issuing pause command"));

            iEndTimeCheckEnabled = false;
            iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_ENDTIMECHECK);
            // Issues end time reached command
            AddCommandToQueue(PVP_ENGINE_COMMAND_PAUSE_DUE_TO_ENDTIME_REACHED, NULL, NULL, NULL, false);
        }
        else if (!iEndTimeCheckEnabled)
        {
            iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_ENDTIMECHECK);
        }
    }
}

void PVPlayerEngine::RecognizeCompleted(PVMFFormatType aSourceFormatType, OsclAny* aContext)
{
    // Check if a cancel command completed
    uint32* context_uint32 = (uint32*)(aContext);
    if (context_uint32 == &iNumberCancelCmdPending)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::RecognizeCompleted() Recognize request cancelled"));
        --iNumberCancelCmdPending;
        if (iNumberCancelCmdPending == 0)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                            (0, "PVPlayerEngine::RecognizeCompleted() Cancelling of all node/datapath commands complete, now reset all nodes"));
            // Clear the CancelCmd queue as the cmd has been cancelled.
            iCmdToCancel.clear();

            DereferenceLicenseInterface();
            RemoveDatapathContextFromList(); // empty left over contexts from cancelled datapath commands
            // Now reset the source node
            PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, -1, NULL, -1);

            PVMFCommandId cmdid = -1;
            int32 leavecode = 0;
            OSCL_TRY(leavecode, cmdid = iSourceNode->Reset(iSourceNodeSessionId, (OsclAny*)context));
            OSCL_FIRST_CATCH_ANY(leavecode,
                                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::RecognizeCompleted() Reset on iSourceNode did a leave!"));
                                 FreeEngineContext(context);
                                 OSCL_ASSERT(false);
                                 return);

            SetEngineState(PVP_ENGINE_STATE_RESETTING);
        }
        return;
    }

    // Ignore recognize completion if cancelling
    if (!iCmdToCancel.empty() || CheckForPendingErrorHandlingCmd())
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::RecognizeCompleted() Recognize completion ignored due to cancel process"));
        // Remove the context from the list
        FreeEngineContext((PVPlayerEngineContext*)(aContext));
        return;
    }

    // Save the recognized source format
    iSourceFormatType = aSourceFormatType;

    // Free the engine context after saving the cmd id and context
    PVPlayerEngineContext* reccontext = (PVPlayerEngineContext*)(aContext);
    OSCL_ASSERT(reccontext != NULL);
    PVCommandId cmdid = reccontext->iCmdId;
    OsclAny* cmdcontext = reccontext->iCmdContext;
    FreeEngineContext(reccontext);

    // Start the source node creation and setup sequence
    PVMFStatus retval = DoSetupSourceNode(cmdid, cmdcontext);

    if (retval != PVMFSuccess)
    {
        AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_ADD_DATA_SOURCE, retval, NULL);
        return;
    }

    // Send the event to notify the user of the updated format type
    int32 len = iSourceFormatType.getMIMEStrLen();
    uint8* localbuffer = (uint8*)iSourceFormatType.getMIMEStrPtr();
    SendInformationalEvent(PVMFInfoSourceFormatUpdated, NULL, NULL, localbuffer, len);
}

void PVPlayerEngine::CPMCommandCompleted(const PVMFCmdResp& aResponse)
{
    PVPlayerEngineContext* context = (PVPlayerEngineContext*)(aResponse.GetContext());

    OSCL_ASSERT((aResponse.GetCmdId() == iCPMGetLicenseCmdId)
                || (aResponse.GetCmdId() == iCPMCancelGetLicenseCmdId)
                || (aResponse.GetCmdId() == iCPMJoinDomainCmdId)
               );

    switch (aResponse.GetCmdStatus())
    {
        case PVMFSuccess:
            EngineCommandCompleted(context->iCmdId, context->iCmdContext, PVMFSuccess);
            break;

        default:
        {
            // Report command complete
            PVMFStatus cmdstatus = aResponse.GetCmdStatus();
            PVMFErrorInfoMessageInterface* nextmsg = NULL;
            if (aResponse.GetEventExtensionInterface())
            {
                nextmsg = GetErrorInfoMessageInterface(*(aResponse.GetEventExtensionInterface()));
            }

            PVUuid uuid = PVPlayerErrorInfoEventTypesUUID;
            PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSource, uuid, nextmsg));

            if ((aResponse.GetCmdId() == iCPMGetLicenseCmdId)
                    || (aResponse.GetCmdId() == iCPMJoinDomainCmdId)
               )
            {
                EngineCommandCompleted(context->iCmdId, context->iCmdContext, cmdstatus, OSCL_STATIC_CAST(PVInterface*, errmsg));
            }
            else if (aResponse.GetCmdId() == iCPMCancelGetLicenseCmdId)
            {
                if ((iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_CHAR)
                        || (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_WCHAR)
                        || (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_JOIN_DOMAIN)
                   )
                {
                    OSCL_ASSERT(!iCmdToDlaCancel.empty());
                    if (!iCmdToDlaCancel.empty())
                    {
                        PVPlayerEngineCommand currentcmd(iCurrentCmd[0]);
                        iCurrentCmd.erase(iCurrentCmd.begin());
                        iCurrentCmd.push_front(iCmdToDlaCancel[0]);
                        // If we get here, the command isn't queued so the cancel fails
                        EngineCommandCompleted(context->iCmdId, context->iCmdContext, cmdstatus, OSCL_STATIC_CAST(PVInterface*, errmsg));
                        iCurrentCmd.push_front(currentcmd);
                        iCmdToDlaCancel.erase(iCmdToDlaCancel.begin());
                    }
                }
                else if (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_CANCEL_ACQUIRE_LICENSE)
                {
                    EngineCommandCompleted(context->iCmdId, context->iCmdContext, cmdstatus, OSCL_STATIC_CAST(PVInterface*, errmsg));
                }
            }
            errmsg->removeRef();
        }
        break;
    }

    if (((aResponse.GetCmdId() == iCPMGetLicenseCmdId)
            || (aResponse.GetCmdId() == iCPMJoinDomainCmdId)
        )
            && !iCmdToDlaCancel.empty()
       )
    {
        // Set CancelAcquireLicense cmd in current cmd
        iCurrentCmd.push_front(iCmdToDlaCancel[0]);
        iCmdToDlaCancel.clear();
    }
    FreeEngineContext(context);
}

//A callback from the threadsafe queue
void PVPlayerEngine::ThreadSafeQueueDataAvailable(ThreadSafeQueue* aQueue)
{
    OSCL_UNUSED_ARG(aQueue);

    //pull all available data off the thread-safe queue and transfer
    //it to the internal queue.
    for (uint32 ndata = 1; ndata;)
    {
        ThreadSafeQueueId id;
        OsclAny* data;
        ndata = iThreadSafeQueue.DeQueue(id, data);
        if (ndata)
        {
            PVPlayerEngineCommand* cmd = (PVPlayerEngineCommand*)data;
            AddCommandToQueue(cmd->iCmdType
                              , cmd->iContextData
                              , &cmd->iParamVector
                              , &cmd->iUuid
                              , true//assume all out-of-thread data is an API command.
                              , (PVCommandId*)&id);//use the command ID that was returned to the caller.
            OSCL_DELETE(cmd);
        }
    }
}

PVMFStatus PVPlayerEngine::DoOOTSyncCommand(int32 aCmdType,
        Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator>* aParamVector,
        const PVUuid* aUuid)
{
    //Called from out-of-thread to perform a synchronous command


    //Add a PVMFStatus* to the end of the command param vec to hold the result.
    PVMFStatus status;
    PVPlayerEngineCommandParamUnion param;
    param.pOsclAny_value = (OsclAny*) & status;
    aParamVector->push_back(param);

    //push the command across the thread boundary
    PVCommandId id = 0;
    PVPlayerEngineCommand* cmd = OSCL_NEW(PVPlayerEngineCommand, (aCmdType, id, NULL, aParamVector));
    if (aUuid)
    {
        cmd->SetUuid(*aUuid);
    }
    iThreadSafeQueue.AddToQueue(cmd);

    //block and wait for completion by engine thread.
    iOOTSyncCommandSem.Wait();
    return status;
}

void PVPlayerEngine::OOTSyncCommandComplete(PVPlayerEngineCommand& aCmd, PVMFStatus aStatus)
{
    //Called in engine thread to complete an out-of-thread synchronous command

    //Put the result status into the last element of the command param vector.
    PVMFStatus* status = (PVMFStatus*)(aCmd.GetParam(aCmd.iParamVector.size() - 1).pOsclAny_value);
    OSCL_ASSERT(status);
    *status = aStatus;

    //Signal the calling thread.
    iOOTSyncCommandSem.Signal();
}

PVCommandId PVPlayerEngine::AddCommandToQueue(int32 aCmdType, OsclAny* aContextData,
        Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator>* aParamVector,
        const PVUuid* aUuid, bool aAPICommand, PVCommandId* aId)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::AddCommandToQueue() In CmdType %d, CmdId %d", aCmdType, iCommandId));

    PVCommandId commandId;
    if (aId)
    {
        //This command is being transferred from the thread-safe queue to the
        //internal queue, in engine thread context.
        //The input ID is the one that was returned to the
        //caller, so use that ID instead of generating a new one.
        commandId = *aId;
    }
    else
    {
        //Generate the next command ID, being careful to avoid thread contention
        //for "iCommandId".
        iCommandIdMut.Lock();
        commandId = iCommandId;
        ++iCommandId;
        if (iCommandId == 0x7FFFFFFF)
        {
            iCommandId = 0;
        }
        iCommandIdMut.Unlock();

        //If this is from outside engine thread context, then push the command across the
        //thread boundary.
        if (!iThreadSafeQueue.IsInThread())
        {
            PVPlayerEngineCommand* cmd = OSCL_NEW(PVPlayerEngineCommand, (aCmdType, commandId, aContextData, aParamVector, aAPICommand));
            if (aUuid)
            {
                cmd->SetUuid(*aUuid);
            }
            iThreadSafeQueue.AddToQueue(cmd, (ThreadSafeQueueId*)&commandId);
            return commandId;
        }
    }

    PVPlayerEngineCommand cmd(aCmdType, commandId, aContextData, aParamVector, aAPICommand);
    if (aUuid)
    {
        cmd.SetUuid(*aUuid);
    }

    int32 leavecode = 0;
    OSCL_TRY(leavecode, iPendingCmds.push(cmd));
    OSCL_FIRST_CATCH_ANY(leavecode,
                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::AddCommandToQueue() Adding command to pending command list did a leave!"));
                         OSCL_ASSERT(false);
                         return -1;);

    // if engine needs to queue any error handling command set the engine state as PVP_ENGINE_STATE_ERROR.
    switch (aCmdType)
    {
        case PVP_ENGINE_COMMAND_ERROR_HANDLING_ADD_DATA_SOURCE:
        case PVP_ENGINE_COMMAND_ERROR_HANDLING_INIT:
        case PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE:
        case PVP_ENGINE_COMMAND_ERROR_HANDLING_PAUSE:
        case PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME:
        case PVP_ENGINE_COMMAND_ERROR_HANDLING_SET_PLAYBACK_RANGE:
        case PVP_ENGINE_COMMAND_ERROR_HANDLING_SET_PLAYBACK_RATE:
        case PVP_ENGINE_COMMAND_ERROR_HANDLING_STOP:
        case PVP_ENGINE_COMMAND_ERROR_HANDLING_CANCEL_ALL_COMMANDS:
        case PVP_ENGINE_COMMAND_ERROR_HANDLING_GENERAL:
            SetEngineState(PVP_ENGINE_STATE_ERROR);
            SendInformationalEvent(PVMFInfoErrorHandlingStart, NULL);
            break;

        default:
            break;
    }

    RunIfNotReady();

    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE,
                    (0, "PVPlayerEngine::AddCommandToQueue() Type=%d ID=%d APIcmd=%d Tick=%d",
                     aCmdType, cmd.GetCmdId(), aAPICommand, OsclTickCount::TickCount()));

    return cmd.GetCmdId();
}


void PVPlayerEngine::SetEngineState(PVPlayerEngineState aState)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::SetEngineState() In Current state %d, New state %d", iState, aState));
    iState = aState;
}


PVPlayerState PVPlayerEngine::GetPVPlayerState(void)
{
    switch (iState)
    {
        case PVP_ENGINE_STATE_IDLE:
        case PVP_ENGINE_STATE_INITIALIZING:
            return PVP_STATE_IDLE;

        case PVP_ENGINE_STATE_INITIALIZED:
        case PVP_ENGINE_STATE_PREPARING:
        case PVP_ENGINE_STATE_TRACK_SELECTION_1_DONE:
        case PVP_ENGINE_STATE_TRACK_SELECTION_2_DONE:
        case PVP_ENGINE_STATE_TRACK_SELECTION_3_DONE:
            return PVP_STATE_INITIALIZED;

        case PVP_ENGINE_STATE_PREPARED:
        case PVP_ENGINE_STATE_STARTING:
            return PVP_STATE_PREPARED;

        case PVP_ENGINE_STATE_STARTED:
        case PVP_ENGINE_STATE_AUTO_PAUSING:
        case PVP_ENGINE_STATE_AUTO_RESUMING:
        case PVP_ENGINE_STATE_PAUSING:
        case PVP_ENGINE_STATE_STOPPING:
            return PVP_STATE_STARTED;

        case PVP_ENGINE_STATE_AUTO_PAUSED:
        {
            if (iStartIssuedOnEngine)
            {
                return PVP_STATE_STARTED;
            }
            else
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                                (0, "PVPlayerEngine::GetPVPlayerState return PVP_STATE_PREPARED in Engine Auto_Paused state, since Engine is still waiting for Start command"));
                return PVP_STATE_PREPARED;
            }
        }

        case PVP_ENGINE_STATE_PAUSED:
        case PVP_ENGINE_STATE_RESUMING:
            return PVP_STATE_PAUSED;

        case PVP_ENGINE_STATE_RESETTING:
        {
            bool ehPending = CheckForPendingErrorHandlingCmd();
            if (ehPending)
            {
                return PVP_STATE_ERROR;
            }
            else
            {
                return PVP_STATE_IDLE;
            }
        }

        case PVP_ENGINE_STATE_ERROR:
            return PVP_STATE_ERROR;

        default:
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::GetPVPlayerState() Unknown engine state. Asserting"));
            OSCL_ASSERT(false);
            break;
    }

    return PVP_STATE_ERROR;
}


void PVPlayerEngine::GetPlaybackClockPosition(PVPPlaybackPosition& aClockPos)
{
    aClockPos.iIndeterminate = false;

    uint32 nptcurpos;

    if (!iChangeDirectionNPT.iIndeterminate)
    {
        // report the expected NPT after the direction change
        // to avoid weird transient values between the direction change
        // and the repositioning completion.
        nptcurpos = iChangeDirectionNPT.iPosValue.millisec_value;
    }
    else
    {
        // Get current playback clock position
        iPlaybackClock.GetNPTClockPosition(nptcurpos);
    }

    nptcurpos = (nptcurpos > iSourceDurationInMS) ? iSourceDurationInMS : nptcurpos;
    if (ConvertFromMillisec(nptcurpos, aClockPos) != PVMFSuccess)
    {
        // Other position units are not supported yet
        aClockPos.iIndeterminate = true;
    }
}


PVMFStatus PVPlayerEngine::ConvertToMillisec(PVPPlaybackPosition& aPBPos, uint32& aTimeMS)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::ConvertToMillisec() In"));

    if (aPBPos.iIndeterminate)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::ConvertToMillisec() Indeterminate position"));
        return PVMFErrArgument;
    }

    bool owallclockunits = false;
    switch (aPBPos.iPosUnit)
    {
        case PVPPBPOSUNIT_MILLISEC:
            aTimeMS = aPBPos.iPosValue.millisec_value;
            owallclockunits = true;
            break;

        case PVPPBPOSUNIT_SEC:
            aTimeMS = aPBPos.iPosValue.sec_value * 1000;
            owallclockunits = true;
            break;

        case PVPPBPOSUNIT_MIN:
            aTimeMS = aPBPos.iPosValue.min_value * 60000;
            owallclockunits = true;
            break;

        case PVPPBPOSUNIT_HOUR:
            aTimeMS = aPBPos.iPosValue.hour_value * 3600000;
            owallclockunits = true;
            break;

        case PVPPBPOSUNIT_SMPTE:
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertToMillisec() SMPTE not supported yet"));
            return PVMFErrArgument;

        case PVPPBPOSUNIT_PERCENT:
        {
            if (iSourceDurationAvailable == false)
            {
                // Duration info not available from source node so can't convert
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertToMillisec() Duration not available so can't convert"));
                return PVMFErrArgument;
            }

            if (iSourceDurationInMS == 0)
            {
                // Duration is 0 so can't convert
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertToMillisec() Duration value is 0 so can't convert"));
                return PVMFErrArgument;
            }

            if (aPBPos.iPosValue.percent_value >= 100)
            {
                // If percentage greater than 100, cap to 100%
                aTimeMS = iSourceDurationInMS;
            }
            else
            {
                // Calculate time in millseconds based on percentage of duration
                aTimeMS = (aPBPos.iPosValue.percent_value * iSourceDurationInMS) / 100;
            }
        }
        break;

        case PVPPBPOSUNIT_SAMPLENUMBER:
        {
            if (iSourceNodeTrackLevelInfoIF == NULL)
            {
                // The source node doesn't have the query IF to convert samplenum to time
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertToMillisec() Sample number to time conversion not available"));
                return PVMFErrArgument;
            }

            // Determine which track to use for conversion.
            // Give preference to video track, then text, and finally audio
            PVMFTrackInfo* track = NULL;
            int32 datapathIndex = -1;

            // Search from the datapath list.
            // First look for video track
            bool retVal = FindDatapathForTrackUsingMimeString(true, false, false, datapathIndex);
            if (retVal == false)
            {
                // Video track not available, look for text track
                retVal = FindDatapathForTrackUsingMimeString(false, false, true, datapathIndex);
                if (retVal == false)
                {
                    // Text track also not avaliable, look for audio track
                    retVal = FindDatapathForTrackUsingMimeString(false, true, false, datapathIndex);
                    if (retVal == false)
                    {
                        // Track is not available to do the conversion
                        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertToMillisec() Track not selected for conversion"));
                        return PVMFErrArgument;
                    }
                }
            }

            // Track avalaible.
            track = iDatapathList[datapathIndex].iTrackInfo;

            // Convert the sample number to time in milliseconds
            PVMFTimestamp framets = 0;
            if (iSourceNodeTrackLevelInfoIF->GetTimestampForSampleNumber(*track, aPBPos.iPosValue.samplenum_value, framets) != PVMFSuccess)
            {
                // Conversion failed
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertToMillisec() Sample number to time conversion failed"));
                return PVMFErrArgument;
            }

            aTimeMS = framets;
        }
        break;

        case PVPPBPOSUNIT_DATAPOSITION:
        {
            if (iSourceNodeTrackLevelInfoIF == NULL)
            {
                // The source node doesn't have the ext IF to convert data position to time
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertToMillisec() Data position to time conversion not available"));
                return PVMFErrArgument;
            }

            // Go through each active track and find the minimum time for given data position
            bool mintsvalid = false;
            PVMFTimestamp mints = 0xFFFFFFFF;
            for (uint32 i = 0; i < iDatapathList.size(); ++i)
            {
                if (iDatapathList[i].iDatapath)
                {
                    PVMFTimestamp curts = 0;
                    if (iSourceNodeTrackLevelInfoIF->GetTimestampForDataPosition(*(iDatapathList[i].iTrackInfo), aPBPos.iPosValue.datapos_value, curts) != PVMFSuccess)
                    {
                        // Conversion failed
                        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertToMillisec() Data position to time conversion failed"));
                    }
                    else
                    {
                        // Conversion succeeded. Save only if it is the minimum encountered so far.
                        mintsvalid = true;
                        if (curts < mints)
                        {
                            mints = curts;
                        }
                    }
                }
            }

            if (mintsvalid == false)
            {
                // Conversion on all active tracks failed
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "PVPlayerEngine::ConvertToMillisec() Data position to time conversion could not be done on any active track"));
                return PVMFErrArgument;
            }

            aTimeMS = mints;
        }
        break;

        case PVPPBPOSUNIT_PLAYLIST:
        {
            switch (aPBPos.iPlayListPosUnit)
            {
                case PVPPBPOSUNIT_MILLISEC:
                    aTimeMS = aPBPos.iPlayListPosValue.millisec_value;
                    break;

                case PVPPBPOSUNIT_SEC:
                    aTimeMS = aPBPos.iPlayListPosValue.sec_value * 1000;
                    break;

                case PVPPBPOSUNIT_MIN:
                    aTimeMS = aPBPos.iPlayListPosValue.min_value * 60000;
                    break;

                case PVPPBPOSUNIT_HOUR:
                    aTimeMS = aPBPos.iPlayListPosValue.hour_value * 3600000;
                    break;

                default:
                    // Don't support the other units for now
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertToMillisec() Unsupported playlist position units"));
                    return PVMFErrArgument;
            }
        }
        break;

        default:
            // Don't support the other units for now
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertToMillisec() Unsupported position units"));
            return PVMFErrArgument;
    }

    if (owallclockunits == true)
    {
        if ((aTimeMS > iSourceDurationInMS) && (iSourceDurationAvailable == true))
        {
            //cap time to clip duration
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVPlayerEngine::ConvertToMillisec() Capping value - Acutal=%d, CappedValue=%d",
                            aTimeMS, iSourceDurationInMS));
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_DEBUG, (0, "PVPlayerEngine::ConvertToMillisec() Capping value - Acutal=%d, CappedValue=%d",
                            aTimeMS, iSourceDurationInMS));
            aTimeMS = iSourceDurationInMS;
        }
        else
        {
            // just pass the converted time even if duration is not available and let
            // source node handle the request.
        }
    }

    if (aPBPos.iPosUnit == PVPPBPOSUNIT_PLAYLIST)
    {
        aPBPos.iPlayListPosValue.millisec_value = aTimeMS;
        aPBPos.iPlayListPosUnit = PVPPBPOSUNIT_MILLISEC;
    }
    else
    {
        aPBPos.iPosValue.millisec_value = aTimeMS;
        aPBPos.iPosUnit = PVPPBPOSUNIT_MILLISEC;
    }
    iTargetNPT = aTimeMS;

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::ConvertToMillisec() Out"));
    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::ConvertFromMillisec(uint32 aTimeMS, PVPPlaybackPosition& aPBPos)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::ConvertFromMillisec() In"));

    // Convert to specified time units
    switch (aPBPos.iPosUnit)
    {
        case PVPPBPOSUNIT_MILLISEC:
            aPBPos.iPosValue.millisec_value = aTimeMS;
            break;

        case PVPPBPOSUNIT_SEC:
            aPBPos.iPosValue.sec_value = aTimeMS / 1000;
            break;

        case PVPPBPOSUNIT_MIN:
            aPBPos.iPosValue.min_value = aTimeMS / 60000;
            break;

        case PVPPBPOSUNIT_HOUR:
            aPBPos.iPosValue.hour_value = aTimeMS / 3600000;
            break;

        case PVPPBPOSUNIT_SMPTE:
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::ConvertFromMillisec() SMPTE units not supported yet"));
            return PVMFErrArgument;

        case PVPPBPOSUNIT_PERCENT:
        {
            if (iSourceDurationAvailable == false)
            {
                // Duration info not available from source node so can't convert
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertFromMillisec() Duration not available so can't convert"));
                return PVMFErrArgument;
            }

            if (iSourceDurationInMS == 0)
            {
                // Duration is 0 so can't convert
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertFromMillisec() Duration value is 0 so can't convert"));
                return PVMFErrArgument;
            }

            if (aTimeMS >= iSourceDurationInMS)
            {
                // Put a ceiling of 100%
                aPBPos.iPosValue.percent_value = 100;
            }
            else
            {
                // Calculate percentage of playback, avoiding overflow
                if (iSourceDurationInMS >= PVP_MIN_PLAYSTATUS_PERCENT_OVERFLOW_THRESHOLD)
                {
                    aPBPos.iPosValue.percent_value = aTimeMS / (iSourceDurationInMS / 100);
                }
                else
                {
                    aPBPos.iPosValue.percent_value = (aTimeMS * 100) / iSourceDurationInMS;
                }
            }
        }
        break;

        case PVPPBPOSUNIT_SAMPLENUMBER:
        {
            if (iSourceNodeTrackLevelInfoIF == NULL)
            {
                // The source node doesn't have the query IF to convert time to sample number
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertFromMillisec() Time to sample numberconversion not available"));
                return PVMFErrArgument;
            }

            // Determine which track to use for conversion.
            // Give preference to video track, then text, and finally audio
            PVMFTrackInfo* track = NULL;
            int32 datapathIndex = -1;

            // Search from the datapath list.
            // First look for video track
            bool retVal = FindDatapathForTrackUsingMimeString(true, false, false, datapathIndex);
            if (retVal == false)
            {
                // Video track not available, look for text track
                retVal = FindDatapathForTrackUsingMimeString(false, false, true, datapathIndex);
                if (retVal == false)
                {
                    // Text track also not avaliable, look for audio track
                    retVal = FindDatapathForTrackUsingMimeString(false, true, false, datapathIndex);
                    if (retVal == false)
                    {
                        // Track is not available to do the conversion
                        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertToMillisec() Track not selected for conversion"));
                        return PVMFErrArgument;
                    }
                }
            }

            // Track avalaible.
            track = iDatapathList[datapathIndex].iTrackInfo;

            // Convert the time to sample number
            PVMFTimestamp ts = aTimeMS;
            uint32 samplenum = 0;
            if (iSourceNodeTrackLevelInfoIF->GetSampleNumberForTimestamp(*track, ts, samplenum) != PVMFSuccess)
            {
                // Conversion failed
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertFromMillisec() Sample number to time conversion failed"));
                return PVMFErrArgument;
            }

            aPBPos.iPosValue.samplenum_value = samplenum;
        }
        break;

        case PVPPBPOSUNIT_DATAPOSITION:
        {
            if (iSourceNodeTrackLevelInfoIF == NULL)
            {
                // The source node doesn't have the ext IF to convert time to data position
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "PVPlayerEngine::ConvertFromMillisec() Time to data position conversion not available in source node"));
                return PVMFErrArgument;
            }

            // Query each active track for its data position
            // Return the max data position
            PVMFTimestamp ts = aTimeMS;
            uint32 maxdatapos = 0;
            bool maxdataposvalid = false;

            // Go through each active track
            for (uint32 i = 0; i < iDatapathList.size(); ++i)
            {
                if (iDatapathList[i].iDatapath)
                {
                    uint32 curdatapos = 0;
                    // Convert the time to data position
                    if (iSourceNodeTrackLevelInfoIF->GetDataPositionForTimestamp(*(iDatapathList[i].iTrackInfo), ts, curdatapos) != PVMFSuccess)
                    {
                        // Conversion failed
                        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertFromMillisec() Time to data position conversion failed"));
                    }
                    else
                    {
                        // Save the data position if it is greater than
                        // any position encountered so far.
                        maxdataposvalid = true;
                        if (curdatapos > maxdatapos)
                        {
                            maxdatapos = curdatapos;
                        }
                    }
                }
            }

            if (maxdataposvalid == false)
            {
                // Conversion failed for all active tracks
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertFromMillisec() Track not selected for conversion"));
                return PVMFErrArgument;
            }
            // Save the data position to return
            aPBPos.iPosValue.datapos_value = maxdatapos;
        }
        break;

        default:
            // Don't support the other units for now
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::ConvertFromMillisec() Unsupported position units"));
            return PVMFErrArgument;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::ConvertFromMillisec() Out"));
    return PVMFSuccess;
}


void PVPlayerEngine::EngineCommandCompleted(PVCommandId aId, OsclAny* aContext, PVMFStatus aStatus, PVInterface* aExtInterface, OsclAny* aEventData, int32 aEventDataSize)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::EngineCommandCompleted() In CmdId %d, Status %d", aId, aStatus));

    // Update the current command vector

    // Assert if the current cmd is not saved or the cmd ID does not match
    OSCL_ASSERT(iCurrentCmd.size() == 1);
    OSCL_ASSERT(iCurrentCmd[0].GetCmdId() == aId);

    // Empty out the current cmd vector and set active if there are other pending commands
    PVPlayerEngineCommand completedcmd(iCurrentCmd[0]);
    iCurrentCmd.erase(iCurrentCmd.begin());
    if (!iPendingCmds.empty())
    {
        RunIfNotReady();
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE,
                    (0, "PVPlayerEngine::EngineCommandCompleted() Type=%d ID=%d APIcmd=%d Tick=%d",
                     completedcmd.GetCmdType(), completedcmd.GetCmdId(), completedcmd.IsAPICommand(), OsclTickCount::TickCount()));

    // Send informational event or send other callback if needed
    switch (completedcmd.GetCmdType())
    {
        case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_ENDOFCLIP:
            SendEndOfClipInfoEvent(aStatus, aExtInterface);
            break;

        case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_ENDTIME_REACHED:
            SendEndTimeReachedInfoEvent(aStatus, aExtInterface);
            break;

        case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_BUFFER_UNDERFLOW:
            SendSourceUnderflowInfoEvent(aStatus, aExtInterface);
            break;

        case PVP_ENGINE_COMMAND_RESUME_DUE_TO_BUFFER_DATAREADY:
            SendSourceDataReadyInfoEvent(aStatus, aExtInterface);
            break;

        case PVP_ENGINE_COMMAND_CAPCONFIG_SET_PARAMETERS:
            // Send callback to the specified observer
            if (iCfgCapCmdObserver)
            {
                iCfgCapCmdObserver->SignalEvent(aId);
            }
            break;

        default:
            // None to be sent
            break;
    }

    // Send the command completed event
    if (iCmdStatusObserver)
    {
        if (aId != -1 && completedcmd.IsAPICommand())
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                            (0, "PVPlayerEngine::EngineCommandCompleted() Notifying engine command as completed. CmdId %d Status %d", aId, aStatus));
            PVCmdResponse cmdcompleted(aId, aContext, aStatus, aExtInterface, aEventData, aEventDataSize);
            iCmdStatusObserver->CommandCompleted(cmdcompleted);
        }
        else
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                            (0, "PVPlayerEngine::EngineCommandCompleted() aId is -1 or not an API command. CmdType %d", completedcmd.GetCmdType()));
        }
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::EngineCommandCompleted() iCmdStatusObserver is NULL"));
    }

    if (iRemoveDataSource)
    {
        if (iDataSource)
        {
            RemoveDataSourceSync(*iDataSource);
        }
        iRemoveDataSource = false;
    }
}


void PVPlayerEngine::SendInformationalEvent(PVMFEventType aEventType, PVInterface* aExtInterface, OsclAny* aEventData, uint8* aLocalBuffer, uint32 aLocalBufferSize)
{
    // Send the info event if observer has been specified
    if (iInfoEventObserver)
    {
        PVAsyncInformationalEvent infoevent((PVEventType)aEventType, NULL, aExtInterface, (PVExclusivePtr)aEventData, aLocalBuffer, aLocalBufferSize);
        iInfoEventObserver->HandleInformationalEvent(infoevent);
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::SendInformationalEvent() iInfoEventObserver is NULL"));
    }
}


void PVPlayerEngine::SendErrorEvent(PVMFEventType aEventType, PVInterface* aExtInterface, OsclAny* aEventData, uint8* aLocalBuffer, uint32 aLocalBufferSize)
{
    // Send the error event if observer has been specified
    if (iErrorEventObserver)
    {
        PVAsyncErrorEvent errorevent((PVEventType)aEventType, NULL, aExtInterface, (PVExclusivePtr)aEventData, aLocalBuffer, aLocalBufferSize);
        iErrorEventObserver->HandleErrorEvent(errorevent);
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::SendErrorEvent() iErrorEventObserver is NULL"));
    }
}


void PVPlayerEngine::DoCancelCommand(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelCommand() In"));

    // Boolean to check if the command is cancelled or not.
    bool commandCancelled = false;

    // cmd to cancel either has been completed or is in pending queue.
    // Create a temporary queue for pending commands and current command if any.
    OsclPriorityQueue<PVPlayerEngineCommand, OsclMemAllocator, Oscl_Vector<PVPlayerEngineCommand, OsclMemAllocator>, PVPlayerEngineCommandCompareLess> iTempPendingCmds;
    Oscl_Vector<PVPlayerEngineCommand, OsclMemAllocator> iTempCurrentCmd;
    // Copy the pending commands to the new queue
    iTempPendingCmds = iPendingCmds;
    while (!iTempPendingCmds.empty())
    {
        // Get the queue from the top
        PVPlayerEngineCommand cmd(iTempPendingCmds.top());
        // Check if it needs to be cancelled
        if (aCmd.GetParam(0).int32_value == cmd.GetCmdId())
        {
            // Found command to be cancelled in the Pending Queue, set the
            // commandCancelled boolean to true.
            commandCancelled = true;

            // Remove it from the pending commands queue
            iPendingCmds.remove(cmd);
            // Save it temporary as "current command" and then cancel it. If CurrentCmd has some
            // command, first move it to TempCurrentCmd queue.
            if (!iCurrentCmd.empty())
            {
                iTempCurrentCmd.push_front(iCurrentCmd[0]);
                iCurrentCmd.erase(iCurrentCmd.begin());
            }

            iCurrentCmd.push_front(cmd);
            EngineCommandCompleted(cmd.GetCmdId(), cmd.GetContext(), PVMFErrCancelled);

            // send command complete for CancelCommand also.
            iCurrentCmd.push_front(aCmd);
            EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);

            // If TempCurrentCmd queue is holding up any command, move it back to CurrentCmd queue.
            if (!iTempCurrentCmd.empty())
            {
                iCurrentCmd.push_front(iTempCurrentCmd[0]);
                iTempCurrentCmd.erase(iTempCurrentCmd.begin());
            }
        }
        // Pop each cmd from the temporary queue
        iTempPendingCmds.pop();
    }

    if (!commandCancelled)
    {
        // There was no command cancelled, user might have given a wrong Argument
        // Fail the command with PVMFErrArgument
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelCommand() Wrong Argument, No comand cancelled"));
        if (!iCurrentCmd.empty())
        {
            PVPlayerEngineCommand currentcmd(iCurrentCmd[0]);
            iCurrentCmd.erase(iCurrentCmd.begin());
            iCurrentCmd.push_front(aCmd);
            EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFErrArgument);
            iCurrentCmd.push_front(currentcmd);
        }
        else
        {
            // Current Command is empty, just push CancelCommand and do Command Complete.
            iCurrentCmd.push_front(aCmd);
            EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFErrArgument);
        }
    }
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelCommand() Out"));
}


void PVPlayerEngine::DoCancelAllCommands(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelAllCommands() In"));


    // Engine cannot be processing another cancel command
    OSCL_ASSERT(iCmdToCancel.empty() == true);

    // While AcquireLicense and CancelAcquireLicense is processing, CancelAllCommands is prohibited.
    if (!iCmdToDlaCancel.empty() ||
            (!iCurrentCmd.empty() &&
             (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_CANCEL_ACQUIRE_LICENSE ||
              iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_WCHAR ||
              iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_CHAR)))
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::DoCancelAllCommands() Error due to processing AcquireLicense or CancelAcquireLicense,CmdType=%d",
                         iCurrentCmd[0].GetCmdType()));
        PVPlayerEngineCommand currentcmd(iCurrentCmd[0]);
        iCurrentCmd.erase(iCurrentCmd.begin());
        iCurrentCmd.push_front(aCmd);
        EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFErrArgument);
        iCurrentCmd.push_front(currentcmd);
        return;
    }
    // set engine state to Resetting, as cancel command completion will take Engine to Idle state, after internal reset.
    SetEngineState(PVP_ENGINE_STATE_RESETTING);
    iRollOverState = RollOverStateIdle; //reset roll over state to Idle, as engine is resetting itself

    //Reset the variable iStartIssuedOnEngine
    iStartIssuedOnEngine = false;

    // Stop the playback clock
    iPlaybackClock.Stop();
    // Cancel the current command first
    if (iCurrentCmd.size() == 1)
    {
        // First save the current command being processed
        iCmdToCancel.push_front(iCurrentCmd[0]);
        // Cancel it
        EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), PVMFErrCancelled);
    }

    // Cancel all the pending commands

    // Create a temporary queue for pending commands
    OsclPriorityQueue<PVPlayerEngineCommand, OsclMemAllocator, Oscl_Vector<PVPlayerEngineCommand, OsclMemAllocator>, PVPlayerEngineCommandCompareLess> iTempPendingCmds;
    // Copy the pending commands to the new queue
    iTempPendingCmds = iPendingCmds;
    while (!iTempPendingCmds.empty())
    {
        // Get the queue from the top
        PVPlayerEngineCommand cmd(iTempPendingCmds.top());
        // Check if it needs to be cancelled
        if ((aCmd.GetCmdId() > cmd.GetCmdId()) && !((aCmd.GetCmdId() - cmd.GetCmdId()) > 0x7FFFFFFF))
        {
            // Remove it from the pending commands queue
            iPendingCmds.remove(cmd);
            // Save it temporary as "current command" and then cancel it
            iCurrentCmd.push_front(cmd);
            EngineCommandCompleted(cmd.GetCmdId(), cmd.GetContext(), PVMFErrCancelled);
        }
        // Pop each cmd from the temporary queue
        iTempPendingCmds.pop();
    }

    // Make the CancelAll() command the current command
    iCurrentCmd.push_front(aCmd);

    // Check if there was an ongoing command that needs to be properly cancelled
    if (!iCmdToCancel.empty())
    {
        // Properly cancel a command being currently processed
        DoCancelCommandBeingProcessed();
    }
    else
    {
        // Nothing to cancel, move on to resetting Source Nodes and Datapaths
        if (iSourceNode)
        {
            int32 leavecode = 0;
            // call reset on source node if not in created state
            if (iSourceNode->GetState() != EPVMFNodeCreated)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "PVPlayerEngine::DoCancelAllCommands() Issue reset on Source Node"));
                // error handling code set engine state to resetting
                SetEngineState(PVP_ENGINE_STATE_RESETTING);

                DereferenceLicenseInterface();

                PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, -1, NULL, -1);

                PVMFCommandId cmdid = -1;
                leavecode = 0;
                OSCL_TRY(leavecode, cmdid = iSourceNode->Reset(iSourceNodeSessionId, (OsclAny*)context));
                OSCL_FIRST_CATCH_ANY(leavecode,
                                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                                     (0, "PVPlayerEngine::DoCancelAllCommands() Reset on iSourceNode did a leave!"));
                                     FreeEngineContext(context);
                                     OSCL_ASSERT(false););

                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelAllCommands() Out"));

                return;
            }
        }

        iRemoveDataSource = true;
        SetEngineState(PVP_ENGINE_STATE_IDLE);
        EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelAllCommands() Out"));
}


void PVPlayerEngine::DoCancelCommandBeingProcessed(void)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelCommandBeingProcessed() In"));

    // There should be a command to cancel
    OSCL_ASSERT(iCmdToCancel.empty() == false);

    // If cmd to cancel is GetMetadataKeys() or GetMetadataValues(), first release the memory for
    // nodes which have already completed the call and then issue cancel on other nodes.
    switch (iCmdToCancel[0].GetCmdType())
    {
        case PVP_ENGINE_COMMAND_GET_METADATA_KEY:
        {
            // Release the memory allocated for the metadata keys
            while (iMetadataKeyReleaseList.empty() == false)
            {
                PVMFMetadataExtensionInterface* mdif = iMetadataIFList[iMetadataKeyReleaseList[0].iMetadataIFListIndex].iInterface;
                OSCL_ASSERT(mdif != NULL);
                mdif->ReleaseNodeMetadataKeys(*(iGetMetadataKeysParam.iKeyList), iMetadataKeyReleaseList[0].iStartIndex, iMetadataKeyReleaseList[0].iEndIndex);
                iMetadataKeyReleaseList.erase(iMetadataKeyReleaseList.begin());
            }
            // no need to break from the current switch, as we need to issue Cancel on nodes. Continue.
        }
        case PVP_ENGINE_COMMAND_GET_METADATA_VALUE:
        {
            // Release the memory allocated for the metadata values
            while (iMetadataValueReleaseList.empty() == false)
            {
                PVMFMetadataExtensionInterface* mdif = iMetadataIFList[iMetadataValueReleaseList[0].iMetadataIFListIndex].iInterface;
                OSCL_ASSERT(mdif != NULL);
                mdif->ReleaseNodeMetadataValues(*(iGetMetadataValuesParam.iValueList), iMetadataValueReleaseList[0].iStartIndex, iMetadataValueReleaseList[0].iEndIndex);
                iMetadataValueReleaseList.erase(iMetadataValueReleaseList.begin());
            }

            iReleaseMetadataValuesPending = false;
            // no need to break from the current switch, as we need to issue Cancel on nodes. Continue.
        }
        case PVP_ENGINE_COMMAND_ADD_DATA_SOURCE:
        case PVP_ENGINE_COMMAND_UPDATE_DATA_SOURCE:
        case PVP_ENGINE_COMMAND_INIT:
        case PVP_ENGINE_COMMAND_PREPARE:
        case PVP_ENGINE_COMMAND_PAUSE:
        case PVP_ENGINE_COMMAND_RESUME:
        case PVP_ENGINE_COMMAND_SET_PLAYBACK_RANGE:
        case PVP_ENGINE_COMMAND_SET_PLAYBACK_RATE:
        case PVP_ENGINE_COMMAND_CANCEL_COMMAND:
        case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_ENDTIME_REACHED:
        case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_ENDOFCLIP:
        case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_SET_PLAYBACK_RANGE:
        case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_BUFFER_UNDERFLOW:
        case PVP_ENGINE_COMMAND_RESUME_DUE_TO_BUFFER_DATAREADY:
        case PVP_ENGINE_COMMAND_STOP:
        {
            // go ahead and issue cancel on nodes and datapath if needed.
            if (!iCurrentContextList.empty())
            {
                // Since there is a pending node or datapath, cancel it
                PVMFStatus status = DoCancelPendingNodeDatapathCommand();
                if (status == PVMFPending)
                {
                    // There are some commands which need to be cancelled so wait for cancel complete
                    // once cancels complete, we would start the reset sequence from either
                    // NodeCommandComplete, HandlePlayerDataPathEvent, RecognizeComplete
                    break;
                }
            }

            // No pending command so reset the nodes now
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelCommandBeingProcessed() No command to cancel, now reset all nodes"));
            // Clear the CancelCmd queue as the cmd has been cancelled.
            iCmdToCancel.clear();

            DereferenceLicenseInterface();

            // reset the source node
            PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, -1, NULL, -1);

            PVMFCommandId cmdid = -1;
            int32 leavecode = 0;
            OSCL_TRY(leavecode, cmdid = iSourceNode->Reset(iSourceNodeSessionId, (OsclAny*)context));
            OSCL_FIRST_CATCH_ANY(leavecode,
                                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                                 (0, "PVPlayerEngine::DoCancelCommandBeingProcessed() Reset on iSourceNode did a leave!"));
                                 FreeEngineContext(context);
                                 OSCL_ASSERT(false);
                                 return);

            SetEngineState(PVP_ENGINE_STATE_RESETTING);
            break;
        }

        case PVP_ENGINE_COMMAND_QUERY_INTERFACE:
        case PVP_ENGINE_COMMAND_GET_PLAYBACK_RANGE:
        case PVP_ENGINE_COMMAND_GET_PLAYBACK_RATE:
        case PVP_ENGINE_COMMAND_GET_PLAYBACK_MINMAX_RATE:
        case PVP_ENGINE_COMMAND_GET_SDK_INFO:
        case PVP_ENGINE_COMMAND_GET_SDK_MODULE_INFO:
        case PVP_ENGINE_COMMAND_SET_LOG_APPENDER:
        case PVP_ENGINE_COMMAND_REMOVE_LOG_APPENDER:
        case PVP_ENGINE_COMMAND_SET_LOG_LEVEL:
        case PVP_ENGINE_COMMAND_GET_LOG_LEVEL:
        case PVP_ENGINE_COMMAND_CANCEL_ALL_COMMANDS:
        case PVP_ENGINE_COMMAND_GET_PVPLAYER_STATE:
        case PVP_ENGINE_COMMAND_ADD_DATA_SINK:
        case PVP_ENGINE_COMMAND_GET_CURRENT_POSITION:
        case PVP_ENGINE_COMMAND_START:
        case PVP_ENGINE_COMMAND_REMOVE_DATA_SINK:
        case PVP_ENGINE_COMMAND_REMOVE_DATA_SOURCE:
        default:
            // These commands should complete in one AO scheduling so there should be no need to cancel.
            // CancelAll() is done so complete it
            EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), PVMFSuccess);
            break;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelCommandBeingProcessed() Out"));
}


PVMFStatus PVPlayerEngine::DoCancelPendingNodeDatapathCommand()
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() In"));

    OSCL_ASSERT(iCurrentContextList.empty() == false);

    // Determine where the pending commands were issued to and then cancel them
    int32 leavecode = 0;
    iNumberCancelCmdPending = 0;
    for (int32 i = (OSCL_STATIC_CAST(int32, iCurrentContextList.size()) - 1); i >= 0; i--)
    {
        if (iCurrentContextList[i]->iNode)
        {
            if (iCurrentContextList[i]->iNode == iSourceNode)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                                (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() Calling CancelAllCommands() on source node"));
                leavecode = IssueNodeCancelCommand(iCurrentContextList[i], iSourceNodeSessionId, (OsclAny*) & iNumberCancelCmdPending);
                if (leavecode == 0)
                {
                    ++iNumberCancelCmdPending;
                }
                else
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                    (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() CancelAllCommands() on source node did a leave"));
                    FreeEngineContext(iCurrentContextList[i]);
                }
            }
            else if (iCurrentContextList[i]->iEngineDatapath != NULL)
            {
                if (iCurrentContextList[i]->iNode == iCurrentContextList[i]->iEngineDatapath->iSinkNode)
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                                    (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() Calling CancelAllCommands() on sink node"));
                    leavecode = IssueNodeCancelCommand(iCurrentContextList[i], iCurrentContextList[i]->iEngineDatapath->iSinkNodeSessionId,
                                                       (OsclAny*) & iNumberCancelCmdPending);
                    if (leavecode == 0)
                    {
                        ++iNumberCancelCmdPending;
                    }
                    else
                    {
                        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                        (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() CancelAllCommands() on sink node did a leave"));
                        FreeEngineContext(iCurrentContextList[i]);
                    }
                }
                else if (iCurrentContextList[i]->iNode == iCurrentContextList[i]->iEngineDatapath->iDecNode)
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                                    (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() Calling CancelAllCommands() on dec node"));
                    leavecode = IssueNodeCancelCommand(iCurrentContextList[i], iCurrentContextList[i]->iEngineDatapath->iDecNodeSessionId,
                                                       (OsclAny*) & iNumberCancelCmdPending);
                    if (leavecode == 0)
                    {
                        ++iNumberCancelCmdPending;
                    }
                    else
                    {
                        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                        (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() CancelAllCommands() on dec node did a leave"));
                        FreeEngineContext(iCurrentContextList[i]);
                    }
                }
                else
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() Unknown node type. Asserting"));
                    OSCL_ASSERT(false);
                }
            }
            else
            {
                // Entering here it might be possible that Engine is doing track selection and has issued a command on decoder node which has not yet made
                // to the PVPlayerEngineDatapath (iEngineDatapath). In that case go through all the decoder nodes in iTrackSelectionList and try to find a
                // matching decoder node. If found issue a cancel command to that node. If not found or if Engine is not doing Track Selection, then this is some
                // unknown node just assert.
                if (!iTrackSelectionList.empty())
                {
                    // Go through the TrackSelectionList used in TrackSelection
                    for (uint32 j = 0; j < iTrackSelectionList.size(); j++)
                    {
                        // Compare the node here
                        if ((iTrackSelectionList[j].iTsDecNode != NULL) && (iCurrentContextList[i]->iNode == iTrackSelectionList[j].iTsDecNode))
                        {
                            // Found the node, call Cancel Command on the node and also break out of the loop
                            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() Calling CancelAllCommands() on dec node"));
                            leavecode = IssueNodeCancelCommand(iCurrentContextList[i], iTrackSelectionList[j].iTsDecNodeSessionId, (OsclAny*) & iNumberCancelCmdPending);
                            if (leavecode == 0)
                            {
                                ++iNumberCancelCmdPending;
                            }
                            else
                            {
                                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                                (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() CancelAllCommands() on dec node did a leave"));
                                FreeEngineContext(iCurrentContextList[i]);
                            }
                            break;
                        }
                        // Node not found, continue checking the TrackSelectionList
                    }
                }
                else
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() Unknown node. Asserting"));
                    OSCL_ASSERT(false);
                }
            }
        }
        else if (iCurrentContextList[i]->iDatapath != NULL)
        {
            if (iCurrentContextList[i]->iEngineDatapath != NULL)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                                (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() Calling CancelAllCommands() on datapath"));
                leavecode = IssueDatapathCancelCommand(iCurrentContextList[i], (OsclAny*) & iNumberCancelCmdPending);
                if (leavecode == 0)
                {
                    ++iNumberCancelCmdPending;
                }
            }
            else
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() Unknown datapath. Asserting"));
                OSCL_ASSERT(false);
            }
        }
        else if (iCurrentContextList[i]->iCmdType == PVP_CMD_QUERYSOURCEFORMATTYPE)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                            (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() Calling CancelAllCommands() on recognizer"));
            leavecode = IssueRecognizerRegistryCancel((OsclAny*) & iNumberCancelCmdPending);
            if (leavecode == 0)
            {
                ++iNumberCancelCmdPending;
            }
            else
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() CancelAllCommands() on recognizer node did a leave"));
                FreeEngineContext(iCurrentContextList[i]);
            }
        }
        else
        {
            // Either a node or datapath should be pending
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() No pending node or datapath. Asserting"));
            OSCL_ASSERT(false);
        }
    }

    if (iNumberCancelCmdPending == 0)
    {
        // Cancel on the node / datapath failed so go to next step
        // Note that we do not care about not being able to queue cancel since
        // we are going to reset the components anyway
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() CancelAllCommands() on the node did a leave"));
        RemoveDatapathContextFromList(); // remove left-over datapath contexts
        return PVMFSuccess;
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                        (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() %d CancelAllCommands are pending", iNumberCancelCmdPending));
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() Out"));
    return PVMFPending;
}

PVMFStatus PVPlayerEngine::DoGetSDKInfo(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetSDKInfo() In"));

    PVSDKInfo* sdkinfo = (PVSDKInfo*)(aCmd.GetParam(0).pOsclAny_value);
    if (sdkinfo == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetSDKInfo() Passed in parameter invalid."));
        return PVMFErrArgument;
    }

    // Set the SDK info to the ones defined in the header file pv_player_sdkinfo.h generated at build time
    sdkinfo->iLabel = PVPLAYER_ENGINE_SDKINFO_LABEL;
    sdkinfo->iDate = PVPLAYER_ENGINE_SDKINFO_DATE;

    EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), PVMFSuccess);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetSDKInfo() Out"));
    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoSetLogAppender(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetLogAppender() In"));

    char* tag = (char*)(aCmd.GetParam(0).pChar_value);
    OsclSharedPtr<PVLoggerAppender>* appender = (OsclSharedPtr<PVLoggerAppender>*)(aCmd.GetParam(1).pOsclAny_value);

    if (tag == NULL || appender == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetLogAppender() Passed in parameter invalid."));
        return PVMFErrArgument;
    }

    // Get the logger node based on the specified tag
    PVLogger *rootnode = PVLogger::GetLoggerObject(tag);
    if (rootnode == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetLogAppender() Node specified by tag is invalid"));
        return PVMFErrBadHandle;
    }

    // Add the specified appender to this node
    rootnode->AddAppender(*appender);

    EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);


    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetLogAppender() Out"));
    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoRemoveLogAppender(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoRemoveLogAppender() In"));

    char* tag = (char*)(aCmd.GetParam(0).pChar_value);
    OsclSharedPtr<PVLoggerAppender>* appender = (OsclSharedPtr<PVLoggerAppender>*)(aCmd.GetParam(1).pOsclAny_value);

    if (tag == NULL || appender == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoRemoveLogAppender() Passed in parameter invalid."));
        return PVMFErrArgument;
    }

    // Get the logger node based on the specified tag
    PVLogger *lognode = PVLogger::GetLoggerObject(tag);
    if (lognode == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoRemoveLogAppender() Node specified by tag is invalid"));
        return PVMFErrBadHandle;
    }

    // Remove the specified appender to this node
    lognode->RemoveAppender(*appender);

    EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);


    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoRemoveLogAppender() Out"));
    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoSetLogLevel(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetLogLevel() In"));

    char* tag = (char*)(aCmd.GetParam(0).pChar_value);
    int32 level = aCmd.GetParam(1).int32_value;
    bool subtree = aCmd.GetParam(2).bool_value;

    if (tag == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetLogLevel() Passed in parameter invalid."));
        return PVMFErrArgument;
    }

    // Get the logger node based on the specified tag
    PVLogger *lognode = PVLogger::GetLoggerObject(tag);
    if (lognode == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetLogLevel() Node specified by tag is invalid"));
        return PVMFErrBadHandle;
    }

    // Set the log level
    if (subtree)
    {
        lognode->SetLogLevelAndPropagate(level);
    }
    else
    {
        lognode->SetLogLevel(level);
    }

    EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);


    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetLogLevel() Out"));
    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoGetLogLevel(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetLogLevel() In"));

    char* tag = (char*)(aCmd.GetParam(0).pChar_value);
    PVLogLevelInfo* levelinfo = (PVLogLevelInfo*)(aCmd.GetParam(1).pOsclAny_value);

    if (tag == NULL || levelinfo == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetLogLevel() Passed in parameter invalid."));
        return PVMFErrArgument;
    }

    // Get the logger node based on the specified tag
    PVLogger *lognode = PVLogger::GetLoggerObject(tag);
    if (lognode == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetLogLevel() Node specified by tag is invalid"));
        return PVMFErrBadHandle;
    }

    // Get the log level info
    *levelinfo = lognode->GetLogLevel();

    EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetLogLevel() Out"));
    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::DoQueryInterface(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoQueryInterface() In"));

    PVInterface** ifptr = (PVInterface**)(aCmd.GetParam(0).pOsclAny_value);
    PVUuid uuid = aCmd.GetUuid();
    if (ifptr == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoQueryInterface() Passed in parameter invalid."));
        return PVMFErrArgument;
    }

    PVMFStatus cmdstatus = PVMFSuccess;
    if (queryInterface(uuid, *ifptr) == false)
    {
        cmdstatus = PVMFErrNotSupported;
    }
    else
    {
        (*ifptr)->addRef();
    }

    EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), cmdstatus);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoQueryInterface() Out"));
    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoGetPVPlayerState(PVPlayerEngineCommand& aCmd, bool aSyncCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetPVPlayerState() In"));

    PVPlayerState* state = (PVPlayerState*)(aCmd.GetParam(0).pOsclAny_value);
    if (state == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPVPlayerState() Passed in parameter invalid."));
        return PVMFErrArgument;
    }

    // Get player state using internal function
    *state = GetPVPlayerState();

    if (!aSyncCmd)
    {
        EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetPVPlayerState() Out"));
    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoAddDataSource(PVPlayerEngineCommand& aCmd)
{
    // reset number of queued clips
    iNumClipsQueued = 0;
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE,
                    (0, "PVPlayerEngine::DoAddDataSource() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoAddDataSource() In"));

    if (GetPVPlayerState() != PVP_STATE_IDLE)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAddDataSource() Wrong engine state"));
        return PVMFErrInvalidState;
    }

    if (aCmd.GetParam(0).pOsclAny_value == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAddDataSource() Passed in parameter invalid."));
        return PVMFErrArgument;
    }

    // Save the data source
    iDataSource = (PVPlayerDataSource*)(aCmd.GetParam(0).pOsclAny_value);
    PVInterface* pvInterface = OSCL_STATIC_CAST(PVInterface*, (iDataSource->GetDataSourceContextData()));
    uint32 intent = 0;
    bool isIntentPresent = false;
    if (pvInterface)
    {
        PVInterface* localDataSrc = NULL;
        PVUuid localDataSrcUuid(PVMF_LOCAL_DATASOURCE_UUID);
        if (pvInterface->queryInterface(localDataSrcUuid, localDataSrc))
        {
            PVMFLocalDataSource* opaqueData =
                OSCL_STATIC_CAST(PVMFLocalDataSource*, localDataSrc);
            intent = opaqueData->iIntent;
            isIntentPresent = true;
        }
        else
        {
            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))
            {
                if (sourceDataContext->queryInterface(commonContextUuid, commonDataContext))
                {
                    PVMFSourceContextDataCommon* cContext =
                        OSCL_STATIC_CAST(PVMFSourceContextDataCommon*, commonDataContext);
                    intent = cContext->iIntent;
                    isIntentPresent = true;
                }
            }
        }
        if ((isIntentPresent) &&
                (((intent & (BITMASK_PVMF_SOURCE_INTENT_THUMBNAILS + BITMASK_PVMF_SOURCE_INTENT_PLAY + BITMASK_PVMF_SOURCE_INTENT_GETMETADATA)) == 0) ||
                 ((intent & (BITMASK_PVMF_SOURCE_INTENT_THUMBNAILS + BITMASK_PVMF_SOURCE_INTENT_PLAY))
                  == (BITMASK_PVMF_SOURCE_INTENT_THUMBNAILS + BITMASK_PVMF_SOURCE_INTENT_PLAY))))
        {
            // 1. Make sure that atleast one of the available intents is set.
            // 2. Make sure that thumbnail and play intents are not set simultaneously.
            PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::DoAddDataSource() Intent (0x%x) passed in source context data is not valid.", intent));
            return PVMFErrArgument;
        }
    }

    // (mg) For rollover reset to first available alternate
    iAlternateSrcFormatIndex = 0;
    iDataReadySent = false;

    // Check the source format and do a recognize if unknown
    PVMFStatus retval = PVMFSuccess;
    uint32 clipIndex = 0;
    iDataSource->SetCurrentClip(clipIndex);
    iSourceFormatType = iDataSource->GetDataSourceFormatType();

    if (iSourceFormatType == PVMF_MIME_FORMAT_UNKNOWN)
    {
        retval = DoQuerySourceFormatType(aCmd.GetCmdId(), aCmd.GetContext());
    }
    else
    {
        if (iSourceFormatType == PVMF_MIME_DATA_SOURCE_UNKNOWN_URL)
        {
            retval = SetupDataSourceForUnknownURLAccess();
            if (retval != PVMFSuccess)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoAddDataSource() - SetupDataSourceForUnknownURLAccess Failed"));
                return retval;
            }
        }

        // Start the source node creation and setup sequence
        retval = DoSetupSourceNode(aCmd.GetCmdId(), aCmd.GetContext());

        if (retval != PVMFSuccess)
        {
            return AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_ADD_DATA_SOURCE, retval, NULL);
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoAddDataSource() Out"));
    return retval;

}

PVMFStatus PVPlayerEngine::DoUpdateDataSource(PVPlayerEngineCommand& aCmd)
{
    // reset number of queued clips
    iNumClipsQueued = 0;
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::DoUpdateDataSource() Tick=%d", OsclTickCount::TickCount()));
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoUpdateDataSource() In"));

    if (iDataSource == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoUpdateDataSource() Wrong engine state"));
        return PVMFErrInvalidState;
    }

    PVMFStatus retval = PVMFFailure;
    PVMFStatus status =  PVMFSuccess;

    for (uint32 clipIndex = 0; clipIndex < iDataSource->GetNumClips(); clipIndex++)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVPlayerEngine::DoUpdateDataSource() - Set index of current clip to %d", clipIndex));
        iDataSource->SetCurrentClip(clipIndex);

        //retrieve data from new data source and update the existing data source with engine
        OSCL_wHeapString<OsclMemAllocator> sourceURL;
        // In case the URL starts with file:// skip it
        OSCL_wStackString<8> fileScheme(_STRLIT_WCHAR("file"));
        OSCL_wStackString<8> schemeDelimiter(_STRLIT_WCHAR("://"));
        const oscl_wchar* actualURL = NULL;

        if (oscl_strncmp(fileScheme.get_cstr(), iDataSource->GetDataSourceURL().get_cstr(), 4) == 0)
        {
            actualURL = oscl_strstr(iDataSource->GetDataSourceURL().get_cstr(), schemeDelimiter.get_cstr());
            if (actualURL == NULL)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryTrackSelIF() Unable to skip over file://"));
                return PVMFErrArgument;
            }
            //skip over ://
            actualURL += schemeDelimiter.get_size();
            sourceURL += actualURL;
        }
        else
        {
            sourceURL += iDataSource->GetDataSourceURL().get_cstr();
        }
        PVMFFormatType srcFormatType = iDataSource->GetDataSourceFormatType();
        retval = iSourceNodeInitIF->SetSourceInitializationData(sourceURL, srcFormatType,
                 iDataSource->GetDataSourceContextData(),
                 clipIndex);

        if (retval == PVMFSuccess || retval == PVMFErrAlreadyExists)
        {
            iNumClipsQueued++;
        }
        else
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoUpdateDataSource() SetSourceInitializationData failed errCode %d", retval));
            if (retval == PVMFErrNotSupported)
            {
                status =  PVMFFailure;
                // dont ignore update failure for clips index == 0
                if (clipIndex == 0)
                {
                    return PVMFFailure;
                }
            }
        }
    }

    if (status != PVMFSuccess)
    {
        return status;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoUpdateDataSource() Out"));
    EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), retval);
    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::DoQuerySourceFormatType(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::DoQuerySourceFormatType() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoQuerySourceFormatType() In"));

    // Use the recognizer if the source format type is unknown
    OSCL_ASSERT(iDataSource != NULL);
    PVPlayerEngineContext* context = AllocateEngineContext(NULL, NULL, NULL, aCmdId, aCmdContext, PVP_CMD_QUERYSOURCEFORMATTYPE);
    PVMFStatus retval = PVMFSuccess;
    int32 leavecode = 0;

    OsclAny * opaqueData = iDataSource->GetDataSourceContextData();
    PVInterface* pvInterface = OSCL_STATIC_CAST(PVInterface*, opaqueData);
    PVInterface* SourceContextData = NULL;
    PVUuid SourceContextDataUuid(PVMF_SOURCE_CONTEXT_DATA_UUID);
    PVMFCPMPluginAccessInterfaceFactory * DataStreamDataFactory = NULL;

    if (pvInterface != NULL && pvInterface->queryInterface(SourceContextDataUuid, SourceContextData))
    {
        PVMFSourceContextData * aSourceContextData = OSCL_STATIC_CAST(PVMFSourceContextData*, SourceContextData);
        PVMFSourceContextDataCommon * aSourceContextDataCommon = aSourceContextData->CommonData();
        if (aSourceContextDataCommon)
        {
            DataStreamDataFactory = aSourceContextDataCommon->iRecognizerDataStreamFactory;
        }
    }

    if (DataStreamDataFactory)
    {
        OSCL_TRY(leavecode, retval = iPlayerRecognizerRegistry.QueryFormatType(DataStreamDataFactory, *this, (OsclAny*) context));
        OSCL_FIRST_CATCH_ANY(leavecode,
                             retval = PVMFErrNotSupported;
                            );
    }
    else
    {
        OsclFileHandle* fileHandle = NULL;

        OsclAny* sourceData = iDataSource->GetDataSourceContextData();
        PVInterface* localDataSrc = NULL;
        PVUuid localDataSrcUuid(PVMF_LOCAL_DATASOURCE_UUID);
        PVInterface* pvInterface = OSCL_STATIC_CAST(PVInterface*, sourceData);

        if (pvInterface != NULL)
        {
            if (pvInterface->queryInterface(localDataSrcUuid, localDataSrc))
            {
                PVMFLocalDataSource* opaqueData = OSCL_STATIC_CAST(PVMFLocalDataSource*, localDataSrc);
                fileHandle = opaqueData->iFileHandle;
            }
            else
            {
                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);

                    if (context->iFileHandle)
                    {
                        fileHandle = context->iFileHandle;
                    }
                }
            }
        }

        retval = DoSourceURLQueryFormatType(context, fileHandle);
    }

    if (retval != PVMFSuccess)
    {
        FreeEngineContext(context);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoQuerySourceFormatType() Out - retval = %d", retval));
    return retval;
}


PVMFStatus PVPlayerEngine::DoSetupSourceNode(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::DoSetupSourceNode() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetupSourceNode() In"));

    OSCL_ASSERT(iDataSource != NULL);

    if (iSourceNode == NULL)
    {
        PVMFFormatType outputformattype = PVMF_MIME_FORMAT_UNKNOWN ;

        Oscl_Vector<PVUuid, OsclMemAllocator> foundUuids;
        // Query the node registry
        if (iPlayerNodeRegistry.QueryRegistry(iSourceFormatType, outputformattype, foundUuids) == PVMFSuccess)
        {
            if (foundUuids.empty())
            {
                // No matching node found
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "PVPlayerEngine::DoSetupSourceNode() Query Regsitry successful, No matching source node found."));
                return PVMFErrNotSupported;
            }

            int32 leavecode = 0;
            OSCL_TRY(leavecode, iSourceNode = iPlayerNodeRegistry.CreateNode(foundUuids[0]));
            OSCL_FIRST_CATCH_ANY(leavecode,
                                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupDecNode() Error in creating SourceNode"));
                                 return PVMFFailure;);

            iNodeUuids.push_back(PVPlayerEngineUuidNodeMapping(foundUuids[0], iSourceNode));

            if (iSourceNode == NULL)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupSourceNode() Source node create failed"));
                return PVMFErrNoMemory;
            }
        }
        else
        {
            // Registry query failed
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupSourceNode() Registry query for source node failed"));
            return PVMFErrNotSupported;
        }
    }

    if (iSourceNode->ThreadLogon() != PVMFSuccess)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupSourceNode() ThreadLogon() on the source node failed"));
        OSCL_ASSERT(false);
        return PVMFFailure;
    }

    PVMFNodeSessionInfo nodesessioninfo(this, this, (OsclAny*)iSourceNode, this, (OsclAny*)iSourceNode);
    int32 leavecode = 0;
    OSCL_TRY(leavecode, iSourceNodeSessionId = iSourceNode->Connect(nodesessioninfo));
    OSCL_FIRST_CATCH_ANY(leavecode,
                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupSourceNode() Connect on iSourceNode did a leave!"));
                         OSCL_ASSERT(false);
                         return PVMFFailure);

    PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQueryInitIF);

    PVUuid sourceinituuid = PVMF_DATA_SOURCE_INIT_INTERFACE_UUID;
    leavecode = 0;
    PVMFCommandId cmdid = -1;
    iSourceNodePVInterfaceInit = NULL;
    OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, sourceinituuid, iSourceNodePVInterfaceInit, (OsclAny*)context));
    OSCL_FIRST_CATCH_ANY(leavecode,
                         iSourceNodePVInterfaceInit = NULL;
                         FreeEngineContext(context);
                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupSourceNode() QueryInterface on iSourceNode did a leave!"));
                         return PVMFFailure);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetupSourceNode() Out"));
    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoSourceNodeQueryTrackSelIF(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVPlayerEngine::DoSourceNodeQueryTrackSelIF() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeQueryTrackSelIF() In"));

    int32 leavecode = 0;

    if (iDataSource->GetDataSourceType() == PVP_DATASRCTYPE_URL)
    {
        // Setup the source node via the initialization IF
        OSCL_ASSERT(iSourceFormatType != PVMF_MIME_FORMAT_UNKNOWN);

        for (uint32 clipIndex = 0; clipIndex < iDataSource->GetNumClips(); clipIndex++)
        {

            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVPlayerEngine::DoSourceNodeQueryTrackSelIF() - Set index of current clip to %d", clipIndex));
            iDataSource->SetCurrentClip(clipIndex);

            OSCL_wHeapString<OsclMemAllocator> sourceURL;
            // In case the URL starts with file:// skip it
            OSCL_wStackString<8> fileScheme(_STRLIT_WCHAR("file"));
            OSCL_wStackString<8> schemeDelimiter(_STRLIT_WCHAR("://"));
            const oscl_wchar* actualURL = NULL;

            if (oscl_strncmp(fileScheme.get_cstr(), iDataSource->GetDataSourceURL().get_cstr(), 4) == 0)
            {
                actualURL = oscl_strstr(iDataSource->GetDataSourceURL().get_cstr(), schemeDelimiter.get_cstr());
                if (actualURL == NULL)
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryTrackSelIF() Unable to skip over file://"));
                    return PVMFErrArgument;
                }
                //skip over ://
                actualURL += schemeDelimiter.get_size();
                sourceURL += actualURL;
            }
            else
            {
                sourceURL += iDataSource->GetDataSourceURL().get_cstr();
            }

            PVMFStatus retval = PVMFFailure;
            if (clipIndex > 0)
            {
                PVMFFormatType srcFormatType = iDataSource->GetDataSourceFormatType();
                retval = iSourceNodeInitIF->SetSourceInitializationData(sourceURL, srcFormatType, iDataSource->GetDataSourceContextData(), clipIndex);
            }
            else
            {
                retval = iSourceNodeInitIF->SetSourceInitializationData(sourceURL, iSourceFormatType, iDataSource->GetDataSourceContextData(), clipIndex);
            }

            if (retval == PVMFSuccess || retval == PVMFErrAlreadyExists)
            {
                iNumClipsQueued++;
            }
            else
            {
                if (retval == PVMFErrNotSupported)
                {
                    // dont ignore update failure for clips index == 0
                    if (clipIndex == 0)
                    {
                        return PVMFFailure;
                    }
                }
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryTrackSelIF() SetSourceInitializationData failed errcode %d", retval));

            }
        }
        // Set Playback Clock
        PVMFStatus status = iSourceNodeInitIF->SetClientPlayBackClock(&iPlaybackClock);
        if (status != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryTrackSelIF() SetClientPlayBackClock failed!"));
            return PVMFFailure;
        }
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryTrackSelIF() Data source type not supported yet so asserting"));
        OSCL_ASSERT(false);
        return PVMFFailure;
    }

    PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQueryTrackSelIF);

    // Query the source node for the track selection IF
    PVUuid trackseluuid = PVMF_TRACK_SELECTION_INTERFACE_UUID;
    PVMFCommandId cmdid = -1;
    leavecode = 0;
    iSourceNodePVInterfaceTrackSel = NULL;
    OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, trackseluuid, iSourceNodePVInterfaceTrackSel, (OsclAny*)context));
    OSCL_FIRST_CATCH_ANY(leavecode,
                         iSourceNodePVInterfaceTrackSel = NULL;
                         FreeEngineContext(context);
                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryTrackSelIF() QueryInterface on iSourceNode did a leave!"));
                         return PVMFFailure);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeQueryTrackSelIF() Out"));
    return PVMFSuccess;
}

void PVPlayerEngine::DoSourceNodeQueryCPMLicenseInterface(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    if (iCPMLicenseIF)
    {
        return;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVPlayerEngine::DoSourceNodeQueryCPMLicenseInterface() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeQueryCPMLicenseInterface() In"));

    // Query for CPM License interface
    PVPlayerEngineContext* context = NULL;
    PVMFCommandId cmdid = -1;
    int32 leavecode = 0;

    context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQueryCPMLicenseIF);
    PVUuid licUuid = PVMFCPMPluginLicenseInterfaceUuid;
    iPVInterfaceCPMLicense = NULL;
    OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, licUuid, iPVInterfaceCPMLicense, (OsclAny*)context));
    if (leavecode)
    {
        iPVInterfaceCPMLicense = NULL;
        FreeEngineContext(context);
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryCPMLicenseInterface() QueryInterface on iSourceNode did a leave!"));
        return;
    }
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeQueryCPMLicenseInterface() Out"));
    return;
}

PVMFStatus PVPlayerEngine::DoSourceNodeQueryInterfaceOptional(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVPlayerEngine::DoSourceNodeQueryInterfaceOptional() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeQueryInterfaceOptional() In"));

    PVPlayerEngineContext* context = NULL;
    PVMFCommandId cmdid = -1;
    int32 leavecode = 0;

    iNumPendingNodeCmd = 0;

    // Query for Track Level Info IF
    context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQueryTrackLevelInfoIF);
    PVUuid tracklevelinfouuid = PVMF_TRACK_LEVEL_INFO_INTERFACE_UUID;
    cmdid = -1;
    leavecode = 0;
    iSourceNodePVInterfaceTrackLevelInfo = NULL;
    OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, tracklevelinfouuid, iSourceNodePVInterfaceTrackLevelInfo, (OsclAny*)context));
    if (leavecode)
    {
        iSourceNodePVInterfaceTrackLevelInfo = NULL;
        FreeEngineContext(context);
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryInterfaceOptional() QueryInterface on iSourceNode did a leave!"));
    }
    else
    {
        ++iNumPendingNodeCmd;
    }

    // Query for Playback Control IF
    context = NULL;
    context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQueryPBCtrlIF);
    PVUuid pbctrluuid = PvmfDataSourcePlaybackControlUuid;
    cmdid = -1;
    leavecode = 0;
    iSourceNodePVInterfacePBCtrl = NULL;
    OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, pbctrluuid, iSourceNodePVInterfacePBCtrl, (OsclAny*)context));
    if (leavecode)
    {
        iSourceNodePVInterfacePBCtrl = NULL;
        FreeEngineContext(context);
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryInterfaceOptional() QueryInterface on iSourceNode did a leave!"));
    }
    else
    {
        ++iNumPendingNodeCmd;
    }

    // Query for direction control IF
    context = NULL;
    context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQueryDirCtrlIF);
    PVUuid dirctrluuid = PvmfDataSourceDirectionControlUuid;
    cmdid = -1;
    leavecode = 0;
    iSourceNodePVInterfaceDirCtrl = NULL;
    OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, dirctrluuid, iSourceNodePVInterfaceDirCtrl, (OsclAny*)context));
    if (leavecode)
    {
        iSourceNodePVInterfaceDirCtrl = NULL;
        FreeEngineContext(context);
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryInterfaceOptional() QueryInterface on iSourceNode did a leave!"));
    }
    else
    {
        ++iNumPendingNodeCmd;
    }

    // Query for Metadata IF
    context = NULL;
    context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQueryMetadataIF);
    PVUuid metadatauuid = KPVMFMetadataExtensionUuid;
    cmdid = -1;
    leavecode = 0;
    iSourceNodePVInterfaceMetadataExt = NULL;
    OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, metadatauuid, iSourceNodePVInterfaceMetadataExt, (OsclAny*)context));
    if (leavecode)
    {
        iSourceNodePVInterfaceMetadataExt = NULL;
        FreeEngineContext(context);
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryInterfaceOptional() QueryInterface on iSourceNode did a leave!"));
    }
    else
    {
        ++iNumPendingNodeCmd;
    }

    // Query for Cap-Config IF
    context = NULL;
    context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQueryCapConfigIF);
    PVUuid capconfiguuid = PVMI_CAPABILITY_AND_CONFIG_PVUUID;
    cmdid = -1;
    leavecode = 0;
    iSourceNodePVInterfaceCapConfig = NULL;
    OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, capconfiguuid, iSourceNodePVInterfaceCapConfig, (OsclAny*)context));
    if (leavecode)
    {
        iSourceNodePVInterfaceCapConfig = NULL;
        FreeEngineContext(context);
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryInterfaceOptional() QueryInterface on iSourceNode did a leave!"));
    }
    else
    {
        ++iNumPendingNodeCmd;
    }

    // Query for source node registry init extension IF
    context = NULL;
    context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQuerySrcNodeRegInitIF);
    PVUuid regInitUuid = PVMF_DATA_SOURCE_NODE_REGISRTY_INIT_INTERFACE_UUID;
    cmdid = -1;
    leavecode = 0;
    iSourceNodePVInterfaceRegInit = NULL;
    OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, regInitUuid, iSourceNodePVInterfaceRegInit, (OsclAny*)context));
    if (leavecode)
    {
        iSourceNodePVInterfaceRegInit = NULL;
        FreeEngineContext(context);
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryInterfaceOptional() QueryInterface on iSourceNode did a leave!"));
    }
    else
    {
        ++iNumPendingNodeCmd;
    }

    if (iNumPendingNodeCmd > 0)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeQueryInterfaceOptional() Out"));
        return PVMFSuccess;
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeQueryInterfaceOptional() Out No pending QueryInterface() on source node"));
        return PVMFFailure;
    }
}

PVMFStatus PVPlayerEngine::DoGetMetadataKey(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE,
                    (0, "PVPlayerEngine::DoGetMetadataKey() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetMetadataKey() In"));

    if (GetPVPlayerState() == PVP_STATE_ERROR)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetMetadataKey() Wrong engine state."));
        return PVMFFailure;
    }

    iGetMetadataKeysParam.iKeyList = (PVPMetadataList*)(aCmd.GetParam(0).pOsclAny_value);
    iGetMetadataKeysParam.iStartingKeyIndex = aCmd.GetParam(1).int32_value;
    iGetMetadataKeysParam.iMaxKeyEntries = aCmd.GetParam(2).int32_value;
    iGetMetadataKeysParam.iQueryKey = aCmd.GetParam(3).pChar_value;
    iGetMetadataKeysParam.iClipIndex = aCmd.GetParam(4).uint32_value;

    if (iGetMetadataKeysParam.iKeyList == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetMetadataKey() Passed in parameter invalid."));
        return PVMFErrArgument;
    }

    if (iGetMetadataKeysParam.iMaxKeyEntries < -1 || iGetMetadataKeysParam.iMaxKeyEntries == 0 || iGetMetadataKeysParam.iStartingKeyIndex < 0)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetMetadataKey() Passed in parameter invalid."));
        return PVMFErrArgument;
    }

    // Determine which node's metadata interface to start the retrieval based on the starting index
    uint32 i = 0;
    int32 totalnumkey = 0;
    uint32 nodestartindex = 0;
    while (i < iMetadataIFList.size())
    {
        int32 numkey = iMetadataIFList[i].iInterface->GetNumMetadataKeys(iGetMetadataKeysParam.iQueryKey);
        if (iGetMetadataKeysParam.iStartingKeyIndex < (totalnumkey + numkey))
        {
            // Found the node to start the key retrieval
            // Determine the start index for this node
            nodestartindex = iGetMetadataKeysParam.iStartingKeyIndex - totalnumkey;
            break;
        }
        else
        {
            // Keep checking
            totalnumkey += numkey;
            ++i;
        }
    }

    // Check if the search succeeded
    if (i == iMetadataIFList.size() || iMetadataIFList.size() == 0)
    {
        // Starting index is too large or there is no metadata interface available
        return PVMFErrArgument;
    }

    // Retrieve the metadata key from the first node
    PVPlayerEngineContext* context = AllocateEngineContext(iMetadataIFList[i].iEngineDatapath, iMetadataIFList[i].iNode, NULL, aCmd.GetCmdId(), aCmd.GetContext(), PVP_CMD_GetNodeMetadataKey);
    PVMFMetadataExtensionInterface* metadataif = iMetadataIFList[i].iInterface;
    PVMFSessionId sessionid = iMetadataIFList[i].iSessionId;
    PVMFCommandId cmdid = -1;
    metadataif->SetMetadataClipIndex(iGetMetadataKeysParam.iClipIndex);
    cmdid = metadataif->GetNodeMetadataKeys(sessionid,
                                            *(iGetMetadataKeysParam.iKeyList),
                                            nodestartindex,
                                            iGetMetadataKeysParam.iMaxKeyEntries,
                                            iGetMetadataKeysParam.iQueryKey,
                                            (OsclAny*)context);
    if (cmdid == -1)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::DoGetMetadataKey() GetNodeMetadataKeys failed"));
        return PVMFFailure;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetMetadataKey() Out"));

    // Save the current metadata value retrieval status
    iGetMetadataKeysParam.iCurrentInterfaceIndex = i;
    iGetMetadataKeysParam.iNumKeyEntriesToFill = iGetMetadataKeysParam.iMaxKeyEntries;
    iGetMetadataKeysParam.iNumKeyEntriesInList = iGetMetadataKeysParam.iKeyList->size();

    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoGetMetadataValue(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE,
                    (0, "PVPlayerEngine::DoGetMetadataValue() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetMetadataValue() In"));

    if (GetPVPlayerState() == PVP_STATE_ERROR)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetMetadataValue() Wrong engine state"));
        return PVMFErrInvalidState;
    }

    if (iReleaseMetadataValuesPending)
    {
        // App has called GetMetadataValues without calling ReleaseMetadata values on previous list. Wrong
        // usage. Failure needs to be returned in this case.
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::GetMetadataValues() Wrong usage, called again without releasing earlier metadata list"));
        return PVMFErrReleaseMetadataValueNotDone;
    }

    iGetMetadataValuesParam.iKeyList = (PVPMetadataList*)(aCmd.GetParam(0).pOsclAny_value);
    iGetMetadataValuesParam.iStartingValueIndex = aCmd.GetParam(1).int32_value;
    iGetMetadataValuesParam.iMaxValueEntries = aCmd.GetParam(2).int32_value;
    iGetMetadataValuesParam.iNumAvailableValues = (int32*)(aCmd.GetParam(3).pOsclAny_value);
    iGetMetadataValuesParam.iValueList = (Oscl_Vector<PvmiKvp, OsclMemAllocator>*)(aCmd.GetParam(4).pOsclAny_value);
    iMetadataValuesCopiedInCallBack = aCmd.GetParam(5).bool_value;
    iGetMetadataValuesParam.iClipIndex = aCmd.GetParam(6).uint32_value;

    if (iGetMetadataValuesParam.iKeyList == NULL || iGetMetadataValuesParam.iValueList == NULL || iGetMetadataValuesParam.iNumAvailableValues == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetMetadataValue() Passed in parameter invalid."));
        return PVMFErrArgument;
    }

    if (iGetMetadataValuesParam.iMaxValueEntries < -1 || iGetMetadataValuesParam.iMaxValueEntries == 0 || iGetMetadataValuesParam.iStartingValueIndex < 0)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetMetadataValue() Passed in parameter invalid."));
        return PVMFErrArgument;
    }

    // Determine which node's metadata interface to start the retrieval based on the starting index
    uint32 i = 0;
    int32 totalnumvalue = 0;
    uint32 nodestartindex = 0;
    while (i < iMetadataIFList.size())
    {
        int32 numvalue = iMetadataIFList[i].iInterface->GetNumMetadataValues(*(iGetMetadataValuesParam.iKeyList));
        if (iGetMetadataValuesParam.iStartingValueIndex < (totalnumvalue + numvalue))
        {
            // Found the node to start the value retrieval
            // Determine the start index for this node
            nodestartindex = iGetMetadataValuesParam.iStartingValueIndex - totalnumvalue;
            // Save the number of available values so far
            *(iGetMetadataValuesParam.iNumAvailableValues) = totalnumvalue + numvalue;
            break;
        }
        else
        {
            // Keep checking
            totalnumvalue += numvalue;
            ++i;
        }
    }

    // Check if the search succeeded
    if (i == iMetadataIFList.size() || iMetadataIFList.size() == 0)
    {
        // Starting index is too large or there is no metadata interface available.
        // Return success and a list with nothing
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetMetadataValue()"
                        "No MetadataValue to return, return success and a list with nothing"));
        EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
        return PVMFSuccess;
    }

    // Retrieve the metadata value from the first node
    PVPlayerEngineContext* context = AllocateEngineContext(iMetadataIFList[i].iEngineDatapath, iMetadataIFList[i].iNode, NULL, aCmd.GetCmdId(), aCmd.GetContext(), PVP_CMD_GetNodeMetadataValue);
    PVMFMetadataExtensionInterface* metadataif = iMetadataIFList[i].iInterface;
    PVMFSessionId sessionid = iMetadataIFList[i].iSessionId;
    PVMFCommandId cmdid = -1;
    metadataif->SetMetadataClipIndex(iGetMetadataValuesParam.iClipIndex);
    cmdid = metadataif->GetNodeMetadataValues(sessionid,
            *(iGetMetadataValuesParam.iKeyList),
            *(iGetMetadataValuesParam.iValueList),
            nodestartindex,
            iGetMetadataValuesParam.iMaxValueEntries,
            (OsclAny*)context);

    if (cmdid == -1)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::DoGetMetadataValue() GetNodeMetadataValues failed"));
        return PVMFFailure;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetMetadataValue() Out"));

    // Save the current metadata value retrieval status
    iGetMetadataValuesParam.iCurrentInterfaceIndex = i;
    iGetMetadataValuesParam.iNumValueEntriesToFill = iGetMetadataValuesParam.iMaxValueEntries;
    iGetMetadataValuesParam.iNumValueEntriesInList = iGetMetadataValuesParam.iValueList->size();

    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::DoReleaseMetadataValues(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE,
                    (0, "PVPlayerEngine::DoReleaseMetadataValues() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoReleaseMetadataValues() In"));

    if (GetPVPlayerState() == PVP_STATE_ERROR ||
            GetPVPlayerState() == PVP_STATE_IDLE)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoReleaseMetadataValues() Wrong engine state"));
        return PVMFErrInvalidState;
    }

    iGetMetadataValuesParam.iValueList = (Oscl_Vector<PvmiKvp, OsclMemAllocator>*)(aCmd.GetParam(0).pOsclAny_value);
    iGetMetadataValuesParam.iClipIndex = aCmd.GetParam(1).uint32_value;

    if (iGetMetadataValuesParam.iValueList == NULL || iGetMetadataValuesParam.iClipIndex < 0)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoReleaseMetadataValues() Passed in parameter invalid."));
        return PVMFErrArgument;
    }

    // Release the memory allocated for the metadata values
    while (iMetadataValueReleaseList.empty() == false)
    {
        PVMFMetadataExtensionInterface* mdif = iMetadataIFList[iMetadataValueReleaseList[0].iMetadataIFListIndex].iInterface;
        OSCL_ASSERT(mdif != NULL);
        if (PVMFSuccess == mdif->SetMetadataClipIndex(iGetMetadataValuesParam.iClipIndex))
        {
            mdif->ReleaseNodeMetadataValues(*(iGetMetadataValuesParam.iValueList), iMetadataValueReleaseList[0].iStartIndex, iMetadataValueReleaseList[0].iEndIndex);
            iMetadataValueReleaseList.erase(iMetadataValueReleaseList.begin());
        }
    }

    iReleaseMetadataValuesPending = false;

    EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);

    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::DoInit(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE,
                    (0, "PVPlayerEngine::DoInit() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoInit() In"));

    if (GetPVPlayerState() == PVP_STATE_INITIALIZED)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoInit() Engine already in Initialized State"));
        EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
        return PVMFSuccess;
    }

    if ((GetPVPlayerState() != PVP_STATE_IDLE) || (iSourceNode == NULL))
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoInit() Wrong engine state"));
        return PVMFErrInvalidState;
    }

    iRollOverState = RollOverStateIdle;

    PVMFStatus retval = DoSourceNodeInit(aCmd.GetCmdId(), aCmd.GetContext());

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoInit() Out"));

    if (retval == PVMFSuccess)
    {
        SetEngineState(PVP_ENGINE_STATE_INITIALIZING);
        return PVMFSuccess;
    }
    else
    {
        return AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_INIT, retval, NULL);
    }
}


PVMFStatus PVPlayerEngine::DoSourceNodeInit(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::DoSourceNodeInit() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeInit() In"));

    OSCL_ASSERT(iSourceNode != NULL);

    int32 leavecode = 0;

    // Clean up any previous reference to license interface
    DereferenceLicenseInterface();

    // Initialize the source node
    PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeInit);

    leavecode = 0;
    PVMFCommandId cmdid = -1;
    OSCL_TRY(leavecode, cmdid = iSourceNode->Init(iSourceNodeSessionId, (OsclAny*)context));
    OSCL_FIRST_CATCH_ANY(leavecode,
                         FreeEngineContext(context);
                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeInit() Init on iSourceNode did a leave!"));
                         return PVMFFailure);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeInit() Out"));

    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoSourceNodeGetDurationValue(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeGetDurationValue() In"));

    if (iSourceNodeMetadataExtIF == NULL)
    {
        return PVMFErrNotSupported;
    }

    // Create a key list with just duration key
    iSourceDurationKeyList.clear();
    OSCL_HeapString<OsclMemAllocator> tmpstr = _STRLIT_CHAR("duration");
    iSourceDurationKeyList.push_back(tmpstr);
    // Clear the value list
    iSourceDurationValueList.clear();

    // Call GetNodeMetadataValues on the source node to retrieve duration
    PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeGetDurationValue);

    int32 leavecode = 0;
    PVMFCommandId cmdid = -1;
    OSCL_TRY(leavecode, cmdid = iSourceNodeMetadataExtIF->GetNodeMetadataValues(iSourceNodeSessionId,
                                iSourceDurationKeyList,
                                iSourceDurationValueList,
                                0 /*starting index*/, 1 /*max entries*/, (OsclAny*)context));
    OSCL_FIRST_CATCH_ANY(leavecode,
                         FreeEngineContext(context);
                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeGetDurationValue() GetNodeMetadataValues on iSourceNode did a leave!"));
                         return PVMFFailure);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeGetDurationValue() Out"));
    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::DoSourceNodeRollOver(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeRollOver() In"));
    /* Clean up any exisiting source node */
    DoSourceNodeCleanup();

    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeRollOver() DoSourceNodeCleanup Complete"));
    if (CheckForSourceRollOver())
    {
        if (iDataSource->GetAlternateSourceFormatType(iSourceFormatType,
                iAlternateSrcFormatIndex))
        {
            uint8 localbuffer[8];
            oscl_memset(localbuffer, 0, 8);
            localbuffer[0] = 1;
            oscl_memcpy(&localbuffer[4], &iSourceFormatType, sizeof(uint32));

            PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
            PVMFBasicErrorInfoMessage* infomsg =
                OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoAttemptingSourceRollOver, puuid, NULL));
            SendInformationalEvent(PVMFInfoSourceFormatNotSupported, OSCL_STATIC_CAST(PVInterface*, infomsg), NULL, localbuffer, 8);
            infomsg->removeRef();

            iAlternateSrcFormatIndex++;
            PVMFStatus status = DoSetupSourceNode(aCmdId, aCmdContext);
            if (status != PVMFSuccess)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeRollOver() SourceNodeRollOver Failed, return status"));
                return status;
            }
            //roll over pending
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeRollOver() SourceNodeRollOver In Progress"));
            return PVMFPending;
        }
    }
    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeRollOver() Invalid State"));
    return PVMFErrInvalidState;
}

PVMFStatus PVPlayerEngine::DoAcquireLicense(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE,
                    (0, "PVPlayerEngine::DoAcquireLicense() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoAcquireLicense() In"));

    // Retrieve the command parameters and validate
    iCPMAcquireLicenseParam.iContentNameChar = NULL;
    iCPMAcquireLicenseParam.iContentNameWChar = NULL;
    iCPMAcquireLicenseParam.iTimeoutMsec = (-1);
    iCPMAcquireLicenseParam.iLicenseData = NULL;
    iCPMAcquireLicenseParam.iLicenseDataSize = 0;

    if (aCmd.GetParam(0).pOsclAny_value != NULL)
    {
        iCPMAcquireLicenseParam.iLicenseData = aCmd.GetParam(0).pOsclAny_value;
    }

    if (aCmd.GetParam(1).uint32_value != 0)
    {
        iCPMAcquireLicenseParam.iLicenseDataSize = aCmd.GetParam(1).uint32_value;
    }

    if (aCmd.GetCmdType() == PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_WCHAR)
    {
        iCPMAcquireLicenseParam.iContentNameWChar = aCmd.GetParam(2).pWChar_value;
    }
    else
    {
        iCPMAcquireLicenseParam.iContentNameChar = aCmd.GetParam(2).pChar_value;
    }
    iCPMAcquireLicenseParam.iTimeoutMsec = aCmd.GetParam(3).int32_value;

    if (iCPMAcquireLicenseParam.iContentNameWChar == NULL && iCPMAcquireLicenseParam.iContentNameChar == NULL)
    {
        // Content name not specified
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAcquireLicense() Content name not specified."));
        return PVMFErrArgument;
    }

    if (iCPMAcquireLicenseParam.iTimeoutMsec < -1)
    {
        // Timeout parameter not valid
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAcquireLicense() Timeout value not valid."));
        return PVMFErrArgument;
    }

    // To acquire license, player data source and local data source need to be available
    if (iDataSource == NULL)
    {
        // Player data source not available
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAcquireLicense() Player data source not specified."));
        return PVMFErrNotReady;
    }
    if (iDataSource->GetDataSourceContextData() == NULL)
    {
        // Pointer to the local data source if not available
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAcquireLicense() Local data source in player data source not specified."));
        return PVMFErrBadHandle;
    }

    //If a license interface is available, use that.
    if (iCPMLicenseIF != NULL)
    {
        PVMFStatus status = DoGetLicense(aCmd.GetCmdId(), aCmd.GetContext());
        if (status != PVMFSuccess)
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAcquireLicense() DoGetLicense failed."));

        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoAcquireLicense() Out"));
        return status;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoAcquireLicense() Out"));
    // if the license interface is not available, fail the command
    return PVMFFailure;
}

void PVPlayerEngine::DoCancelAcquireLicense(PVPlayerEngineCommand& aCmd)
{

    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE,
                    (0, "PVPlayerEngine::DoCancelAcquireLicense() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelAcquireLicense() In"));

    /* Engine cannot be processing another cancel command */
    OSCL_ASSERT(iCmdToDlaCancel.empty() == true);

    PVMFCommandId id = aCmd.GetParam(0).int32_value;
    PVMFStatus status = PVMFSuccess;

    if (iCurrentCmd.size() == 1)
    {
        /* First save the current command being processed */
        PVPlayerEngineCommand currentcmd(iCurrentCmd[0]);

        /* First check "current" command if any */
        if (id == iCurrentCmd[0].GetCmdId())
        {
            /* Cancel the current command first */
            if ((iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_CHAR)
                    || (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_WCHAR)
                    || (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_JOIN_DOMAIN)
               )
            {
                /* Make the CancelAll() command the current command */
                iCmdToDlaCancel.push_front(aCmd);
                /* Properly cancel a command being currently processed */
                if (iCPMLicenseIF != NULL)
                {
                    PVPlayerEngineContext* context = AllocateEngineContext(NULL, NULL, NULL, aCmd.GetCmdId(), aCmd.GetContext(), -1);
                    // Default cmd to be called will be that of the GetLicense cmd.
                    PVMFCommandId aCmdIdToBeCancelled = iCPMGetLicenseCmdId;
                    if (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_JOIN_DOMAIN)
                    {
                        // If the current issued command was a JoinDomain call, the command Id
                        // needs to be updated.
                        aCmdIdToBeCancelled = iCPMJoinDomainCmdId;
                    }
                    status = DoCancelGetLicense(aCmdIdToBeCancelled, context);
                }
                else
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                    (0, "PVPlayerEngine::DoCancelAcquireLicense() CPM plug-in registry in local data source not specified."));
                    status = PVMFErrBadHandle;
                }
            }
            else
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "PVPlayerEngine::DoCancelAcquireLicense() Current cmd is not AquireLicense."));
                status = PVMFErrArgument;
            }
        }
        else
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::DoCancelAcquireLicense() Current cmd ID is not equal with App specified cmd ID."));
            status = PVMFErrArgument;
        }
        if (status != PVMFSuccess)
        {
            /* We send error completetion for CancelAcquireLicense API*/
            iCurrentCmd.erase(iCurrentCmd.begin());
            iCurrentCmd.push_front(aCmd);
            EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), status);
            iCurrentCmd.push_front(currentcmd);
        }
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelAcquireLicense() No Current cmd"));
        iCurrentCmd.push_front(aCmd);
        status = PVMFErrArgument;
        /* If we get here the command isn't queued so the cancel fails */
        EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), status);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelAcquireLicense() Out"));
    return;
}

PVMFStatus PVPlayerEngine::DoJoinDomain(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE,
                    (0, "PVPlayerEngine::DoJoinDomain() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoJoinDomain() In"));

    // Retrieve the command parameters and validate
    iCPMJoinDomainParam.iJoinData = NULL;
    iCPMJoinDomainParam.iTimeoutMsec = (-1);
    if (aCmd.GetParam(0).pOsclAny_value != NULL)
    {
        iCPMJoinDomainParam.iJoinData = (PVMFCPMDomainJoinData*)(aCmd.GetParam(0).pOsclAny_value);
    }

    iCPMJoinDomainParam.iTimeoutMsec = aCmd.GetParam(1).int32_value;

    //If a license interface is available, use that.
    if (iCPMLicenseIF != NULL)
    {
        PVMFStatus status = PVMFSuccess;
        int32 leavecode = 0;
        PVPlayerEngineContext* context = AllocateEngineContext(NULL, NULL, NULL, aCmd.GetCmdId(), aCmd.GetContext(), -1);
        OSCL_TRY(leavecode, iCPMJoinDomainCmdId = iCPMLicenseIF->JoinDomain(iSourceNodeSessionId,
                 *(iCPMJoinDomainParam.iJoinData),
                 iCPMJoinDomainParam.iTimeoutMsec,
                 (OsclAny*)context));
        if (leavecode)
        {
            FreeEngineContext(context);
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::DoJoinDomain() -- JoinDomain on iCPMLicenseIF did a leave!"));
            status = PVMFFailure;
        }
        if (status != PVMFSuccess)
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoJoinDomain() failed."));

        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoJoinDomain() Out"));
        return status;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoJoinDomain() Out"));
    // if the license interface is not available, fail the command
    return PVMFFailure;
}

PVMFStatus PVPlayerEngine::DoGetLicense(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::DoGetLicense() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetLicense() In"));

    if (iCPMLicenseIF == NULL)
    {
        OSCL_ASSERT(false);
        return PVMFErrBadHandle;
    }

    // Get the license
    int32 leavecode = 0;
    PVPlayerEngineContext* context = AllocateEngineContext(NULL, NULL, NULL, aCmdId, aCmdContext, -1);
    if (iCPMAcquireLicenseParam.iContentNameChar)
    {
        // Use the char version
        iCPMContentNameStr = iCPMAcquireLicenseParam.iContentNameChar;
        // Using the source node session id.
        OSCL_TRY(leavecode, iCPMGetLicenseCmdId =
                     iCPMLicenseIF->GetLicense(iSourceNodeSessionId,
                                               iCPMContentNameStr,
                                               iCPMAcquireLicenseParam.iLicenseData,
                                               iCPMAcquireLicenseParam.iLicenseDataSize,
                                               iCPMAcquireLicenseParam.iTimeoutMsec,
                                               (OsclAny*)context));
    }
    else if (iCPMAcquireLicenseParam.iContentNameWChar)
    {
        // Use the wchar version
        iCPMContentNameWStr = iCPMAcquireLicenseParam.iContentNameWChar;
        OSCL_TRY(leavecode, iCPMGetLicenseCmdId =
                     iCPMLicenseIF->GetLicense(iSourceNodeSessionId,
                                               iCPMContentNameWStr,
                                               iCPMAcquireLicenseParam.iLicenseData,
                                               iCPMAcquireLicenseParam.iLicenseDataSize,
                                               iCPMAcquireLicenseParam.iTimeoutMsec,
                                               (OsclAny*)context));
    }
    else
    {
        // This should not happen
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetLicense() Content name not specified. Asserting"));
        OSCL_ASSERT(false);
        return PVMFErrArgument;
    }

    if (leavecode)
    {
        FreeEngineContext(context);
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetLicense() GetLicense on iSourceNode did a leave!"));
        return PVMFFailure;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetLicense() Out"));
    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::DoAddDataSink(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE,
                    (0, "PVPlayerEngine::DoAddDataSink() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoAddDataSink() In"));

    if (GetPVPlayerState() != PVP_STATE_INITIALIZED)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAddDataSink() Wrong engine state"));
        return PVMFErrInvalidState;
    }

    if (aCmd.GetParam(0).pOsclAny_value == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAddDataSink() Passed in parameter invalid."));
        return PVMFErrArgument;
    }

    PVPlayerDataSink* datasink = (PVPlayerDataSink*)(aCmd.GetParam(0).pOsclAny_value);

    PVPlayerEngineDatapath newdatapath;
    newdatapath.iDataSink = datasink;

    // Add a new engine datapath to the list for the data sink
    iDatapathList.push_back(newdatapath);

    EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoAddDataSink() Out"));
    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoSetPlaybackRange(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE,
                    (0, "PVPlayerEngine::DoSetPlaybackRange() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetPlaybackRange() In"));

    PVMFStatus retval;

    if ((GetPVPlayerState() == PVP_STATE_ERROR) ||
            (iDataSource == NULL))
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRange() Wrong engine state"));
        return PVMFErrInvalidState;
    }

    if (((iNumPVMFInfoStartOfDataPending > 0) || (iNumPendingDatapathCmd > 0))
            && ((iState == PVP_ENGINE_STATE_PAUSED) || (iState == PVP_ENGINE_STATE_STARTED)))
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVPlayerEngine::DoSetPlaybackRange() Pending PVMFInfoStartOfData events or datapath commands"));
        return PVMFPending;
    }

    if (aCmd.GetParam(2).bool_value)
    {
        // Queueing of playback range is not supported yet
        iQueuedRangePresent = false;
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRange() Queued playback range is not supported yet"));
        return PVMFErrNotSupported;
    }

    // Change the end position
    iCurrentEndPosition = aCmd.GetParam(1).playbackpos_value;
    retval = UpdateCurrentEndPosition(iCurrentEndPosition);
    if (retval != PVMFSuccess)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRange() Changing end position failed"));
        return retval;
    }

    if (aCmd.GetParam(0).playbackpos_value.iIndeterminate)
    {
        // Start position not specified so return as success
        EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
        return PVMFSuccess;
    }

    // reset repos related variables except the StreamID.
    ResetReposVariables(false);
    iStreamID++;

    if (iPlaybackPausedDueToEndOfClip)
    {
        // Reset the paused-due-to-EOS flag
        iPlaybackPausedDueToEndOfClip = false;
        iClipsCompleted--;
    }

    if (iPlaybackPausedDueToEndOfTimeReached)
    {
        // Reset the paused-due-to-EOT flag
        iPlaybackPausedDueToEndOfTimeReached = false;
    }

    iSkipToRequestedPosition = aCmd.GetParam(3).bool_value;
    iSeekToSyncPoint = aCmd.GetParam(4).bool_value;

    // Change the begin position
    iCurrentBeginPosition = aCmd.GetParam(0).playbackpos_value;
    iTargetNPT = iCurrentBeginPosition.iPosValue.millisec_value;
    retval = UpdateCurrentBeginPosition(iCurrentBeginPosition, aCmd);

    if (retval == PVMFSuccess)
    {
        // Notify completion of engine command
        EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
    }
    else if (retval == PVMFPending)
    {
        // SetPlaybackRange command is still being processed
        // so change the return status so command is not completed yet
        retval = PVMFSuccess;
    }

    if (iDataSource->GetNumClips() == 1)
    {
        iClipsCompleted = 0;
    }
    else
    {
        // For a datasource with multiple clips, it is expected that
        // the iPlayElementIndex is provided.
        iClipsCompleted = iCurrentBeginPosition.iPlayElementIndex;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetPlaybackRange() Out"));
    return retval;
}


PVMFStatus PVPlayerEngine::UpdateCurrentEndPosition(PVPPlaybackPosition& aEndPos)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateCurrentEndPosition() In"));

    if (aEndPos.iIndeterminate)
    {
        // Disable end time checking if running
        if (iEndTimeCheckEnabled)
        {
            iEndTimeCheckEnabled = false;
            iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_ENDTIMECHECK);
        }
    }
    else
    {
        // Convert the end time to milliseconds to have consistent units internally
        uint32 timems = 0;
        PVMFStatus retval = ConvertToMillisec(aEndPos, timems);
        if (retval != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::UpdateCurrentEndPosition() Converting to millisec failed"));
            return retval;
        }
        aEndPos.iPosValue.millisec_value = timems;
        aEndPos.iPosUnit = PVPPBPOSUNIT_MILLISEC;

        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateCurrentEndPosition() Changing end time to %d ms", timems));

        // Enable the end time checking if not running
        if (!iEndTimeCheckEnabled)
        {
            iEndTimeCheckEnabled = true;

            if (GetPVPlayerState() == PVP_STATE_STARTED)
            {
                // Determine the check cycle based on interval setting in milliseconds
                // and timer frequency of 100 millisec
                int32 checkcycle = iEndTimeCheckInterval / 100;
                if (checkcycle == 0)
                {
                    ++checkcycle;
                }
                iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_ENDTIMECHECK);
                iPollingCheckTimer->Request(PVPLAYERENGINE_TIMERID_ENDTIMECHECK, 0, checkcycle, this, true);
            }
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateCurrentEndPosition() Out"));
    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::UpdateCurrentBeginPosition(PVPPlaybackPosition& aBeginPos, PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateCurrentBeginPosition() In"));

    PVMFStatus retval = PVMFSuccess;
    uint32 timems = 0;

    switch (GetPVPlayerState())
    {
        case PVP_STATE_PREPARED:
        case PVP_STATE_STARTED:
        {
            // Change the playback position immediately
            retval = ConvertToMillisec(aBeginPos, timems);
            if (retval != PVMFSuccess)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::UpdateCurrentBeginPosition() Converting to millisec failed"));
                return retval;
            }

            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateCurrentBeginPosition() Requested begin position is %d ms", timems));

            retval = DoChangePlaybackPosition(aCmd.GetCmdId(), aCmd.GetContext());
        }
        break;

        case PVP_STATE_PAUSED:
        {
            // This is for use-case: Pause - SetPlaybackRate - Resume.
            // In DoResume engine will call SetDataSourceDirection and then from HandleSourceNodeSetDataSourceDirection
            // will call UpdateCurrentBeginPosition.
            if (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_RESUME)
            {
                // Reposition occurred during the paused state so need to change the source position first
                retval = DoSourceNodeQueryDataSourcePosition(aCmd.GetCmdId(), aCmd.GetContext());
                if (retval == PVMFSuccess)
                {
                    //return Pending to indicate a node command was issued
                    return PVMFPending;
                }
                else
                {
                    //ignore failure, continue with resume sequence
                    return PVMFSuccess;
                }
            }
            else
            {
                //if there's already a direction change pending, then don't
                //allow a reposition also
                if (iChangePlaybackDirectionWhenResuming)
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::UpdateCurrentBeginPosition() Direction change already pending, fail."));
                    return PVMFErrInvalidState;
                }

                // Convert the time units but flag to change playback position when resuming
                retval = ConvertToMillisec(aBeginPos, timems);
                if (retval != PVMFSuccess)
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::UpdateCurrentBeginPosition() Converting to millisec failed in paused state"));
                    return retval;
                }

                retval = DoChangePlaybackPosition(aCmd.GetCmdId(), aCmd.GetContext());
            }
        }
        break;

        default:
            // Playback is stopped and start position is set so wait for playback to start
            break;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateCurrentBeginPosition() Out"));
    return retval;
}

PVMFStatus PVPlayerEngine::DoChangePlaybackPosition(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoChangePlaybackPosition() In"));

    // Check if the source node has position control IF or
    // begin position is indeterminate
    if (iSourceNodePBCtrlIF == NULL ||
            iCurrentBeginPosition.iIndeterminate ||
            ((iCurrentBeginPosition.iPosUnit != PVPPBPOSUNIT_MILLISEC) &&
             (iCurrentBeginPosition.iPlayListPosUnit != PVPPBPOSUNIT_MILLISEC)))
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoChangePlaybackPosition() Playback control IF on source node not available or invalid begin position"));
        return PVMFErrNotSupported;
    }

    PVMFCommandId cmdid = -1;

    if (iSeekToSyncPoint && iSyncPointSeekWindow > 0)
    {
        PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQueryDataSourcePositionDuringPlayback);

        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoChangePlaybackPosition() Querying source position. Position %d ms, SeekToSyncPt %d", iTargetNPT, iSeekToSyncPoint));
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoChangePlaybackPosition() Querying source position. Position %d ms, SeekToSyncPt %d", iTargetNPT, iSeekToSyncPoint));
        int32 leavecode = 0;

        // As in case of MP4 file we need to call overload function of QueryDataSourcePosition which retruns
        // I frame before and after instead of actaul NPT, format type will be checked here to first find if
        // format-type is one of the MP4 varient

        PVMFNodeCapability nodeCapability;
        iSourceNode->GetCapability(nodeCapability);
        PVMFFormatType * formatType = nodeCapability.iInputFormatCapability.begin();
        bool mpeg4FormatType = false;
        if (formatType != NULL)
        {
            if ((pv_mime_strcmp((char*)formatType->getMIMEStrPtr(), PVMF_MIME_MPEG4FF)) == 0)
            {
                mpeg4FormatType = true;
            }
            else
            {
                mpeg4FormatType = false;
            }
        }

        if (mpeg4FormatType)
        {
            OSCL_TRY(leavecode, cmdid = iSourceNodePBCtrlIF->QueryDataSourcePosition(iSourceNodeSessionId, iTargetNPT,
                                        iSeekPointBeforeTargetNPT, iSeekPointAfterTargetNPT, (OsclAny*)context, iSeekToSyncPoint));
        }
        else
        {
            OSCL_TRY(leavecode, cmdid = iSourceNodePBCtrlIF->QueryDataSourcePosition(iSourceNodeSessionId, iTargetNPT, iActualNPT,
                                        iSeekToSyncPoint, (OsclAny*)context));
        }

        OSCL_FIRST_CATCH_ANY(leavecode,
                             FreeEngineContext(context);
                             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoChangePlaybackPosition() QueryDataSourcePosition on iSourceNodePBCtrlIF did a leave!"));
                             if (leavecode == PVMFErrNotSupported || leavecode == PVMFErrArgument)
    {
        return leavecode;
    }
    else
    {
        return PVMFFailure;
    }
                        );
    }
    else
    {
        // Go straight to repositioning the data source
        PVMFStatus retval = DoSourceNodeSetDataSourcePositionDuringPlayback(aCmdId, aCmdContext);
        if (retval == PVMFSuccess)
        {
            return PVMFPending;
        }
        else
        {
            return retval;
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoChangePlaybackPosition() Out"));

    return PVMFPending;
}

PVMFStatus PVPlayerEngine::DoSourceNodeSetDataSourcePositionDuringPlayback(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePositionDuringPlayback() In"));

    // Check if the source node has position control IF
    if (iSourceNodePBCtrlIF == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePositionDuringPlayback() No source playback control IF"));
        return PVMFErrNotSupported;
    }
    bool clockpausedhere = false;
    switch (iPlaybackPositionMode)
    {
        case PVPPBPOS_MODE_END_OF_CURRENT_PLAY_ELEMENT:
        case PVPPBPOS_MODE_END_OF_CURRENT_PLAY_SESSION:
            break;
        case PVPPBPOS_MODE_NOW:
        default:
            // Pause the playback clock
            clockpausedhere = iPlaybackClock.Pause();

            // Stop the playback position status timer
            StopPlaybackStatusTimer();
            break;
    }
    // Set the new position on the source node
    PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeSetDataSourcePositionDuringPlayback);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePositionDuringPlayback() Calling SetDataSourcePosition() on source node. TargetNPT %d ms, SeekToSyncPoint %d", iTargetNPT, iSeekToSyncPoint));

    int32 leavecode = 0;
    if (iCurrentBeginPosition.iPosUnit == PVPPBPOSUNIT_PLAYLIST)
    {
        iDataSourcePosParams.iActualMediaDataTS = 0;
        iDataSourcePosParams.iActualNPT = 0;
        if ((iCurrentBeginPosition.iMode == PVPPBPOS_MODE_UNKNOWN) ||
                (iCurrentBeginPosition.iMode == PVPPBPOS_MODE_NOW))
        {
            iDataSourcePosParams.iMode = PVMF_SET_DATA_SOURCE_POSITION_MODE_NOW;
        }
        else if (iCurrentBeginPosition.iMode == PVPPBPOS_MODE_END_OF_CURRENT_PLAY_ELEMENT)
        {
            iDataSourcePosParams.iMode = PVMF_SET_DATA_SOURCE_POSITION_END_OF_CURRENT_PLAY_ELEMENT;
        }
        else if (iCurrentBeginPosition.iMode == PVPPBPOS_MODE_END_OF_CURRENT_PLAY_SESSION)
        {
            iDataSourcePosParams.iMode = PVMF_SET_DATA_SOURCE_POSITION_MODE_END_OF_CURRENT_PLAY_SESSION;
        }
        else if (iCurrentBeginPosition.iMode == PVPPBPOS_MODE_3GPP_FCS)
        {
            uint32 clockcurpos = 0;
            bool tmpbool = false;
            iPlaybackClock.GetCurrentTime32(clockcurpos, tmpbool, PVMF_MEDIA_CLOCK_MSEC);
            iDataSourcePosParams.iActualMediaDataTS = clockcurpos; // Set to current playback clock value so that failure handling is smooth.
            iDataSourcePosParams.iMode = PVMF_SET_DATA_SOURCE_POSITION_MODE_3GPP_FCS;
        }
        iDataSourcePosParams.iPlayElementIndex = iCurrentBeginPosition.iPlayElementIndex;
        iDataSourcePosParams.iSeekToSyncPoint = iSeekToSyncPoint;
        iDataSourcePosParams.iTargetNPT = iCurrentBeginPosition.iPlayListPosValue.millisec_value;
        iDataSourcePosParams.iStreamID = iStreamID;
        if (iCurrentBeginPosition.iMode == PVPPBPOS_MODE_3GPP_FCS)
        {
            iDataSourcePosParams.iSDPAvailable = iCurrentBeginPosition.iPlayListPosValue3GPPFCS.iSDPAvailableFlag;
            iDataSourcePosParams.iPlaylistUri = iCurrentBeginPosition.iPlayListPosValue3GPPFCS.iControlUri;
        }
        else
        {
            iDataSourcePosParams.iPlaylistUri = iCurrentBeginPosition.iPlayListUri;
        }

        leavecode = IssueSourceSetDataSourcePosition(true, (OsclAny*)context);
        if (leavecode != 0)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePositionDuringPlayback() SetDataSourcePosition on iSourceNodePBCtrlIF did a leave!"));
            FreeEngineContext(context);
            if (clockpausedhere)
            {
                // Resume the clock if paused in this function
                StartPlaybackClock();
            }

            --iStreamID;

            if (leavecode == PVMFErrNotSupported || leavecode == PVMFErrArgument)
            {
                return leavecode;
            }
            else
            {
                return PVMFFailure;
            }
        }
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePositionDuringPlayback() SetDataSourcePosition on iSourceNodePBCtrlIF - TargetNPT=%d, SeekToSyncPoint=%d", iTargetNPT, iSeekToSyncPoint));
        leavecode = IssueSourceSetDataSourcePosition(false, (OsclAny*)context);

        if (leavecode != 0)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePositionDuringPlayback() SetDataSourcePosition on iSourceNodePBCtrlIF did a leave!"));
            FreeEngineContext(context);
            if (clockpausedhere)
            {
                // Resume the clock if paused in this function
                StartPlaybackClock();
            }
            --iStreamID;
            if (leavecode == PVMFErrNotSupported || leavecode == PVMFErrArgument)
            {
                return leavecode;
            }
            else
            {
                return PVMFFailure;
            }
        }
    }
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePositionDuringPlayback() Out"));

    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::DoSinkNodeSkipMediaDataDuringPlayback(PVCommandId aCmdId,
        OsclAny* aCmdContext,
        bool aSFR)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::DoSinkNodeSkipMediaDataDuringPlayback() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeSkipMediaDataDuringPlayback() In"));

    // Pause the playback clock
    bool clockpausedhere = iPlaybackClock.Pause();


    PVMFStatus retval = DoSinkNodeSkipMediaData(aCmdId, aSFR, PVP_CMD_SinkNodeSkipMediaDataDuringPlayback, aCmdContext);

    if (retval != PVMFSuccess)
    {
        if (clockpausedhere)
        {
            // Resume the clock if paused in this function
            StartPlaybackClock();
        }

        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeSkipMediaDataDuringPlayback() Skip on sink nodes failed"));
    }

    // If the nodes are paused, then start them
    // Usecase: Start -- Pause -- SetPlaybackRange -- Resume
    if (GetPVPlayerState() == PVP_STATE_PAUSED)
    {
        return DoSourceNodeStart(aCmdId, aCmdContext);
    }
    return retval;
}

PVMFStatus PVPlayerEngine::DoGetPlaybackRange(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetPlaybackRange() In"));

    if (aCmd.GetParam(0).pPlaybackpos_value == NULL ||
            aCmd.GetParam(1).pPlaybackpos_value == NULL)
    {
        // User did not pass in the reference to write the start and stop positions
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlaybackRange() Passed in parameter invalid."));
        return PVMFErrArgument;
    }

    if (aCmd.GetParam(2).bool_value)
    {
        // Return the queued playback range
        if (iQueuedRangePresent)
        {
            *(aCmd.GetParam(0).pPlaybackpos_value) = iQueuedBeginPosition;
            *(aCmd.GetParam(1).pPlaybackpos_value) = iQueuedEndPosition;
        }
        else
        {
            // Queued range has not been set
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlaybackRange() Queued range not set"));
            return PVMFErrNotReady;
        }
    }
    else
    {
        PVMFStatus retval = PVMFSuccess;

        // Return the current playback range
        if (iCurrentBeginPosition.iIndeterminate)
        {
            // Since indeterminate, just directly copy
            *(aCmd.GetParam(0).pPlaybackpos_value) = iCurrentBeginPosition;
        }
        else
        {
            retval = ConvertFromMillisec(iCurrentBeginPosition.iPosValue.millisec_value, *(aCmd.GetParam(0).pPlaybackpos_value));
            if (retval != PVMFSuccess)
            {
                // The conversion failed.
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlaybackRange() Conversion from millisec failed (1)"));
                return retval;
            }
        }

        if (iCurrentEndPosition.iIndeterminate)
        {
            // Since indeterminate, just directly copy
            *(aCmd.GetParam(1).pPlaybackpos_value) = iCurrentEndPosition;
        }
        else
        {
            retval = ConvertFromMillisec(iCurrentEndPosition.iPosValue.millisec_value, *(aCmd.GetParam(1).pPlaybackpos_value));
            if (retval != PVMFSuccess)
            {
                // The conversion failed.
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlaybackRange() Conversion from millisec failed (2)"));
                return retval;
            }
        }
    }

    EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetPlaybackRange() Out"));
    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoGetCurrentPosition(PVPlayerEngineCommand& aCmd, bool aSyncCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetCurrentPosition() In"));

    PVPPlaybackPosition* pbpos = aCmd.GetParam(0).pPlaybackpos_value;

    if (GetPVPlayerState() == PVP_STATE_IDLE ||
            GetPVPlayerState() == PVP_STATE_ERROR)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetCurrentPosition() Wrong engine state"));
        return PVMFErrInvalidState;
    }

    if (pbpos == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetCurrentPosition() Passed in parameter invalid."));
        return PVMFErrArgument;
    }

    if (pbpos->iPosUnit != PVPPBPOSUNIT_MILLISEC)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetCurrentPosition() Passed in parameter invalid."));
        return PVMFErrArgument;
    }

    // Query playback clock for current playback position
    GetPlaybackClockPosition(*pbpos);

    if (pbpos->iIndeterminate)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetCurrentPosition() Passed in parameter invalid."));
        return PVMFErrArgument;
    }

    if (!aSyncCmd)
    {
        EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetCurrentPosition() Out"));
    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoSetPlaybackRate(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetPlaybackRate() In"));

    int32 rate = aCmd.GetParam(0).int32_value;
    PVMFTimebase* timebase = (PVMFTimebase*)(aCmd.GetParam(1).pOsclAny_value);

    // Split the rate into the absolute value plus the direction 1 or -1.
    int32 direction = 1;
    if (rate < 0)
    {
        direction = (-1);
        rate = (-rate);
    }

    // Check if called in valid states.
    if (GetPVPlayerState() != PVP_STATE_PREPARED
            && GetPVPlayerState() != PVP_STATE_STARTED
            && GetPVPlayerState() != PVP_STATE_PAUSED)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRate() Wrong engine state to change rate"));
        return PVMFErrInvalidState;
    }

    // Timebase can only be changed when prepared or paused.
    if (timebase != iOutsideTimebase
            && GetPVPlayerState() != PVP_STATE_PREPARED
            && GetPVPlayerState() != PVP_STATE_PAUSED)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRate() Wrong engine state to change timebase"));
        return PVMFErrInvalidState;
    }

    // Don't allow a direction change while paused, if there's already
    // a pending reposition.  Engine doesn't have logic to handle both repos and
    // direction change during the Resume.
    if (direction != iPlaybackDirection
            && GetPVPlayerState() == PVP_STATE_PAUSED
            && iChangePlaybackPositionWhenResuming)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRate() Repos already pending-- can't change direction."));
        return PVMFErrInvalidState;
    }

    // Switching from forward to backward really only makes sense when playing or paused,
    // otherwise we'll be at the end of clip.  If we ever allow combined repositioning
    // and direction change, this restriction could be removed.
    if (direction != iPlaybackDirection
            && direction < 0
            && GetPVPlayerState() != PVP_STATE_STARTED
            && GetPVPlayerState() != PVP_STATE_PAUSED)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRate() Wrong engine state to go backward"));
        return PVMFErrInvalidState;
    }

    // Validate the playback rate parameters.

    // Rate zero is only valid with an outside timebase.
    if (rate == 0
            && timebase == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRate() Invalid parameter-- rate 0 with no outside timbase."));
        return PVMFErrArgument;
    }

    // Rate must be within allowed range
    if (rate > 0
            && (rate < PVP_PBRATE_MIN || rate > PVP_PBRATE_MAX))
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRate() Invalid parameter-- rate outside allowed range"));
        return PVMFErrArgument;
    }

    // With an outside timebase, we can't really support rates.  If -1x is input,
    // it means backward direction, but otherwise, rate is ignored.
    // So flag an error for any rate other than zero, 1x, or -1x.
    if (timebase != NULL
            && (rate != 0 && rate != 100000))
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRate() Invalid rate with outside timebase"));
        return PVMFErrInvalidState;
    }

    // To do any rate change, the source node must have the playback control IF.
    if (rate != iPlaybackClockRate
            && iSourceNodePBCtrlIF == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRate() iSourceNodePBCtrlIF is NULL"));
        return PVMFErrNotSupported;
    }

    // To do any direction change, the source node must have the direction control IF.
    if (direction != iPlaybackDirection
            && iSourceNodeDirCtrlIF == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRate() iSourceNodeDirCtrlIF is NULL"));
        return PVMFErrNotSupported;
    }

    // Reset the paused-due-to-EOS flag if direction changes
    if (direction != iPlaybackDirection)
    {
        iPlaybackPausedDueToEndOfClip = false;
        //a direction change also involves an internal repositioning
        //so reset repos related variables and increment iStreamID
        ResetReposVariables(false);
        iStreamID++;
    }

    // Save the new values.  They won't be installed until they're verified
    iOutsideTimebase_New = timebase;
    iPlaybackDirection_New = direction;
    iPlaybackClockRate_New = rate;

    // Start the sequence.

    if (iPlaybackClockRate_New != iPlaybackClockRate)
    {
        // This code starts a rate change.  Any direction and/or timebase change
        // will happen once the rate change is complete.

        // Query the source node if the new playback rate is supported
        PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmd.GetCmdId(), aCmd.GetContext(), PVP_CMD_SourceNodeSetDataSourceRate);

        PVMFCommandId cmdid = -1;
        int32 leavecode = 0;
        OSCL_TRY(leavecode, cmdid = iSourceNodePBCtrlIF->SetDataSourceRate(iSourceNodeSessionId, iPlaybackClockRate_New, iOutsideTimebase_New, (OsclAny*)context));
        OSCL_FIRST_CATCH_ANY(leavecode,
                             FreeEngineContext(context);
                             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRate() SetDataSourceRate on iSourceNodePBCtrlIF did a leave!"));
                             return PVMFFailure);

        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetPlaybackRate() Out"));

        return PVMFSuccess;
        // wait for the source node callback, then HandleSourceNodeSetDataSourceRate
    }

    if (iPlaybackDirection_New != iPlaybackDirection)
    {
        // Do a direction change without a rate change.
        PVMFStatus status = UpdateCurrentDirection(aCmd.GetCmdId(), aCmd.GetContext());
        switch (status)
        {
            case PVMFPending:
                // If we get here, engine is Prepared or Started, and we're now
                // waiting on source node command completion followed
                // by a call to HandleSourceNodeSetDataSource.
                // Set the return status to Success, since the caller does not expect
                // PVMFPending.
                status = PVMFSuccess;
                break;
            case PVMFSuccess:
                // If we get here, engine is Paused or Stopped.  The SetPlaybackRate
                // command is done for now, but we need to set the direction when the
                // engine is resumed or prepared.
                if (iOutsideTimebase_New != iOutsideTimebase)
                {
                    UpdateTimebaseAndRate();
                }
                EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
                break;
            default:
                //failure!
                break;
        }
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetPlaybackRate() Out"));
        return status;
    }

    //If we get here it's either a timebase change, or no change at all, so
    //the engine command is complete.
    if (iOutsideTimebase_New != iOutsideTimebase)
    {
        UpdateTimebaseAndRate();
    }

    EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetPlaybackRate() Out"));
    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::UpdateCurrentDirection(PVMFCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateCurrentDirection() In"));

    // Launch a direction change sequence.

    PVMFStatus status = PVMFFailure;

    // Check if the source node has direction control
    if (!iSourceNodeDirCtrlIF)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::UpdateCurrentDirection() Direction control IF on source node not available "));
        status = PVMFErrNotSupported;
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateCurrentDirection() Out"));
        return status;
    }

    switch (GetPVPlayerState())
    {
        case PVP_STATE_PREPARED:
        case PVP_STATE_STARTED:

            // Change the playback direction immediately
            status = DoSourceNodeSetDataSourceDirection(aCmdId, aCmdContext);
            if (status == PVMFSuccess)
            {
                //return Pending to indicate there is still a node command pending.
                status = PVMFPending;
            }
            else
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateCurrentDirection() DoSourceNodeSetDataSourceDirection failed."));
            }
            break;

        case PVP_STATE_PAUSED:
            if (iChangePlaybackPositionWhenResuming)
            {
                //if there's already a reposition pending, don't allow
                //a direction change also.
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateCurrentDirection() Reposition already pending-- can't change direction."));
                status = PVMFFailure;
            }
            else
            {
                //The command will complete now-- but the direction change
                //won't actually occur until the engine Resume command.
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateCurrentDirection() Setting iChangePlaybackDirectionWhenResuming."));
                iChangePlaybackDirectionWhenResuming = true;
                status = PVMFSuccess;
            }
            break;

        default:
            //not supported.
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateCurrentDirection() Invalid engine state"));
            status = PVMFErrInvalidState;
            break;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateCurrentDirection() Out"));
    return status;
}

PVMFStatus PVPlayerEngine::DoGetPlaybackRate(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetPlaybackRate() In"));

    int32* rate = aCmd.GetParam(0).pInt32_value;
    PVMFTimebase** timebase = (PVMFTimebase**)(aCmd.GetParam(1).pOsclAny_value);

    if (rate == NULL || timebase == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlaybackRate() Passed in parameter invalid"));
        return PVMFErrArgument;
    }

    if (GetPVPlayerState() != PVP_STATE_PREPARED &&
            GetPVPlayerState() != PVP_STATE_STARTED &&
            GetPVPlayerState() != PVP_STATE_PAUSED)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlaybackRate() Wrong engine state"));
        return PVMFErrInvalidState;
    }

    // Fill in with current engine settings for playback rate
    *rate = iPlaybackClockRate * iPlaybackDirection;
    *timebase = iOutsideTimebase;

    EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetPlaybackRate() Out"));
    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoGetPlaybackMinMaxRate(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetPlaybackMinMaxRate() In"));

    int32* minrate = aCmd.GetParam(0).pInt32_value;
    int32* maxrate = aCmd.GetParam(1).pInt32_value;

    if (minrate == NULL || maxrate == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlaybackMinMaxRate() Passed in parameter invalid"));
        return PVMFErrArgument;
    }

    // Use hardcoded ranges for now
    *minrate = PVP_PBRATE_MIN;
    *maxrate = PVP_PBRATE_MAX;

    EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetPlaybackMinMaxRate() Out"));
    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoPrepare(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE,
                    (0, "PVPlayerEngine::DoPrepare() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoPrepare() In"));

    if (GetPVPlayerState() == PVP_STATE_PREPARED)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPrepare() Engine already in Prepared State"));
        EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
        return PVMFSuccess;
    }

    if (GetPVPlayerState() != PVP_STATE_INITIALIZED)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPrepare() Wrong engine state"));
        return PVMFErrInvalidState;
    }

    if (iState == PVP_ENGINE_STATE_PREPARING)
    {
        // Engine is already in PREPARING STATE and doing Track selection. DoPrepare will be called everytime
        // engine completes a stage of track selection and flips the state to _TRACK_SELECTION_1_DONE etc.
        // If DoPrepare called without flipping the state, that means in _PREPARING state, do nothing here
        // just return.
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::DoPrepare() Engine state PVP_ENGINE_STATE_PREPARING - Do Nothing"));
        return PVMFSuccess;
    }

    PVMFStatus cmdstatus = PVMFFailure;

    /* Engine will call DoPrepare 4 times
     * 1) When Engine is in PVP_ENGINE_STATE_INITIALIZED state, here engine will start the Track Selection, which
     * will start with Sink Nodes.
     * 2) After Init completes on Sink nodes Engine will be in PVP_ENGINE_STATE_TRACK_SELECTION_1_DONE and Engine will
     * start creating Dec nodes and call Init on dec nodes, if needed.
     * 3) Init completion on Dec nodes will take Engine to PVP_ENGINE_STATE_TRACK_SELECTION_2_DONE and Engine will
     * start populating the Playable List after verifying parameters of different tracks. Engine after selecting
     * tracks will call Reset on Sink and Dec nodes.
     * 4) Once Reset completes on Sink and Dec nodes, Engine will be in PVP_ENGINE_STATE_TRACK_SELECTION_3_DONE and then
     * Engine will delete all the unused dec nodes.
     */
    if (iState == PVP_ENGINE_STATE_INITIALIZED)
    {
        SetEngineState(PVP_ENGINE_STATE_PREPARING);

        // Reset the paused-due-to-EOS flag
        iPlaybackPausedDueToEndOfClip = false;
        // Reset the paused-due-to-EOT flag
        iPlaybackPausedDueToEndOfTimeReached = false;

        if (iDatapathList.empty() == true)
        {
            // No sink added so fail
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPrepare() Data sinks not added."));
            return PVMFErrNotReady;
        }

        // Query cap-config based on available engine datapaths
        cmdstatus = DoSinkNodeQueryInterfaceMandatory(aCmd.GetCmdId(), aCmd.GetContext());
        if (cmdstatus != PVMFSuccess)
        {
            return AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, cmdstatus, NULL);
        }
    }
    else if (iState == PVP_ENGINE_STATE_TRACK_SELECTION_1_DONE)
    {
        SetEngineState(PVP_ENGINE_STATE_PREPARING);

        // Now check for the tracks which can be played only using the Sink nodes, that means no Decoder node needed.
        cmdstatus = DoSinkNodeTrackSelection(aCmd.GetCmdId(), aCmd.GetContext());
        if (cmdstatus != PVMFSuccess)
        {
            return AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, cmdstatus, NULL);
        }

        // For the tracks which cannot be played by Sink nodes only, we need to instantiate decoder nodes.
        // Create Decoder nodes and query for the cap and config IF here.
        cmdstatus = DoDecNodeQueryCapConfigIF(aCmd.GetCmdId(), aCmd.GetContext());
        if (cmdstatus != PVMFSuccess)
        {
            return AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, cmdstatus, NULL);
        }
    }
    else if (iState == PVP_ENGINE_STATE_TRACK_SELECTION_2_DONE)
    {
        SetEngineState(PVP_ENGINE_STATE_PREPARING);

        cmdstatus = DoSourceNodeTrackSelection(aCmd.GetCmdId(), aCmd.GetContext());
        if (cmdstatus != PVMFSuccess)
        {
            return AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, cmdstatus, NULL);
        }
        // Reset all the sink and decoder nodes.
        cmdstatus = DoSinkNodeDecNodeReset(aCmd.GetCmdId(), aCmd.GetContext());
        if (cmdstatus != PVMFSuccess)
        {
            return AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, cmdstatus, NULL);
        }
    }
    else if (iState == PVP_ENGINE_STATE_TRACK_SELECTION_3_DONE)
    {
        SetEngineState(PVP_ENGINE_STATE_PREPARING);

        cmdstatus = DoSinkDecCleanupSourcePrepare(aCmd.GetCmdId(), aCmd.GetContext());
        if (cmdstatus != PVMFSuccess)
        {
            return AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, cmdstatus, NULL);
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoPrepare() Out"));
    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::DoSinkNodeQueryInterfaceMandatory(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceMandatory() In"));

    if (iSourceNodeTrackSelIF == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceMandatory() Source node track sel IF not available. Asserting"));
        return PVMFFailure;
    }

    uint32 i = 0;
    int32 leavecode = 0;
    uint32 numTracks = 0;
    PVPlayerEngineContext* context = NULL;
    PVMFCommandId cmdid = -1;
    iNumPendingNodeCmd = 0;

    if (iSourceNodeTrackSelIF->GetMediaPresentationInfo(iSourcePresInfoList) != PVMFSuccess)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceMandatory() GetMediaPresentationInfo() call on source node failed"));
        return PVMFFailure;
    }

    numTracks = iSourcePresInfoList.getNumTracks();
    iTrackSelectionList.reserve(numTracks);

    for (i = 0; i < numTracks; i++)
    {
        // Create the track selection list, which will store a set of sink and dec node (if needed) for each track.
        PVPlayerEngineTrackSelection trackSelection;

        PVMFTrackInfo* trackInfo = iSourcePresInfoList.getTrackInfo(i);
        trackSelection.iTsTrackID = trackInfo->getTrackID();

        iTrackSelectionList.push_back(trackSelection);
    }

    for (i = 0; i < iDatapathList.size(); ++i)
    {
        // Destroy the track info if present
        if (iDatapathList[i].iTrackInfo)
        {
            OSCL_DELETE(iDatapathList[i].iTrackInfo);
            iDatapathList[i].iTrackInfo = NULL;
        }

        // Use the specified output node for sink node
        iDatapathList[i].iSinkNode = iDatapathList[i].iDataSink->GetDataSinkNodeInterface();
        if (iDatapathList[i].iSinkNode == NULL)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceMandatory() Passed in sink node is NULL"));
            return PVMFFailure;
        }

        if (iDatapathList[i].iSinkNode->ThreadLogon() != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceMandatory() ThreadLogon() on passed-in sink node failed"));
            OSCL_ASSERT(false);
            return PVMFFailure;
        }

        PVMFNodeSessionInfo nodesessioninfo(this, this, (OsclAny*)iDatapathList[i].iSinkNode, this, (OsclAny*)iDatapathList[i].iSinkNode);
        iDatapathList[i].iSinkNodeSessionId = iDatapathList[i].iSinkNode->Connect(nodesessioninfo);

        // Query for Cap-Config IF
        context = AllocateEngineContext(&iDatapathList[i], iDatapathList[i].iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeQueryCapConfigIF);

        PVUuid capconfiguuid = PVMI_CAPABILITY_AND_CONFIG_PVUUID;
        cmdid = -1;
        leavecode = 0;
        iDatapathList[i].iSinkNodePVInterfaceCapConfig = NULL;
        leavecode = IssueQueryInterface(iDatapathList[i].iSinkNode, iDatapathList[i].iSinkNodeSessionId, capconfiguuid, iDatapathList[i].iSinkNodePVInterfaceCapConfig, (OsclAny*)context, cmdid);
        if (leavecode != 0 || cmdid == -1)
        {
            iDatapathList[i].iSinkNodePVInterfaceCapConfig = NULL;
            FreeEngineContext(context);
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceMandatory() QueryInterface on sink node for cap-config IF did a leave!"));
            return PVMFFailure;
        }
        else
        {
            ++iNumPendingNodeCmd;
        }

        // Query for sync control IF
        context = AllocateEngineContext(&iDatapathList[i], iDatapathList[i].iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeQuerySyncCtrlIF);

        PVUuid syncctrluuid = PvmfNodesSyncControlUuid;
        cmdid = -1;
        leavecode = 0;
        iDatapathList[i].iSinkNodePVInterfaceSyncCtrl = NULL;
        leavecode = IssueQueryInterface(iDatapathList[i].iSinkNode, iDatapathList[i].iSinkNodeSessionId, syncctrluuid, iDatapathList[i].iSinkNodePVInterfaceSyncCtrl, (OsclAny*)context, cmdid);
        if (leavecode != 0 || cmdid == -1)
        {
            iDatapathList[i].iSinkNodePVInterfaceSyncCtrl = NULL;
            FreeEngineContext(context);
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceMandatory() QueryInterface on sink node for sync-ctrl IF did a leave!"));
            return PVMFFailure;
        }
        else
        {
            ++iNumPendingNodeCmd;
        }
    }

    if (iNumPendingNodeCmd <= 0)
    {
        // NumPendingNodeCmd less than or equal to zero means that none of the Sink nodes support Cap-Config interface, which means that these
        // sinks cannot be used for playing the content. Return PVMFErrNotSupported from here which will take engine into Error handling and will fail
        // Prepare command.
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceMandatory() Out No pending QueryInterface() on sink node"));
        return PVMFErrNotSupported;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceMandatory() Out"));
    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::DoSinkNodeInit(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::DoSinkNodeInit() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeInit() In"));

    iNumPendingNodeCmd = 0;
    PVMFCommandId cmdid = -1;
    int32 leavecode = 0;

    for (uint32 i = 0; i < iDatapathList.size(); ++i)
    {
        if (iDatapathList[i].iSinkNode != NULL)
        {
            // Call Init() on the sink node
            PVPlayerEngineContext* context = AllocateEngineContext(&(iDatapathList[i]), iDatapathList[i].iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeInit);

            leavecode = IssueSinkNodeInit(&(iDatapathList[i]), (OsclAny*) context, cmdid);

            if (cmdid != -1 && leavecode == 0)
            {
                ++iNumPendingNodeCmd;
            }
            else
            {
                FreeEngineContext(context);
                return PVMFFailure;
            }
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeInit() Out"));
    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::DoSinkNodeTrackSelection(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    OSCL_UNUSED_ARG(aCmdId);
    OSCL_UNUSED_ARG(aCmdContext);
    // For a track to be playable only by sink node, the Sink node should support the Format Type and Format Specific Info
    // for the track. If any of the 2 variables are not supported by the sink node, the track needs to have a decoder which
    // will be created in next stage of track selection. If Sink node supports both the above variables for a particular
    // track, the track will make to the Playable list without any decoder node.
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeTrackSelection() In"));

    PVMFStatus status = PVMFFailure;

    PvmiKvp kvpFormatType;
    PvmiKvp kvpFSI;

    OSCL_StackString<64> iKVPFormatType = _STRLIT_CHAR(PVMF_FORMAT_TYPE_VALUE_KEY);

    const char* aFormatValType = PVMF_FORMAT_SPECIFIC_INFO_KEY;

    OsclMemAllocator alloc;

    kvpFormatType.key = NULL;
    kvpFSI.key = NULL;

    kvpFormatType.key = iKVPFormatType.get_str();

    kvpFSI.length = oscl_strlen(aFormatValType) + 1; // +1 for \0
    kvpFSI.key = (PvmiKeyType)alloc.ALLOCATE(kvpFSI.length);
    if (kvpFSI.key == NULL)
    {
        return PVMFErrNoMemory;
    }
    oscl_strncpy(kvpFSI.key, aFormatValType, kvpFSI.length);

    for (uint32 i = 0; i < iDatapathList.size(); i++)
    {
        if (iDatapathList[i].iSinkNodeCapConfigIF != NULL)
        {
            for (uint32 j = 0; j < iSourcePresInfoList.getNumTracks(); j++)
            {
                // if any track is already been added to the playlist then no need to check with the next Datapath
                // go onto the next track
                if (!iTrackSelectionList[j].iTsTrackValidForPlayableList)
                {
                    OsclRefCounterMemFrag aConfig;
                    PVMFTrackInfo* currTrack = iSourcePresInfoList.getTrackInfo(j);
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeTrackSelection() Check format type for %s", currTrack->getTrackMimeType().get_cstr()));

                    kvpFormatType.value.pChar_value = currTrack->getTrackMimeType().get_str();

                    // Check for the format type of the track first. If Supported move to Format specific info, if not
                    // move on to the next track.

                    status = iDatapathList[i].iSinkNodeCapConfigIF->verifyParametersSync(NULL, &kvpFormatType, 1);

                    if (status == PVMFSuccess)
                    {
                        // go ahead and check for Format specific info
                        aConfig = currTrack->getTrackConfigInfo();
                        kvpFSI.value.key_specific_value = (OsclAny*)(aConfig.getMemFragPtr());
                        kvpFSI.capacity = aConfig.getMemFragSize();

                        status = iDatapathList[i].iSinkNodeCapConfigIF->verifyParametersSync(NULL, &kvpFSI, 1);

                        if (status == PVMFSuccess)
                        {
                            // This track can be played just using the Sink nodes we need not have decoders for this track
                            // Set the boolean iTsTrackValidForPlayableList to true in the TrackSelectionList.
                            // Check the boolean iTsTrackValidForPlayableList before creating the decoder nodes, if
                            // already set no need for decoders.
                            iTrackSelectionList[j].iTsSinkNode = iDatapathList[i].iSinkNode;
                            iTrackSelectionList[j].iTsSinkNodeCapConfigIF = iDatapathList[i].iSinkNodeCapConfigIF;
                            iTrackSelectionList[j].iTsTrackValidForPlayableList = true;
                        }
                    }
                }
                // if any of the above verifyParameterSync returns a failure, just move onto the next track.
            }
        }
    }

    alloc.deallocate((OsclAny*)(kvpFSI.key));
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeTrackSelection() Out"));
    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::DoDecNodeQueryCapConfigIF(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDecNodeQueryCapConfigIF() In"));

    int32 leavecode = 0;
    PVPlayerEngineContext* context = NULL;
    PVMFCommandId cmdid = -1;

    PVMFFormatType iSrcFormat = 0;
    PVMFFormatType iSinkFormat = 0;

    iNumPendingNodeCmd = 0;

    uint32 numTracks = iSourcePresInfoList.getNumTracks();

    for (uint32 i = 0; i < numTracks; i++)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDecNodeQueryCapConfigIF() Check the track"));
        for (uint32 j = 0; j < iDatapathList.size(); j++)
        {
            // Start creating decoder nodes for tracks which cannot be played with Sink nodes alone.
            // It is also possible that there can be similar tracks with same mime strings but with
            // different config parameters which share the same decoder node. For these similar tracks
            // engine should not create decoder nodes again, it should use the same decoder node instance.
            if (iTrackSelectionList[i].iTsDecNode == NULL && !iTrackSelectionList[i].iTsTrackValidForPlayableList)
            {
                PVMFTrackInfo* currTrack = iSourcePresInfoList.getTrackInfo(i);
                iSrcFormat = currTrack->getTrackMimeType().get_str();

                //Try to get supported formats from the media I/O component.
                PvmiKvp* kvp = NULL;
                int numParams = 0;
                PVMFStatus status = iDatapathList[j].iSinkNodeCapConfigIF->getParametersSync(NULL, (char*)INPUT_FORMATS_CAP_QUERY, kvp, numParams, NULL);
                if (status == PVMFSuccess)
                {
                    for (int k = 0; k < numParams; k++)
                    {
                        iSinkFormat = kvp[k].value.pChar_value;

                        Oscl_Vector<PVUuid, OsclMemAllocator> foundUuids;
                        // Query the player node registry for the required decoder node
                        if (iPlayerNodeRegistry.QueryRegistry(iSrcFormat, iSinkFormat, foundUuids) == PVMFSuccess)
                        {
                            if (!foundUuids.empty())
                            {
                                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDecNodeQueryCapConfigIF() Node found for %s, sink %s", currTrack->getTrackMimeType().get_str(), iSinkFormat.getMIMEStrPtr()));
                                iTrackSelectionList[i].iTsDecNode = iPlayerNodeRegistry.CreateNode(foundUuids[0]);

                                if (iTrackSelectionList[i].iTsDecNode != NULL)
                                {
                                    iNodeUuids.push_back(PVPlayerEngineUuidNodeMapping(foundUuids[0], iTrackSelectionList[i].iTsDecNode));

                                    if (iTrackSelectionList[i].iTsDecNode->ThreadLogon() != PVMFSuccess)
                                    {
                                        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDecNodeQueryCapConfigIF() ThreadLogon() on dec node failed"));
                                        OSCL_ASSERT(false);
                                    }

                                    PVMFNodeSessionInfo nodesessioninfo(this, this, (OsclAny*)iTrackSelectionList[i].iTsDecNode, this, (OsclAny*)iTrackSelectionList[i].iTsDecNode);
                                    iTrackSelectionList[i].iTsDecNodeSessionId = iTrackSelectionList[i].iTsDecNode->Connect(nodesessioninfo);

                                    // Query for CapConfig IF
                                    context = AllocateEngineContext(NULL, iTrackSelectionList[i].iTsDecNode, NULL, aCmdId, aCmdContext, PVP_CMD_DecNodeQueryCapConfigIF);

                                    PVUuid capconfiguuid = PVMI_CAPABILITY_AND_CONFIG_PVUUID;
                                    cmdid = -1;
                                    iTrackSelectionList[i].iTsDecNodePVInterfaceCapConfig = NULL;
                                    leavecode = IssueQueryInterface(iTrackSelectionList[i].iTsDecNode, iTrackSelectionList[i].iTsDecNodeSessionId, capconfiguuid, iTrackSelectionList[i].iTsDecNodePVInterfaceCapConfig, (OsclAny*)context, cmdid);
                                    if (cmdid == -1 || leavecode != 0)
                                    {
                                        iTrackSelectionList[i].iTsDecNodePVInterfaceCapConfig = NULL;
                                        FreeEngineContext(context);
                                        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDecNodeQueryCapConfigIF() QueryInterface on dec node for cap-config IF did a leave!"));
                                    }
                                    else
                                    {
                                        ++iNumPendingNodeCmd;
                                    }

                                    // A decoder is found in the registry and succesfully created for the particular set of track and datapath.
                                    // Set the sink nodes and its cap and config IF for the track in trackSelectionList
                                    iTrackSelectionList[i].iTsSinkNode = iDatapathList[j].iSinkNode;
                                    iTrackSelectionList[i].iTsSinkNodeCapConfigIF = iDatapathList[j].iSinkNodeCapConfigIF;
                                    iTrackSelectionList[i].iTsSinkNodeSessionId = iDatapathList[j].iSinkNodeSessionId;

                                    // Set the sink format for the datapath.
                                    iDatapathList[j].iSinkFormat = iSinkFormat;

                                    // Valid decoder node set in TrackSelectionList. Scan the TrackSelectionList further and if
                                    // any similar MIME track is there just use the same decoder and the same sink nodes.
                                    for (uint32 s = i + 1; s < numTracks; s++)
                                    {
                                        PVMFTrackInfo* tmpTrack = iSourcePresInfoList.getTrackInfo(s);
                                        if (!(pv_mime_strcmp(currTrack->getTrackMimeType().get_str(), tmpTrack->getTrackMimeType().get_str())))
                                        {
                                            iTrackSelectionList[s].iTsSinkNode = iTrackSelectionList[i].iTsSinkNode;
                                            iTrackSelectionList[s].iTsSinkNodeCapConfigIF = iTrackSelectionList[i].iTsSinkNodeCapConfigIF;
                                            iTrackSelectionList[s].iTsSinkNodeSessionId = iTrackSelectionList[i].iTsSinkNodeSessionId;

                                            iTrackSelectionList[s].iTsDecNode = iTrackSelectionList[i].iTsDecNode;
                                            iTrackSelectionList[s].iTsDecNodeSessionId = iTrackSelectionList[i].iTsDecNodeSessionId;
                                        }
                                    }

                                    k = numParams;
                                }
                                else
                                {
                                    // Create node on decoder failed, check with the next sink format
                                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDecNodeQueryCapConfigIF() Dec node creation failed"));
                                }
                            }
                            else
                            {
                                // No matching node found with the given Sinkformat, check with the next Sink Format
                                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDecNodeQueryCapConfigIF() No matching decoder node found"));
                            }
                        }
                        else
                        {
                            // Registry query failed with the given Sinkformat, check with the next Sink Format.
                            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDecNodeQueryCapConfigIF() Registry query for dec node failed"));
                        }
                    }
                    iDatapathList[j].iSinkNodeCapConfigIF->releaseParameters(0, kvp, numParams);
                }
                else
                {
                    // getParamterSync on MIO node to get the supported formats by MIO failed
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDecNodeQueryCapConfigIF() getParamterSync on MIO node to get the supported formats by MIO failed"));
                }
            }
        }
    }

    if (iNumPendingNodeCmd == 0)
    {
        // no decoder nodes are needed, go ahead for track selection logic
        SetEngineState(PVP_ENGINE_STATE_TRACK_SELECTION_2_DONE);
        RunIfNotReady();
    }
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDecNodeQueryCapConfigIF() Out"));
    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::DoDecNodeInit(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::DoDecNodeInit() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDecNodeInit() In"));

    iNumPendingNodeCmd = 0;
    PVMFCommandId cmdid = -1;
    int32 leavecode = 0;

    for (uint32 i = 0; i < iTrackSelectionList.size(); ++i)
    {
        if (iTrackSelectionList[i].iTsDecNode != NULL)
        {
            // Call Init() on the dec node
            PVPlayerEngineContext* context = AllocateEngineContext(NULL, iTrackSelectionList[i].iTsDecNode, NULL, aCmdId, aCmdContext, PVP_CMD_DecNodeInit);

            leavecode = IssueDecNodeInit(iTrackSelectionList[i].iTsDecNode, iTrackSelectionList[i].iTsDecNodeSessionId, (OsclAny*) context, cmdid);

            if (cmdid != -1 && leavecode == 0)
            {
                ++iNumPendingNodeCmd;
            }
            else
            {
                FreeEngineContext(context);
                return PVMFFailure;
            }
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDecNodeInit() Out"));
    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::DoSourceNodeTrackSelection(PVCommandId /*aCmdId*/, OsclAny* /*aCmdContext*/)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeTrackSelection() In"));

    if (iSourceNodeTrackSelIF == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeTrackSelection() Source node track sel IF not available."));
        return PVMFFailure;
    }

    //populate playable list first
    PVMFStatus retval = DoTrackSelection(true, false);
    if (retval != PVMFSuccess)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeTrackSelection() DoTrackSelection - Populating playable list Failed"));
        return retval;
    }

    bool usepreferencelist = false;
    if (iTrackSelectionHelper != NULL)
    {
        PVMFMediaPresentationInfo localList;
        iPreferenceList.Reset();
        localList.setPresentationType(iPlayableList.getPresentationType());
        localList.setSeekableFlag(iPlayableList.IsSeekable());
        localList.SetDurationAvailable(iPlayableList.IsDurationAvailable());
        localList.setDurationValue(iPlayableList.getDurationValue());
        localList.setDurationTimeScale(iPlayableList.getDurationTimeScale());
        //if track selection helper is present, it means that
        //user of engine wants to provide inputs
        //the reason we use a local list instead of iPreferenceList is
        //due to memory consideration. This call to "SelectTracks" goes
        //to the app and the app allocates memory to populate the local list
        //This memory needs to be released right away. So we make a copy
        //and release the memory for local list.
        PVMFStatus status =
            iTrackSelectionHelper->SelectTracks(iPlayableList, localList);
        if ((status == PVMFSuccess) &&
                (localList.getNumTracks() != 0))
        {
            usepreferencelist = true;
            iPreferenceList = localList;
        }
        //release memory now that we have made a copy
        iTrackSelectionHelper->ReleasePreferenceList(localList);
        //else user made no choice, use playable list
    }

    retval = DoTrackSelection(false, usepreferencelist);
    if (retval != PVMFSuccess)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeTrackSelection() DoTrackSelection - TrackSelection Failed"));
        return retval;
    }

    uint32 i = 0;

    // Create a selected track list
    PVMFMediaPresentationInfo selectedtracks;
    for (i = 0; i < iDatapathList.size(); ++i)
    {
        if (iDatapathList[i].iTrackInfo != NULL)
        {
            selectedtracks.addTrackInfo(*(iDatapathList[i].iTrackInfo));
        }
    }

    // Check that at least one track was selected
    if (selectedtracks.getNumTracks() == 0)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeTrackSelection() No tracks were selected"));
        // @TODO Provide a more specific error info
        return PVMFErrResourceConfiguration;
    }

    // Select in source node
    retval = iSourceNodeTrackSelIF->SelectTracks(selectedtracks);
    if (retval != PVMFSuccess)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeTrackSelection() SelectTracks() on source node failed"));
        return retval;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeTrackSelection() Out"));
    return retval;
}

PVMFStatus PVPlayerEngine::DoTrackSelection(bool oPopulatePlayableListOnly, bool oUsePreferenceList)
{

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoTrackSelection() In"));

    if (iSourceNodeTrackSelIF == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoTrackSelection() Source node track sel IF not available."));
        return PVMFFailure;
    }

    PVMFMediaPresentationInfo sourcepresinfo;
    if (oPopulatePlayableListOnly)
    {
        // use already saved presentation info list from source node
        sourcepresinfo = iSourcePresInfoList;

        iPlayableList.Reset();

        iPlayableList.setPresentationType(iSourcePresInfoList.getPresentationType());
        iPlayableList.setSeekableFlag(iSourcePresInfoList.IsSeekable());
        iPlayableList.SetDurationAvailable(iSourcePresInfoList.IsDurationAvailable());
        iPlayableList.setDurationValue(iSourcePresInfoList.getDurationValue());
        iPlayableList.setDurationTimeScale(iSourcePresInfoList.getDurationTimeScale());
    }
    else
    {
        if (oUsePreferenceList)
        {
            //perform track selection based on playable list
            sourcepresinfo = iPreferenceList;
        }
        else
        {
            //perform track selection based on playable list
            sourcepresinfo = iPlayableList;
        }
    }

    PVMFStatus retVal = PVMFSuccess;
    uint32 i = 0;
    uint32 k = 0;

    if (oPopulatePlayableListOnly)
    {
        for (i = 0; i < iDatapathList.size(); i++)
        {
            // Destroy the track info if present
            if (iDatapathList[i].iTrackInfo)
            {
                OSCL_DELETE(iDatapathList[i].iTrackInfo);
                iDatapathList[i].iTrackInfo = NULL;
            }
        }

        for (i = 0; i < sourcepresinfo.getNumTracks(); i++)
        {
            PVMFStatus checkcodec = PVMFFailure;
            int32 trackId = -1;

            // Go through each track, check codec type, and save the track info
            PVMFTrackInfo* curtrack = sourcepresinfo.getTrackInfo(i);
            trackId = curtrack->getTrackID();

            // check if this track can be directly pushed in playable list. This will be the case where decoder node is not needed
            // and Sink node supports the format and format specific info. OR
            // The track is a text track.

            if (iTrackSelectionList[i].iTsDecNode == NULL)
            {
                // check if it is a valid track or not, decoder node can be NULL only in 2 cases
                // 1) Track can be played without decoder nodes, here iTsTrackValidForPlayableList should be true OR track is TEXT track
                // 2) If the track is not valid at all, if this is the case, move onto next track.

                if (iTrackSelectionList[i].iTsTrackValidForPlayableList ||
                        (pv_mime_strcmp(curtrack->getTrackMimeType().get_str(), PVMF_MIME_3GPP_TIMEDTEXT)) == 0)
                {
                    // this can make directly to the Playable list, since it satisfies condition# 1 above.
                    iPlayableList.addTrackInfo(*curtrack);
                    iTrackSelectionList[i].iTsTrackValidForPlayableList = false;
                    checkcodec = PVMFSuccess;
                }
            }
            else
            {
                // if sink node alone does not support this track verify its parameters.
                retVal = DoVerifyTrackInfo(iTrackSelectionList[i], curtrack, checkcodec);
                if (retVal != PVMFSuccess)
                    return retVal;

                if (checkcodec == PVMFSuccess)
                {
                    //add it to playable list
                    iPlayableList.addTrackInfo(*curtrack);

                }
            }

            if (checkcodec != PVMFSuccess && trackId >= 0)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoTrackSelection() Bad track config for TrackId=%d", trackId));
                SendInformationalEvent(PVMFInfoTrackDisable, NULL, (OsclAny*)trackId, NULL, 0);
            }
        }
    }
    else
    {
        for (i = 0; i < sourcepresinfo.getNumTracks(); i++)
        {
            PVMFTrackInfo* curtrack = sourcepresinfo.getTrackInfo(i);

            for (k = 0; k < iTrackSelectionList.size(); k++)
            {
                // check which track is selected by comparing the TrackId
                int32 trackId = curtrack->getTrackID();
                if (trackId == iTrackSelectionList[k].iTsTrackID)
                {
                    for (uint32 j = 0; j < iDatapathList.size(); j++)
                    {
                        // if a track has already been added to the datapath, move onto the next datapath.
                        if (!iDatapathList[j].iTrackInfo)
                        {
                            // check for the corresponding datapath to the track
                            if (iDatapathList[j].iSinkNode == iTrackSelectionList[k].iTsSinkNode)
                            {
                                if (curtrack->DoesTrackHaveDependency() == true)
                                {
                                    // Track has dependency, move onto next track
                                    j = iDatapathList.size();
                                    k = iTrackSelectionList.size();
                                }
                                else
                                {
                                    // The track has been added to the final list, this means that this track is valid
                                    // and will make to DatapathList and all other video decoders will be destroyed.
                                    iDatapathList[j].iTrackInfo = OSCL_NEW(PVMFTrackInfo, (*curtrack));

                                    // set the decoder node, its session id and decoder cap&config IF in the Datapath, since the track is the
                                    // selected one.
                                    if (iTrackSelectionList[k].iTsDecNode)
                                    {
                                        iDatapathList[j].iDecNode = iTrackSelectionList[k].iTsDecNode;
                                        iDatapathList[j].iDecNodeSessionId = iTrackSelectionList[k].iTsDecNodeSessionId;
                                        iDatapathList[j].iDecNodeCapConfigIF = iTrackSelectionList[k].iTsDecNodeCapConfigIF;

                                        // once the track is selected and added to datapath - tell the dec node about preferences (i.e. which omx component to prioritize)
                                        if (iTrackSelectionHelper)
                                        {
                                            PVMFStatus status = NotifyDecNodeAboutComponentPreferences(iTrackSelectionList[k], curtrack);
                                            if (status != PVMFSuccess)
                                            {
                                                // just log , but ignore, perhaps the dec node does not support the interface
                                                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoTrackSelection() Cannot set dec node component preference for TrackId=%d", trackId));
                                            }
                                        }
                                    }

                                    iTrackSelectionList[k].iTsSinkNode = NULL;
                                    iTrackSelectionList[k].iTsSinkNodeSessionId = 0;
                                    iTrackSelectionList[k].iTsSinkNodeCapConfigIF = NULL;

                                    iTrackSelectionList[k].iTsDecNode = NULL;
                                    iTrackSelectionList[k].iTsDecNodeSessionId = 0;
                                    iTrackSelectionList[k].iTsDecNodeCapConfigIF = NULL;
                                    iTrackSelectionList[k].iTsDecNodePVInterfaceCapConfig = NULL;

                                    iTrackSelectionList[k].iTsTrackID = -1;
                                    iTrackSelectionList[k].iTsTrackValidForPlayableList = false;
                                }
                                j = iDatapathList.size();
                            }
                            // Datapath sinknode does not match, check the next datapath for the track
                        }
                        // a track has already been assigned for the datapath, check next datapath for the track
                    }
                    k = iTrackSelectionList.size(); // break out of the for(k = ...) loop
                }
                // The trackId of the track does not match with the track in the List, check the next track.
            }
        }

        // Go through the track selection list and set similar decoder nodes to NULL. There should be only 1 entry
        // of a decoder node either in DatapathList (this will be for the final playable track) or in
        // TrackSelectionList which will be for tracks which will not be used for playback.
        for (i = 0; i < iTrackSelectionList.size(); i++)
        {
            PVMFTrackInfo* currTrack = iSourcePresInfoList.getTrackInfo(i);
            for (uint32 j = i + 1; j < iTrackSelectionList.size(); j++)
            {
                PVMFTrackInfo* tmpTrack = iSourcePresInfoList.getTrackInfo(j);
                if (!(pv_mime_strcmp(currTrack->getTrackMimeType().get_str(), tmpTrack->getTrackMimeType().get_str())))
                {
                    iTrackSelectionList[j].iTsDecNode = NULL;
                    iTrackSelectionList[j].iTsDecNodeSessionId = 0;
                    iTrackSelectionList[j].iTsDecNodeCapConfigIF = NULL;
                }
            }
        }

        // now go through whole TrackSelectionList and look for similar sink and decoder nodes
        // to the track selected i.e. added to datapath, set all sink and decoder nodes to NULL for the track selected
        for (k = 0; k < iDatapathList.size(); k++)
        {
            for (uint32 s = 0; s < iTrackSelectionList.size(); s++)
            {
                if ((iDatapathList[k].iSinkNode == iTrackSelectionList[s].iTsSinkNode))
                {
                    iTrackSelectionList[s].iTsSinkNode = NULL;
                    iTrackSelectionList[s].iTsSinkNodeSessionId = 0;
                    iTrackSelectionList[s].iTsSinkNodeCapConfigIF = NULL;
                }

                if ((iDatapathList[k].iDecNode != NULL) &&
                        (iDatapathList[k].iDecNode == iTrackSelectionList[s].iTsDecNode))
                {
                    iTrackSelectionList[s].iTsDecNode = NULL;
                    iTrackSelectionList[s].iTsDecNodeSessionId = 0;
                    iTrackSelectionList[s].iTsDecNodeCapConfigIF = NULL;
                    iTrackSelectionList[s].iTsDecNodePVInterfaceCapConfig = NULL;
                }

                iTrackSelectionList[s].iTsTrackID = -1;
                iTrackSelectionList[s].iTsTrackValidForPlayableList = false;
            }
        }
    }
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoTrackSelection() Out"));
    return retVal;
}

PVMFStatus PVPlayerEngine::DoVerifyTrackInfo(PVPlayerEngineTrackSelection &aTrackSelection, PVMFTrackInfo* aTrack, PVMFStatus& aCheckcodec)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoVerifyTrackInfo() In %s", aTrack->getTrackMimeType().get_cstr()));

    PVMFStatus status = PVMFSuccess;
    OsclMemAllocator alloc;
    PvmiKvp kvp;
    kvp.key = NULL;

    const char* aFormatValType = PVMF_FORMAT_SPECIFIC_INFO_KEY;
    OsclRefCounterMemFrag aConfig;


    kvp.length = oscl_strlen(aFormatValType) + 1; // +1 for \0
    kvp.key = (PvmiKeyType)alloc.ALLOCATE(kvp.length);
    if (kvp.key == NULL)
    {
        return PVMFErrNoMemory;
    }
    oscl_strncpy(kvp.key, aFormatValType, kvp.length);
    aConfig = aTrack->getTrackConfigInfo();
    kvp.value.key_specific_value = (OsclAny*)(aConfig.getMemFragPtr());
    kvp.capacity = aConfig.getMemFragSize();

    aTrack->setTrackWidth((uint32) 0); // initialize to 0 to invalidate
    aTrack->setTrackHeight((uint32) 0);

    //Check if we have decoder node cap-config
    if (aTrackSelection.iTsDecNodeCapConfigIF != NULL)
    {

        PVMFFormatType DecnodeFormatType = aTrack->getTrackMimeType().get_str();

        PvmiKvp* iErrorKVP = NULL;


        // NOTES: 1) set both the FSI and MIME type as KVP parameters
        // if track selection helper is present, we'll send both parameters in setparamsync call
        // 2) in this piece of code - we don't know if we're dealing with audio or video dec node/track.
        // so, we'll first try to set VIDEO parameters. If it succeeds - we're dealing with video dec node.
        // if this fails - we'll try to set AUDIO parameters. If it succeeds,we're dealing with audio dec node
        // if both audio & video queries fail, then track just fails

        // 3) if track selection helper is present & omx nodes need to supply list of omx components, we'll try to
        // use the omx customized queries. If this method fails, we'll fall back to "old" method that simply checks if track config info is
        // valid/decodable or not (e.g. this would be the case with the old nodes that don't use Omx components).

        // 4) If track selection helper is not present, we don't need need the list of omx components that support the track, and
        // we'll just use the "old" simplified method for both omx&non-omx nodes that simply checks if track config info is
        // valid/decodable or not

        // 5) The simplified method requires a set parameter to set the MIME type, and then use verifyparameters call (which provides FSI)
        // 6) The new omx customized method requires a set parameter to set both the Mime type and FSI, and then uses a getparameter call to
        // get the list of omx component that support the track.

        int numKvp = 0;
        PvmiKvp* kvpPtr;

        PvmiKvp iKVPSetFormat[2];
        iKVPSetFormat[0] = kvp; // this is format specific info
        iKVPSetFormat[1].key = NULL;
        OSCL_StackString<64> iKeyStringSetFormat;
        iKVPSetFormat[1].value.pChar_value = (char*)DecnodeFormatType.getMIMEStrPtr();



        // Query for video decoder first with the track (providing both MIME type and FSI), if no success, then use the "old" method that just provides
        // the mime type. If this fails as well - attempt the same thing for audio.
        // for audio decoder.

        iKeyStringSetFormat = _STRLIT_CHAR(PVMF_VIDEO_DEC_FORMAT_TYPE_VALUE_KEY);
        iKVPSetFormat[1].key = iKeyStringSetFormat.get_str();

        bool isVideoAttempt = true;
        // loop to avoid code duplication. In the first pass - we try video the node, if it works - we break out of the loop
        // in the 2nd pass - we try the audio node (most of the code is the same), and break out of the loop
        while (true)
        {

            if (iTrackSelectionHelper)
            {
                aTrackSelection.iTsDecNodeCapConfigIF->setParametersSync(NULL, iKVPSetFormat, 2, iErrorKVP);
                if (iErrorKVP == NULL)
                {
                    // video set parameter succeeded - proceed with video.


                    // Query using get
                    OSCL_StackString<64> querykey;

                    // try to check the list of omx components that support the track
                    querykey = _STRLIT_CHAR(PVMF_DEC_AVAILABLE_OMX_COMPONENTS_KEY);

                    aCheckcodec = aTrackSelection.iTsDecNodeCapConfigIF->getParametersSync(NULL, querykey.get_str(), kvpPtr, numKvp, NULL);
                    if (aCheckcodec == PVMFSuccess)
                    {
                        if (numKvp > 0)
                        {
                            Oscl_Vector<OMXDecComponentItem, OsclMemAllocator> *pOMXcomponentList;
                            pOMXcomponentList = aTrack->getOMXComponentSupportingTheTrackVec();
                            int ii = 0;
                            char *str = NULL;
                            uint32 len = 0;
                            for (ii = 0; ii < numKvp; ii++)
                            {
                                // get a string from the list and push it into the OMXComponentList
                                str = kvpPtr[ii].value.pChar_value;
                                len = kvpPtr[ii].length;
                                pOMXcomponentList->push_back(OMXDecComponentItem(str, len));
                            }

                        }
                        else
                        {
                            // the omx component list that support the track is empty, i.e. the track is not supported
                            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyTrackInfo() verifyParametersSync() on decoder node succeeded - but no omx components support the track"));
                            return PVMFErrNotSupported;

                        }

                        // must release memory
                        status = aTrackSelection.iTsDecNodeCapConfigIF->releaseParameters(NULL, kvpPtr, numKvp);

                    }
                    else
                    {
                        // the query for omx component list that support the track failed
                        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyTrackInfo() verifyParametersSync() on decoder node failed - no omx component supports the track"));
                        return PVMFErrNotSupported;

                    }
                }
            }

            if ((iTrackSelectionHelper && iErrorKVP != NULL) || !iTrackSelectionHelper)
            {
                // invoking this piece of code means that we want to use the simplified track selection
                // (without getting the list of omx components).
                // this means that either no track selection helper is present (in which case - we apply the simplified method
                // to both omx and non-omx nodes), or that the track selection helper is present, but that the previous
                // set parameter call (meant to get the list of omx components) failed because we are dealing with old nodes which cannot take both the FSI & MIME info, only the MIME type

                iErrorKVP = NULL;

                // NOTE: Format type value key is stored at iKVPSetFormat[1] position (so that old nodes could reject the
                // previous query
                aTrackSelection.iTsDecNodeCapConfigIF->setParametersSync(NULL, &iKVPSetFormat[1], 1, iErrorKVP);
                if (iErrorKVP == NULL)
                {
                    //verify codec specific info thru a function call (to avoid clobbering)
                    aCheckcodec = TryDecNodeVerifyParameterSync(aTrackSelection, &kvp);

                    if (aCheckcodec == PVMFFailure)
                    {
                        // this is the error that gets returned from the method in case of verifyparametersync did a leave
                        alloc.deallocate((OsclAny*)(kvp.key));
                        aCheckcodec = PVMFSuccess;
                        return PVMFSuccess;
                    }
                    else if (aCheckcodec != PVMFSuccess)
                    {
                        alloc.deallocate((OsclAny*)(kvp.key));
                        //In case of other error code, this is operation error.
                        if (aCheckcodec != PVMFErrNotSupported)
                        {
                            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyTrackInfo() verifyParametersSync() on decoder node failed"));
                            return aCheckcodec;
                        }
                        return status;
                    }
                }
            }

            if (iErrorKVP == NULL)
            {

                numKvp = 0;
                if (true == isVideoAttempt)
                {
                    // if we end up here, i.e.
                    // if either simple track verify method or omx list verify track method succeeded for video,
                    // then we know that this is video node and track. We need to verify things with sink node)

                    // verify widht/height with the sink
                    OSCL_StackString<64> querykey;
                    querykey = _STRLIT_CHAR("x-pvmf/video/render");
                    if (aTrackSelection.iTsDecNodeCapConfigIF->getParametersSync(NULL, querykey.get_str(), kvpPtr, numKvp, NULL) == PVMFSuccess)
                    {
                        for (int32 ii = 0; ii < numKvp; ii++)
                        {

                            // record width and height of the video track
                            if (pv_mime_strcmp(kvpPtr[ii].key, MOUT_VIDEO_WIDTH_KEY) >= 0)
                            {
                                aTrack->setTrackWidth(kvpPtr[0].value.uint32_value);
                            }
                            if (pv_mime_strcmp(kvpPtr[ii].key, MOUT_VIDEO_HEIGHT_KEY) >= 0)
                            {
                                aTrack->setTrackHeight(kvpPtr[1].value.uint32_value);
                            }
                        }

                        //verify width/height
                        if (aTrackSelection.iTsSinkNodeCapConfigIF != NULL)
                            aCheckcodec = aTrackSelection.iTsSinkNodeCapConfigIF->verifyParametersSync(NULL, kvpPtr, numKvp);
                        status = aTrackSelection.iTsDecNodeCapConfigIF->releaseParameters(NULL, kvpPtr, numKvp);
                    }
                }
                else
                {
                    // this was the attempt to communicate with audio node, and it succeeded
                    // if we end up here, i.e.
                    // if either simple track verify method or omx list verify track method succeeded for audio,
                    // then we know that this is audio node and track. We need to verify few things with sink node)
                    numKvp = 0;
                    OSCL_StackString<64> querykey;
                    querykey = _STRLIT_CHAR("x-pvmf/audio/render");
                    if (aTrackSelection.iTsDecNodeCapConfigIF->getParametersSync(NULL, querykey.get_str(), kvpPtr, numKvp, NULL) == PVMFSuccess)
                    {
                        //verify samplerate and channels
                        if (aTrackSelection.iTsSinkNodeCapConfigIF != NULL)
                            aCheckcodec = aTrackSelection.iTsSinkNodeCapConfigIF->verifyParametersSync(NULL, kvpPtr, numKvp);
                        status = aTrackSelection.iTsDecNodeCapConfigIF->releaseParameters(NULL, kvpPtr, numKvp);
                    }
                }

                break; // the attempt succeeded, so need to go through the loop again
            }
            else
            {
                // this attempt failed. If it was an attempt to communicate with video node,
                // then, repeat the loop for audio node.
                // If it was already the attempt to communicate with audio node then, we've run out of options.
                if (true == isVideoAttempt)
                {
                    // if we ended up here, it means that neither omx list nor the simplified verification worked for video
                    // meaning that this is audio track and audio node (or else that something else is wrong)
                    // Set up the parameters for audio here
                    isVideoAttempt = false;
                    iErrorKVP = NULL;

                    iKeyStringSetFormat = NULL;
                    // format specific info is already in iKVPSetFormat[0]
                    // adjust the [1] field again to fit the audio case
                    iKVPSetFormat[1].key = NULL;

                    iKeyStringSetFormat += _STRLIT_CHAR(PVMF_AUDIO_DEC_FORMAT_TYPE_VALUE_KEY);
                    iKVPSetFormat[1].key = iKeyStringSetFormat.get_str();
                    // now go back and repeat the loop for audio
                }
                else
                {
                    // both video and audio set parameter sync failed for the parameter for both
                    // omx list method and the simplified track verify method
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyTrackInfo() No queries worked for either video or audio decoder node"));
                    break; // break out of the loop

                }

            }

        }// end of while(true)


    }
    else // end of if(check whether we have dec node cap config)
    {
        if (aTrackSelection.iTsSinkNodeCapConfigIF != NULL)
        {
            aCheckcodec = aTrackSelection.iTsSinkNodeCapConfigIF->verifyParametersSync(NULL, &kvp, 1);
        }
    }

    alloc.deallocate((OsclAny*)(kvp.key));
    if (aCheckcodec != PVMFSuccess)
    {
        //In case of other error code, this is operation error.
        if (aCheckcodec != PVMFErrNotSupported)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyTrackInfo() verifyParametersSync() on sink node failed"));
            return aCheckcodec;
        }
        return status;
    }

    //verify bitrate
    PvmiKvp iKVPBitRate;
    iKVPBitRate.key = NULL;

    OSCL_StackString<64> iKVPStringBitRate = _STRLIT_CHAR(PVMF_BITRATE_VALUE_KEY);
    iKVPBitRate.key = iKVPStringBitRate.get_str();
    iKVPBitRate.value.uint32_value = aTrack->getTrackBitRate();

    if (aTrackSelection.iTsSinkNodeCapConfigIF != NULL)
        aCheckcodec = aTrackSelection.iTsSinkNodeCapConfigIF->verifyParametersSync(NULL, &iKVPBitRate, 1);
    //In case of other error code, this is operation error.
    if (aCheckcodec != PVMFSuccess)
    {
        //In case of other error code, this is operation error.
        if (aCheckcodec != PVMFErrNotSupported)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyTrackInfo() verifyParametersSync() on sinknode bitrate failed"));
            return aCheckcodec;
        }
        return status;
    }

    //verify video framerate, if track is not video, sink will return ErrNotSupported.
    if (aTrack->getTrackFrameRate() > 0)
    {
        PvmiKvp iKVPFrameRate;
        iKVPFrameRate.key = NULL;

        OSCL_StackString<64> iKVPStringFrameRate = _STRLIT_CHAR(PVMF_FRAMERATE_VALUE_KEY);
        iKVPFrameRate.key = iKVPStringFrameRate.get_str();
        iKVPFrameRate.value.uint32_value = aTrack->getTrackFrameRate();

        if (aTrackSelection.iTsSinkNodeCapConfigIF != NULL)
            aCheckcodec = aTrackSelection.iTsSinkNodeCapConfigIF->verifyParametersSync(NULL, &iKVPFrameRate, 1);
        //In case of other error code, this is operation error.
        if (aCheckcodec != PVMFErrNotSupported && aCheckcodec != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyTrackInfo() verifyParametersSync() on sink node framerate failed"));
            return aCheckcodec;
        }
    }

    return status;
}

PVMFStatus PVPlayerEngine::DoSinkNodeDecNodeReset(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::DoSinkNodeDecNodeReset() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeDecNodeReset() In"));

    iNumPendingNodeCmd = 0;
    PVMFCommandId cmdid = -1;
    int32 leavecode = 0;

    for (uint32 i = 0; i < iDatapathList.size(); ++i)
    {
        if (iDatapathList[i].iSinkNode != NULL)
        {
            // Call Reset() on the sink node
            PVPlayerEngineContext* context = AllocateEngineContext(&(iDatapathList[i]), iDatapathList[i].iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeDecNodeReset);

            leavecode = IssueSinkNodeReset(&(iDatapathList[i]), (OsclAny*) context, cmdid);

            if (cmdid != -1 && leavecode == 0)
            {
                ++iNumPendingNodeCmd;
            }
            else
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeDecNodeReset() Reset on sink node leaved, asserting"));
                FreeEngineContext(context);
                OSCL_ASSERT(false);
            }
        }

        if (iDatapathList[i].iDecNode != NULL)
        {
            // Call Reset() on the dec node
            PVPlayerEngineContext* context = AllocateEngineContext(&(iDatapathList[i]), iDatapathList[i].iDecNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeDecNodeReset);

            leavecode = IssueDecNodeReset(iDatapathList[i].iDecNode, iDatapathList[i].iDecNodeSessionId, (OsclAny*) context, cmdid);

            if (cmdid != -1 && leavecode == 0)
            {
                ++iNumPendingNodeCmd;
            }
            else
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeDecNodeReset() Reset on sink node leaved, asserting"));
                FreeEngineContext(context);
                OSCL_ASSERT(false);
            }
        }
    }

    // There can be some more decoders in TrackSelectionList on which engine needs to call Reset. call Reset on those decoders now.
    for (uint32 j = 0; j < iTrackSelectionList.size(); j++)
    {
        if (iTrackSelectionList[j].iTsDecNode != NULL)
        {
            // Call Reset() on the dec node
            PVPlayerEngineContext* context = AllocateEngineContext(NULL, iTrackSelectionList[j].iTsDecNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeDecNodeReset);

            leavecode = IssueDecNodeReset(iTrackSelectionList[j].iTsDecNode, iTrackSelectionList[j].iTsDecNodeSessionId, (OsclAny*) context, cmdid);

            if (cmdid != -1 && leavecode == 0)
            {
                ++iNumPendingNodeCmd;
            }
            else
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeDecNodeReset() Reset on sink node leaved, asserting"));
                FreeEngineContext(context);
                OSCL_ASSERT(false);
            }
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeDecNodeReset() Out"));
    if (iNumPendingNodeCmd == 0)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeDecNodeReset() No datapath could be prepared!"));
        return PVMFFailure;
    }
    else
    {
        return PVMFSuccess;
    }
}

PVMFStatus PVPlayerEngine::DoSinkDecCleanupSourcePrepare(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() In"));

    uint32 i = 0;
    //Destroy created temporal decoder node and sink node
    for (i = 0; i < iTrackSelectionList.size(); ++i)
    {
        if (iTrackSelectionList[i].iTsDecNode != NULL)
        {
            if (iTrackSelectionList[i].iTsDecNodeCapConfigIF)
                iTrackSelectionList[i].iTsDecNodeCapConfigIF = NULL;
            PVMFStatus status = PVMFFailure;
            status = iTrackSelectionList[i].iTsDecNode->Disconnect(iTrackSelectionList[i].iTsDecNodeSessionId);
            if (status == PVMFFailure)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() Disconnect on dec node Failed"));
                OSCL_ASSERT(false);
            }
            status = iTrackSelectionList[i].iTsDecNode->ThreadLogoff();
            if (status == PVMFFailure)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() ThreadLogoff on dec node Failed"));
                OSCL_ASSERT(false);
            }
            PVPlayerEngineUuidNodeMapping* iter = iNodeUuids.begin();
            for (; iter != iNodeUuids.end(); ++iter)
                if (iter->iNode == iTrackSelectionList[i].iTsDecNode)
                    break;

            if (iter != iNodeUuids.end())
            {
                bool release_status = false;

                release_status = iPlayerNodeRegistry.ReleaseNode(iter->iUuid, iTrackSelectionList[i].iTsDecNode);
                if (release_status == false)
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() Factory returned false while releasing the decnode"));
                    OSCL_ASSERT(false);
                    return PVMFFailure;
                }

                iNodeUuids.erase(iter);
                iTrackSelectionList[i].iTsDecNode = NULL;
            }
            else
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() decnode not found"));
                return PVMFFailure;
            }
        }
        if (iTrackSelectionList[i].iTsSinkNode != NULL)
        {
            for (uint32 j = 0; j < iDatapathList.size(); j++)
            {
                if (iDatapathList[j].iSinkNode == iTrackSelectionList[i].iTsSinkNode)
                {
                    PVMFStatus status = PVMFFailure;
                    status = iDatapathList[j].iSinkNode->Disconnect(iDatapathList[j].iSinkNodeSessionId);
                    if (status == PVMFFailure)
                    {
                        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() Disconnect on sink node Failed"));
                        OSCL_ASSERT(false);
                    }
                    status = iDatapathList[j].iSinkNode->ThreadLogoff();
                    if (status == PVMFFailure)
                    {
                        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() ThreadLogoff on sink node Failed"));
                        OSCL_ASSERT(false);
                    }
                    if (iDatapathList[j].iSinkNodeCapConfigIF)
                    {
                        iDatapathList[j].iSinkNodeCapConfigIF->removeRef();
                        iDatapathList[j].iSinkNodeCapConfigIF = NULL;
                    }
                    iDatapathList[j].iSinkNode = NULL;
                }
            }
        }
    }

    // Also go through the datapathList and if for any datapath TrackInfo is not created, delete that datapath
    for (i = 0; i < iDatapathList.size(); i++)
    {
        if (iDatapathList[i].iTrackInfo == NULL)
        {
            // destroy the sinks first.
            if (iDatapathList[i].iSinkNode != NULL)
            {
                PVMFStatus status = PVMFFailure;
                status = iDatapathList[i].iSinkNode->Disconnect(iDatapathList[i].iSinkNodeSessionId);
                if (status == PVMFFailure)
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() Disconnect on sink node Failed"));
                    OSCL_ASSERT(false);
                }
                status = iDatapathList[i].iSinkNode->ThreadLogoff();
                if (status == PVMFFailure)
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() ThreadLogoff on sink node Failed"));
                    OSCL_ASSERT(false);
                }
                if (iDatapathList[i].iSinkNodeCapConfigIF)
                {
                    iDatapathList[i].iSinkNodeCapConfigIF->removeRef();
                    iDatapathList[i].iSinkNodeCapConfigIF = NULL;
                }
                if (iDatapathList[i].iSinkNodeSyncCtrlIF)
                {
                    iDatapathList[i].iSinkNodeSyncCtrlIF->removeRef();
                    iDatapathList[i].iSinkNodeSyncCtrlIF = NULL;
                }

                iDatapathList[i].iSinkNode = NULL;
            }

            // next delete the decoder nodes
            if (iDatapathList[i].iDecNode != NULL)
            {
                if (iDatapathList[i].iDecNodeCapConfigIF)
                    iDatapathList[i].iDecNodeCapConfigIF = NULL;
                PVMFStatus status = PVMFFailure;
                status = iDatapathList[i].iDecNode->Disconnect(iDatapathList[i].iDecNodeSessionId);
                if (status == PVMFFailure)
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() Disconnect on dec node Failed"));
                    OSCL_ASSERT(false);
                }
                status = iDatapathList[i].iDecNode->ThreadLogoff();
                if (status == PVMFFailure)
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() ThreadLogoff on dec node Failed"));
                    OSCL_ASSERT(false);
                }
                PVPlayerEngineUuidNodeMapping* iter = iNodeUuids.begin();
                for (; iter != iNodeUuids.end(); ++iter)
                    if (iter->iNode == iDatapathList[i].iDecNode)
                        break;

                if (iter != iNodeUuids.end())
                {
                    bool release_status = false;

                    release_status = iPlayerNodeRegistry.ReleaseNode(iter->iUuid, iDatapathList[i].iDecNode);
                    if (release_status == false)
                    {
                        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() Factory returned false while releasing the decnode"));
                        OSCL_ASSERT(false);
                        return PVMFFailure;
                    }

                    iNodeUuids.erase(iter);
                    iDatapathList[i].iDecNode = NULL;
                }
                else
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() decnode not found"));
                    return PVMFFailure;
                }
            }
        }
    }

    // Reset the Presentation Info list
    iSourcePresInfoList.Reset();

    // Clear the Track selection List
    iTrackSelectionList.clear();

    PVMFStatus cmdstatus = PVMFErrNotSupported;

    // Notify the TargetNPT to the source node before calling Prepare.
    if (iSourceNodePBCtrlIF)
    {
        cmdstatus = iSourceNodePBCtrlIF->NotifyTargetPositionSync(iTargetNPT);
    }
    if (cmdstatus == PVMFSuccess || cmdstatus == PVMFErrNotSupported)
    {
        // Prepare the source node
        cmdstatus = DoSourceNodePrepare(aCmdId, aCmdContext);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() Out"));
    return cmdstatus;
}

PVMFStatus PVPlayerEngine::DoSourceNodePrepare(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::DoSourceNodePrepare() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodePrepare() In"));

    if (iSourceNode == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodePrepare() Source node not available."));
        return PVMFFailure;
    }

    // If source node is already in Prepared state then don't call Prepare()
    if (iSourceNode->GetState() == EPVMFNodePrepared)
    {
        // Datapaths are already set during intelligent track selection, just query for optional interfaces.
        iNumPendingDatapathCmd = 0;
        for (uint32 i = 0; i < iDatapathList.size(); ++i)
        {
            if (iDatapathList[i].iTrackInfo != NULL)
            {
                PVMFStatus cmdstatus = DoSinkNodeQueryInterfaceOptional(iDatapathList[i], aCmdId, aCmdContext);
                if (cmdstatus == PVMFSuccess)
                {
                    ++iNumPendingDatapathCmd;
                }
            }
        }

        if (iNumPendingDatapathCmd == 0)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodePrepare() No datapath could be prepared!"));
            return PVMFFailure;
        }
        else
        {
            return PVMFSuccess;
        }
    }

    // Call Prepare() on the source node
    PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodePrepare);

    PVMFCommandId cmdid = -1;
    int32 leavecode = 0;
    OSCL_TRY(leavecode, cmdid = iSourceNode->Prepare(iSourceNodeSessionId, (OsclAny*)context));
    OSCL_FIRST_CATCH_ANY(leavecode,
                         FreeEngineContext(context);
                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodePrepare() Prepare on iSourceNode did a leave!"));
                         return PVMFFailure);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodePrepare() Out"));

    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::DoSinkNodeQueryInterfaceOptional(PVPlayerEngineDatapath &aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceOptional() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceOptional() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));

    int32 leavecode = 0;

    // Request optional extension interface from the sink node
    PVPlayerEngineContext* context = NULL;
    PVMFCommandId cmdid = -1;
    aDatapath.iNumPendingCmd = 0;

    // Query for Metadata IF
    context = AllocateEngineContext(&aDatapath, aDatapath.iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeQueryMetadataIF);
    PVUuid metadatauuid = KPVMFMetadataExtensionUuid;
    cmdid = -1;
    leavecode = 0;
    aDatapath.iSinkNodePVInterfaceMetadataExt = NULL;
    OSCL_TRY(leavecode, cmdid = aDatapath.iSinkNode->QueryInterface(aDatapath.iSinkNodeSessionId, metadatauuid, aDatapath.iSinkNodePVInterfaceMetadataExt, (OsclAny*)context));
    if (leavecode)
    {
        aDatapath.iSinkNodePVInterfaceMetadataExt = NULL;
        FreeEngineContext(context);
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceOptional() QueryInterface on sink node for metadata IF did a leave!"));
    }
    else
    {
        ++aDatapath.iNumPendingCmd;
    }

    if (aDatapath.iNumPendingCmd > 0)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceOptional() Out"));
        return PVMFSuccess;
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceOptional() Out No pending QueryInterface() on sink node"));
        return PVMFErrNotSupported;
    }
}

PVMFStatus PVPlayerEngine::DoDecNodeQueryInterfaceOptional(PVPlayerEngineDatapath &aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVPlayerEngine::DoDecNodeQueryInterfaceOptional() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDecNodeQueryInterfaceOptional() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));

    // Check if the dec node is present
    if (aDatapath.iDecNode == NULL)
    {
        return PVMFErrNotSupported;
    }

    PVPlayerEngineContext* context = NULL;
    PVMFCommandId cmdid = -1;
    int32 leavecode = 0;

    aDatapath.iNumPendingCmd = 0;

    // Query for Metadata IF
    context = AllocateEngineContext(&aDatapath, aDatapath.iDecNode, NULL, aCmdId, aCmdContext, PVP_CMD_DecNodeQueryMetadataIF);
    PVUuid metadatauuid = KPVMFMetadataExtensionUuid;
    cmdid = -1;
    leavecode = 0;
    aDatapath.iDecNodePVInterfaceMetadataExt = NULL;
    OSCL_TRY(leavecode, cmdid = aDatapath.iDecNode->QueryInterface(aDatapath.iDecNodeSessionId, metadatauuid, aDatapath.iDecNodePVInterfaceMetadataExt, (OsclAny*)context));
    if (leavecode)
    {
        aDatapath.iDecNodePVInterfaceMetadataExt = NULL;
        FreeEngineContext(context);
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDecNodeQueryInterfaceOptional() QueryInterface on dec node for metadata IF did a leave!"));
    }
    else
    {
        ++aDatapath.iNumPendingCmd;
    }

    if (aDatapath.iNumPendingCmd > 0)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDecNodeQueryInterfaceOptional() Out"));
        return PVMFSuccess;
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDecNodeQueryInterfaceOptional() Out No pending QueryInterface() on dec node"));
        return PVMFErrNotSupported;
    }
}


PVMFStatus PVPlayerEngine::DoDatapathPrepare(PVPlayerEngineDatapath &aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::DoDatapathPrepare() for %s Tick=%d",
                     aDatapath.iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathPrepare() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));
    int32 leavecode = 0;

    // Create the datapath utility object
    if (aDatapath.iDatapath == NULL)
    {
        leavecode = 0;
        OSCL_TRY(leavecode, aDatapath.iDatapath = OSCL_NEW(PVPlayerDatapath, ()));
        OSCL_FIRST_CATCH_ANY(leavecode,
                             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDatapathPrepare() Could not create datapath object"));
                             return PVMFErrNoMemory);
    }

    // Configure the datapath utility based on datapath configuration
    aDatapath.iDatapath->SetObserver(*this, *this, *this);
    aDatapath.iDatapath->SetSourceNode(iSourceNode);
    aDatapath.iDatapath->SetSinkNode(aDatapath.iSinkNode);

    if (aDatapath.iDecNode)
    {
        aDatapath.iDatapath->SetDecNode(aDatapath.iDecNode);
        aDatapath.iDatapath->SetSourceDecTrackInfo(*(aDatapath.iTrackInfo));
        aDatapath.iDatapath->SetDecSinkFormatType(aDatapath.iSinkFormat);
    }
    else
    {
        aDatapath.iDatapath->SetSourceSinkTrackInfo(*(aDatapath.iTrackInfo));
    }

    // Prepare the datapath
    PVPlayerEngineContext* context = AllocateEngineContext(&aDatapath, NULL, aDatapath.iDatapath, aCmdId, aCmdContext, PVP_CMD_DPPrepare);

    PVMFStatus retval = aDatapath.iDatapath->Prepare((OsclAny*)context);
    if (retval != PVMFSuccess)
    {
        FreeEngineContext(context);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathPrepare() Out"));
    return retval;
}


PVMFStatus PVPlayerEngine::DoSourceNodeQueryDataSourcePosition(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeQueryDataSourcePosition() In"));

    // Check if the source node has position control IF
    if (iSourceNodePBCtrlIF == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryDataSourcePosition() Playback control IF on source node not available"));
        return PVMFErrNotSupported;
    }

    uint32 timems = 0;
    if (iCurrentBeginPosition.iIndeterminate == false)
    {
        // Convert beginning position to milliseconds
        PVMFStatus retval = ConvertToMillisec(iCurrentBeginPosition, timems);
        if (retval != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryDataSourcePosition() Converting to millisec failed"));
            return retval;
        }
    }

    PVMFCommandId cmdid = -1;
    iCurrentBeginPosition.iPosValue.millisec_value = timems;
    iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;

    if (iSeekToSyncPoint && iSyncPointSeekWindow > 0)
    {
        iTargetNPT = iCurrentBeginPosition.iPosValue.millisec_value;
        PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQueryDataSourcePosition);

        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeQueryDataSourcePosition() Calling QueryDataSourcePosition() Starting pos %d ms, SeekToSyncPt %d", iTargetNPT, iSeekToSyncPoint));
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeQueryDataSourcePosition() Calling QueryDataSourcePosition() Starting pos %d ms, SeekToSyncPt %d", iTargetNPT, iSeekToSyncPoint));
        // As in case of MP4 file we need to call overload function of QueryDataSourcePosition which retruns
        // I frame before and after instead of actaul NPT, format type will be checked here to first find if
        // format-type is one of the MP4 varient

        PVMFNodeCapability nodeCapability;
        iSourceNode->GetCapability(nodeCapability);
        PVMFFormatType * formatType = nodeCapability.iInputFormatCapability.begin();
        bool mpeg4FormatType = false;
        if (formatType != NULL)
        {
            if ((pv_mime_strcmp((char*)formatType->getMIMEStrPtr(), PVMF_MIME_MPEG4FF)) == 0)
            {
                mpeg4FormatType = true;
            }
            else
            {
                mpeg4FormatType = false;
            }
        }
        int32 leavecode = 0;
        if (mpeg4FormatType)
        {
            OSCL_TRY(leavecode, cmdid = iSourceNodePBCtrlIF->QueryDataSourcePosition(iSourceNodeSessionId, iTargetNPT,
                                        iSeekPointBeforeTargetNPT, iSeekPointAfterTargetNPT, (OsclAny*) context, iSeekToSyncPoint));
        }
        else
        {
            OSCL_TRY(leavecode, cmdid = iSourceNodePBCtrlIF->QueryDataSourcePosition(iSourceNodeSessionId, iTargetNPT, iActualNPT,
                                        iSeekToSyncPoint, (OsclAny*)context));
        }

        if (leavecode != 0)
        {
            FreeEngineContext(context);
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryDataSourcePosition() QueryDataSourcePosition on iSourceNodePBCtrlIF did a leave!"));
            if (leavecode == PVMFErrNotSupported || leavecode == PVMFErrArgument)
            {
                // Since position query is not supported, assume the repositioning will
                // go to the requested position
                // Do the source positioning
                return DoSourceNodeSetDataSourcePosition(aCmdId, aCmdContext);
            }
            else
            {
                return PVMFFailure;
            }
        }
    }
    else
    {
        // Go straight to repositioning the data source
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeQueryDataSourcePosition: Straight call SetDataSourcePosition Starting pos %d ms, SeekToSyncPt %d", iTargetNPT, iSeekToSyncPoint));
        return DoSourceNodeSetDataSourcePosition(aCmdId, aCmdContext);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeQueryDataSourcePosition() Out"));

    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoSourceNodeSetDataSourcePosition(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePosition() In"));

    // Check if the source node has position control IF
    if (iSourceNodePBCtrlIF == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePosition() Playback control IF on source node not available"));
        // Since repositioning IF is not supported by this source node, assume the playback
        // will start from time 0
        iActualNPT = 0;
        iActualMediaDataTS = 0;
        iSkipMediaDataTS = 0;
        // Then continue to handle like success case
        iStartNPT = 0;
        iStartMediaDataTS = 0;
        iPlaybackClock.UpdateNPTClockPosition(iStartNPT, (iPlaybackDirection < 0) ? true : false);
        // Save the actual starting position for GetPlaybackRange() query
        iCurrentBeginPosition.iPosValue.millisec_value = iActualNPT;
        iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;
        iTargetNPT = iActualNPT;

        // Repositioning so reset the EOS received flag for each active datapath
        for (uint32 i = 0; i < iDatapathList.size(); ++i)
        {
            if (iDatapathList[i].iDatapath)
            {
                iDatapathList[i].iEndOfDataReceived = false;
            }
        }

        // Start the source node
        return DoSourceNodeStart(aCmdId, aCmdContext);
    }

    // Set the position of the source node
    PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeSetDataSourcePosition);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePosition() Calling SetDataSourcePosition() TargetNPT %d ms, SeekToSyncPoint %d", iTargetNPT, iSeekToSyncPoint));

    int32 leavecode = 0;
    PVMFCommandId cmdid = -1;

    OSCL_TRY(leavecode, cmdid = iSourceNodePBCtrlIF->SetDataSourcePosition(iSourceNodeSessionId, iTargetNPT, iActualNPT, iActualMediaDataTS, iSeekToSyncPoint, iStreamID, (OsclAny*)context));
    OSCL_FIRST_CATCH_ANY(leavecode,
                         FreeEngineContext(context);
                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePosition() SetDataSourcePosition on iSourceNodePBCtrlIF did a leave!"));
                         if (leavecode == PVMFErrNotSupported || leavecode == PVMFErrArgument)
{
    // Since this repositioning was not supported, assume the playback
    // will start from same location as before reposition request.
    PVPPlaybackPosition curpos;
    curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC;
    GetPlaybackClockPosition(curpos);
        uint32 clockcurpos = 0;
        bool tmpbool = false;
        iPlaybackClock.GetCurrentTime32(clockcurpos, tmpbool, PVMF_MEDIA_CLOCK_MSEC);

        // since repositioning is not supported continue playing from current position.
        iWatchDogTimerInterval = 0;
        iActualNPT = curpos.iPosValue.millisec_value;
        iActualMediaDataTS = clockcurpos;
        iSkipMediaDataTS = clockcurpos;

        iStartNPT = iActualNPT;
        iStartMediaDataTS = iSkipMediaDataTS;
        iPlaybackClock.UpdateNPTClockPosition(iStartNPT, (iPlaybackDirection < 0) ? true : false);

        // also decrement the stream id as no skip will be called on MIO node.
        --iStreamID;

        // Save the actual starting position for GetPlaybackRange() query
        iCurrentBeginPosition.iPosValue.millisec_value = iActualNPT;
        iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;
        iTargetNPT = iActualNPT;

        // Repositioning so reset the EOS received flag for each active datapath
        for (uint32 i = 0; i < iDatapathList.size(); ++i)
        {
            if (iDatapathList[i].iDatapath)
            {
                iDatapathList[i].iEndOfDataReceived = false;
            }
        }

        // Start the source node
        return DoSourceNodeStart(aCmdId, aCmdContext);
    }
    else
    {
        return PVMFFailure;
    }
                        );

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePosition() Out"));

    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::DoSourceNodeSetDataSourceDirection(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourceDirection() In"));

    if (iChangePlaybackDirectionWhenResuming)
    {
        //Setting direction during engine Resume, due to a SetPlaybackRate that
        //occurred during engine Paused state.

        // Check if the source node has position control IF
        if (iSourceNodeDirCtrlIF == NULL)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeSetDataSourceDirection() Direction control IF on source node not available"));

            // Since repositioning IF is not supported by this source node, assume the playback
            // will start from time 0
            iActualNPT = 0;
            iActualMediaDataTS = 0;
            iSkipMediaDataTS = 0;
            // Then continue to handle like success case
            iStartNPT = 0;
            iStartMediaDataTS = 0;
            iPlaybackClock.UpdateNPTClockPosition(iStartNPT, (iPlaybackDirection < 0) ? true : false);
            // Save the actual starting position for GetPlaybackRange() query
            iCurrentBeginPosition.iPosValue.millisec_value = iActualNPT;
            iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;
            iTargetNPT = iActualNPT;

            // Repositioning so reset the EOS flag for each active datapath
            for (uint32 i = 0; i < iDatapathList.size(); ++i)
            {
                if (iDatapathList[i].iDatapath)
                {
                    iDatapathList[i].iEndOfDataReceived = false;
                }
            }

            return PVMFErrNotSupported;
        }

        // Set the position of the source node
        PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeSetDataSourceDirection);

        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourceDirection() Calling SetDataSourcePosition() "));

        int32 leavecode = 0;
        PVMFCommandId cmdid = -1;
        OSCL_TRY(leavecode, cmdid = iSourceNodeDirCtrlIF->SetDataSourceDirection(iSourceNodeSessionId
                                    , (iPlaybackDirection_New < 0) ? PVMF_DATA_SOURCE_DIRECTION_REVERSE : PVMF_DATA_SOURCE_DIRECTION_FORWARD
                                    , iActualNPT
                                    , iActualMediaDataTS
                                    , iOutsideTimebase
                                    , (OsclAny*)context));
        OSCL_FIRST_CATCH_ANY(leavecode,
                             FreeEngineContext(context);
                             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeSetDataSourceDirection() SetDataSourceDirection on iSourceNodeDirCtrlIF did a leave!"));
                             if (leavecode == PVMFErrNotSupported || leavecode == PVMFErrArgument)
    {
        // Since this repositioning was not supported, assume the playback
        // will start from same location as before repos request.
        PVPPlaybackPosition curpos;
        curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC;
        GetPlaybackClockPosition(curpos);
            uint32 clockcurpos = 0;
            bool tmpbool = false;
            iPlaybackClock.GetCurrentTime32(clockcurpos, tmpbool, PVMF_MEDIA_CLOCK_MSEC);

            // since repositioning is not supported continue playing from current position.
            iWatchDogTimerInterval = 0;
            iActualNPT = curpos.iPosValue.millisec_value;
            iActualMediaDataTS = clockcurpos;
            iSkipMediaDataTS = clockcurpos;

            iStartNPT = iActualNPT;
            iStartMediaDataTS = iSkipMediaDataTS;
            iPlaybackClock.UpdateNPTClockPosition(iStartNPT, (iPlaybackDirection < 0) ? true : false);

            // Save the actual starting position for GetPlaybackRange() query
            iCurrentBeginPosition.iPosValue.millisec_value = iActualNPT;
            iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;
            iTargetNPT = iActualNPT;

            // Repositioning so reset the EOS flag for each active datapath
            for (uint32 i = 0; i < iDatapathList.size(); ++i)
            {
                if (iDatapathList[i].iDatapath)
                {
                    iDatapathList[i].iEndOfDataReceived = false;
                }
            }

            return PVMFErrNotSupported;
        }
        else
        {
            return PVMFFailure;
        }
                            );

        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourceDirection() Out"));

        return PVMFSuccess;
    }
    else
    {
        //changing direction during SetPlaybackRate command

        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourceDirection() In"));

        // Check if the source node has direction control IF
        if (iSourceNodeDirCtrlIF == NULL)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeSetDataSourceDirection() No source direction control IF"));
            return PVMFErrNotSupported;
        }

        // Pause the playback clock
        bool clockpausedhere = iPlaybackClock.Pause();

        // Set the new direction on the source node
        PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeSetDataSourceDirection);

        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourceDirection() Calling SetDataSourceDirection() on source node."));

        int32 leavecode = 0;
        PVMFCommandId cmdid = -1;
        OSCL_TRY(leavecode, cmdid = iSourceNodeDirCtrlIF->SetDataSourceDirection(iSourceNodeSessionId
                                    , (iPlaybackDirection_New < 0) ? PVMF_DATA_SOURCE_DIRECTION_REVERSE : PVMF_DATA_SOURCE_DIRECTION_FORWARD
                                    , iActualNPT
                                    , iActualMediaDataTS
                                    , iOutsideTimebase_New
                                    , (OsclAny*)context));
        OSCL_FIRST_CATCH_ANY(leavecode,
                             FreeEngineContext(context);
                             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeSetDataSourceDirection() SetDataSourceDirection on iSourceNodeDirCtrlIF did a leave!"));
                             if (clockpausedhere)
    {
        // Resume the clock if paused in this function
        StartPlaybackClock();
        }

        if (leavecode == PVMFErrNotSupported || leavecode == PVMFErrArgument)
    {
        return leavecode;
    }
    else
    {
        return PVMFFailure;
    }
                        );

        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourceDirection() Out"));

        return PVMFSuccess;
        //wait on node command complete and a call to HandleSourceNodeSetDataSourceDirection
    }
}

PVMFStatus PVPlayerEngine::DoSourceNodeStart(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::DoSourceNodeStart() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeStart() In"));

    if (iSourceNode == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeStart() Source node not available."));
        return PVMFFailure;
    }

    // Start the source node
    PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeStart);

    PVMFCommandId cmdid = -1;
    int32 leavecode = 0;
    OSCL_TRY(leavecode, cmdid = iSourceNode->Start(iSourceNodeSessionId, (OsclAny*)context));
    OSCL_FIRST_CATCH_ANY(leavecode,
                         FreeEngineContext(context);
                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeStart() Start on iSourceNode did a leave!"));
                         return PVMFFailure);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeStart() Out"));

    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoDatapathStart(PVPlayerEngineDatapath &aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::DoDatapathStart() for %s Tick=%d",
                     aDatapath.iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathStart() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));

    // Start the datapath
    PVPlayerEngineContext* context = AllocateEngineContext(&aDatapath, NULL, aDatapath.iDatapath, aCmdId, aCmdContext, PVP_CMD_DPStart);

    PVMFStatus retval = aDatapath.iDatapath->Start((OsclAny*)context);
    if (retval != PVMFSuccess)
    {
        FreeEngineContext(context);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathStart() Out"));
    return retval;
}


PVMFStatus PVPlayerEngine::DoSinkNodeSkipMediaData(PVCommandId aCmdId, bool aSFR, int32 aCmdType, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::DoSinkNodeSkipMediaData() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeSkipMediaData() In"));

    // Tell the sink nodes to skip the unneeded media data
    iNumPendingNodeCmd = 0;
    int32 leavecode = 0;

    // Call SkipMediaData() for each active datapath with sink nodes that have the sync control IF
    for (uint32 i = 0; i < iDatapathList.size(); ++i)
    {
        if (iDatapathList[i].iDatapath &&
                iDatapathList[i].iEndOfDataReceived == false &&
                iDatapathList[i].iSinkNodeSyncCtrlIF)
        {
            PVPlayerEngineContext* context = AllocateEngineContext(&(iDatapathList[i]), iDatapathList[i].iSinkNode, NULL, aCmdId, aCmdContext, aCmdType);

            leavecode = IssueSinkSkipMediaData(&(iDatapathList[i]), aSFR, (OsclAny*) context);
            if (leavecode == 0)
            {
                ++iNumPendingNodeCmd;
                ++iNumPendingSkipCompleteEvent;
                ++iNumPVMFInfoStartOfDataPending;
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                                (0, "PVPlayerEngine::DoSinkNodeSkipMediaData() iNumPVMFInfoStartOfDataPending=%d", iNumPVMFInfoStartOfDataPending));
            }
            else
            {
                FreeEngineContext(context);
            }
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeSkipMediaData() Out"));
    if (iNumPendingNodeCmd > 0)
    {
        return PVMFSuccess;
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeSkipMediaData() Skip on sink nodes failed"));
        return PVMFFailure;
    }
}


PVMFStatus PVPlayerEngine::DoStart(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE,
                    (0, "PVPlayerEngine::DoStart() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoStart() In, State=%d", iState));

    if (iState == PVP_ENGINE_STATE_AUTO_PAUSED)
    {
        // Engine in AUTO-PAUSED state since it recieved an Underflow event
        // during Prepare. Set the engine state to STARTED and return success
        // Wait for DataReady event for the playback to start.
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                        (0, "PVPlayerEngine::DoStart() Engine in auto-paused state, set it to started"));
        SetEngineState(PVP_ENGINE_STATE_STARTED);
        iStartIssuedOnEngine = true;
    }


    if (GetPVPlayerState() == PVP_STATE_STARTED)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoStart() Engine already in Started State"));
        EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
        return PVMFSuccess;
    }

    if (iPlaybackPausedDueToEndOfClip)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoStart() Playback already paused due to End of clip"));
        EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
        return PVMFSuccess;
    }
    if (GetPVPlayerState() != PVP_STATE_PREPARED)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoStart() Wrong engine state"));
        return PVMFErrInvalidState;
    }

    if (iNumPVMFInfoStartOfDataPending == 0)
    {
        // start the clock only if Skip is complete and InfoStartOfData has been received
        // Enable the end time check if specified
        UpdateCurrentEndPosition(iCurrentEndPosition);
        StartPlaybackClock();
    }
    else
    {
        // Sink nodes have not reported InfoStartOfData yet.
        // Check if WatchDogTimer has already been set or not,
        // if Timer has not been set or has expired then set it to a default value timer.
        if (!(iWatchDogTimer->IsBusy()))
        {
            // set a dafault timer
            iWatchDogTimerInterval = 0;
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                            (0, "PVPlayerEngine::DoStart() Setting WatchDogTimer to a dafult value of 1 second"));
            iWatchDogTimer->setTimerDuration(iWatchDogTimerInterval); // this will set a timer to a default
            iWatchDogTimer->Start();                                  // value of 1 sec. since iWatchDogTimerInterval is zero.
        }
    }

    SetEngineState(PVP_ENGINE_STATE_STARTED);
    iStartIssuedOnEngine = true;

    EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoStart() Out"));
    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoPause(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE,
                    (0, "PVPlayerEngine::DoPause() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoPause() In"));

    // Check engine state
    switch (GetPVPlayerState())
    {
        case PVP_STATE_PAUSED :
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoPause() Engine already in Paused State"));
            EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
            return PVMFSuccess;

        case PVP_STATE_STARTED :
            break;

        case PVP_STATE_PREPARED :
            if (aCmd.GetCmdType() == PVP_ENGINE_COMMAND_PAUSE_DUE_TO_ENDOFCLIP)
            {
                //It is possible in repositioning to end use-case that
                //engine receives StartofData and EndofData before Prepare
                //completes. So we should not fail Pause, just process it.
                break;
            }

        default:
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPause() Wrong engine state"));
            return PVMFErrInvalidState;
    }

    // Send position update to app.
    SendPositionStatusUpdate();

    // Stop the end time check timer
    iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_ENDTIMECHECK);

    // Stop the watchdog timer if active. We will Start the timer again in resume.
    // this should only be done when engine is waiting for StartofData info event
    // after reposition.
    if (iNumPVMFInfoStartOfDataPending > 0)
    {
        if (iWatchDogTimer->IsBusy())
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                            (0, "PVPlayerEngine::DoPause - Pause after setplayback, Cancelling Watchdog timer, iNumPVMFInfoStartOfDataPending=%d", iNumPVMFInfoStartOfDataPending));
            iWatchDogTimer->Cancel();
        }
        return PVMFPending;
    }

    // Pause the clock and notify sinks if not auto-paused
    uint32 i;
    if (iState != PVP_ENGINE_STATE_AUTO_PAUSED)
    {
        // Pause the playback clock
        iPlaybackClock.Pause();
        // Notify data sinks that clock has paused
        for (i = 0; i < iDatapathList.size(); ++i)
        {
            if (iDatapathList[i].iDatapath && iDatapathList[i].iSinkNodeSyncCtrlIF)
            {
                iDatapathList[i].iSinkNodeSyncCtrlIF->ClockStopped();
            }
        }
    }

    // Issue pause to all active datapaths
    iNumPendingDatapathCmd = 0;

    PVMFStatus retval = DoPauseDatapath(aCmd.GetCmdId(), aCmd.GetContext());

    if (retval == PVMFPending)
    {
        return PVMFPending;
    }

    if (iNumPendingDatapathCmd == 0)
    {
        // If there are no active datapaths, continue on to pause the source node
        retval = DoSourceNodePause(aCmd.GetCmdId(), aCmd.GetContext());
    }

    if (retval != PVMFSuccess)
    {
        return AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PAUSE, retval, NULL);
    }

    // TEMP Until queued playback range is available
    // Reset the flag when doing a pause
    iChangePlaybackPositionWhenResuming = false;
    iChangePlaybackDirectionWhenResuming = false;
    // END TEMP

    SetEngineState(PVP_ENGINE_STATE_PAUSING);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoPause() Out"));
    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoDatapathPause(PVPlayerEngineDatapath& aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext, bool aSinkPaused)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::DoDatapathPause() for %s Tick=%d",
                     aDatapath.iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount()));

    if (aDatapath.iTrackInfo == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDatapathPause() TrackInfo not available, failure"));
        return PVMFFailure;
    }
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathPause() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));

    // Pause the datapath
    PVPlayerEngineContext* context = AllocateEngineContext(&aDatapath, NULL, aDatapath.iDatapath, aCmdId, aCmdContext, PVP_CMD_DPPause);

    PVMFStatus retval = aDatapath.iDatapath->Pause((OsclAny*)context, aSinkPaused);
    if (retval != PVMFSuccess)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDatapathPause() - Datapath pause failed"));
        FreeEngineContext(context);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathPause() Out"));
    return retval;
}


PVMFStatus PVPlayerEngine::DoSourceNodePause(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodePause() In"));

    if (iSourceNode == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodePause() Source node not available"));
        return PVMFFailure;
    }

    // Pause the source node
    PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodePause);

    PVMFCommandId cmdid = -1;
    int32 leavecode = 0;
    OSCL_TRY(leavecode, cmdid = iSourceNode->Pause(iSourceNodeSessionId, (OsclAny*)context));
    OSCL_FIRST_CATCH_ANY(leavecode,
                         FreeEngineContext(context);
                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodePause() Pause on iSourceNode did a leave!"));
                         return PVMFFailure);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodePause() Out"));

    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoResume(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoResume() In"));
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoResume() iNumPendingSkipCompleteEvent: %d", iNumPendingSkipCompleteEvent));

    if (GetPVPlayerState() == PVP_STATE_STARTED)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoResume() Engine already in Started State"));
        EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
        return PVMFSuccess;
    }

    // Check engine state
    if (GetPVPlayerState() != PVP_STATE_PAUSED)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoResume() Wrong engine state"));
        return PVMFErrInvalidState;
    }

    // Disallow resume when paused due to EOS and position/direction
    // hasn't been changed
    if (iPlaybackPausedDueToEndOfClip)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoResume() Currently paused due to EOS so not allowed!"));
        return PVMFErrInvalidState;
    }

    if ((iNumPVMFInfoStartOfDataPending > 0) || (iNumPendingDatapathCmd > 0))
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVPlayerEngine::DoResume() Pending PVMFInfoStartOfData events"));
        return PVMFPending;
    }

    PVMFStatus retval;
    if (iChangePlaybackPositionWhenResuming)
    {
        // Reposition occurred during the paused state so need to change the source position first
        retval = DoSourceNodeQueryDataSourcePosition(aCmd.GetCmdId(), aCmd.GetContext());
        // ignore failure, continue on to Start
        if (retval != PVMFSuccess)
        {
            PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
            PVMFBasicErrorInfoMessage* infomsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoChangePlaybackPositionNotSupported, puuid, NULL));
            SendInformationalEvent(PVMFInfoChangePlaybackPositionNotSupported, OSCL_STATIC_CAST(PVInterface*, infomsg));
            infomsg->removeRef();
            retval = DoSourceNodeStart(aCmd.GetCmdId(), aCmd.GetContext());
        }
    }
    else if (iChangePlaybackDirectionWhenResuming)
    {
        // Direction change occurred during the paused state so need to change the source direction first
        retval = DoSourceNodeSetDataSourceDirection(aCmd.GetCmdId(), aCmd.GetContext());
        // ignore failure, continue on to Start
        if (retval != PVMFSuccess)
        {
            PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
            PVMFBasicErrorInfoMessage* infomsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoChangePlaybackPositionNotSupported, puuid, NULL));
            SendInformationalEvent(PVMFInfoChangePlaybackPositionNotSupported, OSCL_STATIC_CAST(PVInterface*, infomsg));
            infomsg->removeRef();
            retval = DoSourceNodeStart(aCmd.GetCmdId(), aCmd.GetContext());
        }
    }
    else
    {
        retval = DoSourceNodeStart(aCmd.GetCmdId(), aCmd.GetContext());
    }

    if (retval != PVMFSuccess)
    {
        return AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME, retval, NULL);
    }

    SetEngineState(PVP_ENGINE_STATE_RESUMING);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoResume() Out"));
    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::AddToMetadataInterfaceList(PVMFMetadataExtensionInterface* aMetadataIF, PVMFSessionId aSessionId, PVPlayerEngineDatapath* aEngineDatapath, PVMFNodeInterface* aNode)
{
    // Validate the interface ptr
    if (aMetadataIF == NULL)
    {
        return PVMFErrArgument;
    }

    // Add the specified interface ptr and session ID to the list
    PVPlayerEngineMetadataIFInfo mdifinfo;
    mdifinfo.iInterface = aMetadataIF;
    mdifinfo.iSessionId = aSessionId;
    mdifinfo.iEngineDatapath = aEngineDatapath;
    mdifinfo.iNode = aNode;
    int32 leavecode = 0;
    OSCL_TRY(leavecode, iMetadataIFList.push_back(mdifinfo));
    OSCL_FIRST_CATCH_ANY(leavecode, return PVMFErrNoMemory);

    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::RemoveFromMetadataInterfaceList(PVMFMetadataExtensionInterface* aMetadataIF, PVMFSessionId aSessionId)
{
    // Validate the interface ptr
    if (aMetadataIF == NULL)
    {
        return PVMFErrArgument;
    }

    // Go through the list to find the specified entry
    for (uint32 i = 0; i < iMetadataIFList.size(); ++i)
    {
        if (aMetadataIF == iMetadataIFList[i].iInterface &&
                aSessionId == iMetadataIFList[i].iSessionId)
        {
            // Found it. Now erase it from the list
            iMetadataIFList.erase(iMetadataIFList.begin() + i);
            return PVMFSuccess;
        }
    }

    // If here that means the specified entry wasn't found in the list
    return PVMFErrArgument;
}


PVMFStatus PVPlayerEngine::DoStop(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoStop() In"));

    if (GetPVPlayerState() == PVP_STATE_INITIALIZED)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoStop() Engine already in Initialized State"));
        EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
        return PVMFSuccess;
    }

    if (GetPVPlayerState() != PVP_STATE_PREPARED &&
            GetPVPlayerState() != PVP_STATE_STARTED &&
            GetPVPlayerState() != PVP_STATE_PAUSED)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoStop() Wrong engine state"));
        return PVMFErrInvalidState;
    }

    if (iReleaseMetadataValuesPending)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::DoStop() Wrong engine Usage, Stop called without releasing metadata values"));
        return PVMFErrReleaseMetadataValueNotDone;
    }

    // reset the dataReady event boolean
    iDataReadySent = false;

    // reset all repos related variables
    ResetReposVariables(true);

    // Stop the playback position status timer
    StopPlaybackStatusTimer();

    // Stop the playback clock
    iPlaybackClock.Stop();
    uint32 starttime = 0;
    bool overflow = 0;
    iPlaybackClock.SetStartTime32(starttime, PVMF_MEDIA_CLOCK_MSEC, overflow);
    iPlaybackDirection = 1;

    // Reset the begin/end time variables
    iCurrentBeginPosition.iIndeterminate = true;
    iCurrentEndPosition.iIndeterminate = true;
    iQueuedBeginPosition.iIndeterminate = true;
    iQueuedEndPosition.iIndeterminate = true;

    // Reset the paused-due-to-EOS flag
    iPlaybackPausedDueToEndOfClip = false;
    // Reset the paused-due-to-EOT flag
    iPlaybackPausedDueToEndOfTimeReached = false;
    iClipsCompleted = 0;

    //Reset the variable iStartIssuedOnEngine
    iStartIssuedOnEngine = false;

    // Stop the end time check
    if (iEndTimeCheckEnabled)
    {
        iEndTimeCheckEnabled = false;
        iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_ENDTIMECHECK);
    }

    PVMFStatus retval = PVMFErrNotSupported;

    // Start the stopping sequence
    // First stop all the active datapaths
    iNumPendingDatapathCmd = 0;
    for (uint32 i = 0; i < iDatapathList.size(); ++i)
    {
        if (iDatapathList[i].iDatapath)
        {
            PVMFStatus retcode = DoDatapathStop(iDatapathList[i], aCmd.GetCmdId(), aCmd.GetContext());
            if (retcode == PVMFSuccess)
            {
                ++iNumPendingDatapathCmd;
                retval = PVMFSuccess;
            }
            else
            {
                retval = retcode;
                break;
            }
        }
    }

    if (iNumPendingDatapathCmd == 0 && retval == PVMFErrNotSupported)
    {
        // If there are no active datapath, stop the source node
        retval = DoSourceNodeStop(aCmd.GetCmdId(), aCmd.GetContext());
    }

    if (retval != PVMFSuccess)
    {
        return AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_STOP, retval, NULL);
    }

    SetEngineState(PVP_ENGINE_STATE_STOPPING);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoStop() Out"));
    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoDatapathStop(PVPlayerEngineDatapath& aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathStop() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));
    if (aDatapath.iTrackInfo == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDatapathStop() TrackInfo not available, failure"));
        return PVMFFailure;
    }

    // Stop the datapath
    PVPlayerEngineContext* context = AllocateEngineContext(&aDatapath, NULL, aDatapath.iDatapath, aCmdId, aCmdContext, PVP_CMD_DPStop);

    PVMFStatus retval = aDatapath.iDatapath->Stop((OsclAny*)context);
    if (retval != PVMFSuccess)
    {
        FreeEngineContext(context);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathStop() Out"));
    return retval;
}


PVMFStatus PVPlayerEngine::DoSourceNodeStop(PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeStop() In"));

    if (iSourceNode == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeStop() Source node not available."));
        return PVMFFailure;
    }

    // Stop the source node
    PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, -1);

    PVMFCommandId cmdid = -1;
    int32 leavecode = 0;
    OSCL_TRY(leavecode, cmdid = iSourceNode->Stop(iSourceNodeSessionId, (OsclAny*)context));
    OSCL_FIRST_CATCH_ANY(leavecode,
                         FreeEngineContext(context);
                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeStop() Stop on iSourceNode did a leave!"));
                         return PVMFFailure);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeStop() Out"));

    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoDatapathTeardown(PVPlayerEngineDatapath &aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathTeardown() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));

    PVPlayerEngineContext* context = AllocateEngineContext(&aDatapath, NULL, aDatapath.iDatapath, aCmdId, aCmdContext, PVP_CMD_DPTeardown);

    PVMFStatus retval = aDatapath.iDatapath->Teardown((OsclAny*)context);
    if (retval != PVMFSuccess)
    {
        FreeEngineContext(context);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathTeardown() Out"));
    return retval;
}


PVMFStatus PVPlayerEngine::DoDatapathReset(PVPlayerEngineDatapath &aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathReset() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));

    // Reset the datapath
    PVPlayerEngineContext* context = AllocateEngineContext(&aDatapath, NULL, aDatapath.iDatapath, aCmdId, aCmdContext, PVP_CMD_DPReset);

    PVMFStatus retval = aDatapath.iDatapath->Reset((OsclAny*)context);
    if (retval != PVMFSuccess)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDatapathReset() Reset failed. Asserting"));
        FreeEngineContext(context);
        OSCL_ASSERT(false);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathReset() Out"));
    return retval;
}


PVMFStatus PVPlayerEngine::DoRemoveDataSink(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoRemoveDataSink() In"));

    // previously removed, e.g. during error handling ?
    if (iDatapathList.empty() && GetPVPlayerState() == PVP_STATE_IDLE)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoRemoveDataSink() All sinks were previously deleted"));
        EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
        return PVMFSuccess;
    }

    if (GetPVPlayerState() != PVP_STATE_INITIALIZED)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoRemoveDataSink() Wrong engine state"));
        return PVMFErrInvalidState;
    }

    PVPlayerDataSink* datasink = (PVPlayerDataSink*)(aCmd.GetParam(0).pOsclAny_value);

    if (datasink == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoRemoveDataSink() Passed in parameter invalid"));
        return PVMFErrArgument;
    }

    // Find the track that the passed-in sink belongs to
    PVPlayerEngineDatapath* pvpedp = NULL;
    int32 dpindex = -1;
    for (uint32 i = 0; i < iDatapathList.size(); ++i)
    {
        if (iDatapathList[i].iDataSink == datasink)
        {
            pvpedp = &(iDatapathList[i]);
            dpindex = i;
            break;
        }
    }

    if (pvpedp == NULL || dpindex == -1)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoRemoveDataSink() Passed in data sink does not match with ones in engine"));
        return PVMFFailure;
    }
    else
    {
        // Cleanup and remove the datapath associated with the data sink from the list
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoRemoveDataSink() Removing datapath"));
        DoEngineDatapathCleanup(*pvpedp);

        iDatapathList.erase(iDatapathList.begin() + dpindex);
    }

    EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoRemoveDataSink() Out"));
    return PVMFSuccess;
}

void PVPlayerEngine::DoRemoveAllSinks()
{
    // Clean up the datapaths
    for (uint32 i = 0; i < iDatapathList.size(); ++i)
    {
        DoEngineDatapathCleanup(iDatapathList[i]);
    }
    iDatapathList.clear();
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoRemoveAllSinks() all datapaths removed"));
}


PVMFStatus PVPlayerEngine::DoReset(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoReset() In"));

    // set engine state to Resetting
    SetEngineState(PVP_ENGINE_STATE_RESETTING);
    iStartIssuedOnEngine = false;
    iRollOverState = RollOverStateIdle; //reset roll over state to Idle, as engine is resetting itself

    // reset all repos related variables
    ResetReposVariables(true);

    // Stop the playback position status timer
    StopPlaybackStatusTimer();

    // Stop the playback clock
    iPlaybackClock.Stop();
    uint32 starttime = 0;
    bool overflow = 0;
    iPlaybackClock.SetStartTime32(starttime, PVMF_MEDIA_CLOCK_MSEC, overflow);
    iPlaybackDirection = 1;

    // Reset the begin/end time variables
    iCurrentBeginPosition.iIndeterminate = true;
    iCurrentEndPosition.iIndeterminate = true;
    iQueuedBeginPosition.iIndeterminate = true;
    iQueuedEndPosition.iIndeterminate = true;

    // Reset the paused-due-to-EOS flag
    iPlaybackPausedDueToEndOfClip = false;
    // Reset the paused-due-to-EOT flag
    iPlaybackPausedDueToEndOfTimeReached = false;
    iClipsCompleted = 0;

    // Reset the Presentation Info list
    iSourcePresInfoList.Reset();

    // Clear the Track selection List
    iTrackSelectionList.clear();

    //Clear the Metadata value release List
    iMetadataValueReleaseList.clear();

    // Stop the end time check
    if (iEndTimeCheckEnabled)
    {
        iEndTimeCheckEnabled = false;
        iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_ENDTIMECHECK);
    }

    int32 leavecode = 0;
    PVMFStatus status = PVMFSuccess;

    if (iSourceNode)
    {
        if (iSourceNode->GetState() != EPVMFNodeCreated)
        {
            DereferenceLicenseInterface();

            PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, -1, NULL, -1);

            PVMFCommandId cmdid = -1;
            leavecode = 0;
            OSCL_TRY(leavecode, cmdid = iSourceNode->Reset(iSourceNodeSessionId, (OsclAny*)context));
            OSCL_FIRST_CATCH_ANY(leavecode,

                                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoReset() Reset on iSourceNode did a leave!"));
                                 FreeEngineContext(context);
                                 OSCL_ASSERT(false);
                                 return PVMFFailure);
        }
        else
        {
            // It is assumed that if SourceNode is in created state then datapaths if present,
            // has to be in IDLE State
            if (!iDatapathList.empty())
            {
                for (uint32 i = 0; i < iDatapathList.size(); ++i)
                {
                    if (!iDatapathList[i].iDatapath)
                    {
                        if (iDatapathList[i].iDatapath->iState != PVPDP_IDLE)
                        {
                            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                            (0, "PVPlayerEngine::DoReset() Source Node already in created state, Datapath not in idle state, asserting"));
                            OSCL_ASSERT(false);
                        }
                    }
                }
                DoRemoveAllSinks();
            }
            iRemoveDataSource = true;
            SetEngineState(PVP_ENGINE_STATE_IDLE);
            EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
        }
    }
    else
    {
        iRemoveDataSource = true;
        SetEngineState(PVP_ENGINE_STATE_IDLE);
        EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoReset() Out"));
    return status;
}

PVMFStatus PVPlayerEngine::RemoveDataSourceSync(PVPlayerDataSource &aSrc)
{
    OSCL_UNUSED_ARG(aSrc);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::RemoveDataSourceSync() In"));

    // Destroy the source node if present
    DoSourceNodeCleanup();

    // Remove Stored KVP Values
    DeleteKVPValues();

    // Remove all metadata IF from the list
    iMetadataIFList.clear();

    iDataSource = NULL;

    iSourceDurationVector.clear();

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::RemoveDataSourceSync() Out"));
    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoRemoveDataSource(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoRemoveDataSource() In"));

    if (GetPVPlayerState() != PVP_STATE_IDLE)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoRemoveDataSource() called when engine is not in the IDLE state"));
        return PVMFErrInvalidState;
    }

    if (iDataSource == NULL) // previously removed, e.g. during errorhandling
    {
        EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
        return PVMFSuccess;
    }

    PVPlayerDataSource* src = (PVPlayerDataSource*)(aCmd.GetParam(0).pOsclAny_value);

    if (iDataSource != src || src == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoRemoveDataSource() Passed in parameter invalid"));
        return PVMFErrArgument;
    }

    PVMFStatus result = RemoveDataSourceSync(*src);

    if (result == PVMFSuccess)
        EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoRemoveDataSource() Out"));
    return result;
}


PVMFStatus PVPlayerEngine::DoSourceUnderflowAutoPause(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceUnderflowAutoPause() In"));

    /*
     * Underflow can happen in the following States
     * Prepared - Use-cases where-in Source Node reports DataReady and goes into
     * underflow immediately when it starts to retrieve data.
     * Started - This will be the most generic use-case where in the source node
     * is retreiving data and because of low bandwidth conditions runs out of data.
     * In such case Source Node will send an Underflow event to Engine.
     * Paused - A rare use-case but can happen. Use-case where Source Node is about
     * to run out of data and just before Source Node sends an Underflow event to
     * engine, user presses Pause on Engine. Engine gets Pause from user and Underflow
     * from Source Node back-to-back.
     */
    bool pauseSinkNodes = false;

    switch (iState)
    {
        case PVP_ENGINE_STATE_PREPARED:
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                            (0, "PVPlayerEngine::DoSourceUnderflowAutoPause() in Prepared state"));
            SetEngineState(PVP_ENGINE_STATE_AUTO_PAUSED);
            break;

        case PVP_ENGINE_STATE_STARTED:
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                            (0, "PVPlayerEngine::DoSourceUnderflowAutoPause() in Started state"));
            pauseSinkNodes = true;
            break;

        case PVP_ENGINE_STATE_PAUSED:
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                            (0, "PVPlayerEngine::DoSourceUnderflowAutoPause() in Paused state"));
            break;

        default:
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::DoSourceUnderflowAutoPause() Invalid state so cancel auto-pause request!"));
            return PVMFErrCancelled;
    }

    // Stop the watchdog timer if active. We will Start the timer again in auto-resume.
    // this should only be done when engine is waiting for StartofData info event
    // after reposition.
    if (iNumPVMFInfoStartOfDataPending > 0)
    {
        if (iWatchDogTimer->IsBusy())
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                            (0, "PVPlayerEngine::DoSourceUnderflowAutoPause - Pause after setplayback, Cancelling Watchdog timer, iNumPVMFInfoStartOfDataPending=%d", iNumPVMFInfoStartOfDataPending));
            iWatchDogTimer->Cancel();
        }
    }

    if (!pauseSinkNodes)
    {
        // Sink nodes already in Paused state or have no data to process, so
        // no need to call Pause on the sink nodes.
        return PVMFErrNotSupported;
    }

    // Pause the playback clock
    iPlaybackClock.Pause();

    uint32 i;
    // Notify data sinks that clock has paused
    for (i = 0; i < iDatapathList.size(); ++i)
    {
        if (iDatapathList[i].iDatapath && iDatapathList[i].iSinkNodeSyncCtrlIF)
        {
            iDatapathList[i].iSinkNodeSyncCtrlIF->ClockStopped();
        }
    }

    PVMFStatus retval = PVMFErrNotSupported;

    // Pause all active sink nodes
    iNumPendingDatapathCmd = 0;
    for (i = 0; i < iDatapathList.size(); ++i)
    {
        if (iDatapathList[i].iDatapath)
        {
            retval = DoSinkNodePause(iDatapathList[i], aCmd.GetCmdId(), aCmd.GetContext());
            if (retval == PVMFSuccess)
            {
                ++iNumPendingDatapathCmd;
            }
            else
            {
                break;
            }
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceUnderflowAutoPause() Out"));
    if (iNumPendingDatapathCmd == 0)
    {
        return PVMFErrNotSupported;
    }
    else
    {
        SetEngineState(PVP_ENGINE_STATE_AUTO_PAUSING);
        return retval;
    }
}


PVMFStatus PVPlayerEngine::DoSourceDataReadyAutoResume(PVPlayerEngineCommand& aCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceDataReadyAutoResume() In"));

    // Don't need to worry about transitional states(...ING).
    // Auto-pause/resume cmds are just regular engine cmds and won't be interrupted by normal ones

    // Check if Datapaths (Sink Node) are already in Started state.
    bool datapathSinkNodeStarted = false;
    for (uint32 j = 0; j < iDatapathList.size(); j++)
    {
        if (iDatapathList[j].iSinkNode)
        {
            if (iDatapathList[j].iSinkNode->GetState() != EPVMFNodeStarted)
            {
                // One of the nodes is not in Started state break from the loop
                // keeping the boolean datapathSinkNodeStaretd as false.
                datapathSinkNodeStarted = false;
                break;
            }
            // this will be true only when all Sink Nodes are in started state.
            datapathSinkNodeStarted = true;
        }
    }

    // Next check to see if it is any one of the use-cases:
    // Prepare->Underflow->Start->DataReady or
    // Prepare->Underflow->DataReady->Start or
    // Underflow->Pause->Resume->DataReady or
    // Underflow->Pause->SetPlaybackRange->Resume->DataReady
    // These are cases where Sink Nodes are already in Started state and
    // engine might be still waiting for PVMFInfoStartOfData.
    // Here if all PVMFInfoStartofData have not been received yet,
    // then iNumPVMFInfoStartOfDataPending would be non-zero,
    // In few of these usecase, engine starts playback clock in Resume, source nodes are sposed to pause the
    // clock, since they are the ones in underflow. Once source nodes report dataready, engine would
    // already be in STARTED state. So if the clock is still paused, then start it here.
    // Here just send NotSupported so engine can send DataReady Event to the app.
    // and set the watchdog timer which was cancelled when underflow was recieved.
    if (datapathSinkNodeStarted)
    {
        if (iState == PVP_ENGINE_STATE_PREPARED)
        {
            // DataReady recieved during Prepare, Engine just needs to send
            // DataReady event.
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                            (0, "PVPlayerEngine::DoSourceDataReadyAutoResume: DataReady rcvd, Engine in Prepared state"));
        }
        else if (iState == PVP_ENGINE_STATE_STARTED)
        {
            // Usecases for this scenario:
            // Underflow->Pause->Resume->DataReady
            // Underflow->Pause->SetPlaybackRange->Resume->DataReady
            // Prepare->Underflow->Start->DataReady
            // do nothing here
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                            (0, "PVPlayerEngine::DoSourceDataReadyAutoResume: DataReady rcvd, Engine already in Started state"));
        }
        else if (iState == PVP_ENGINE_STATE_AUTO_PAUSED)
        {
            // Usecase for this scenario:
            // Prepare->Underflow->DataReady->Started
            // Change state back to PREPARED, since Underflow and DataReady cancels each other out.
            // Wait for Start command from App to Start the clock and change state to STARTED.
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                            (0, "PVPlayerEngine::DoSourceDataReadyAutoResume: DataReady rcvd, Prepare->Underflow->DataReady->Started, datapaths already started"));
            SetEngineState(PVP_ENGINE_STATE_PREPARED);
        }
        else
        {
            // This should never happen
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::DoSourceDataReadyAutoResume() Invalid state %d, Sinks in Started state", iState));
            OSCL_ASSERT(false);
        }

        if (iNumPVMFInfoStartOfDataPending > 0)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                            (0, "PVPlayerEngine::DoSourceDataReadyAutoResume: Clock in Stopped state, waiting for StartofData"));

            if (iWatchDogTimerInterval > 0)
            {
                if (iWatchDogTimer->IsBusy())
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                                    (0, "PVPlayerEngine::DoSourceDataReadyAutoResume - Pause after setplayback, Cancelling Watchdog timer, iNumPVMFInfoStartOfDataPending=%d", iNumPVMFInfoStartOfDataPending));
                    iWatchDogTimer->Cancel();
                }

                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                                (0, "PVPlayerEngine::DoSourceDataReadyAutoResume Setting WatchDogTimer for %d ms, iNumPVMFInfoStartOfDataPending=%d",
                                 iWatchDogTimerInterval, iNumPVMFInfoStartOfDataPending));
                iWatchDogTimer->setTimerDuration(iWatchDogTimerInterval);
                iWatchDogTimer->Start();
            }
        }
        else if ((iNumPVMFInfoStartOfDataPending == 0) && (iState == PVP_ENGINE_STATE_STARTED))
        {
            StartPlaybackClock();

            // Notify data sinks that clock has started
            for (uint32 i = 0; i < iDatapathList.size(); ++i)
            {
                if (iDatapathList[i].iDatapath && iDatapathList[i].iSinkNodeSyncCtrlIF)
                {
                    iDatapathList[i].iSinkNodeSyncCtrlIF->ClockStarted();
                }
            }
        }
        //return PVMFErrNotSupported so the the DataReady can be sent, depending on iDataReadySent flag.
        return PVMFErrNotSupported;
    }

    // Next check to see if it is Underflow->Pause->DataReady->Resume usecase.
    // Then we CANNOT start clock in here, because clock is paused by app.
    // After Pause done, the engine is in PAUSED state. By allowing auto-resume only when
    // auto-paused we deal with this usecase ok.
    if (iState != PVP_ENGINE_STATE_AUTO_PAUSED)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceDataReadyAutoResume() Invalid state %d", iState));
        //return PVMFErrNotSupported so the the DataReady can be sent, depending on iDataReadySent flag.
        return PVMFErrNotSupported;
    }

    PVMFStatus retval = PVMFErrNotSupported;

    // Resume all active sink nodes
    iNumPendingDatapathCmd = 0;
    for (uint32 i = 0; i < iDatapathList.size(); ++i)
    {
        if (iDatapathList[i].iDatapath)
        {
            retval = DoSinkNodeResume(iDatapathList[i], aCmd.GetCmdId(), aCmd.GetContext());
            if (retval == PVMFSuccess)
            {
                ++iNumPendingDatapathCmd;
            }
            else
            {
                break;
            }
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceDataReadyAutoResume() Out"));
    if (iNumPendingDatapathCmd == 0)
    {
        return PVMFErrNotSupported;
    }
    else
    {
        SetEngineState(PVP_ENGINE_STATE_AUTO_RESUMING);
        return retval;
    }
}


PVMFStatus PVPlayerEngine::DoSinkNodePause(PVPlayerEngineDatapath &aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodePause() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));

    if (!(aDatapath.iTrackInfo) || !(aDatapath.iSinkNode))
    {
        return PVMFErrNotSupported;
    }

    // Pause the sink node
    PVPlayerEngineContext* context = AllocateEngineContext(&aDatapath, aDatapath.iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeAutoPause);

    PVMFCommandId cmdid = -1;
    int32 leavecode = 0;
    OSCL_TRY(leavecode, cmdid = aDatapath.iSinkNode->Pause(aDatapath.iSinkNodeSessionId, (OsclAny*)context));
    OSCL_FIRST_CATCH_ANY(leavecode,
                         FreeEngineContext(context);
                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodePause() Pause on sink node did a leave!"));
                         return PVMFFailure);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodePause() Out"));

    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoSinkNodeResume(PVPlayerEngineDatapath &aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeResume() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));

    if (!(aDatapath.iTrackInfo) || !(aDatapath.iSinkNode))
    {
        return PVMFErrNotSupported;
    }

    // Start the sink node to resume
    PVPlayerEngineContext* context = AllocateEngineContext(&aDatapath, aDatapath.iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeAutoResume);

    PVMFCommandId cmdid = -1;
    int32 leavecode = 0;
    OSCL_TRY(leavecode, cmdid = aDatapath.iSinkNode->Start(aDatapath.iSinkNodeSessionId, (OsclAny*)context));
    OSCL_FIRST_CATCH_ANY(leavecode,
                         FreeEngineContext(context);
                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeResume() Start on sink node did a leave!"));
                         return PVMFFailure);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeResume() Out"));

    return PVMFSuccess;
}

void PVPlayerEngine::DoEngineDatapathTeardown(PVPlayerEngineDatapath& aDatapath)
{
    if (aDatapath.iTrackInfo)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoEngineDatapathTeardown() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoEngineDatapathTeardown() In"));
    }

    if (aDatapath.iDatapath)
    {
        // Shutdown and reset the datapath
        aDatapath.iDatapath->DisconnectNodeSession();
        aDatapath.iDatapath->SetSinkNode(NULL);
        aDatapath.iDatapath->SetDecNode(NULL);
        aDatapath.iDatapath->SetSourceNode(NULL);
    }

    if (aDatapath.iSinkNode)
    {
        PVMFStatus status = PVMFFailure;
        status = aDatapath.iSinkNode->Disconnect(aDatapath.iSinkNodeSessionId);
        if (status == PVMFFailure)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoEngineDatapathTeardown() Disconnect on Sink Node Failed"));
            OSCL_ASSERT(false);
        }
        status = aDatapath.iSinkNode->ThreadLogoff();
        if (status == PVMFFailure)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoEngineDatapathTeardown() Threadlogoff on SinkNode Failed"));
            OSCL_ASSERT(false);
        }

        // Remove sync ctrl IF if available
        if (aDatapath.iSinkNodeSyncCtrlIF)
        {
            aDatapath.iSinkNodeSyncCtrlIF->SetClock(NULL);
            aDatapath.iSinkNodeSyncCtrlIF->removeRef();
            aDatapath.iSinkNodeSyncCtrlIF = NULL;
        }

        // Remove metadata IF if available
        if (aDatapath.iSinkNodeMetadataExtIF)
        {
            RemoveFromMetadataInterfaceList(aDatapath.iSinkNodeMetadataExtIF, aDatapath.iSinkNodeSessionId);
            aDatapath.iSinkNodeMetadataExtIF->removeRef();
            aDatapath.iSinkNodeMetadataExtIF = NULL;
        }

        // Remove cap-config IF if available
        if (aDatapath.iSinkNodeCapConfigIF)
        {
            aDatapath.iSinkNodeCapConfigIF->removeRef();
            aDatapath.iSinkNodeCapConfigIF = NULL;
        }

        aDatapath.iSinkNode = NULL;
    }

    if (aDatapath.iDecNode)
    {
        // Remove metadata IF if available
        if (aDatapath.iDecNodeMetadataExtIF)
        {
            RemoveFromMetadataInterfaceList(aDatapath.iDecNodeMetadataExtIF, aDatapath.iDecNodeSessionId);
            aDatapath.iDecNodeMetadataExtIF->removeRef();
            aDatapath.iDecNodeMetadataExtIF = NULL;
        }

        // Remove cap-config IF if available
        if (aDatapath.iDecNodeCapConfigIF)
        {
            aDatapath.iDecNodeCapConfigIF = NULL;
        }

        PVMFStatus status = PVMFFailure;
        status = aDatapath.iDecNode->Disconnect(aDatapath.iDecNodeSessionId);
        if (status == PVMFFailure)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoEngineDatapathTeardown() Disconnect on dec node Failed"));
            OSCL_ASSERT(false);
        }
        status = aDatapath.iDecNode->ThreadLogoff();
        if (status == PVMFFailure)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoEngineDatapathTeardown() ThreadLogoff on dec node Failed"));
            OSCL_ASSERT(false);
        }

        // search for matching uuid entry in list of instantiated nodes
        PVPlayerEngineUuidNodeMapping* iter = iNodeUuids.begin();
        for (; iter != iNodeUuids.end(); ++iter)
            if (iter->iNode == aDatapath.iDecNode)
                break;

        if (iter != iNodeUuids.end())
        {
            bool release_status = false;

            release_status = iPlayerNodeRegistry.ReleaseNode(iter->iUuid, aDatapath.iDecNode);

            if (release_status == false)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoEngineDatapathTeardown() Factory returned false while releasing the decnode"));
                return;
            }

            iNodeUuids.erase(iter);
            aDatapath.iDecNode = NULL;
        }
        else
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoEngineDatapathTeardown() decnode not found"));
            return;
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoEngineDatapathTeardown() Out"));
}


void PVPlayerEngine::DoEngineDatapathCleanup(PVPlayerEngineDatapath& aDatapath)
{
    if (aDatapath.iTrackInfo)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoEngineDatapathCleanup() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoEngineDatapathCleanup() In"));
    }

    DoEngineDatapathTeardown(aDatapath);

    // Destroy the datapath utility object instance
    if (aDatapath.iDatapath)
    {
        OSCL_DELETE(aDatapath.iDatapath);
        aDatapath.iDatapath = NULL;
    }

    // Destroy the track info
    if (aDatapath.iTrackInfo)
    {
        OSCL_DELETE(aDatapath.iTrackInfo);
        aDatapath.iTrackInfo = NULL;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoEngineDatapathCleanup() Out"));
}


void PVPlayerEngine::DoSourceNodeCleanup(void)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeCleanup() In"));

    if (iSourceNode)
    {
        // Remove reference to the parser node init interface if available
        if (iSourceNodeInitIF)
        {
            iSourceNodeInitIF->removeRef();
            iSourceNodeInitIF = NULL;
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - iSourceNodeInitIF Released"));
        }

        // Remove reference to the parser node track sel interface if available
        if (iSourceNodeTrackSelIF)
        {
            iPlayableList.Reset();
            iPreferenceList.Reset();
            iSourceNodeTrackSelIF->removeRef();
            iSourceNodeTrackSelIF = NULL;
            iTrackSelectionHelper = NULL;
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - iSourceNodeTrackSelIF Released"));
        }

        // Remove reference to the parser node track level info interface if available
        if (iSourceNodeTrackLevelInfoIF)
        {
            iSourceNodeTrackLevelInfoIF->removeRef();
            iSourceNodeTrackLevelInfoIF = NULL;
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - iSourceNodeTrackLevelInfoIF Released"));
        }

        // Remove reference to the parser node position control interface if available
        if (iSourceNodePBCtrlIF)
        {
            iSourceNodePBCtrlIF->removeRef();
            iSourceNodePBCtrlIF = NULL;
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - iSourceNodePBCtrlIF Released"));
        }

        // Remove reference to the parser node direction control interface if available
        if (iSourceNodeDirCtrlIF)
        {
            iSourceNodeDirCtrlIF->removeRef();
            iSourceNodeDirCtrlIF = NULL;
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - iSourceNodeDirCtrlIF Released"));
        }

        // Remove reference to the parser node metadata interface if available
        if (iSourceNodeMetadataExtIF)
        {
            RemoveFromMetadataInterfaceList(iSourceNodeMetadataExtIF, iSourceNodeSessionId);
            iSourceNodeMetadataExtIF->removeRef();
            iSourceNodeMetadataExtIF = NULL;
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - iSourceNodeMetadataExtIF Released"));
        }

        // Reset the duration value retrieved from source
        iSourceDurationAvailable = false;
        iSourceDurationInMS = 0;

        // Remove reference to the parser node cap-config interface if available
        if (iSourceNodeCapConfigIF)
        {
            iSourceNodeCapConfigIF->removeRef();
            iSourceNodeCapConfigIF = NULL;
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - iSourceNodeCapConfigIF Released"));
        }

        if (iSourceNodeRegInitIF)
        {
            iSourceNodeRegInitIF->removeRef();
            iSourceNodeRegInitIF = NULL;
        }


        // Reset the Presentation Info list
        iSourcePresInfoList.Reset();

        PVMFStatus status = PVMFFailure;
        status = iSourceNode->Disconnect(iSourceNodeSessionId);
        if (status == PVMFFailure)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeCleanup() Disconnect Failed"));
            OSCL_ASSERT(false);
        }
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - DisConnect Done"));

        status = iSourceNode->ThreadLogoff();
        if (status == PVMFFailure)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeCleanup() ThreadLogoff Failed"));
            OSCL_ASSERT(false);
        }
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - ThreadLogoff Done"));

        // search for matching uuid entry in list of instantiated nodes
        PVPlayerEngineUuidNodeMapping* iter = iNodeUuids.begin();
        for (; iter != iNodeUuids.end(); ++iter)
            if (iter->iNode == iSourceNode)
                break;

        if (iter != iNodeUuids.end())
        {
            bool release_status = false;

            release_status = iPlayerNodeRegistry.ReleaseNode(iter->iUuid, iSourceNode);

            if (release_status == false)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeCleanup() Factory returned false while releasing the sourcenode"));
                return;
            }


            iNodeUuids.erase(iter);
            iSourceNode = NULL;
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - iSourceNode Delete Done"));
        }
        else
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - iSourceNode not found"));
            return;
        }
    }

    // Cleanup the control varibles related to rate & direction changes.
    iPlaybackDirection_New = iPlaybackDirection;
    iOutsideTimebase_New = iOutsideTimebase;
    iPlaybackClockRate_New = iPlaybackClockRate;
    iChangeDirectionNPT.iIndeterminate = true;
    // Reset the flag that tracks pause-due-to-EOS
    iPlaybackPausedDueToEndOfClip = false;
    // Reset the paused-due-to-EOT flag
    iPlaybackPausedDueToEndOfTimeReached = false;
    iClipsCompleted = 0;
    iClipsCorrupted = 0;
    iNumClipsQueued = 0;
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeCleanup() Out"));
}


PVMFStatus PVPlayerEngine::DoCapConfigGetParametersSync(PvmiKeyType aIdentifier, PvmiKvp*& aParameters, int& aNumParamElements, PvmiCapabilityContext aContext)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCapConfigGetParametersSync() In"));
    OSCL_UNUSED_ARG(aContext);

    // Initialize the output parameters
    aNumParamElements = 0;
    aParameters = NULL;

    // Count the number of components and parameters in the key
    int compcount = pv_mime_string_compcnt(aIdentifier);
    // Retrieve the first component from the key string
    char* compstr = NULL;
    pv_mime_string_extract_type(0, aIdentifier, compstr);

    if ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf")) < 0) || compcount < 2)
    {
        // First component should be "x-pvmf" and there must
        // be at least two components to go past x-pvmf
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigGetParametersSync() Invalid key string"));
        return PVMFErrArgument;
    }

    // Retrieve the second component from the key string
    pv_mime_string_extract_type(1, aIdentifier, compstr);

    // First check if it is key string for engine ("player")
    if (pv_mime_strcmp(compstr, _STRLIT_CHAR("player")) >= 0)
    {
        // Key is for player
        if (compcount == 2)
        {
            // Since key is "x-pvmf/player" return all
            // nodes available at this level. Ignore attribute
            // since capability is only allowed

            // Allocate memory for the KVP list
            aParameters = (PvmiKvp*)oscl_malloc(PVPLAYERCONFIG_BASE_NUMKEYS * sizeof(PvmiKvp));
            if (aParameters == NULL)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigGetParametersSync() Memory allocation for KVP failed"));
                return PVMFErrNoMemory;
            }
            oscl_memset(aParameters, 0, PVPLAYERCONFIG_BASE_NUMKEYS*sizeof(PvmiKvp));
            // Allocate memory for the key strings in each KVP
            PvmiKeyType memblock = (PvmiKeyType)oscl_malloc(PVPLAYERCONFIG_BASE_NUMKEYS * PVPLAYERCONFIG_KEYSTRING_SIZE * sizeof(char));
            if (memblock == NULL)
            {
                oscl_free(aParameters);
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigGetParametersSync() Memory allocation for key string failed"));
                return PVMFErrNoMemory;
            }
            oscl_strset(memblock, 0, PVPLAYERCONFIG_BASE_NUMKEYS*PVPLAYERCONFIG_KEYSTRING_SIZE*sizeof(char));
            // Assign the key string buffer to each KVP
            int32 j;
            for (j = 0; j < PVPLAYERCONFIG_BASE_NUMKEYS; ++j)
            {
                aParameters[j].key = memblock + (j * PVPLAYERCONFIG_KEYSTRING_SIZE);
            }
            // Copy the requested info
            for (j = 0; j < PVPLAYERCONFIG_BASE_NUMKEYS; ++j)
            {
                oscl_strncat(aParameters[j].key, _STRLIT_CHAR("x-pvmf/player/"), 14);
                oscl_strncat(aParameters[j].key, PVPlayerConfigBaseKeys[j].iString, oscl_strlen(PVPlayerConfigBaseKeys[j].iString));
                oscl_strncat(aParameters[j].key, _STRLIT_CHAR(";type="), 6);
                switch (PVPlayerConfigBaseKeys[j].iType)
                {
                    case PVMI_KVPTYPE_AGGREGATE:
                        oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPTYPE_AGGREGATE_STRING), oscl_strlen(PVMI_KVPTYPE_AGGREGATE_STRING));
                        break;

                    case PVMI_KVPTYPE_POINTER:
                        oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPTYPE_POINTER_STRING), oscl_strlen(PVMI_KVPTYPE_POINTER_STRING));
                        break;

                    case PVMI_KVPTYPE_VALUE:
                    default:
                        oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPTYPE_VALUE_STRING), oscl_strlen(PVMI_KVPTYPE_VALUE_STRING));
                        break;
                }
                oscl_strncat(aParameters[j].key, _STRLIT_CHAR(";valtype="), 9);
                switch (PVPlayerConfigBaseKeys[j].iValueType)
                {
                    case PVMI_KVPVALTYPE_RANGE_INT32:
                        oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_RANGE_INT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_RANGE_INT32_STRING));
                        break;

                    case PVMI_KVPVALTYPE_KSV:
                        oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_KSV_STRING), oscl_strlen(PVMI_KVPVALTYPE_KSV_STRING));
                        break;

                    case PVMI_KVPVALTYPE_CHARPTR:
                        oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_CHARPTR_STRING), oscl_strlen(PVMI_KVPVALTYPE_CHARPTR_STRING));
                        break;

                    case PVMI_KVPVALTYPE_BOOL:
                        oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_BOOL_STRING), oscl_strlen(PVMI_KVPVALTYPE_BOOL_STRING));
                        break;

                    case PVMI_KVPVALTYPE_UINT32:
                    default:
                        oscl_strncat(aParameters[j].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING));
                        break;
                }
                aParameters[j].key[PVPLAYERCONFIG_KEYSTRING_SIZE-1] = 0;
            }

            aNumParamElements = PVPLAYERCONFIG_BASE_NUMKEYS;
        }
        else
        {
            // Retrieve the third component from the key string
            pv_mime_string_extract_type(2, aIdentifier, compstr);

            for (int32 engcomp3ind = 0; engcomp3ind < PVPLAYERCONFIG_BASE_NUMKEYS; ++engcomp3ind)
            {
                // Go through each engine component string at 3rd level
                if (pv_mime_strcmp(compstr, (char*)(PVPlayerConfigBaseKeys[engcomp3ind].iString)) >= 0)
                {
                    if (compcount == 3)
                    {
                        // Determine what is requested
                        PvmiKvpAttr reqattr = GetAttrTypeFromKeyString(aIdentifier);
                        if (reqattr == PVMI_KVPATTR_UNKNOWN)
                        {
                            reqattr = PVMI_KVPATTR_CUR;
                        }

                        // Return the requested info
                        PVMFStatus retval = DoGetPlayerParameter(aParameters, aNumParamElements, engcomp3ind, reqattr);
                        if (retval != PVMFSuccess)
                        {
                            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigGetParametersSync() Retrieving player parameter failed"));
                            return retval;
                        }
                    }
                    else
                    {
                        // Right now engine doesn't support more than 3 components
                        // for this sub-key string so error out
                        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigGetParametersSync() Unsupported key"));
                        return PVMFErrArgument;
                    }

                    // Breakout of the for(engcomp3ind) loop
                    break;
                }
            }
        }
    }
    else
    {
        if (iSourceNodeCapConfigIF != NULL)
        {
            iSourceNodeCapConfigIF->getParametersSync(NULL, aIdentifier, aParameters, aNumParamElements, aContext);
        }

        if (aNumParamElements == 0) // Source node did not find the parameter
        {
            // Go through each datapath's cap-config IF in the datapath list and check for the string.
            for (uint32 i = 0; i < iDatapathList.size(); i++)
            {
                if (iDatapathList[i].iDecNodeCapConfigIF != NULL)
                {
                    iDatapathList[i].iDecNodeCapConfigIF->getParametersSync(NULL, aIdentifier, aParameters, aNumParamElements, aContext);
                    if (aNumParamElements != 0)
                    {
                        // Parameter matched. Break the loop.
                        break;
                    }
                }

                if (iDatapathList[i].iSinkNodeCapConfigIF != NULL)
                {
                    iDatapathList[i].iSinkNodeCapConfigIF->getParametersSync(NULL, aIdentifier, aParameters, aNumParamElements, aContext);
                    if (aNumParamElements != 0)
                    {
                        // Parameter matched. Break the loop.
                        break;
                    }
                }
            }
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCapConfigGetParametersSync() Out"));
    if (aNumParamElements == 0)
    {
        // If no one could get the parameter, return error
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigGetParametersSync() Unsupported key"));
        return PVMFFailure;
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigGetParametersSync() - key supported"));
        return PVMFSuccess;
    }
}


PVMFStatus PVPlayerEngine::DoCapConfigReleaseParameters(PvmiKvp* aParameters, int aNumElements)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCapConfigReleaseParameters() In"));

    if (aParameters == NULL || aNumElements < 1)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigReleaseParameters() KVP list is NULL or number of elements is 0"));
        return PVMFErrArgument;
    }

    // Count the number of components and parameters in the key
    int compcount = pv_mime_string_compcnt(aParameters[0].key);
    // Retrieve the first component from the key string
    char* compstr = NULL;
    pv_mime_string_extract_type(0, aParameters[0].key, compstr);

    if ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf")) < 0) || compcount < 2)
    {
        // First component should be "x-pvmf" and there must
        // be at least two components to go past x-pvmf
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigReleaseParameters() Unsupported key"));
        return PVMFErrArgument;
    }

    // Retrieve the second component from the key string
    pv_mime_string_extract_type(1, aParameters[0].key, compstr);

    // Assume all the parameters come from the same component so the base components are the same
    // First check if it is key string for engine ("player")
    if (pv_mime_strcmp(compstr, _STRLIT_CHAR("player")) >= 0)
    {
        // Go through each KVP and release memory for value if allocated from heap
        for (int32 i = 0; i < aNumElements; ++i)
        {
            // Next check if it is a value type that allocated memory
            PvmiKvpType kvptype = GetTypeFromKeyString(aParameters[i].key);
            if (kvptype == PVMI_KVPTYPE_VALUE || kvptype == PVMI_KVPTYPE_UNKNOWN)
            {
                PvmiKvpValueType keyvaltype = GetValTypeFromKeyString(aParameters[i].key);
                if (keyvaltype == PVMI_KVPVALTYPE_UNKNOWN)
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigReleaseParameters() Valtype not specified in key string"));
                    return PVMFErrArgument;
                }

                if (keyvaltype == PVMI_KVPVALTYPE_CHARPTR && aParameters[i].value.pChar_value != NULL)
                {
                    oscl_free(aParameters[i].value.pChar_value);
                    aParameters[i].value.pChar_value = NULL;
                }
                else if (keyvaltype == PVMI_KVPVALTYPE_KSV && aParameters[i].value.key_specific_value != NULL)
                {
                    oscl_free(aParameters[i].value.key_specific_value);
                    aParameters[i].value.key_specific_value = NULL;
                }
                else if (keyvaltype == PVMI_KVPVALTYPE_RANGE_INT32 && aParameters[i].value.key_specific_value != NULL)
                {
                    range_int32* ri32 = (range_int32*)aParameters[i].value.key_specific_value;
                    aParameters[i].value.key_specific_value = NULL;
                    oscl_free(ri32);
                }
                else if (keyvaltype == PVMI_KVPVALTYPE_RANGE_UINT32 && aParameters[i].value.key_specific_value != NULL)
                {
                    range_uint32* rui32 = (range_uint32*)aParameters[i].value.key_specific_value;
                    aParameters[i].value.key_specific_value = NULL;
                    oscl_free(rui32);
                }
                // @TODO Add more types if engine starts returning more types
            }
        }

        // Player engine allocated its key strings in one chunk so just free the first key string ptr
        oscl_free(aParameters[0].key);

        // Free memory for the parameter list
        oscl_free(aParameters);
        aParameters = NULL;
    }
    else
    {
        PVMFStatus retval = PVMFFailure;
        if (iSourceNodeCapConfigIF != NULL)
        {
            retval = iSourceNodeCapConfigIF->releaseParameters(NULL, aParameters, aNumElements);
        }
        if (retval != PVMFSuccess)
        {
            // Go through each datapath's cap-config IF in the datapath list and check for the string.
            for (uint32 i = 0; i < iDatapathList.size(); i++)
            {
                if (iDatapathList[i].iDecNodeCapConfigIF != NULL)
                {
                    retval = iDatapathList[i].iDecNodeCapConfigIF->releaseParameters(NULL, aParameters, aNumElements);
                    if (retval == PVMFSuccess)
                    {
                        // Key matched break the loop.
                        break;
                    }
                }

                if (iDatapathList[i].iSinkNodeCapConfigIF != NULL)
                {
                    retval = iDatapathList[i].iSinkNodeCapConfigIF->releaseParameters(NULL, aParameters, aNumElements);
                    if (retval == PVMFSuccess)
                    {
                        // Key matched break the loop.
                        break;
                    }
                }
            }
        }
        if (retval != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigReleaseParametersSync() Unsupported key"));
            return retval;
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCapConfigReleaseParameters() Out"));
    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoCapConfigSetParameters(PVPlayerEngineCommand& aCmd, bool aSyncCmd)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCapConfigSetParameters() In"));

    PvmiKvp* paramkvp;
    int32 numparam;
    PvmiKvp** retkvp;
    paramkvp = (PvmiKvp*)(aCmd.GetParam(0).pOsclAny_value);
    numparam = aCmd.GetParam(1).int32_value;
    retkvp = (PvmiKvp**)(aCmd.GetParam(2).pOsclAny_value);

    if (paramkvp == NULL || retkvp == NULL || numparam < 1)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigSetParameters() Passed in parameter invalid"));
        return PVMFErrArgument;
    }

    // Go through each parameter
    for (int32 paramind = 0; paramind < numparam; ++paramind)
    {
        if (iRollOverState == RollOverStateIdle)
        {
            PVMFStatus ret = VerifyAndSaveKVPValues(&paramkvp[paramind]);
            if (ret != PVMFSuccess)
            {
                return ret;
            };
        }
        // Count the number of components and parameters in the key
        int compcount = pv_mime_string_compcnt(paramkvp[paramind].key);
        // Retrieve the first component from the key string
        char* compstr = NULL;
        pv_mime_string_extract_type(0, paramkvp[paramind].key, compstr);

        if ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf")) < 0) || compcount < 2)
        {
            // First component should be "x-pvmf" and there must
            // be at least two components to go past x-pvmf
            *retkvp = &paramkvp[paramind];
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigSetParameters() Unsupported key"));
            return PVMFErrArgument;
        }

        // Retrieve the second component from the key string
        pv_mime_string_extract_type(1, paramkvp[paramind].key, compstr);

        // First check if it is key string for engine ("player")
        if (pv_mime_strcmp(compstr, _STRLIT_CHAR("player")) >= 0)
        {
            if (compcount == 3)
            {
                // Verify and set the passed-in player setting
                PVMFStatus retval = DoVerifyAndSetPlayerParameter(paramkvp[paramind], true);
                if (retval != PVMFSuccess)
                {
                    *retkvp = &paramkvp[paramind];
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigSetParameters() Setting parameter %d failed", paramind));
                    return retval;
                }
            }
            else
            {
                // Do not support more than 3 components right now
                *retkvp = &paramkvp[paramind];
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigSetParameters() Unsupported key"));
                return PVMFErrArgument;
            }
        }
        else
        {
            *retkvp = &paramkvp[paramind];
            bool anysuccess = false;


            if (iSourceNodeCapConfigIF != NULL)
            {
                *retkvp = NULL;
                iSourceNodeCapConfigIF->setParametersSync(NULL, &paramkvp[paramind], 1, *retkvp);
                if (*retkvp == NULL)
                {
                    anysuccess = true;
                }
            }
            // Go through each datapath's cap-config IF in the datapath list and check for the string.
            for (uint32 i = 0; i < iDatapathList.size(); i++)
            {
                if (iDatapathList[i].iDecNodeCapConfigIF != NULL)
                {
                    *retkvp = NULL;
                    iDatapathList[i].iDecNodeCapConfigIF->setParametersSync(NULL, &paramkvp[paramind], 1, *retkvp);
                    if (*retkvp == NULL)
                    {
                        anysuccess = true;
                        break;
                    }
                }

                if (iDatapathList[i].iSinkNodeCapConfigIF != NULL)
                {
                    *retkvp = NULL;
                    iDatapathList[i].iSinkNodeCapConfigIF->setParametersSync(NULL, &paramkvp[paramind], 1, *retkvp);
                    if (*retkvp == NULL)
                    {
                        anysuccess = true;
                        break;
                    }
                }
            }

            if (anysuccess == false)
            {
                // setParametersSync was not accepted by the node(s)
                *retkvp = &paramkvp[paramind];
                return PVMFErrArgument;
            }
        }

    }

    if (!aSyncCmd)
    {
        EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCapConfigSetParameters() Out"));
    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoCapConfigVerifyParameters(PvmiKvp* aParameters, int aNumElements)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCapConfigVerifyParameters() In"));

    if (aParameters == NULL || aNumElements < 1)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigVerifyParameters() Passed in parameter invalid"));
        return PVMFErrArgument;
    }

    // Go through each parameter and verify
    for (int32 paramind = 0; paramind < aNumElements; ++paramind)
    {
        // Count the number of components and parameters in the key
        int compcount = pv_mime_string_compcnt(aParameters[paramind].key);
        // Retrieve the first component from the key string
        char* compstr = NULL;
        pv_mime_string_extract_type(0, aParameters[paramind].key, compstr);

        if ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf")) < 0) || compcount < 2)
        {
            // First component should be "x-pvmf" and there must
            // be at least two components to go past x-pvmf
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigVerifyParameters() Unsupported key"));
            return PVMFErrArgument;
        }

        // Retrieve the second component from the key string
        pv_mime_string_extract_type(1, aParameters[paramind].key, compstr);

        // First check if it is key string for engine ("player")
        if (pv_mime_strcmp(compstr, _STRLIT_CHAR("player")) >= 0)
        {
            if (compcount == 3)
            {
                // Verify the passed-in player setting
                PVMFStatus retval = DoVerifyAndSetPlayerParameter(aParameters[paramind], false);
                if (retval != PVMFSuccess)
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigVerifyParameters() Verifying parameter %d failed", paramind));
                    return retval;
                }
            }
            else
            {
                // Do not support more than 3 components right now
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigVerifyParameters() Unsupported key"));
                return PVMFErrArgument;
            }
        }
        else
        {
            PVMFStatus retval = PVMFFailure;
            if (iSourceNodeCapConfigIF != NULL)
            {
                retval = iSourceNodeCapConfigIF->releaseParameters(NULL, aParameters, aNumElements);
            }
            if (retval != PVMFSuccess)
            {
                // Go through each datapath's cap-config IF in the datapath list and check for the string.
                for (uint32 i = 0; i < iDatapathList.size(); i++)
                {
                    if (iDatapathList[i].iDecNodeCapConfigIF != NULL)
                    {
                        retval = iDatapathList[i].iDecNodeCapConfigIF->verifyParametersSync(NULL, &aParameters[paramind], 1);
                        if (retval == PVMFSuccess)
                        {
                            // Key matched break the loop.
                            break;
                        }
                    }

                    if (iDatapathList[i].iSinkNodeCapConfigIF != NULL)
                    {
                        retval = iDatapathList[i].iSinkNodeCapConfigIF->verifyParametersSync(NULL, &aParameters[paramind], 1);
                        if (retval == PVMFSuccess)
                        {
                            // Key matched break the loop.
                            break;
                        }
                    }
                }
            }
            if (retval != PVMFSuccess)
            {
                return retval;
            }
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCapConfigVerifyParameters() Out"));
    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::DoGetPlayerParameter(PvmiKvp*& aParameters, int& aNumParamElements, int32 aIndex, PvmiKvpAttr reqattr)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetPlayerParameter() In"));

    aNumParamElements = 0;

    // Allocate memory for the KVP
    aParameters = (PvmiKvp*)oscl_malloc(sizeof(PvmiKvp));
    if (aParameters == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerParameter() Memory allocation for KVP failed"));
        return PVMFErrNoMemory;
    }
    oscl_memset(aParameters, 0, sizeof(PvmiKvp));
    // Allocate memory for the key string in KVP
    PvmiKeyType memblock = (PvmiKeyType)oscl_malloc(PVPLAYERCONFIG_KEYSTRING_SIZE * sizeof(char));
    if (memblock == NULL)
    {
        oscl_free(aParameters);
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerParameter() Memory allocation for key string failed"));
        return PVMFErrNoMemory;
    }
    oscl_strset(memblock, 0, PVPLAYERCONFIG_KEYSTRING_SIZE*sizeof(char));
    // Assign the key string buffer to KVP
    aParameters[0].key = memblock;

    // Copy the key string
    oscl_strncat(aParameters[0].key, _STRLIT_CHAR("x-pvmf/player/"), 14);
    oscl_strncat(aParameters[0].key, PVPlayerConfigBaseKeys[aIndex].iString, oscl_strlen(PVPlayerConfigBaseKeys[aIndex].iString));
    oscl_strncat(aParameters[0].key, _STRLIT_CHAR(";type=value;valtype="), 20);
    switch (PVPlayerConfigBaseKeys[aIndex].iValueType)
    {
        case PVMI_KVPVALTYPE_RANGE_INT32:
            oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_RANGE_INT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_RANGE_INT32_STRING));
            break;

        case PVMI_KVPVALTYPE_KSV:
            oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_KSV_STRING), oscl_strlen(PVMI_KVPVALTYPE_KSV_STRING));
            break;

        case PVMI_KVPVALTYPE_CHARPTR:
            oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_CHARPTR_STRING), oscl_strlen(PVMI_KVPVALTYPE_CHARPTR_STRING));
            break;

        case PVMI_KVPVALTYPE_BOOL:
            oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_BOOL_STRING), oscl_strlen(PVMI_KVPVALTYPE_BOOL_STRING));
            break;

        case PVMI_KVPVALTYPE_UINT32:
        default:
            if (reqattr == PVMI_KVPATTR_CAP)
            {
                oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_RANGE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_RANGE_UINT32_STRING));
            }
            else
            {
                oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING));
            }
            break;
    }
    aParameters[0].key[PVPLAYERCONFIG_KEYSTRING_SIZE-1] = 0;

    // Copy the requested info
    switch (aIndex)
    {
        case PBPOS_UNITS: // "pbpops_units"
            if (reqattr == PVMI_KVPATTR_CUR)
            {
                // Return current value
                // Allocate memory for the string
                char* curstr = (char*)oscl_malloc(32 * sizeof(char));
                if (curstr == NULL)
                {
                    oscl_free(aParameters[0].key);
                    oscl_free(aParameters);
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerParameter() Memory allocation for char* string failed"));
                    return PVMFErrNoMemory;
                }
                oscl_strset(curstr, 0, 32);
                // Copy the appropriate string based on units being used
                switch (iPBPosStatusUnit)
                {
                    case PVPPBPOSUNIT_SEC:
                        oscl_strncpy(curstr, _STRLIT_CHAR("PVPPBPOSUNIT_SEC"), 16);
                        aParameters[0].length = 16;
                        break;

                    case PVPPBPOSUNIT_MIN:
                        oscl_strncpy(curstr, _STRLIT_CHAR("PVPPBPOSUNIT_MIN"), 16);
                        aParameters[0].length = 16;
                        break;

                    case PVPPBPOSUNIT_MILLISEC:
                    default:
                        oscl_strncpy(curstr, _STRLIT_CHAR("PVPPBPOSUNIT_MILLISEC"), 21);
                        aParameters[0].length = 21;
                        break;
                }

                aParameters[0].value.pChar_value = curstr;
                aParameters[0].capacity = 32;
            }
            else if (reqattr == PVMI_KVPATTR_DEF)
            {
                // Return default
                // Allocate memory for the string
                int32 defstrlen = oscl_strlen(PVPLAYERENGINE_CONFIG_PBPOSSTATUSUNIT_DEF_STRING);
                char* defstr = (char*)oscl_malloc((defstrlen + 1) * sizeof(char));
                if (defstr == NULL)
                {
                    oscl_free(aParameters[0].key);
                    oscl_free(aParameters);
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerParameter() Memory allocation for char* string failed"));
                    return PVMFErrNoMemory;
                }
                // Copy and set
                oscl_strncpy(defstr, _STRLIT_CHAR(PVPLAYERENGINE_CONFIG_PBPOSSTATUSUNIT_DEF_STRING), defstrlen);
                defstr[defstrlen] = 0;
                aParameters[0].value.pChar_value = defstr;
                aParameters[0].capacity = defstrlen + 1;
                aParameters[0].length = defstrlen;
            }
            else
            {
                // Return capability
                // Allocate memory for the string
                int32 capstrlen = oscl_strlen(PVPLAYERENGINE_CONFIG_PBPOSSTATUSINTERVAL_CAP_STRING);
                char* capstr = (char*)oscl_malloc((capstrlen + 1) * sizeof(char));
                if (capstr == NULL)
                {
                    oscl_free(aParameters[0].key);
                    oscl_free(aParameters);
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerParameter() Memory allocation for char* string failed"));
                    return PVMFErrNoMemory;
                }
                // Copy and set
                oscl_strncpy(capstr, _STRLIT_CHAR(PVPLAYERENGINE_CONFIG_PBPOSSTATUSINTERVAL_CAP_STRING), capstrlen);
                capstr[capstrlen] = 0;
                aParameters[0].value.pChar_value = capstr;
                aParameters[0].capacity = capstrlen + 1;
                aParameters[0].length = capstrlen;
            }
            break;

        case PBPOS_INTERVAL:    // "pbpos_interval"
            if (reqattr == PVMI_KVPATTR_CUR)
            {
                // Return current value
                aParameters[0].value.uint32_value = iPBPosStatusInterval;
            }
            else if (reqattr == PVMI_KVPATTR_DEF)
            {
                // Return default
                aParameters[0].value.uint32_value = PVPLAYERENGINE_CONFIG_PBPOSSTATUSINTERVAL_DEF;
            }
            else
            {
                // Return capability
                range_uint32* rui32 = (range_uint32*)oscl_malloc(sizeof(range_uint32));
                if (rui32 == NULL)
                {
                    oscl_free(aParameters[0].key);
                    oscl_free(aParameters);
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerParameter() Memory allocation for range uint32 failed"));
                    return PVMFErrNoMemory;
                }
                rui32->min = PVPLAYERENGINE_CONFIG_PBPOSSTATUSINTERVAL_MIN;
                rui32->max = PVPLAYERENGINE_CONFIG_PBPOSSTATUSINTERVAL_MAX;
                aParameters[0].value.key_specific_value = (void*)rui32;
            }
            break;

        case SYNCPOINTSEEKWINDOW:   // "syncpointseekwindow"
            if (reqattr == PVMI_KVPATTR_CUR)
            {
                // Return current value
                aParameters[0].value.uint32_value = iSyncPointSeekWindow;
            }
            else if (reqattr == PVMI_KVPATTR_DEF)
            {
                // Return default
                aParameters[0].value.uint32_value = PVPLAYERENGINE_CONFIG_SEEKTOSYNCPOINTWINDOW_DEF;
            }
            else
            {
                // Return capability
                range_uint32* rui32 = (range_uint32*)oscl_malloc(sizeof(range_uint32));
                if (rui32 == NULL)
                {
                    oscl_free(aParameters[0].key);
                    oscl_free(aParameters);
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerParameter() Memory allocation for range uint32 failed"));
                    return PVMFErrNoMemory;
                }
                rui32->min = PVPLAYERENGINE_CONFIG_SEEKTOSYNCPOINTWINDOW_MIN;
                rui32->max = PVPLAYERENGINE_CONFIG_SEEKTOSYNCPOINTWINDOW_MAX;
                aParameters[0].value.key_specific_value = (void*)rui32;
            }
            break;

        case SYNCMARGIN_VIDEO:  // "syncmargin_video"
        case SYNCMARGIN_AUDIO:  // "syncmargin_audio"
        case SYNCMARGIN_TEXT:   // "syncmargin_text"
        {
            range_int32* ri32 = (range_int32*)oscl_malloc(sizeof(range_int32));
            if (ri32 == NULL)
            {
                oscl_free(aParameters[0].key);
                oscl_free(aParameters);
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerParameter() Memory allocation for range int32 failed"));
                return PVMFErrNoMemory;
            }

            if (reqattr == PVMI_KVPATTR_CUR)
            {
                // Return current value
                if (aIndex == SYNCMARGIN_VIDEO)
                {
                    // Video
                    ri32->min = iSyncMarginVideo.min;
                    ri32->max = iSyncMarginVideo.max;
                }
                else if (aIndex == SYNCMARGIN_AUDIO)
                {
                    // Audio
                    ri32->min = iSyncMarginAudio.min;
                    ri32->max = iSyncMarginAudio.max;
                }
                else
                {
                    // Text
                    ri32->min = iSyncMarginText.min;
                    ri32->max = iSyncMarginText.max;
                }
                aParameters[0].value.key_specific_value = (void*)ri32;
            }
            else if (reqattr == PVMI_KVPATTR_DEF)
            {
                // Return default
                ri32->min = PVPLAYERENGINE_CONFIG_SYNCMARGIN_EARLY_DEF;
                ri32->max = PVPLAYERENGINE_CONFIG_SYNCMARGIN_LATE_DEF;
                aParameters[0].value.key_specific_value = (void*)ri32;
            }
            else
            {
                // Return capability
                ri32->min = PVPLAYERENGINE_CONFIG_SYNCMARGIN_MIN;
                ri32->max = PVPLAYERENGINE_CONFIG_SYNCMARGIN_MAX;
                aParameters[0].value.key_specific_value = (void*)ri32;
            }
        }
        break;

        case PBPOS_ENABLE:  // "pbpos_enable"
            if (reqattr == PVMI_KVPATTR_CUR)
            {
                // Return current value
                aParameters[0].value.bool_value = iPBPosEnable;
            }
            else if (reqattr == PVMI_KVPATTR_DEF)
            {
                // Return default
                aParameters[0].value.bool_value = true;
            }
            else
            {
                // Return capability
                // Bool so no capability
            }
            break;

        case SILENCEINSERTION_ENABLE:  // "silenceinsertion_enable"
            if (reqattr == PVMI_KVPATTR_CUR)
            {
                // Return current value
                aParameters[0].value.bool_value = iSilenceInsertionEnable;
            }
            else if (reqattr == PVMI_KVPATTR_DEF)
            {
                // Return default
                aParameters[0].value.bool_value = true;
            }
            else
            {
                // Return capability
                // Bool so no capability
            }
            break;


        case GRACEFULDEGRADATION_ENABLE: // "gracefuldegradation_enable"
            if (reqattr == PVMI_KVPATTR_CUR)
            {
                // Return current value
                aParameters[0].value.bool_value = iGracefulDegradationEnable;
            }
            else if (reqattr == PVMI_KVPATTR_DEF)
            {
                // Return default
                aParameters[0].value.bool_value = PVPLAYERENGINE_CONFIG_GRACEFULDEGRADATIONENABLE_DEF;
            }
            else
            {
                // Return capability
                // Bool so no capability
            }
            break;

        default:
            // Invalid index
            oscl_free(aParameters[0].key);
            oscl_free(aParameters);
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerParameter() Invalid index to player parameter"));
            return PVMFErrArgument;
    }

    aNumParamElements = 1;

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetPlayerParameter() Out"));
    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::DoVerifyAndSetPlayerParameter(PvmiKvp& aParameter, bool aSetParam)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() In"));

    // Determine the valtype
    PvmiKvpValueType keyvaltype = GetValTypeFromKeyString(aParameter.key);
    if (keyvaltype == PVMI_KVPVALTYPE_UNKNOWN)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() Valtype in key string unknown"));
        return PVMFErrArgument;
    }
    // Retrieve the third component from the key string
    char* compstr = NULL;
    pv_mime_string_extract_type(2, aParameter.key, compstr);

    int32 engcomp3ind = 0;
    for (engcomp3ind = 0; engcomp3ind < PVPLAYERCONFIG_BASE_NUMKEYS; ++engcomp3ind)
    {
        // Go through each engine component string at 3rd level
        if (pv_mime_strcmp(compstr, (char*)(PVPlayerConfigBaseKeys[engcomp3ind].iString)) >= 0)
        {
            // Break out of the for loop
            break;
        }
    }

    if (engcomp3ind >= PVPLAYERCONFIG_BASE_NUMKEYS)
    {
        // Match couldn't be found
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() Unsupported key or non-leaf node"));
        return PVMFErrArgument;
    }

    // Verify the valtype
    if (keyvaltype != PVPlayerConfigBaseKeys[engcomp3ind].iValueType)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() Valtype does not match for key"));
        return PVMFErrArgument;
    }

    switch (engcomp3ind)
    {
        case PBPOS_UNITS: // "pbpos_units"
        {
            // Validate
            if (aParameter.value.pChar_value == NULL)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() char* string for pbpos_units is NULL"));
                return PVMFErrArgument;
            }

            // Check the specified unit
            // Use sample number as the invalid default since it is not allowed
            PVPPlaybackPositionUnit newposunit = PVPPBPOSUNIT_UNKNOWN;
            if (oscl_strncmp(aParameter.value.pChar_value, _STRLIT_CHAR("PVPPBPOSUNIT_SEC"), 16) == 0)
            {
                newposunit = PVPPBPOSUNIT_SEC;
            }
            else if (oscl_strncmp(aParameter.value.pChar_value, _STRLIT_CHAR("PVPPBPOSUNIT_MIN"), 16) == 0)
            {
                newposunit = PVPPBPOSUNIT_MIN;
            }
            else if (oscl_strncmp(aParameter.value.pChar_value, _STRLIT_CHAR("PVPPBPOSUNIT_MILLISEC"), 21) == 0)
            {
                newposunit = PVPPBPOSUNIT_MILLISEC;
            }

            if (newposunit == PVPPBPOSUNIT_UNKNOWN)
            {
                // Couldn't determine the new units
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() Invalid units for pbpos_units"));
                return PVMFErrArgument;
            }
            // Change the config if to set
            if (aSetParam)
            {
                iPBPosStatusUnit = newposunit;
            }
        }
        break;

        case PBPOS_INTERVAL: // "pbpos_interval"
            // Check if within range
            if (aParameter.value.uint32_value < PVPLAYERENGINE_CONFIG_PBPOSSTATUSINTERVAL_MIN ||
                    aParameter.value.uint32_value > PVPLAYERENGINE_CONFIG_PBPOSSTATUSINTERVAL_MAX)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() Invalid value for pbpos_interval"));
                return PVMFErrArgument;
            }
            // Change the config if to set
            if (aSetParam)
            {
                iPBPosStatusInterval = aParameter.value.uint32_value;
            }
            break;


        case SYNCPOINTSEEKWINDOW: // "syncpointseekwindow"
            // Check if within range
            if (aParameter.value.uint32_value > PVPLAYERENGINE_CONFIG_SEEKTOSYNCPOINTWINDOW_MAX)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() Invalid value for syncpointseekwindow"));
                return PVMFErrArgument;
            }
            // Change the config if to set
            if (aSetParam)
            {
                iSyncPointSeekWindow = aParameter.value.uint32_value;
            }
            break;

        case SYNCMARGIN_VIDEO: // "syncmargin_video"
        case SYNCMARGIN_AUDIO: // "syncmargin_audio"
        case SYNCMARGIN_TEXT: // "syncmargin_text"
        {
            range_int32* ri32 = (range_int32*)aParameter.value.key_specific_value;
            if (ri32 == NULL)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() ksv for syncmargin is NULL"));
                return PVMFErrArgument;
            }

            // Check if within range
            if (ri32->min < PVPLAYERENGINE_CONFIG_SYNCMARGIN_MIN ||
                    ri32->min > PVPLAYERENGINE_CONFIG_SYNCMARGIN_MAX ||
                    ri32->max < PVPLAYERENGINE_CONFIG_SYNCMARGIN_MIN ||
                    ri32->max > PVPLAYERENGINE_CONFIG_SYNCMARGIN_MAX)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() Invalid range for syncmargin"));
                return PVMFErrArgument;
            }

            // Change the config if to set
            if (aSetParam)
            {
                return DoSetConfigSyncMargin(ri32->min, ri32->max, engcomp3ind);
            }
        }
        break;

        case PBPOS_ENABLE: // "pbpos_enable"
            // Nothing to validate since it is boolean
            // Change the config if to set
            if (aSetParam)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() pbpos_enable set to %d", iPBPosEnable));
                bool prevPBPosEnable = iPBPosEnable;
                iPBPosEnable = aParameter.value.bool_value;
                if (prevPBPosEnable && !(aParameter.value.bool_value))
                {
                    // Stop playback position reporting
                    StopPlaybackStatusTimer();
                }
                else if (!prevPBPosEnable && (aParameter.value.bool_value))
                {
                    // Start playback position reporting only when playback clock is running
                    if (iPlaybackClock.GetState() == PVMFMediaClock::RUNNING)
                    {
                        StartPlaybackStatusTimer();
                    }
                }

            }
            break;

        case SILENCEINSERTION_ENABLE: // "silenceinsertion_enable"
            // Nothing to validate since it is boolean
            // Change the config if to set
            if (aSetParam)
            {
                iSilenceInsertionEnable = aParameter.value.bool_value;
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() iSilenceInsertionEnable set to %d", iSilenceInsertionEnable));
            }
            break;

        case GRACEFULDEGRADATION_ENABLE: // "gracefuldegradation_enable"
            // Nothing to validate since it is boolean
            // Change the config if to set
            if (aSetParam)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() gracefuldegradation_enable set to %d", iGracefulDegradationEnable));

                iGracefulDegradationEnable = aParameter.value.bool_value;
            }
            break;

        default:
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() Invalid index for player parameter"));
            return PVMFErrArgument;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() Out"));
    return PVMFSuccess;
}


PVMFStatus PVPlayerEngine::DoSetConfigSyncMargin(int32 aEarlyMargin, int32 aLateMargin, int32 aMediaType)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetConfigSyncMargin() In"));

    if (SYNCMARGIN_VIDEO == aMediaType)
    {
        // Video
        iSyncMarginVideo.min = aEarlyMargin;
        iSyncMarginVideo.max = aLateMargin;

        // Find the video datapath in the list
        int32 vdpind = -1;
        if (FindDatapathForTrackUsingMimeString(true, false, false, vdpind) == true)
        {
            PVPlayerEngineDatapath* pvpedp = &(iDatapathList[vdpind]);
            if (pvpedp->iDatapath)
            {
                if (pvpedp->iSinkNodeSyncCtrlIF)
                {
                    pvpedp->iSinkNodeSyncCtrlIF->SetMargins((-1*iSyncMarginVideo.min), iSyncMarginVideo.max);
                }
            }
        }
    }
    else if (SYNCMARGIN_AUDIO == aMediaType)
    {
        // Audio
        iSyncMarginAudio.min = aEarlyMargin;
        iSyncMarginAudio.max = aLateMargin;

        // Find the audio datapath in the list
        int32 adpind = -1;
        if (FindDatapathForTrackUsingMimeString(false, true, false, adpind) == true)
        {
            PVPlayerEngineDatapath* pvpedp = &(iDatapathList[adpind]);
            if (pvpedp->iDatapath)
            {
                if (pvpedp->iSinkNodeSyncCtrlIF)
                {
                    pvpedp->iSinkNodeSyncCtrlIF->SetMargins((-1*iSyncMarginAudio.min), iSyncMarginAudio.max);
                }
            }
        }
    }
    else if (SYNCMARGIN_TEXT == aMediaType)
    {
        // Text
        iSyncMarginText.min = aEarlyMargin;
        iSyncMarginText.max = aLateMargin;

        // Find the text datapath in the list
        int32 tdpind = -1;
        if (FindDatapathForTrackUsingMimeString(false, false, true, tdpind) == true)
        {
            PVPlayerEngineDatapath* pvpedp = &(iDatapathList[tdpind]);
            if (pvpedp->iDatapath)
            {
                if (pvpedp->iSinkNodeSyncCtrlIF)
                {
                    pvpedp->iSinkNodeSyncCtrlIF->SetMargins((-1*iSyncMarginText.min), iSyncMarginText.max);
                }
            }
        }
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetConfigSyncMargin() Invalid media type index"));
        return PVMFErrArgument;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetConfigSyncMargin() Out"));
    return PVMFSuccess;
}


PVPlayerEngineContext* PVPlayerEngine::AllocateEngineContext(PVPlayerEngineDatapath* aEngineDatapath, PVMFNodeInterface* aNode, PVPlayerDatapath* aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext, int32 aCmdType)
{
    // Allocate memory for the context from the fixed size memory pool
    PVPlayerEngineContext* context = NULL;
    int32 leavecode = 0;
    OSCL_TRY(leavecode, context = (PVPlayerEngineContext*)(iCurrentContextListMemPool.allocate(sizeof(PVPlayerEngineContext))));
    OSCL_FIRST_CATCH_ANY(leavecode,
                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::AllocateEngineContext() allocate on iCurrentContextListMemPool did a leave!"));
                         OSCL_ASSERT(false));

    OSCL_ASSERT(context);

    // Set the context info
    context->iEngineDatapath = aEngineDatapath;
    context->iNode = aNode;
    context->iDatapath = aDatapath;
    context->iCmdId = aCmdId;
    context->iCmdContext = aCmdContext;
    context->iCmdType = aCmdType;

    // Save the context in the list
    leavecode = 0;
    OSCL_TRY(leavecode, iCurrentContextList.push_back(context));
    OSCL_FIRST_CATCH_ANY(leavecode,
                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::AllocateEngineContext() Push back on the context list did a leave!"));
                         iCurrentContextListMemPool.deallocate((OsclAny*)context);
                         OSCL_ASSERT(false);
                         return NULL;);

    return context;
}


void PVPlayerEngine::FreeEngineContext(PVPlayerEngineContext* aContext)
{
    OSCL_ASSERT(aContext);

    // Remove the context from the list
    uint32 i = 0;
    bool foundcontext = false;
    for (i = 0; i < iCurrentContextList.size(); ++i)
    {
        if (iCurrentContextList[i] == aContext)
        {
            foundcontext = true;
            break;
        }
    }

    if (foundcontext)
    {
        iCurrentContextList.erase(iCurrentContextList.begin() + i);
        // Free the memory used by context in the memory pool
        iCurrentContextListMemPool.deallocate((OsclAny*)aContext);
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::FreeEngineContext() Context not on current list (0x%x). CmdType %d", aContext, aContext->iCmdType));
        OSCL_ASSERT(false);
        // Don't return to memory pool since it could add multiple entries
        // of same address in free list
    }
}


void PVPlayerEngine::HandleSourceNodeQueryInitIF(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVPlayerEngine::HandleSourceNodeQueryInitIF() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryInitIF() In"));

    PVMFStatus cmdstatus;
    bool rescheduleAO = false;

    switch (aNodeResp.GetCmdStatus())
    {
        case PVMFSuccess:
            if (iSourceNodePVInterfaceInit)
            {
                iSourceNodeInitIF = (PVMFDataSourceInitializationExtensionInterface*)iSourceNodePVInterfaceInit;
                iSourceNodePVInterfaceInit = NULL;
            }
            // Query for track selection interface
            cmdstatus = DoSourceNodeQueryTrackSelIF(aNodeContext.iCmdId, aNodeContext.iCmdContext);
            if (cmdstatus != PVMFSuccess)
            {
                if ((CheckForSourceRollOver() == true) && (iRollOverState == RollOverStateInProgress))
                {
                    iRollOverState = RollOverStateStart;
                    rescheduleAO = true;
                }
                else
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                    (0, "PVPlayerEngine::HandleSourceNodeQueryInitIF() DoSourceNodeQueryTrackSelIF failed, Add EH command"));
                    iCommandCompleteStatusInErrorHandling = cmdstatus;
                    iCommandCompleteErrMsgInErrorHandling = NULL;
                    if (iRollOverState == RollOverStateInProgress)
                    {
                        // Init is the current ongoing cmd so queue Init EH cmd
                        AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_INIT, NULL, NULL, NULL, false);
                    }
                    else
                    {
                        // AddDataSource cmd is Current Command, queue ADS EH cmd
                        AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_ADD_DATA_SOURCE, NULL, NULL, NULL, false);
                    }
                    iRollOverState = RollOverStateIdle;
                }
            }
            break;

        default:
        {
            iSourceNodePVInterfaceInit = NULL;
            iSourceNodeInitIF = NULL;

            if ((CheckForSourceRollOver() == true) && (iRollOverState == RollOverStateInProgress))
            {
                iRollOverState = RollOverStateStart;
                rescheduleAO = true;
            }
            else
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "PVPlayerEngine::HandleSourceNodeQueryInitIF() failed, Add EH command"));
                cmdstatus = aNodeResp.GetCmdStatus();
                PVMFErrorInfoMessageInterface* nextmsg = NULL;
                if (aNodeResp.GetEventExtensionInterface())
                {
                    nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
                }

                PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
                iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceInit, puuid, nextmsg));
                iCommandCompleteStatusInErrorHandling = cmdstatus;
                if (iRollOverState == RollOverStateInProgress)
                {
                    // Init is the current ongoing cmd so queue Init EH cmd
                    AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_INIT, NULL, NULL, NULL, false);
                }
                else
                {
                    // AddDataSource cmd is Current Command, queue ADS EH cmd
                    AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_ADD_DATA_SOURCE, NULL, NULL, NULL, false);
                }
                iRollOverState = RollOverStateIdle;
            }
        }
        break;
    }
    if (rescheduleAO)
    {
        if (IsBusy())
        {
            Cancel();
        }

        RunIfNotReady();
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryInitIF() Out"));
}


void PVPlayerEngine::HandleSourceNodeQueryTrackSelIF(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVPlayerEngine::HandleSourceNodeQueryTrackSelIF() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryTrackSelIF() In"));

    PVMFStatus cmdstatus;
    bool rescheduleAO = false;

    switch (aNodeResp.GetCmdStatus())
    {
        case PVMFSuccess:
            if (iSourceNodePVInterfaceTrackSel)
            {
                iSourceNodeTrackSelIF = (PVMFTrackSelectionExtensionInterface*)iSourceNodePVInterfaceTrackSel;
                iSourceNodePVInterfaceTrackSel = NULL;
            }
            // Query the source node for optional extension IFs
            cmdstatus = DoSourceNodeQueryInterfaceOptional(aNodeContext.iCmdId, aNodeContext.iCmdContext);
            if (cmdstatus != PVMFSuccess)
            {
                // If optional extension IFs are not available, just complete the AddDataSource command as success
                if ((CheckForSourceRollOver() == true) && (iRollOverState == RollOverStateInProgress))
                {
                    iRollOverState = RollOverStateStart;
                    rescheduleAO = true;
                }
                else
                {
                    iRollOverState = RollOverStateIdle;
                    EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess);
                }
            }
            break;

        default:
        {
            iSourceNodePVInterfaceTrackSel = NULL;
            iSourceNodeTrackSelIF = NULL;

            if ((CheckForSourceRollOver() == true) && (iRollOverState == RollOverStateInProgress))
            {
                iRollOverState = RollOverStateStart;
                rescheduleAO = true;
            }
            else
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "PVPlayerEngine::HandleSourceNodeQueryTrackSelIF() failed, Add EH Command"));
                cmdstatus = aNodeResp.GetCmdStatus();
                PVMFErrorInfoMessageInterface* nextmsg = NULL;
                if (aNodeResp.GetEventExtensionInterface())
                {
                    nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
                }

                PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
                iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceInit, puuid, nextmsg));

                iCommandCompleteStatusInErrorHandling = cmdstatus;
                if (iRollOverState == RollOverStateInProgress)
                {
                    // Init is the current ongoing cmd so queue Init EH cmd
                    AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_INIT, NULL, NULL, NULL, false);
                }
                else
                {
                    // AddDataSource cmd is Current Command, queue ADS EH cmd
                    AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_ADD_DATA_SOURCE, NULL, NULL, NULL, false);
                }
                iRollOverState = RollOverStateIdle;
            }
        }
        break;
    }
    if (rescheduleAO)
    {
        if (IsBusy())
        {
            Cancel();
        }

        RunIfNotReady();
    }
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryTrackSelIF() Out"));
}


void PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() In"));

    // Determine QueryInterface() for which interface completed
    if (aNodeContext.iCmdType == PVP_CMD_SourceNodeQueryTrackLevelInfoIF)
    {
        if ((aNodeResp.GetCmdStatus() == PVMFSuccess) && iSourceNodePVInterfaceTrackLevelInfo)
        {
            iSourceNodeTrackLevelInfoIF = (PVMFTrackLevelInfoExtensionInterface*)iSourceNodePVInterfaceTrackLevelInfo;
            iSourceNodePVInterfaceTrackLevelInfo = NULL;
        }
        else
        {
            // Track level info IF is not available in this data source
            iSourceNodePVInterfaceTrackLevelInfo = NULL;
            iSourceNodeTrackLevelInfoIF = NULL;
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() Track level info IF not available"));
        }
    }
    else if (aNodeContext.iCmdType == PVP_CMD_SourceNodeQueryPBCtrlIF)
    {
        if ((aNodeResp.GetCmdStatus() == PVMFSuccess) && iSourceNodePVInterfacePBCtrl)
        {
            iSourceNodePBCtrlIF = (PvmfDataSourcePlaybackControlInterface*)iSourceNodePVInterfacePBCtrl;
            iSourceNodePVInterfacePBCtrl = NULL;
        }
        else
        {
            // Playback control is not available in this data source
            iSourceNodePVInterfacePBCtrl = NULL;
            iSourceNodePBCtrlIF = NULL;
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() Position control IF not available"));
        }
    }
    else if (aNodeContext.iCmdType == PVP_CMD_SourceNodeQueryDirCtrlIF)
    {
        if ((aNodeResp.GetCmdStatus() == PVMFSuccess) && iSourceNodePVInterfaceDirCtrl)
        {
            iSourceNodeDirCtrlIF = (PvmfDataSourceDirectionControlInterface*)iSourceNodePVInterfaceDirCtrl;
            iSourceNodePVInterfaceDirCtrl = NULL;
        }
        else
        {
            // Direction control is not available in this data source
            iSourceNodePVInterfaceDirCtrl = NULL;
            iSourceNodeDirCtrlIF = NULL;
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() Direction control IF not available"));
        }
    }
    else if (aNodeContext.iCmdType == PVP_CMD_SourceNodeQueryMetadataIF)
    {
        if ((aNodeResp.GetCmdStatus() == PVMFSuccess) && iSourceNodePVInterfaceMetadataExt)
        {
            iSourceNodeMetadataExtIF = (PVMFMetadataExtensionInterface*)iSourceNodePVInterfaceMetadataExt;
            iSourceNodePVInterfaceMetadataExt = NULL;

            // Add the parser node's metadata extension IF to the list
            if (AddToMetadataInterfaceList(iSourceNodeMetadataExtIF, iSourceNodeSessionId, NULL, iSourceNode) != PVMFSuccess)
            {
                iSourceNodeMetadataExtIF->removeRef();
                iSourceNodeMetadataExtIF = NULL;

                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() Metadata IF could not be added to list"));
            }
        }
        else
        {
            // Metadata is not available in this data source
            iSourceNodePVInterfaceMetadataExt = NULL;
            iSourceNodeMetadataExtIF = NULL;
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() Metadata IF not available"));
        }
    }
    else if (aNodeContext.iCmdType == PVP_CMD_SourceNodeQueryCapConfigIF)
    {
        if ((aNodeResp.GetCmdStatus() == PVMFSuccess) && iSourceNodePVInterfaceCapConfig)
        {
            iSourceNodeCapConfigIF = (PvmiCapabilityAndConfig*)iSourceNodePVInterfaceCapConfig;
            iSourceNodePVInterfaceCapConfig = NULL;
        }
        else
        {
            // Cap-config is not available in this data source
            iSourceNodePVInterfaceCapConfig = NULL;
            iSourceNodeCapConfigIF = NULL;
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() Cap-Config IF not available"));
        }
    }
    else if (aNodeContext.iCmdType == PVP_CMD_SourceNodeQuerySrcNodeRegInitIF)
    {
        if ((aNodeResp.GetCmdStatus() == PVMFSuccess) && iSourceNodePVInterfaceRegInit)
        {
            iSourceNodeRegInitIF = (PVMFDataSourceNodeRegistryInitInterface*)iSourceNodePVInterfaceRegInit;
            iSourceNodePVInterfaceRegInit = NULL;

            // Set source node regsitry
            iSourceNodeRegInitIF->SetPlayerNodeRegistry(&iPlayerNodeRegistry);
        }
        else
        {
            //Node Registry Init Extension Interface is not available in this data source
            iSourceNodePVInterfaceRegInit = NULL;
            iSourceNodeRegInitIF = NULL;
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() Src Node Registry Init IF not available"));
        }
    }

    // Decrement the pending counter and complete the AddDataSource command if 0.
    --iNumPendingNodeCmd;
    if (iNumPendingNodeCmd == 0)
    {
        if (iRollOverState == RollOverStateInProgress)
        {
            SetRollOverKVPValues();
            PVMFStatus retval = DoSourceNodeInit(aNodeContext.iCmdId, aNodeContext.iCmdContext);
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() - Source Roll Over In Progress - Doing Source Node Init"));

            if (retval == PVMFSuccess)
            {
                SetEngineState(PVP_ENGINE_STATE_INITIALIZING);
            }
            else
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() - Source Roll Over In Progress - DoSourceNodeInit Failed"));
                if ((CheckForSourceRollOver() == true) && (iRollOverState == RollOverStateInProgress))
                {
                    iRollOverState = RollOverStateStart;
                    RunIfNotReady();
                }
                else
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                    (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() DoSourceNodeInit failed, Add EH Command"));
                    iRollOverState = RollOverStateIdle;
                    iCommandCompleteStatusInErrorHandling = retval;
                    iCommandCompleteErrMsgInErrorHandling = NULL;
                    AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_INIT, NULL, NULL, NULL, false);
                }
            }
        }
        else
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() All QueryInterface() commands complete so AddDataSource is complete"));
            EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess);
        }
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() %d QueryInterface() commands are still pending", iNumPendingNodeCmd));
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() Out"));
}

void PVPlayerEngine::HandleSourceNodeInit(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::HandleSourceNodeInit() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInit() In"));

    iRollOverState = RollOverStateIdle;
    PVMFStatus cmdstatus;

    // Querying for the CPM License Interface is delayed until the Source Node Init is complete
    DoSourceNodeQueryCPMLicenseInterface(aNodeContext.iCmdId, aNodeContext.iCmdContext);

    switch (aNodeResp.GetCmdStatus())
    {
        case PVMFSuccess:
        {
            // Try to retrieve the duration from the source node via metadata IF
            // Only if we din't got that value through PVMFInfoDurationAvailable informational event.
            if (!iSourceDurationAvailable)
            {
                if (DoSourceNodeGetDurationValue(aNodeContext.iCmdId, aNodeContext.iCmdContext) != PVMFSuccess)
                {
                    // Duration could not be retrieved.
                    // Not an error so complete so engine's Init()
                    SetEngineState(PVP_ENGINE_STATE_INITIALIZED);
                    EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess);
                }
            }
            else
            {
                // Duration is already available through Info event.
                // so complete  engine's Init()
                SetEngineState(PVP_ENGINE_STATE_INITIALIZED);
                EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess);
            }
        }
        break;


        case PVMFErrDrmLicenseNotFound:
        case PVMFErrDrmLicenseExpired:
        case PVMFErrHTTPAuthenticationRequired:
        case PVMFErrRedirect:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInit() PVMFErrDrmLicenseNotFound/PVMFErrHTTPAuthenticationRequired/PVMFErrRedirect"));

            SetEngineState(PVP_ENGINE_STATE_IDLE);
            cmdstatus = aNodeResp.GetCmdStatus();

            PVMFErrorInfoMessageInterface* nextmsg = NULL;
            if (aNodeResp.GetEventExtensionInterface())
            {
                nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
            }

            PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
            PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceInit, puuid, nextmsg));

            EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus, OSCL_STATIC_CAST(PVInterface*, errmsg), aNodeResp.GetEventData());
            errmsg->removeRef();

        }
        break;

        case PVMFErrContentInvalidForProgressivePlayback:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleSourceNodeInit() failed with PVMFErrContentInvalidForProgressivePlayback, Add EH Command"));

            SetEngineState(PVP_ENGINE_STATE_IDLE);
            cmdstatus = aNodeResp.GetCmdStatus();

            PVMFErrorInfoMessageInterface* nextmsg = NULL;
            if (aNodeResp.GetEventExtensionInterface())
            {
                nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
            }

            PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
            iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceInit, puuid, nextmsg));
            iCommandCompleteStatusInErrorHandling = cmdstatus;
            AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_INIT, NULL, NULL, NULL, false);
        }
        break;

        default:
        {
            if (iState == PVP_ENGINE_STATE_INITIALIZING)
            {
                SetEngineState(PVP_ENGINE_STATE_IDLE);
                if (CheckForSourceRollOver() == false)
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeInit() failed, Add EH Command"));
                    cmdstatus = aNodeResp.GetCmdStatus();

                    PVMFErrorInfoMessageInterface* nextmsg = NULL;
                    if (aNodeResp.GetEventExtensionInterface())
                    {
                        nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
                    }

                    PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
                    iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceInit, puuid, nextmsg));
                    iCommandCompleteStatusInErrorHandling = cmdstatus;
                    AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_INIT, NULL, NULL, NULL, false);
                }
                else
                {
                    // Initialization of source node failed so try alternates
                    //reschedule to do source node roll over
                    iRollOverState = RollOverStateStart;
                    //remove any queued up auto-pause/auto-resume commands
                    //they are no longer applicable since we are doing a change of sourcenode
                    removeCmdFromQ(iPendingCmds, PVP_ENGINE_COMMAND_PAUSE_DUE_TO_BUFFER_UNDERFLOW, true);
                    removeCmdFromQ(iPendingCmds, PVP_ENGINE_COMMAND_RESUME_DUE_TO_BUFFER_DATAREADY, true);
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeInit() - Rescheduling to do source roll over"));
                    RunIfNotReady();
                }
            }
            else
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeInit() - Incorrect State - Asserting"));
                OSCL_ASSERT(false);
            }
        }
        break;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInit() Out"));
}

void PVPlayerEngine::HandleSourceNodeQueryCPMLicenseInterface(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVPlayerEngine::HandleSourceNodeQueryCPMLicenseInterface() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryCPMLicenseInterface() In"));
    if ((aNodeResp.GetCmdStatus() == PVMFSuccess) && iPVInterfaceCPMLicense)
    {
        iCPMLicenseIF = (PVMFCPMPluginLicenseInterface*)iPVInterfaceCPMLicense;
        iCPMLicenseIF->SetObserver(*this);
        iPVInterfaceCPMLicense = NULL;
    }
    else
    {
        //CPM License is not available in this data source
        iPVInterfaceCPMLicense = NULL;
        iCPMLicenseIF = NULL;
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0,
                        "PVPlayerEngine::HandleSourceNodeQueryCPMLicenseInterface() CPM License IF not available"));
    }
}

void PVPlayerEngine::HandleSourceNodeGetDurationValue(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVPlayerEngine::HandleSourceNodeGetDurationValue() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeGetDurationValue() In"));

    switch (aNodeResp.GetCmdStatus())
    {
        case PVMFSuccess:
        {
            // Extract the duration and save it
            // Check that there is one KVP in value list
            if (iSourceDurationValueList.size() != 1)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSourceNodeGetDurationValue() Value list size is not 1 (size=%d)",
                                iSourceDurationValueList.size()));
                break;
            }

            // Check that the key in KVP is not NULL
            if (iSourceDurationValueList[0].key == NULL)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSourceNodeGetDurationValue() Value list key string is NULL"));
                break;
            }

            // Check that value is for duration
            int retval = pv_mime_strstr(iSourceDurationValueList[0].key, (char*)_STRLIT_CHAR("duration"));
            if (retval == -1)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSourceNodeGetDurationValue() Key string does not contain duration"));
                break;
            }

            // Check that duration value is uint32. If not available assume uint32.
            PvmiKvpValueType durvaltype = GetValTypeFromKeyString(iSourceDurationValueList[0].key);
            if (durvaltype != PVMI_KVPVALTYPE_UINT32 && durvaltype != PVMI_KVPVALTYPE_UNKNOWN)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSourceNodeGetDurationValue() Value type is not uint32 or unknown"));
                break;
            }
            iSourceDurationInMS = iSourceDurationValueList[0].value.uint32_value;

            // Check the timescale. If not available, assume millisecond (1000)
            const char* retsubstr = NULL;
            uint32 retsubstrlen = 0;
            uint32 tsparamlen = oscl_strlen(_STRLIT_CHAR("timescale="));
            retsubstr = oscl_strstr(iSourceDurationValueList[0].key, _STRLIT_CHAR("timescale="));
            if (retsubstr != NULL)
            {
                retsubstrlen = oscl_strlen(retsubstr);
                if (retsubstrlen > tsparamlen)
                {
                    uint32 timescale = 0;
                    PV_atoi((char*)(retsubstr + tsparamlen), 'd', (retsubstrlen - tsparamlen), timescale);
                    if (timescale > 0 && timescale != 1000)
                    {
                        // Convert to milliseconds
                        MediaClockConverter mcc(timescale);
                        mcc.update_clock(iSourceDurationInMS);
                        iSourceDurationInMS = mcc.get_converted_ts(1000);
                        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSourceNodeGetDurationValue() Timescale for duration is %d",
                                        timescale));
                    }
                }
            }

            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSourceNodeGetDurationValue() Duration in millisec is %d",
                            iSourceDurationInMS));
            iSourceDurationAvailable = true;
            UpdateSourceDurationVector((uint8*)&iClipsCompleted, iSourceDurationInMS);
        }
        break;

        default:
        {
            // Duration is not available
            // Do nothing
        }
        break;
    }

    // Release any metadata values back to source node
    // and then clear it
    if (iSourceDurationValueList.empty() == false)
    {
        if (iSourceNodeMetadataExtIF != NULL)
        {
            iSourceNodeMetadataExtIF->ReleaseNodeMetadataValues(iSourceDurationValueList, 0, iSourceDurationValueList.size());
        }
        iSourceDurationValueList.clear();
    }

    // Engine's Init() is now complete
    SetEngineState(PVP_ENGINE_STATE_INITIALIZED);
    EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeGetDurationValue() Out"));
}

void PVPlayerEngine::HandleSourceNodeSetDataSourceRate(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceRate() In"));

    PVMFStatus cmdstatus = aNodeResp.GetCmdStatus();

    if (cmdstatus != PVMFSuccess)
    {
        EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus);
    }
    else
    {
        //Continue on to sink rate change.
        cmdstatus = DoSinkNodeChangeClockRate();
        if (cmdstatus != PVMFSuccess)
        {
            EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus);
        }
        else
        {
            //Rate Change is complete.

            //Install the updated rate and timebase.
            UpdateTimebaseAndRate();

            //Start direction change sequence if needed.
            if (iPlaybackDirection_New != iPlaybackDirection)
            {
                cmdstatus = UpdateCurrentDirection(aNodeContext.iCmdId, aNodeContext.iCmdContext);
                switch (cmdstatus)
                {
                    case PVMFPending:
                        //wait on node command completion and call to HandleSourceNodeSetDataSourceDirection
                        break;
                    case PVMFSuccess:
                        //engine command is done, but direction is not actually set on the
                        //source until the Resume or Prepare happens.
                        EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess);
                        break;
                    default:
                        //failed!
                        EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus);
                        break;
                }
            }
            else
            {
                //SetPlaybackRate is complete!
                EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess);
            }
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceRate() Out"));
}

PVMFStatus PVPlayerEngine::DoSinkNodeChangeClockRate()
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeChangeClockRate() In"));

    // Check with sink nodes
    PVMFStatus cmdstatus = PVMFSuccess;

    for (uint32 i = 0; i < iDatapathList.size(); ++i)
    {
        if (iDatapathList[i].iDatapath && iDatapathList[i].iSinkNodeSyncCtrlIF)
        {
            cmdstatus = iDatapathList[i].iSinkNodeSyncCtrlIF->ChangeClockRate(iPlaybackClockRate_New);

            if (cmdstatus != PVMFSuccess)
            {
                // One of the sinks reported not supported so don't allow the clock rate change.
                break;
            }
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeChangeClockRate() Out"));
    return cmdstatus;
}

void PVPlayerEngine::UpdateDirection(PVMFTimestamp aNPT, PVMFTimestamp aMediaTS, PVPPlaybackPosition& aPos)
{
    //First note the current observed NPT value.  We will reposition to this
    //value.
    PVPPlaybackPosition curpos;
    curpos.iIndeterminate = false;
    curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC;
    GetPlaybackClockPosition(curpos);
    aPos = curpos;

    //Install the new value for direction.
    iPlaybackDirection = iPlaybackDirection_New;

    //Save the start NPT and TS
    iStartNPT = aNPT;
    iStartMediaDataTS = aMediaTS;
    iPlaybackClock.UpdateNPTClockPosition(iStartNPT, (iPlaybackDirection < 0) ? true : false);
    if (iPlaybackDirection_New < 0)
    {
        if (aPos.iPosValue.millisec_value >= iSourceDurationInMS)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateDirection() Current pos %dms is more than Duration %dms", aPos.iPosValue.millisec_value, iSourceDurationInMS));
            if (ConvertFromMillisec((uint32)(iSourceDurationInMS - 1), aPos) != PVMFSuccess)
            {
                // Other position units are not supported yet
                aPos.iIndeterminate = true;
            }
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVPlayerEngine::UpdateDirection() Direction %d New Start NPT %d Start Media Data TS %d, Repos NPT %d, Pos Indeterminate %d"
                     , iPlaybackDirection
                     , iStartNPT
                     , iStartMediaDataTS
                     , aPos.iPosValue.millisec_value
                     , aPos.iIndeterminate));
}

void PVPlayerEngine::UpdateTimebaseAndRate()
{
    if (iPlaybackClockRate_New == iPlaybackClockRate
            && iOutsideTimebase_New == iOutsideTimebase)
        return;//no update needed

    //Install the new values for rate & timebase.
    iPlaybackClockRate = iPlaybackClockRate_New;
    iOutsideTimebase = iOutsideTimebase_New;

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVPlayerEngine::UpdateTimebaseAndRate() Rate %d OutsideTB 0x%x CurDir %d NewDir %d"
                     , iPlaybackClockRate, iOutsideTimebase
                     , iPlaybackDirection, iPlaybackDirection_New));

    // Pause the clock if running. If already stopped or paused, the call would fail
    bool clockpaused = iPlaybackClock.Pause();

    if (iOutsideTimebase)
    {
        //use the outside timebase & ignore the rate.
        iPlaybackClock.SetClockTimebase(*iOutsideTimebase);
    }
    else
    {
        //use the player timebase and set the rate.
        iPlaybackTimebase.SetRate(iPlaybackClockRate);
        iPlaybackClock.SetClockTimebase(iPlaybackTimebase);
    }

    // Only restart the clock if the clock was paused in this function
    if (clockpaused)
    {
        StartPlaybackClock();
    }
}

void PVPlayerEngine::HandleSinkNodeQueryInterfaceMandatory(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceMandatory() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceMandatory() In"));

    switch (aNodeResp.GetCmdStatus())
    {
        case PVMFSuccess:
        {
            if (aNodeContext.iEngineDatapath->iSinkNodePVInterfaceCapConfig)
            {
                aNodeContext.iEngineDatapath->iSinkNodeCapConfigIF = (PvmiCapabilityAndConfig*)aNodeContext.iEngineDatapath->iSinkNodePVInterfaceCapConfig;
                aNodeContext.iEngineDatapath->iSinkNodePVInterfaceCapConfig = NULL;
            }
            else if (aNodeContext.iEngineDatapath->iSinkNodePVInterfaceSyncCtrl)
            {
                aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF = (PvmfNodesSyncControlInterface*)aNodeContext.iEngineDatapath->iSinkNodePVInterfaceSyncCtrl;
                aNodeContext.iEngineDatapath->iSinkNodePVInterfaceSyncCtrl = NULL;

                // Pass the playback clock to the sync control
                aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF->SetClock(&iPlaybackClock);

                // Set the sync margin, find corresponding track for the datapath using mime string
                bool videoTrack = false;
                bool audioTrack = false;
                bool textTrack = false;
                bool retVal = FindTrackForDatapathUsingMimeString(videoTrack, audioTrack, textTrack, aNodeContext.iEngineDatapath);
                if (textTrack && retVal)
                {
                    // Text track
                    aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF->SetMargins((-1*iSyncMarginText.min), iSyncMarginText.max);
                }
                else if (audioTrack && retVal)
                {
                    // Audio track
                    aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF->SetMargins((-1*iSyncMarginAudio.min), iSyncMarginAudio.max);
                }
                else
                {
                    // Video track available or an unknown datapath
                }
            }
        }
        break;

        default:
        {
            if (aNodeContext.iNode == aNodeContext.iEngineDatapath->iSinkNode)
            {
                aNodeContext.iEngineDatapath->iSinkNodePVInterfaceCapConfig = NULL;
                aNodeContext.iEngineDatapath->iSinkNodeCapConfigIF = NULL;
            }
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceMandatory() Node dont support Cap-Config Interface, ignoring"));
        }
        break;
    }

    // Decrement the pending counter and go to next step if 0.
    --iNumPendingNodeCmd;
    if (iNumPendingNodeCmd == 0)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                        (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceMandatory() All QueryInterface() commands complete"));

        PVMFStatus cmdstatus = DoSinkNodeInit(aNodeContext.iCmdId, aNodeContext.iCmdContext);
        if (cmdstatus != PVMFSuccess)
        {
            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, cmdstatus, NULL);
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceMandatory() Out"));
}

void PVPlayerEngine::HandleSinkNodeInit(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    OSCL_UNUSED_ARG(aNodeContext);
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVPlayerEngine::HandleSinkNodeInit() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeInit() In"));

    if (aNodeResp.GetCmdStatus() != PVMFSuccess)
    {
        PVMFErrorInfoMessageInterface* nextmsg = NULL;
        if (aNodeResp.GetEventExtensionInterface())
        {
            nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
        }
        PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
        PVMFBasicErrorInfoMessage *errMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSinkInit, puuid, nextmsg));
        AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, aNodeResp.GetCmdStatus(), errMsg);
        return;
    }

    // Decrement the pending counter and go to next step if 0.
    --iNumPendingNodeCmd;
    if (iNumPendingNodeCmd == 0)
    {
        // Init on sink nodes is complete, next step in track selection is to check with the sink nodes alone if the track is
        // playable or not. If track can be played using sink nodes only move to track selection or else go further to
        // instantiate decoder nodes for the tracks.

        // set the Engine state to Track selection so that engine calls DoPrepare and do further processing in Track selection

        SetEngineState(PVP_ENGINE_STATE_TRACK_SELECTION_1_DONE);
        RunIfNotReady();
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeInit() Out"));

    return;
}

void PVPlayerEngine::HandleDecNodeQueryCapConfigIF(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVPlayerEngine::HandleDecNodeQueryCapConfigIF() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeQueryCapConfigIF() In"));

    for (uint32 i = 0; i < iTrackSelectionList.size(); i++)
    {
        switch (aNodeResp.GetCmdStatus())
        {
            case PVMFSuccess:
            {
                if (aNodeContext.iNode == iTrackSelectionList[i].iTsDecNode && iTrackSelectionList[i].iTsDecNodePVInterfaceCapConfig)
                {
                    iTrackSelectionList[i].iTsDecNodeCapConfigIF = (PvmiCapabilityAndConfig*)iTrackSelectionList[i].iTsDecNodePVInterfaceCapConfig;
                    iTrackSelectionList[i].iTsDecNodePVInterfaceCapConfig = NULL;

                    PVMFTrackInfo* currTrack = iSourcePresInfoList.getTrackInfo(i);
                    // Valid decoder node set in TrackSelectionList. Scan the TrackSelectionList further and if
                    // any similar MIME track is present just set the decoders to NULL for now.
                    // This is to avoid multiple Init calls on same decoder nodes for similar tracks.
                    // Set the decoder nodes and its cap and config I/F once decoder node Inits complete.
                    for (uint32 j = i + 1; j < iTrackSelectionList.size(); j++)
                    {
                        PVMFTrackInfo* tmpTrack = iSourcePresInfoList.getTrackInfo(j);
                        if (!(pv_mime_strcmp(currTrack->getTrackMimeType().get_str(), tmpTrack->getTrackMimeType().get_str())))
                        {
                            // These were earlier set in DoDecNodeQueryCapConfifIF to avoid multiple creation of same
                            // decoder nodes.
                            iTrackSelectionList[j].iTsDecNode = NULL;
                            iTrackSelectionList[j].iTsDecNodeSessionId = 0;
                            iTrackSelectionList[j].iTsDecNodeCapConfigIF = NULL;
                        }
                    }
                }
            }
            break;

            default:
            {
                if (aNodeContext.iNode == iTrackSelectionList[i].iTsDecNode)
                {
                    iTrackSelectionList[i].iTsDecNodePVInterfaceCapConfig = NULL;
                    iTrackSelectionList[i].iTsDecNodeCapConfigIF = NULL;
                }
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "PVPlayerEngine::HandleDecNodeQueryCapConfigIF() Node dont support Cap-Config Interface, ignoring"));
            }
            break;
        }
    }

    // Decrement the pending counter and go to next step if 0.
    --iNumPendingNodeCmd;
    if (iNumPendingNodeCmd == 0)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                        (0, "PVPlayerEngine::HandleDecNodeQueryCapConfigIF() All QueryInterface() commands complete"));

        PVMFStatus cmdstatus = DoDecNodeInit(aNodeContext.iCmdId, aNodeContext.iCmdContext);
        if (cmdstatus != PVMFSuccess)
        {
            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, cmdstatus, NULL);
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeQueryCapConfigIF() Out"));
}

void PVPlayerEngine::HandleDecNodeInit(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    OSCL_UNUSED_ARG(aNodeContext);
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVPlayerEngine::HandleDecNodeInit() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeInit() In"));

    if (aNodeResp.GetCmdStatus() != PVMFSuccess)
    {
        PVMFErrorInfoMessageInterface* nextmsg = NULL;
        if (aNodeResp.GetEventExtensionInterface())
        {
            nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
        }

        PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
        PVMFBasicErrorInfoMessage *errMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapath, puuid, nextmsg));
        AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, aNodeResp.GetCmdStatus(), errMsg);
        return;
    }

    // Decrement the pending counter and go to next step if 0.
    --iNumPendingNodeCmd;
    if (iNumPendingNodeCmd == 0)
    {
        // All decoder node Init is complete, now set the decoder node for similar tracks in TrackSelectionList.
        for (uint32 i = 0; i < iTrackSelectionList.size(); i++)
        {
            PVMFTrackInfo* currTrack = iSourcePresInfoList.getTrackInfo(i);

            for (uint32 j = i + 1; j < iTrackSelectionList.size(); j++)
            {
                // If the track has the same MIME type and needs to have a decoder node for it to be playabale track
                // use the already created decoder node for the track.
                PVMFTrackInfo* tmpTrack = iSourcePresInfoList.getTrackInfo(j);

                if ((iTrackSelectionList[i].iTsDecNode != NULL) &&
                        !(pv_mime_strcmp(currTrack->getTrackMimeType().get_str(), tmpTrack->getTrackMimeType().get_str())) &&
                        !(iTrackSelectionList[j].iTsTrackValidForPlayableList))
                {
                    // These were earlier set in DoDecNodeQueryCapConfifIF to avoid multiple creation of same
                    // decoder nodes.
                    iTrackSelectionList[j].iTsDecNode = iTrackSelectionList[i].iTsDecNode;
                    iTrackSelectionList[j].iTsDecNodeSessionId = iTrackSelectionList[i].iTsDecNodeSessionId;
                    iTrackSelectionList[j].iTsDecNodeCapConfigIF = iTrackSelectionList[i].iTsDecNodeCapConfigIF;
                }
            }
        }

        // Now engine has all decoder and sink nodes setup for each valid track. Engine will now do the track selection based
        // on config paramters of each track

        SetEngineState(PVP_ENGINE_STATE_TRACK_SELECTION_2_DONE);
        RunIfNotReady();
    }
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeInit() Out"));
    return;
}

void PVPlayerEngine::HandleSourceNodePrepare(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::HandleSourceNodePrepare() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodePrepare() In"));

    PVMFStatus cmdstatus = PVMFErrNotSupported;

    switch (aNodeResp.GetCmdStatus())
    {
        case PVMFSuccess:
        {
            // Datapaths are already set during intelligent track selection, just query for optional interfaces.
            iNumPendingDatapathCmd = 0;
            for (uint32 i = 0; i < iDatapathList.size(); ++i)
            {
                if (iDatapathList[i].iTrackInfo != NULL)
                {
                    PVMFStatus retcode = DoSinkNodeQueryInterfaceOptional(iDatapathList[i], aNodeContext.iCmdId, aNodeContext.iCmdContext);
                    if (retcode == PVMFSuccess)
                    {
                        ++iNumPendingDatapathCmd;
                        cmdstatus = PVMFSuccess;
                    }
                    else
                    {
                        cmdstatus = retcode;
                    }
                }
            }

            if (iNumPendingDatapathCmd == 0)
            {
                if (cmdstatus == PVMFErrNotSupported)
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodePrepare() No datapath could be setup. Asserting"));
                    OSCL_ASSERT(false);
                }
                AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, cmdstatus, NULL);
            }
        }
        break;

        default:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleSourceNodePrepare() failed, Add EH Command"));
            PVMFErrorInfoMessageInterface* nextmsg = NULL;
            if (aNodeResp.GetEventExtensionInterface())
            {
                nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
            }

            PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
            PVMFBasicErrorInfoMessage *errMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg));
            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, aNodeResp.GetCmdStatus(), errMsg);
        }
        break;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodePrepare() Out"));
}

void PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional() In %s", aNodeContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr()));

    // Currently, there is only one optional interface.
    OSCL_ASSERT(aNodeContext.iCmdType == PVP_CMD_SinkNodeQueryMetadataIF);
    if (aNodeResp.GetCmdStatus() == PVMFSuccess && aNodeContext.iEngineDatapath->iSinkNodePVInterfaceMetadataExt)
    {
        aNodeContext.iEngineDatapath->iSinkNodeMetadataExtIF = (PVMFMetadataExtensionInterface*)aNodeContext.iEngineDatapath->iSinkNodePVInterfaceMetadataExt;
        aNodeContext.iEngineDatapath->iSinkNodePVInterfaceMetadataExt = NULL;

        // Add the video sink node's metadata extension IF to the list
        if (AddToMetadataInterfaceList(aNodeContext.iEngineDatapath->iSinkNodeMetadataExtIF, aNodeContext.iEngineDatapath->iSinkNodeSessionId, aNodeContext.iEngineDatapath, aNodeContext.iEngineDatapath->iSinkNode) != PVMFSuccess)
        {
            aNodeContext.iEngineDatapath->iSinkNodeMetadataExtIF->removeRef();
            aNodeContext.iEngineDatapath->iSinkNodeMetadataExtIF = NULL;
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional() Metadata IF could not be added to list"));
        }
    }
    else
    {
        // Metadata is not available in this video sink node
        aNodeContext.iEngineDatapath->iSinkNodePVInterfaceMetadataExt = NULL;
        aNodeContext.iEngineDatapath->iSinkNodeMetadataExtIF = NULL;
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional() Metadata IF not available"));
    }

    // Decrement the pending counter and go to next step if 0.
    --aNodeContext.iEngineDatapath->iNumPendingCmd;
    if (aNodeContext.iEngineDatapath->iNumPendingCmd == 0)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional() All QueryInterface() commands complete"));

        // Create the decoder node if necessary
        PVMFStatus cmdstatus = DoDecNodeQueryInterfaceOptional(*(aNodeContext.iEngineDatapath), aNodeContext.iCmdId, aNodeContext.iCmdContext);
        if (cmdstatus == PVMFErrNotSupported)
        {
            cmdstatus = DoDatapathPrepare(*(aNodeContext.iEngineDatapath), aNodeContext.iCmdId, aNodeContext.iCmdContext);
        }

        if (cmdstatus != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional() Report command as failed, Add EH Command"));
            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, cmdstatus, NULL);
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional() Out"));
}

void PVPlayerEngine::HandleSinkNodeDecNodeReset(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    OSCL_UNUSED_ARG(aNodeContext);
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVPlayerEngine::HandleSinkNodeDecNodeReset() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeDecNodeReset() In"));

    if (aNodeResp.GetCmdStatus() != PVMFSuccess)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::HandleSinkNodeDecNodeReset() Reset failed, assert"));
        OSCL_ASSERT(false);
        return;
    }

    // Decrement the pending counter and go to next step if 0.
    --iNumPendingNodeCmd;
    if (iNumPendingNodeCmd == 0)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeDecNodeReset() All Sinknode and decnode Reset() commands complete"));
        SetEngineState(PVP_ENGINE_STATE_TRACK_SELECTION_3_DONE);
        RunIfNotReady();
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeDecNodeReset() Out"));
}

void PVPlayerEngine::HandleDecNodeQueryInterfaceOptional(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() Tick=%d", OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() In %s", aNodeContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr()));

    // Determine QueryInterface() for which interface completed
    if (aNodeContext.iCmdType == PVP_CMD_DecNodeQueryMetadataIF)
    {
        if (aNodeResp.GetCmdStatus() == PVMFSuccess && aNodeContext.iEngineDatapath->iDecNodePVInterfaceMetadataExt)
        {
            aNodeContext.iEngineDatapath->iDecNodeMetadataExtIF = (PVMFMetadataExtensionInterface*)aNodeContext.iEngineDatapath->iDecNodePVInterfaceMetadataExt;
            aNodeContext.iEngineDatapath->iDecNodePVInterfaceMetadataExt = NULL;

            // Add the video dec node's metadata extension IF to the list
            if (AddToMetadataInterfaceList(aNodeContext.iEngineDatapath->iDecNodeMetadataExtIF, aNodeContext.iEngineDatapath->iDecNodeSessionId, aNodeContext.iEngineDatapath, aNodeContext.iEngineDatapath->iDecNode) != PVMFSuccess)
            {
                aNodeContext.iEngineDatapath->iDecNodeMetadataExtIF->removeRef();
                aNodeContext.iEngineDatapath->iDecNodeMetadataExtIF = NULL;

                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() Metadata IF could not be added to list"));
            }
        }
        else
        {
            // Metadata is not available in this dec node
            aNodeContext.iEngineDatapath->iDecNodePVInterfaceMetadataExt = NULL;
            aNodeContext.iEngineDatapath->iDecNodeMetadataExtIF = NULL;
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() Metadata IF not available"));
        }
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() Unknown cmd type. Asserting"));
        OSCL_ASSERT(false);
    }

    if (aNodeContext.iEngineDatapath->iDecNodeCapConfigIF)
    {
        // Configure the dec node for player use
        PvmiKvp kvpparam;
        PvmiKvp* retkvp = NULL;
        OSCL_StackString<64> kvpparamkey;

        bool videoTrack = false;
        bool audioTrack = false;
        bool textTrack = false;
        bool retVal = FindTrackForDatapathUsingMimeString(videoTrack, audioTrack, textTrack, aNodeContext.iEngineDatapath);
        if (videoTrack && retVal)
        {
            // Video track
            // Disable drop frame mode
            kvpparamkey = _STRLIT_CHAR("x-pvmf/video/decoder/dropframe_enable;valtype=bool");
            kvpparam.value.bool_value = false;
        }
        else if (audioTrack && retVal)
        {
            // Audio track
            // Enable/Disable silence insertion
            kvpparamkey = _STRLIT_CHAR(PVMF_AUDIO_SILENCE_INSERTION_KEY);
            kvpparam.value.bool_value = iSilenceInsertionEnable;
            aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF->SetMargins((-1*iSyncMarginAudio.min), iSyncMarginAudio.max);
        }

        if (kvpparamkey.get_size() > 0)
        {
            kvpparam.key = kvpparamkey.get_str();
            aNodeContext.iEngineDatapath->iDecNodeCapConfigIF->setParametersSync(NULL, &kvpparam, 1, retkvp);
            if (retkvp != NULL)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() Configuring dec node for player use via cap-config IF failed"));
            }
        }
    }

    // Decrement the pending counter and go to next step if 0.
    OSCL_ASSERT(aNodeContext.iEngineDatapath->iNumPendingCmd > 0);
    --aNodeContext.iEngineDatapath->iNumPendingCmd;
    if (aNodeContext.iEngineDatapath->iNumPendingCmd == 0)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() All QueryInterface() commands complete"));

        // Prepare the datapath
        PVMFStatus cmdstatus = DoDatapathPrepare(*(aNodeContext.iEngineDatapath), aNodeContext.iCmdId, aNodeContext.iCmdContext);

        if (cmdstatus != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() Report command as failed, Add EH command"));
            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, cmdstatus, NULL);
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() Out"));
}


void PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() In"));

    PVMFTimestamp requesttime = iTargetNPT;

    if (aNodeResp.GetCmdStatus() == PVMFErrNotSupported || aNodeResp.GetCmdStatus() == PVMFErrArgument)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() QueryDataSourcePosition failed. Assume position goes to requested position"));
    }
    else if (aNodeResp.GetCmdStatus() != PVMFSuccess)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() QueryDataSourcePosition failed, Add EH command"));
        PVMFErrorInfoMessageInterface* nextmsg = NULL;
        if (aNodeResp.GetEventExtensionInterface())
        {
            nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
        }

        PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
        PVMFBasicErrorInfoMessage *errMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg));
        if (iState == PVP_ENGINE_STATE_PREPARING)
            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, aNodeResp.GetCmdStatus(), errMsg);
        else if (iState == PVP_ENGINE_STATE_RESUMING)
            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME, aNodeResp.GetCmdStatus(), errMsg);
        return;
    }
    else
    {
        PVMFNodeCapability nodeCapability;
        iSourceNode->GetCapability(nodeCapability);
        PVMFFormatType * formatType = nodeCapability.iInputFormatCapability.begin();
        bool mpeg4FormatType = false;
        if (formatType != NULL)
        {
            if ((pv_mime_strcmp((char*)formatType->getMIMEStrPtr(), PVMF_MIME_MPEG4FF)) == 0)
            {
                mpeg4FormatType = true;
            }
            else
            {
                mpeg4FormatType = false;
            }
        }

        if (mpeg4FormatType)
        {
            // Every thing is OK.. Calculate the modified target position depending upon nearest before and after syncPoints.
            // For MPEG4 files
            CalculateActualPlaybackPosition();
        }
    }

    // Determine the SetDataSourcePosition parameter based on query result and reposition settings
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,
                    "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition()"
                    "Requested NPT %d, Modified Target NPT %d", requesttime, iTargetNPT));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0,
                    "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition()"
                    "Requested NPT %d, Modified Target NPT %d", requesttime, iTargetNPT));

    uint32 startOfSeekWindow = 0;
    if (requesttime > iSyncPointSeekWindow)
    {
        startOfSeekWindow = (requesttime - iSyncPointSeekWindow);
    }
    uint32 endOfSeekWindow = requesttime + iSyncPointSeekWindow;

    // 1) Check if the modified target position falls within the window
    if ((iTargetNPT >= startOfSeekWindow) &&
            (iTargetNPT <= endOfSeekWindow))
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0,
                        "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() - "
                        "RequestedNPT(%d) ModifiedTargetNPT(%d) is in the window (%d, %d), Seeking To %d",
                        requesttime, iTargetNPT, startOfSeekWindow, endOfSeekWindow, iTargetNPT));

        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0,
                        "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() - "
                        "RequestedNPT(%d) ModifiedTargetNPT(%d) is in the window (%d, %d), Seeking To %d",
                        requesttime, iTargetNPT, startOfSeekWindow, endOfSeekWindow, iTargetNPT));

        requesttime = iTargetNPT;
    }
    else
    {
        // 1) Check if the actual seek point is before the window start, then set the
        // request time to start of the window
        // 2) Check if the actual seek point is after the window end, then
        // go back to start of the seek window
        // SFR is not really an option here since we are not playing yet, therefore always
        // go to start of the window
        if ((iTargetNPT < startOfSeekWindow) ||
                (iTargetNPT > endOfSeekWindow))
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0,
                            "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() - "
                            "RequestedNPT(%d) ModifiedTargetNPT(%d) is outside the window (%d, %d), Seeking To %d Seek-To-SyncPt False",
                            requesttime, iTargetNPT, startOfSeekWindow, endOfSeekWindow, startOfSeekWindow));

            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0,
                            "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() - "
                            "RequestedNPT(%d) ModifiedTargetNPT(%d) is outside the window (%d, %d), Seeking To %d Seek-To-SyncPt False",
                            requesttime, iTargetNPT, startOfSeekWindow, endOfSeekWindow, startOfSeekWindow));

            requesttime = startOfSeekWindow;
            iTargetNPT = requesttime;
        }
        else
        {
            //error
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0,
                            "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() - "
                            "RequestedNPT(%d) ModifiedTargetNPT(%d) window (%d, %d), Error Condition Asserting",
                            requesttime, iTargetNPT, startOfSeekWindow, endOfSeekWindow));
            OSCL_ASSERT(false);
        }
    }

    // Do the source positioning
    PVMFStatus retval = DoSourceNodeSetDataSourcePosition(aNodeContext.iCmdId, aNodeContext.iCmdContext);
    if (retval != PVMFSuccess)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() Report command as failed, Add EH command"));
        if (iState == PVP_ENGINE_STATE_PREPARING)
            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, retval, NULL);
        else if (iState == PVP_ENGINE_STATE_RESUMING)
            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME, retval, NULL);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() Out"));
}


void PVPlayerEngine::HandleSourceNodeSetDataSourcePosition(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() In"));

    PVMFStatus cmdstatus = PVMFFailure;

    switch (aNodeResp.GetCmdStatus())
    {
        case PVMFErrArgument:
        case PVMFErrNotSupported:
        {
            if (iChangePlaybackPositionWhenResuming)
            {
                PVPPlaybackPosition curpos;
                curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC;
                GetPlaybackClockPosition(curpos);
                uint32 clockcurpos = 0;
                bool tmpbool = false;
                iPlaybackClock.GetCurrentTime32(clockcurpos, tmpbool, PVMF_MEDIA_CLOCK_MSEC);

                // since repositioning is not supported and if the playback position change request was
                // issued during paused state, then continue from paused position.
                iChangePlaybackPositionWhenResuming = false;
                iWatchDogTimerInterval = 0;
                iActualNPT = curpos.iPosValue.millisec_value;
                iActualMediaDataTS = clockcurpos;
                iSkipMediaDataTS = clockcurpos;

                iStartNPT = iActualNPT;
                iStartMediaDataTS = iSkipMediaDataTS;
                iPlaybackClock.UpdateNPTClockPosition(iStartNPT, (iPlaybackDirection < 0) ? true : false);
                // also decrement the stream id as no skip will be called on MIO node.
                --iStreamID;

                PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
                PVMFBasicErrorInfoMessage* infomsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoChangePlaybackPositionNotSupported, puuid, NULL));
                SendInformationalEvent(PVMFInfoChangePlaybackPositionNotSupported, OSCL_STATIC_CAST(PVInterface*, infomsg));
                infomsg->removeRef();
            }
            else
            {
                // This happens when we are in preparing state
                // Since this repositioning was not supported, assume the playback
                // will start from time 0
                iWatchDogTimerInterval = 0;
                iActualNPT = 0;
                iActualMediaDataTS = 0;
                iSkipMediaDataTS = 0;
                // Then continue to handle like success case
                iStartNPT = 0;
                iStartMediaDataTS = 0;
                iPlaybackClock.UpdateNPTClockPosition(iStartNPT, (iPlaybackDirection < 0) ? true : false);
            }

            // Save the actual starting position for GetPlaybackRange() query
            iTargetNPT = iActualNPT;
            iCurrentBeginPosition.iPosValue.millisec_value = iActualNPT;
            iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() Requested begin position(%d ms) is not supported so start from prev location.",
                             iTargetNPT));
        }
        break;

        case PVMFSuccess:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                            (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() SetDataSourcePosition() successful. StartMediaTS %d ms, ActualNPT %d ms, TargetNPT %d ms",
                             iActualMediaDataTS, iActualNPT, iTargetNPT));
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                            (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() SetDataSourcePosition() successful. StartMediaTS %d ms, ActualNPT %d ms, TargetNPT %d ms",
                             iActualMediaDataTS, iActualNPT, iTargetNPT));
            // Compute the difference between actualNPT and targetNPT before any adjustments
            if (iTargetNPT >= iActualNPT)
            {
                iWatchDogTimerInterval = iTargetNPT - iActualNPT;
            }

            // Determine if adjustment needed to skip to requested time
            if (iSkipToRequestedPosition && (iActualNPT < iTargetNPT))
            {
                if (iTargetNPT - iActualNPT > iNodeDataQueuingTimeout)
                {
                    // Sync point seems to be far away in the stream
                    // Can't adjust the skip time back so use the returned values to skip to
                    iSkipMediaDataTS = iActualMediaDataTS;
                    iTargetNPT = iActualNPT;
                    iWatchDogTimerInterval = 0;
                    iCurrentBeginPosition.iPosValue.millisec_value = iActualNPT;
                }
                else
                {
                    //check if source node wants to override
                    uint32 startNPTFrmSource = iActualNPT;
                    if (iSourceNodePBCtrlIF->ComputeSkipTimeStamp(iTargetNPT,
                            iActualNPT,
                            iActualMediaDataTS,
                            iSkipMediaDataTS,
                            startNPTFrmSource) == PVMFSuccess)
                    {
                        iWatchDogTimerInterval = startNPTFrmSource - iActualNPT;
                        iActualNPT = startNPTFrmSource;
                        iTargetNPT = iActualNPT;
                        iCurrentBeginPosition.iPosValue.millisec_value = iActualNPT;
                    }
                    else
                    {
                        // Adjust the media data time to skip-to to correspond to the requested time
                        // Add the difference of target NPT with actual playback position in NPT to the actual media data time to get time to skip to.
                        iSkipMediaDataTS = iActualMediaDataTS + (iTargetNPT - iActualNPT);
                        iActualNPT = iTargetNPT;
                    }
                }
            }
            else
            {
                // Can't adjust the skip time back so use the returned values to skip to
                iSkipMediaDataTS = iActualMediaDataTS;
                iTargetNPT = iActualNPT;
                iCurrentBeginPosition.iPosValue.millisec_value = iActualNPT;
                iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;
                iWatchDogTimerInterval = 0;
            }

            // Save initial NTP and TS values
            iStartNPT = iActualNPT;
            iStartMediaDataTS = iSkipMediaDataTS;
            iPlaybackClock.UpdateNPTClockPosition(iStartNPT, (iPlaybackDirection < 0) ? true : false);

            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                            (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() After adjustment StartMediaTS %d ms, AdjustedMediaTS %d ms, ActualPBPos %d ms Start NPT %d Start TS %d",
                             iActualMediaDataTS, iSkipMediaDataTS, iActualNPT, iStartNPT, iStartMediaDataTS));
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                            (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() After adjustment StartMediaTS %d ms, AdjustedMediaTS %d ms, ActualNPT %d ms StartNPT %d StartTS %d",
                             iActualMediaDataTS, iSkipMediaDataTS, iActualNPT, iStartNPT, iStartMediaDataTS));
        }
        break;

        default:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() failed, Add EH command"));
            PVMFErrorInfoMessageInterface* nextmsg = NULL;
            if (aNodeResp.GetEventExtensionInterface())
            {
                nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
            }
            PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
            PVMFBasicErrorInfoMessage* errMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg));

            if (iState == PVP_ENGINE_STATE_PREPARING)
                AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, aNodeResp.GetCmdStatus(), errMsg);
            else if (iState == PVP_ENGINE_STATE_RESUMING)
                AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME, aNodeResp.GetCmdStatus(), errMsg);

            return;
        }
    }
    // Repositioning so reset the EOS flag for each active datapath
    for (uint32 i = 0; i < iDatapathList.size(); ++i)
    {
        if (iDatapathList[i].iDatapath)
        {
            iDatapathList[i].iEndOfDataReceived = false;
        }
    }

    // Contine on and start the source node
    cmdstatus = DoSourceNodeStart(aNodeContext.iCmdId, aNodeContext.iCmdContext);
    if (cmdstatus != PVMFSuccess)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() Report command as failed, Add EH command"));
        if (iState == PVP_ENGINE_STATE_PREPARING)
            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, cmdstatus, NULL);
        else if (iState == PVP_ENGINE_STATE_RESUMING)
            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME, cmdstatus, NULL);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() Out"));
}

void PVPlayerEngine::HandleSourceNodeSetDataSourceDirection(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() In"));

    if (iChangePlaybackDirectionWhenResuming)
    {
        // Continuation of Engine Resume sequence.

        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Context RESUME"));
        PVMFStatus cmdstatus = PVMFFailure;

        switch (aNodeResp.GetCmdStatus())
        {
            case PVMFErrArgument:
            case PVMFErrNotSupported:
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Requested direction is not supported!"));
                PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
                PVMFBasicErrorInfoMessage* infomsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoChangePlaybackPositionNotSupported, puuid, NULL));
                SendInformationalEvent(PVMFInfoChangePlaybackPositionNotSupported, OSCL_STATIC_CAST(PVInterface*, infomsg));
                infomsg->removeRef();
            }
            break;

            case PVMFSuccess:
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                                (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() SetDataSourceDirection() successful. StartMediaTS %d ms, ActualPBPos %d ms",
                                 iActualMediaDataTS, iActualNPT));

                //there's no adjustment to the media TS here.
                iSkipMediaDataTS = iActualMediaDataTS;
                iCurrentBeginPosition.iPosValue.millisec_value = iActualNPT;
                iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;

                //Install the new direction and get the repositioning target.
                UpdateDirection(iActualNPT, iSkipMediaDataTS, iChangeDirectionNPT);

                //Reposition the source to the desired playback time
                if (!iChangeDirectionNPT.iIndeterminate)
                {
                    iChangePlaybackDirectionWhenResuming = false;
                    iChangePlaybackPositionWhenResuming = true;
                    PVPlayerEngineCommand cmd(0, aNodeContext.iCmdId, aNodeContext.iCmdContext, NULL, false);
                    iCurrentBeginPosition = iChangeDirectionNPT;
                    PVMFStatus retval = UpdateCurrentBeginPosition(iCurrentBeginPosition, cmd);
                    if (retval == PVMFPending)
                    {
                        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Repos to %d started", iChangeDirectionNPT.iPosValue));
                        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Out"));
                        return;//wait on the repos sequence...
                    }
                    else if (retval != PVMFSuccess)
                    {
                        //else can't reposition, ignore failure and continue.
                        iChangeDirectionNPT.iIndeterminate = true;
                        iChangePlaybackPositionWhenResuming = false;
                        //need to leave the flag set for later in HandleDatapathResume,
                        //to trigger the skip media data.
                        iChangePlaybackDirectionWhenResuming = true;
                    }
                }
            }
            break;

            default:
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() failed, Add EH command"));
                PVMFErrorInfoMessageInterface* nextmsg = NULL;
                if (aNodeResp.GetEventExtensionInterface())
                {
                    nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
                }

                PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
                PVMFBasicErrorInfoMessage *errMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg));
                AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME, aNodeResp.GetCmdStatus(), errMsg);
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Out"));
                return;
            }
        }


        // Repositioning so reset the EOS flag for each active datapath
        for (uint32 i = 0; i < iDatapathList.size(); ++i)
        {
            if (iDatapathList[i].iDatapath)
            {
                iDatapathList[i].iEndOfDataReceived = false;
            }
        }

        // Start the source node.
        cmdstatus = DoSourceNodeStart(aNodeContext.iCmdId, aNodeContext.iCmdContext);
        if (cmdstatus != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() Report command as failed, Add EH command"));
            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME, cmdstatus, NULL);
        }
    }
    else
    {
        //Continuation of SetPlaybackRate sequence.

        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Context SETPLAYBACKRATE"));

        if (aNodeResp.GetCmdStatus() != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() SetDataSourceDirection failed. Playback position change has been cancelled"));

            if (aNodeResp.GetCmdStatus() == PVMFErrNotSupported || aNodeResp.GetCmdStatus() == PVMFErrArgument)
            {
                // For non-fatal error, continue playback by resuming the clock
                StartPlaybackClock();
            }
            else
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() failed, Add EH command"));
                // Initiate error handling
                PVMFErrorInfoMessageInterface* nextmsg = NULL;
                if (aNodeResp.GetEventExtensionInterface())
                {
                    nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
                }

                PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
                PVMFBasicErrorInfoMessage *errMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg));
                AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_SET_PLAYBACK_RATE, aNodeResp.GetCmdStatus(), errMsg);
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Out"));
                return;
            }

            PVMFErrorInfoMessageInterface* nextmsg = NULL;
            if (aNodeResp.GetEventExtensionInterface() != NULL)
            {
                nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
            }
            PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
            PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSource, puuid, nextmsg));

            // Complete the SetPlaybackRate() command as failed
            EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, aNodeResp.GetCmdStatus(), OSCL_STATIC_CAST(PVInterface*, errmsg));

            errmsg->removeRef();
            errmsg = NULL;
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Out"));
            return;
        }

        // no adjustement here.
        iSkipMediaDataTS = iActualMediaDataTS;
        iCurrentBeginPosition.iPosValue.millisec_value = iActualNPT;
        iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;

        //Install the new direction and get the repositioning target
        UpdateDirection(iActualNPT, iSkipMediaDataTS, iChangeDirectionNPT);

        //Launch a repositioning sequence now.
        if (!iChangeDirectionNPT.iIndeterminate)
        {
            PVPlayerEngineCommand cmd(0, aNodeContext.iCmdId, aNodeContext.iCmdContext, NULL, false);
            iCurrentBeginPosition = iChangeDirectionNPT;
            PVMFStatus retval = UpdateCurrentBeginPosition(iCurrentBeginPosition, cmd);
            if (retval == PVMFPending)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Repos to %d started", iChangeDirectionNPT.iPosValue));
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Out"));
                return;//wait on the repos sequence...
            }
            else if (retval != PVMFSuccess)
            {
                //the direction is already changed, so just ignore this failure and continue
                iChangeDirectionNPT.iIndeterminate = true;
            }
        }

        // Repositioning so reset the EOS flag for each active datapath
        for (uint32 i = 0; i < iDatapathList.size(); ++i)
        {
            if (iDatapathList[i].iDatapath)
            {
                iDatapathList[i].iEndOfDataReceived = false;
            }
        }

        // Skip to the new source node position, so that all the data that was queued
        // when the command was received will get flushed.

        PVMFStatus retval = DoSinkNodeSkipMediaDataDuringPlayback(aNodeContext.iCmdId, aNodeContext.iCmdContext);
        if (retval != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Skipping media data request in sink nodes failed. Repositioning did not complete."));
            PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
            PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSink, puuid, NULL));

            //clear the pending direction change NPT.
            iChangeDirectionNPT.iIndeterminate = true;

            // Complete the SetPlaybackRate() command as failed
            EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, retval, OSCL_STATIC_CAST(PVInterface*, errmsg));

            errmsg->removeRef();
            errmsg = NULL;
        }
        // else wait on HandleSinkNodeSkipMediaDataDuringPlayback.
    }
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Out"));
}

void PVPlayerEngine::HandleSinkNodeSkipMediaData(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    OSCL_UNUSED_ARG(aNodeContext);
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::HandleSinkNodeSkipMediaData() for %s Tick=%d",
                     aNodeContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::HandleSinkNodeSkipMediaData() for %s, iNumPVMFInfoStartOfDataPending=%d",
                     aNodeContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr(), iNumPVMFInfoStartOfDataPending));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                    (0, "PVPlayerEngine::HandleSinkNodeSkipMediaData() In"));

    --iNumPendingNodeCmd;

    if (aNodeResp.GetCmdStatus() != PVMFSuccess)
    {
        // Sink node report error with SkipMediaData()
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeSkipMediaData() Sink node report error for SkipMediaData(). Asserting"));
        OSCL_ASSERT(false);
    }

    --iNumPendingSkipCompleteEvent;

    if (iNumPendingNodeCmd == 0)
    {
        // We dont start the playback clock here since engine is waiting for Start on Sink nodes to complete
        // This will also check the order in which Sink Node completes the command. Sinks should complete Skip
        // first and then Start, therefore iNumPendingDatapathCmd should always be greater than zero when
        // this happens. If not just assert.
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                        (0, "PVPlayerEngine::HandleSinkNodeSkipMediaData() Skip Complete"));
    }

    if ((iNumPendingSkipCompleteEvent == 0) && (iNumPVMFInfoStartOfDataPending == 0))
    {
        // we have received all the bos event so cancel the watchDogTimer if any.
        if (iWatchDogTimer->IsBusy())
        {
            iWatchDogTimer->Cancel();
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSinkNodeSkipMediaData - WatchDogTimer cancelled"));
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeSkipMediaData() Out"));
}


void PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() In"));

    PVMFTimestamp requesttime = iTargetNPT;
    if (aNodeResp.GetCmdStatus() != PVMFSuccess)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() QueryDataSourcePosition failed. Assume position goes to requested position"));
    }
    else
    {
        PVMFNodeCapability nodeCapability;
        iSourceNode->GetCapability(nodeCapability);
        PVMFFormatType * formatType = nodeCapability.iInputFormatCapability.begin();
        bool mpeg4FormatType = false;
        if (formatType != NULL)
        {
            if ((pv_mime_strcmp((char*)formatType->getMIMEStrPtr(), PVMF_MIME_MPEG4FF)) == 0)
            {
                mpeg4FormatType = true;
            }
            else
            {
                mpeg4FormatType = false;
            }
        }
        if (mpeg4FormatType)
        {
            // Every thing is OK.. Calculate the modified target position depending upon nearest before and after syncPoints.
            // For MPEG4 files
            CalculateActualPlaybackPosition();
        }
    }

    // Determine the SetDataSourcePosition parameter based on query result and reposition settings
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,
                    "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback()"
                    "Requested NPT %d, ModifiedTarget NPT %d", requesttime, iTargetNPT));

    uint32 startOfSeekWindow = 0;
    if (requesttime > iSyncPointSeekWindow)
    {
        startOfSeekWindow = (requesttime - iSyncPointSeekWindow);
    }
    uint32 endOfSeekWindow = requesttime + iSyncPointSeekWindow;

    PVPPlaybackPosition curpos;
    curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC;
    GetPlaybackClockPosition(curpos);
    bool oSFR = false;

    //depending on whether it is fwd or rwnd, the window is different
    //if doing a rwnd, the worst case window is (0, currentplaybackposition)
    //if doing a fwd, the worst case window is (currentplaybackposition, endofclip)
    if (requesttime <= curpos.iPosValue.millisec_value)
    {
        //requested pos <= currpos => rwnd
        //cap end of seek window to be the current play back pos
        endOfSeekWindow = curpos.iPosValue.millisec_value;
    }
    if (requesttime > curpos.iPosValue.millisec_value)
    {
        //requested pos > currpos => fwd
        //cap start of seek window to be the current play back pos
        startOfSeekWindow = curpos.iPosValue.millisec_value;
    }

    // 1) Check if the Modified target position falls within the window
    if ((iTargetNPT >= startOfSeekWindow) &&
            (iTargetNPT <= endOfSeekWindow))
    {
        // Check for SFR
        // In case if actual playback position
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0,
                        "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() - "
                        "RequestedNPT(%d) ModifiedTargetNPT(%d) is in the window (%d, %d), Seeking To %d",
                        requesttime, iTargetNPT, startOfSeekWindow, endOfSeekWindow, iTargetNPT));

        requesttime = iTargetNPT;
    }
    else
    {
        // Check for SFR
        // SFR means currplaybackpos < requestedpos
        if (curpos.iPosValue.millisec_value < requesttime)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0,
                            "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() - "
                            "CurrNPT(%d) less than RequestedNPT(%d) Ignoring ModifiedTargetNPT(%d) and the window (%d, %d), Doing SFR",
                            curpos.iPosValue.millisec_value, requesttime, iTargetNPT, startOfSeekWindow, endOfSeekWindow, startOfSeekWindow));

            oSFR = true;

            PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
            PVMFBasicErrorInfoMessage* infomsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoAttemptingSFRAsPartOfSetPlayBackRange, puuid, NULL));
            SendInformationalEvent(PVMFInfoPositionStatus, OSCL_STATIC_CAST(PVInterface*, infomsg));
            infomsg->removeRef();

        }
        else
        {
            // if the actual seek point is before the window start,
            // or if the actual seek point is after the window end,
            // then go back to start of the seek window only in case of a finite window
            // in case of infinite window just go to the requested position and do normal
            // repositioning
            if (iSyncPointSeekWindow == 0x7FFFFFFF)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0,
                                "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() - "
                                "RequestedNPT(%d) ModifiedTargetNPT(%d) is outside the window (%d, %d), Seeking To %d Seek-To-SyncPt True",
                                requesttime, iTargetNPT, startOfSeekWindow, endOfSeekWindow, startOfSeekWindow));

                iTargetNPT = requesttime;
            }
            else
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0,
                                "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() - "
                                "RequestedNPT(%d) ModifiedTargetNPT(%d) is outside the window (%d, %d), Seeking To %d Seek-To-SyncPt False",
                                requesttime, iTargetNPT, startOfSeekWindow, endOfSeekWindow, startOfSeekWindow));

                requesttime = startOfSeekWindow;
                iTargetNPT = requesttime;
            }
        }
    }

    if (oSFR)
    {
        // No need to change source position so go to skipping at sink nodes
        // First determine to what time sink nodes should skip to
        // Get current playback clock position in media data time
        uint32 clockcurpos = 0;
        bool tmpbool = false;
        iPlaybackClock.GetCurrentTime32(clockcurpos, tmpbool, PVMF_MEDIA_CLOCK_MSEC);

        // for SFR since the source node is bypassed, there will be no frames generated with new
        // Stream ID so, for skip to complete on Sink Node, Stream ID needs to be decremented. As
        // there will be no new Stream in case of SFR.
        --iStreamID;

        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                        (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() New source reposition before current position so no need to change source position."));

        if (iSkipToRequestedPosition)
        {
            // Skip to the requested begin position
            // Add the difference of target NPT with current time in NPT to the current clock to get media data time to skip to.
            iActualMediaDataTS = clockcurpos;
            iSkipMediaDataTS = (requesttime - curpos.iPosValue.millisec_value) + clockcurpos;
            iActualNPT = requesttime;
            iWatchDogTimerInterval = requesttime - curpos.iPosValue.millisec_value;

            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                            (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() Skip-to-requested position SET. ActualNPT=%d, ActualMediaTS=%d, AdjustedMediaTS=%d",
                             iActualNPT, iActualMediaDataTS, iSkipMediaDataTS));
        }
        else
        {
            // Just continue playback from current position
            iActualMediaDataTS = clockcurpos;
            iSkipMediaDataTS = clockcurpos;
            iActualNPT = curpos.iPosValue.millisec_value;
            iWatchDogTimerInterval = 0;

            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                            (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() Skip-to-requested position NOT SET so continue playing. ActualNPT=%d, ActualMediaTS=%d, AdjustedMediaTS=%d",
                             iActualNPT, iActualMediaDataTS, iSkipMediaDataTS));
        }

        PVMFStatus retval = DoSinkNodeSkipMediaDataDuringPlayback(aNodeContext.iCmdId, aNodeContext.iCmdContext, true);
        if (retval != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() Skipping media data request in sink nodes failed. Repositioning did not complete."));
            PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
            PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSink, puuid, NULL));

            //clear the pending direction change NPT.
            iChangeDirectionNPT.iIndeterminate = true;

            // Complete the SetPlaybackRange() command as failed
            EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, retval, OSCL_STATIC_CAST(PVInterface*, errmsg));

            errmsg->removeRef();
            errmsg = NULL;
        }

    }
    else
    {
        // Do the source positioning
        PVMFStatus retval = DoSourceNodeSetDataSourcePositionDuringPlayback(aNodeContext.iCmdId, aNodeContext.iCmdContext);
        if (retval != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() SetDataSourcePosition failed. Playback position change has been cancelled"));
            PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
            PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSource, puuid, NULL));

            // Complete the SetPlaybackRange() command as failed
            EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, retval, OSCL_STATIC_CAST(PVInterface*, errmsg));

            errmsg->removeRef();
            errmsg = NULL;
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() Out"));
}

void PVPlayerEngine::CalculateActualPlaybackPosition()
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::CalculateActualPlaybackPosition In"));

    PVPPlaybackPosition curpos;
    curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC;
    GetPlaybackClockPosition(curpos);

    // Following code has been taken from MP4 parser node, all the vars are kept very near to the MP4 parser node.
    // Previously the calculation of before and after sync point was done in MP4 parser node.

    if (curpos.iPosValue.millisec_value > iTargetNPT)
    {
        // curpos.iPosValue.millisec_value was passed as iActualNPT in QueryDataSourcePosition
        // which became aActualNPT while collection, and used to decide forward and reverse repos.
        iBackwardReposFlag = true;
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::CalculateActualPlaybackPosition In: Backward Reposition"));
    }
    else
    {
        iForwardReposFlag = true;
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::CalculateActualPlaybackPosition In: Forward Reposition"));
    }

    // pick the closest time to targetNPT
    uint32 delta = 0;
    uint32 diffBetSeekPointBeforeAndTarget = 0;
    if (PVTimeComparisonUtils::IsEarlier(iSeekPointBeforeTargetNPT, iTargetNPT, delta))
    {
        // this should always be true when checking the SeekPointBefore with
        // targetNPT.
        diffBetSeekPointBeforeAndTarget = delta;
        delta = 0;
    }
    else
    {
        // this will only happen when mp4ff library returns an SeekPointBefore which
        // is after targetNPT with small delta because of some rounding off error in
        // media clock converter class.
        diffBetSeekPointBeforeAndTarget = delta;
        delta = 0;
    }

    uint32 diffBetSeekPointAfterAndTarget = 0;
    if (PVTimeComparisonUtils::IsEarlier(iTargetNPT, iSeekPointAfterTargetNPT, delta))
    {
        // this should always be true when checking the SeekPointAfter with
        // targetNPT.
        diffBetSeekPointAfterAndTarget = delta;
        delta = 0;
    }
    else
    {
        // this should never happen.
        diffBetSeekPointAfterAndTarget = delta;
        delta = 0;
    }

    // modify the target NPT and set it to the closest I-frame returned by parser node.
    if (diffBetSeekPointAfterAndTarget < diffBetSeekPointBeforeAndTarget)
    {
        iTargetNPT = iSeekPointAfterTargetNPT;
    }
    else
    {
        if (iSeekPointBeforeTargetNPT < curpos.iPosValue.millisec_value && iForwardReposFlag)
        {
            iTargetNPT = iSeekPointAfterTargetNPT;
            iForwardReposFlag = false;
        }
        else
        {
            iTargetNPT = iSeekPointBeforeTargetNPT;
            iForwardReposFlag = false;
        }
    }
    if (iBackwardReposFlag) // To avoid backwardlooping :: A flag to remember backward repositioning
    {
        iTargetNPT = iSeekPointBeforeTargetNPT;
        iBackwardReposFlag = false;
    }


    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,
                    "PVPlayerEngine::CalculateActualPlaybackPosition()"
                    "targetNPT %d Current NPT %d, Modified Target NPT %d, SeekPointBeforeTargetNPT %d, SeekPointAfterTargetNPT %d ",
                    iCurrentBeginPosition.iPosValue.millisec_value, curpos.iPosValue.millisec_value, iTargetNPT, iSeekPointBeforeTargetNPT, iSeekPointAfterTargetNPT));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::CalculateActualPlaybackPosition Out"));
}

void PVPlayerEngine::HandleSourceNodeSetDataSourcePositionDuringPlayback(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePositionDuringPlayback() In"));

    if (aNodeResp.GetCmdStatus() != PVMFSuccess)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePositionDuringPlayback() SetDataSourcePosition failed. Playback position change has been cancelled"));

        if (aNodeResp.GetCmdStatus() == PVMFErrNotSupported || aNodeResp.GetCmdStatus() == PVMFErrArgument)
        {
            PVPPlaybackPosition curpos;
            curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC;
            GetPlaybackClockPosition(curpos);
            uint32 clockcurpos = 0;
            bool tmpbool = false;
            iPlaybackClock.GetCurrentTime32(clockcurpos, tmpbool, PVMF_MEDIA_CLOCK_MSEC);

            // since repositioning is not supported continue playing from current position.
            iWatchDogTimerInterval = 0;
            iActualNPT = curpos.iPosValue.millisec_value;
            iActualMediaDataTS = clockcurpos;
            iSkipMediaDataTS = clockcurpos;

            iStartNPT = iActualNPT;
            iStartMediaDataTS = iSkipMediaDataTS;
            iPlaybackClock.UpdateNPTClockPosition(iStartNPT, (iPlaybackDirection < 0) ? true : false);

            // also decrement the stream id as no skip will be called on MIO node.
            --iStreamID;

            // For non-fatal error, continue playback by resuming the clock
            // Do not start the clock for the usecase: Prepare - SetPlaybackRange - Start
            if ((GetPVPlayerState() == PVP_STATE_STARTED) &&
                    (iNumPVMFInfoStartOfDataPending == 0))
            {
                StartPlaybackClock();
            }
            // Complete the SetPlaybackRange() command as notsupported / failed
            EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, aNodeResp.GetCmdStatus());
        }
        else
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePositionDuringPlayback() failed, Add EH command"));
            PVMFErrorInfoMessageInterface* nextmsg = NULL;
            if (aNodeResp.GetEventExtensionInterface())
            {
                nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
            }
            PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
            PVMFBasicErrorInfoMessage *errMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg));
            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_SET_PLAYBACK_RANGE, aNodeResp.GetCmdStatus(), errMsg);
        }
        return;
    }

    if ((iCurrentBeginPosition.iMode != PVPPBPOS_MODE_END_OF_CURRENT_PLAY_ELEMENT) &&
            (iCurrentBeginPosition.iMode != PVPPBPOS_MODE_END_OF_CURRENT_PLAY_SESSION))
    {
        if (iCurrentBeginPosition.iPosUnit == PVPPBPOSUNIT_PLAYLIST)
        {
            iActualMediaDataTS = iDataSourcePosParams.iActualMediaDataTS;
            iActualNPT = iDataSourcePosParams.iActualNPT;
        }

        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                        (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePositionDuringPlayback() SetDataSourcePosition() successful. StartMediaTS %d ms, ActualPBPos %d ms",
                         iActualMediaDataTS, iActualNPT));

        if (iCurrentBeginPosition.iPosUnit == PVPPBPOSUNIT_PLAYLIST)
        {
            if (iTargetNPT >= iActualNPT)
            {
                iWatchDogTimerInterval = iTargetNPT - iActualNPT;
            }
        }
        // Compute the difference between actualNPT and targetNPT before any adjustments
        else if (iTargetNPT >= iActualNPT)
        {
            iWatchDogTimerInterval = iTargetNPT - iActualNPT;
        }

        //iCurrentBeginPosition.iPosUnit has served its purpose, it is ok if it is overwritten
        if (iSkipToRequestedPosition && (iActualNPT < iTargetNPT))
        {
            if (iTargetNPT - iActualNPT >= iNodeDataQueuingTimeout)
            {
                // Can't adjust the skip time back so use the returned values to skip to
                iSkipMediaDataTS = iActualMediaDataTS;
                iTargetNPT = iActualNPT;
                iWatchDogTimerInterval = 0;
            }
            else
            {
                //check if source node wants to override
                uint32 startNPTFrmSource = iActualNPT;
                if (iSourceNodePBCtrlIF->ComputeSkipTimeStamp(iTargetNPT,
                        iActualNPT,
                        iActualMediaDataTS,
                        iSkipMediaDataTS,
                        startNPTFrmSource) == PVMFSuccess)
                {
                    iWatchDogTimerInterval = startNPTFrmSource - iActualNPT;
                    iActualNPT = startNPTFrmSource;
                }
                else
                {
                    // Adjust the media data time to skip-to to correspond to the requested time
                    // Add the difference of target NPT with actual playback position in NPT to the actual media data time to get time to skip to.
                    iSkipMediaDataTS = iActualMediaDataTS + (iTargetNPT - iActualNPT);
                    // Set the actual playback position to the requested time since actual media data TS was adjusted
                    // This is important since the difference between the two is used to calculate the NPT to media data offset in HandleSinkNodeskipMediaDataDuringPlayback()
                    iActualNPT = iTargetNPT;
                }

            }
            iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;
        }
        else
        {
            // Can't adjust the skip time back so just use the returned values to skip to
            iSkipMediaDataTS = iActualMediaDataTS;
            iTargetNPT = iActualNPT;
            iCurrentBeginPosition.iPosValue.millisec_value = iActualNPT;
            iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;
            iWatchDogTimerInterval = 0;
        }

        uint32 clockcurpos = 0;
        bool tmpbool;
        // Get current playback clock position
        iPlaybackClock.GetCurrentTime32(clockcurpos, tmpbool, PVMF_MEDIA_CLOCK_MSEC);

        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                        (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePositionDuringPlayback() After adjustment StartMediaTS %d ms, AdjustedMediaTS %d ms, ActualPBPos %d ms Clock %d ms",
                         iActualMediaDataTS, iSkipMediaDataTS, iActualNPT, clockcurpos));

        // Repositioning so reset the EOS flag for each active datapath
        for (uint32 i = 0; i < iDatapathList.size(); ++i)
        {
            if (iDatapathList[i].iDatapath)
            {
                iDatapathList[i].iEndOfDataReceived = false;
            }
        }

        PVMFStatus retval = DoSinkNodeSkipMediaDataDuringPlayback(aNodeContext.iCmdId, aNodeContext.iCmdContext);
        if (retval != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePositionDuringPlayback() Skipping media data request in sink nodes failed. Repositioning did not complete."));

            // clear the pending direction change NPT.
            iChangeDirectionNPT.iIndeterminate = true;

            // Complete the SetPlaybackRange() command as failed
            EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, retval);
        }
    }
    else
    {
        PVMFErrorInfoMessageInterface* nextmsg = NULL;
        if (aNodeResp.GetEventExtensionInterface() != NULL)
        {
            nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
        }
        PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
        PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSource, puuid, nextmsg));

        // Complete the SetPlaybackRange() command as Success
        EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, aNodeResp.GetCmdStatus(), OSCL_STATIC_CAST(PVInterface*, errmsg));
        if (errmsg)
        {
            errmsg->removeRef();
            errmsg = NULL;
        }
    }
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePositionDuringPlayback() Out"));
}

void PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() for %s Tick=%d",
                     aNodeContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() for %s, iNumPVMFInfoStartOfDataPending=%d",
                     aNodeContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr(), iNumPVMFInfoStartOfDataPending));

    if (aNodeResp.GetCmdStatus() != PVMFSuccess)
    {
        // Sink node report error with SkipMediaData()
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() Sink node report error for SkipMediaData(). Asserting"));
        OSCL_ASSERT(false);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() In %s", aNodeContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr()));

    // Stop the sink that has reached the skipping end point until other sinks are ready
    if (aNodeContext.iEngineDatapath->iDatapath && aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF)
    {
        aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF->ClockStopped();
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() Datapath does not exist or sync control IF not available."));
    }

    --iNumPendingSkipCompleteEvent;

    --iNumPendingNodeCmd;

    if (iNumPendingNodeCmd == 0)
    {
        // Set the clock to the specified begin time just before Start of playback Clock
        iPlaybackClock.Stop();
        bool overflow = 0;
        iPlaybackClock.SetStartTime32(iSkipMediaDataTS, PVMF_MEDIA_CLOCK_MSEC, overflow);

        if (iOverflowFlag)
        {
            iOverflowFlag = false;
            iActualNPT = iSkipMediaDataTS;
        }
        if ((iNumPVMFInfoStartOfDataPending == 0) &&
                (iState == PVP_ENGINE_STATE_STARTED))
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                            (0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() Skipping WatchDogTimer - Starting PlayBackClock"));
            StartPlaybackClock();
        }
        else
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                            (0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() Setting WatchDogTimer for %d ms, TargetNPT=%d  ActualNPT=%d, if interval zero set to default 1 second",
                             iWatchDogTimerInterval, iTargetNPT, iActualNPT));
            // There can be a case in which WatchDogTimerInterval is zero and iNumPVMFInfoStartOfDataPending is greater than zero.
            // In this case it is possible InfoStartofData is not sent by Sink Nodes for some time and player hangs. To avoid the player hang
            // set the watchdog timer Interval to the default value of 1 second. If interval is 0, it will be set to default 1 second.
            iWatchDogTimer->setTimerDuration(iWatchDogTimerInterval);
            iWatchDogTimer->Start();
        }

        // Set the actual playback position to the requested time since actual media data TS was adjusted
        // This is important since the difference between the two is used to calculate the NPT to media data offset
        // This is not required here as the ActualPlaybackPosition is already adjusted before calling Skip on Sink Node.
        // iActualNPT=iCurrentBeginPosition.iPosValue.millisec_value;

        //clear the pending direction change NPT.
        iChangeDirectionNPT.iIndeterminate = true;
        // Save the start NPT and TS
        iStartNPT = iActualNPT;
        iStartMediaDataTS = iSkipMediaDataTS;
        iPlaybackClock.UpdateNPTClockPosition(iStartNPT, (iPlaybackDirection < 0) ? true : false);
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO,
                        (0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() TargetNPT %d, ActualNPT %d StartTS %d",
                         iTargetNPT, iStartNPT, iStartMediaDataTS));
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                        (0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() TargetNPT %d, ActualNPT %d StartTS %d",
                         iTargetNPT, iStartNPT, iStartMediaDataTS));

        // Send event to the observer indicating start of data
        if (iDataSourcePosParams.iMode == PVMF_SET_DATA_SOURCE_POSITION_MODE_NOW)
        {
            /* Reset */
            iDataSourcePosParams.iActualMediaDataTS = 0;
            iDataSourcePosParams.iActualNPT = 0;
            iDataSourcePosParams.iMode = PVMF_SET_DATA_SOURCE_POSITION_MODE_UNKNOWN;
            iDataSourcePosParams.iPlayElementIndex = -1;
            iDataSourcePosParams.iSeekToSyncPoint = true;
            iDataSourcePosParams.iTargetNPT = 0;
            SendInformationalEvent(PVMFInfoStartOfData);
        }

        // send the actual playback position from where playback will resume after reposition.
        PVPPlaybackPosition actualPlaybackPosition;
        actualPlaybackPosition.iPosValue.millisec_value = iStartNPT;
        actualPlaybackPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;

        PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
        PVMFBasicErrorInfoMessage* infomsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoPlaybackFromBeginTime, puuid, NULL));
        SendInformationalEvent(PVMFInfoActualPlaybackPosition, OSCL_STATIC_CAST(PVInterface*, infomsg), (OsclAny*)&actualPlaybackPosition);
        infomsg->removeRef();

        // Complete SetPlaybackRange() or SetPlaybackRate()
        EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess);
    }

    if ((iNumPendingSkipCompleteEvent == 0) && (iNumPVMFInfoStartOfDataPending == 0))
    {
        if (iWatchDogTimer->IsBusy())
        {
            iWatchDogTimer->Cancel();
        }
        // we have received all the bos event for
        // playback hasnt started yet
        if (GetPVPlayerState() != PVP_STATE_PAUSED)
        {
            StartPlaybackClock();
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback - PlayClock Started"));
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() Out"));
}


void PVPlayerEngine::HandleSourceNodePause(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodePause() In"));

    switch (aNodeResp.GetCmdStatus())
    {
        case PVMFSuccess:
        {
            if (iState != PVP_ENGINE_STATE_PAUSED)
            {
                // Pause command is complete
                SetEngineState(PVP_ENGINE_STATE_PAUSED);
                EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess);
            }
            else
            {
                // This is needed to process Stop or Resume or SetPlaybackRange or Pause queued
                // immediately after SetPlaybackRange
                RunIfNotReady();
            }
        }
        break;

        default:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleSourceNodePause() failed, Add EH command"));
            PVMFErrorInfoMessageInterface* nextmsg = NULL;
            if (aNodeResp.GetEventExtensionInterface())
            {
                nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
            }
            PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
            PVMFBasicErrorInfoMessage *errMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg));

            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PAUSE, aNodeResp.GetCmdStatus(), errMsg);
        }
        break;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodePause() Out"));
}


void PVPlayerEngine::HandleSourceNodeStart(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeStart() In"));

    PVMFStatus cmdstatus = PVMFErrNotSupported;

    switch (aNodeResp.GetCmdStatus())
    {
        case PVMFSuccess:
        {
            // Issue Skip on Sink Node and Start on datapaths back to back. This is done to make sure that
            // sink node is started only after discarding the data from an earlier stream.
            if (iChangePlaybackPositionWhenResuming || iChangePlaybackDirectionWhenResuming || (iState == PVP_ENGINE_STATE_PREPARING))
            {
                PVMFStatus cmdstatus = DoSinkNodeSkipMediaData(aNodeContext.iCmdId, false, PVP_CMD_SinkNodeSkipMediaData, aNodeContext.iCmdContext);
                if (cmdstatus != PVMFSuccess)
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeStart() Skip of sink node did a leave, asserting"));
                    OSCL_ASSERT(false);
                }
            }
            // Issue start to all active datapaths
            iNumPendingDatapathCmd = 0;
            for (uint32 i = 0; i < iDatapathList.size(); ++i)
            {
                if (iDatapathList[i].iDatapath)
                {
                    PVMFStatus retval = DoDatapathStart(iDatapathList[i], aNodeContext.iCmdId, aNodeContext.iCmdContext);
                    if (retval == PVMFSuccess)
                    {
                        ++iNumPendingDatapathCmd;
                        cmdstatus = PVMFSuccess;
                    }
                    else
                    {
                        cmdstatus = retval;
                        break;
                    }
                }
            }

            if (iNumPendingDatapathCmd == 0)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeStart() Report command as failed, Add EH command"));
                if (iState == PVP_ENGINE_STATE_PREPARING)
                {
                    AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, cmdstatus, NULL);
                }
                else
                {
                    AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME, cmdstatus, NULL);
                }
            }
        }
        break;

        default:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeStart() failed, Add EH command"));
            cmdstatus = aNodeResp.GetCmdStatus();
            PVMFErrorInfoMessageInterface* nextmsg = NULL;
            if (aNodeResp.GetEventExtensionInterface())
            {
                nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
            }
            PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
            PVMFBasicErrorInfoMessage *errMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg));
            if (iState == PVP_ENGINE_STATE_PREPARING)
            {
                AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, cmdstatus, errMsg);
            }
            else
            {
                AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME, cmdstatus, errMsg);
            }
        }
        break;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeStart() Out"));
}


void PVPlayerEngine::HandleSourceNodeStop(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeStop() In"));

    PVMFStatus cmdstatus = PVMFFailure;

    switch (aNodeResp.GetCmdStatus())
    {
        case PVMFSuccess:
        {
            // Issue teardown sequence to all active datapaths
            iNumPendingDatapathCmd = 0;
            for (uint32 i = 0; i < iDatapathList.size(); ++i)
            {
                if (iDatapathList[i].iDatapath)
                {
                    PVMFStatus retval = DoDatapathTeardown(iDatapathList[i], aNodeContext.iCmdId, aNodeContext.iCmdContext);
                    if (retval == PVMFSuccess)
                    {
                        ++iNumPendingDatapathCmd;
                        cmdstatus = PVMFSuccess;
                    }
                    else
                    {
                        cmdstatus = retval;
                        break;
                    }
                }
            }
        }

        if (iNumPendingDatapathCmd == 0)
        {
            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_STOP, cmdstatus, NULL);
        }
        break;

        default:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleSourceNodeStop() Source node stop failed, go in error handling, Add EH command"));
            cmdstatus = aNodeResp.GetCmdStatus();
            PVMFErrorInfoMessageInterface* nextmsg = NULL;
            if (aNodeResp.GetEventExtensionInterface())
            {
                nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
            }
            PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
            PVMFBasicErrorInfoMessage *errMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg));

            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_STOP, cmdstatus, errMsg);
        }
        break;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeStop() Out"));
}


void PVPlayerEngine::HandleSourceNodeReset(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeReset() In"));

    PVMFStatus cmdstatus = PVMFErrNotSupported;

    if (aNodeResp.GetCmdStatus() == PVMFSuccess)
    {
        if (iSourceNode->GetState() != EPVMFNodeIdle)
        {
            // when reset completes on Source node, source node should be in Idle State,
            // If not then just assert.
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleSourceNodeReset() Source Node not in a idle state after reset, Asserting"));
            OSCL_ASSERT(false);
        }

        PVMFStatus status = PVMFFailure;
        status = iSourceNode->ThreadLogoff();
        if (status != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoEngineDatapathTeardown() Threadlogoff on SourceNode Failed"));
            OSCL_ASSERT(false);
        }

        if (iSourceNode->GetState() != EPVMFNodeCreated)
        {
            // when reset completes on Source node, source node should be in Idle State,
            // If not then just assert.
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleSourceNodeReset() Source Node not in a created state after threadlogoff, Asserting"));
            OSCL_ASSERT(false);
        }

        // Reset active datapaths
        if (!iDatapathList.empty())
        {
            iNumPendingDatapathCmd = 0;
            PVMFCommandId cmdid = -1;
            int32 leavecode = 0;
            for (uint32 i = 0; i < iDatapathList.size(); ++i)
            {
                if ((iDatapathList[i].iDatapath != NULL) &&
                        (iDatapathList[i].iTrackInfo != NULL) &&
                        (iDatapathList[i].iDatapath->iState != PVPDP_IDLE))
                {
                    PVMFStatus retval = DoDatapathReset(iDatapathList[i], aNodeContext.iCmdId, aNodeContext.iCmdContext);
                    if (retval == PVMFSuccess)
                    {
                        ++iNumPendingDatapathCmd;
                        cmdstatus = PVMFSuccess;
                    }
                    else
                    {
                        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                        (0, "PVPlayerEngine::HandleSourceNodeReset() Reset failed, Asserting"));
                        OSCL_ASSERT(false);
                        break;
                    }
                }
                else if (iDatapathList[i].iDecNode != NULL)
                {
                    // This happens in case of error during prepare, when datapaths have not yet
                    // been fully constructed.
                    // reset the decoder node during inteligent track selection
                    // Call Reset() on the decoder node
                    PVPlayerEngineContext* context = AllocateEngineContext(&(iDatapathList[i]), iDatapathList[i].iDecNode, NULL, aNodeContext.iCmdId, aNodeContext.iCmdContext, PVP_CMD_DecNodeReset);

                    leavecode = IssueDecNodeReset(iDatapathList[i].iDecNode, iDatapathList[i].iDecNodeSessionId, (OsclAny*) context, cmdid);

                    if (cmdid != -1 && leavecode == 0)
                    {
                        ++iNumPendingDatapathCmd;
                    }
                    else
                    {
                        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeReset() Reset on dec node leaved, asserting"));
                        FreeEngineContext(context);
                        OSCL_ASSERT(false);
                    }
                }
                else if (iDatapathList[i].iSinkNode != NULL)
                {
                    // This happens in case of error during prepare, when datapaths have not yet
                    // been fully constructed.
                    // reset the sink node during inteligent track selection
                    // Call Reset() on the sink node
                    PVPlayerEngineContext* context = AllocateEngineContext(&(iDatapathList[i]), iDatapathList[i].iSinkNode, NULL, aNodeContext.iCmdId, aNodeContext.iCmdContext, PVP_CMD_SinkNodeReset);

                    leavecode = IssueSinkNodeReset(&(iDatapathList[i]), (OsclAny*) context, cmdid);

                    if (cmdid != -1 && leavecode == 0)
                    {
                        ++iNumPendingDatapathCmd;
                    }
                    else
                    {
                        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeReset() Reset on sink node leaved, asserting"));
                        FreeEngineContext(context);
                        OSCL_ASSERT(false);
                    }
                }
                else
                {
                    // No Sink nodes and no datapaths created yet so just do Enginedatapath Teardown.
                    DoEngineDatapathTeardown(iDatapathList[i]);
                }
            }

            if (iNumPendingDatapathCmd == 0)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "PVPlayerEngine::HandleSourceNodeReset() Reset on SourceNode completed and no datapath or sink node to reset."));
                // Reset on source node is complete and there are no datapaths or sink nodes to reset,
                // now need to remove the data sinks and sources
                // so schedule engine AO - we cannnot delete datapaths in callback, hence the reschedule
                SetEngineState(PVP_ENGINE_STATE_IDLE);
                RunIfNotReady();
            }
        }
        else
        {
            // Reset on source node is complete and there are no datapaths or sink nodes to reset,
            // now need to remove the data sinks and sources
            // so schedule engine AO - we cannnot delete datapaths in callback, hence the reschedule
            SetEngineState(PVP_ENGINE_STATE_IDLE);
            RunIfNotReady();
        }
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::HandleSourceNodeReset() Reset failed on Source Node, Asserting"));
        OSCL_ASSERT(false);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeReset() Out"));
}


void PVPlayerEngine::HandleSinkNodePause(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodePause() In %s", aNodeContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr()));

    // Decrement the counter for pending cmds
    --iNumPendingDatapathCmd;

    if (aNodeResp.GetCmdStatus() != PVMFSuccess)
    {
        bool ehPending = CheckForPendingErrorHandlingCmd();
        if (ehPending)
        {
            // there should be no error handling queued.
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodePause() Already EH pending, should never happen"));
            return;
        }
        else
        {
            // Cancel any pending node/datapath commands
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodePause() Failed, Add EH command"));
            PVMFErrorInfoMessageInterface* nextmsg = NULL;
            if (aNodeResp.GetEventExtensionInterface())
            {
                nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
            }
            PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
            PVMFBasicErrorInfoMessage *errMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSinkFatal, puuid, nextmsg));
            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PAUSE, aNodeResp.GetCmdStatus(), errMsg);
        }

        return;
    }

    if (iNumPendingDatapathCmd == 0)
    {
        // Auto-pause is complete
        SetEngineState(PVP_ENGINE_STATE_AUTO_PAUSED);
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodePause() Report command as success"));
        EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodePause() Out"));
}


void PVPlayerEngine::HandleSinkNodeResume(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeResume() In %s", aNodeContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr()));

    // Decrement the counter for pending cmds
    --iNumPendingDatapathCmd;

    if (aNodeResp.GetCmdStatus() != PVMFSuccess)
    {
        bool ehPending = CheckForPendingErrorHandlingCmd();
        if (ehPending)
        {
            // there should be no error handling queued.
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeResume() Already EH pending, should never happen"));
            return;
        }
        else
        {
            // Cancel any pending node/datapath commands
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeResume() Failed, Add EH command"));
            PVMFErrorInfoMessageInterface* nextmsg = NULL;
            if (aNodeResp.GetEventExtensionInterface())
            {
                nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
            }
            PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
            PVMFBasicErrorInfoMessage *errMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSinkFatal, puuid, nextmsg));
            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME, aNodeResp.GetCmdStatus(), errMsg);
        }
        return;
    }

    if (iNumPendingDatapathCmd == 0)
    {
        // Auto-resume is complete
        // Resume the playback clock only if InfoStartofData has been received for all tracks.
        // If SetPlaybackRange is called in Auto-Pause state, its possible that engine is waiting for InfoStartofData.
        // If waiting, restart the watchdog timer which was cancelled in Auto-Pause command.
        // this should only be done when engine is waiting for StartofData info event
        // after reposition. If already busy after SetPlaybackRange command complete,
        // then cancel it and start again. Playback clock will be started in either HandleSinkNodeInfoEvent or
        // PVPlayerWatchdogTimerEvent
        if (iNumPVMFInfoStartOfDataPending > 0)
        {
            if (iWatchDogTimerInterval > 0)
            {
                if (iWatchDogTimer->IsBusy())
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                                    (0, "PVPlayerEngine::HandleSinkNodeResume - Pause after setplayback, Cancelling Watchdog timer, iNumPVMFInfoStartOfDataPending=%d", iNumPVMFInfoStartOfDataPending));
                    iWatchDogTimer->Cancel();
                }

                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                                (0, "PVPlayerEngine::HandleSinkNodeResume Setting WatchDogTimer for %d ms, iNumPVMFInfoStartOfDataPending=%d",
                                 iWatchDogTimerInterval, iNumPVMFInfoStartOfDataPending));
                iWatchDogTimer->setTimerDuration(iWatchDogTimerInterval);
                iWatchDogTimer->Start();
            }
        }
        // Auto-resume is complete & not waiting on PVMFInfoStartOfData, so go ahead and
        // start the clock
        if (iNumPVMFInfoStartOfDataPending == 0)
        {
            StartPlaybackClock();

            // Notify data sinks that clock has started
            for (uint32 i = 0; i < iDatapathList.size(); ++i)
            {
                if (iDatapathList[i].iDatapath && iDatapathList[i].iSinkNodeSyncCtrlIF)
                {
                    iDatapathList[i].iSinkNodeSyncCtrlIF->ClockStarted();
                }
            }
        }

        SetEngineState(PVP_ENGINE_STATE_STARTED);
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeResume() Report command as success"));
        EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeResume() Out"));
}

void PVPlayerEngine::HandleSinkNodeReset(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    OSCL_ASSERT(aNodeContext.iEngineDatapath != NULL);
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeReset() In"));

    // Decrement the counter for pending cmds
    --iNumPendingDatapathCmd;

    if (aNodeResp.GetCmdStatus() != PVMFSuccess)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::HandleSinkNodeReset() Reset failed, assert"));
        OSCL_ASSERT(false);
        return;
    }
    else
    {
        // Reset for this sink node is complete
        //a sync call in engine - no async cmds issued here
        DoEngineDatapathTeardown(*(aNodeContext.iEngineDatapath));
    }

    if (iNumPendingDatapathCmd == 0)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::HandleSinkNodeReset() Reset on SourceNode and Sink nodes completed"));
        // Reset on source node and sink node is complete, now need to remove the data sinks and sources
        // so schedule engine AO - we cannnot delete datapaths in callback, hence the reschedule
        SetEngineState(PVP_ENGINE_STATE_IDLE);
        RunIfNotReady();
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeReset() Out"));
}

void PVPlayerEngine::HandleDecNodeReset(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
    OSCL_ASSERT(aNodeContext.iEngineDatapath != NULL);
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeReset() In"));

    // Decrement the counter for pending cmds
    --iNumPendingDatapathCmd;

    if (aNodeResp.GetCmdStatus() != PVMFSuccess)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::HandleDecNodeReset() Reset failed, assert"));
        OSCL_ASSERT(false);
        return;
    }

    if (iNumPendingDatapathCmd == 0)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::HandleDecNodeReset() Reset on SourceNode and dec nodes completed, now reset Sink nodes"));
        // Reset on source node and dec node is complete, now need to reset the sink nodes
        if (!iDatapathList.empty())
        {
            iNumPendingDatapathCmd = 0;
            PVMFCommandId cmdid = -1;
            int32 leavecode = 0;
            for (uint32 i = 0; i < iDatapathList.size(); ++i)
            {
                if (iDatapathList[i].iSinkNode != NULL)
                {
                    // This happens in case of error during prepare, when datapaths have not yet
                    // been fully constructed.
                    // reset the sink node during inteligent track selection
                    // Call Reset() on the sink node
                    PVPlayerEngineContext* context = AllocateEngineContext(&(iDatapathList[i]), iDatapathList[i].iSinkNode, NULL, aNodeContext.iCmdId, aNodeContext.iCmdContext, PVP_CMD_SinkNodeReset);

                    leavecode = IssueSinkNodeReset(&(iDatapathList[i]), (OsclAny*) context, cmdid);

                    if (cmdid != -1 && leavecode == 0)
                    {
                        ++iNumPendingDatapathCmd;
                    }
                    else
                    {
                        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDecNodeReset() Reset on sink node leaved, asserting"));
                        FreeEngineContext(context);
                        OSCL_ASSERT(false);
                    }
                }
            }
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeReset() Out"));
}

void PVPlayerEngine::HandleDatapathPrepare(PVPlayerEngineContext& aDatapathContext, PVMFStatus aDatapathStatus, PVMFCmdResp* aCmdResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::HandleDatapathPrepare() for %s Tick=%d",
                     aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathPrepare() In %s", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr()));

    // Decrement the counter for pending datapath cmds
    --iNumPendingDatapathCmd;

    if (aDatapathStatus != PVMFSuccess)
    {
        bool ehPending = CheckForPendingErrorHandlingCmd();
        if (ehPending)
        {
            // there should be no error handling queued.
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathPrepare() Already EH pending, should never happen"));
            return;
        }
        else
        {
            // Cancel any pending node/datapath commands
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleDatapathPrepare() In %s Failed, Add EH command", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr()));
            PVMFErrorInfoMessageInterface* nextmsg = NULL;
            if (aCmdResp)
            {
                if (aCmdResp->GetEventExtensionInterface())
                {
                    nextmsg = GetErrorInfoMessageInterface(*(aCmdResp->GetEventExtensionInterface()));
                }
            }
            PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
            PVMFBasicErrorInfoMessage *errMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathFatal, puuid, nextmsg));
            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, aDatapathStatus, errMsg);
        }
        return;
    }

    if (iNumPendingDatapathCmd == 0)
    {
        // Reposition and/or start the source node
        PVMFStatus cmdstatus = DoSourceNodeQueryDataSourcePosition(aDatapathContext.iCmdId, aDatapathContext.iCmdContext);
        if (cmdstatus != PVMFSuccess)
        {
            // Setting position not supported so start the source node
            cmdstatus = DoSourceNodeStart(aDatapathContext.iCmdId, aDatapathContext.iCmdContext);
        }

        if (cmdstatus != PVMFSuccess)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathPrepare() Report command as failed, Add EH command"));
            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, cmdstatus, NULL);
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathPrepare() Out"));
}


void PVPlayerEngine::HandleDatapathStart(PVPlayerEngineContext& aDatapathContext, PVMFStatus aDatapathStatus, PVMFCmdResp* aCmdResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::HandleDatapathStart() for %s Tick=%d",
                     aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathStart() In %s", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr()));

    // Decrement the counter for pending datapath cmds
    --iNumPendingDatapathCmd;

    if (aDatapathStatus != PVMFSuccess)
    {
        PVMFErrorInfoMessageInterface* nextmsg = NULL;
        if (aCmdResp)
        {
            if (aCmdResp->GetEventExtensionInterface())
            {
                nextmsg = GetErrorInfoMessageInterface(*(aCmdResp->GetEventExtensionInterface()));
            }
        }
        PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
        PVMFBasicErrorInfoMessage *errMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathFatal, puuid, nextmsg));
        AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, aDatapathStatus, errMsg);
        return;
    }

    if (iNumPendingDatapathCmd == 0)
    {
        // This should never be happen if Skip on sink node has not completed (i.e. iNumPendingSkipCompleteEvent
        // is greater than zero). If this happens with iNumPendingSkipCompleteEvent > 0 then just assert.
        // Set the clock to the specified begin time just before Start of playback Clock
        iPlaybackClock.Stop();
        bool overflow = 0;
        iPlaybackClock.SetStartTime32(iSkipMediaDataTS, PVMF_MEDIA_CLOCK_MSEC, overflow);

        if (!(iWatchDogTimer->IsBusy()))
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                            (0, "PVPlayerEngine::HandleDatapathStart() Setting WatchDogTimer for %d ms, TargetNPT=%d  ActualNPT=%d, if interval zero set to default 1 second",
                             iWatchDogTimerInterval, iTargetNPT, iActualNPT));
            iWatchDogTimer->setTimerDuration(iWatchDogTimerInterval);
            iWatchDogTimer->Start();
        }
        // Set the actual playback position to the requested time since actual media data TS was adjusted
        // This is important since the difference between the two is used to calculate the NPT to media data offset
        // This is not required here as the ActualPlaybackPosition is already adjusted before calling Skip on Sink Node.
        // iActualNPT=iCurrentBeginPosition.iPosValue.millisec_value;

        // Save the start NPT and TS
        iStartNPT = iActualNPT;
        iStartMediaDataTS = iSkipMediaDataTS;
        iPlaybackClock.UpdateNPTClockPosition(iStartNPT, (iPlaybackDirection < 0) ? true : false);
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO,
                        (0, "PVPlayerEngine::HandleDatapathStart() TargetNPT %d, StartNPT %d StartTS %d",
                         iTargetNPT, iStartNPT, iStartMediaDataTS));
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                        (0, "PVPlayerEngine::HandleDatapathStart() TargetNPT %d, StartNPT %d StartTS %d",
                         iTargetNPT, iStartNPT, iStartMediaDataTS));

        SetEngineState(PVP_ENGINE_STATE_PREPARED);

        // send the actual playback position from where playback will resume after reposition.
        PVPPlaybackPosition actualPlaybackPosition;
        actualPlaybackPosition.iPosValue.millisec_value = iStartNPT;
        actualPlaybackPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;

        PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
        PVMFBasicErrorInfoMessage* infomsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoPlaybackFromBeginTime, puuid, NULL));
        SendInformationalEvent(PVMFInfoActualPlaybackPosition, OSCL_STATIC_CAST(PVInterface*, infomsg), (OsclAny*)&actualPlaybackPosition);
        infomsg->removeRef();

        EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, PVMFSuccess);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathStart() Out"));
}


void PVPlayerEngine::HandleDatapathPause(PVPlayerEngineContext& aDatapathContext, PVMFStatus aDatapathStatus, PVMFCmdResp* aCmdResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::HandleDatapathPause() for %s Tick=%d",
                     aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathPause() In %s", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr()));

    // Decrement the counter for pending datapath cmds
    --iNumPendingDatapathCmd;

    if (aDatapathStatus != PVMFSuccess)
    {
        PVMFErrorInfoMessageInterface* nextmsg = NULL;
        if (aCmdResp)
        {
            if (aCmdResp->GetEventExtensionInterface())
            {
                nextmsg = GetErrorInfoMessageInterface(*(aCmdResp->GetEventExtensionInterface()));
            }
        }

        PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
        PVMFBasicErrorInfoMessage *errMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathFatal, puuid, nextmsg));
        AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PAUSE, aDatapathStatus, errMsg);
        return;
    }

    if (iNumPendingDatapathCmd == 0)
    {
        // Continue on by pauseing the source node
        PVMFStatus cmdstatus = DoSourceNodePause(aDatapathContext.iCmdId, aDatapathContext.iCmdContext);

        if (cmdstatus != PVMFSuccess)
        {
            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PAUSE, cmdstatus, NULL);
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathPause() Out"));
}


void PVPlayerEngine::HandleDatapathResume(PVPlayerEngineContext& aDatapathContext, PVMFStatus aDatapathStatus, PVMFCmdResp* aCmdResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::HandleDatapathResume() for %s Tick=%d",
                     aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathResume() In %s", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr()));

    // Decrement the counter for pending datapath cmds
    --iNumPendingDatapathCmd;

    if (aDatapathStatus != PVMFSuccess)
    {
        PVMFErrorInfoMessageInterface* nextmsg = NULL;
        if (aCmdResp)
        {
            if (aCmdResp->GetEventExtensionInterface())
            {
                nextmsg = GetErrorInfoMessageInterface(*(aCmdResp->GetEventExtensionInterface()));
            }
        }

        PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
        PVMFBasicErrorInfoMessage *errMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathFatal, puuid, nextmsg));
        AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_STOP, aDatapathStatus, errMsg);
        return;
    }

    if (iNumPendingDatapathCmd == 0)
    {
        if (iChangePlaybackPositionWhenResuming || iChangePlaybackDirectionWhenResuming)
        {
            // This should never be happen if Skip on sink node has not completed (i.e. iNumPendingSkipCompleteEvent
            // is greater than zero). If this happens with iNumPendingSkipCompleteEvent > 0 then just assert.
            // Set the clock to the specified begin time just before Start of playback Clock
            iPlaybackClock.Stop();
            bool overflow = 0;
            iPlaybackClock.SetStartTime32(iSkipMediaDataTS, PVMF_MEDIA_CLOCK_MSEC, overflow);

            if (iNumPVMFInfoStartOfDataPending == 0)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                                (0, "PVPlayerEngine::HandleDatapathResume() Skipping WatchDogTimer - Starting PlayBackClock"));
                StartPlaybackClock();
            }
            else
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                                (0, "PVPlayerEngine::HandleDatapathResume() Setting WatchDogTimer for %d ms, TargetNPT=%d  ActualNPT=%d",
                                 iWatchDogTimerInterval, iTargetNPT, iActualNPT));

                // There can be a case in which WatchDogTimerInterval is zero and iNumPVMFInfoStartOfDataPending is greater than zero.
                // In this case it is possible InfoStartofData is not sent by Sink Nodes for some time and player hangs. To avoid the player hang
                // set the watchdog timer Interval to the default value of 1 second.
                iWatchDogTimer->setTimerDuration(iWatchDogTimerInterval);
                iWatchDogTimer->Start();
            }

            // Set the actual playback position to the requested time since actual media data TS was adjusted
            // This is important since the difference between the two is used to calculate the NPT to media data offset
            // This is not required here as the ActualPlaybackPosition is already adjusted before calling Skip on Sink Node.
            // iActualNPT=iCurrentBeginPosition.iPosValue.millisec_value;

            //clear the pending direction change NPT.
            iChangeDirectionNPT.iIndeterminate = true;
            // Save the start NPT and TS
            iStartNPT = iActualNPT;
            iStartMediaDataTS = iSkipMediaDataTS;
            iPlaybackClock.UpdateNPTClockPosition(iStartNPT, (iPlaybackDirection < 0) ? true : false);
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO,
                            (0, "PVPlayerEngine::HandleDatapathResume() TargetNPT %d, ActualNPT %d StartTS %d",
                             iTargetNPT, iStartNPT, iStartMediaDataTS));
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                            (0, "PVPlayerEngine::HandleDatapathResume() TargetNPT %d, ActualNPT %d StartTS %d",
                             iTargetNPT, iStartNPT, iStartMediaDataTS));

            // send the actual playback position from where playback will resume after reposition.
            PVPPlaybackPosition actualPlaybackPosition;
            actualPlaybackPosition.iPosValue.millisec_value = iStartNPT;
            actualPlaybackPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;

            PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
            PVMFBasicErrorInfoMessage* infomsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoPlaybackFromBeginTime, puuid, NULL));
            SendInformationalEvent(PVMFInfoActualPlaybackPosition, OSCL_STATIC_CAST(PVInterface*, infomsg), (OsclAny*)&actualPlaybackPosition);
            infomsg->removeRef();
            SetEngineState(PVP_ENGINE_STATE_STARTED);

            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathResume() Report command as completed"));
            EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, PVMFSuccess);
        }
        else if ((iState == PVP_ENGINE_STATE_RESUMING) ||
                 (iState == PVP_ENGINE_STATE_AUTO_RESUMING))
        {
            // Resume the playback clock - only if we have come out of any previous auto pause, if any
            if (iPlaybackClock.GetState() != PVMFMediaClock::RUNNING)
            {
                StartPlaybackClock();

                // Notify all sink nodes that have sync control IF that clock has started
                for (uint32 i = 0; i < iDatapathList.size(); ++i)
                {
                    if (iDatapathList[i].iDatapath && iDatapathList[i].iSinkNodeSyncCtrlIF)
                    {
                        iDatapathList[i].iSinkNodeSyncCtrlIF->ClockStarted();
                    }
                }
            }

            // Restart the watchdog timer which was cancelled in Pause command.
            // this should only be done when engine is waiting for StartofData info event
            // after reposition.
            if (iNumPVMFInfoStartOfDataPending > 0)
            {
                if (iWatchDogTimerInterval > 0)
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                                    (0, "PVPlayerEngine::HandleDatapathResume Setting WatchDogTimer for %d ms, iNumPVMFInfoStartOfDataPending=%d",
                                     iWatchDogTimerInterval, iNumPVMFInfoStartOfDataPending));
                    iWatchDogTimer->setTimerDuration(iWatchDogTimerInterval);
                    iWatchDogTimer->Start();
                }
            }

            // Restart the end time check if enabled
            if (iEndTimeCheckEnabled)
            {
                // Determine the check cycle based on interval setting in milliseconds
                // and timer frequency of 100 millisec
                int32 checkcycle = iEndTimeCheckInterval / 100;
                if (checkcycle == 0)
                {
                    ++checkcycle;
                }
                iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_ENDTIMECHECK);
                iPollingCheckTimer->Request(PVPLAYERENGINE_TIMERID_ENDTIMECHECK, 0, checkcycle, this, true);
            }
            SetEngineState(PVP_ENGINE_STATE_STARTED);

            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathResume() Report command as completed"));
            EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, PVMFSuccess);
        }
        if (!iPendingCmds.empty())
        {
            if (iPendingCmds.top().GetCmdType() == PVP_ENGINE_COMMAND_PAUSE_DUE_TO_SET_PLAYBACK_RANGE)
            {
                // If we are here, it means that the HandleDatapathResume
                // was part of the SetPlaybackRange command, and the StartOfData
                // events have already reached the engine. So, pause the engine.
                RunIfNotReady();
            }
        }
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVPlayerEngine::HandleDatapathResume() - %d pending datapath commands", iNumPendingDatapathCmd));
    }
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathResume() Out"));
}


void PVPlayerEngine::HandleDatapathStop(PVPlayerEngineContext& aDatapathContext, PVMFStatus aDatapathStatus, PVMFCmdResp* aCmdResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::HandleDatapathStop() for %s Tick=%d",
                     aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathStop() In %s", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr()));

    // Decrement the counter for pending datapath cmds
    --iNumPendingDatapathCmd;

    if (aDatapathStatus != PVMFSuccess)
    {
        PVMFErrorInfoMessageInterface* nextmsg = NULL;
        if (aCmdResp)
        {
            if (aCmdResp->GetEventExtensionInterface())
            {
                nextmsg = GetErrorInfoMessageInterface(*(aCmdResp->GetEventExtensionInterface()));
            }
        }

        PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
        PVMFBasicErrorInfoMessage *errMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathFatal, puuid, nextmsg));
        AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_STOP, aDatapathStatus, errMsg);
        return;
    }

    if (iNumPendingDatapathCmd == 0)
    {
        // Continue on by stopping the source node
        PVMFStatus cmdstatus = DoSourceNodeStop(aDatapathContext.iCmdId, aDatapathContext.iCmdContext);

        if (cmdstatus != PVMFSuccess)
        {
            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_STOP, cmdstatus, NULL);
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathStop() Out"));
}


void PVPlayerEngine::HandleDatapathTeardown(PVPlayerEngineContext& aDatapathContext, PVMFStatus aDatapathStatus, PVMFCmdResp* aCmdResp)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::HandleDatapathTeardown() for %s Tick=%d",
                     aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathTeardown() In %s", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr()));

    PVMFStatus cmdstatus;

    switch (aDatapathStatus)
    {
        case PVMFSuccess:
            // Reset this datapath next
            cmdstatus = DoDatapathReset(*(aDatapathContext.iEngineDatapath), aDatapathContext.iCmdId, aDatapathContext.iCmdContext);
            break;

        default:
        {
            PVMFErrorInfoMessageInterface* nextmsg = NULL;
            if (aCmdResp)
            {
                if (aCmdResp->GetEventExtensionInterface())
                {
                    nextmsg = GetErrorInfoMessageInterface(*(aCmdResp->GetEventExtensionInterface()));
                }
            }

            PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
            PVMFBasicErrorInfoMessage *errMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathFatal, puuid, nextmsg));
            AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_STOP, aDatapathStatus, errMsg);
            return;
        }
    }

    if (cmdstatus != PVMFSuccess)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathTeardown() Reset failed, asserting"));
        OSCL_ASSERT(false);
        EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, cmdstatus);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleVideoDatapathTeardown() Out"));
}


void PVPlayerEngine::HandleDatapathReset(PVPlayerEngineContext& aDatapathContext, PVMFStatus aDatapathStatus, PVMFCmdResp* aCmdResp)
{
    OSCL_UNUSED_ARG(aCmdResp);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
                    (0, "PVPlayerEngine::HandleDatapathReset() for %s Tick=%d",
                     aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount()));

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathReset() In %s", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr()));

    // Decrement the counter for pending datapath cmds
    --iNumPendingDatapathCmd;

    if (aDatapathStatus != PVMFSuccess)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::HandleDatapathReset() In %s Reset failed, assert", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr()));
        OSCL_ASSERT(false);
        return;
    }
    else
    {
        // Reset for this datapath is complete
        //a sync call in engine - no async cmds issued here
        DoEngineDatapathTeardown(*(aDatapathContext.iEngineDatapath));
    }

    //this means datapath reset and teardown is complete for all datapaths
    if (iNumPendingDatapathCmd == 0)
    {
        if (iState == PVP_ENGINE_STATE_RESETTING)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleDatapathReset() Reset on SourceNode and Datapath completed"));
            // Reset on source node and datapath is complete, now need to remove the data sinks and sources
            // so schedule engine AO - we cannnot delete datapaths in callback, hence the reschedule
            SetEngineState(PVP_ENGINE_STATE_IDLE);
            RunIfNotReady();
        }
        else if (iState == PVP_ENGINE_STATE_STOPPING)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathReset() Stop Completed"));
            // stop has completed
            SetEngineState(PVP_ENGINE_STATE_INITIALIZED);
            EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, PVMFSuccess);
        }
        else
        {
            //engine cannot be in any other state
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleDatapathReset() Wrong Engine state for Reset to complete, asserting"));
            OSCL_ASSERT(false);
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathReset() Out"));
}

void PVPlayerEngine::HandleSourceNodeErrorEvent(const PVMFAsyncEvent& aEvent)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeErrorEvent() In"));

    if (iState == PVP_ENGINE_STATE_RESETTING)
    {
        //this means error handling, reset or cancelall is still in progress
        //no need to look for error event
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::HandleSourceNodeErrorEvent() Return engine in resetting state no need to process the error event"));
        return;
    }

    for (uint32 i = 0; i < iCurrentContextList.size(); ++i)
    {
        if (iCurrentContextList[i]->iNode)
        {
            if (iCurrentContextList[i]->iNode == iSourceNode)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "PVPlayerEngine::HandleSourceNodeErrorEvent() Cmd Pending on Source node, so src node should not send error events - ignoring err event"));
                return;
            }
        }
    }

    int32 code;
    bool handleError = false;
    PVMFEventType event = aEvent.GetEventType();
    switch (event)
    {
        case PVMFErrCorrupt:
        case PVMFErrOverflow:
        case PVMFErrResource:
        case PVMFErrProcessing:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleSourceNodeErrorEvent() Sending PVPlayerErrSourceMediaData for error event %d, Add EH command if not present", event));
            code = PVPlayerErrSourceMediaData;
            handleError = true;
        }
        break;

        case PVMFErrUnderflow:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleSourceNodeErrorEvent() Sending PVPlayerErrSourceMediaDataUnavailable for error event %d, Add EH command if not present", event));
            code = PVPlayerErrSourceMediaDataUnavailable;
            handleError = true;
        }
        break;

        case PVMFErrNoResources:
        case PVMFErrResourceConfiguration:
        case PVMFErrTimeout:
        case PVMFErrNoMemory:
        case PVMFFailure:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleSourceNodeErrorEvent() Sending PVPlayerErrSourceFatal for error event %d, Add EH command if not present", event));
            code = PVPlayerErrSourceFatal;
            handleError = true;
        }
        break;

        default:
            // Do nothing but log it
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeErrorEvent() Do nothing for this event %d", event));
            break;
    }

    if (handleError)
    {
        PVMFErrorInfoMessageInterface* nextmsg = NULL;
        if (aEvent.GetEventExtensionInterface() != NULL)
        {
            nextmsg = GetErrorInfoMessageInterface(*(aEvent.GetEventExtensionInterface()));
        }
        PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
        PVMFBasicErrorInfoMessage* errMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (code, puuid, nextmsg));
        AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_GENERAL, event, errMsg);
        if (iCurrentCmd.empty())
        {
            // this error was received when no cmd was being processed so send the error event from here
            SendErrorEvent(event,
                           OSCL_STATIC_CAST(PVInterface*, errMsg),
                           aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
            errMsg->removeRef();
            iCommandCompleteErrMsgInErrorHandling = NULL;
        }
    }
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeErrorEvent() Out"));
}


void PVPlayerEngine::HandleDecNodeErrorEvent(const PVMFAsyncEvent& aEvent, int32 aDatapathIndex)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDecNodeErrorEvent() In"));

    OSCL_UNUSED_ARG(aDatapathIndex);

    if (iState == PVP_ENGINE_STATE_RESETTING)
    {
        //this means error handling, reset or cancelall is still in progress
        //no need to look for error event
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::HandleDecNodeErrorEvent() Return engine in resetting state no need to process the error event"));
        return;
    }

    int32 code;
    bool handleError = false;
    PVMFEventType event = aEvent.GetEventType();
    switch (event)
    {
        case PVMFErrCorrupt:
        case PVMFErrOverflow:
        case PVMFErrUnderflow:
        case PVMFErrProcessing:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleDecNodeErrorEvent() Sending PVPlayerErrDatapathMediaData for error event %d, Add EH command if not present", event));
            code = PVPlayerErrDatapathMediaData;
            handleError = true;
        }
        break;

        case PVMFErrTimeout:
        case PVMFErrNoResources:
        case PVMFErrResourceConfiguration:
        case PVMFErrResource:
        case PVMFErrNoMemory:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleDecNodeErrorEvent() Sending PVPlayerErrDatapathFatal for error event %d, Add EH command if not present", event));
            code = PVPlayerErrDatapathFatal;
            handleError = true;
        }
        break;

        default:
            // Do nothing but log it
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeErrorEvent() Do nothing for this event %d", event));
            break;
    }

    if (handleError)
    {
        PVMFErrorInfoMessageInterface* nextmsg = NULL;
        if (aEvent.GetEventExtensionInterface() != NULL)
        {
            nextmsg = GetErrorInfoMessageInterface(*(aEvent.GetEventExtensionInterface()));
        }
        PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
        PVMFBasicErrorInfoMessage* errMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (code, puuid, nextmsg));
        AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_GENERAL, event, errMsg);
        if (iCurrentCmd.empty())
        {
            // this error was received when no cmd was being processed so send the error event from here
            SendErrorEvent(event,
                           OSCL_STATIC_CAST(PVInterface*, errMsg),
                           aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
            errMsg->removeRef();
            iCommandCompleteErrMsgInErrorHandling = NULL;
        }
    }
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeErrorEvent() Out"));
}


void PVPlayerEngine::HandleSinkNodeErrorEvent(const PVMFAsyncEvent& aEvent, int32 aDatapathIndex)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeErrorEvent() In"));

    OSCL_UNUSED_ARG(aDatapathIndex);

    if (iState == PVP_ENGINE_STATE_RESETTING)
    {
        //this means error handling, reset or cancelall is still in progress
        //no need to look for error event
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::HandleSinkNodeErrorEvent() Return engine in resetting state no need to process the error event"));
        return;
    }

    int32 code;
    bool handleError = false;
    PVMFEventType event = aEvent.GetEventType();
    switch (event)
    {
        case PVMFErrCorrupt:
        case PVMFErrOverflow:
        case PVMFErrUnderflow:
        case PVMFErrProcessing:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleSinkNodeErrorEvent() Sending PVPlayerErrDatapathMediaData for error event %d, Add EH command if not present", event));
            code = PVPlayerErrSinkMediaData;
            handleError = true;
        }
        break;

        case PVMFErrTimeout:
        case PVMFErrNoResources:
        case PVMFErrResourceConfiguration:
        case PVMFErrResource:
        case PVMFErrNoMemory:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::HandleSinkNodeErrorEvent() Sending PVPlayerErrSinkFatal for error event %d, Add EH command if not present", event));
            code = PVPlayerErrSinkFatal;
            handleError = true;
        }
        break;

        default:
            // Do nothing but log it
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeErrorEvent() Do nothing for this event %d", event));
            break;
    }

    if (handleError)
    {
        PVMFErrorInfoMessageInterface* nextmsg = NULL;
        if (aEvent.GetEventExtensionInterface() != NULL)
        {
            nextmsg = GetErrorInfoMessageInterface(*(aEvent.GetEventExtensionInterface()));
        }
        PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
        PVMFBasicErrorInfoMessage* errMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (code, puuid, nextmsg));
        AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_GENERAL, event, errMsg);
        if (iCurrentCmd.empty())
        {
            // this error was received when no cmd was being processed so send the error event from here
            SendErrorEvent(event,
                           OSCL_STATIC_CAST(PVInterface*, errMsg),
                           aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
            errMsg->removeRef();
            iCommandCompleteErrMsgInErrorHandling = NULL;
        }
    }
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeErrorEvent() Out"));
}

//Return val: true means found/deleted cmd(s).
bool PVPlayerEngine::removeCmdFromQ(Oscl_Vector<PVPlayerEngineCommand, OsclMemAllocator> &aVec, const PVPlayerEngineCommandType aCmdType, bool aRemove)
{
    if (aVec.size() == 0)
    {
        return false;
    }
    // OSCL priority queue doesn't allow index access so will need to
    // go through each pending cmd one-by-one, save commands that are not auto-resume
    // and put the commands back into the pending queue.
    // Vector to hold the pending cmds temporarily
    bool ret = false;
    Oscl_Vector<PVPlayerEngineCommand, OsclMemAllocator> tmpvec;
    tmpvec.reserve(aVec.size());
    tmpvec.clear();
    // Go through each pending command

    for (int i = aVec.size() - 1; i >= 0; i--)
    {
        if (aVec[i].GetCmdType() == aCmdType)
        {
            ret = true;
            if (!aRemove)
            {
                return ret;
            }
            continue;
        }
        tmpvec.push_back(aVec[i]);
    }
    aVec.clear();
    // Put the pending commands back in the priqueue
    while (tmpvec.empty() == false)
    {
        aVec.push_front(tmpvec[0]);
        tmpvec.erase(tmpvec.begin());
    }
    return ret;
}

//Return val: true means found/deleted cmd(s).
bool PVPlayerEngine::removeCmdFromQ(OsclPriorityQueue<PVPlayerEngineCommand, OsclMemAllocator, Oscl_Vector<PVPlayerEngineCommand, OsclMemAllocator>, PVPlayerEngineCommandCompareLess> &aVec, const PVPlayerEngineCommandType aCmdType, bool aRemove)
{
    // OSCL priority queue doesn't allow index access so will need to
    // go through each pending cmd one-by-one, save commands that are not auto-resume
    // and put the commands back into the pending queue.
    // Vector to hold the pending cmds temporarily
    bool ret = false;
    Oscl_Vector<PVPlayerEngineCommand, OsclMemAllocator> tmpvec;
    tmpvec.reserve(aVec.size());
    tmpvec.clear();
    // Go through each pending command
    while (aVec.empty() == false)
    {
        if (aVec.top().GetCmdType() == aCmdType)
        {
            ret = true;
            if (!aRemove)
            {
                return ret;
            }
            aVec.pop();
            continue;
        }
        tmpvec.push_back(aVec.top());
        aVec.pop();
    }
    // Put the pending commands back in the priqueue
    while (tmpvec.empty() == false)
    {
        aVec.push(tmpvec[0]);
        tmpvec.erase(tmpvec.begin());
    }
    return ret;
}

void PVPlayerEngine::HandleSourceNodeInfoEvent(const PVMFAsyncEvent& aEvent)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() In"));

    if (iState == PVP_ENGINE_STATE_RESETTING)
    {
        //this means error handling, reset or cancelall is still in progress
        //no need to look for info event
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Return engine in resetting state no need to process the info event %d", aEvent.GetEventType()));
        return;
    }

    PVMFEventType event = aEvent.GetEventType();

    switch (event)
    {
        case PVMFInfoBufferingStart:
        case PVMFInfoBufferingComplete:
        case PVMFInfoOverflow:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Sending buffering event %d", event));
            SendInformationalEvent(event, NULL, aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
        }
        break;

        case PVMFInfoBufferingStatus:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Sending buffering status event %d", event));
            SendInformationalEvent(event, NULL, aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
        }
        break;

        case PVMFInfoUnderflow:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Received PVMFInfoUnderflow"));
            // remove pending auto-resume if there is any
            if (removeCmdFromQ(iPendingCmds, PVP_ENGINE_COMMAND_RESUME_DUE_TO_BUFFER_DATAREADY, true))
            {
                //cancelled the pending auto-resume
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() PVMFInfoUnderflow got cancelled"));
                break;
            }

            // if no auto-pause in the queue and no auto-pause in progress, add one
            if ((! removeCmdFromQ(iCurrentCmd, PVP_ENGINE_COMMAND_PAUSE_DUE_TO_BUFFER_UNDERFLOW, false))
                    && (! removeCmdFromQ(iPendingCmds, PVP_ENGINE_COMMAND_PAUSE_DUE_TO_BUFFER_UNDERFLOW, false)))
            {
                AddCommandToQueue(PVP_ENGINE_COMMAND_PAUSE_DUE_TO_BUFFER_UNDERFLOW, NULL, NULL, NULL, false);
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Received source underflow event, issue auto-pause command"));
            }
        }
        break;

        case PVMFInfoDataReady:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Received PVMFInfoDataReady"));
            // remove pending auto-pause if there is any
            if (removeCmdFromQ(iPendingCmds, PVP_ENGINE_COMMAND_PAUSE_DUE_TO_BUFFER_UNDERFLOW, true))
            {
                //cancelled the pending auto-pause
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() PVMFInfoDataReady got cancelled"));
                break;
            }

            // if no resume in the queue and no resume in progress, add one
            if ((! removeCmdFromQ(iCurrentCmd, PVP_ENGINE_COMMAND_RESUME_DUE_TO_BUFFER_DATAREADY, false))
                    && (! removeCmdFromQ(iPendingCmds, PVP_ENGINE_COMMAND_RESUME_DUE_TO_BUFFER_DATAREADY, false))
                    && (iState != PVP_ENGINE_STATE_PAUSED))
            {
                AddCommandToQueue(PVP_ENGINE_COMMAND_RESUME_DUE_TO_BUFFER_DATAREADY, NULL, NULL, NULL, false);
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Received source data ready event, issue auto-resume command"));
            }
        }
        break;

        case PVMFInfoContentLength:
        case PVMFInfoContentType:
        case PVMFInfoContentTruncated:
        case PVMFInfoRemoteSourceNotification:
        case PVMFInfoPlayListClipTransition:
        case PVMFInfoPlayListSwitch:
        {
            PVInterface* intf = NULL;
            PVMFBasicErrorInfoMessage* infomsg = NULL;
            PVMFErrorInfoMessageInterface* nextmsg = NULL;
            if (aEvent.GetEventExtensionInterface() != NULL)
            {
                nextmsg = GetErrorInfoMessageInterface(*(aEvent.GetEventExtensionInterface()));
                PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
                infomsg =
                    OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoSourceMediaData,
                                                         puuid,
                                                         nextmsg));
                intf = OSCL_STATIC_CAST(PVInterface*, infomsg);
            }
            SendInformationalEvent(event, intf, aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
            if (infomsg != NULL)
            {
                infomsg->removeRef();
            }
            infomsg = NULL;
        }
        break;

        case PVMFInfoTrackDisable:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Sending bad track disabled event %d", event));
            SendInformationalEvent(event, NULL, aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
        }
        break;

        case PVMFInfoUnexpectedData:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Sending unexpected data event %d", event));
            SendInformationalEvent(event, NULL, aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
        }
        break;

        case PVMFInfoSessionDisconnect:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Sending session disconnect %d", event));
            SendInformationalEvent(event, NULL, aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
        }
        break;
        case PVMFInfoMetadataAvailable:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                            (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Sending Metadata available event"));
            PVUuid infomsguuid = PVMFMetadataInfoMessageInterfaceUUID;
            PVMFMetadataInfoMessageInterface* eventMsg = NULL;
            PVInterface* infoExtInterface = aEvent.GetEventExtensionInterface();
            PVInterface* temp = NULL;
            if (infoExtInterface &&
                    infoExtInterface->queryInterface(infomsguuid, temp))
            {
                PVUuid eventuuid;
                int32 infoCode;
                eventMsg = OSCL_STATIC_CAST(PVMFMetadataInfoMessageInterface*, temp);
                eventMsg->GetCodeUUID(infoCode, eventuuid);
                if (eventuuid == infomsguuid)
                {
                    Oscl_Vector<PvmiKvp, OsclMemAllocator> kvpVector = eventMsg->GetMetadataVector();
                    SendInformationalEvent(aEvent.GetEventType(), infoExtInterface, aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
                }
            }
            else
            {
                SendInformationalEvent(PVPlayerInfoClipInitialized, NULL, aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
            }
        }
        break;
        case PVMFInfoDurationAvailable:
        {
            PVUuid infomsguuid = PVMFDurationInfoMessageInterfaceUUID;
            PVMFDurationInfoMessageInterface* eventMsg = NULL;
            PVInterface* infoExtInterface = aEvent.GetEventExtensionInterface();
            PVInterface* temp = NULL;
            if (infoExtInterface &&
                    infoExtInterface->queryInterface(infomsguuid, temp))
            {
                PVUuid eventuuid;
                int32 infoCode;
                eventMsg = OSCL_STATIC_CAST(PVMFDurationInfoMessageInterface*, temp);
                eventMsg->GetCodeUUID(infoCode, eventuuid);
                if (eventuuid == infomsguuid)
                {
                    uint8* localBuf = NULL;
                    if (aEvent.GetLocalBufferSize() > 0)
                    {
                        localBuf = aEvent.GetLocalBuffer();
                    }
                    UpdateSourceDurationVector(localBuf, eventMsg->GetDuration());
                    UpdateCurrentClipSourceDuration();
                    SendInformationalEvent(aEvent.GetEventType(), infoExtInterface, aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
                }
            }
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Sending duration available %d", event));
        }
        break;

        case PVMFInfoPoorlyInterleavedContent:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                            (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Sending Poorly Interleaved Content Info %d", event));
            SendInformationalEvent(event, NULL, aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
        }
        break;
        case PVMFInfoSourceOverflow:
        {
            PVPPlaybackPosition aBeginPos;
            aBeginPos.iIndeterminate = false;
            aBeginPos.iPosUnit = PVPPBPOSUNIT_MILLISEC;
            aBeginPos.iPosValue.millisec_value = 0;
            PVPPlaybackPosition aEndPos;
            aEndPos.iIndeterminate = true;
            iOverflowFlag = true;
            SetPlaybackRange(aBeginPos, aEndPos, false);
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                            (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Received source overflow event, issue auto-reposition command"));
        }
        break;
        case PVMFInfoClipCorrupted:
        {
            iClipsCorrupted++;
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
                            (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Corrupted clip encountered Info %d", event));
            SendInformationalEvent(event, NULL, aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
        }
        break;
        case PVMFInfoEndOfData:
        default:
            // Do nothing but log it
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Do nothing for this event %d", event));
            break;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Out"));
}


void PVPlayerEngine::HandleDecNodeInfoEvent(const PVMFAsyncEvent& aEvent, int32 aDatapathIndex)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeInfoEvent() In"));

    if (iState == PVP_ENGINE_STATE_RESETTING)
    {
        //this means error handling, reset or cancelall is still in progress
        //no need to look for info event
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::HandleDecNodeInfoEvent() Return engine in resetting state no need to process the info event %d", aEvent.GetEventType()));
        return;
    }

    OSCL_UNUSED_ARG(aDatapathIndex);

    PVMFEventType event = aEvent.GetEventType();

    switch (event)
    {
        case PVMFInfoProcessingFailure:

            SendInformationalEvent(PVMFInfoProcessingFailure);
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeInfoEvent() Report ProcessingFailure event %d", event));
            break;

        case PVMFInfoOverflow:
        case PVMFInfoEndOfData:
        default:
            // Do nothing but log it
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeInfoEvent() Do nothing for this event %d", event));
            break;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeInfoEvent() Out"));
}


void PVPlayerEngine::HandleSinkNodeInfoEvent(const PVMFAsyncEvent& aEvent, int32 aDatapathIndex)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() In"));

    if (iState == PVP_ENGINE_STATE_RESETTING)
    {
        //this means error handling, reset or cancelall is still in progress
        //no need to look for info event
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() Return engine in resetting state no need to process the info event %d", aEvent.GetEventType()));
        return;
    }

    PVMFEventType event = aEvent.GetEventType();

    switch (event)
    {
        case PVMFInfoStartOfData:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() PVMFInfoStartOfData event received for %s",
                            iDatapathList[aDatapathIndex].iTrackInfo->getTrackMimeType().get_cstr()));

            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                            (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() PVMFInfoStartOfData event received for %s, iNumPendingSkipCompleteEvent=%d iNumPVMFInfoStartOfDataPending=%d",
                             iDatapathList[aDatapathIndex].iTrackInfo->getTrackMimeType().get_cstr(),
                             iNumPendingSkipCompleteEvent, iNumPVMFInfoStartOfDataPending));

            uint32 *data = (uint32*) aEvent.GetEventData();
            uint32 streamID = *data;
            if (streamID != iStreamID)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                                (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() PVMFInfoStartOfData event received for previous streamId ... Ignoring"));
                // received StartOfData for previous streamId, ignoring these events
                break;
            }

            if (iNumPVMFInfoStartOfDataPending > 0)
            {
                --iNumPVMFInfoStartOfDataPending;
            }

            uint32 clipId = *(data + 1);
            if (iCurrentPlaybackClipId != clipId)
            {
                // only during clip transition
                IssueSourceNodeAudioSinkEvent(aEvent);
            }

            if (iNumPVMFInfoStartOfDataPending == 0)
            {
                iCurrentPlaybackClipId = clipId;
                UpdateCurrentClipSourceDuration();
                if (iNumPendingSkipCompleteEvent == 0)
                {
                    if (iWatchDogTimer->IsBusy())
                    {
                        iWatchDogTimer->Cancel();
                    }
                    //check engine internal state here prior to starting the clock
                    //this is to make sure that we do not start the clock in case engine is still
                    //auto-paused (think usecase: auto-pause, setplaybackrange, auto-resume)
                    if (iState == PVP_ENGINE_STATE_STARTED)
                    {
                        // start the clock only if engine is in started state
                        StartPlaybackClock();
                        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() - PlayClock Started"));
                        // Process any pending command
                        RunIfNotReady();
                    }
                    else if (iState == PVP_ENGINE_STATE_PAUSED)
                    {
                        if (iNumPendingDatapathCmd == 0)
                        {
                            // Skip is complete and data is ready
                            // Now, pause the nodes
                            // @TODO - Check if there is a resume command already queued in.
                            //         If so, complete the current SetPlaybackRange command,
                            //         and in DoResume() ignore the "invalid state".
                            PVMFStatus retval =  DoPauseDatapath(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext());
                            if (retval != PVMFSuccess)
                            {
                                AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_SET_PLAYBACK_RANGE, retval, NULL);
                            }
                        }
                        else
                        {
                            // The StartOfData has reached the engine even before the nodes have
                            // completed the Start() command. Wait for Start() to finish, and then
                            // pause the nodes.
                            AddCommandToQueue(PVP_ENGINE_COMMAND_PAUSE_DUE_TO_SET_PLAYBACK_RANGE, NULL, NULL, NULL, false);
                        }
                    }
                }
            }
            //else it could mean duplicate or old PVMFInfoStartOfData, ignore both
        }
        break;
        case PVMFInfoEndOfData:
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() PVMFInfoEndOfData event received for %s",
                            iDatapathList[aDatapathIndex].iTrackInfo->getTrackMimeType().get_cstr()));

            uint32 *data = (uint32*) aEvent.GetEventData();
            uint32 streamID = *data;

            if (streamID != iStreamID)
            {
                // received EndOfData for previous streamId, ignoring these events
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
                                (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() PVMFInfoEndOfData event received for %s with StreamID=%d, Engine StreamID=%d",
                                 iDatapathList[aDatapathIndex].iTrackInfo->getTrackMimeType().get_cstr(),
                                 streamID, iStreamID));
                break;
            }

            if (iNumPVMFInfoStartOfDataPending)
            {
                iNumPVMFInfoStartOfDataPending--;
            }
            if (iDatapathList[aDatapathIndex].iDatapath && iDatapathList[aDatapathIndex].iEndOfDataReceived == false)
            {
                iDatapathList[aDatapathIndex].iEndOfDataReceived = true;
                // If all datapath received EOS, initiate a pause-due-to-EOS
                if (AllDatapathReceivedEndOfData() == true)
                {
                    IssueSourceNodeAudioSinkEvent(aEvent);
                    iClipsCompleted++;
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                                    (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() - iClipsCompleted = %d, totalnumclips = %d", iClipsCompleted, iDataSource->GetNumClips()));

                    // scenarios where playlist playback is considered complete.
                    // If sum of number of clips played back and corrupted clips in list equates to total clips queued to Source Node.
                    if ((iNumClipsQueued == iClipsCompleted + iClipsCorrupted))
                    {
                        if (iState != PVP_ENGINE_STATE_PAUSING)
                        {
                            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() Issue Pause due to end of clip"));
                            AddCommandToQueue(PVP_ENGINE_COMMAND_PAUSE_DUE_TO_ENDOFCLIP, NULL, NULL, NULL, false);
                        }
                    }
                    else
                    {
                        // Send position update to the application.
                        SendPositionStatusUpdate();
                        iStartNPT = 0;
                        iPlaybackClock.UpdateNPTClockPosition(iStartNPT, (iPlaybackDirection < 0) ? true : false);
                        ResetDatapathEndOfDataStatus();
                    }
                }
            }
            else
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() PVMFInfoEndOfData event received for non-active or already-ended datapath. Asserting"));
                OSCL_ASSERT(false);
            }
        }
        break;

        case PVMFInfoDataDiscarded:
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() PVMFInfoDataDiscarded event received"));
            SendInformationalEvent(event, NULL, aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
            break;

        case PVMFInfoVideoTrackFallingBehind:
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() PVMFInfoVideoTrackFallingBehind event received"));
            SendInformationalEvent(event, NULL, aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
            if (iGracefulDegradationEnable &&
                    (iDatapathList[aDatapathIndex].iDecNodeCapConfigIF != NULL))
            {
                PvmiKvp kvpparam;
                PvmiKvp* retkvp = NULL;
                OSCL_StackString<64> kvpparamkey;

                kvpparamkey = _STRLIT_CHAR(PVMF_DECODER_KEY_FRAME_ONLY_MODE_KEY);
                kvpparam.value.bool_value = true;

                kvpparam.key = kvpparamkey.get_str();
                iDatapathList[aDatapathIndex].iDecNodeCapConfigIF->setParametersSync(NULL, &kvpparam, 1, retkvp);

                if (retkvp != NULL)
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() Configuring dec node for player use via cap-config IF failed"));
                }
            }
            break;

        default:
            // Do nothing but log it
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() Do nothing for this event %d", event));
            break;
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() Out"));
}


bool PVPlayerEngine::AllDatapathReceivedEndOfData()
{
    // Return false if any active datapath hasn't
    // received EOS yet. Else true.
    for (uint32 i = 0; i < iDatapathList.size(); ++i)
    {
        if (iDatapathList[i].iDatapath &&
                iDatapathList[i].iEndOfDataReceived == false)
        {
            return false;
        }
    }

    return true;
}

void PVPlayerEngine::ResetDatapathEndOfDataStatus()
{
    for (uint32 i = 0; i < iDatapathList.size(); ++i)
    {
        if (iDatapathList[i].iDatapath)
        {
            iDatapathList[i].iEndOfDataReceived = false;
        }
    }
}

void PVPlayerEngine::SendEndOfClipInfoEvent(PVMFStatus aStatus, PVInterface* aExtInterface)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::SendEndOfClipInfoEvent() In"));

    // If paused succeeded or already paused
    if (aStatus == PVMFSuccess || aStatus == PVMFErrInvalidState)
    {
        // Set the flag so we can disable resume unless user stops, repositions, or changes directrion
        iPlaybackPausedDueToEndOfClip = true;

        PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
        PVMFBasicErrorInfoMessage* infomsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoEndOfClipReached, puuid, NULL));
        SendInformationalEvent(PVMFInfoEndOfData, OSCL_STATIC_CAST(PVInterface*, infomsg));
        infomsg->removeRef();
    }
    else
    {
        SendErrorEvent(aStatus, aExtInterface);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::SendEndOfClipInfoEvent() Out"));
}


void PVPlayerEngine::SendEndTimeReachedInfoEvent(PVMFStatus aStatus, PVInterface* aExtInterface)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::SendEndTimeReachedInfoEvent() In"));

    if (aStatus == PVMFSuccess)
    {
        iPlaybackPausedDueToEndOfTimeReached = true;

        PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
        PVMFBasicErrorInfoMessage* infomsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoEndTimeReached, puuid, NULL));
        SendInformationalEvent(PVMFInfoEndOfData, OSCL_STATIC_CAST(PVInterface*, infomsg));
        infomsg->removeRef();
    }
    else
    {
        SendErrorEvent(aStatus, aExtInterface);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::SendEndTimeReachedInfoEvent() Out"));
}


void PVPlayerEngine::SendSourceUnderflowInfoEvent(PVMFStatus aStatus, PVInterface* aExtInterface)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::SendSourceUnderflowInfoEvent() In"));

    if (aStatus == PVMFSuccess || aStatus == PVMFErrNotSupported)
    {
        if (iDataReadySent)
        {
            iDataReadySent = false;
            SendInformationalEvent(PVMFInfoUnderflow);
        }
    }
    else if (aStatus == PVMFErrCancelled)
    {
        // Do nothing since the auto-pause was cancelled
    }
    else
    {
        SendErrorEvent(aStatus, aExtInterface);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::SendSourceUnderflowInfoEvent() Out"));
}


void PVPlayerEngine::SendSourceDataReadyInfoEvent(PVMFStatus aStatus, PVInterface* aExtInterface)
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::SendSourceDataReadyInfoEvent() In"));


    if (aStatus == PVMFSuccess || aStatus == PVMFErrNotSupported)
    {
        // send DataReady event only if it is not sent earlier and if EOS is not reported.
        // It is possible that for Streaming repositioning to end use-cases engine receives
        // EOS before prepare completes, in that case suppress DataReady event.
        if (!iDataReadySent && !iPlaybackPausedDueToEndOfClip)
        {
            iDataReadySent = true;
            SendInformationalEvent(PVMFInfoDataReady);
        }
    }
    else if (aStatus == PVMFErrCancelled)
    {
        // Do nothing since the auto-resume was cancelled
    }
    else
    {
        SendErrorEvent(aStatus, aExtInterface);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::SendSourceDataReadyInfoEvent() Out"));
}


PVMFErrorInfoMessageInterface* PVPlayerEngine::GetErrorInfoMessageInterface(PVInterface& aInterface)
{
    PVMFErrorInfoMessageInterface* extiface = NULL;
    PVInterface* temp = NULL;
    if (aInterface.queryInterface(PVMFErrorInfoMessageInterfaceUUID, temp))
    {
        extiface = OSCL_STATIC_CAST(PVMFErrorInfoMessageInterface*, temp);
        return extiface;
    }
    else
    {
        return NULL;
    }
}


void PVPlayerEngine::StartPlaybackStatusTimer(void)
{
    // Check if playback position reporting is enabled
    if (!iPBPosEnable || iPlayStatusTimerEnabled)
        return;
    // To get regular play status events
    iPlayStatusTimerEnabled = true;

    iClockNotificationsInf->SetCallbackDeltaTime(iPBPosStatusInterval,
            iPlayStatusCallbackTimerMarginWindow, (PVMFMediaClockNotificationsObs*)this, false, NULL,
            iPlayStatusCallbackTimerID);
}


void PVPlayerEngine::StopPlaybackStatusTimer(void)
{

    // Stop the playback position status timer
    iPlayStatusTimerEnabled = false;
    if (iClockNotificationsInf && iPlayStatusCallbackTimerID)
    {
        iClockNotificationsInf->CancelCallback(iPlayStatusCallbackTimerID, false);
        iPlayStatusCallbackTimerID = 0;
    }
}

bool PVPlayerEngine::CheckForSourceRollOver()
{
    uint32 alternates = iDataSource->GetNumAlternateSourceFormatTypes();
    if ((alternates > 0) && (iAlternateSrcFormatIndex < alternates))
    {
        return true;
    }
    return false;
}

PVMFStatus PVPlayerEngine::SetupDataSourceForUnknownURLAccess()
{
    if (iDataSource == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::SetupDataSourceForUnknownURLAccess() - No Data Source"));
        return PVMFErrInvalidState;
    }
    else
    {
        /*
         * In case of unknown url, here is the sequence that engine would attempt:
         *  1) First Alternate source format would be PVMF_DATA_SOURCE_RTSP_URL,
         *  implying that we would attempt a RTSP streaming session
         *
         *  2) Primary source format would be set to PVMF_DATA_SOURCE_HTTP_URL,
         *  implying that we would attempt a progressive download first.
         *
         *  3) Second Alternate source format would be PVMF_MIME_DATA_SOURCE_RTSP_TUNNELLING,
         *  implying that we would attempt cloaking session(RTP packets retrievd in tcp
         *  connection.
         *
         *  4) Third Alternate source format would be PVMF_DATA_SOURCE_REAL_HTTP_CLOAKING_URL,
         *  implying that we would attempt a real media cloaking session
         *
         *  5) Fourth alternate source format would be PVMF_DATA_SOURCE_MS_HTTP_STREAMING_URL,
         *  implying that we would attempt a MS HTTP streaming session
         */
        iSourceFormatType = PVMF_MIME_DATA_SOURCE_RTSP_URL; ;
        if (iDataSource->SetAlternateSourceFormatType(PVMF_MIME_DATA_SOURCE_HTTP_URL) != true)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::SetupDataSourceForUnknownURLAccess() - SetAlternateSourceFormatType Failed"));
            return PVMFFailure;
        }
        if (iDataSource->SetAlternateSourceFormatType(PVMF_MIME_DATA_SOURCE_RTSP_TUNNELLING) != true)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::SetupDataSourceForUnknownURLAccess() - SetAlternateSourceFormatType Failed"));
            return PVMFFailure;
        }
        if (iDataSource->SetAlternateSourceFormatType(PVMF_MIME_DATA_SOURCE_REAL_HTTP_CLOAKING_URL) != true)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::SetupDataSourceForUnknownURLAccess() - SetAlternateSourceFormatType Failed"));
            return PVMFFailure;
        }
        if (iDataSource->SetAlternateSourceFormatType(PVMF_MIME_DATA_SOURCE_MS_HTTP_STREAMING_URL) != true)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::SetupDataSourceForUnknownURLAccess() - SetAlternateSourceFormatType Failed"));
            return PVMFFailure;
        }
        return PVMFSuccess;
    }
}

/* scan thru aKvpValue, create a new PvmiKvp object and push
 * than onto iPvmiKvpCapNConfig.
 *  return PVMFSuccess unless allocation error
 */
PVMFStatus PVPlayerEngine:: VerifyAndSaveKVPValues(PvmiKvp *aKvpValue)
{

    PvmiKvp* KvpCapNConfig = (PvmiKvp *)OSCL_MALLOC(sizeof(PvmiKvp));
    if (! KvpCapNConfig)  return PVMFErrNoMemory;
    oscl_memcpy(KvpCapNConfig, aKvpValue, sizeof(PvmiKvp));


    KvpCapNConfig->key = (char*)OSCL_MALLOC(oscl_strlen(aKvpValue->key) + 1);
    if (! KvpCapNConfig->key)  return PVMFErrNoMemory;
    oscl_strncpy(KvpCapNConfig->key, aKvpValue->key, oscl_strlen(aKvpValue->key) + 1);


    // all the values have copied automatically so just need to allocate memory of pointer type.

    if (oscl_strstr(aKvpValue->key, _STRLIT_CHAR("valtype=wchar*")) != NULL)
    {
        KvpCapNConfig->value.pWChar_value = (oscl_wchar*)OSCL_MALLOC((oscl_strlen(aKvpValue->value.pWChar_value) + 1) * sizeof(oscl_wchar));
        if (! KvpCapNConfig->value.pWChar_value)  return PVMFErrNoMemory;
        oscl_strncpy(KvpCapNConfig->value.pWChar_value, aKvpValue->value.pWChar_value, oscl_strlen(aKvpValue->value.pWChar_value) + 1);

    }
    else if (oscl_strstr(aKvpValue->key, _STRLIT_CHAR("valtype=char*")) != NULL)
    {
        KvpCapNConfig->value.pChar_value = (char*)OSCL_MALLOC(oscl_strlen(aKvpValue->value.pChar_value) + 1);
        if (! KvpCapNConfig->value.pChar_value)  return PVMFErrNoMemory;
        oscl_strncpy(KvpCapNConfig->value.pChar_value, aKvpValue->value.pChar_value, oscl_strlen(aKvpValue->value.pChar_value) + 1);

    }
    else if (oscl_strstr(aKvpValue->key, _STRLIT_CHAR("valtype=uint8*")) != NULL)
    {
        KvpCapNConfig->value.pUint8_value = (uint8*)OSCL_MALLOC(oscl_strlen((char *)aKvpValue->value.pUint8_value) + 1);
        if (! KvpCapNConfig->value.pUint8_value)  return PVMFErrNoMemory;
        oscl_memcpy(KvpCapNConfig->value.pUint8_value, aKvpValue->value.pUint8_value, oscl_strlen((char *)aKvpValue->value.pUint8_value) + 1);

    }
    else if (oscl_strstr(aKvpValue->key, _STRLIT_CHAR("valtype=int32*")) != NULL)
    {
        KvpCapNConfig->value.pInt32_value = (int32*)OSCL_MALLOC(sizeof(int32));
        if (! KvpCapNConfig->value.pInt32_value)  return PVMFErrNoMemory;
        oscl_memcpy(KvpCapNConfig->value.pInt32_value, aKvpValue->value.pInt32_value, sizeof(int32));
        // @TODO: Future support will be based on length , currently support only one element
    }
    else if (oscl_strstr(aKvpValue->key, _STRLIT_CHAR("valtype=uint32*")) != NULL)
    {
        KvpCapNConfig->value.pUint32_value = (uint32*)OSCL_MALLOC(sizeof(uint32));
        if (! KvpCapNConfig->value.pUint32_value)  return PVMFErrNoMemory;
        oscl_memcpy(KvpCapNConfig->value.pUint32_value, aKvpValue->value.pUint32_value, sizeof(uint32));
        // @TODO: Future support will be based on length, currently support only one element
    }
    else if (oscl_strstr(aKvpValue->key, _STRLIT_CHAR("valtype=int64*")) != NULL)
    {
        KvpCapNConfig->value.pInt64_value = (int64*)OSCL_MALLOC(sizeof(int64));
        if (! KvpCapNConfig->value.pInt64_value)  return PVMFErrNoMemory;
        oscl_memcpy(KvpCapNConfig->value.pInt64_value, aKvpValue->value.pInt64_value, sizeof(int64));
        // @TODO: Future support will be based on length, currently support only one element
    }
    else if (oscl_strstr(aKvpValue->key, _STRLIT_CHAR("valtype=uint64*")) != NULL)
    {
        KvpCapNConfig->value.pUint64_value = (uint64*)OSCL_MALLOC(sizeof(uint64));
        if (! KvpCapNConfig->value.pUint64_value)  return PVMFErrNoMemory;
        oscl_memcpy(KvpCapNConfig->value.pUint64_value, aKvpValue->value.pUint64_value, sizeof(uint64));
        // @TODO: Future support will be based on length, currently support only one element
    }
    else if (oscl_strstr(aKvpValue->key, _STRLIT_CHAR("valtype=float*")) != NULL)
    {
        KvpCapNConfig->value.pFloat_value = (float*)OSCL_MALLOC(sizeof(float));
        if (! KvpCapNConfig->value.pFloat_value)  return PVMFErrNoMemory;
        oscl_memcpy(KvpCapNConfig->value.pFloat_value, aKvpValue->value.pFloat_value, sizeof(float));
        // @TODO: Future support will be based on length, currently support only one element
    }
    else if (oscl_strstr(aKvpValue->key, _STRLIT_CHAR("valtype=double*")) != NULL)
    {
        KvpCapNConfig->value.pDouble_value = (double*)OSCL_MALLOC(sizeof(double));
        if (! KvpCapNConfig->value.pDouble_value)  return PVMFErrNoMemory;
        oscl_memcpy(KvpCapNConfig->value.pDouble_value, aKvpValue->value.pDouble_value, sizeof(double));
        // @TODO: Future support will be based on length, currently support only one element
    }
    else if (oscl_strstr(aKvpValue->key, _STRLIT_CHAR("valtype=range_int32")) != NULL)
    {
        KvpCapNConfig->value.key_specific_value = (void*)OSCL_MALLOC(sizeof(range_int32));
        if (! KvpCapNConfig->value.key_specific_value)  return PVMFErrNoMemory;
        oscl_memcpy(KvpCapNConfig->value.key_specific_value, aKvpValue->value.key_specific_value, sizeof(range_int32));
        // @TODO: Future support will be based on length, currently support only one element
    }
    else if (oscl_strstr(aKvpValue->key, _STRLIT_CHAR("valtype=range_uint32")) != NULL)
    {
        KvpCapNConfig->value.key_specific_value = (void*)OSCL_MALLOC(sizeof(range_uint32));
        if (! KvpCapNConfig->value.key_specific_value)  return PVMFErrNoMemory;
        oscl_memcpy(KvpCapNConfig->value.key_specific_value, aKvpValue->value.key_specific_value, sizeof(range_uint32));
        // @TODO: Future support will be based on length, currently support only one element
    }

    iPvmiKvpCapNConfig.push_back(KvpCapNConfig);
    return PVMFSuccess;
}


void PVPlayerEngine::SetRollOverKVPValues()
{
    PvmiKvp *SaveKvp;
    PvmiKvp *ErrorKVP;

    for (uint i = 0; i < iPvmiKvpCapNConfig.size(); i++)
    {
        SaveKvp = iPvmiKvpCapNConfig[i];
        setParametersSync(NULL, SaveKvp, 1 , ErrorKVP);

        if (ErrorKVP != NULL)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::SetRollOverKVPValues() Configuring cap-config failed"));
        }
    }

}

void PVPlayerEngine::DeleteKVPValues()
{
    uint i = 0;
    while (i < iPvmiKvpCapNConfig.size())
    {
        PvmiKvp **Setkvp = iPvmiKvpCapNConfig.begin();

        if (oscl_strstr((*Setkvp)->key, _STRLIT_CHAR("valtype=wchar*")) != NULL)
        {
            OSCL_FREE((*Setkvp)->value.pWChar_value);
            (*Setkvp)->value.pWChar_value = NULL;

        }
        else if (oscl_strstr((*Setkvp)->key, _STRLIT_CHAR("valtype=char*")) != NULL)
        {
            OSCL_FREE((*Setkvp)->value.pChar_value);
            (*Setkvp)->value.pChar_value = NULL;
        }
        else if (oscl_strstr((*Setkvp)->key, _STRLIT_CHAR("valtype=uint8*")) != NULL)
        {
            OSCL_FREE((*Setkvp)->value.pUint8_value);
            (*Setkvp)->value.pUint8_value = NULL;
        }

        else if (oscl_strstr((*Setkvp)->key, _STRLIT_CHAR("valtype=int32*")) != NULL)
        {
            OSCL_FREE((*Setkvp)->value.pInt32_value);
            (*Setkvp)->value.pInt32_value = NULL;

        }
        else if (oscl_strstr((*Setkvp)->key, _STRLIT_CHAR("valtype=uint32*")) != NULL)
        {
            OSCL_FREE((*Setkvp)->value.pUint32_value);
            (*Setkvp)->value.pUint32_value = NULL;

        }
        else if (oscl_strstr((*Setkvp)->key, _STRLIT_CHAR("valtype=int64*")) != NULL)
        {
            OSCL_FREE((*Setkvp)->value.pInt64_value);
            (*Setkvp)->value.pInt64_value = NULL;

        }
        else if (oscl_strstr((*Setkvp)->key, _STRLIT_CHAR("valtype=uint64*")) != NULL)
        {
            OSCL_FREE((*Setkvp)->value.pUint64_value);
            (*Setkvp)->value.pUint64_value = NULL;
        }
        else if (oscl_strstr((*Setkvp)->key, _STRLIT_CHAR("valtype=float*")) != NULL)
        {
            OSCL_FREE((*Setkvp)->value.pFloat_value);
            (*Setkvp)->value.pFloat_value = NULL;
        }
        else if (oscl_strstr((*Setkvp)->key, _STRLIT_CHAR("valtype=double*")) != NULL)
        {
            OSCL_FREE((*Setkvp)->value.pDouble_value);
            (*Setkvp)->value.pDouble_value = NULL;
        }
        else if ((oscl_strstr((*Setkvp)->key, _STRLIT_CHAR("valtype=range_int32")) != NULL) ||
                 (oscl_strstr((*Setkvp)->key, _STRLIT_CHAR("valtype=range_uint32")) != NULL))
        {
            OSCL_FREE((*Setkvp)->value.key_specific_value);
            (*Setkvp)->value.key_specific_value = NULL;
        }

        OSCL_FREE((*Setkvp)->key);
        (*Setkvp)->key = NULL;

        OSCL_FREE(*Setkvp);
        *Setkvp = NULL;

        iPvmiKvpCapNConfig.erase(iPvmiKvpCapNConfig.begin());
    }

}


void PVPlayerEngine::PVPlayerWatchdogTimerEvent()
{
    //check engine internal state here prior to starting the clock
    //this is to make sure that we do not start the clock in case engine is still
    //auto-paused (think usecase: auto-pause, setplaybackrange, auto-resume)
    if (iState == PVP_ENGINE_STATE_STARTED)
    {
        // start the clock only if engine is in started state
        StartPlaybackClock();
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::PVPlayerWatchdogTimerEvent() WatchDog timer expired"));
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::PVPlayerWatchdogTimerEvent() WatchDog timer expired"));
    }
}

void PVPlayerEngine::StartPlaybackClock()
{
    if (iWatchDogTimer->IsBusy())
    {
        iWatchDogTimer->Cancel();
    }

    if (iPlaybackClock.GetState() == PVMFMediaClock::RUNNING)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "PVPlayerEngine::StartPlaybackClock() clock already started"));
        return;
    }

    iPlaybackClock.Start();
    // Notify all sink nodes that have sync control IF that clock has started
    for (uint32 i = 0; i < iDatapathList.size(); ++i)
    {
        if (iDatapathList[i].iDatapath && iDatapathList[i].iSinkNodeSyncCtrlIF)
        {
            iDatapathList[i].iSinkNodeSyncCtrlIF->ClockStarted();
        }
    }

    // To get regular play status events
    StartPlaybackStatusTimer();

    // Restart the end time check if enabled
    if (iEndTimeCheckEnabled)
    {
        // Determine the check cycle based on interval setting in milliseconds
        // and timer frequency of 100 millisec
        int32 checkcycle = iEndTimeCheckInterval / 100;
        if (checkcycle == 0)
        {
            ++checkcycle;
        }
        iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_ENDTIMECHECK);
        iPollingCheckTimer->Request(PVPLAYERENGINE_TIMERID_ENDTIMECHECK, 0, checkcycle, this, true);
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::StartPlaybackClock() StartNPT %d StartTS %d", iStartNPT, iStartMediaDataTS));
}

PVMFStatus PVPlayerEngine::GetCompleteList(PVMFMediaPresentationInfo& aList)
{
    if (iSourceNodeTrackSelIF)
    {
        PVPlayerState state = GetPVPlayerState();
        if ((state == PVP_STATE_INITIALIZED) ||
                (state == PVP_STATE_PREPARED) ||
                (state == PVP_STATE_STARTED) ||
                (state == PVP_STATE_PAUSED))
        {
            aList.Reset();
            PVMFStatus retval = PVMFFailure;
            int32 leavecode = 0;
            OSCL_TRY(leavecode, retval = iSourceNodeTrackSelIF->GetMediaPresentationInfo(aList));
            OSCL_FIRST_CATCH_ANY(leavecode,
                                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::GetCompleteList() GetMediaPresentationInfo on iSourceNodeTrackSelIF did a leave!"));
                                 return PVMFFailure);
            if (retval != PVMFSuccess)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::GetCompleteList() GetMediaPresentationInfo() call on source node failed"));
            }
            return retval;
        }
    }
    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::GetCompleteList() iSourceNodeTrackSelIF Invalid"));
    return PVMFFailure;
}

PVMFStatus PVPlayerEngine::ReleaseCompleteList(PVMFMediaPresentationInfo& aList)
{
    aList.Reset();
    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::GetPlayableList(PVMFMediaPresentationInfo& aList)
{
    PVPlayerState state = GetPVPlayerState();
    if ((state == PVP_STATE_PREPARED) ||
            (state == PVP_STATE_STARTED) ||
            (state == PVP_STATE_PAUSED))
    {
        aList = iPlayableList;
        if (aList.getNumTracks() == 0)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::GetPlayableList() No tracks"));
            return PVMFFailure;
        }
        return PVMFSuccess;
    }
    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::GetPlayableList() Invalid Engine State"));
    return PVMFErrInvalidState;
}

PVMFStatus PVPlayerEngine::ReleasePlayableList(PVMFMediaPresentationInfo& aList)
{
    aList.Reset();
    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::GetSelectedList(PVMFMediaPresentationInfo& aList)
{
    PVPlayerState state = GetPVPlayerState();
    if ((state == PVP_STATE_PREPARED) ||
            (state == PVP_STATE_STARTED) ||
            (state == PVP_STATE_PAUSED))
    {
        aList.Reset();
        aList.setPresentationType(iPlayableList.getPresentationType());
        aList.setSeekableFlag(iPlayableList.IsSeekable());
        aList.SetDurationAvailable(iPlayableList.IsDurationAvailable());
        aList.setDurationValue(iPlayableList.getDurationValue());
        aList.setDurationTimeScale(iPlayableList.getDurationTimeScale());
        for (uint32 i = 0; i < iDatapathList.size(); ++i)
        {
            if (iDatapathList[i].iTrackInfo != NULL)
            {
                aList.addTrackInfo(*(iDatapathList[i].iTrackInfo));
            }
        }
        if (aList.getNumTracks() == 0)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::GetSelectedList() No tracks"));
            return PVMFFailure;
        }
        return PVMFSuccess;
    }
    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::GetSelectedList() Invalid Engine State"));
    return PVMFErrInvalidState;
}

PVMFStatus PVPlayerEngine::ReleaseSelectedList(PVMFMediaPresentationInfo& aList)
{
    aList.Reset();
    return PVMFSuccess;
}

PVMFStatus PVPlayerEngine::RegisterHelperObject(PVMFTrackSelectionHelper* aObject)
{
    if (aObject != NULL)
    {
        if (iTrackSelectionHelper != NULL)
        {
            return PVMFErrAlreadyExists;
        }
    }
    iTrackSelectionHelper = aObject;
    return PVMFSuccess;
}

void PVPlayerEngine::ResetReposVariables(bool aResetAll)
{
    if (aResetAll)
    {
        iStreamID = 0;
        iCurrentBeginPosition.iIndeterminate = true;
        iCurrentEndPosition.iIndeterminate = true;
        iQueuedBeginPosition.iIndeterminate = true;
        iQueuedEndPosition.iIndeterminate = true;
    }
    if (iWatchDogTimer != NULL)
    {
        if (iWatchDogTimer->IsBusy())
        {
            iWatchDogTimer->Cancel();
        }
    }
    iNumPendingSkipCompleteEvent = 0;
    iNumPVMFInfoStartOfDataPending = 0;
    iTargetNPT = 0;
    iActualNPT = 0;
    iActualMediaDataTS = 0;
    iSkipMediaDataTS = 0;
}

PVMFStatus PVPlayerEngine::DoErrorHandling()
{
    //pls note that we come into this method twice, in case of error handling
    //first time, we come here to start the error handling seq (cancelall if any, followed by reset)
    //second time, we come here when all resets are complete to cleanup and send command completes
    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoErrorHandling() In"));
    // Stop the playback clock
    iPlaybackClock.Stop();
    StopPlaybackStatusTimer();

    // 1st check if anything needs to be cancelled on Source Node or Datapaths
    if (!iCurrentContextList.empty())
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::DoErrorHandling() Some Command is being processed, cancel it"));
        for (uint32 i = 0; i < iCurrentContextList.size(); ++i)
        {
            if (iCurrentContextList[i]->iNode)
            {
                if (iCurrentContextList[i]->iNode == iSourceNode)
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoErrorHandling() Cmd Pending on Source node, should never happend, asserting"));
                    OSCL_ASSERT(false);
                }
            }
        }

        // error handling code set engine state to resetting
        SetEngineState(PVP_ENGINE_STATE_RESETTING);
        iRollOverState = RollOverStateIdle; //reset roll over state to Idle, as engine is resetting itself
        // Since there is a pending node or datapath, cancel it
        PVMFStatus status = DoCancelPendingNodeDatapathCommand();
        if (status == PVMFPending)
        {
            // There are some commands which need to be cancelled so wait for cancel complete
            // once cancels complete, we would start the reset sequence from either
            // NodeCommandComplete, HandlePlayerDataPathEvent, RecognizeComplete
            return PVMFPending;
        }
        // if there is nothing to cancel move forward to reset.
    }

    // move on to resetting Source Nodes and Datapaths
    if (iSourceNode)
    {
        int32 leavecode = 0;
        // call reset on source node if not in created state
        if (iSourceNode->GetState() != EPVMFNodeCreated)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                            (0, "PVPlayerEngine::DoErrorHandling() Issue reset on Source Node"));
            // error handling code set engine state to resetting
            SetEngineState(PVP_ENGINE_STATE_RESETTING);
            DereferenceLicenseInterface();

            iRollOverState = RollOverStateIdle; //reset roll over state to Idle, as engine is resetting itself

            PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, -1, NULL, -1);

            PVMFCommandId cmdid = -1;
            leavecode = 0;
            OSCL_TRY(leavecode, cmdid = iSourceNode->Reset(iSourceNodeSessionId, (OsclAny*)context));
            OSCL_FIRST_CATCH_ANY(leavecode,

                                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                                                 (0, "PVPlayerEngine::DoErrorHandling() Reset on iSourceNode did a leave!"));
                                 FreeEngineContext(context);
                                 OSCL_ASSERT(false);
                                 return PVMFFailure);

            return PVMFPending;
        }
    }

    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                    (0, "PVPlayerEngine::DoErrorHandling() Source node is deleted or in created state, so start removing sinks"));

    // Now delete the datapath.
    DoRemoveAllSinks();

    // Remove the datasource after the command completes.
    // If there is a command to be completed, it is important to
    // remove the datasource after the command completes because
    // the extended error messages still could need access to the
    // dynamically loadable library's address space which could
    // contain the virtual table.
    iRemoveDataSource = true;

    // reset all repos related variables
    ResetReposVariables(true);

    SetEngineState(PVP_ENGINE_STATE_IDLE);

    // Send the command completion if there is any command in Current command
    if (!iCurrentCmd.empty())
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::DoErrorHandling() Complete the engine command being processed"));
        if (iCommandCompleteErrMsgInErrorHandling)
        {
            EngineCommandCompleted(iCurrentCmd[0].GetCmdId(),
                                   iCurrentCmd[0].GetContext(),
                                   iCommandCompleteStatusInErrorHandling,
                                   OSCL_STATIC_CAST(PVInterface*, iCommandCompleteErrMsgInErrorHandling));
            iCommandCompleteErrMsgInErrorHandling->removeRef();
            iCommandCompleteErrMsgInErrorHandling = NULL;
        }
        else
        {
            EngineCommandCompleted(iCurrentCmd[0].GetCmdId(),
                                   iCurrentCmd[0].GetContext(),
                                   iCommandCompleteStatusInErrorHandling);
        }
    }
    else if (iDataSource)
    {
        RemoveDataSourceSync(*iDataSource);
        iRemoveDataSource = false;
    }

    // just send the error handling complete event
    SendInformationalEvent(PVMFInfoErrorHandlingComplete, NULL);

    //Reset the variable iStartIssuedOnEngine
    iStartIssuedOnEngine = false;

    PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoErrorHandling() Out"));

    return PVMFSuccess;
}

bool PVPlayerEngine::CheckForPendingErrorHandlingCmd()
{
    //if an error handling cmd had been queued previously
    //it must be in top, since error handling cmds have the
    //highest priority and pending cmds queue is a priority
    //queue
    bool retval = false;
    if (!iPendingCmds.empty())
    {
        switch (iPendingCmds.top().GetCmdType())
        {
            case PVP_ENGINE_COMMAND_ERROR_HANDLING_ADD_DATA_SOURCE:
            case PVP_ENGINE_COMMAND_ERROR_HANDLING_INIT:
            case PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE:
            case PVP_ENGINE_COMMAND_ERROR_HANDLING_PAUSE:
            case PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME:
            case PVP_ENGINE_COMMAND_ERROR_HANDLING_SET_PLAYBACK_RANGE:
            case PVP_ENGINE_COMMAND_ERROR_HANDLING_SET_PLAYBACK_RATE:
            case PVP_ENGINE_COMMAND_ERROR_HANDLING_STOP:
            case PVP_ENGINE_COMMAND_ERROR_HANDLING_CANCEL_ALL_COMMANDS:
            case PVP_ENGINE_COMMAND_ERROR_HANDLING_GENERAL:
                retval = true;
                break;

            default:
                break;
        }
    }
    return retval;
}

PVMFStatus PVPlayerEngine::IssueNodeCancelCommand(PVPlayerEngineContext* aCurrentListContext, PVMFSessionId aSessionId, OsclAny* aNumberCancelCmdPending)
{
    PVMFStatus leavecode = 0;
    OSCL_TRY(leavecode, aCurrentListContext->iNode->CancelAllCommands(aSessionId, aNumberCancelCmdPending));
    OSCL_FIRST_CATCH_ANY(leavecode,;);
    return leavecode;
}

PVMFStatus PVPlayerEngine::IssueDatapathCancelCommand(PVPlayerEngineContext* aCurrentListContext, OsclAny* aNumberCancelCmdPending)
{
    PVMFStatus leavecode = 0;
    OSCL_TRY(leavecode, aCurrentListContext->iDatapath->CancelCommand(aNumberCancelCmdPending));
    OSCL_FIRST_CATCH_ANY(leavecode,;);
    return leavecode;
}

PVMFStatus PVPlayerEngine::IssueRecognizerRegistryCancel(OsclAny* aNumberCancelCmdPending)
{
    PVMFStatus leavecode = 0;
    OSCL_TRY(leavecode, iPlayerRecognizerRegistry.CancelQuery(aNumberCancelCmdPending));
    OSCL_FIRST_CATCH_ANY(leavecode,;);
    return leavecode;
}

PVMFStatus PVPlayerEngine::IssueSinkNodeInit(PVPlayerEngineDatapath* aDatapath, OsclAny* aCmdContext, PVMFCommandId &aCmdId)
{
    PVMFStatus leavecode = 0;
    OSCL_TRY(leavecode, aCmdId = aDatapath->iSinkNode->Init(aDatapath->iSinkNodeSessionId, aCmdContext));
    OSCL_FIRST_CATCH_ANY(leavecode,;);
    return leavecode;
}

PVMFStatus PVPlayerEngine::IssueSinkNodeReset(PVPlayerEngineDatapath* aDatapath, OsclAny* aCmdContext, PVMFCommandId &aCmdId)
{
    PVMFStatus leavecode = 0;
    OSCL_TRY(leavecode, aCmdId = aDatapath->iSinkNode->Reset(aDatapath->iSinkNodeSessionId, aCmdContext));
    OSCL_FIRST_CATCH_ANY(leavecode,;);
    return leavecode;
}

PVMFStatus PVPlayerEngine::IssueSinkSkipMediaData(PVPlayerEngineDatapath* aDatapath, bool aSFR, OsclAny* aCmdContext)
{
    PVMFStatus leavecode = 0;
    OSCL_TRY(leavecode, aDatapath->iSinkNodeSyncCtrlIF->SkipMediaData(aDatapath->iSinkNodeSessionId, iSkipMediaDataTS, iStreamID, aSFR, aCmdContext));
    OSCL_FIRST_CATCH_ANY(leavecode,;);
    return leavecode;
}

PVMFStatus PVPlayerEngine::IssueSourceSetDataSourcePosition(bool aIsPosUnitPlayList, OsclAny* aCmdContext)
{
    PVMFStatus leavecode = 0;
    if (aIsPosUnitPlayList)
    {
        OSCL_TRY(leavecode, iSourceNodePBCtrlIF->SetDataSourcePosition(iSourceNodeSessionId,
                 iDataSourcePosParams,
                 aCmdContext));

    }
    else
    {
        OSCL_TRY(leavecode, iSourceNodePBCtrlIF->SetDataSourcePosition(iSourceNodeSessionId,
                 iTargetNPT, iActualNPT, iActualMediaDataTS, iSeekToSyncPoint, iStreamID, aCmdContext));
    }
    OSCL_FIRST_CATCH_ANY(leavecode,;);
    return leavecode;
}

PVMFStatus PVPlayerEngine::IssueDecNodeInit(PVMFNodeInterface* aNode, PVMFSessionId aDecNodeSessionId, OsclAny* aCmdContext, PVMFCommandId &aCmdId)
{
    PVMFStatus leavecode = 0;
    OSCL_TRY(leavecode, aCmdId = aNode->Init(aDecNodeSessionId, aCmdContext));
    OSCL_FIRST_CATCH_ANY(leavecode,;);
    return leavecode;
}

PVMFStatus PVPlayerEngine::IssueDecNodeReset(PVMFNodeInterface* aNode, PVMFSessionId aDecNodeSessionId, OsclAny* aCmdContext, PVMFCommandId &aCmdId)
{
    PVMFStatus leavecode = 0;
    OSCL_TRY(leavecode, aCmdId = aNode->Reset(aDecNodeSessionId, aCmdContext));
    OSCL_FIRST_CATCH_ANY(leavecode,;);
    return leavecode;
}

PVMFStatus PVPlayerEngine::IssueQueryInterface(PVMFNodeInterface* aNode, PVMFSessionId aSessionId, const PVUuid aUuid, PVInterface*& aInterfacePtr, OsclAny* aCmdContext, PVMFCommandId& aCmdId)
{
    PVMFStatus leavecode = 0;
    OSCL_TRY(leavecode, aCmdId = aNode->QueryInterface(aSessionId, aUuid, aInterfacePtr, aCmdContext));
    OSCL_FIRST_CATCH_ANY(leavecode,;);
    return leavecode;
}

PVMFStatus PVPlayerEngine::DoSourceURLQueryFormatType(PVPlayerEngineContext* context, OsclFileHandle* fileHandle)
{
    PVMFStatus retval = PVMFErrNotSupported;
    int32 leavecode = 0;
    OSCL_TRY(leavecode, retval = iPlayerRecognizerRegistry.QueryFormatType(iDataSource->GetDataSourceURL(), *this, (OsclAny*) context, fileHandle));
    OSCL_FIRST_CATCH_ANY(leavecode,;);
    return retval;
}

PVMFStatus PVPlayerEngine::DoCancelGetLicense(PVMFCommandId aCmdId, PVPlayerEngineContext* context)
{
    PVMFStatus status = PVMFSuccess;
    int32 leavecode = 0;
    OSCL_TRY(leavecode, iCPMCancelGetLicenseCmdId = iCPMLicenseIF->CancelGetLicense(iSourceNodeSessionId, aCmdId, (OsclAny*)context));
    if (leavecode)
    {
        FreeEngineContext(context);
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
                        (0, "PVPlayerEngine::DoCancelGetLicense() - CancelGetLicense on iCPMLicenseIF did a leave!"));
        status = PVMFErrNotSupported;
    }
    return status;
}

void PVPlayerEngine::IssueSourceNodeAudioSinkEvent(const PVMFAsyncEvent& aEvent)
{
    bool retVal = false;
    int32 datapathIndex = -1;
    // Make sure there are no video tracks
    retVal = FindDatapathForTrackUsingMimeString(true, false, false, datapathIndex);
    if (retVal == false)
    {
        // Make sure there are no text tracks
        retVal = FindDatapathForTrackUsingMimeString(false, false, true, datapathIndex);
        if (retVal == false)
        {
            retVal = FindDatapathForTrackUsingMimeString(false, true, false, datapathIndex);
            if (retVal)
            {
                uint32 *data = (uint32*) aEvent.GetEventData();
                uint32 clipId = *(data + 1);
                uint8 localbuffer[8];
                oscl_memcpy(localbuffer, &clipId, sizeof(uint32));

                int32 eventType = aEvent.GetEventType();

                if (eventType == PVMFInfoStartOfData)
                {
                    if (iNumPVMFInfoStartOfDataPending == 0)
                    {
                        SendInformationalEvent(PVPlayerInfoClipPlaybackStarted, NULL, aEvent.GetEventData(), localbuffer, 8);
                    }
                }
                else // aEvent == PVMFInfoEndOfData
                {
                    SendInformationalEvent(PVPlayerInfoClipPlaybackEnded, NULL, aEvent.GetEventData(), localbuffer, 8);
                }
                if (clipId + 1 <= iDataSource->GetNumClips())
                {
                    iSourceNodeInitIF->AudioSinkEvent(eventType, clipId);
                }
            }
        }
    }
}

OSCL_EXPORT_REF void
PVPlayerInterface::GetSDKInfo
(
    PVSDKInfo& aSdkInfo
)
{
    aSdkInfo.iLabel = PVPLAYER_ENGINE_SDKINFO_LABEL;
    aSdkInfo.iDate  = PVPLAYER_ENGINE_SDKINFO_DATE;
}

void PVPlayerEngine::DereferenceLicenseInterface()
{
    if (iCPMLicenseIF)
    {
        iCPMLicenseIF->removeRef();
        iCPMLicenseIF = NULL;
    }
}

#define PV_OMX_MAX_COMPONENT_NAME_LENGTH 128
PVMFStatus PVPlayerEngine::NotifyDecNodeAboutComponentPreferences(PVPlayerEngineTrackSelection &aTrackSelection, PVMFTrackInfo* aTrack)
{

    // check how many components are available
    Oscl_Vector<OMXDecComponentItem, OsclMemAllocator> *pOMXcomponentList;
    pOMXcomponentList = aTrack->getOMXComponentSupportingTheTrackVec();

    if ((aTrackSelection.iTsDecNodeCapConfigIF != NULL) && (pOMXcomponentList->size() > 0))
    {

        // allocate memory for the kvp
        PvmiKvp *Parameters = NULL;
        Parameters = (PvmiKvp*)OSCL_MALLOC(sizeof(PvmiKvp));
        if (Parameters == NULL)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::NotifyDecNodeAboutComponentPreferences - Memory allocation for KVP failed"));
            return PVMFErrNoMemory;
        }

        oscl_memset(Parameters, 0, sizeof(PvmiKvp));

        // Allocate memory for the key
        Parameters->key = (PvmiKeyType)OSCL_MALLOC((sizeof(_STRLIT_CHAR(PVMF_DEC_AVAILABLE_OMX_COMPONENTS_KEY)) + 1) * sizeof(char));
        if (Parameters->key == NULL)
        {
            OSCL_FREE(Parameters);
            PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::NotifyDecNodeAboutComponentPreferences Memory allocation for key string failed"));
            return PVMFErrNoMemory;
        }

        oscl_strset(Parameters->key, 0, (sizeof(_STRLIT_CHAR(PVMF_DEC_AVAILABLE_OMX_COMPONENTS_KEY)) + 1) * sizeof(char));

        oscl_strncat(Parameters->key, _STRLIT_CHAR(PVMF_DEC_AVAILABLE_OMX_COMPONENTS_KEY), sizeof(_STRLIT_CHAR(PVMF_DEC_AVAILABLE_OMX_COMPONENTS_KEY)));
        Parameters->key[sizeof(_STRLIT_CHAR(PVMF_DEC_AVAILABLE_OMX_COMPONENTS_KEY))] = 0; // null terminate

        PvmiKvp* iErrorKVP = NULL;
        Oscl_Vector<OMXDecComponentItem, OsclMemAllocator>::iterator component_item;
        for (component_item = pOMXcomponentList->begin(); component_item != pOMXcomponentList->end(); component_item++)
        {
            // set the pointer based on the item in the list
            OSCL_HeapString<OsclMemAllocator> omxcompname = (*component_item).getOMXComponentName();
            Parameters->value.pChar_value = omxcompname.get_str();
            Parameters->capacity = omxcompname.get_maxsize();


            // now that KVP is ready - call SetParameterSync
            aTrackSelection.iTsDecNodeCapConfigIF->setParametersSync(NULL, Parameters, 1, iErrorKVP);

            if (iErrorKVP != NULL)
            {
                // release memory
                OSCL_FREE(Parameters->key);
                OSCL_FREE(Parameters);
                PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::NotifyDecNodeAboutComponentPreferences cannot set omx component preferred list in the dec node"));

                return PVMFErrNotSupported;
            }
        }

        // release memory
        OSCL_FREE(Parameters->key);
        OSCL_FREE(Parameters);
        return PVMFSuccess;

    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::NotifyDecNodeAboutComponentPreferences dec node does not support capconfig IF or no component supports the track "));
        return PVMFErrNotSupported;

    }

}

PVMFStatus PVPlayerEngine::TryDecNodeVerifyParameterSync(PVPlayerEngineTrackSelection &aTrackSelection, PvmiKvp *kvp)
{
//verify codec specific info
    int32 leavecode = 0;
    PVMFStatus status = PVMFSuccess;
    OSCL_TRY(leavecode, status = aTrackSelection.iTsDecNodeCapConfigIF->verifyParametersSync(NULL, kvp, 1));
    OSCL_FIRST_CATCH_ANY(leavecode,
                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::TryDecNodeVerifyParameterSync unsupported verifyParametersSync did a leave!"));
                         return PVMFFailure;);

    return status;
}


void PVPlayerEngine::UpdateSourceDurationVector(uint8* localBuffer, uint32 duration)
{
    uint32 clipId = 0;
    if (localBuffer)
    {
        clipId = *(uint32*)localBuffer;
    }
    // Find the clipId in the vector.
    // If found, update the duration.
    // Else, add a new element.
    bool updated = false;
    Oscl_Vector<SourceDuration, OsclMemAllocator>::iterator it;
    for (it = iSourceDurationVector.begin(); it != iSourceDurationVector.end(); it++)
    {
        if (it->iClipId == clipId)
        {
            it->iSourceDuration = duration;
            updated = true;
            break;
        }
    }
    if (!updated)
    {
        SourceDuration sd;
        sd.iClipId = clipId;
        sd.iSourceDuration = duration;
        iSourceDurationVector.push_back(sd);
    }
}

void PVPlayerEngine::UpdateCurrentClipSourceDuration()
{
    // Find iCurrentPlaybackClipId in the vector.
    // If found, set iSourceDurationInMS.
    //      and, set iSourceDurationAvailable to true.
    // Else, set iSourceDurationAvailable to false.
    iSourceDurationAvailable = false;
    Oscl_Vector<SourceDuration, OsclMemAllocator>::iterator it;
    for (it = iSourceDurationVector.begin(); it != iSourceDurationVector.end(); it++)
    {
        if (it->iClipId == iCurrentPlaybackClipId)
        {
            iSourceDurationInMS = it->iSourceDuration;
            iSourceDurationAvailable = true;
            break;
        }
    }
}

PVMFStatus PVPlayerEngine::DoPauseDatapath(PVCommandId cmdId, OsclAny* context)
{
    PVMFStatus retval = PVMFSuccess;

    for (uint32 i = 0; i < iDatapathList.size(); ++i)
    {
        if (iDatapathList[i].iDatapath)
        {
            if (iState == PVP_ENGINE_STATE_AUTO_PAUSED)
            {
                // Since sinks are already paused in auto-pause state, skip pausing the sink in the datapath
                retval = DoDatapathPause(iDatapathList[i], cmdId, context, true);
            }
            else
            {
                // Pause all nodes in the datapath
                retval = DoDatapathPause(iDatapathList[i], cmdId, context, false);
            }

            if (retval == PVMFSuccess)
            {
                ++iNumPendingDatapathCmd;
            }
            else
            {
                return AddErrorHandlingCmd(PVP_ENGINE_COMMAND_ERROR_HANDLING_PAUSE, retval, NULL);
            }
        }
    }
    return retval;
}

PVMFStatus PVPlayerEngine::AddErrorHandlingCmd(int32 aCmdType, PVMFStatus aErrStatus, PVMFBasicErrorInfoMessage* aErrMsg)
{
    bool ehPending = CheckForPendingErrorHandlingCmd();
    if (ehPending)
    {
        // there should be no error handling queued.
        PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "Pending EH command, should never happen"));
        if (aErrMsg)
        {
            aErrMsg->removeRef();
        }
        return PVMFPending;
    }
    // go in error handling
    iCommandCompleteStatusInErrorHandling = aErrStatus;
    iCommandCompleteErrMsgInErrorHandling = aErrMsg;
    AddCommandToQueue(aCmdType, NULL, NULL, NULL, false);
    return PVMFPending;
}

// END FILE











