blob: 43ac44b3e0c231bf6fdc734c9d124d24c5085d2d [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 2008 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_engine_tunables.h"
#include "pv_player_sdkinfo.h"
#include "pv_player_config.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_fileoutput_factory.h"
#include "pvmf_fileoutput_config.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 "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"
#ifdef HAS_OSCL_LIB_SUPPORT
#include "pv_player_engine.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"
#include "oscl_shared_library.h"
#include "oscl_library_list.h"
#include "oscl_shared_lib_interface.h"
#include "pvmf_node_shared_lib_interface.h"
#define PVPLAYERENGINE_DEFAULT_CONFIG_PATH_SIZE 32
#ifndef PVPLAYERENGINE_NODE_REGISTRY_CONFIG_PATH
#define PVPLAYERENGINE_NODE_REGISTRY_CONFIG_PATH NULL
#endif
#endif
//
#define PVPLAYERENGINE_NUM_COMMANDS 10
#define PVPLAYERENGINE_TIMERID_ENDTIMECHECK 1
#define PVPLAYERENGINE_TIMERID_PLAY_STATUS 2
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()
{
Cancel();
// 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_TEMPLATED_DELETE(iPollingCheckTimer, OsclTimer<OsclMemAllocator>, OsclTimer);
// Return all engine contexts to pool
while (!iCurrentContextList.empty())
{
FreeEngineContext(iCurrentContextList[0]);
}
iNodeUuids.clear();
#ifdef HAS_OSCL_LIB_SUPPORT
DepopulateAllRegistries();
#endif
}
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::QueryUUID(const PvmfMimeString& aMimeType, Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids,
bool aExactUuidsOnly, const OsclAny* aContextData)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::QueryUUID()"));
Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
paramvec.reserve(3);
paramvec.clear();
PVPlayerEngineCommandParamUnion param;
param.pOsclAny_value = (OsclAny*) & aMimeType;
paramvec.push_back(param);
param.pOsclAny_value = (OsclAny*) & aUuids;
paramvec.push_back(param);
param.bool_value = aExactUuidsOnly;
paramvec.push_back(param);
return AddCommandToQueue(PVP_ENGINE_COMMAND_QUERY_UUID, (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::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);
PVPlayerEngineCommand cmd(PVP_ENGINE_COMMAND_GET_PVPLAYER_STATE, -1, NULL, &paramvec);
return DoGetPVPlayerState(cmd, true);
}
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::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)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::GetMetadataKeys()"));
Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
paramvec.reserve(4);
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);
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)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::GetMetadataValues()"));
Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
paramvec.reserve(5);
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);
return AddCommandToQueue(PVP_ENGINE_COMMAND_GET_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)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::SetPlaybackRange()"));
PVPPlaybackPosition curpos;
curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC;
iPlaybackPositionMode = aBeginPos.iMode;
GetPlaybackClockPosition(curpos);
Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec;
paramvec.reserve(3);
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);
return AddCommandToQueue(PVP_ENGINE_COMMAND_SET_PLAYBACK_RANGE, (OsclAny*)aContextData, &paramvec);
}
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);
PVPlayerEngineCommand cmd(PVP_ENGINE_COMMAND_GET_CURRENT_POSITION, -1, NULL, &paramvec);
return DoGetCurrentPosition(cmd, true);
}
PVCommandId PVPlayerEngine::SetPlaybackRate(int32 aRate, OsclTimebase* 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, OsclTimebase*& 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()"));
if (!iSourceDurationAvailable)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Pause() - Pause not supported"));
OSCL_LEAVE(PVMFErrNotSupported);
return -1;
}
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()"));
iCfgCapCmdObserver = aObserver;
}
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);
return DoCapConfigGetParametersSync(aIdentifier, aParameters, aNumParamElements, aContext);
}
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);
return DoCapConfigReleaseParameters(aParameters, aNumElements);
}
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
aContext = (PvmiCapabilityContext) & iCapConfigContext;
}
void PVPlayerEngine::setContextParameters(PvmiMIOSession aSession, PvmiCapabilityContext& aContext, PvmiKvp* aParameters, int aNumParamElements)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::setContextParameters()"));
OSCL_UNUSED_ARG(aSession);
OSCL_UNUSED_ARG(aContext);
OSCL_UNUSED_ARG(aParameters);
OSCL_UNUSED_ARG(aNumParamElements);
// This method is not supported so leave
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::setContextParameters() is not supported!"));
OSCL_LEAVE(PVMFErrNotSupported);
}
void PVPlayerEngine::DeleteContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DeleteContext()"));
OSCL_UNUSED_ARG(aSession);
OSCL_UNUSED_ARG(aContext);
// Do nothing since the context is just the a member variable of the engine
}
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);
// 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);
PVPlayerEngineCommand cmd(PVP_ENGINE_COMMAND_CAPCONFIG_SET_PARAMETERS, -1, NULL, &paramvec);
// Complete the request synchronously
DoCapConfigSetParameters(cmd, true);
}
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);
}
uint32 PVPlayerEngine::getCapabilityMetric(PvmiMIOSession aSession)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::getCapabilityMetric()"));
OSCL_UNUSED_ARG(aSession);
// Not supported so return 0
return 0;
}
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);
return DoCapConfigVerifyParameters(aParameters, aNumElements);
}
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);
}
PVMFStatus PVPlayerEngine::GetLicenseStatus(PVMFCPMLicenseStatus& aStatus)
{
if (iSourceNodeCPMLicenseIF)
return iSourceNodeCPMLicenseIF->GetLicenseStatus(aStatus);
if (iCPMPluginLicenseIF)
return iCPMPluginLicenseIF->GetLicenseStatus(aStatus);
return PVMFFailure;
}
void PVPlayerEngine::addRef()
{
}
void PVPlayerEngine::removeRef()
{
}
bool PVPlayerEngine::queryInterface(const PVUuid& uuid, PVInterface*& iface)
{
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
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::queryInterface() Unsupported interface UUID."));
return false;
}
return true;
}
PVPlayerEngine::PVPlayerEngine() :
OsclTimerObject(OsclActiveObject::EPriorityNominal, "PVPlayerEngine"),
iCommandId(0),
iState(PVP_ENGINE_STATE_IDLE),
iCmdStatusObserver(NULL),
iErrorEventObserver(NULL),
iInfoEventObserver(NULL),
iCfgCapCmdObserver(NULL),
iPollingCheckTimer(NULL),
iCommandCompleteInEngineAOPending(false),
iCommandCompleteInEngineAOCmdStatus(PVMFSuccess),
iCommandCompleteInEngineAOErrMsg(NULL),
iCapConfigContext(0),
iNumPendingNodeCmd(0),
iNumPendingDatapathCmd(0),
iDataSource(NULL),
iDataSourcePS(NULL),
iSourceFormatType(PVMF_FORMAT_UNKNOWN),
iSourceNode(NULL),
iSourceNodeSessionId(0),
iSourceNodeInitIF(NULL),
iSourceNodeTrackSelIF(NULL),
iSourceNodePBCtrlIF(NULL),
iSourceNodeDirCtrlIF(NULL),
iSourceNodeTrackLevelInfoIF(NULL),
iSourceNodeMetadataExtIF(NULL),
iSourceNodeCapConfigIF(NULL),
iSourceNodeRegInitIF(NULL),
iSourceNodeCPMLicenseIF(NULL),
iSourceNodePacketSourceIF(NULL),
iCPMPlugin(NULL),
iCPMPluginFactory(NULL),
iCPMPluginSessionId(0),
iCPMPluginLicenseIF(NULL),
iCPMPluginCapConfigIf(NULL),
iCPMPluginCommand(-1),
iCPMGetLicenseCmdId(0),
iCurrentContextListMemPool(12),
iPendingCancelDueToCancelRequest(0),
iPendingStopDueToCancelRequest(0),
iPendingResetDueToCancelRequest(0),
iPendingCancelDueToErrorRequest(0),
iErrorOccurredDuringErrorHandling(false),
iLogger(NULL),
iPerfLogger(NULL),
iReposLogger(NULL),
iPlaybackClockRate(100000),
iOutsideTimebase(NULL),
iPlaybackClockRate_New(100000),
iOutsideTimebase_New(NULL),
iActualPlaybackPosition(0),
iSeekPointBeforeTargetNPT(0),
iSeekPointAfterTargetNPT(0),
iActualMediaDataTS(0),
iAdjustedMediaDataTS(0),
iWatchDogTimerInterval(0),
iStartNPT(0),
iStartMediaDataTS(0),
iForwardReposFlag(false),
iBackwardReposFlag(false),
iPlaybackDirection(1),
iPlaybackDirection_New(1),
iChangePlaybackDirectionWhenResuming(false),
iEndTimeCheckEnabled(false),
iQueuedRangePresent(false),
iChangePlaybackPositionWhenResuming(false),
iDataReadySent(false),
iPlayStatusTimerEnabled(false),
iPlaybackPausedDueToEndOfClip(false),
iSourceDurationAvailable(false),
iSourceDurationInMS(0),
iPBPosEnable(true),
iPBPosStatusUnit(PVPLAYERENGINE_CONFIG_PBPOSSTATUSUNIT_DEF),
iPBPosStatusInterval(PVPLAYERENGINE_CONFIG_PBPOSSTATUSINTERVAL_DEF),
iEndTimeCheckInterval(PVPLAYERENGINE_CONFIG_ENDTIMECHECKINTERVAL_DEF),
iSeekToSyncPoint(PVPLAYERENGINE_CONFIG_SEEKTOSYNCPOINT_DEF),
iSkipToRequestedPosition(PVPLAYERENGINE_CONFIG_SKIPTOREQUESTEDPOS_DEF),
iRenderSkipped(PVPLAYERENGINE_CONFIG_RENDERSKIPPED_DEF),
iSyncPointSeekWindow(PVPLAYERENGINE_CONFIG_SEEKTOSYNCPOINTWINDOW_DEF),
iNodeCmdTimeout(PVPLAYERENGINE_CONFIG_NODECMDTIMEOUT_DEF),
iNodeDataQueuingTimeout(PVPLAYERENGINE_CONFIG_NODEDATAQUEUINGTIMEOUT_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)),
iRollOverState(RollOverStateIdle),
iBackwardRepos(false),
iAlternateSrcFormatIndex(0),
iStreamID(0),
iNumPendingSkipCompleteEvent(0),
iNumPVMFInfoStartOfDataPending(0),
iResumeAfterReposition(false),
iTrackSelectionHelper(NULL),
iPlaybackPositionMode(PVPPBPOS_MODE_UNKNOWN)
{
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)
{
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();
iMetadataReleaseList.reserve(6);
iMetadataReleaseList.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;
iPlaybackClock.SetStartTime32(starttime, OSCLCLOCK_MSEC);
// 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));
#ifdef HAS_OSCL_LIB_SUPPORT
if (NULL != PVPLAYERENGINE_NODE_REGISTRY_CONFIG_PATH)
{
OSCL_HeapString<OsclMemAllocator> configFileName =
PVPLAYERENGINE_NODE_REGISTRY_CONFIG_PATH;
PopulateAllRegistries(configFileName);
}
#endif
return;
}
void PVPlayerEngine::Run()
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Run() In"));
int32 leavecode = 0;
if (iRollOverState == RollOverStateStart)
{
if (iPendingCmds.top().GetCmdType() == PVP_ENGINE_COMMAND_CANCEL_ALL_COMMANDS)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Run() Source Roll Over In Progress But CancelAllCommands is requied by App"));
iRollOverState = RollOverStateIdle;
}
else if (iPendingCmds.top().GetCmdType() == PVP_ENGINE_COMMAND_RESET_DUE_TO_ERROR)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Run() Source Roll Over In Progress But ResetDueToError is required by Error handling"));
iRollOverState = RollOverStateIdle;
}
else
{
if (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_INIT)
{
iCommandCompleteInEngineAOPending = false;
//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::RunL() DoSourceNodeRollOver Failed, alternate source node for rollover is available"));
RunIfNotReady();
return;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() DoSourceNodeRollOver Failed"));
iRollOverState = RollOverStateIdle;
EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), PVMFFailure);
}
else
{
iRollOverState = RollOverStateInProgress;
}
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() Source Roll Over In Progress But Incorrect Engine Cmd - Asserting"));
OSCL_ASSERT(false);
}
return;
}
}
if (iRollOverState == RollOverStateInProgress)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::RunL() Source Roll Over In Progress "));
return;
}
// Check if a command that needs to complete in engine's AO is pending
if (iCommandCompleteInEngineAOPending)
{
iCommandCompleteInEngineAOPending = false;
OSCL_ASSERT(iCurrentCmd.empty() == false);
switch (iCurrentCmd[0].GetCmdType())
{
case PVP_ENGINE_COMMAND_CANCEL_ALL_COMMANDS:
DoCleanupDueToCancel();
break;
case PVP_ENGINE_COMMAND_ADD_DATA_SOURCE:
DoAddDataSourceFailureComplete();
break;
case PVP_ENGINE_COMMAND_INIT:
DoInitFailureComplete();
break;
case PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_WCHAR:
case PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_CHAR:
DoCPMPluginAcquireLicenseComplete();
break;
case PVP_ENGINE_COMMAND_RESET:
case PVP_ENGINE_COMMAND_RESET_DUE_TO_ERROR:
if (iState != PVP_ENGINE_STATE_IDLE)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() Wrong state for completing Reset encountered. Asserting"));
OSCL_ASSERT(false); // we should not be here
EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), PVMFErrInvalidState);
return;
}
if (iDataSource)
RemoveDataSourceSync(*iDataSource);
EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), PVMFSuccess);
break;
default:
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() Command type that does not need to complete in engine AO encountered. Asserting"));
OSCL_ASSERT(false);
EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), PVMFFailure);
break;
}
return;
}
/* Check if CancelAll()/CancelAcquireLicense request was made */
if (!iPendingCmds.empty())
{
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;
}
}
// Handle other requests normally
if (!iPendingCmds.empty() && iCurrentCmd.empty())
{
// Retrieve the first pending command from queue
PVPlayerEngineCommand cmd(iPendingCmds.top());
// check if Stop cmd injection is necessary during Reset
if (iPendingCmds.top().GetCmdType() == PVP_ENGINE_COMMAND_RESET)
{
switch (GetPVPlayerState())
{
case PVP_STATE_PREPARED:
case PVP_STATE_STARTED:
case PVP_STATE_PAUSED:
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Run() Reset request, injecting Stop first"));
RunIfNotReady(); //reschedule Reset
// execute Stop before doing Reset
cmd = PVPlayerEngineCommand(PVP_ENGINE_COMMAND_STOP, iCommandId++, NULL, NULL, false);
if (iCommandId == 0x7FFFFFFF)
iCommandId = 0;
break;
default: //process normally in all other states
iPendingCmds.pop();
}
}
else
{
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);
OSCL_ASSERT(false);
return;);
// Process the command according to the cmd type
PVMFStatus cmdstatus = PVMFSuccess;
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_UUID:
cmdstatus = DoQueryUUID(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_ADD_DATA_SOURCE:
cmdstatus = DoAddDataSource(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_ADD_DATA_SINK:
cmdstatus = DoAddDataSink(cmd);
break;
case PVP_ENGINE_COMMAND_GET_CURRENT_POSITION:
cmdstatus = DoGetCurrentPosition(cmd, false);
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:
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_ACQUIRE_LICENSE_WCHAR:
case PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_CHAR:
cmdstatus = DoAcquireLicense(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_STOP_DUE_TO_ERROR:
cmdstatus = DoStopDueToError(cmd);
break;
case PVP_ENGINE_COMMAND_RESET_DUE_TO_ERROR:
cmdstatus = DoResetDueToError(cmd);
break;
case PVP_ENGINE_COMMAND_CLEANUP_DUE_TO_ERROR:
cmdstatus = DoCleanupDueToError(cmd);
break;
case PVP_ENGINE_COMMAND_DATAPATH_DELETE:
cmdstatus = DoDatapathDelete(cmd);
break;
case PVP_ENGINE_COMMAND_CANCEL_DUE_TO_ERROR:
// Nothing to do since this command would not
// be processed from here
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. Asserting."));
OSCL_ASSERT(false);
// Just handle as "not supported"
default:
cmdstatus = PVMFErrNotSupported;
break;
}
if (cmdstatus != PVMFSuccess)
{
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::FindDatapathByMediaType(PVPlayerMediaType aMediaType, int32& aDatapathListIndex)
{
// Current implementaion needs to determine which media types are available
// and this logic can be removed if the engine is completely media type agnostic.
// This logic assumes there is only one possible datapath with the same media type.
if (aMediaType == PVP_MEDIATYPE_UNKNOWN)
{
// Cannot check with media type being unknown
// Might bring up false positives
aDatapathListIndex = -1;
return false;
}
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iMediaType == aMediaType)
{
aDatapathListIndex = i;
return true;
}
}
// Could not determine the types
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 == &iPendingCancelDueToCancelRequest)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::NodeCommandCompleted() Cancel in node completed for cancel command. Pending %d", iPendingCancelDueToCancelRequest));
OSCL_ASSERT(iPendingCancelDueToCancelRequest > 0);
--iPendingCancelDueToCancelRequest;
if (iPendingCancelDueToCancelRequest == 0)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::NodeCommandCompleted() Cancelling of all node/datapath commands complete so continue to shutdown"));
RemoveDatapathContextFromList(); // empty left over contexts from cancelled datapath commands
DoShutdownDueToCancel();
}
return;
}
// Check if stop called on node due to cancel shutdown
else if (context_uint32 == &iPendingStopDueToCancelRequest)
{
// Don't care about the response
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::NodeCommandCompleted() Stop in node due to cancel completed. Pending %d", iPendingStopDueToCancelRequest));
--iPendingStopDueToCancelRequest;
if (iPendingStopDueToCancelRequest == 0)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::NodeCommandCompleted() Stopping of all nodes due to cancel has completed so continuing on to reset"));
DoResetDueToCancel();
}
return;
}
// Check if reset called on node due to cancel shutdown
else if (context_uint32 == &iPendingResetDueToCancelRequest)
{
// Don't care about the response
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::NodeCommandCompleted() Reset in node due to cancel completed. Pending %d", iPendingResetDueToCancelRequest));
--iPendingResetDueToCancelRequest;
if (iPendingResetDueToCancelRequest == 0)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::NodeCommandCompleted() Resetting of all nodes due to cancel has completed so continuing on to cleanup"));
// Need to cleanup in engine's AO so set the flag.
// There shouldn't be any other command pending to complete in engine's AO
OSCL_ASSERT(iCommandCompleteInEngineAOPending == false);
iCommandCompleteInEngineAOPending = true;
if (IsBusy())
{
Cancel();
}
RunIfNotReady();
}
return;
}
// Check if cancel called on node due to error
else if (context_uint32 == &iPendingCancelDueToErrorRequest)
{
// Don't care about the response
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::NodeCommandCompleted() Cancel in node due to error completed. Pending %d", iPendingCancelDueToErrorRequest));
--iPendingCancelDueToErrorRequest;
if (iPendingCancelDueToErrorRequest == 0)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::NodeCommandCompleted() Cancel due to error complete."));
// Check that current cmd is the internal cancel-due-to-error command
OSCL_ASSERT(iCurrentCmd.empty() == false);
OSCL_ASSERT(iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_CANCEL_DUE_TO_ERROR);
RemoveDatapathContextFromList(); // empty left over contexts from cancelled datapath commands
// Call EngineCommandCompleted() so the internal cancel-due-to-error command
// would be completed and next engine command in pending queue would be processed
EngineCommandCompleted(-1, NULL, PVMFSuccess);
// Clear out iCmdToCancel queue
OSCL_ASSERT(iCmdToCancel.empty() == false);
iCmdToCancel.clear();
}
return;
}
PVPlayerEngineContext* nodecontext = (PVPlayerEngineContext*)(aResponse.GetContext());
OSCL_ASSERT(nodecontext);
// Ignore other node completion if cancelling
if (!iCmdToCancel.empty())
{
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_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_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, iMetadataReleaseList.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 (iMetadataReleaseList.empty() == false)
{
mdif = iMetadataIFList[iMetadataReleaseList[0].iMetadataIFListIndex].iInterface;
OSCL_ASSERT(mdif != NULL);
mdif->ReleaseNodeMetadataKeys(*(iGetMetadataKeysParam.iKeyList), iMetadataReleaseList[0].iStartIndex, iMetadataReleaseList[0].iEndIndex);
iMetadataReleaseList.erase(iMetadataReleaseList.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(NULL, NULL, 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 (iMetadataReleaseList.empty() == false)
{
mdif = iMetadataIFList[iMetadataReleaseList[0].iMetadataIFListIndex].iInterface;
OSCL_ASSERT(mdif != NULL);
mdif->ReleaseNodeMetadataKeys(*(iGetMetadataKeysParam.iKeyList), iMetadataReleaseList[0].iStartIndex, iMetadataReleaseList[0].iEndIndex);
iMetadataReleaseList.erase(iMetadataReleaseList.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 (iMetadataReleaseList.empty() == false)
{
PVMFMetadataExtensionInterface* mdif = iMetadataIFList[iMetadataReleaseList[0].iMetadataIFListIndex].iInterface;
OSCL_ASSERT(mdif != NULL);
mdif->ReleaseNodeMetadataKeys(*(iGetMetadataKeysParam.iKeyList), iMetadataReleaseList[0].iStartIndex, iMetadataReleaseList[0].iEndIndex);
iMetadataReleaseList.erase(iMetadataReleaseList.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, iMetadataReleaseList.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 (iMetadataReleaseList.empty() == false)
{
mdif = iMetadataIFList[iMetadataReleaseList[0].iMetadataIFListIndex].iInterface;
OSCL_ASSERT(mdif != NULL);
mdif->ReleaseNodeMetadataValues(*(iGetMetadataValuesParam.iValueList), iMetadataReleaseList[0].iStartIndex, iMetadataReleaseList[0].iEndIndex);
iMetadataReleaseList.erase(iMetadataReleaseList.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(NULL, NULL, 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());
// Release the memory allocated for the metadata values
while (iMetadataReleaseList.empty() == false)
{
mdif = iMetadataIFList[iMetadataReleaseList[0].iMetadataIFListIndex].iInterface;
OSCL_ASSERT(mdif != NULL);
mdif->ReleaseNodeMetadataValues(*(iGetMetadataValuesParam.iValueList), iMetadataReleaseList[0].iStartIndex, iMetadataReleaseList[0].iEndIndex);
iMetadataReleaseList.erase(iMetadataReleaseList.begin());
}
// 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());
// Release the memory allocated for the metadata values
while (iMetadataReleaseList.empty() == false)
{
PVMFMetadataExtensionInterface* mdif = iMetadataIFList[iMetadataReleaseList[0].iMetadataIFListIndex].iInterface;
OSCL_ASSERT(mdif != NULL);
mdif->ReleaseNodeMetadataValues(*(iGetMetadataValuesParam.iValueList), iMetadataReleaseList[0].iStartIndex, iMetadataReleaseList[0].iEndIndex);
iMetadataReleaseList.erase(iMetadataReleaseList.begin());
}
// 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
{
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_SourceNodeQueryCPMLicenseIF:
case PVP_CMD_SourceNodeQuerySrcNodeRegInitIF:
case PVP_CMD_SourceNodeQueryPacketSourceIF:
HandleSourceNodeQueryInterfaceOptional(*nodecontext, aResponse);
break;
case PVP_CMD_SourceNodeGetDlaData:
HandleSourceNodeGetDlaData(*nodecontext, aResponse);
break;
case PVP_CMD_SourceNodeGetLicense:
HandleSourceNodeGetLicense(*nodecontext, aResponse);
break;
case PVP_CMD_SourceNodeCancelGetLicense:
HandleSourceNodeCancelGetLicense(*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_INITIALIZED:
switch (nodecontext->iCmdType)
{
case PVP_CMD_SourceNodeGetLicense:
HandleSourceNodeGetLicense(*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_SourceNodeQueryDataSourcePosition:
HandleSourceNodeQueryDataSourcePosition(*nodecontext, aResponse);
break;
case PVP_CMD_SourceNodeSetDataSourcePosition:
HandleSourceNodeSetDataSourcePosition(*nodecontext, aResponse);
break;
case PVP_CMD_SourceNodeSetDataSourceDirection:
HandleSourceNodeSetDataSourceDirection(*nodecontext, aResponse);
break;
case PVP_CMD_SourceNodeStart:
HandleSourceNodeResume(*nodecontext, aResponse);
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_STOPPING:
HandleSourceNodeStop(*nodecontext, aResponse);
break;
case PVP_ENGINE_STATE_RESETTING:
HandleSourceNodeReset(*nodecontext, aResponse);
break;
case PVP_ENGINE_STATE_HANDLINGERROR:
switch (nodecontext->iCmdType)
{
case PVP_CMD_SourceNodeStop:
HandleSourceNodeStopDueToError(*nodecontext, aResponse);
break;
case PVP_CMD_SourceNodeReset:
HandleSourceNodeResetDueToError(*nodecontext, aResponse);
break;
default:
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::NodeCommandCompleted() Invalid source node command type in PVP_ENGINE_STATE_HANDLINGERROR. Asserting"));
OSCL_ASSERT(false);
break;
}
break;
default:
break;
}
}
}
else if (iState == PVP_ENGINE_STATE_PREPARING)
{
switch (nodecontext->iCmdType)
{
case PVP_CMD_SinkNodeQueryFOConfigIF:
HandleSinkNodeQueryFileOutConfigIF(*nodecontext, aResponse);
break;
case PVP_CMD_SinkNodeQuerySyncCtrlIF:
case PVP_CMD_SinkNodeQueryMetadataIF:
case PVP_CMD_SinkNodeQueryCapConfigIF:
HandleSinkNodeQueryInterfaceOptional(*nodecontext, aResponse);
break;
case PVP_CMD_DecNodeQueryMetadataIF:
case PVP_CMD_DecNodeQueryCapConfigIF:
HandleDecNodeQueryInterfaceOptional(*nodecontext, aResponse);
break;
case PVP_CMD_SinkNodeSkipMediaData:
HandleSinkNodeSkipMediaData(*nodecontext, aResponse);
break;
case PVP_CMD_SinkNodeDecNodeQueryCapConfigIF:
HandleSinkNodeDecNodeQueryCapConfigIF(*nodecontext, aResponse);
break;
case PVP_CMD_SinkNodeDecNodeVerifyParameter:
HandleSinkNodeDecNodeVerifyParameter(*nodecontext, aResponse);
break;
case PVP_CMD_SinkNodeDecNodeReset:
HandleSinkNodeDecNodeReset(*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_INFO, (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 if (nodetype == 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 type Event type 0x%x Context 0x%x Data 0x%x",
aEvent.GetEventType(), aEvent.GetContext(), aEvent.GetEventData()));
}
}
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 if (nodetype == 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 type Event type 0x%x Context 0x%x Data 0x%x",
aEvent.GetEventType(), aEvent.GetContext(), aEvent.GetEventData()));
}
}
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_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 == &iPendingCancelDueToCancelRequest)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Cancel in datapath completed for cancel command. Pending %d", iPendingCancelDueToCancelRequest));
OSCL_ASSERT(iPendingCancelDueToCancelRequest > 0);
--iPendingCancelDueToCancelRequest;
if (iPendingCancelDueToCancelRequest == 0)
{
RemoveDatapathContextFromList(); // empty left over contexts from cancelled datapath commands
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Cancelling of all node/datapath command complete so continuing to shutdown"));
DoShutdownDueToCancel();
}
return;
}
// Check if cancel called on node due to error
else if (context_uint32 == &iPendingCancelDueToErrorRequest)
{
// Don't care about the response
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Cancel in datapath due to error completed. Pending %d", iPendingCancelDueToErrorRequest));
--iPendingCancelDueToErrorRequest;
if (iPendingCancelDueToErrorRequest == 0)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Cancel due to error complete."));
// Check that current cmd is the internal cancel-due-to-error command
OSCL_ASSERT(iCurrentCmd.empty() == false);
OSCL_ASSERT(iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_CANCEL_DUE_TO_ERROR);
RemoveDatapathContextFromList(); // empty left over contexts from cancelled datapath commands
// Call EngineCommandCompleted() so the internal cancel-due-to-error command
// would be completed and next engine command in pending queue would be processed
EngineCommandCompleted(-1, NULL, PVMFSuccess);
// Clear out iCmdToCancel queue
OSCL_ASSERT(iCmdToCancel.empty() == false);
iCmdToCancel.clear();
}
return;
}
PVPlayerEngineContext* datapathcontext = (PVPlayerEngineContext*)aContext;
OSCL_ASSERT(datapathcontext);
// Ignore other datapath event if cancelling
if (!iCmdToCancel.empty())
{
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. Asserting"));
OSCL_ASSERT(false);
break;
}
}
else if (iState == PVP_ENGINE_STATE_PAUSING)
{
HandleDatapathPause(*datapathcontext, aEventStatus, aCmdResp);
}
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. Asserting"));
OSCL_ASSERT(false);
break;
}
}
else if (iState == PVP_ENGINE_STATE_HANDLINGERROR)
{
switch (datapathcontext->iCmdType)
{
case PVP_CMD_DPStop:
HandleDatapathStopDueToError(*datapathcontext, aEventStatus, aCmdResp);
break;
case PVP_CMD_DPTeardown:
HandleDatapathTeardownDueToError(*datapathcontext, aEventStatus, aCmdResp);
break;
case PVP_CMD_DPReset:
HandleDatapathResetDueToError(*datapathcontext, aEventStatus, aCmdResp);
break;
default:
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Invalid datapath command type in PVP_ENGINE_STATE_HANDLINGERROR. Asserting"));
OSCL_ASSERT(false);
break;
}
}
else
{
// Unknown datapath. Assert
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Invalid state for datapath command completion. Asserting"));
OSCL_ASSERT(false);
}
// Remove the context from the list
FreeEngineContext(datapathcontext);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Out"));
}
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);
}
}
else if (timerID == PVPLAYERENGINE_TIMERID_PLAY_STATUS)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::TimeoutOccurred() Timer for PlayStatus event triggered"));
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();
if (!iPlayStatusTimerEnabled)
{
iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_PLAY_STATUS);
}
}
}
void PVPlayerEngine::CPMPluginCommandCompleted(const PVMFCmdResp& aResponse)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::CPMPluginCommandCompleted() In"));
OSCL_ASSERT(iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_CHAR ||
iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_WCHAR);
switch (iCPMPluginCommand)
{
case PVP_CMD_CPMQueryLicenseIF:
HandleCPMPluginQueryLicenseIF(aResponse);
break;
case PVP_CMD_CPMQueryCapConfigIF:
HandleCPMPluginQueryCapConfigIF(aResponse);
break;
case PVP_CMD_CPMGetLicense:
HandleCPMPluginGetLicense(aResponse);
break;
default:
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::CPMPluginCommandCompleted() Unknown CPM plug-in command. Asserting"));
OSCL_ASSERT(false);
break;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::CPMPluginCommandCompleted() Out"));
}
void PVPlayerEngine::RecognizeCompleted(PVMFFormatType aSourceFormatType, OsclAny* aContext)
{
// Check if a cancel command completed
uint32* context_uint32 = (uint32*)(aContext);
if (context_uint32 == &iPendingCancelDueToCancelRequest)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::RecognizeCompleted() Recognize request cancelled"));
OSCL_ASSERT(iPendingCancelDueToCancelRequest > 0);
--iPendingCancelDueToCancelRequest;
if (iPendingCancelDueToCancelRequest == 0)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::RecognizeCompleted() Cancelling of all pending commands complete so continue to shutdown"));
RemoveDatapathContextFromList(); // empty left over contexts from cancelled datapath commands
DoShutdownDueToCancel();
}
return;
}
// Ignore recognize completion if cancelling
if (!iCmdToCancel.empty())
{
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)
{
// Do cleanup
DoSourceNodeCleanup();
iDataSource = NULL;
// Complete the AddDataSource() command with failure
EngineCommandCompleted(cmdid, cmdcontext, retval);
}
}
PVCommandId PVPlayerEngine::AddCommandToQueue(int32 aCmdType, OsclAny* aContextData,
Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator>* aParamVector,
const PVUuid* aUuid, bool aAPICommand)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::AddCommandToQueue() In CmdType %d, CmdId %d", aCmdType, iCommandId));
PVPlayerEngineCommand cmd(aCmdType, iCommandId, aContextData, aParamVector, aAPICommand);
if (aUuid)
{
cmd.SetUuid(*aUuid);
}
/*
* If engine is in error or error handling state, then don't add external commands to the queue
*/
int32 leavecode = 0;
if (aAPICommand == true) //External Command
{
if (iState == PVP_ENGINE_STATE_ERROR || iState == PVP_ENGINE_STATE_HANDLINGERROR)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::AddCommandToQueue() Invalid state due to Error Handling : CmdType %d, CmdId %d", aCmdType, iCommandId));
OSCL_LEAVE(OsclErrInvalidState);
return -1; // Dummy Cmdid
}
}
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;);
RunIfNotReady();
++iCommandId;
if (iCommandId == 0x7FFFFFFF)
{
iCommandId = 0;
}
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_RESETTING:
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_PAUSED:
case PVP_ENGINE_STATE_AUTO_RESUMING:
case PVP_ENGINE_STATE_PAUSING:
case PVP_ENGINE_STATE_STOPPING:
return PVP_STATE_STARTED;
case PVP_ENGINE_STATE_PAUSED:
case PVP_ENGINE_STATE_RESUMING:
return PVP_STATE_PAUSED;
case PVP_ENGINE_STATE_HANDLINGERROR:
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)
{
bool tmpbool = false;
uint32 clockcurpos = 0;
aClockPos.iIndeterminate = false;
int32 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.GetCurrentTime32(clockcurpos, tmpbool, OSCLCLOCK_MSEC);
nptcurpos = iStartNPT + iPlaybackDirection * (clockcurpos - iStartMediaDataTS);
}
if (nptcurpos < 0)
{
nptcurpos = 0;
}
if (ConvertFromMillisec((uint32)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;
PVPlayerMediaType selmediatype = PVP_MEDIATYPE_UNKNOWN;
// Search from the datapath list.
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackActive)
{
switch (iDatapathList[i].iMediaType)
{
case PVP_MEDIATYPE_VIDEO:
track = iDatapathList[i].iTrackInfo;
selmediatype = PVP_MEDIATYPE_VIDEO;
// Video track found so no need to check further
i = iDatapathList.size();
break;
case PVP_MEDIATYPE_TEXT:
track = iDatapathList[i].iTrackInfo;
selmediatype = PVP_MEDIATYPE_TEXT;
break;
case PVP_MEDIATYPE_AUDIO:
if (selmediatype != PVP_MEDIATYPE_TEXT)
{
track = iDatapathList[i].iTrackInfo;
selmediatype = PVP_MEDIATYPE_TEXT;
}
break;
default:
break;
}
}
}
if (track == NULL)
{
// 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;
}
// 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].iTrackActive)
{
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.
}
}
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
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
PVMFTrackInfo* track = NULL;
PVPlayerMediaType selmediatype = PVP_MEDIATYPE_UNKNOWN;
// Search from the datapath list.
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackActive)
{
switch (iDatapathList[i].iMediaType)
{
case PVP_MEDIATYPE_VIDEO:
track = iDatapathList[i].iTrackInfo;
selmediatype = PVP_MEDIATYPE_VIDEO;
// Video track found so no need to check further
i = iDatapathList.size();
break;
case PVP_MEDIATYPE_TEXT:
track = iDatapathList[i].iTrackInfo;
selmediatype = PVP_MEDIATYPE_TEXT;
break;
case PVP_MEDIATYPE_AUDIO:
if (selmediatype != PVP_MEDIATYPE_TEXT)
{
track = iDatapathList[i].iTrackInfo;
selmediatype = PVP_MEDIATYPE_TEXT;
}
break;
default:
break;
}
}
}
if (track == NULL)
{
// Track is not available to do the conversion
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertFromMillisec() Track not selected for conversion"));
return PVMFErrArgument;
}
// 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].iTrackActive)
{
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_RESET_DUE_TO_ERROR:
case PVP_ENGINE_COMMAND_CLEANUP_DUE_TO_ERROR:
SendErrorHandlingCompleteEvent(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"));
}
}
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::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[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;
}
// 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()) < 0x80000000))
{
// 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
{
// CancelAll() command is completed so send the completion event
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);
switch (iCmdToCancel[0].GetCmdType())
{
case PVP_ENGINE_COMMAND_ADD_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_STOP:
if (!iCurrentContextList.empty())
{
// Since there is a pending node or datapath, cancel it
DoCancelPendingNodeDatapathCommand();
}
else
{
// No pending command so contine to shutdown
DoShutdownDueToCancel();
}
break;
case PVP_ENGINE_COMMAND_RESET:
case PVP_ENGINE_COMMAND_SET_PLAYBACK_RATE:
case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_ENDTIME_REACHED:
case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_ENDOFCLIP:
case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_BUFFER_UNDERFLOW:
case PVP_ENGINE_COMMAND_RESUME_DUE_TO_BUFFER_DATAREADY:
case PVP_ENGINE_COMMAND_STOP_DUE_TO_ERROR:
case PVP_ENGINE_COMMAND_RESET_DUE_TO_ERROR:
case PVP_ENGINE_COMMAND_CLEANUP_DUE_TO_ERROR:
case PVP_ENGINE_COMMAND_GET_METADATA_KEY:
case PVP_ENGINE_COMMAND_GET_METADATA_VALUE:
case PVP_ENGINE_COMMAND_DATAPATH_DELETE:
// Complete the CancelAll() but allow the pending command to complete.
// This is necessary until transition cancel is fully implemented.
EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), PVMFSuccess);
iCurrentCmd.push_front(iCmdToCancel[0]);
iCmdToCancel.clear();
break;
case PVP_ENGINE_COMMAND_QUERY_UUID:
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"));
}
void 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;
iPendingCancelDueToCancelRequest = 0;
for (uint32 i = 0; i < iCurrentContextList.size(); ++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 = 0;
OSCL_TRY(leavecode, iSourceNode->CancelAllCommands(iSourceNodeSessionId, (OsclAny*)&iPendingCancelDueToCancelRequest));
if (leavecode == 0)
{
++iPendingCancelDueToCancelRequest;
}
}
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 = 0;
OSCL_TRY(leavecode, iCurrentContextList[i]->iNode->CancelAllCommands(iCurrentContextList[i]->iEngineDatapath->iSinkNodeSessionId, (OsclAny*)&iPendingCancelDueToCancelRequest));
if (leavecode == 0)
{
++iPendingCancelDueToCancelRequest;
}
}
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 = 0;
OSCL_TRY(leavecode, iCurrentContextList[i]->iNode->CancelAllCommands(iCurrentContextList[i]->iEngineDatapath->iDecNodeSessionId, (OsclAny*)&iPendingCancelDueToCancelRequest));
if (leavecode == 0)
{
++iPendingCancelDueToCancelRequest;
}
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() Unknown node type. Asserting"));
OSCL_ASSERT(false);
}
}
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 = 0;
OSCL_TRY(leavecode, iCurrentContextList[i]->iDatapath->CancelCommand((OsclAny*)&iPendingCancelDueToCancelRequest));
if (leavecode == 0)
{
++iPendingCancelDueToCancelRequest;
}
}
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 = 0;
OSCL_TRY(leavecode, iPlayerRecognizerRegistry.CancelQuery((OsclAny*)&iPendingCancelDueToCancelRequest));
if (leavecode == 0)
{
++iPendingCancelDueToCancelRequest;
}
}
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 (iPendingCancelDueToCancelRequest == 0)
{
// Cancel on the node failed so go to next step
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() CancelAllCommands() on the node did a leave"));
RemoveDatapathContextFromList(); // remove left-over datapath contexts
DoShutdownDueToCancel();
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() %d CancelAllCommands are pending", iPendingCancelDueToCancelRequest));
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() Out"));
}
void PVPlayerEngine::DoShutdownDueToCancel()
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoShutdownDueToCancel() In"));
// There should be a command to cancel
OSCL_ASSERT(iCmdToCancel.empty() == false);
switch (iCmdToCancel[0].GetCmdType())
{
case PVP_ENGINE_COMMAND_ADD_DATA_SOURCE:
case PVP_ENGINE_COMMAND_SET_PLAYBACK_RANGE:
case PVP_ENGINE_COMMAND_PREPARE:
case PVP_ENGINE_COMMAND_PAUSE:
case PVP_ENGINE_COMMAND_RESUME:
case PVP_ENGINE_COMMAND_STOP:
DoStopDueToCancel();
break;
case PVP_ENGINE_COMMAND_INIT:
DoResetDueToCancel();
break;
default:
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoShutdownDueToCancel() Unsupported command to cancel. Asserting"));
OSCL_ASSERT(false);
break;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoShutdownDueToCancel() Out"));
}
void PVPlayerEngine::DoStopDueToCancel(void)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoStopDueToCancel() In"));
int32 leavecode = 0;
iPendingStopDueToCancelRequest = 0;
if (iSourceNode)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoStopDueToCancel() Calling Stop() on source node"));
leavecode = 0;
OSCL_TRY(leavecode, iSourceNode->Stop(iSourceNodeSessionId, &iPendingStopDueToCancelRequest));
if (!leavecode)
{
++iPendingStopDueToCancelRequest;
}
}
// Go through each active datapath and stop the decoder and sink nodes
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackActive)
{
if (iDatapathList[i].iDecNode)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoStopDueToCancel() Calling Stop() on dec node"));
leavecode = 0;
OSCL_TRY(leavecode, iDatapathList[i].iDecNode->Stop(iDatapathList[i].iDecNodeSessionId, &iPendingStopDueToCancelRequest));
if (!leavecode)
{
++iPendingStopDueToCancelRequest;
}
}
if (iDatapathList[i].iSinkNode)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoStopDueToCancel() Calling Stop() on sink node"));
leavecode = 0;
OSCL_TRY(leavecode, iDatapathList[i].iSinkNode->Stop(iDatapathList[i].iSinkNodeSessionId, &iPendingStopDueToCancelRequest));
if (!leavecode)
{
++iPendingStopDueToCancelRequest;
}
}
}
}
if (iPendingStopDueToCancelRequest == 0)
{
// All Stop() on the nodes failed so go to next step
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoStopDueToCancel() All Stop() on the nodes did a leave"));
DoResetDueToCancel();
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoStopDueToCancel() %d Stops are pending", iPendingStopDueToCancelRequest));
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoStopDueToCancel() Out"));
}
void PVPlayerEngine::DoResetDueToCancel(void)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoResetDueToCancel() In"));
int32 leavecode = 0;
iPendingResetDueToCancelRequest = 0;
if (iSourceNode)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoResetDueToCancel() Calling Reset() on source node"));
leavecode = 0;
OSCL_TRY(leavecode, iSourceNode->Reset(iSourceNodeSessionId, &iPendingResetDueToCancelRequest));
if (!leavecode)
{
++iPendingResetDueToCancelRequest;
}
}
// Go through each active datapath and reset the decoder and sink nodes
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackActive)
{
if (iDatapathList[i].iDecNode)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoResetDueToCancel() Calling Reset() on dec node"));
leavecode = 0;
OSCL_TRY(leavecode, iDatapathList[i].iDecNode->Reset(iDatapathList[i].iDecNodeSessionId, &iPendingResetDueToCancelRequest));
if (!leavecode)
{
++iPendingResetDueToCancelRequest;
}
}
if (iDatapathList[i].iSinkNode)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoResetDueToCancel() Calling Reset() on sink node"));
leavecode = 0;
OSCL_TRY(leavecode, iDatapathList[i].iSinkNode->Reset(iDatapathList[i].iSinkNodeSessionId, &iPendingResetDueToCancelRequest));
if (!leavecode)
{
++iPendingResetDueToCancelRequest;
}
}
}
}
if (iPendingResetDueToCancelRequest == 0)
{
// All Reset() on the nodes failed so go to next step
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoResetDueToCancel() All Reset() on the nodes did a leave"));
DoCleanupDueToCancel();
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoResetDueToCancel() %d Resets are pending", iPendingResetDueToCancelRequest));
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoResetDueToCancel() Out"));
}
void PVPlayerEngine::DoCleanupDueToCancel(void)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCleanupDueToCancel() In"));
// Wipe everything out
iPollingCheckTimer->Clear();
// Clean up the datapaths
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
DoEngineDatapathCleanup(iDatapathList[i]);
}
iDatapathList.clear();
// Clean up the source node
DoSourceNodeCleanup();
while (!iCurrentContextList.empty())
{
FreeEngineContext(iCurrentContextList[0]);
}
SetEngineState(PVP_ENGINE_STATE_IDLE);
iCmdToCancel.clear();
EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), PVMFSuccess);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCleanupDueToCancel() Out"));
}
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::DoQueryUUID(PVPlayerEngineCommand& aCmd)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoQueryUUID() In"));
PvmfMimeString* mimetype;
Oscl_Vector<PVUuid, OsclMemAllocator> *uuidvec;
bool exactmatch;
mimetype = (PvmfMimeString*)(aCmd.GetParam(0).pOsclAny_value);
uuidvec = (Oscl_Vector<PVUuid, OsclMemAllocator>*)(aCmd.GetParam(1).pOsclAny_value);
exactmatch = aCmd.GetParam(2).bool_value;
if (mimetype == NULL || uuidvec == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoQueryUUID() Passed in parameter invalid."));
return PVMFErrArgument;
}
int32 leavecode = 0;
PVMFStatus cmdstatus = PVMFSuccess;
// For now just return all available extension interface UUID
// Capability and config interface
OSCL_TRY(leavecode, uuidvec->push_back(PVMI_CAPABILITY_AND_CONFIG_PVUUID));
OSCL_FIRST_CATCH_ANY(leavecode, cmdstatus = PVMFErrNoMemory);
// License acquisition interface
OSCL_TRY(leavecode, uuidvec->push_back(PVPlayerLicenseAcquisitionInterfaceUuid));
OSCL_FIRST_CATCH_ANY(leavecode, cmdstatus = PVMFErrNoMemory);
// Track level info interface from source node
if (iSourceNodeTrackLevelInfoIF && leavecode == 0)
{
leavecode = 0;
OSCL_TRY(leavecode, uuidvec->push_back(PVMF_TRACK_LEVEL_INFO_INTERFACE_UUID));
OSCL_FIRST_CATCH_ANY(leavecode, cmdstatus = PVMFErrNoMemory);
}
EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), cmdstatus);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoQueryUUID() 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)
{
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);
iDataSourcePS = (PVPlayerDataSourcePacketSource*)(aCmd.GetParam(0).pOsclAny_value);
// (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;
iSourceFormatType = iDataSource->GetDataSourceFormatType();
if (iSourceFormatType == PVMF_FORMAT_UNKNOWN)
{
retval = DoQuerySourceFormatType(aCmd.GetCmdId(), aCmd.GetContext());
}
else
{
if (iSourceFormatType == PVMF_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)
{
// Do cleanup
DoSourceNodeCleanup();
iDataSource = NULL;
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoAddDataSource() Out"));
return retval;
}
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;
OSCL_TRY(leavecode, retval = iPlayerRecognizerRegistry.QueryFormatType(iDataSource->GetDataSourceURL(), *this, (OsclAny*) context));
OSCL_FIRST_CATCH_ANY(leavecode,
FreeEngineContext(context);
return PVMFErrNotSupported;
);
if (retval != PVMFSuccess)
{
FreeEngineContext(context);
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoQuerySourceFormatType() Out"));
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_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() 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"));
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!"));
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;
OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, sourceinituuid, (PVInterface*&)iSourceNodeInitIF, (OsclAny*)context));
OSCL_FIRST_CATCH_ANY(leavecode,
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_FORMAT_UNKNOWN);
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("://"));
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 = iSourceNodeInitIF->SetSourceInitializationData(sourceURL, iSourceFormatType, iDataSource->GetDataSourceContextData());
if (retval != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryTrackSelIF() SetSourceInitializationData failed"));
return retval;
}
// Set Playback Clock
retval = iSourceNodeInitIF->SetClientPlayBackClock(&iPlaybackClock);
if (retval != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryTrackSelIF() SetClientPlayBackClock failed!"));
return retval;
}
}
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;
OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, trackseluuid, (PVInterface*&)iSourceNodeTrackSelIF, (OsclAny*)context));
OSCL_FIRST_CATCH_ANY(leavecode,
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;
}
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;
OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, tracklevelinfouuid, (PVInterface*&)iSourceNodeTrackLevelInfoIF, (OsclAny*)context));
if (leavecode)
{
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;
OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, pbctrluuid, (PVInterface*&)iSourceNodePBCtrlIF, (OsclAny*)context));
if (leavecode)
{
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;
OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, dirctrluuid, (PVInterface*&)iSourceNodeDirCtrlIF, (OsclAny*)context));
if (leavecode)
{
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;
OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, metadatauuid, (PVInterface*&)iSourceNodeMetadataExtIF, (OsclAny*)context));
if (leavecode)
{
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;
OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, capconfiguuid, (PVInterface*&)iSourceNodeCapConfigIF, (OsclAny*)context));
if (leavecode)
{
FreeEngineContext(context);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryInterfaceOptional() QueryInterface on iSourceNode did a leave!"));
}
else
{
++iNumPendingNodeCmd;
}
// Query for CPM License interface
context = NULL;
context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQueryCPMLicenseIF);
PVUuid licUuid = PVMFCPMPluginLicenseInterfaceUuid;
cmdid = -1;
leavecode = 0;
OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, licUuid, (PVInterface*&)iSourceNodeCPMLicenseIF, (OsclAny*)context));
if (leavecode)
{
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;
OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, regInitUuid, (PVInterface*&)iSourceNodeRegInitIF, (OsclAny*)context));
if (leavecode)
{
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::DoAddDataSourceFailureComplete(void)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoAddDataSourceFailureComplete() In"));
// Cleanup the source node since AddDataSource failed
DoSourceNodeCleanup();
iDataSource = NULL;
// Send the command completion
if (iCommandCompleteInEngineAOErrMsg)
{
EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), iCommandCompleteInEngineAOCmdStatus, OSCL_STATIC_CAST(PVInterface*, iCommandCompleteInEngineAOErrMsg));
iCommandCompleteInEngineAOErrMsg->removeRef();
iCommandCompleteInEngineAOErrMsg = NULL;
}
else
{
EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), iCommandCompleteInEngineAOCmdStatus);
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoAddDataSourceFailureComplete() Out"));
return PVMFSuccess;
}
PVMFStatus PVPlayerEngine::DoInitFailureComplete(void)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoInitFailureComplete() In"));
// Cleanup the source node since AddDataSource failed
DoSourceNodeCleanup();
iDataSource = NULL;
// Send the command completion
if (iCommandCompleteInEngineAOErrMsg)
{
EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), iCommandCompleteInEngineAOCmdStatus, OSCL_STATIC_CAST(PVInterface*, iCommandCompleteInEngineAOErrMsg));
iCommandCompleteInEngineAOErrMsg->removeRef();
iCommandCompleteInEngineAOErrMsg = NULL;
}
else
{
EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), iCommandCompleteInEngineAOCmdStatus);
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoInitFailureComplete() Out"));
return PVMFSuccess;
}
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;
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(NULL, NULL, NULL, aCmd.GetCmdId(), aCmd.GetContext(), PVP_CMD_GetNodeMetadataKey);
PVMFMetadataExtensionInterface* metadataif = iMetadataIFList[i].iInterface;
PVMFSessionId sessionid = iMetadataIFList[i].iSessionId;
int32 leavecode = 0;
PVMFCommandId cmdid = -1;
OSCL_TRY(leavecode, cmdid = metadataif->GetNodeMetadataKeys(sessionid,
*(iGetMetadataKeysParam.iKeyList),
nodestartindex,
iGetMetadataKeysParam.iMaxKeyEntries,
iGetMetadataKeysParam.iQueryKey,
(OsclAny*)context));
OSCL_FIRST_CATCH_ANY(leavecode,
FreeEngineContext(context);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetMetadataKey() GetNodeMetadataKeys on a node did a leave!"));
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;
}
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);
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 PVMFErrArgument;
}
// Retrieve the metadata value from the first node
PVPlayerEngineContext* context = AllocateEngineContext(NULL, NULL, NULL, aCmd.GetCmdId(), aCmd.GetContext(), PVP_CMD_GetNodeMetadataValue);
PVMFMetadataExtensionInterface* metadataif = iMetadataIFList[i].iInterface;
PVMFSessionId sessionid = iMetadataIFList[i].iSessionId;
int32 leavecode = 0;
PVMFCommandId cmdid = -1;
OSCL_TRY(leavecode, cmdid = metadataif->GetNodeMetadataValues(sessionid,
*(iGetMetadataValuesParam.iKeyList),
*(iGetMetadataValuesParam.iValueList),
nodestartindex,
iGetMetadataValuesParam.iMaxValueEntries,
(OsclAny*)context));
OSCL_FIRST_CATCH_ANY(leavecode,
FreeEngineContext(context);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetMetadataValue() GetNodeMetadataValues on a node did a leave!"));
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::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"));
iRollOverState = RollOverStateIdle;
if ((GetPVPlayerState() != PVP_STATE_IDLE) || (iSourceNode == NULL))
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoInit() Wrong engine state"));
return PVMFErrInvalidState;
}
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 retval;
}
}
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;
// 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"));
// 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();
if (iSourceNodeMetadataExtIF == NULL)
{
return PVMFErrArgument;
}
// 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)
{
//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() SourceNodeRollOver Failed"));
return status;
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeRollOver() Invalid State"));
return PVMFErrInvalidState;
}
PVMFStatus PVPlayerEngine::DoSourceNodeGetDlaData(PVCommandId aCmdId, OsclAny* aCmdContext)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeGetDlaData() In"));
// Create a key list with just duration key
iDlaDataKeyList.clear();
OSCL_HeapString<OsclMemAllocator> tmpstr = _STRLIT_CHAR("drm/dla-data");
iDlaDataKeyList.push_back(tmpstr);
// Clear the value list
iDlaDataValueList.clear();
if (iSourceNodeMetadataExtIF == NULL)
{
return PVMFErrArgument;
}
// Call GetNodeMetadataValues on the source node to retrieve duration
PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeGetDlaData);
int32 leavecode = 0;
PVMFCommandId cmdid = -1;
OSCL_TRY(leavecode, cmdid = iSourceNodeMetadataExtIF->GetNodeMetadataValues(iSourceNodeSessionId,
iDlaDataKeyList,
iDlaDataValueList,
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::DoSourceNodeGetDlaData() GetNodeMetadataValues on iSourceNode did a leave!"));
return PVMFFailure);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeGetDlaData() Out"));
return PVMFSuccess;
}
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 the license interface is available from the source node, use that.
if (iSourceNodeCPMLicenseIF != NULL)
{
PVMFStatus status = DoSourceNodeGetLicense(aCmd.GetCmdId(), aCmd.GetContext());
if (status != PVMFSuccess)
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAcquireLicense() DoSourceNodeGetLicense failed."));
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoAcquireLicense() Out"));
return PVMFSuccess;
}
//Before getting license we need to get the dla-data blob from the source node
//to pass to the new plugin instance.
PVMFStatus status = DoSourceNodeGetDlaData(aCmd.GetCmdId(), aCmd.GetContext());
if (status != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAcquireLicense() DoSourceNodeGetDlaData failed."));
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoAcquireLicense() Out"));
return status;
}
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)
{
/* Make the CancelAll() command the current command */
iCmdToDlaCancel.push_front(aCmd);
/* Properly cancel a command being currently processed */
if (iSourceNodeCPMLicenseIF != NULL)
{
/* Cancel the GetLicense */
PVPlayerEngineContext* context = NULL;
PVMFCommandId cmdid = -1;
int32 leavecode = 0;
context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmd.GetCmdId(), aCmd.GetContext(), PVP_CMD_SourceNodeCancelGetLicense);
OSCL_TRY(leavecode, cmdid = iSourceNodeCPMLicenseIF->CancelGetLicense(iSourceNodeSessionId, iCPMGetLicenseCmdId, (OsclAny*)context));
if (leavecode)
{
FreeEngineContext(context);
status = PVMFErrNotSupported;
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelAcquireLicense() CancelGetLicense on iSourceNode did a leave!"));
}
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelAcquireLicense() CPM plug-in registry in local data source not specified."));
OSCL_ASSERT(false);
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::DoGetPluginLicenseIF()
{
//create & use a plug-in instance.
// Retrieve the CPM plug-in instance from the registry
if (iDataSource->GetDataSourceContextData() != NULL)
{
PVInterface* pvInterface =
OSCL_STATIC_CAST(PVInterface*, iDataSource->GetDataSourceContextData());
PVInterface* localDataSrc = NULL;
PVUuid localDataSrcUuid(PVMF_LOCAL_DATASOURCE_UUID);
if (pvInterface->queryInterface(localDataSrcUuid, localDataSrc))
{
PVMFLocalDataSource* opaqueData =
OSCL_STATIC_CAST(PVMFLocalDataSource*, localDataSrc);
if (opaqueData->iUseCPMPluginRegistry == false)
{
// CPM plug-in registry not available in the local data source
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAcquireLicense() CPM plug-in registry in local data source not specified."));
return PVMFErrBadHandle;
}
}
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);
if (cContext->iUseCPMPluginRegistry == false)
{
// CPM plug-in registry not available in the local data source
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAcquireLicense() CPM plug-in registry in local data source not specified."));
return PVMFErrBadHandle;
}
}
}
}
}
//Lookup the factory for the janus plugin
{
//Connect to registry
OsclRegistryAccessClient cli;
if (cli.Connect() != OsclErrNone)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAcquireLicense() Can't connect to plugin registry."));
return PVMFFailure;
}
OSCL_StackString<32> janusmimestr("X-CPM-PLUGIN/PV-WMDRM-JANUS");
iCPMPluginFactory = cli.GetFactory(janusmimestr);
if (iCPMPluginFactory)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoAcquireLicense() Using Janus Plug-in."));
}
else
{
OSCL_StackString<34> jupitermimestr("X-CPM-PLUGIN/PV-WMDRM-JUPITER");
iCPMPluginFactory = cli.GetFactory(jupitermimestr);
if (iCPMPluginFactory)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoAcquireLicense() Using Jupiter Plug-in."));
}
}
//Close registry session.
cli.Close();
}
if (iCPMPluginFactory == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAcquireLicense() Can't find Janus plugin factory."));
return PVMFFailure;
}
//Create an instance of the plugin.
iCPMPlugin = ((PVMFCPMPluginFactory*)iCPMPluginFactory)->CreateCPMPlugin();
if (!iCPMPlugin)
{
// Specified CPM plug-in is not available in the registry
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAcquireLicense() Can't create janus plugin."));
return PVMFFailure;
}
int32 leavecode = 0;
// Create a session to the CPM plug-in
OSCL_TRY(leavecode, iCPMPluginSessionId = iCPMPlugin->Connect(*this));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAcquireLicense() Connect to the plug-in did a leave!"));
((PVMFCPMPluginFactory*)iCPMPluginFactory)->DestroyCPMPlugin(iCPMPlugin);
iCPMPlugin = NULL;
iCPMPluginFactory = NULL;
return PVMFErrResource;);
// Query for the license extension IF
leavecode = 0;
OSCL_TRY(leavecode, iCPMPlugin->QueryInterface(iCPMPluginSessionId, PVMFCPMPluginLicenseInterfaceUuid, (PVInterface*&)iCPMPluginLicenseIF, NULL));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAcquireLicense() QueryInterface to the plug-in did a leave!"));
iCPMPlugin->Disconnect(iCPMPluginSessionId);
((PVMFCPMPluginFactory*)iCPMPluginFactory)->DestroyCPMPlugin(iCPMPlugin);
iCPMPlugin = NULL;
iCPMPluginFactory = NULL;
return PVMFErrResource;);
iCPMPluginCommand = PVP_CMD_CPMQueryLicenseIF;
return PVMFSuccess;
}
PVMFStatus PVPlayerEngine::DoSourceNodeGetLicense(PVCommandId aCmdId, OsclAny* aCmdContext)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
(0, "PVPlayerEngine::DoSourceNodeGetLicense() Tick=%d", OsclTickCount::TickCount()));
OSCL_UNUSED_ARG(aCmdId);
OSCL_UNUSED_ARG(aCmdContext);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeGetLicense() In"));
if (iSourceNodeCPMLicenseIF == NULL)
{
OSCL_ASSERT(false);
return PVMFErrBadHandle;
}
// Get the license
PVPlayerEngineContext* context = NULL;
int32 leavecode = 0;
context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeGetLicense);
if (iCPMAcquireLicenseParam.iContentNameChar)
{
// Use the char version
iCPMContentNameStr = iCPMAcquireLicenseParam.iContentNameChar;
OSCL_TRY(leavecode, iCPMGetLicenseCmdId = iSourceNodeCPMLicenseIF->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 = iSourceNodeCPMLicenseIF->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::DoSourceNodeGetLicense() Content name not specified. Asserting"));
OSCL_ASSERT(false);
return PVMFErrArgument;
}
if (leavecode)
{
FreeEngineContext(context);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeGetLicense() GetLicense on iSourceNode did a leave!"));
}
else
{
++iNumPendingNodeCmd;
}
if (iNumPendingNodeCmd <= 0)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeGetLicense() Out No pending QueryInterface() on source node"));
return PVMFFailure;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeGetLicense() Out"));
return PVMFSuccess;
}
PVMFStatus PVPlayerEngine::DoCPMPluginSetUserAgentHeader(PVCommandId aCmdId, OsclAny* aCmdContext)
{
OSCL_UNUSED_ARG(aCmdId);
OSCL_UNUSED_ARG(aCmdContext);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCPMPluginSetUserAgentHeader() In"));
if (iCPMPluginCapConfigIf == NULL)
{
OSCL_ASSERT(false);
return PVMFErrBadHandle;
}
//set the parameter
OSCL_StackString<64> userAgentheaderKey(_STRLIT_CHAR("x-pvmf/net/user-agent"));
PvmiKvp *retKVP;
/*Search for user-agent key in the vector*/
for (uint32 i = 0;i < iPvmiKvpCapNConfig.size();i++)
{
if (oscl_strstr(iPvmiKvpCapNConfig[i]->key, userAgentheaderKey.get_cstr()))
{
iCPMPluginCapConfigIf->setParametersSync(NULL, iPvmiKvpCapNConfig[i], 1, retKVP);
//log if error
if (retKVP)
{
//log error
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCPMPluginSetUserAgentHeader() user-agent parameter could not be set in CPM"));
}
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCPMPluginSetUserAgentHeader() Out"));
return PVMFSuccess;
}
PVMFStatus PVPlayerEngine::DoCPMPluginGetLicense(PVCommandId aCmdId, OsclAny* aCmdContext)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
(0, "PVPlayerEngine::DoCPMPluginGetLicense() Tick=%d", OsclTickCount::TickCount()));
OSCL_UNUSED_ARG(aCmdId);
OSCL_UNUSED_ARG(aCmdContext);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCPMPluginGetLicense() In"));
if (iCPMPluginLicenseIF == NULL)
{
OSCL_ASSERT(false);
return PVMFErrBadHandle;
}
// Get the license
int32 leavecode = 0;
if (iCPMAcquireLicenseParam.iContentNameChar)
{
// Use the char version
iCPMContentNameStr = iCPMAcquireLicenseParam.iContentNameChar;
OSCL_TRY(leavecode, iCPMPluginLicenseIF->GetLicense(iCPMPluginSessionId,
iCPMContentNameStr,
iCPMAcquireLicenseParam.iLicenseData,
iCPMAcquireLicenseParam.iLicenseDataSize,
iCPMAcquireLicenseParam.iTimeoutMsec));
}
else if (iCPMAcquireLicenseParam.iContentNameWChar)
{
// Use the wchar version
iCPMContentNameWStr = iCPMAcquireLicenseParam.iContentNameWChar;
OSCL_TRY(leavecode, iCPMPluginLicenseIF->GetLicense(iCPMPluginSessionId,
iCPMContentNameWStr,
iCPMAcquireLicenseParam.iLicenseData,
iCPMAcquireLicenseParam.iLicenseDataSize,
iCPMAcquireLicenseParam.iTimeoutMsec));
}
else
{
// This should not happen
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCPMPluginGetLicense() Content name not specified. Asserting"));
OSCL_ASSERT(false);
return PVMFErrArgument;
}
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCPMPluginGetLicense() GetLicense to the plug-in's license interface did a leave!"));
return PVMFErrResource;);
iCPMPluginCommand = PVP_CMD_CPMGetLicense;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCPMPluginGetLicense() Out"));
return PVMFSuccess;
}
PVMFStatus PVPlayerEngine::DoCPMPluginAcquireLicenseComplete()
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
(0, "PVPlayerEngine::DoCPMPluginAcquireLicenseComplete() Tick=%d", OsclTickCount::TickCount()));
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCPMPluginAcquireLicenseComplete() In"));
// Close the CPM plug-in session and reset variables
if (iCPMPluginLicenseIF)
{
iCPMPluginLicenseIF->removeRef();
iCPMPluginLicenseIF = NULL;
}
iCPMPluginCapConfigIf = NULL;
// Destroy the plugin instance that we created.
if (iCPMPlugin)
{
// Trap any leave but no need to handle it other than report it
int32 leavecode = 0;
OSCL_TRY(leavecode, iCPMPlugin->Disconnect(iCPMPluginSessionId));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCPMPluginAcquireLicenseComplete() Disconnect on CPM plugin did a leave. Asserting."));
OSCL_ASSERT(false);
);
((PVMFCPMPluginFactory*)iCPMPluginFactory)->DestroyCPMPlugin(iCPMPlugin);
}
iCPMPlugin = NULL;
iCPMPluginFactory = NULL;
iCPMPluginSessionId = 0;
iCPMPluginCommand = -1;
// Send the command completion
if (iCommandCompleteInEngineAOErrMsg)
{
EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), iCommandCompleteInEngineAOCmdStatus, OSCL_STATIC_CAST(PVInterface*, iCommandCompleteInEngineAOErrMsg));
iCommandCompleteInEngineAOErrMsg->removeRef();
iCommandCompleteInEngineAOErrMsg = NULL;
}
else
{
EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), iCommandCompleteInEngineAOCmdStatus);
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCPMPluginAcquireLicenseComplete() 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 (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;
// Determine the data sink's media type
switch (GetMediaTypeIndex(datasink->GetDataSinkFormatType()))
{
case PVMF_UNCOMPRESSED_VIDEO_FORMAT:
case PVMF_COMPRESSED_VIDEO_FORMAT:
newdatapath.iMediaType = PVP_MEDIATYPE_VIDEO;
break;
case PVMF_UNCOMPRESSED_AUDIO_FORMAT:
case PVMF_COMPRESSED_AUDIO_FORMAT:
newdatapath.iMediaType = PVP_MEDIATYPE_AUDIO;
break;
case PVMF_TEXT_FORMAT:
newdatapath.iMediaType = PVP_MEDIATYPE_TEXT;
break;
default:
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAddDataSink() Unknown format. Cannot determine sink's media type"));
return PVMFErrNotSupported;
}
// Add a new engine datapath to the list for the data sink
int32 leavecode = 0;
OSCL_TRY(leavecode, iDatapathList.push_front(newdatapath));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAddDataSink() New datapath could not be added to iDatapathList"));
return PVMFErrNoMemory);
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 (iWatchDogTimer != NULL)
{
if (iWatchDogTimer->IsBusy())
{
iWatchDogTimer->Cancel();
}
}
iNumPendingSkipCompleteEvent = 0;
iNumPVMFInfoStartOfDataPending = 0;
iStreamID++;
if (GetPVPlayerState() == PVP_STATE_ERROR)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRange() Wrong engine state"));
return PVMFErrInvalidState;
}
if (aCmd.GetParam(2).bool_value)
{
#if 1
// 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;
#else
iQueuedRangePresent = true;
iQueuedStartPosition = aCmd.GetParam(0).playbackpos_value;
iQueuedStopPosition = aCmd.GetParam(1).playbackpos_value;
EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
return PVMFSuccess;
#endif
}
// 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 the paused-due-to-EOS flag
iPlaybackPausedDueToEndOfClip = false;
// Change the begin position
iCurrentBeginPosition = aCmd.GetParam(0).playbackpos_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;
}
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;
}
if (aBeginPos.iPosUnit == PVPPBPOSUNIT_PLAYLIST)
{
aBeginPos.iPlayListPosValue.millisec_value = timems;
aBeginPos.iPlayListPosUnit = PVPPBPOSUNIT_MILLISEC;
}
else
{
aBeginPos.iPosValue.millisec_value = timems;
aBeginPos.iPosUnit = PVPPBPOSUNIT_MILLISEC;
}
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:
{
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;
}
aBeginPos.iPosValue.millisec_value = timems;
aBeginPos.iPosUnit = PVPPBPOSUNIT_MILLISEC;
iChangePlaybackPositionWhenResuming = true;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateCurrentBeginPosition() Saving requested begin position(%d ms) for resume", timems));
}
}
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 PVMFFailure;
}
PVMFCommandId cmdid = -1;
if (iSeekToSyncPoint && iSyncPointSeekWindow > 0)
{
PVPPlaybackPosition curpos;
curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC;
GetPlaybackClockPosition(curpos);
// Need to query the data source on where playback would actually begin from
PVMFTimestamp startpos;
startpos = iCurrentBeginPosition.iPosValue.millisec_value;
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", startpos, iSeekToSyncPoint));
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoChangePlaybackPosition() Querying source position. Position %d ms, SeekToSyncPt %d", startpos, iSeekToSyncPoint));
iActualPlaybackPosition = curpos.iPosValue.millisec_value;
int32 leavecode = 0;
iSeekPointBeforeTargetNPT = 0;
iSeekPointAfterTargetNPT = 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)
{
switch (*formatType)
{
case PVMF_MPEG4FF:
mpeg4FormatType = true;
break;
default:
mpeg4FormatType = false;
break;
}
}
if (mpeg4FormatType)
{
OSCL_TRY(leavecode, cmdid = iSourceNodePBCtrlIF->QueryDataSourcePosition(iSourceNodeSessionId, startpos,
iSeekPointBeforeTargetNPT, iSeekPointAfterTargetNPT, (OsclAny*)context, iSeekToSyncPoint));
}
else
{
OSCL_TRY(leavecode, cmdid = iSourceNodePBCtrlIF->QueryDataSourcePosition(iSourceNodeSessionId, startpos, iActualPlaybackPosition,
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(iCurrentBeginPosition.iPosValue.millisec_value, iSeekToSyncPoint, 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(PVMFTimestamp aTargetNPT, bool aSeekToSyncPoint, 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 PVMFFailure;
}
bool clockpausedhere;
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", aTargetNPT, aSeekToSyncPoint));
int32 leavecode = 0;
if (iCurrentBeginPosition.iPosUnit == PVPPBPOSUNIT_PLAYLIST)
{
int32 tempStreamID = 0;
tempStreamID = iStreamID;
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;
}
iDataSourcePosParams.iPlayElementIndex = iCurrentBeginPosition.iPlayElementIndex;
iDataSourcePosParams.iSeekToSyncPoint = aSeekToSyncPoint;
iDataSourcePosParams.iTargetNPT = iCurrentBeginPosition.iPlayListPosValue.millisec_value;
iDataSourcePosParams.iStreamID = iStreamID;
iDataSourcePosParams.iPlaylistUri = iCurrentBeginPosition.iPlayListUri;
PVMFCommandId cmdid = -1;
leavecode = 0;
OSCL_TRY(leavecode, cmdid = iSourceNodePBCtrlIF->SetDataSourcePosition(iSourceNodeSessionId,
iDataSourcePosParams,
(OsclAny*)context));
OSCL_FIRST_CATCH_ANY(leavecode,
FreeEngineContext(context);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePositionDuringPlayback() SetDataSourcePosition on iSourceNodePBCtrlIF did a leave!"));
if (clockpausedhere)
{
// Resume the clock if paused in this function
iPlaybackClock.Start();
// To get regular play status events
StartPlaybackStatusTimer();
}
if (leavecode == PVMFErrNotSupported || leavecode == PVMFErrArgument)
{
return leavecode;
}
else
{
return PVMFFailure;
}
);
}
else
{
// we assume that the data is not present in the graph
// if present we will reset this flag.
int32 tempStreamID = 0;
// if reposition points exists in between the actualPlaybackPosition and
// the currentPlaybackClock position, then the reposition data exists with
// in the graph, so we need to start a new media segment
// Check if forward repositioning does not need source repositioning
PVPPlaybackPosition curpos;
curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC;
GetPlaybackClockPosition(curpos);
tempStreamID = iStreamID;
iActualMediaDataTS = 0;
iAdjustedMediaDataTS = 0;
iActualPlaybackPosition = 0;
leavecode = 0;
PVMFCommandId cmdid = -1;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePositionDuringPlayback() SetDataSourcePosition on iSourceNodePBCtrlIF - TargetNPT=%d, aSeekToSyncPoint=%d", aTargetNPT, aSeekToSyncPoint));
OSCL_TRY(leavecode, cmdid = iSourceNodePBCtrlIF->SetDataSourcePosition(iSourceNodeSessionId, aTargetNPT, iActualPlaybackPosition, iActualMediaDataTS, aSeekToSyncPoint, tempStreamID, (OsclAny*)context));
OSCL_FIRST_CATCH_ANY(leavecode,
FreeEngineContext(context);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePositionDuringPlayback() SetDataSourcePosition on iSourceNodePBCtrlIF did a leave!"));
if (clockpausedhere)
{
// Resume the clock if paused in this function
iPlaybackClock.Start();
// To get regular play status events
StartPlaybackStatusTimer();
}
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();
// Stop the playback position status timer
StopPlaybackStatusTimer();
// Tell the sink nodes to skip the unneeded media data
iNumPendingNodeCmd = 0;
PVMFCommandId cmdid = -1;
int32 leavecode = 0;
// For all sink node with sync control IF, call SkipMediaData()
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVPlayerEngine::DoSinkNodeSkipMediaDataDuringPlayback() Calling SkipMediaData() on sink nodes. MediadataTS to flush to %d ms, MediadataTS to skip to %d ms, RenderSkipped %d", iActualMediaDataTS, iAdjustedMediaDataTS, iRenderSkipped));
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
(0, "PVPlayerEngine::DoSinkNodeSkipMediaDataDuringPlayback() Calling SkipMediaData() on sink nodes. MediadataTS to flush to %d ms, MediadataTS to skip to %d ms, RenderSkipped %d", iActualMediaDataTS, iAdjustedMediaDataTS, iRenderSkipped));
if (iDatapathList[i].iTrackActive == true &&
iDatapathList[i].iEndOfDataReceived == false &&
iDatapathList[i].iSinkNodeSyncCtrlIF != NULL)
{
leavecode = 0;
PVPlayerEngineContext* context = AllocateEngineContext(&(iDatapathList[i]), iDatapathList[i].iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeSkipMediaDataDuringPlayback);
OSCL_TRY(leavecode, cmdid = iDatapathList[i].iSinkNodeSyncCtrlIF->SkipMediaData(iDatapathList[i].iSinkNodeSessionId, iActualMediaDataTS, iAdjustedMediaDataTS, iStreamID, iRenderSkipped, aSFR, (OsclAny*) context));
if (leavecode == 0)
{
++iNumPendingNodeCmd;
++iNumPendingSkipCompleteEvent;
++iNumPVMFInfoStartOfDataPending;
}
else
{
FreeEngineContext(context);
}
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeSkipMediaDataDuringPlayback() Out"));
if (iNumPendingNodeCmd > 0)
{
return PVMFSuccess;
}
else
{
if (clockpausedhere)
{
// Resume the clock if paused in this function
iPlaybackClock.Start();
// To get regular play status events
StartPlaybackStatusTimer();
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeSkipMediaDataDuringPlayback() Skip on sink nodes failed"));
return PVMFFailure;
}
}
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 (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"));
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;
}
// 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;
OsclTimebase* timebase = (OsclTimebase*)(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 PVMFFailure;
}
// 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 PVMFFailure;
}
// Reset the paused-due-to-EOS flag if direction changes
if (direction != iPlaybackDirection)
{
iPlaybackPausedDueToEndOfClip = false;
}
// 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 = PVMFFailure;
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;
OsclTimebase** timebase = (OsclTimebase**)(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"));
// Reset the paused-due-to-EOS flag
iPlaybackPausedDueToEndOfClip = false;
if (GetPVPlayerState() != PVP_STATE_INITIALIZED)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPrepare() Wrong engine state"));
return PVMFErrInvalidState;
}
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
PVMFStatus cmdstatus = DoSourceNodeTrackQuery(aCmd.GetCmdId(), aCmd.GetContext());
if (cmdstatus != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPrepare() DoSourceNodeTrackQuery() failed"));
return cmdstatus;
}
SetEngineState(PVP_ENGINE_STATE_PREPARING);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoPrepare() Out"));
return PVMFSuccess;
}
PVMFStatus PVPlayerEngine::DoSourceNodeTrackQuery(PVCommandId aCmdId, OsclAny* aCmdContext)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeTrackQuery() In"));
if (iSourceNodeTrackSelIF == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeTrackQuery() Source node track sel IF not available. Asserting"));
OSCL_ASSERT(false);
return PVMFFailure;
}
uint32 i = 0;
int32 leavecode = 0;
iNumPendingNodeCmd = 0;
bool bMimeType = false;
bool bMediaType = false;
PVMFMediaPresentationInfo sourcepresinfo;
PVMFStatus retval = PVMFFailure;
OSCL_TRY(leavecode, retval = iSourceNodeTrackSelIF->GetMediaPresentationInfo(sourcepresinfo));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeTrackQuery() GetMediaPresentationInfo on iSourceNodeTrackSelIF did a leave!"));
return PVMFFailure);
if (retval != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeTrackQuery() GetMediaPresentationInfo() call on source node failed"));
return retval;
}
// For each engine datapath, assign a track info from the list
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;
}
switch (iDatapathList[i].iMediaType)
{
case PVP_MEDIATYPE_TEXT:
{
for (uint32 j = 0; j < sourcepresinfo.getNumTracks(); ++j)
{
// Go through each track, check codec type, and save the track info
PVMFTrackInfo* curtrack = sourcepresinfo.getTrackInfo(j);
switch (GetFormatIndex(curtrack->getTrackMimeType().get_str()))
{
case PVMF_3GPP_TIMEDTEXT:
retval = DoQueryTrackInfo(iDatapathList[i], curtrack, aCmdId, aCmdContext);
if (retval != PVMFSuccess)
return retval;
// Break out of the loop
j = sourcepresinfo.getNumTracks();
bMimeType = true;
break;
default:
break;
}
}
}
bMediaType = true;
break;
case PVP_MEDIATYPE_VIDEO:
{
for (uint32 j = 0; j < sourcepresinfo.getNumTracks(); ++j)
{
// Go through each track, check codec type, and save the track info
PVMFTrackInfo* curtrack = sourcepresinfo.getTrackInfo(j);
PVMFFormatType srcformat = GetFormatIndex(curtrack->getTrackMimeType().get_str());
PVMFFormatType sinkformat = iDatapathList[i].iDataSink->GetDataSinkFormatType();
Oscl_Vector<PVUuid, OsclMemAllocator> foundUuids;
switch (srcformat)
{
case PVMF_M4V:
case PVMF_H263:
case PVMF_H264_RAW:
case PVMF_H264_MP4:
case PVMF_H264:
case PVMF_WMV:
case PVMF_RV:
{
if (IsDecNodeNeeded(srcformat, sinkformat) == true && iPlayerNodeRegistry.QueryRegistry(srcformat, sinkformat, foundUuids) != PVMFSuccess)
{
break;
}
retval = DoQueryTrackInfo(iDatapathList[i], curtrack, aCmdId, aCmdContext);
if (retval != PVMFSuccess)
return retval;
// Break out of the loop
j = sourcepresinfo.getNumTracks();
bMimeType = true;
break;
}
default:
break;
}
}
}
bMediaType = true;
break;
case PVP_MEDIATYPE_AUDIO:
{
for (uint32 j = 0; j < sourcepresinfo.getNumTracks(); ++j)
{
// Go through each track, check codec type, and save the track info
PVMFTrackInfo* curtrack = sourcepresinfo.getTrackInfo(j);
PVMFFormatType srcformat = GetFormatIndex(curtrack->getTrackMimeType().get_str());
PVMFFormatType sinkformat = iDatapathList[i].iDataSink->GetDataSinkFormatType();
Oscl_Vector<PVUuid, OsclMemAllocator> foundUuids;
switch (srcformat)
{
case PVMF_AMR_IETF:
case PVMF_AMR_IETF_COMBINED:
case PVMF_AMRWB_IETF:
case PVMF_AMRWB_IETF_PAYLOAD:
case PVMF_AMR_IF2:
case PVMF_ADIF:
case PVMF_ADTS:
case PVMF_MPEG4_AUDIO:
case PVMF_LATM:
case PVMF_MP3:
case PVMF_G726:
case PVMF_WMA:
case PVMF_REAL_AUDIO:
case PVMF_PCM:
case PVMF_PCM8:
case PVMF_PCM16:
case PVMF_PCM16_BE:
case PVMF_PCM_ULAW:
case PVMF_PCM_ALAW:
case PVMF_ASF_MPEG4_AUDIO:
{
if (IsDecNodeNeeded(srcformat, sinkformat) == true && iPlayerNodeRegistry.QueryRegistry(srcformat, sinkformat, foundUuids) != PVMFSuccess)
{
break;
}
retval = DoQueryTrackInfo(iDatapathList[i], curtrack, aCmdId, aCmdContext);
if (retval != PVMFSuccess)
return retval;
// Break out of the loop
j = sourcepresinfo.getNumTracks();
bMimeType = true;
break;
}
default:
break;
}
}
}
bMediaType = true;
break;
default:
// For unknown media type, do nothing
break;
}
}
if (!bMimeType || !bMediaType)
return PVMFFailure;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeTrackQuery() Out"));
return retval;
}
PVMFStatus PVPlayerEngine::DoQueryTrackInfo(PVPlayerEngineDatapath &aDatapath, PVMFTrackInfo* aTrack, PVCommandId aCmdId, OsclAny* aCmdContext)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoQueryTrackInfo() In %s", aTrack->getTrackMimeType().get_cstr()));
int32 leavecode = 0;
PVPlayerEngineContext* context = NULL;
PVMFCommandId cmdid = -1;
PVMFFormatType iSrcFormat = GetFormatIndex(aTrack->getTrackMimeType().get_str());
PVMFFormatType iSinkFormat = aDatapath.iDataSink->GetDataSinkFormatType();
if (IsDecNodeNeeded(iSrcFormat, iSinkFormat) == true)
{
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())
{
// No matching node found
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoQueryTrackInfo() No matching decoder node found"));
return PVMFFailure;
}
leavecode = 0;
OSCL_TRY(leavecode, aDatapath.iDecNode = iPlayerNodeRegistry.CreateNode(foundUuids[0]));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoQueryTrackInfo() Error in creating DecNode"));
return PVMFFailure;);
iNodeUuids.push_back(PVPlayerEngineUuidNodeMapping(foundUuids[0], aDatapath.iDecNode));
if (aDatapath.iDecNode == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoQueryTrackInfo() Dec node creation failed"));
return PVMFErrNoMemory;
}
if (aDatapath.iDecNode->ThreadLogon() != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoQueryTrackInfo() ThreadLogon() on dec node failed"));
return PVMFFailure;
}
PVMFNodeSessionInfo nodesessioninfo(this, this, (OsclAny*)aDatapath.iDecNode, this, (OsclAny*)aDatapath.iDecNode);
leavecode = 0;
OSCL_TRY(leavecode, aDatapath.iDecNodeSessionId = aDatapath.iDecNode->Connect(nodesessioninfo));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoQueryTrackInfo() Connect on dec node did a leave!"));
return PVMFFailure);
}
else
{
// Registry query failed
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoQueryTrackInfo() Registry query for dec node failed"));
return PVMFFailure;
}
// Query for Metadata IF
context = AllocateEngineContext(&aDatapath, aDatapath.iDecNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeDecNodeQueryCapConfigIF);
PVUuid capconfiguuid = PVMI_CAPABILITY_AND_CONFIG_PVUUID;
cmdid = -1;
leavecode = 0;
OSCL_TRY(leavecode, cmdid = aDatapath.iDecNode->QueryInterface(aDatapath.iDecNodeSessionId, capconfiguuid, (PVInterface*&)aDatapath.iDecNodeCapConfigIF, (OsclAny*)context));
if (leavecode)
{
FreeEngineContext(context);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoQueryTrackInfo() QueryInterface on dec node for cap-config IF did a leave!"));
}
else
{
++iNumPendingNodeCmd;
}
}
if (aDatapath.iDataSink->GetDataSinkType() == PVP_DATASINKTYPE_FILENAME)
{
// Create file output node for sink
leavecode = 0;
OSCL_TRY(leavecode, aDatapath.iSinkNode = PVFileOutputNodeFactory::CreateFileOutput());
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoQueryTrackInfo() Creation of file output node did a leave!"));
return PVMFErrNoMemory);
}
else if (aDatapath.iDataSink->GetDataSinkType() == PVP_DATASINKTYPE_SINKNODE)
{
// Use the specified output node for sink node
aDatapath.iSinkNode = aDatapath.iDataSink->GetDataSinkNodeInterface();
if (aDatapath.iSinkNode == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoQueryTrackInfo() Passed in sink node is NULL"));
return PVMFFailure;
}
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoQueryTrackInfo() Unsupported player data sink type"));
return PVMFErrNotSupported;
}
if (aDatapath.iSinkNode->ThreadLogon() != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoQueryTrackInfo() ThreadLogon() on passed-in sink node failed"));
return PVMFFailure;
}
PVMFNodeSessionInfo nodesessioninfo(this, this, (OsclAny*)aDatapath.iSinkNode, this, (OsclAny*)aDatapath.iSinkNode);
leavecode = 0;
OSCL_TRY(leavecode, aDatapath.iSinkNodeSessionId = aDatapath.iSinkNode->Connect(nodesessioninfo));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoQueryTrackInfo() Connect() on passed-in sink node did a leave!"));
return PVMFFailure);
// Query for Cap-Config IF
context = AllocateEngineContext(&aDatapath, aDatapath.iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeDecNodeQueryCapConfigIF);
PVUuid capconfiguuid = PVMI_CAPABILITY_AND_CONFIG_PVUUID;
cmdid = -1;
leavecode = 0;
OSCL_TRY(leavecode, cmdid = aDatapath.iSinkNode->QueryInterface(aDatapath.iSinkNodeSessionId, capconfiguuid, (PVInterface*&)aDatapath.iSinkNodeCapConfigIF, (OsclAny*)context));
if (leavecode)
{
FreeEngineContext(context);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoQueryTrackInfo() QueryInterface on sink node for cap-config IF did a leave!"));
}
else
{
++iNumPendingNodeCmd;
}
if (iNumPendingNodeCmd <= 0)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoQueryTrackInfo() Out No pending QueryInterface() on sink node"));
return PVMFErrNotSupported;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoQueryTrackInfo() 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. Asserting"));
OSCL_ASSERT(false);
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;
int32 leavecode = 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"));
return PVMFErrResourceConfiguration;
}
// Select in source node
leavecode = 0;
OSCL_TRY(leavecode, retval = iSourceNodeTrackSelIF->SelectTracks(selectedtracks));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeTrackSelection() SelectTracks on iSourceNodeTrackSelIF did a leave!"));
return PVMFFailure);
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. Asserting"));
OSCL_ASSERT(false);
return PVMFFailure;
}
uint32 i = 0;
int32 leavecode = 0;
PVMFStatus retval = PVMFFailure;
PVMFMediaPresentationInfo sourcepresinfo;
if (oPopulatePlayableListOnly)
{
iPlayableList.Reset();
OSCL_TRY(leavecode, retval = iSourceNodeTrackSelIF->GetMediaPresentationInfo(sourcepresinfo));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoTrackSelection() GetMediaPresentationInfo on iSourceNodeTrackSelIF did a leave!"));
return PVMFFailure);
if (retval != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoTrackSelection() GetMediaPresentationInfo() call on source node failed"));
return retval;
}
iPlayableList.setPresentationType(sourcepresinfo.getPresentationType());
iPlayableList.setSeekableFlag(sourcepresinfo.IsSeekable());
iPlayableList.SetDurationAvailable(sourcepresinfo.IsDurationAvailable());
iPlayableList.setDurationValue(sourcepresinfo.getDurationValue());
iPlayableList.setDurationTimeScale(sourcepresinfo.getDurationTimeScale());
}
else
{
if (oUsePreferenceList)
{
//perform track selection based on playable list
sourcepresinfo = iPreferenceList;
}
else
{
//perform track selection based on playable list
sourcepresinfo = iPlayableList;
}
}
// For each engine datapath, assign a track info from the list
for (i = 0;i < iDatapathList.size(); ++i)
{
PVMFStatus checkcodec = PVMFFailure;
int32 trackId = -1;
// Destroy the track info if present
if (iDatapathList[i].iTrackInfo)
{
OSCL_DELETE(iDatapathList[i].iTrackInfo);
iDatapathList[i].iTrackInfo = NULL;
}
switch (iDatapathList[i].iMediaType)
{
case PVP_MEDIATYPE_TEXT:
{
for (uint32 j = 0; j < sourcepresinfo.getNumTracks(); ++j)
{
// Go through each track, check codec type, and save the track info
PVMFTrackInfo* curtrack = sourcepresinfo.getTrackInfo(j);
switch (GetFormatIndex(curtrack->getTrackMimeType().get_str()))
{
case PVMF_3GPP_TIMEDTEXT:
{
if (oPopulatePlayableListOnly)
{
//add it to playable list
iPlayableList.addTrackInfo(*curtrack);
}
else
{
leavecode = 0;
OSCL_TRY(leavecode, iDatapathList[i].iTrackInfo = OSCL_NEW(PVMFTrackInfo, (*curtrack)));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoTrackSelection() Could not allocate memory for PVMFTrackInfo"));
return PVMFErrNoMemory);
// Break out of the loop
j = sourcepresinfo.getNumTracks();
}
}
break;
default:
break;
}
}
}
break;
case PVP_MEDIATYPE_VIDEO:
{
for (uint32 j = 0; j < sourcepresinfo.getNumTracks(); ++j)
{
// Go through each track, check codec type, and save the track info
PVMFTrackInfo* curtrack = sourcepresinfo.getTrackInfo(j);
PVMFFormatType srcformat = GetFormatIndex(curtrack->getTrackMimeType().get_str());
PVMFFormatType sinkformat = iDatapathList[i].iDataSink->GetDataSinkFormatType();
Oscl_Vector<PVUuid, OsclMemAllocator> foundUuids;
switch (srcformat)
{
case PVMF_M4V:
case PVMF_H263:
case PVMF_H264_RAW:
case PVMF_H264_MP4:
case PVMF_H264:
case PVMF_WMV:
case PVMF_RV:
{
trackId = curtrack->getTrackID();
if (IsDecNodeNeeded(srcformat, sinkformat) == true &&
iPlayerNodeRegistry.QueryRegistry(srcformat, sinkformat, foundUuids) != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoTrackSelection: Unsupported codec trackID=%d due to NodeRegistry", trackId));
break;
}
retval = DoVerifyTrackInfo(iDatapathList[i], curtrack, checkcodec);
if (retval != PVMFSuccess)
return retval;
if (oPopulatePlayableListOnly)
{
if (checkcodec == PVMFSuccess)
{
//add it to playable list
iPlayableList.addTrackInfo(*curtrack);
}
}
else
{
// Only select base track in case of temporal scalability
if (curtrack->DoesTrackHaveDependency() == false && checkcodec == PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoTrackSelection: selected video trackID=%d", trackId));
leavecode = 0;
OSCL_TRY(leavecode, iDatapathList[i].iTrackInfo = OSCL_NEW(PVMFTrackInfo, (*curtrack)));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoTrackSelection() Could not allocate memory for PVMFTrackInfo"));
return PVMFErrNoMemory);
// Break out of the loop
j = sourcepresinfo.getNumTracks();
}
}
}
break;
default:
break;
}
}
}
break;
case PVP_MEDIATYPE_AUDIO:
{
for (uint32 j = 0; j < sourcepresinfo.getNumTracks(); ++j)
{
// Go through each track, check codec type, and save the track info
PVMFTrackInfo* curtrack = sourcepresinfo.getTrackInfo(j);
PVMFFormatType srcformat = GetFormatIndex(curtrack->getTrackMimeType().get_str());
PVMFFormatType sinkformat = iDatapathList[i].iDataSink->GetDataSinkFormatType();
Oscl_Vector<PVUuid, OsclMemAllocator> foundUuids;
switch (srcformat)
{
case PVMF_AMR_IETF:
case PVMF_AMR_IETF_COMBINED:
case PVMF_AMR_IF2:
case PVMF_ADIF:
case PVMF_ADTS:
case PVMF_MPEG4_AUDIO:
case PVMF_LATM:
case PVMF_MP3:
case PVMF_G726:
case PVMF_WMA:
case PVMF_REAL_AUDIO:
case PVMF_PCM:
case PVMF_PCM8:
case PVMF_PCM16:
case PVMF_PCM16_BE:
case PVMF_PCM_ULAW:
case PVMF_PCM_ALAW:
case PVMF_AMRWB_IETF:
case PVMF_ASF_MPEG4_AUDIO:
case PVMF_AMRWB_IETF_PAYLOAD:
{
trackId = curtrack->getTrackID();
if (IsDecNodeNeeded(srcformat, sinkformat) == true && iPlayerNodeRegistry.QueryRegistry(srcformat, sinkformat, foundUuids) != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoTrackSelection: Unsupported codec trackID=%d due to NodeRegistry", trackId));
break;
}
retval = DoVerifyTrackInfo(iDatapathList[i], curtrack, checkcodec);
if (retval != PVMFSuccess)
return retval;
if (oPopulatePlayableListOnly)
{
if (checkcodec == PVMFSuccess)
{
//add it to playable list
iPlayableList.addTrackInfo(*curtrack);
}
}
else
{
if (checkcodec == PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoTrackSelection: selected audio trackID=%d", trackId));
leavecode = 0;
OSCL_TRY(leavecode, iDatapathList[i].iTrackInfo = OSCL_NEW(PVMFTrackInfo, (*curtrack)));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoTrackSelection() Could not allocate memory for PVMFTrackInfo"));
return PVMFErrNoMemory);
// Break out of the loop
j = sourcepresinfo.getNumTracks();
}
}
}
break;
default:
break;
}
}
}
break;
default:
// For unknown media type, do nothing
break;
}
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, NULL);
}
}
return retval;
}
PVMFStatus PVPlayerEngine::DoVerifyTrackInfo(PVPlayerEngineDatapath &aDatapath, 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;
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();
//Check if we have decoder node cap-config
if (aDatapath.iDecNodeCapConfigIF != NULL)
{
PVMFFormatType DecnodeFormatType = GetFormatIndex(aTrack->getTrackMimeType().get_str());
switch (DecnodeFormatType)
{
case PVMF_M4V:
case PVMF_H263:
case PVMF_H264:
case PVMF_H264_MP4:
case PVMF_H264_RAW:
case PVMF_LATM:
case PVMF_MPEG4_AUDIO:
case PVMF_ASF_MPEG4_AUDIO:
case PVMF_WMV:
{
PvmiKvp* iErrorKVP = NULL;
PvmiKvp iKVPSetFormat;
iKVPSetFormat.key = NULL;
OSCL_StackString<64> iKeyStringSetFormat;
if ((DecnodeFormatType == PVMF_M4V) ||
(DecnodeFormatType == PVMF_H263) ||
(DecnodeFormatType == PVMF_H264) ||
(DecnodeFormatType == PVMF_H264_MP4) ||
(DecnodeFormatType == PVMF_H264_RAW) ||
(DecnodeFormatType == PVMF_WMV)
)
{
iKeyStringSetFormat = _STRLIT_CHAR("x-pvmf/video/decoder/format-type;valtype=uint32");
}
else
{
iKeyStringSetFormat += _STRLIT_CHAR("x-pvmf/audio/decoder/format-type;valtype=uint32");
}
iKVPSetFormat.key = iKeyStringSetFormat.get_str();
iKVPSetFormat.value.uint32_value = DecnodeFormatType;
aDatapath.iDecNodeCapConfigIF->setParametersSync(NULL, &iKVPSetFormat, 1, iErrorKVP);
}
break;
default:
break;
}
//verify codec specific info
int32 leavecode = 0;
OSCL_TRY(leavecode, aCheckcodec = aDatapath.iDecNodeCapConfigIF->verifyParametersSync(NULL, &kvp, 1));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyTrackInfo() unsupported verifyParametersSync did a leave!"));
alloc.deallocate((OsclAny*)(kvp.key));
aCheckcodec = PVMFSuccess; // set it success in case track selection info is not yet available;
return PVMFSuccess;);
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;
}
int numKvp = 0;
PvmiKvp* kvpPtr;
// Query using get
OSCL_StackString<64> querykey;
switch (aDatapath.iMediaType)
{
case PVP_MEDIATYPE_VIDEO:
{
querykey = _STRLIT_CHAR("x-pvmf/video/render");
if (aDatapath.iDecNodeCapConfigIF->getParametersSync(NULL, querykey.get_str(), kvpPtr, numKvp, NULL) == PVMFSuccess)
{
//verify width/height
if (aDatapath.iSinkNodeCapConfigIF != NULL)
aCheckcodec = aDatapath.iSinkNodeCapConfigIF->verifyParametersSync(NULL, kvpPtr, numKvp);
status = aDatapath.iDecNodeCapConfigIF->releaseParameters(NULL, kvpPtr, numKvp);
if (status != PVMFSuccess || aCheckcodec != PVMFSuccess)
break;
}
}
break;
case PVP_MEDIATYPE_AUDIO:
{
querykey = _STRLIT_CHAR("x-pvmf/audio/render");
if (aDatapath.iDecNodeCapConfigIF->getParametersSync(NULL, querykey.get_str(), kvpPtr, numKvp, NULL) == PVMFSuccess)
{
//verify samplerate and channels
if (aDatapath.iSinkNodeCapConfigIF != NULL)
aCheckcodec = aDatapath.iSinkNodeCapConfigIF->verifyParametersSync(NULL, kvpPtr, numKvp);
status = aDatapath.iDecNodeCapConfigIF->releaseParameters(NULL, kvpPtr, numKvp);
if (status != PVMFSuccess || aCheckcodec != PVMFSuccess)
break;
}
}
break;
default:
break;
}
}
else
{
if (aDatapath.iSinkNodeCapConfigIF != NULL)
{
aCheckcodec = aDatapath.iSinkNodeCapConfigIF->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 (aDatapath.iSinkNodeCapConfigIF != NULL)
aCheckcodec = aDatapath.iSinkNodeCapConfigIF->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
switch (aDatapath.iMediaType)
{
case PVP_MEDIATYPE_VIDEO:
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 (aDatapath.iSinkNodeCapConfigIF != NULL)
aCheckcodec = aDatapath.iSinkNodeCapConfigIF->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;
}
}
break;
default:
break;
}
return status;
}
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"));
// For each engine datapath in the list, initiate the setup sequence
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_SinkNodeDecNodeVerifyParameter);
leavecode = 0;
OSCL_TRY(leavecode, cmdid = iDatapathList[i].iSinkNode->Init(iDatapathList[i].iSinkNodeSessionId, (OsclAny*) context));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeInit() Init on iSinkNode did a leave")););
if (cmdid != -1 && leavecode == 0)
{
++iNumPendingNodeCmd;
}
else
{
FreeEngineContext(context);
}
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeInit() Out"));
if (iNumPendingNodeCmd == 0)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeInit() No datapath could be prepared!"));
return PVMFFailure;
}
else
{
return PVMFSuccess;
}
}
PVMFStatus PVPlayerEngine::DoSinkNodeReset(PVCommandId aCmdId, OsclAny* aCmdContext)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
(0, "PVPlayerEngine::DoSinkNodeReset() Tick=%d", OsclTickCount::TickCount()));
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeReset() In"));
// For each engine datapath in the list, initiate the setup sequence
iNumPendingNodeCmd = 0;
PVMFCommandId cmdid = -1;
int32 leavecode = 0;
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iSinkNode != NULL)
{
// Call Reseet() on the sink node
PVPlayerEngineContext* context = AllocateEngineContext(&(iDatapathList[i]), iDatapathList[i].iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeDecNodeReset);
leavecode = 0;
OSCL_TRY(leavecode, cmdid = iDatapathList[i].iSinkNode->Reset(iDatapathList[i].iSinkNodeSessionId, (OsclAny*) context));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeReset() Reseet on iSinkNode did a leave")););
if (cmdid != -1 && leavecode == 0)
{
++iNumPendingNodeCmd;
}
else
{
FreeEngineContext(context);
}
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeReset() Out"));
if (iNumPendingNodeCmd == 0)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeReset() No datapath could be prepared!"));
return PVMFFailure;
}
else
{
return PVMFSuccess;
}
}
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. Asserting"));
OSCL_ASSERT(false);
return PVMFFailure;
}
// If source node is already in Prepared state then don't call Prepare()
if (iSourceNode->GetState() == EPVMFNodePrepared)
{
// For each engine datapath in the list, initiate the setup sequence
iNumPendingDatapathCmd = 0;
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackInfo != NULL)
{
PVMFStatus cmdstatus = DoSetupSinkNode(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::DoSetupSinkNode(PVPlayerEngineDatapath &aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
(0, "PVPlayerEngine::DoSetupSinkNode() for %s Tick=%d",
aDatapath.iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount()));
OSCL_ASSERT(aDatapath.iTrackInfo != NULL);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetupSinkNode() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));
int32 leavecode = 0;
// Check if datapath can be setup
if (aDatapath.iTrackInfo == NULL || aDatapath.iDataSink == NULL)
{
// No
OSCL_ASSERT(false);
return PVMFErrNotSupported;
}
// Determine the sink node based on PVPlayerDataSink
if (aDatapath.iDataSink->GetDataSinkType() == PVP_DATASINKTYPE_FILENAME)
{
// Create file output node for sink
leavecode = 0;
OSCL_TRY(leavecode, aDatapath.iSinkNode = PVFileOutputNodeFactory::CreateFileOutput());
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupSinkNode() Creation of file output node did a leave!"));
return PVMFErrNoMemory);
if (aDatapath.iSinkNode->ThreadLogon() != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupSinkNode() ThreadLogon() on file output sink node failed"));
return PVMFFailure;
}
PVMFNodeSessionInfo nodesessioninfo(this, this, (OsclAny*)(aDatapath.iSinkNode), this, (OsclAny*)(aDatapath.iSinkNode));
leavecode = 0;
OSCL_TRY(leavecode, aDatapath.iSinkNodeSessionId = aDatapath.iSinkNode->Connect(nodesessioninfo));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupSinkNode() Connect on file output sink node did a leave!"));
return PVMFFailure);
// Request the fileoutput node config interface
PVPlayerEngineContext* context = AllocateEngineContext(&aDatapath, aDatapath.iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeQueryFOConfigIF);
PVMFCommandId cmdid = -1;
leavecode = 0;
OSCL_TRY(leavecode, cmdid = aDatapath.iSinkNode->QueryInterface(aDatapath.iSinkNodeSessionId, PvmfFileOutputNodeConfigUuid, (PVInterface*&)aDatapath.iSinkNodeFOConfigIF, (OsclAny*)context));
OSCL_FIRST_CATCH_ANY(leavecode,
FreeEngineContext(context);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupSinkNode() QueryInterface on file output sink node did a leave!"));
return PVMFFailure);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetupSinkNode() Out"));
return PVMFSuccess;
}
else if (aDatapath.iDataSink->GetDataSinkType() == PVP_DATASINKTYPE_SINKNODE)
{
// Use the specified output node for sink node
aDatapath.iSinkNode = aDatapath.iDataSink->GetDataSinkNodeInterface();
if (aDatapath.iSinkNode == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupSinkNode() Passed in sink node is NULL"));
return PVMFFailure;
}
if (aDatapath.iSinkNode->ThreadLogon() != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupSinkNode() ThreadLogon() on passed-in sink node failed"));
return PVMFFailure;
}
PVMFNodeSessionInfo nodesessioninfo(this, this, (OsclAny*)aDatapath.iSinkNode, this, (OsclAny*)aDatapath.iSinkNode);
leavecode = 0;
OSCL_TRY(leavecode, aDatapath.iSinkNodeSessionId = aDatapath.iSinkNode->Connect(nodesessioninfo));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupSinkNode() Connect() on passed-in sink node did a leave!"));
return PVMFFailure);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetupSinkNode() Out"));
return DoSinkNodeQueryInterfaceOptional(aDatapath, aCmdId, aCmdContext);
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupSinkNode() Unsupported player data sink type"));
return PVMFErrNotSupported;
}
}
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()));
OSCL_ASSERT(aDatapath.iTrackInfo != NULL);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceOptional() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));
int32 leavecode = 0;
if (aDatapath.iSinkNode == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceOptional() Sink node not available. Asserting"));
OSCL_ASSERT(false);
return PVMFFailure;
}
// Request optional extension interface from the sink node
PVPlayerEngineContext* context = NULL;
PVMFCommandId cmdid = -1;
aDatapath.iNumPendingCmd = 0;
// Request the sync control interface for the sink node
context = AllocateEngineContext(&aDatapath, aDatapath.iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeQuerySyncCtrlIF);
cmdid = -1;
leavecode = 0;
OSCL_TRY(leavecode, cmdid = aDatapath.iSinkNode->QueryInterface(aDatapath.iSinkNodeSessionId, PvmfNodesSyncControlUuid, (PVInterface*&)aDatapath.iSinkNodeSyncCtrlIF, (OsclAny*)context));
if (leavecode)
{
FreeEngineContext(context);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceOptional() QueryInterface on sink node for sync control IF did a leave!"));
}
else
{
++aDatapath.iNumPendingCmd;
}
// Query for Metadata IF
context = AllocateEngineContext(&aDatapath, aDatapath.iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeQueryMetadataIF);
PVUuid metadatauuid = KPVMFMetadataExtensionUuid;
cmdid = -1;
leavecode = 0;
OSCL_TRY(leavecode, cmdid = aDatapath.iSinkNode->QueryInterface(aDatapath.iSinkNodeSessionId, metadatauuid, (PVInterface*&)aDatapath.iSinkNodeMetadataExtIF, (OsclAny*)context));
if (leavecode)
{
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;
}
// Query for Cap-Config IF
context = AllocateEngineContext(&aDatapath, aDatapath.iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeQueryCapConfigIF);
PVUuid capconfiguuid = PVMI_CAPABILITY_AND_CONFIG_PVUUID;
cmdid = -1;
leavecode = 0;
OSCL_TRY(leavecode, cmdid = aDatapath.iSinkNode->QueryInterface(aDatapath.iSinkNodeSessionId, capconfiguuid, (PVInterface*&)aDatapath.iSinkNodeCapConfigIF, (OsclAny*)context));
if (leavecode)
{
FreeEngineContext(context);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceOptional() QueryInterface on sink node for cap-config 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::DoSetupDecNode(PVPlayerEngineDatapath &aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
(0, "PVPlayerEngine::DoSetupDecNode() for %s Tick=%d",
aDatapath.iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount()));
OSCL_ASSERT(aDatapath.iTrackInfo != NULL);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetupDecNode() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));
int32 leavecode = 0;
// Create decoder node if necessary
aDatapath.iSrcFormat = GetFormatIndex(aDatapath.iTrackInfo->getTrackMimeType().get_str());
aDatapath.iSinkFormat = aDatapath.iDataSink->GetDataSinkFormatType();
// Determine if decoder node is needed. In future, this will be replaced by querying
// the capability of data sink to match with source format type
if (IsDecNodeNeeded(aDatapath.iSrcFormat, aDatapath.iSinkFormat) == true)
{
Oscl_Vector<PVUuid, OsclMemAllocator> foundUuids;
// Query the player node registry for the required decoder node
if (iPlayerNodeRegistry.QueryRegistry(aDatapath.iSrcFormat, aDatapath.iSinkFormat, foundUuids) == PVMFSuccess)
{
if (foundUuids.empty())
{
// No matching node found
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupDecNode() No matching decoder node found"));
return PVMFFailure;
}
leavecode = 0;
OSCL_TRY(leavecode, aDatapath.iDecNode = iPlayerNodeRegistry.CreateNode(foundUuids[0]));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupDecNode() Error in creating DecNode"));
return PVMFFailure;);
iNodeUuids.push_back(PVPlayerEngineUuidNodeMapping(foundUuids[0], aDatapath.iDecNode));
if (aDatapath.iDecNode == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupDecNode() Dec node creation failed"));
return PVMFErrNoMemory;
}
if (aDatapath.iDecNode->ThreadLogon() != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupDecNode() ThreadLogon() on dec node failed"));
return PVMFFailure;
}
PVMFNodeSessionInfo nodesessioninfo(this, this, (OsclAny*)aDatapath.iDecNode, this, (OsclAny*)aDatapath.iDecNode);
leavecode = 0;
OSCL_TRY(leavecode, aDatapath.iDecNodeSessionId = aDatapath.iDecNode->Connect(nodesessioninfo));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupDecNode() Connect on dec node did a leave!"));
return PVMFFailure);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetupDecNode() Out"));
return DoDecNodeQueryInterfaceOptional(aDatapath, aCmdId, aCmdContext);
}
else
{
// Registry query failed
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupDecNode() Registry query for dec node failed"));
return PVMFFailure;
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSetupDecNode() Decoder node not needed"));
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetupDecNode() Out"));
return PVMFErrNotSupported;
}
bool PVPlayerEngine::IsDecNodeNeeded(PVMFFormatType& aSrcFormat, PVMFFormatType& aSinkFormat)
{
OSCL_ASSERT(aSrcFormat != PVMF_FORMAT_UNKNOWN);
OSCL_ASSERT(aSinkFormat != PVMF_FORMAT_UNKNOWN);
if ((aSinkFormat == PVMF_YUV420) || (aSinkFormat == PVMF_RGB16))
{
// For uncompressed video, decoder node is always needed
return true;
}
else if ((aSinkFormat >= PVMF_FIRST_UNCOMPRESSED_AUDIO && aSinkFormat <= PVMF_LAST_UNCOMPRESSED_AUDIO) &&
(!(aSrcFormat >= PVMF_FIRST_UNCOMPRESSED_AUDIO && aSrcFormat <= PVMF_LAST_UNCOMPRESSED_AUDIO)))
{
// For uncompressed audio, decoder node is needed if the source type is compressed
aSinkFormat = PVMF_PCM16;
return true;
}
else
{
// Set the sink format to be the same as the source format as default
aSinkFormat = aSrcFormat;
return false;
}
}
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()));
OSCL_ASSERT(aDatapath.iTrackInfo != NULL);
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)
{
OSCL_ASSERT(false);
return PVMFFailure;
}
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;
OSCL_TRY(leavecode, cmdid = aDatapath.iDecNode->QueryInterface(aDatapath.iDecNodeSessionId, metadatauuid, (PVInterface*&)aDatapath.iDecNodeMetadataExtIF, (OsclAny*)context));
if (leavecode)
{
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;
}
// Query for Cap-Config IF
context = AllocateEngineContext(&aDatapath, aDatapath.iDecNode, NULL, aCmdId, aCmdContext, PVP_CMD_DecNodeQueryCapConfigIF);
PVUuid capconfiguuid = PVMI_CAPABILITY_AND_CONFIG_PVUUID;
cmdid = -1;
leavecode = 0;
OSCL_TRY(leavecode, cmdid = aDatapath.iDecNode->QueryInterface(aDatapath.iDecNodeSessionId, capconfiguuid, (PVInterface*&)aDatapath.iDecNodeCapConfigIF, (OsclAny*)context));
if (leavecode)
{
FreeEngineContext(context);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDecNodeQueryInterfaceOptional() QueryInterface on dec node for cap-config 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()));
OSCL_ASSERT(aDatapath.iTrackInfo != NULL);
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);
aDatapath.iTrackActive = true;
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"));
// get the current playback position, which needs to be passed to parsernode in QueryDataSourcePosition
// to check whether reposotioning done is forward or backward.
PVPPlaybackPosition curpos;
curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC;
GetPlaybackClockPosition(curpos);
// Initialize the playback position and clock variables
iActualMediaDataTS = 0;
iAdjustedMediaDataTS = 0;
iActualPlaybackPosition = 0;
iStartNPT = 0;
iStartMediaDataTS = 0;
// 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;
}
PVMFCommandId cmdid = -1;
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;
}
}
iCurrentBeginPosition.iPosValue.millisec_value = timems;
iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;
if (iSeekToSyncPoint && iSyncPointSeekWindow > 0)
{
// Need to query the data source on where playback would actually begin from
PVMFTimestamp startpos = 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", startpos, iSeekToSyncPoint));
iActualPlaybackPosition = curpos.iPosValue.millisec_value;
iSeekPointBeforeTargetNPT = 0;
iSeekPointAfterTargetNPT = 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)
{
switch (*formatType)
{
case PVMF_MPEG4FF:
mpeg4FormatType = true;
break;
default:
mpeg4FormatType = false;
break;
}
}
int32 leavecode = 0;
if (mpeg4FormatType)
{
OSCL_TRY(leavecode, cmdid = iSourceNodePBCtrlIF->QueryDataSourcePosition(iSourceNodeSessionId, startpos,
iSeekPointBeforeTargetNPT, iSeekPointAfterTargetNPT, (OsclAny*) context, iSeekToSyncPoint));
}
else
{
OSCL_TRY(leavecode, cmdid = iSourceNodePBCtrlIF->QueryDataSourcePosition(iSourceNodeSessionId, startpos, iActualPlaybackPosition,
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 qquery is not supported, assume the repositioning will
// go to the requested position
// Determine the SetDataSourcePosition parameter based on reposition settings
PVMFTimestamp requesttime = iCurrentBeginPosition.iPosValue.millisec_value;
iActualPlaybackPosition = requesttime;
bool seektosyncpt = true;
// Do the source positioning
return DoSourceNodeSetDataSourcePosition(aCmdId, aCmdContext, requesttime, seektosyncpt);
}
else
{
return PVMFFailure;
}
}
}
else
{
// Go straight to repositioning the data source
PVMFTimestamp startpos = iCurrentBeginPosition.iPosValue.millisec_value;
return DoSourceNodeSetDataSourcePosition(aCmdId, aCmdContext, startpos, iSeekToSyncPoint);
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeQueryDataSourcePosition() Out"));
return PVMFSuccess;
}
PVMFStatus PVPlayerEngine::DoSourceNodeSetDataSourcePosition(PVCommandId aCmdId, OsclAny* aCmdContext, PVMFTimestamp aTargetNPT, bool aSeekToSyncPoint)
{
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
iActualPlaybackPosition = 0;
iActualMediaDataTS = 0;
iAdjustedMediaDataTS = 0;
// Then continue to handle like success case
iStartNPT = 0;
iStartMediaDataTS = 0;
// Save the actual starting position for GetPlaybackRange() query
iCurrentBeginPosition.iPosValue.millisec_value = iActualPlaybackPosition;
iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;
// Repositioning so reset the EOS received flag for each active datapath
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackActive)
{
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", aTargetNPT, aSeekToSyncPoint));
int32 tempStreamID = 0;
// if reposition points exists in between the actualPlaybackPosition and
// the currentPlaybackClock position, then the reposition data exists with
// in the graph, so we need to start a new media segment
PVPPlaybackPosition curpos;
curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC;
GetPlaybackClockPosition(curpos);
tempStreamID = iStreamID;
iActualMediaDataTS = 0;
iAdjustedMediaDataTS = 0;
iActualPlaybackPosition = 0;
int32 leavecode = 0;
PVMFCommandId cmdid = -1;
OSCL_TRY(leavecode, cmdid = iSourceNodePBCtrlIF->SetDataSourcePosition(iSourceNodeSessionId, aTargetNPT, iActualPlaybackPosition, iActualMediaDataTS, aSeekToSyncPoint, tempStreamID, (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 time 0
iActualPlaybackPosition = 0;
iActualMediaDataTS = 0;
iAdjustedMediaDataTS = 0;
// Then continue to handle like success case
iStartNPT = 0;
iStartMediaDataTS = 0;
// Save the actual starting position for GetPlaybackRange() query
iCurrentBeginPosition.iPosValue.millisec_value = iActualPlaybackPosition;
iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;
// Repositioning so reset the EOS received flag for each active datapath
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackActive)
{
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
iActualPlaybackPosition = 0;
iActualMediaDataTS = 0;
iAdjustedMediaDataTS = 0;
// Then continue to handle like success case
iStartNPT = 0;
iStartMediaDataTS = 0;
// Save the actual starting position for GetPlaybackRange() query
iCurrentBeginPosition.iPosValue.millisec_value = iActualPlaybackPosition;
iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;
// Repositioning so reset the EOS flag for each active datapath
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackActive)
{
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() "));
iActualMediaDataTS = 0;
iAdjustedMediaDataTS = 0;
iActualPlaybackPosition = 0;
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
, iActualPlaybackPosition
, 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 time 0
iActualPlaybackPosition = 0;
iActualMediaDataTS = 0;
iAdjustedMediaDataTS = 0;
// Then continue to handle like success case
iStartNPT = 0;
iStartMediaDataTS = 0;
// Save the actual starting position for GetPlaybackRange() query
iCurrentBeginPosition.iPosValue.millisec_value = iActualPlaybackPosition;
iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;
// Repositioning so reset the EOS flag for each active datapath
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackActive)
{
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 PVMFFailure;
}
// Pause the playback clock
bool clockpausedhere = iPlaybackClock.Pause();
// Stop the playback position status timer
StopPlaybackStatusTimer();
// 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."));
iActualPlaybackPosition = 0;
iActualMediaDataTS = 0;
iAdjustedMediaDataTS = 0;
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
, iActualPlaybackPosition
, 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
iPlaybackClock.Start();
// To get regular play status events
StartPlaybackStatusTimer();
}
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. Asserting"));
OSCL_ASSERT(false);
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()));
OSCL_ASSERT(aDatapath.iTrackInfo != NULL);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathStart() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));
if (aDatapath.iTrackActive == false)
{
OSCL_ASSERT(false);
return PVMFErrNotSupported;
}
// Start the datapath
OSCL_ASSERT(aDatapath.iDatapath != NULL);
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, 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;
PVMFCommandId cmdid = -1;
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].iTrackActive == true &&
iDatapathList[i].iEndOfDataReceived == false &&
iDatapathList[i].iSinkNodeSyncCtrlIF)
{
leavecode = 0;
PVPlayerEngineContext* context = AllocateEngineContext(&(iDatapathList[i]), iDatapathList[i].iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeSkipMediaData);
OSCL_TRY(leavecode, cmdid = iDatapathList[i].iSinkNodeSyncCtrlIF->SkipMediaData(iDatapathList[i].iSinkNodeSessionId, iActualMediaDataTS, iAdjustedMediaDataTS, iStreamID, iRenderSkipped, false, (OsclAny*) context));
if (leavecode == 0)
{
++iNumPendingNodeCmd;
++iNumPendingSkipCompleteEvent;
++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 (GetPVPlayerState() != PVP_STATE_PREPARED)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoStart() Wrong engine state"));
return PVMFErrInvalidState;
}
if (iPlaybackClock.GetState() != OsclClock::RUNNING)
{
// Enable the end time check if specified
UpdateCurrentEndPosition(iCurrentEndPosition);
// Start 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->Request(PVPLAYERENGINE_TIMERID_ENDTIMECHECK, 0, checkcycle, this, true);
}
// Start the playback clock
iPlaybackClock.Start();
// Notify data sinks that clock has started
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackActive)
{
if (iDatapathList[i].iSinkNodeSyncCtrlIF)
{
iDatapathList[i].iSinkNodeSyncCtrlIF->ClockStarted();
}
}
}
}
// To get regular play status events
StartPlaybackStatusTimer();
SetEngineState(PVP_ENGINE_STATE_STARTED);
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
if (GetPVPlayerState() != PVP_STATE_STARTED)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPause() Wrong engine state"));
return PVMFErrInvalidState;
}
// Send position update to app
TimeoutOccurred(PVPLAYERENGINE_TIMERID_PLAY_STATUS, -1);
// Stop the playback position status timer
StopPlaybackStatusTimer();
// 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();
}
}
// 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].iTrackActive && iDatapathList[i].iSinkNodeSyncCtrlIF)
{
iDatapathList[i].iSinkNodeSyncCtrlIF->ClockStopped();
}
}
}
PVMFStatus retval = PVMFErrNotSupported;
// Issue pause to all active datapaths
iNumPendingDatapathCmd = 0;
for (i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackActive)
{
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], aCmd.GetCmdId(), aCmd.GetContext(), true);
}
else
{
// Pause all nodes in the datapath
retval = DoDatapathPause(iDatapathList[i], aCmd.GetCmdId(), aCmd.GetContext(), false);
}
if (retval == PVMFSuccess)
{
++iNumPendingDatapathCmd;
}
else
{
return retval;
}
}
}
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)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPause() Pausing datapath and source node failed"));
return retval;
}
// Reset the flag when doing a pause
iChangePlaybackPositionWhenResuming = false;
iChangePlaybackDirectionWhenResuming = false;
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()));
OSCL_ASSERT(aDatapath.iTrackInfo != NULL);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathPause() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));
if (aDatapath.iTrackActive == false)
{
// Only active datapaths should be paused
OSCL_ASSERT(false);
return PVMFErrNotSupported;
}
// Pause the datapath
OSCL_ASSERT(aDatapath.iDatapath != NULL);
PVPlayerEngineContext* context = AllocateEngineContext(&aDatapath, NULL, aDatapath.iDatapath, aCmdId, aCmdContext, -1);
PVMFStatus retval = aDatapath.iDatapath->Pause((OsclAny*)context, aSinkPaused);
if (retval != PVMFSuccess)
{
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. Asserting"));
OSCL_ASSERT(false);
return PVMFFailure;
}
// Pause the source node
PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, -1);
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));
// 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;
}
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)
{
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)
{
retval = DoSourceNodeStart(aCmd.GetCmdId(), aCmd.GetContext());
}
}
else
{
retval = DoSourceNodeStart(aCmd.GetCmdId(), aCmd.GetContext());
}
if (retval != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoResume() Resuming source node or changing position failed"));
return retval;
}
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)
{
// 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;
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_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;
}
// reset the stream id and repos related variables
iStreamID = 0;
iNumPVMFInfoStartOfDataPending = 0;
iNumPendingSkipCompleteEvent = 0;
if (iWatchDogTimer->IsBusy())
{
iWatchDogTimer->Cancel();
}
// Stop the playback position status timer
StopPlaybackStatusTimer();
// Stop the playback clock
iPlaybackClock.Stop();
uint32 starttime = 0;
iPlaybackClock.SetStartTime32(starttime, OSCLCLOCK_MSEC);
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;
// 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].iTrackActive == true)
{
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)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoStop() Stopping datapath and source node failed"));
return retval;
}
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)
{
OSCL_ASSERT(aDatapath.iTrackInfo != NULL);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathStop() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));
if (aDatapath.iTrackActive == false)
{
return PVMFErrNotSupported;
}
// Stop the datapath
OSCL_ASSERT(aDatapath.iDatapath != NULL);
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. Asserting"));
OSCL_ASSERT(false);
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)
{
OSCL_ASSERT(aDatapath.iTrackInfo != NULL);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathTeardown() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));
if (aDatapath.iTrackActive == false)
{
return PVMFErrNotSupported;
}
// Teardown the datapath
OSCL_ASSERT(aDatapath.iDatapath != NULL);
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)
{
OSCL_ASSERT(aDatapath.iTrackInfo != NULL);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathReset() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));
if (aDatapath.iTrackActive == false)
{
return PVMFErrNotSupported;
}
// Reset the datapath
OSCL_ASSERT(aDatapath.iDatapath != NULL);
PVPlayerEngineContext* context = AllocateEngineContext(&aDatapath, NULL, aDatapath.iDatapath, aCmdId, aCmdContext, PVP_CMD_DPReset);
PVMFStatus retval = aDatapath.iDatapath->Reset((OsclAny*)context);
if (retval != PVMFSuccess)
{
FreeEngineContext(context);
}
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"));
// reset the stream id and repos related variables
iStreamID = 0;
iNumPVMFInfoStartOfDataPending = 0;
iNumPendingSkipCompleteEvent = 0;
if (iWatchDogTimer->IsBusy())
{
iWatchDogTimer->Cancel();
}
int32 leavecode = 0;
PVMFStatus status = PVMFSuccess;
switch (GetPVPlayerState())
{
case PVP_STATE_IDLE: // already in final state
DoRemoveAllSinks();
if (iDataSource)
{
RemoveDataSourceSync(*iDataSource);
}
EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
break;
case PVP_STATE_INITIALIZED:
DoRemoveAllSinks();
if (iSourceNode)
{
PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmd.GetCmdId(), aCmd.GetContext(), -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);
return PVMFFailure);
SetEngineState(PVP_ENGINE_STATE_RESETTING);
}
else
{
SetEngineState(PVP_ENGINE_STATE_IDLE);
EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
}
break;
case PVP_STATE_PREPARED:
case PVP_STATE_STARTED:
case PVP_STATE_PAUSED:
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoReset() called in wrong engine state!"));
status = PVMFFailure;
break;
case PVP_STATE_ERROR:
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoReset() called during error state!"));
status = PVMFFailure;
break;
default:
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoReset() unknown engine state!"));
status = PVMFFailure;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoReset() Out"));
return status;
}
PVMFStatus PVPlayerEngine::RemoveDataSourceSync(PVPlayerDataSource &aSrc)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::RemoveDataSourceSync() In"));
if (GetPVPlayerState() != PVP_STATE_IDLE)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::RemoveDataSourceSync() Wrong engine state"));
// force cleanup
DoSourceNodeCleanup();
iDataSource = NULL;
return PVMFErrInvalidState;
}
// Clean up the trackinfo now because iSourceNode might have memfrags in them
for (uint32 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;
}
if (iDatapathList[i].iDatapath)
iDatapathList[i].iDatapath->SetSourceNode(NULL);
}
// Destroy the source node if present
if (iSourceNode)
{
// Remove reference to the parser node init interface if available
if (iSourceNodeInitIF)
{
iSourceNodeInitIF->removeRef();
iSourceNodeInitIF = NULL;
}
// Remove reference to the parser node track sel interface if available
if (iSourceNodeTrackSelIF)
{
iPlayableList.Reset();
iPreferenceList.Reset();
iSourceNodeTrackSelIF->removeRef();
iSourceNodeTrackSelIF = NULL;
iTrackSelectionHelper = NULL;
}
// Remove reference to the parser node track level info interface if available
if (iSourceNodeTrackLevelInfoIF)
{
iSourceNodeTrackLevelInfoIF->removeRef();
iSourceNodeTrackLevelInfoIF = NULL;
}
// Remove reference to the parser node position control interface if available
if (iSourceNodePBCtrlIF)
{
iSourceNodePBCtrlIF->removeRef();
iSourceNodePBCtrlIF = NULL;
}
// Remove reference to the parser node direction control interface if available
if (iSourceNodeDirCtrlIF)
{
iSourceNodeDirCtrlIF->removeRef();
iSourceNodeDirCtrlIF = NULL;
}
// Remove reference to the parser node metadata interface if available
if (iSourceNodeMetadataExtIF)
{
RemoveFromMetadataInterfaceList(iSourceNodeMetadataExtIF, iSourceNodeSessionId);
iSourceNodeMetadataExtIF->removeRef();
iSourceNodeMetadataExtIF = NULL;
}
// 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;
}
if (iSourceNodeCPMLicenseIF)
{
iSourceNodeCPMLicenseIF->removeRef();
iSourceNodeCPMLicenseIF = NULL;
}
iSourceNode->Disconnect(iSourceNodeSessionId);
iSourceNode->ThreadLogoff();
// 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;
int32 leavecode = 0;
OSCL_TRY(leavecode, release_status = iPlayerNodeRegistry.ReleaseNode(iter->iUuid, iSourceNode));
OSCL_FIRST_CATCH_ANY(leavecode,
// force cleanup
DoSourceNodeCleanup();
iDataSource = NULL;
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::RemoveDataSourceSync() Error in releasing SourceNode"));
return PVMFFailure;);
if (release_status == false)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::RemoveDataSourceSync() Factory returned false while releasing the sourcenode"));
// force cleanup
DoSourceNodeCleanup();
iDataSource = NULL;
return PVMFFailure;
}
iNodeUuids.erase(iter);
iSourceNode = NULL;
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::RemoveDataSourceSync() unknown node"));
// force cleanup
DoSourceNodeCleanup();
iDataSource = NULL;
return PVMFFailure;
}
}
// Remove Stored KVP Values
DeleteKVPValues();
// Remove all metadata IF from the list
iMetadataIFList.clear();
iDataSource = NULL;
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 PVMFFailure;
}
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"));
// Allow auto-pause only when playing
if (iState != PVP_ENGINE_STATE_STARTED)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceUnderflowAutoPause() Invalid state so cancel auto-pause request!"));
return PVMFErrCancelled;
}
// Pause the playback clock
iPlaybackClock.Pause();
// Stop the playback position status timer
StopPlaybackStatusTimer();
uint32 i;
// Notify data sinks that clock has paused
for (i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackActive && 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].iTrackActive == true)
{
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). Because auto-pause/resume cmds are just regular engine cmds and won't be interrupted by normal ones
//Underflow->Pause->Resume->DataReady. Then we start clock in here. Because clock is not started at Resume due to underflow.
//Resume starts playback clock. Souce node pauses it again. Engine stays in STARTED state rather than AUTO_PAUSED state.
//Underflow->Pause->DataReady->Resume. Then we CANNOT start clock in here. Because clock is paused by app.
//After Pause done, the engine is in PAUSED state.
if (iPlaybackClock.GetState() == OsclClock::PAUSED && iState == PVP_ENGINE_STATE_STARTED)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Clock Start"));
iPlaybackClock.Start();
// To get regular play status events
StartPlaybackStatusTimer();
// Notify all sink nodes that have sync control IF that clock has started.
// This is necessary because engine cannot assume all data sinks implement
// the clock state observer.
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackActive && iDatapathList[i].iSinkNodeSyncCtrlIF)
{
iDatapathList[i].iSinkNodeSyncCtrlIF->ClockStarted();
}
}
//instead of return PVMFSuccess because PVMFErrNotSupported will cause the DataReady event be sent to app
return PVMFErrNotSupported;
}
// Allow auto-resume only when auto-paused
if (iState != PVP_ENGINE_STATE_AUTO_PAUSED)
{
//if in these two states, the engine has NOT started yet. It is very likely the app is waiting for DataReady event to call engine Start()
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].iTrackActive == true)
{
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)
{
OSCL_ASSERT(aDatapath.iTrackInfo != NULL);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodePause() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));
if (aDatapath.iTrackActive == false)
{
return PVMFErrNotSupported;
}
// Pause the sink node
OSCL_ASSERT(aDatapath.iSinkNode != NULL);
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)
{
OSCL_ASSERT(aDatapath.iTrackInfo != NULL);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeResume() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));
if (aDatapath.iTrackActive == false)
{
return PVMFErrNotSupported;
}
// Start the sink node to resume
OSCL_ASSERT(aDatapath.iSinkNode != NULL);
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;
}
PVMFStatus PVPlayerEngine::DoCancelDueToError(void)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelDueToError() In: iCurrentContextList.size() %d",
iCurrentContextList.size()));
int32 leavecode = 0;
if (iCurrentContextList.empty() == false)
{
// Issue cancel commands
// Determine where the pending commands were issued to and then cancel them
iPendingCancelDueToErrorRequest = 0;
for (uint32 i = 0; i < iCurrentContextList.size(); ++i)
{
if (iCurrentContextList[i]->iNode)
{
if (iCurrentContextList[i]->iNode == iSourceNode)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelDueToError() Calling CancelAllCommands() on source node"));
leavecode = 0;
OSCL_TRY(leavecode, iSourceNode->CancelAllCommands(iSourceNodeSessionId, (OsclAny*)&iPendingCancelDueToErrorRequest));
if (leavecode == 0)
{
++iPendingCancelDueToErrorRequest;
}
}
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::DoCancelDueToError() Calling CancelAllCommands() on sink node"));
leavecode = 0;
OSCL_TRY(leavecode, iCurrentContextList[i]->iNode->CancelAllCommands(iCurrentContextList[i]->iEngineDatapath->iSinkNodeSessionId, (OsclAny*)&iPendingCancelDueToErrorRequest));
if (leavecode == 0)
{
++iPendingCancelDueToErrorRequest;
}
}
else if (iCurrentContextList[i]->iNode == iCurrentContextList[i]->iEngineDatapath->iDecNode)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelDueToError() Calling CancelAllCommands() on dec node"));
leavecode = 0;
OSCL_TRY(leavecode, iCurrentContextList[i]->iNode->CancelAllCommands(iCurrentContextList[i]->iEngineDatapath->iDecNodeSessionId, (OsclAny*)&iPendingCancelDueToErrorRequest));
if (leavecode == 0)
{
++iPendingCancelDueToErrorRequest;
}
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelDueToError() Unknown node type. Asserting"));
OSCL_ASSERT(false);
}
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelDueToError() 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::DoCancelDueToError() Calling CancelCommand() on datapath"));
leavecode = 0;
OSCL_TRY(leavecode, iCurrentContextList[i]->iDatapath->CancelCommand((OsclAny*)&iPendingCancelDueToErrorRequest));
if (leavecode == 0)
{
++iPendingCancelDueToErrorRequest;
}
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelDueToError() Unknown datapath. Asserting"));
OSCL_ASSERT(false);
}
}
else
{
// Either a node or datapath should be pending
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelDueToError() No pending node or datapath. Asserting"));
OSCL_ASSERT(false);
}
}
// Reset the pending node/datapath cmd counters
iNumPendingNodeCmd = 0;
iNumPendingDatapathCmd = 0;
if (iPendingCancelDueToErrorRequest > 0)
{
// Deactivate the engine AO if active
// to avoid processing the next engine command in queue
if (IsBusy())
{
Cancel();
}
// Put in an internal engine command in the current command queue
// to prevent the next command in queue from being processed
PVPlayerEngineCommand cmd(PVP_ENGINE_COMMAND_CANCEL_DUE_TO_ERROR, -1, NULL, NULL, false);
leavecode = 0;
OSCL_ASSERT(iCurrentCmd.empty() == true);
OSCL_TRY(leavecode, iCurrentCmd.push_front(cmd));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelDueToError() Cancel-due-to-error command could not be pushed onto iCurrentCmd vector. Asserting"));
OSCL_ASSERT(false);
return PVMFErrNoMemory;);
// Put the same command in the cancel command queue
leavecode = 0;
OSCL_ASSERT(iCmdToCancel.empty() == true);
OSCL_TRY(leavecode, iCmdToCancel.push_front(cmd));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelDueToError() Cancel-due-to-error command could not be pushed onto iCmdToCancel vector. Asserting"));
OSCL_ASSERT(false);
return PVMFErrNoMemory;);
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelDueToError() % pending cancels.", iPendingCancelDueToErrorRequest));
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelDueToError() Out"));
return PVMFSuccess;
}
PVMFStatus PVPlayerEngine::DoStopDueToError(PVPlayerEngineCommand& aCmd)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoStopDueToError() In"));
SetEngineState(PVP_ENGINE_STATE_HANDLINGERROR);
iErrorOccurredDuringErrorHandling = false;
// Stop the playback position status timer
StopPlaybackStatusTimer();
// Stop the playback clock
iPlaybackClock.Stop();
uint32 starttime = 0;
iPlaybackClock.SetStartTime32(starttime, OSCLCLOCK_MSEC);
// 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;
// Stop the end time check
if (iEndTimeCheckEnabled)
{
iEndTimeCheckEnabled = false;
iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_ENDTIMECHECK);
}
PVMFStatus retval = PVMFFailure;
// Start the stopping sequence
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackActive == true)
{
PVMFStatus retcode = DoDatapathStopDueToError(iDatapathList[i], aCmd.GetCmdId(), aCmd.GetContext());
if (retcode == PVMFSuccess)
{
++iNumPendingDatapathCmd;
}
}
}
if (iNumPendingDatapathCmd == 0)
{
// No datapath to stop so stop the source node
retval = DoSourceNodeStopDueToError(aCmd.GetCmdId(), aCmd.GetContext());
if (retval != PVMFSuccess)
{
// If stop could not be initiated, complete it and issue a reset command
EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFFailure);
SetEngineState(PVP_ENGINE_STATE_ERROR);
AddCommandToQueue(PVP_ENGINE_COMMAND_RESET_DUE_TO_ERROR, NULL, NULL, NULL, false);
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoStopDueToError() Out"));
return PVMFSuccess;
}
PVMFStatus PVPlayerEngine::DoDatapathStopDueToError(PVPlayerEngineDatapath &aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext)
{
OSCL_ASSERT(aDatapath.iTrackInfo != NULL);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathStopDueToError() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));
if (aDatapath.iTrackActive == false)
{
return PVMFErrNotSupported;
}
// Stop the datapath
OSCL_ASSERT(aDatapath.iDatapath != NULL);
PVPlayerEngineContext* context = AllocateEngineContext(&aDatapath, NULL, aDatapath.iDatapath, aCmdId, aCmdContext, PVP_CMD_DPStop);
PVMFStatus retval = aDatapath.iDatapath->Stop((OsclAny*)context, true);
if (retval != PVMFSuccess)
{
FreeEngineContext(context);
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathStopDueToError() Out"));
return retval;
}
PVMFStatus PVPlayerEngine::DoSourceNodeStopDueToError(PVCommandId aCmdId, OsclAny* aCmdContext)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeStopDueToError() In"));
if (iSourceNode == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeStopDueToError() Source node not available. Asserting"));
OSCL_ASSERT(false);
return PVMFFailure;
}
// Stop the source node
PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeStop);
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::DoSourceNodeStopDueToError() Stop on iSourceNode did a leave!"));
return PVMFFailure);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeStopDueToError() Out"));
return PVMFSuccess;
}
PVMFStatus PVPlayerEngine::DoDatapathTeardownDueToError(PVPlayerEngineDatapath &aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext)
{
OSCL_ASSERT(aDatapath.iTrackInfo != NULL);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathTeardownDueToError() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));
if (aDatapath.iTrackActive == false)
{
return PVMFErrNotSupported;
}
// Teardown the datapath
OSCL_ASSERT(aDatapath.iDatapath != NULL);
PVPlayerEngineContext* context = AllocateEngineContext(&aDatapath, NULL, aDatapath.iDatapath, aCmdId, aCmdContext, PVP_CMD_DPTeardown);
PVMFStatus retval = aDatapath.iDatapath->Teardown((OsclAny*)context, true);
if (retval != PVMFSuccess)
{
FreeEngineContext(context);
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathTeardownDueToError() Out"));
return retval;
}
PVMFStatus PVPlayerEngine::DoDatapathResetDueToError(PVPlayerEngineDatapath &aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext)
{
OSCL_ASSERT(aDatapath.iTrackInfo != NULL);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathResetDueToError() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr()));
if (aDatapath.iTrackActive == false)
{
return PVMFErrNotSupported;
}
// Reset the datapath
OSCL_ASSERT(aDatapath.iDatapath != NULL);
PVPlayerEngineContext* context = AllocateEngineContext(&aDatapath, NULL, aDatapath.iDatapath, aCmdId, aCmdContext, PVP_CMD_DPReset);
PVMFStatus retval = aDatapath.iDatapath->Reset((OsclAny*)context, true);
if (retval != PVMFSuccess)
{
FreeEngineContext(context);
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathResetDueToError() Out"));
return retval;
}
PVMFStatus PVPlayerEngine::DoResetDueToError(PVPlayerEngineCommand& aCmd)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoResetDueToError() In"));
SetEngineState(PVP_ENGINE_STATE_HANDLINGERROR);
iErrorOccurredDuringErrorHandling = false;
int32 leavecode = 0;
PVMFCommandId cmdid = -1;
if (iSourceNode)
{
// Remove reference to the parser node init interface if available
if (iSourceNodeInitIF)
{
iSourceNodeInitIF->removeRef();
iSourceNodeInitIF = NULL;
}
// Remove reference to the parser node track sel interface if available
if (iSourceNodeTrackSelIF)
{
iPlayableList.Reset();
iPreferenceList.Reset();
iSourceNodeTrackSelIF->removeRef();
iSourceNodeTrackSelIF = NULL;
iTrackSelectionHelper = NULL;
}
// Remove reference to the parser node track level info interface if available
if (iSourceNodeTrackLevelInfoIF)
{
iSourceNodeTrackLevelInfoIF->removeRef();
iSourceNodeTrackLevelInfoIF = NULL;
}
// Remove reference to the parser node position control interface if available
if (iSourceNodePBCtrlIF)
{
iSourceNodePBCtrlIF->removeRef();
iSourceNodePBCtrlIF = NULL;
}
// Remove reference to the parser node direction control interface if available
if (iSourceNodeDirCtrlIF)
{
iSourceNodeDirCtrlIF->removeRef();
iSourceNodeDirCtrlIF = NULL;
}
// Remove reference to the parser node metadata interface if available
if (iSourceNodeMetadataExtIF)
{
RemoveFromMetadataInterfaceList(iSourceNodeMetadataExtIF, iSourceNodeSessionId);
iSourceNodeMetadataExtIF->removeRef();
iSourceNodeMetadataExtIF = NULL;
}
// 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;
}
if (iSourceNodeCPMLicenseIF)
{
iSourceNodeCPMLicenseIF->removeRef();
iSourceNodeCPMLicenseIF = NULL;
}
// Reset the source node
PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmd.GetCmdId(), aCmd.GetContext(), PVP_CMD_SourceNodeReset);
cmdid = -1;
leavecode = 0;
OSCL_TRY(leavecode, cmdid = iSourceNode->Reset(iSourceNodeSessionId, (OsclAny*)context));
OSCL_FIRST_CATCH_ANY(leavecode,
FreeEngineContext(context);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoResetDueToError() Reset on iSourceNode did a leave!"));
);
if (leavecode != 0)
{
FreeEngineContext(context);
// If reset could not be initiated, complete it and issue a cleanup command
EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFFailure);
SetEngineState(PVP_ENGINE_STATE_ERROR);
AddCommandToQueue(PVP_ENGINE_COMMAND_CLEANUP_DUE_TO_ERROR, NULL, NULL, NULL, false);
}
}
else
{
// Ready to be in idle state so complete the reset command
SetEngineState(PVP_ENGINE_STATE_IDLE);
EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoResetDueToError() Out"));
return PVMFSuccess;
}
PVMFStatus PVPlayerEngine::DoCleanupDueToError(PVPlayerEngineCommand& aCmd)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCleanupDueToError() In"));
SetEngineState(PVP_ENGINE_STATE_HANDLINGERROR);
iErrorOccurredDuringErrorHandling = false;
// Wipe everything out
iPollingCheckTimer->Clear();
// Clean up the datapaths
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
DoEngineDatapathCleanup(iDatapathList[i]);
}
iDatapathList.clear();
// Clean up the source node
DoSourceNodeCleanup();
// Return all the engine context
while (!iCurrentContextList.empty())
{
OSCL_ASSERT(iCurrentContextList[0] != aCmd.GetContext());
FreeEngineContext(iCurrentContextList[0]);
}
iMetadataIFList.clear();
SetEngineState(PVP_ENGINE_STATE_IDLE);
EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCleanupDueToError() 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)
{
aDatapath.iSinkNode->Disconnect(aDatapath.iSinkNodeSessionId);
aDatapath.iSinkNode->ThreadLogoff();
// 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 = NULL;
}
if (aDatapath.iDataSink)
{
if (aDatapath.iDataSink->GetDataSinkType() == PVP_DATASINKTYPE_FILENAME)
{
// Remove file output config IF if available
if (aDatapath.iSinkNodeFOConfigIF)
{
aDatapath.iSinkNodeFOConfigIF->removeRef();
aDatapath.iSinkNodeFOConfigIF = NULL;
}
// Delete the sink node since engine created it.
PVFileOutputNodeFactory::DeleteFileOutput(aDatapath.iSinkNode);
}
}
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;
}
aDatapath.iDecNode->Disconnect(aDatapath.iDecNodeSessionId);
aDatapath.iDecNode->ThreadLogoff();
// 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;
int32 leavecode = 0;
OSCL_TRY(leavecode, release_status = iPlayerNodeRegistry.ReleaseNode(iter->iUuid, aDatapath.iDecNode));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoEngineDatapathTeardown() Error in releasing DecNode"));
return;);
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;
}
}
aDatapath.iTrackActive = false;
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;
}
aDatapath.iTrackActive = false;
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 (iSourceNodeCPMLicenseIF)
{
iSourceNodeCPMLicenseIF->removeRef();
iSourceNodeCPMLicenseIF = NULL;
}
iSourceNode->Disconnect(iSourceNodeSessionId);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - DisConnect Done"));
iSourceNode->ThreadLogoff();
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;
int32 leavecode = 0;
OSCL_TRY(leavecode, release_status = iPlayerNodeRegistry.ReleaseNode(iter->iUuid, iSourceNode));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeCleanup() Error in releasing SourceNode"));
return;);
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;
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 (engcomp3ind == 12)
{
// "x-pvmf/player/productinfo"
if (compcount == 3)
{
// Return list of product info. Ignore the
// attribute since capability is only allowed
// Allocate memory for the KVP list
aParameters = (PvmiKvp*)oscl_malloc(PVPLAYERCONFIG_PRODINFO_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_PRODINFO_NUMKEYS*sizeof(PvmiKvp));
// Allocate memory for the key strings in each KVP
PvmiKeyType memblock = (PvmiKeyType)oscl_malloc(PVPLAYERCONFIG_PRODINFO_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_PRODINFO_NUMKEYS*PVPLAYERCONFIG_KEYSTRING_SIZE*sizeof(char));
// Assign the key string buffer to each KVP
int32 j;
for (j = 0; j < PVPLAYERCONFIG_PRODINFO_NUMKEYS; ++j)
{
aParameters[j].key = memblock + (j * PVPLAYERCONFIG_KEYSTRING_SIZE);
}
// Copy the requested info
for (j = 0; j < PVPLAYERCONFIG_PRODINFO_NUMKEYS; ++j)
{
oscl_strncat(aParameters[j].key, _STRLIT_CHAR("x-pvmf/player/productinfo/"), 26);
oscl_strncat(aParameters[j].key, PVPlayerConfigProdInfoKeys[j].iString, oscl_strlen(PVPlayerConfigProdInfoKeys[j].iString));
oscl_strncat(aParameters[j].key, _STRLIT_CHAR(";type=value;valtype=char*"), 25);
aParameters[j].key[PVPLAYERCONFIG_KEYSTRING_SIZE-1] = 0;
}
aNumParamElements = PVPLAYERCONFIG_PRODINFO_NUMKEYS;
}
else if (compcount == 4)
{
// Retrieve the fourth component from the key string
pv_mime_string_extract_type(3, aIdentifier, compstr);
for (int32 engcomp4ind = 0; engcomp4ind < PVPLAYERCONFIG_PRODINFO_NUMKEYS; ++engcomp4ind)
{
if (pv_mime_strcmp(compstr, (char*)(PVPlayerConfigProdInfoKeys[engcomp4ind].iString)) >= 0)
{
// Determine what is requested
PvmiKvpAttr reqattr = GetAttrTypeFromKeyString(aIdentifier);
if (reqattr == PVMI_KVPATTR_UNKNOWN)
{
// Default is current setting
reqattr = PVMI_KVPATTR_CUR;
}
// Return the requested info
PVMFStatus retval = DoGetPlayerProductInfoParameter(aParameters, aNumParamElements, engcomp4ind, reqattr);
if (retval != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigGetParametersSync() Retrieving product info failed"));
return retval;
}
// Break out of the for(engcomp4ind) loop
break;
}
}
}
else
{
// Right now engine doesn't support more than 4 components
// so error out
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigGetParametersSync() Unsupported key"));
return PVMFErrArgument;
}
}
else
{
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
{
// Determine which node's cap-config IF needs to be used
Oscl_Vector<PvmiCapabilityAndConfig*, OsclMemAllocator> nodecapconfigif;
PVMFStatus retval = DoQueryNodeCapConfig(compstr, nodecapconfigif);
if (retval == PVMFSuccess && !(nodecapconfigif.empty()))
{
uint32 nodeind = 0;
// Go through each returned node's cap-config until successful
while (nodeind < nodecapconfigif.size() && aNumParamElements == 0)
{
retval = nodecapconfigif[nodeind]->getParametersSync(NULL, aIdentifier, aParameters, aNumParamElements, aContext);
++nodeind;
}
}
}
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
{
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);
}
}
}
// 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
{
// Determine which node's cap-config IF needs to be used
Oscl_Vector<PvmiCapabilityAndConfig*, OsclMemAllocator> nodecapconfigif;
PVMFStatus retval = DoQueryNodeCapConfig(compstr, nodecapconfigif);
if (retval == PVMFSuccess && !(nodecapconfigif.empty()))
{
uint32 nodeind = 0;
retval = PVMFErrArgument;
// Go through each returned node's cap-config until successful
while (nodeind < nodecapconfigif.size() && retval != PVMFSuccess)
{
retval = nodecapconfigif[nodeind]->releaseParameters(NULL, aParameters, aNumElements);
++nodeind;
}
if (retval != PVMFSuccess)
{
return retval;
}
}
else
{
// Unknown key string
return PVMFErrArgument;
}
}
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 if (compcount == 4)
{
// Only product info keys have four components
// Verify and set the passed-in product info setting
PVMFStatus retval = DoVerifyAndSetPlayerProductInfoParameter(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 4 components right now
*retkvp = &paramkvp[paramind];
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigSetParameters() Unsupported key"));
return PVMFErrArgument;
}
}
else
{
// Determine which node's cap-config IF needs to be used
Oscl_Vector<PvmiCapabilityAndConfig*, OsclMemAllocator> nodecapconfigif;
PVMFStatus retval = DoQueryNodeCapConfig(compstr, nodecapconfigif);
*retkvp = &paramkvp[paramind];
if (retval == PVMFSuccess && !(nodecapconfigif.empty()))
{
uint32 nodeind = 0;
bool anysuccess = false;
// Go through each returned node's cap-config until successful
while (nodeind < nodecapconfigif.size())
{
*retkvp = NULL;
nodecapconfigif[nodeind]->setParametersSync(NULL, &paramkvp[paramind], 1, *retkvp);
++nodeind;
if (*retkvp == NULL && anysuccess == false)
{
anysuccess = true;
}
}
if (anysuccess == false)
{ // setParametersSync was not accepted by the node(s)
*retkvp = &paramkvp[paramind];
return PVMFErrArgument;
}
}
else
{
// Unknown key string
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigSetParameters() Unsupported key"));
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 if (compcount == 4)
{
// Only product info keys have four components
// Verify the passed-in product info setting
PVMFStatus retval = DoVerifyAndSetPlayerProductInfoParameter(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 4 components right now
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigVerifyParameters() Unsupported key"));
return PVMFErrArgument;
}
}
else
{
// Determine which node's cap-config IF needs to be used
Oscl_Vector<PvmiCapabilityAndConfig*, OsclMemAllocator> nodecapconfigif;
PVMFStatus retval = DoQueryNodeCapConfig(compstr, nodecapconfigif);
if (retval == PVMFSuccess && !(nodecapconfigif.empty()))
{
uint32 nodeind = 0;
retval = PVMFErrArgument;
// Go through each returned node's cap-config until successful
while (nodeind < nodecapconfigif.size() && retval != PVMFSuccess)
{
retval = nodecapconfigif[nodeind]->verifyParametersSync(NULL, &aParameters[paramind], 1);
++nodeind;
}
if (retval != PVMFSuccess)
{
return retval;
}
}
else
{
// Unknown key string
return PVMFErrArgument;
}
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCapConfigVerifyParameters() Out"));
return PVMFSuccess;
}
PVMFStatus PVPlayerEngine::DoQueryNodeCapConfig(char* aKeySubString, Oscl_Vector<PvmiCapabilityAndConfig*, OsclMemAllocator>& aNodeCapConfigIF)
{
aNodeCapConfigIF.clear();
if (aKeySubString == NULL)
{
return PVMFErrArgument;
}
int32 leavecode = 0;
if (pv_mime_strcmp(aKeySubString, _STRLIT_CHAR("video/decoder")) >= 0)
{
// Video decoder setting
// Find the video datapath in the list
int32 vdpind = -1;
if (FindDatapathByMediaType(PVP_MEDIATYPE_VIDEO, vdpind) == true)
{
PVPlayerEngineDatapath* pvpedp = &(iDatapathList[vdpind]);
if (pvpedp->iTrackActive == true)
{
if (pvpedp->iDecNodeCapConfigIF)
{
leavecode = 0;
OSCL_TRY(leavecode, aNodeCapConfigIF.push_back(pvpedp->iDecNodeCapConfigIF));
OSCL_FIRST_CATCH_ANY(leavecode, return PVMFErrNoMemory);
}
if (pvpedp->iSinkNodeCapConfigIF)
{
leavecode = 0;
OSCL_TRY(leavecode, aNodeCapConfigIF.push_back(pvpedp->iSinkNodeCapConfigIF));
OSCL_FIRST_CATCH_ANY(leavecode, return PVMFErrNoMemory);
}
}
}
}
else if (pv_mime_strcmp(aKeySubString, _STRLIT_CHAR("audio/decoder")) >= 0)
{
// Audio decoder setting
// Find the audio datapath in the list
int32 adpind = -1;
if (FindDatapathByMediaType(PVP_MEDIATYPE_AUDIO, adpind) == true)
{
PVPlayerEngineDatapath* pvpedp = &(iDatapathList[adpind]);
if (pvpedp->iTrackActive == true)
{
if (pvpedp->iDecNodeCapConfigIF)
{
leavecode = 0;
OSCL_TRY(leavecode, aNodeCapConfigIF.push_back(pvpedp->iDecNodeCapConfigIF));
OSCL_FIRST_CATCH_ANY(leavecode, return PVMFErrNoMemory);
}
if (pvpedp->iSinkNodeCapConfigIF)
{
leavecode = 0;
OSCL_TRY(leavecode, aNodeCapConfigIF.push_back(pvpedp->iSinkNodeCapConfigIF));
OSCL_FIRST_CATCH_ANY(leavecode, return PVMFErrNoMemory);
}
}
}
}
else if (pv_mime_strcmp(aKeySubString, _STRLIT_CHAR("video/render")) >= 0)
{
// Video render device setting
// Find the video datapath in the list
int32 vdpind = -1;
if (FindDatapathByMediaType(PVP_MEDIATYPE_VIDEO, vdpind) == true)
{
PVPlayerEngineDatapath* pvpedp = &(iDatapathList[vdpind]);
if (pvpedp->iTrackActive == true)
{
if (pvpedp->iSinkNodeCapConfigIF)
{
leavecode = 0;
OSCL_TRY(leavecode, aNodeCapConfigIF.push_back(pvpedp->iSinkNodeCapConfigIF));
OSCL_FIRST_CATCH_ANY(leavecode, return PVMFErrNoMemory);
}
}
}
}
else if (pv_mime_strcmp(aKeySubString, _STRLIT_CHAR("audio/render")) >= 0)
{
// Audio render device setting
// Find the audio datapath in the list
int32 adpind = -1;
if (FindDatapathByMediaType(PVP_MEDIATYPE_AUDIO, adpind) == true)
{
PVPlayerEngineDatapath* pvpedp = &(iDatapathList[adpind]);
if (pvpedp->iTrackActive == true)
{
if (pvpedp->iSinkNodeCapConfigIF)
{
leavecode = 0;
OSCL_TRY(leavecode, aNodeCapConfigIF.push_back(pvpedp->iSinkNodeCapConfigIF));
OSCL_FIRST_CATCH_ANY(leavecode, return PVMFErrNoMemory);
}
}
}
}
else if (pv_mime_strcmp(aKeySubString, _STRLIT_CHAR("net")) >= 0 ||
pv_mime_strcmp(aKeySubString, _STRLIT_CHAR("parser")) >= 0)
{
// Source node setting
if (iSourceNodeCapConfigIF)
{
leavecode = 0;
OSCL_TRY(leavecode, aNodeCapConfigIF.push_back(iSourceNodeCapConfigIF));
OSCL_FIRST_CATCH_ANY(leavecode, return PVMFErrNoMemory);
}
}
else
{
// No matching node
return PVMFFailure;
}
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 0: // "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 1: // "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 2: // "endtimecheck_interval"
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
aParameters[0].value.uint32_value = iEndTimeCheckInterval;
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
aParameters[0].value.uint32_value = PVPLAYERENGINE_CONFIG_ENDTIMECHECKINTERVAL_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_ENDTIMECHECKINTERVAL_MIN;
rui32->max = PVPLAYERENGINE_CONFIG_ENDTIMECHECKINTERVAL_MAX;
aParameters[0].value.key_specific_value = (void*)rui32;
}
break;
case 3: // "seektosyncpoint"
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
aParameters[0].value.bool_value = iSeekToSyncPoint;
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
aParameters[0].value.bool_value = PVPLAYERENGINE_CONFIG_SEEKTOSYNCPOINT_DEF;
}
else
{
// Return capability
// Bool so no capability
}
break;
case 4: // "skiptorequestedpos"
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
aParameters[0].value.bool_value = iSkipToRequestedPosition;
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
aParameters[0].value.bool_value = PVPLAYERENGINE_CONFIG_SKIPTOREQUESTEDPOS_DEF;
}
else
{
// Return capability
// Bool so no capability
}
break;
case 5: // "renderskipped"
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
aParameters[0].value.bool_value = iRenderSkipped;
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
aParameters[0].value.bool_value = PVPLAYERENGINE_CONFIG_RENDERSKIPPED_DEF;
}
else
{
// Return capability
// Bool so no capability
}
break;
case 6: // "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 7: // "syncmargin_video"
case 8: // "syncmargin_audio"
case 9: // "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 == 7)
{
// Video
ri32->min = iSyncMarginVideo.min;
ri32->max = iSyncMarginVideo.max;
}
else if (aIndex == 8)
{
// 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 10: // "nodecmd_timeout"
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
aParameters[0].value.uint32_value = iNodeCmdTimeout;
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
aParameters[0].value.uint32_value = PVPLAYERENGINE_CONFIG_NODECMDTIMEOUT_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_NODECMDTIMEOUT_MIN;
rui32->max = PVPLAYERENGINE_CONFIG_NODECMDTIMEOUT_MAX;
aParameters[0].value.key_specific_value = (void*)rui32;
}
break;
case 11: // "nodedataqueuing_timeout"
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
aParameters[0].value.uint32_value = iNodeDataQueuingTimeout;
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
aParameters[0].value.uint32_value = PVPLAYERENGINE_CONFIG_NODEDATAQUEUINGTIMEOUT_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"));
return PVMFErrNoMemory;
}
rui32->min = PVPLAYERENGINE_CONFIG_NODEDATAQUEUINGTIMEOUT_MIN;
rui32->max = PVPLAYERENGINE_CONFIG_NODEDATAQUEUINGTIMEOUT_MAX;
aParameters[0].value.key_specific_value = (void*)rui32;
}
break;
case 13: // "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;
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::DoGetPlayerProductInfoParameter(PvmiKvp*& aParameters, int& aNumParamElements, int32 aIndex, PvmiKvpAttr reqattr)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetPlayerProductInfoParameter() 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::DoGetPlayerProductInfoParameter() 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::DoGetPlayerProductInfoParameter() Memory allocation for key string"));
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/productinfo/"), 26);
oscl_strncat(aParameters[0].key, PVPlayerConfigProdInfoKeys[aIndex].iString, oscl_strlen(PVPlayerConfigProdInfoKeys[aIndex].iString));
oscl_strncat(aParameters[0].key, _STRLIT_CHAR(";type=value;valtype=char*"), 25);
aParameters[0].key[PVPLAYERCONFIG_KEYSTRING_SIZE-1] = 0;
// Copy the requested info
switch (aIndex)
{
case 0: // "productname"
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
// Allocate memory for the string
char* curstr = (char*)oscl_malloc(iProdInfoProdName.get_size() + 1);
if (curstr == NULL)
{
oscl_free(aParameters[0].key);
oscl_free(aParameters);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerProductInfoParameter() Memory allocation for char* string failed"));
return PVMFErrNoMemory;
}
oscl_strset(curstr, 0, iProdInfoProdName.get_size() + 1);
// Copy and set
oscl_strncpy(curstr, iProdInfoProdName.get_cstr(), iProdInfoProdName.get_size());
aParameters[0].value.pChar_value = curstr;
aParameters[0].length = iProdInfoProdName.get_size();
aParameters[0].capacity = iProdInfoProdName.get_size() + 1;
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
// Allocate memory for the string
int32 defstrlen = oscl_strlen(PVPLAYERENGINE_PRODINFO_PRODNAME_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::DoGetPlayerProductInfoParameter() Memory allocation for char* string failed"));
return PVMFErrNoMemory;
}
// Copy and set
oscl_strncpy(defstr, _STRLIT_CHAR(PVPLAYERENGINE_PRODINFO_PRODNAME_STRING), defstrlen);
defstr[defstrlen] = 0;
aParameters[0].value.pChar_value = defstr;
aParameters[0].capacity = defstrlen + 1;
aParameters[0].length = defstrlen;
}
else
{
// Return capability
// Empty string
aParameters[0].value.pChar_value = NULL;
aParameters[0].capacity = 0;
aParameters[0].length = 0;
}
break;
case 1: // "partnumber"
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
// Allocate memory for the string
char* curstr = (char*)oscl_malloc(iProdInfoPartNum.get_size() + 1);
if (curstr == NULL)
{
oscl_free(aParameters[0].key);
oscl_free(aParameters);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerProductInfoParameter() Memory allocation for char* string failed"));
return PVMFErrNoMemory;
}
oscl_strset(curstr, 0, iProdInfoPartNum.get_size() + 1);
// Copy and set
oscl_strncpy(curstr, iProdInfoPartNum.get_cstr(), iProdInfoPartNum.get_size());
aParameters[0].value.pChar_value = curstr;
aParameters[0].length = iProdInfoPartNum.get_size();
aParameters[0].capacity = iProdInfoPartNum.get_size() + 1;
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
// Allocate memory for the string
int32 defstrlen = oscl_strlen(PVPLAYERENGINE_PRODINFO_PARTNUM_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::DoGetPlayerProductInfoParameter() Memory allocation for char* string failed"));
return PVMFErrNoMemory;
}
// Copy and set
oscl_strncpy(defstr, _STRLIT_CHAR(PVPLAYERENGINE_PRODINFO_PARTNUM_STRING), defstrlen);
defstr[defstrlen] = 0;
aParameters[0].value.pChar_value = defstr;
aParameters[0].capacity = defstrlen + 1;
aParameters[0].length = defstrlen;
}
else
{
// Return capability
// Empty string
aParameters[0].value.pChar_value = NULL;
aParameters[0].capacity = 0;
aParameters[0].length = 0;
}
break;
case 2: // "hardwareplatform"
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
// Allocate memory for the string
char* curstr = (char*)oscl_malloc(iProdInfoHWPlatform.get_size() + 1);
if (curstr == NULL)
{
oscl_free(aParameters[0].key);
oscl_free(aParameters);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerProductInfoParameter() Memory allocation for char* string failed"));
return PVMFErrNoMemory;
}
oscl_strset(curstr, 0, iProdInfoHWPlatform.get_size() + 1);
// Copy and set
oscl_strncpy(curstr, iProdInfoHWPlatform.get_cstr(), iProdInfoHWPlatform.get_size());
aParameters[0].value.pChar_value = curstr;
aParameters[0].length = iProdInfoHWPlatform.get_size();
aParameters[0].capacity = iProdInfoHWPlatform.get_size() + 1;
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
// Allocate memory for the string
int32 defstrlen = oscl_strlen(PVPLAYERENGINE_PRODINFO_HWPLATFORM_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::DoGetPlayerProductInfoParameter() Memory allocation for char* string failed"));
return PVMFErrNoMemory;
}
// Copy and set
oscl_strncpy(defstr, _STRLIT_CHAR(PVPLAYERENGINE_PRODINFO_HWPLATFORM_STRING), defstrlen);
defstr[defstrlen] = 0;
aParameters[0].value.pChar_value = defstr;
aParameters[0].capacity = defstrlen + 1;
aParameters[0].length = defstrlen;
}
else
{
// Return capability
// Empty string
aParameters[0].value.pChar_value = NULL;
aParameters[0].capacity = 0;
aParameters[0].length = 0;
}
break;
case 3: // "softwareplatform"
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
// Allocate memory for the string
char* curstr = (char*)oscl_malloc(iProdInfoSWPlatform.get_size() + 1);
if (curstr == NULL)
{
oscl_free(aParameters[0].key);
oscl_free(aParameters);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerProductInfoParameter() Memory allocation for char* string failed"));
return PVMFErrNoMemory;
}
oscl_strset(curstr, 0, iProdInfoSWPlatform.get_size() + 1);
// Copy and set
oscl_strncpy(curstr, iProdInfoSWPlatform.get_cstr(), iProdInfoSWPlatform.get_size());
aParameters[0].value.pChar_value = curstr;
aParameters[0].length = iProdInfoSWPlatform.get_size();
aParameters[0].capacity = iProdInfoSWPlatform.get_size() + 1;
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
// Allocate memory for the string
int32 defstrlen = oscl_strlen(PVPLAYERENGINE_PRODINFO_SWPLATFORM_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::DoGetPlayerProductInfoParameter() Memory allocation for char* string failed"));
return PVMFErrNoMemory;
}
// Copy and set
oscl_strncpy(defstr, _STRLIT_CHAR(PVPLAYERENGINE_PRODINFO_SWPLATFORM_STRING), defstrlen);
defstr[defstrlen] = 0;
aParameters[0].value.pChar_value = defstr;
aParameters[0].capacity = defstrlen + 1;
aParameters[0].length = defstrlen;
}
else
{
// Return capability
// Empty string
aParameters[0].value.pChar_value = NULL;
aParameters[0].capacity = 0;
aParameters[0].length = 0;
}
break;
case 4: // "device"
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
// Allocate memory for the string
char* curstr = (char*)oscl_malloc(iProdInfoDevice.get_size() + 1);
if (curstr == NULL)
{
oscl_free(aParameters[0].key);
oscl_free(aParameters);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerProductInfoParameter() Memory allocation for char* string failed"));
return PVMFErrNoMemory;
}
oscl_strset(curstr, 0, iProdInfoDevice.get_size() + 1);
// Copy and set
oscl_strncpy(curstr, iProdInfoPartNum.get_cstr(), iProdInfoDevice.get_size());
aParameters[0].value.pChar_value = curstr;
aParameters[0].length = iProdInfoDevice.get_size();
aParameters[0].capacity = iProdInfoDevice.get_size() + 1;
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
// Allocate memory for the string
int32 defstrlen = oscl_strlen(PVPLAYERENGINE_PRODINFO_DEVICE_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::DoGetPlayerProductInfoParameter() Memory allocation for char* string failed"));
return PVMFErrNoMemory;
}
// Copy and set
oscl_strncpy(defstr, _STRLIT_CHAR(PVPLAYERENGINE_PRODINFO_DEVICE_STRING), defstrlen);
defstr[defstrlen] = 0;
aParameters[0].value.pChar_value = defstr;
aParameters[0].capacity = defstrlen + 1;
aParameters[0].length = defstrlen;
}
else
{
// Return capability
// Empty string
aParameters[0].value.pChar_value = NULL;
aParameters[0].capacity = 0;
aParameters[0].length = 0;
}
break;
default:
// Invalid index
oscl_free(aParameters[0].key);
oscl_free(aParameters);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerProductInfoParameter() Invalid index for product info"));
return PVMFErrArgument;
}
aNumParamElements = 1;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetPlayerProductInfoParameter() 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 || engcomp3ind == 12)
{
// Match couldn't be found or non-leaf node ("productinfo") specified
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 0: // "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 1: // "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 2: // "endtimecheck_interval"
// Check if within range
if (aParameter.value.uint32_value < PVPLAYERENGINE_CONFIG_ENDTIMECHECKINTERVAL_MIN ||
aParameter.value.uint32_value > PVPLAYERENGINE_CONFIG_ENDTIMECHECKINTERVAL_MAX)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() Invalid value for endtimecheck_interval"));
return PVMFErrArgument;
}
// Change the config if to set
if (aSetParam)
{
iEndTimeCheckInterval = aParameter.value.uint32_value;
}
break;
case 3: // "seektosyncpoint"
// Nothing to validate since it is boolean
// Change the config if to set
if (aSetParam)
{
iSeekToSyncPoint = aParameter.value.bool_value;
}
break;
case 4: // "skiptorequestedpos"
// Nothing to validate since it is boolean
// Change the config if to set
if (aSetParam)
{
iSkipToRequestedPosition = aParameter.value.bool_value;
}
break;
case 5: // "renderskipped"
// Nothing to validate since it is boolean
// Change the config if to set
if (aSetParam)
{
iRenderSkipped = aParameter.value.bool_value;
}
break;
case 6: // "syncpointseekwindow"
// Check if within range
if (aParameter.value.uint32_value < PVPLAYERENGINE_CONFIG_SEEKTOSYNCPOINTWINDOW_MIN ||
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 7: // "syncmargin_video"
case 8: // "syncmargin_audio"
case 9: // "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 - 7);
}
}
break;
case 10: // "nodecmd_timeout"
// Check if within range
if (aParameter.value.uint32_value < PVPLAYERENGINE_CONFIG_NODECMDTIMEOUT_MIN ||
aParameter.value.uint32_value > PVPLAYERENGINE_CONFIG_NODECMDTIMEOUT_MAX)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() Invalid value for ndoecmd_timeout"));
return PVMFErrArgument;
}
// Change the config if to set
if (aSetParam)
{
iNodeCmdTimeout = aParameter.value.uint32_value;
}
break;
case 11: // "nodedataqueuing_timeout"
// Check if within range
if (aParameter.value.uint32_value < PVPLAYERENGINE_CONFIG_NODEDATAQUEUINGTIMEOUT_MIN ||
aParameter.value.uint32_value > PVPLAYERENGINE_CONFIG_NODEDATAQUEUINGTIMEOUT_MAX)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() Invalid value for nodedataqueuing_timeout"));
return PVMFErrArgument;
}
// Change the config if to set
if (aSetParam)
{
iNodeDataQueuingTimeout = aParameter.value.uint32_value;
}
break;
case 13: // "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() == OsclClock::RUNNING)
{
StartPlaybackStatusTimer();
}
}
}
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::DoVerifyAndSetPlayerProductInfoParameter(PvmiKvp& aParameter, bool aSetParam)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoVerifyAndSetPlayerProductInfoParameter() In"));
// Determine the valtype
PvmiKvpValueType keyvaltype = GetValTypeFromKeyString(aParameter.key);
if (keyvaltype == PVMI_KVPVALTYPE_UNKNOWN)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerProductInfoParameter() Valtype unknown"));
return PVMFErrArgument;
}
// Retrieve the 4th component from the key string
char* compstr = NULL;
pv_mime_string_extract_type(3, aParameter.key, compstr);
int32 engcomp4ind = 0;
for (engcomp4ind = 0; engcomp4ind < PVPLAYERCONFIG_PRODINFO_NUMKEYS; ++engcomp4ind)
{
// Go through each engine component string at 4th level
if (pv_mime_strcmp(compstr, (char*)(PVPlayerConfigProdInfoKeys[engcomp4ind].iString)) >= 0)
{
// Break out of the for loop
break;
}
}
if (engcomp4ind >= PVPLAYERCONFIG_PRODINFO_NUMKEYS)
{
// Match couldn't be found
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerProductInfoParameter() Unsupported key"));
return PVMFErrArgument;
}
// Verify the valtype
if (keyvaltype != PVPlayerConfigProdInfoKeys[engcomp4ind].iValueType)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerProductInfoParameter() Valtype does not match for key"));
return PVMFErrArgument;
}
switch (engcomp4ind)
{
case 0: // "productname"
// Check if within range
if (aParameter.value.pChar_value == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerProductInfoParameter() char* string for productname is NULL"));
return PVMFErrArgument;
}
// Change the config if to set
if (aSetParam)
{
iProdInfoProdName = aParameter.value.pChar_value;
}
break;
case 1: // "partnumber"
// Check if within range
if (aParameter.value.pChar_value == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerProductInfoParameter() char* string for productname is NULL"));
return PVMFErrArgument;
}
// Change the config if to set
if (aSetParam)
{
iProdInfoPartNum = aParameter.value.pChar_value;
}
break;
case 2: // "hardwareplatform"
// Check if within range
if (aParameter.value.pChar_value == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerProductInfoParameter() char* string for productname is NULL"));
return PVMFErrArgument;
}
// Change the config if to set
if (aSetParam)
{
iProdInfoHWPlatform = aParameter.value.pChar_value;
}
break;
case 3: // "softwareplatform"
// Check if within range
if (aParameter.value.pChar_value == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerProductInfoParameter() char* string for productname is NULL"));
return PVMFErrArgument;
}
// Change the config if to set
if (aSetParam)
{
iProdInfoSWPlatform = aParameter.value.pChar_value;
}
break;
case 4: // "device"
// Check if within range
if (aParameter.value.pChar_value == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerProductInfoParameter() char* string for productname is NULL"));
return PVMFErrArgument;
}
// Change the config if to set
if (aSetParam)
{
iProdInfoDevice = aParameter.value.pChar_value;
}
break;
default:
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerProductInfoParameter() Invalid index for product info"));
return PVMFErrArgument;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoVerifyAndSetPlayerProductInfoParameter() 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 (aMediaType == 0)
{
// Video
iSyncMarginVideo.min = aEarlyMargin;
iSyncMarginVideo.max = aLateMargin;
// Find the video datapath in the list
int32 vdpind = -1;
if (FindDatapathByMediaType(PVP_MEDIATYPE_VIDEO, vdpind) == true)
{
PVPlayerEngineDatapath* pvpedp = &(iDatapathList[vdpind]);
if (pvpedp->iTrackActive == true)
{
if (pvpedp->iSinkNodeSyncCtrlIF)
{
pvpedp->iSinkNodeSyncCtrlIF->SetMargins((-1*iSyncMarginVideo.min), iSyncMarginVideo.max);
}
}
}
}
else if (aMediaType == 1)
{
// Audio
iSyncMarginAudio.min = aEarlyMargin;
iSyncMarginAudio.max = aLateMargin;
// Find the audio datapath in the list
int32 adpind = -1;
if (FindDatapathByMediaType(PVP_MEDIATYPE_AUDIO, adpind) == true)
{
PVPlayerEngineDatapath* pvpedp = &(iDatapathList[adpind]);
if (pvpedp->iTrackActive == true)
{
if (pvpedp->iSinkNodeSyncCtrlIF)
{
pvpedp->iSinkNodeSyncCtrlIF->SetMargins((-1*iSyncMarginAudio.min), iSyncMarginAudio.max);
}
}
}
}
else if (aMediaType == 2)
{
// Text
iSyncMarginText.min = aEarlyMargin;
iSyncMarginText.max = aLateMargin;
// Find the text datapath in the list
int32 tdpind = -1;
if (FindDatapathByMediaType(PVP_MEDIATYPE_TEXT, tdpind) == true)
{
PVPlayerEngineDatapath* pvpedp = &(iDatapathList[tdpind]);
if (pvpedp->iTrackActive == true)
{
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;
switch (aNodeResp.GetCmdStatus())
{
case PVMFSuccess:
// Query for track selection interface
cmdstatus = DoSourceNodeQueryTrackSelIF(aNodeContext.iCmdId, aNodeContext.iCmdContext);
if (cmdstatus != PVMFSuccess)
{
// There shouldn't be any other command pending to complete in engine's AO
OSCL_ASSERT(iCommandCompleteInEngineAOPending == false);
iCommandCompleteInEngineAOPending = true;
if ((CheckForSourceRollOver() == true) && (iRollOverState == RollOverStateInProgress))
{
iRollOverState = RollOverStateStart;
}
else
{
iRollOverState = RollOverStateIdle;
}
iCommandCompleteInEngineAOCmdStatus = cmdstatus;
iCommandCompleteInEngineAOErrMsg = NULL;
}
break;
default:
{
cmdstatus = aNodeResp.GetCmdStatus();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aNodeResp.GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
iCommandCompleteInEngineAOErrMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceInit, puuid, nextmsg));
// There shouldn't be any other command pending to complete in engine's AO
OSCL_ASSERT(iCommandCompleteInEngineAOPending == false);
iCommandCompleteInEngineAOPending = true;
if ((CheckForSourceRollOver() == true) && (iRollOverState == RollOverStateInProgress))
{
iRollOverState = RollOverStateStart;
}
else
{
iRollOverState = RollOverStateIdle;
}
iCommandCompleteInEngineAOCmdStatus = cmdstatus;
}
break;
}
if (iCommandCompleteInEngineAOPending)
{
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;
switch (aNodeResp.GetCmdStatus())
{
case PVMFSuccess:
// 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;
}
else
{
iRollOverState = RollOverStateIdle;
iCommandCompleteInEngineAOPending = false;
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess);
}
}
break;
default:
{
cmdstatus = aNodeResp.GetCmdStatus();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aNodeResp.GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
iCommandCompleteInEngineAOErrMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceInit, puuid, nextmsg));
// There shouldn't be any other command pending to complete in engine's AO
OSCL_ASSERT(iCommandCompleteInEngineAOPending == false);
iCommandCompleteInEngineAOPending = true;
if ((CheckForSourceRollOver() == true) && (iRollOverState == RollOverStateInProgress))
{
iRollOverState = RollOverStateStart;
}
iCommandCompleteInEngineAOCmdStatus = cmdstatus;
}
break;
}
if (iCommandCompleteInEngineAOPending)
{
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)
{
// Track level info IF is not available in this data source
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)
{
// Playback control is not available in this data source
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)
{
// Direction control is not available in this data source
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 && iSourceNodeMetadataExtIF)
{
// Add the parser node's metadata extension IF to the list
if (AddToMetadataInterfaceList(iSourceNodeMetadataExtIF, iSourceNodeSessionId) != 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
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)
{
// Cap-config is not available in this data source
iSourceNodeCapConfigIF = NULL;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() Cap-Config IF not available"));
}
}
else if (aNodeContext.iCmdType == PVP_CMD_SourceNodeQueryCPMLicenseIF)
{
if (aNodeResp.GetCmdStatus() != PVMFSuccess)
{
//CPM License is not available in this data source
iSourceNodeCPMLicenseIF = NULL;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() CPM License IF not available"));
}
}
else if (aNodeContext.iCmdType == PVP_CMD_SourceNodeQuerySrcNodeRegInitIF)
{
if (aNodeResp.GetCmdStatus() == PVMFSuccess && iSourceNodeRegInitIF)
{
// Set source node regsitry
iSourceNodeRegInitIF->SetPlayerNodeRegistry(&iPlayerNodeRegistry);
}
else
{
//Node Registry Init Extension Interface is not available in this data source
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;
}
else
{
iRollOverState = RollOverStateIdle;
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFFailure);
}
}
}
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;
iCommandCompleteInEngineAOPending = false;
PVMFStatus cmdstatus;
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 PVMFErrLicenseRequired:
case PVMFErrHTTPAuthenticationRequired:
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInit() PVMFErrLicenseRequired/PVMFErrHTTPAuthenticationRequired"));
HandleErrorBasedOnPlayerState();
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;
;
default:
{
HandleErrorBasedOnPlayerState();
// idle state implies that init sequence, including any rollovers are complete
// report command complete
if (iState == PVP_ENGINE_STATE_IDLE)
{
if (CheckForSourceRollOver() == false)
{
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();
}
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_LLDBG, 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::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)
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;
}
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)
{
OSCL_ASSERT(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::HandleSourceNodeGetDlaData(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
(0, "PVPlayerEngine::HandleSourceNodeGetDlaData() Tick=%d", OsclTickCount::TickCount()));
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeGetDlaData() In"));
OSCL_UNUSED_ARG(aNodeContext);
switch (aNodeResp.GetCmdStatus())
{
case PVMFSuccess:
{
// Extract the DLA Data and save it
// Check that there is one KVP in value list
if (iDlaDataValueList.size() != 1)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSourceNodeGetDlaData() Value list size is not 1 (size=%d)",
iDlaDataValueList.size()));
break;
}
// Check that the key in KVP is not NULL
if (iDlaDataValueList[0].key == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSourceNodeGetDlaData() Value list key string is NULL"));
break;
}
// Check that value is for DLA Data
int retval = pv_mime_strstr(iDlaDataValueList[0].key, (char*)_STRLIT_CHAR("drm/dla-data"));
if (retval == -1)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSourceNodeGetDlaData() Key string does not contain dla data"));
break;
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSourceNodeGetDlaData() Key string does contain dla data (size=%d)",
iDlaDataValueList[0].length));
}
// Check that Dla Data value is uint8ptr.
PvmiKvpValueType durvaltype = GetValTypeFromKeyString(iDlaDataValueList[0].key);
if (durvaltype != PVMI_KVPVALTYPE_UINT8PTR && durvaltype != PVMI_KVPVALTYPE_UNKNOWN)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSourceNodeGetDlaData() Value type is not PVMI_KVPVALTYPE_UINT8PTR or unknown"));
break;
}
iCPMAcquireLicenseParam.iLicenseData = iDlaDataValueList[0].value.pUint8_value;
iCPMAcquireLicenseParam.iLicenseDataSize = iDlaDataValueList[0].length;
}
break;
default:
{
// DLA Data is not available.
// Most license license acquire will fail, but continue
// anyway.
iCPMAcquireLicenseParam.iLicenseData = NULL;
iCPMAcquireLicenseParam.iLicenseDataSize = 0;
}
break;
}
//Create the plugin and query for the license IF
PVMFStatus status = DoGetPluginLicenseIF();
if (status != PVMFSuccess)
{
//Trigger the AO to complete the engine command
// There shouldn't be any other command pending to complete in engine's AO
OSCL_ASSERT(iCommandCompleteInEngineAOPending == false);
iCommandCompleteInEngineAOPending = true;
iCommandCompleteInEngineAOCmdStatus = status;
iCommandCompleteInEngineAOErrMsg = NULL;
if (iCommandCompleteInEngineAOPending)
{
if (IsBusy())
{
Cancel();
}
RunIfNotReady();
}
}
//else wait on CPMPluginCommandCompleted.
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeGetDlaData() 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].iTrackActive && 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;
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"
, iPlaybackDirection
, iStartNPT
, iStartMediaDataTS
, (aPos.iIndeterminate) ? -1 : aPos.iPosValue.millisec_value));
}
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.
iPlaybackClock.SetClockTimebase(iPlaybackTimebase);
iPlaybackTimebase.SetRate(iPlaybackClockRate);
}
// Only restart the clock if the clock was paused in this function
if (clockpaused)
{
iPlaybackClock.Start();
}
}
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:
{
// Initiate the setup sequence for each datapath
iNumPendingDatapathCmd = 0;
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackInfo != NULL)
{
PVMFStatus retcode = DoSetupSinkNode(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);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodePrepare() Report command as failed"));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFFailure);
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodePrepare() Report command as failed"));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus);
}
}
}
break;
default:
{
HandleErrorBasedOnPlayerState();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aNodeResp.GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, aNodeResp.GetCmdStatus(), OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
}
break;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodePrepare() Out"));
}
void PVPlayerEngine::HandleSinkNodeQueryFileOutConfigIF(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
(0, "PVPlayerEngine::HandleSinkNodeQueryFileOutConfigIF() Tick=%d", OsclTickCount::TickCount()));
OSCL_ASSERT(aNodeContext.iEngineDatapath != NULL);
OSCL_ASSERT(aNodeContext.iEngineDatapath->iTrackInfo != NULL);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeQueryFileOutConfigIF() In %s", aNodeContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr()));
PVMFStatus cmdstatus = PVMFErrNotSupported;
switch (aNodeResp.GetCmdStatus())
{
case PVMFSuccess:
{
OSCL_ASSERT(aNodeContext.iEngineDatapath != NULL);
OSCL_ASSERT(aNodeContext.iEngineDatapath->iDataSink != NULL);
// Set the filename
aNodeContext.iEngineDatapath->iSinkNodeFOConfigIF->SetOutputFileName(aNodeContext.iEngineDatapath->iDataSink->GetDataSinkFilename());
// Query the sink node for optional ext IFs
cmdstatus = DoSinkNodeQueryInterfaceOptional(*(aNodeContext.iEngineDatapath), aNodeContext.iCmdId, aNodeContext.iCmdContext);
if (cmdstatus == PVMFErrNotSupported)
{
// Check if a dec node is needed
cmdstatus = DoSetupDecNode(*(aNodeContext.iEngineDatapath), aNodeContext.iCmdId, aNodeContext.iCmdContext);
if (cmdstatus == PVMFErrNotSupported)
{
// Continue to prepare the datapath
cmdstatus = DoDatapathPrepare(*(aNodeContext.iEngineDatapath), aNodeContext.iCmdId, aNodeContext.iCmdContext);
}
}
if (cmdstatus != PVMFSuccess)
{
HandleErrorBasedOnPlayerState();
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeQueryFileOutConfigIF() Report command as failed"));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus);
--iNumPendingDatapathCmd;
// Cancel any pending node/datapath commands
DoCancelDueToError();
}
}
break;
default:
{
HandleErrorBasedOnPlayerState();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aNodeResp.GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSinkInit, puuid, nextmsg));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, aNodeResp.GetCmdStatus(), OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
// Cancel any pending node/datapath commands
DoCancelDueToError();
}
break;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeQueryFileOutConfigIF() 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()));
OSCL_ASSERT(aNodeContext.iEngineDatapath != NULL);
OSCL_ASSERT(aNodeContext.iEngineDatapath->iTrackInfo != NULL);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional() In %s", aNodeContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr()));
// Determine QueryInterface() for which interface completed
OSCL_ASSERT(aNodeContext.iEngineDatapath != NULL);
if (aNodeContext.iCmdType == PVP_CMD_SinkNodeQuerySyncCtrlIF)
{
if (aNodeResp.GetCmdStatus() == PVMFSuccess && aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF)
{
// Pass the playback clock to the sync control
aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF->SetClock(&iPlaybackClock);
// Set the sync margin based on media type
switch (aNodeContext.iEngineDatapath->iMediaType)
{
case PVP_MEDIATYPE_AUDIO:
aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF->SetMargins((-1*iSyncMarginAudio.min), iSyncMarginAudio.max);
break;
case PVP_MEDIATYPE_TEXT:
aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF->SetMargins((-1*iSyncMarginText.min), iSyncMarginText.max);
break;
case PVP_MEDIATYPE_VIDEO:
default: // Use video's sync margin for unknown media type
aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF->SetMargins((-1*iSyncMarginVideo.min), iSyncMarginVideo.max);
break;
}
}
else
{
// Metadata is not available in this sink node
aNodeContext.iEngineDatapath->iSinkNodeMetadataExtIF = NULL;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional() Metadata IF not available"));
}
}
else if (aNodeContext.iCmdType == PVP_CMD_SinkNodeQueryMetadataIF)
{
if (aNodeResp.GetCmdStatus() == PVMFSuccess && aNodeContext.iEngineDatapath->iSinkNodeMetadataExtIF)
{
// Add the video sink node's metadata extension IF to the list
if (AddToMetadataInterfaceList(aNodeContext.iEngineDatapath->iSinkNodeMetadataExtIF, aNodeContext.iEngineDatapath->iSinkNodeSessionId) != 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->iSinkNodeMetadataExtIF = NULL;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional() Metadata IF not available"));
}
}
else if (aNodeContext.iCmdType == PVP_CMD_SinkNodeQueryCapConfigIF)
{
if (aNodeResp.GetCmdStatus() == PVMFSuccess && aNodeContext.iEngineDatapath->iSinkNodeCapConfigIF)
{
// Nothing to do here
}
else
{
// Cap-config is not available
aNodeContext.iEngineDatapath->iSinkNodeCapConfigIF = NULL;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional() Cap-Config IF not available"));
}
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional() Unknown cmd type. Asserting"));
OSCL_ASSERT(false);
}
// 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 = DoSetupDecNode(*(aNodeContext.iEngineDatapath), aNodeContext.iCmdId, aNodeContext.iCmdContext);
if (cmdstatus == PVMFErrNotSupported)
{
cmdstatus = DoDatapathPrepare(*(aNodeContext.iEngineDatapath), aNodeContext.iCmdId, aNodeContext.iCmdContext);
}
if (cmdstatus != PVMFSuccess)
{
HandleErrorBasedOnPlayerState();
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional() Report command as failed"));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus);
// Cancel any pending node/datapath commands
DoCancelDueToError();
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional() Out"));
}
void PVPlayerEngine::HandleSinkNodeDecNodeQueryCapConfigIF(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
(0, "PVPlayerEngine::HandleSinkNodeDecNodeQueryCapConfigIF() Tick=%d", OsclTickCount::TickCount()));
OSCL_UNUSED_ARG(aNodeResp);
if (aNodeContext.iCmdType != PVP_CMD_SinkNodeDecNodeQueryCapConfigIF)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeDecNodeQueryCapConfigIF() Unknown cmd type. Asserting"));
OSCL_ASSERT(false);
}
// Decrement the pending counter and go to next step if 0.
OSCL_ASSERT(iNumPendingNodeCmd > 0);
--iNumPendingNodeCmd;
if (iNumPendingNodeCmd == 0)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeDecNodeQueryCapConfigIF() All QueryInterface() commands complete"));
PVMFStatus cmdstatus = DoSinkNodeInit(aNodeContext.iCmdId, aNodeContext.iCmdContext);
if (cmdstatus != PVMFSuccess)
{
HandleErrorBasedOnPlayerState();
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeDecNodeQueryCapConfigIF() Report command as failed"));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus);
// Cancel any pending node/datapath commands
DoCancelDueToError();
return;
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeDecNodeQueryCapConfigIF() Out"));
}
void PVPlayerEngine::HandleSinkNodeDecNodeVerifyParameter(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
(0, "PVPlayerEngine::HandleSinkNodeDecNodeVerifyParameter() Tick=%d", OsclTickCount::TickCount()));
OSCL_UNUSED_ARG(aNodeResp);
if (aNodeContext.iCmdType != PVP_CMD_SinkNodeDecNodeVerifyParameter)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeDecNodeVerifyParameter() Unknown cmd type. Asserting"));
OSCL_ASSERT(false);
}
// Decrement the pending counter and go to next step if 0.
OSCL_ASSERT(iNumPendingNodeCmd > 0);
--iNumPendingNodeCmd;
if (iNumPendingNodeCmd == 0)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeDecNodeVerifyParameter() All Sinknode Init() commands complete"));
PVMFStatus cmdstatus = PVMFFailure;
// Select tracks based on available engine datapaths
cmdstatus = DoSourceNodeTrackSelection(aNodeContext.iCmdId, aNodeContext.iCmdContext);
if (cmdstatus != PVMFSuccess)
{
HandleErrorBasedOnPlayerState();
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeDecNodeVerifyParameter() Report command as failed"));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus);
// Cancel any pending node/datapath commands
DoCancelDueToError();
return;
}
// Reset SinkNode and MIO on available engine datapaths
cmdstatus = DoSinkNodeReset(aNodeContext.iCmdId, aNodeContext.iCmdContext);
if (cmdstatus != PVMFSuccess)
{
HandleErrorBasedOnPlayerState();
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeDecNodeVerifyParameter() Report command as failed"));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus);
// Cancel any pending node/datapath commands
DoCancelDueToError();
return;
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeDecNodeVerifyParameter() Out"));
}
void PVPlayerEngine::HandleSinkNodeDecNodeReset(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE,
(0, "PVPlayerEngine::HandleSinkNodeDecNodeReset() Tick=%d", OsclTickCount::TickCount()));
OSCL_UNUSED_ARG(aNodeResp);
if (aNodeContext.iCmdType != PVP_CMD_SinkNodeDecNodeReset)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeDecNodeReset() Unknown cmd type. Asserting"));
OSCL_ASSERT(false);
}
// Decrement the pending counter and go to next step if 0.
OSCL_ASSERT(iNumPendingNodeCmd > 0);
--iNumPendingNodeCmd;
if (iNumPendingNodeCmd == 0)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeDecNodeReset() All Sinknode Reset() commands complete"));
//Destroy created temporal decoder node and sink node
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iDecNode != NULL)
{
if (iDatapathList[i].iDecNodeCapConfigIF == NULL)
iDatapathList[i].iDecNodeCapConfigIF = NULL;
iDatapathList[i].iDecNode->Disconnect(iDatapathList[i].iDecNodeSessionId);
iDatapathList[i].iDecNode->ThreadLogoff();
PVPlayerEngineUuidNodeMapping* iter = iNodeUuids.begin();
for (; iter != iNodeUuids.end(); ++iter)
if (iter->iNode == iDatapathList[i].iDecNode)
break;
if (iter != iNodeUuids.end())
{
bool release_status = false;
int32 leavecode = 0;
OSCL_TRY(leavecode, release_status = iPlayerNodeRegistry.ReleaseNode(iter->iUuid, iDatapathList[i].iDecNode));
OSCL_FIRST_CATCH_ANY(leavecode,
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeDecNodeReset() Error in releasing DecNode"));
return;);
if (release_status == false)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeDecNodeReset() Factory returned false while releasing the decnode"));
return;
}
iNodeUuids.erase(iter);
iDatapathList[i].iDecNode = NULL;
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeDecNodeReset() decnode not found"));
return;
}
}
if (iDatapathList[i].iSinkNode != NULL)
{
iDatapathList[i].iSinkNode->Disconnect(iDatapathList[i].iSinkNodeSessionId);
iDatapathList[i].iSinkNode->ThreadLogoff();
if (iDatapathList[i].iSinkNodeCapConfigIF == NULL)
iDatapathList[i].iSinkNodeCapConfigIF = NULL;
if (iDatapathList[i].iDataSink->GetDataSinkType() == PVP_DATASINKTYPE_FILENAME)
{
PVFileOutputNodeFactory::DeleteFileOutput(iDatapathList[i].iSinkNode);
iDatapathList[i].iSinkNode = NULL;
}
else if (iDatapathList[i].iDataSink->GetDataSinkType() == PVP_DATASINKTYPE_SINKNODE)
{
iDatapathList[i].iSinkNode = NULL;
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeDecNodeReset() Unsupported player data sink type"));
OSCL_ASSERT(false);
return;
}
}
}
// Prepare the source node
PVMFStatus cmdstatus = DoSourceNodePrepare(aNodeContext.iCmdId, aNodeContext.iCmdContext);
if (cmdstatus != PVMFSuccess)
{
HandleErrorBasedOnPlayerState();
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeDecNodeReset() Report command as failed"));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus);
// Cancel any pending node/datapath commands
DoCancelDueToError();
return;
}
}
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()));
OSCL_ASSERT(aNodeContext.iEngineDatapath != NULL);
OSCL_ASSERT(aNodeContext.iEngineDatapath->iTrackInfo != NULL);
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
OSCL_ASSERT(aNodeContext.iEngineDatapath != NULL);
if (aNodeContext.iCmdType == PVP_CMD_DecNodeQueryMetadataIF)
{
if (aNodeResp.GetCmdStatus() == PVMFSuccess && aNodeContext.iEngineDatapath->iDecNodeMetadataExtIF)
{
// Add the video dec node's metadata extension IF to the list
if (AddToMetadataInterfaceList(aNodeContext.iEngineDatapath->iDecNodeMetadataExtIF, aNodeContext.iEngineDatapath->iDecNodeSessionId) != 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->iDecNodeMetadataExtIF = NULL;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() Metadata IF not available"));
}
}
else if (aNodeContext.iCmdType == PVP_CMD_DecNodeQueryCapConfigIF)
{
if (aNodeResp.GetCmdStatus() == PVMFSuccess && aNodeContext.iEngineDatapath->iDecNodeCapConfigIF)
{
// Configure the dec node for player use
PvmiKvp kvpparam;
PvmiKvp* retkvp = NULL;
OSCL_StackString<64> kvpparamkey;
switch (aNodeContext.iEngineDatapath->iMediaType)
{
case PVP_MEDIATYPE_VIDEO:
// Disable drop frame mode
kvpparamkey = _STRLIT_CHAR("x-pvmf/video/decoder/dropframe_enable;valtype=bool");
kvpparam.value.bool_value = false;
break;
case PVP_MEDIATYPE_AUDIO:
// Disable silence insertion
kvpparamkey = _STRLIT_CHAR("x-pvmf/audio/decoder/silenceinsertion_enable;valtype=bool");
kvpparam.value.bool_value = false;
break;
default:
break;
}
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"));
}
}
}
else
{
// Cap-config is not available
aNodeContext.iEngineDatapath->iDecNodeCapConfigIF = NULL;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() Cap-Config IF not available"));
}
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() Unknown cmd type. Asserting"));
OSCL_ASSERT(false);
}
// 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)
{
HandleErrorBasedOnPlayerState();
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() Report command as failed"));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus);
// Cancel any pending node/datapath commands
DoCancelDueToError();
}
}
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"));
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"));
iActualPlaybackPosition = iCurrentBeginPosition.iPosValue.millisec_value;
}
else if (aNodeResp.GetCmdStatus() != PVMFSuccess)
{
// If not unsupported error, then assume fatal error from source node
HandleErrorBasedOnPlayerState();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aNodeResp.GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, aNodeResp.GetCmdStatus(), OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
return;
}
else
{
// Every thing is OK.. Calculate the iActualPlaybackPosition depensing upon nearest before and after syncPoints.
// For MPEG4 files
PVMFNodeCapability nodeCapability;
iSourceNode->GetCapability(nodeCapability);
PVMFFormatType * formatType = nodeCapability.iInputFormatCapability.begin();
bool mpeg4FormatType = false;
if (formatType != NULL)
{
switch (*formatType)
{
case PVMF_MPEG4FF:
mpeg4FormatType = true;
break;
default:
mpeg4FormatType = false;
break;
}
}
if (mpeg4FormatType)
{
CalculateActualPlaybackPosition();
}
}
// Determine the SetDataSourcePosition parameter based on query result and reposition settings
PVMFTimestamp requesttime = iCurrentBeginPosition.iPosValue.millisec_value;
bool seektosyncpt = true;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,
"PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition()"
"Requested NPT %d, Actual NPT %d", requesttime, iActualPlaybackPosition));
uint32 startOfSeekWindow = 0;
if (iCurrentBeginPosition.iPosValue.millisec_value > iSyncPointSeekWindow)
{
startOfSeekWindow = (iCurrentBeginPosition.iPosValue.millisec_value - iSyncPointSeekWindow);
}
uint32 endOfSeekWindow = iCurrentBeginPosition.iPosValue.millisec_value + iSyncPointSeekWindow;
// 1) Check if the actual seek point falls within the window
if ((iActualPlaybackPosition >= startOfSeekWindow) &&
(iActualPlaybackPosition <= endOfSeekWindow))
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0,
"PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() - "
"RequestedNPT(%d) ActualNPT(%d) is in the window (%d, %d), Seeking To %d",
requesttime, iActualPlaybackPosition, startOfSeekWindow, endOfSeekWindow, iActualPlaybackPosition));
requesttime = iActualPlaybackPosition;
}
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 ((iActualPlaybackPosition < startOfSeekWindow) ||
(iActualPlaybackPosition > endOfSeekWindow))
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0,
"PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() - "
"RequestedNPT(%d) ActualNPT(%d) is outside the window (%d, %d), Seeking To %d Seek-To-SyncPt False",
requesttime, iActualPlaybackPosition, startOfSeekWindow, endOfSeekWindow, startOfSeekWindow));
requesttime = startOfSeekWindow;
seektosyncpt = false;
iActualPlaybackPosition = requesttime;
}
else
{
//error
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0,
"PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() - "
"RequestedNPT(%d) ActualNPT(%d) window (%d, %d), Error Condition Asserting",
requesttime, iActualPlaybackPosition, startOfSeekWindow, endOfSeekWindow));
OSCL_ASSERT(false);
}
}
// Do the source positioning
PVMFStatus retval = DoSourceNodeSetDataSourcePosition(aNodeContext.iCmdId, aNodeContext.iCmdContext, requesttime, seektosyncpt);
if (retval != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() Report command as failed"));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, retval);
}
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:
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() Requested begin position(%d ms) is not supported so start from time 0.",
iCurrentBeginPosition.iPosValue.millisec_value));
if (iChangePlaybackPositionWhenResuming)
{
PVPPlaybackPosition curpos;
curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC;
GetPlaybackClockPosition(curpos);
uint32 clockcurpos = 0;
bool tmpbool = false;
iPlaybackClock.GetCurrentTime32(clockcurpos, tmpbool, OSCLCLOCK_MSEC);
// since repositioning is not supported and if the playback position change request was
// issued during paused state, then continue from paused position.
iWatchDogTimerInterval = 0;
iActualPlaybackPosition = curpos.iPosValue.millisec_value;
iActualMediaDataTS = clockcurpos;
iAdjustedMediaDataTS = clockcurpos;
iStartNPT = iActualPlaybackPosition;
iStartMediaDataTS = iAdjustedMediaDataTS;
}
else
{
// Since this repositioning was not supported, assume the playback
// will start from time 0
iWatchDogTimerInterval = 0;
iActualPlaybackPosition = 0;
iActualMediaDataTS = 0;
iAdjustedMediaDataTS = 0;
// Then continue to handle like success case
iStartNPT = 0;
iStartMediaDataTS = 0;
}
// Save the actual starting position for GetPlaybackRange() query
iCurrentBeginPosition.iPosValue.millisec_value = iActualPlaybackPosition;
iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;
}
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, iActualPlaybackPosition, iCurrentBeginPosition.iPosValue.millisec_value));
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
(0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() SetDataSourcePosition() successful. StartMediaTS %d ms, ActualNPT %d ms, TargetNPT %d ms",
iActualMediaDataTS, iActualPlaybackPosition, iCurrentBeginPosition.iPosValue.millisec_value));
// Compute the difference between actualNPT and targetNPT before any adjustments
if (iCurrentBeginPosition.iPosValue.millisec_value >= iActualPlaybackPosition)
{
iWatchDogTimerInterval = iCurrentBeginPosition.iPosValue.millisec_value - iActualPlaybackPosition;
}
// Determine if adjustment needed to skip to requested time
if (iSkipToRequestedPosition && (iActualPlaybackPosition < iCurrentBeginPosition.iPosValue.millisec_value))
{
if (iCurrentBeginPosition.iPosValue.millisec_value - iActualPlaybackPosition > SYNC_POINT_DIFF_THRESHOLD)
{
// 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
iAdjustedMediaDataTS = iActualMediaDataTS;
iCurrentBeginPosition.iPosValue.millisec_value = iActualPlaybackPosition;
iWatchDogTimerInterval = 0;
}
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.
iAdjustedMediaDataTS = iActualMediaDataTS + (iCurrentBeginPosition.iPosValue.millisec_value - iActualPlaybackPosition);
iActualPlaybackPosition = iCurrentBeginPosition.iPosValue.millisec_value;
}
}
else
{
// Can't adjust the skip time back so use the returned values to skip to
iAdjustedMediaDataTS = iActualMediaDataTS;
iCurrentBeginPosition.iPosValue.millisec_value = iActualPlaybackPosition;
iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;
iWatchDogTimerInterval = 0;
}
// Save initial NTP and TS values
iStartNPT = iActualPlaybackPosition;
iStartMediaDataTS = iAdjustedMediaDataTS;
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, iAdjustedMediaDataTS, iActualPlaybackPosition, 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, iAdjustedMediaDataTS, iActualPlaybackPosition, iStartNPT, iStartMediaDataTS));
}
break;
default:
{
HandleErrorBasedOnPlayerState();
cmdstatus = aNodeResp.GetCmdStatus();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aNodeResp.GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus, OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
return;
}
}
// Repositioning so reset the EOS flag for each active datapath
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackActive)
{
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"));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus);
}
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!"));
}
break;
case PVMFSuccess:
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() SetDataSourceDirection() successful. StartMediaTS %d ms, ActualPBPos %d ms",
iActualMediaDataTS, iActualPlaybackPosition));
//there's no adjustment to the media TS here.
iAdjustedMediaDataTS = iActualMediaDataTS;
iCurrentBeginPosition.iPosValue.millisec_value = iActualPlaybackPosition;
iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;
//Install the new direction and get the repositioning target.
UpdateDirection(iActualPlaybackPosition, iAdjustedMediaDataTS, 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:
{
HandleErrorBasedOnPlayerState();
cmdstatus = aNodeResp.GetCmdStatus();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aNodeResp.GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus, OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
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].iTrackActive)
{
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"));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus);
}
}
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
iPlaybackClock.Start();
// To get regular play status events
StartPlaybackStatusTimer();
}
else
{
// Initiate error handling
HandleErrorBasedOnPlayerState();
}
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));
// Report an error event here but do nothing to the playback
SendErrorEvent(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.
iAdjustedMediaDataTS = iActualMediaDataTS;
iCurrentBeginPosition.iPosValue.millisec_value = iActualPlaybackPosition;
iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;
//Install the new direction and get the repositioning target
UpdateDirection(iActualPlaybackPosition, iAdjustedMediaDataTS, 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].iTrackActive)
{
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));
// Report an error event
SendErrorEvent(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::HandleSourceNodeStart(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO,
(0, "PVPlayerEngine::HandleSourceNodeStart() Tick=%d", OsclTickCount::TickCount()));
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeStart() In"));
PVMFStatus cmdstatus = PVMFErrNotSupported;
switch (aNodeResp.GetCmdStatus())
{
case PVMFSuccess:
{
// Start the available datapaths
iNumPendingDatapathCmd = 0;
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackActive)
{
PVMFStatus retval = DoDatapathStart(iDatapathList[i], aNodeContext.iCmdId, aNodeContext.iCmdContext);
if (retval == PVMFSuccess)
{
++iNumPendingDatapathCmd;
cmdstatus = PVMFSuccess;
}
else
{
cmdstatus = retval;
break;
}
}
}
if (iNumPendingDatapathCmd == 0)
{
if (cmdstatus == PVMFErrNotSupported)
{
// There are no active datapaths. Assert.
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeStart() No datapath exists. Asserting"));
OSCL_ASSERT(false);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeStart() Report command as failed"));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFFailure);
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeStart() Report command as failed"));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus);
}
}
}
break;
default:
{
HandleErrorBasedOnPlayerState();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aNodeResp.GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, aNodeResp.GetCmdStatus(), OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
}
break;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeStart() Out"));
}
void PVPlayerEngine::HandleSinkNodeSkipMediaData(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
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"));
OSCL_ASSERT(iNumPendingNodeCmd > 0);
--iNumPendingNodeCmd;
if (aNodeResp.GetCmdStatus() != PVMFSuccess)
{
// Sink node report error with SkipMediaData()
HandleErrorBasedOnPlayerState();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aNodeResp.GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSinkFatal, puuid, nextmsg));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, aNodeResp.GetCmdStatus(), OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
return;
}
OSCL_ASSERT(iNumPendingSkipCompleteEvent > 0);
--iNumPendingSkipCompleteEvent;
if (iNumPendingNodeCmd == 0)
{
PVMFTimestamp targetNPT = iCurrentBeginPosition.iPosValue.millisec_value;
// Set the clock to the specified begin time
iPlaybackClock.Stop();
iPlaybackClock.SetStartTime32(iAdjustedMediaDataTS, OSCLCLOCK_MSEC);
if (!(iWatchDogTimer->IsBusy()))
{
PVMFTimestamp targetNPT = iCurrentBeginPosition.iPosValue.millisec_value;
iWatchDogTimer->Cancel();
if (iWatchDogTimerInterval > 0)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
(0, "PVPlayerEngine::HandleSinkNodeSkipMediaData() Setting WatchDogTimer for %d ms, TargetNPT=%d ActualNPT=%d",
iWatchDogTimerInterval, targetNPT, iActualPlaybackPosition));
iWatchDogTimer->setTimerDuration(iWatchDogTimerInterval);
iWatchDogTimer->Start();
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
(0, "PVPlayerEngine::HandleSinkNodeSkipMediaData() Skipping WatchDogTimer - Starting PlayBackClock"));
StartPlaybackClock();
}
}
// 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.
// iActualPlaybackPosition=iCurrentBeginPosition.iPosValue.millisec_value;
// Save the start NPT and TS
iStartNPT = iActualPlaybackPosition;
iStartMediaDataTS = iAdjustedMediaDataTS;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO,
(0, "PVPlayerEngine::HandleSinkNodeSkipMediaData() TargetNPT %d, StartNPT %d StartTS %d",
targetNPT, iStartNPT, iStartMediaDataTS));
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
(0, "PVPlayerEngine::HandleSinkNodeSkipMediaData() TargetNPT %d, StartNPT %d StartTS %d",
targetNPT, iStartNPT, iStartMediaDataTS));
SetEngineState(PVP_ENGINE_STATE_PREPARED);
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
StartPlaybackClock();
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() - PlayClock Started"));
}
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"));
if (aNodeResp.GetCmdStatus() != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() QueryDataSourcePosition failed. Assume position goes to requested position"));
iActualPlaybackPosition = iCurrentBeginPosition.iPosValue.millisec_value;
}
else
{
// Every thing is OK.. Calculate the iActualPlaybackPosition depensing upon nearest before and after syncPoints.
// For MPEG4 files
PVMFNodeCapability nodeCapability;
iSourceNode->GetCapability(nodeCapability);
PVMFFormatType * formatType = nodeCapability.iInputFormatCapability.begin();
bool mpeg4FormatType = false;
if (formatType != NULL)
{
switch (*formatType)
{
case PVMF_MPEG4FF:
mpeg4FormatType = true;
break;
default:
mpeg4FormatType = false;
break;
}
}
if (mpeg4FormatType)
{
CalculateActualPlaybackPosition();
}
}
// Determine the SetDataSourcePosition parameter based on query result and reposition settings
PVMFTimestamp requesttime = iCurrentBeginPosition.iPosValue.millisec_value;
bool seektosyncpt = true;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,
"PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback()"
"Requested NPT %d, Actual NPT %d", requesttime, iActualPlaybackPosition));
uint32 startOfSeekWindow = 0;
if (iCurrentBeginPosition.iPosValue.millisec_value > iSyncPointSeekWindow)
{
startOfSeekWindow = (iCurrentBeginPosition.iPosValue.millisec_value - iSyncPointSeekWindow);
}
uint32 endOfSeekWindow = iCurrentBeginPosition.iPosValue.millisec_value + 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 (iCurrentBeginPosition.iPosValue.millisec_value <= 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 (iCurrentBeginPosition.iPosValue.millisec_value > 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 actual seek point falls within the window
if ((iActualPlaybackPosition >= startOfSeekWindow) &&
(iActualPlaybackPosition <= endOfSeekWindow))
{
// Check for SFR
// In case if actual playback position
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0,
"PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() - "
"RequestedNPT(%d) ActualNPT(%d) is in the window (%d, %d), Seeking To %d",
requesttime, iActualPlaybackPosition, startOfSeekWindow, endOfSeekWindow, iActualPlaybackPosition));
requesttime = iActualPlaybackPosition;
}
else
{
// Check for SFR
// SFR means currplaybackpos < requestedpos
if (curpos.iPosValue.millisec_value < iCurrentBeginPosition.iPosValue.millisec_value)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0,
"PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() - "
"CurrNPT(%d) less than RequestedNPT(%d) Ignoring ActualNPT(%d) and the window (%d, %d), Doing SFR",
curpos.iPosValue.millisec_value, requesttime, iActualPlaybackPosition, 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) ActualNPT(%d) is outside the window (%d, %d), Seeking To %d Seek-To-SyncPt True",
requesttime, iActualPlaybackPosition, startOfSeekWindow, endOfSeekWindow, startOfSeekWindow));
seektosyncpt = true;
iActualPlaybackPosition = requesttime;
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0,
"PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() - "
"RequestedNPT(%d) ActualNPT(%d) is outside the window (%d, %d), Seeking To %d Seek-To-SyncPt False",
requesttime, iActualPlaybackPosition, startOfSeekWindow, endOfSeekWindow, startOfSeekWindow));
requesttime = startOfSeekWindow;
seektosyncpt = false;
iActualPlaybackPosition = 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, OSCLCLOCK_MSEC);
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;
iAdjustedMediaDataTS = (iCurrentBeginPosition.iPosValue.millisec_value - curpos.iPosValue.millisec_value) + clockcurpos;
iActualPlaybackPosition = requesttime;
iWatchDogTimerInterval = iCurrentBeginPosition.iPosValue.millisec_value - 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",
iActualPlaybackPosition, iActualMediaDataTS, iAdjustedMediaDataTS));
}
else
{
// Just continue playback from current position
iActualMediaDataTS = clockcurpos;
iAdjustedMediaDataTS = clockcurpos;
iActualPlaybackPosition = 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",
iActualPlaybackPosition, iActualMediaDataTS, iAdjustedMediaDataTS));
}
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));
// Report an error event here but do nothing to the playback
SendErrorEvent(retval, OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
errmsg = NULL;
}
}
else
{
// Do the source positioning
PVMFStatus retval = DoSourceNodeSetDataSourcePositionDuringPlayback(requesttime, seektosyncpt, 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));
// Report an error event here but do nothing to the playback
SendErrorEvent(aNodeResp.GetCmdStatus(), 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);
PVMFTimestamp targetNPT = iCurrentBeginPosition.iPosValue.millisec_value;
// 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 > targetNPT)
{
// curpos.iPosValue.millisec_value was passed as iActualPlaybackPosition 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 (IsEarlier(iSeekPointBeforeTargetNPT, targetNPT, 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 (IsEarlier(targetNPT, 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;
}
if (diffBetSeekPointAfterAndTarget < diffBetSeekPointBeforeAndTarget)
{
iActualPlaybackPosition = iSeekPointAfterTargetNPT;
}
else
{
if (iSeekPointBeforeTargetNPT < curpos.iPosValue.millisec_value && iForwardReposFlag)
{
iActualPlaybackPosition = iSeekPointAfterTargetNPT;
iForwardReposFlag = false;
}
else
{
iActualPlaybackPosition = iSeekPointBeforeTargetNPT;
iForwardReposFlag = false;
}
}
if (iBackwardReposFlag) // To avoid backwardlooping :: A flag to remember backward repositioning
{
iActualPlaybackPosition = iSeekPointBeforeTargetNPT;
iBackwardReposFlag = false;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,
"PVPlayerEngine::CalculateActualPlaybackPosition()"
"targetNPT %d Current NPT %d, Actual NPT %d, SeekPointBeforeTargetNPT %d, SeekPointAfterTargetNPT %d ",
targetNPT, curpos.iPosValue.millisec_value, iActualPlaybackPosition, 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)
{
// For non-fatal error, continue playback by resuming the clock
iPlaybackClock.Start();
// To get regular play status events
StartPlaybackStatusTimer();
}
else
{
// Initiate error handling
HandleErrorBasedOnPlayerState();
}
// Complete the SetPlaybackRange() command as notsupported / failed
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, aNodeResp.GetCmdStatus());
return;
}
if ((iCurrentBeginPosition.iMode != PVPPBPOS_MODE_END_OF_CURRENT_PLAY_ELEMENT) && (iCurrentBeginPosition.iMode != PVPPBPOS_MODE_END_OF_CURRENT_PLAY_SESSION))
{
uint32 targetNPT = iCurrentBeginPosition.iPosValue.millisec_value;
if (iCurrentBeginPosition.iPosUnit == PVPPBPOSUNIT_PLAYLIST)
{
iActualMediaDataTS = iDataSourcePosParams.iActualMediaDataTS;
iActualPlaybackPosition = iDataSourcePosParams.iActualNPT;
/* 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;
targetNPT = iCurrentBeginPosition.iPlayListPosValue.millisec_value;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePositionDuringPlayback() SetDataSourcePosition() successful. StartMediaTS %d ms, ActualPBPos %d ms",
iActualMediaDataTS, iActualPlaybackPosition));
if (iCurrentBeginPosition.iPosUnit == PVPPBPOSUNIT_PLAYLIST)
{
if (iCurrentBeginPosition.iPlayListPosValue.millisec_value >= iActualPlaybackPosition)
{
iWatchDogTimerInterval = iCurrentBeginPosition.iPlayListPosValue.millisec_value - iActualPlaybackPosition;
}
}
// Compute the difference between actualNPT and targetNPT before any adjustments
else if (iCurrentBeginPosition.iPosValue.millisec_value >= iActualPlaybackPosition)
{
iWatchDogTimerInterval = iCurrentBeginPosition.iPosValue.millisec_value - iActualPlaybackPosition;
}
//iCurrentBeginPosition.iPosUnit has served its purpose, it is ok if it is overwritten
if (iSkipToRequestedPosition && (iActualPlaybackPosition < targetNPT))
{
if (targetNPT - iActualPlaybackPosition >= SYNC_POINT_DIFF_THRESHOLD)
{
// Can't adjust the skip time back so use the returned values to skip to
iAdjustedMediaDataTS = iActualMediaDataTS;
iActualPlaybackPosition = targetNPT;
iWatchDogTimerInterval = 0;
}
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.
iAdjustedMediaDataTS = iActualMediaDataTS + (targetNPT - iActualPlaybackPosition);
// 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()
iActualPlaybackPosition = targetNPT;
}
iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;
}
else
{
// Can't adjust the skip time back so just use the returned values to skip to
iAdjustedMediaDataTS = iActualMediaDataTS;
iCurrentBeginPosition.iPosValue.millisec_value = iActualPlaybackPosition;
iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC;
iWatchDogTimerInterval = 0;
}
uint32 clockcurpos = 0;
bool tmpbool;
// Get current playback clock position
iPlaybackClock.GetCurrentTime32(clockcurpos, tmpbool, OSCLCLOCK_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, iAdjustedMediaDataTS, iActualPlaybackPosition, clockcurpos));
// Repositioning so reset the EOS flag for each active datapath
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackActive)
{
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 failed
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));
OSCL_UNUSED_ARG(aNodeResp);
OSCL_ASSERT(aNodeContext.iEngineDatapath != NULL);
OSCL_ASSERT(aNodeContext.iEngineDatapath->iTrackInfo != NULL);
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->iTrackActive && aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF && (aNodeResp.GetCmdStatus() == PVMFSuccess))
{
aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF->ClockStopped();
}
else
{
HandleErrorBasedOnPlayerState();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aNodeResp.GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSinkFatal, puuid, nextmsg));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, aNodeResp.GetCmdStatus(), OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
return;
}
OSCL_ASSERT(iNumPendingSkipCompleteEvent > 0);
--iNumPendingSkipCompleteEvent;
OSCL_ASSERT(iNumPendingNodeCmd > 0);
--iNumPendingNodeCmd;
if (iNumPendingNodeCmd == 0)
{
PVMFTimestamp targetNPT = iCurrentBeginPosition.iPosValue.millisec_value;
// Stop and set to the specified reposition time
iPlaybackClock.Stop();
iPlaybackClock.SetStartTime32(iAdjustedMediaDataTS, OSCLCLOCK_MSEC);
if (!(iWatchDogTimer->IsBusy()))
{
iWatchDogTimer->Cancel();
if (iWatchDogTimerInterval > 0)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
(0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() Setting WatchDogTimer for %d ms, TargetNPT=%d ActualNPT=%d",
iWatchDogTimerInterval, targetNPT, iActualPlaybackPosition));
iWatchDogTimer->setTimerDuration(iWatchDogTimerInterval);
iWatchDogTimer->Start();
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
(0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() Skipping WatchDogTimer - Starting PlayBackClock"));
StartPlaybackClock();
}
}
// 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.
// iActualPlaybackPosition=iCurrentBeginPosition.iPosValue.millisec_value;
//clear the pending direction change NPT.
iChangeDirectionNPT.iIndeterminate = true;
// Save the start NPT and TS
iStartNPT = iActualPlaybackPosition;
iStartMediaDataTS = iAdjustedMediaDataTS;
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO,
(0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() TargetNPT %d, ActualNPT %d StartTS %d",
targetNPT, iStartNPT, iStartMediaDataTS));
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
(0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() TargetNPT %d, ActualNPT %d StartTS %d",
targetNPT, iStartNPT, iStartMediaDataTS));
// reset the ResumeAfterRepos boolean here
iResumeAfterReposition = false;
// Complete the SetPlaybackRange(), SetPlaybackRange(), or Resume() command as success
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess);
// Send info event that playback from new position has started
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* infomsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoPlaybackFromBeginTime, puuid, NULL));
SendInformationalEvent(PVMFInfoPositionStatus, OSCL_STATIC_CAST(PVInterface*, infomsg));
infomsg->removeRef();
if ((iNumPendingSkipCompleteEvent == 0) && (iNumPVMFInfoStartOfDataPending == 0))
{
if (iWatchDogTimer->IsBusy())
{
iWatchDogTimer->Cancel();
}
// we have received all the bos event for
// playback hasnt started yet
StartPlaybackClock();
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() - 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:
{
// Pause command is complete
SetEngineState(PVP_ENGINE_STATE_PAUSED);
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess);
}
break;
default:
{
HandleErrorBasedOnPlayerState();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aNodeResp.GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, aNodeResp.GetCmdStatus(), OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
}
break;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodePause() Out"));
}
void PVPlayerEngine::HandleSourceNodeResume(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeResume() In"));
PVMFStatus cmdstatus = PVMFErrNotSupported;
switch (aNodeResp.GetCmdStatus())
{
case PVMFSuccess:
{
// Issue start to all active datapaths
iNumPendingDatapathCmd = 0;
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackActive)
{
PVMFStatus retval = DoDatapathStart(iDatapathList[i], aNodeContext.iCmdId, aNodeContext.iCmdContext);
if (retval == PVMFSuccess)
{
++iNumPendingDatapathCmd;
cmdstatus = PVMFSuccess;
}
else
{
cmdstatus = retval;
break;
}
}
}
if (iNumPendingDatapathCmd == 0)
{
if (cmdstatus == PVMFErrNotSupported)
{
// No datapath so error out
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeResume() No datapath exists. Asserting"));
OSCL_ASSERT(false);
HandleErrorBasedOnPlayerState();
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeResume() Report command as failed"));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFFailure);
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeResume() Report command as failed"));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus);
}
}
}
break;
default:
{
HandleErrorBasedOnPlayerState();
cmdstatus = aNodeResp.GetCmdStatus();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aNodeResp.GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus, OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
}
break;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeResume() Out"));
}
void PVPlayerEngine::HandleSourceNodeStop(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeStop() In"));
PVMFStatus cmdstatus = PVMFErrNotSupported;
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].iTrackActive)
{
PVMFStatus retval = DoDatapathTeardown(iDatapathList[i], aNodeContext.iCmdId, aNodeContext.iCmdContext);
if (retval == PVMFSuccess)
{
++iNumPendingDatapathCmd;
cmdstatus = PVMFSuccess;
}
else
{
cmdstatus = retval;
break;
}
}
}
}
if (iNumPendingDatapathCmd == 0)
{
if (cmdstatus == PVMFErrNotSupported)
{
// No active datapath to shutdown so stop is complete but assert
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeStop() No datapath exists. Asserting"));
OSCL_ASSERT(false);
SetEngineState(PVP_ENGINE_STATE_INITIALIZED);
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess);
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeStop() Report command as failed"));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus);
}
}
break;
default:
{
HandleErrorBasedOnPlayerState();
cmdstatus = aNodeResp.GetCmdStatus();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aNodeResp.GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus, OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
}
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"));
if (aNodeResp.GetCmdStatus() == PVMFSuccess)
{
SetEngineState(PVP_ENGINE_STATE_IDLE);
// we need to delete src node & cmdComplete from engine Run while CMD_Reset is still pending:
OSCL_ASSERT(iCommandCompleteInEngineAOPending == false);
iCommandCompleteInEngineAOPending = true;
RunIfNotReady();
}
else
{
HandleErrorBasedOnPlayerState();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aNodeResp.GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceShutdown, puuid, nextmsg));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, aNodeResp.GetCmdStatus(), OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
return;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeReset() Out"));
}
void PVPlayerEngine::HandleSinkNodePause(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
OSCL_ASSERT(aNodeContext.iEngineDatapath != NULL);
OSCL_ASSERT(aNodeContext.iEngineDatapath->iTrackInfo != NULL);
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
OSCL_ASSERT(iNumPendingDatapathCmd > 0);
--iNumPendingDatapathCmd;
if (aNodeResp.GetCmdStatus() != PVMFSuccess)
{
HandleErrorBasedOnPlayerState();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aNodeResp.GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSinkFatal, puuid, nextmsg));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, aNodeResp.GetCmdStatus(), OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
// Cancel any pending node/datapath commands
DoCancelDueToError();
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)
{
OSCL_ASSERT(aNodeContext.iEngineDatapath != NULL);
OSCL_ASSERT(aNodeContext.iEngineDatapath->iTrackInfo != NULL);
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
OSCL_ASSERT(iNumPendingDatapathCmd > 0);
--iNumPendingDatapathCmd;
if (aNodeResp.GetCmdStatus() != PVMFSuccess)
{
HandleErrorBasedOnPlayerState();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aNodeResp.GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSinkFatal, puuid, nextmsg));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, aNodeResp.GetCmdStatus(), OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
// Cancel any pending node/datapath commands
DoCancelDueToError();
return;
}
if (iNumPendingDatapathCmd == 0)
{
// Auto-resume is complete
// Resume the playback clock
iPlaybackClock.Start();
// To get regular play status events
StartPlaybackStatusTimer();
// Notify data sinks that clock has started
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackActive && 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::HandleSourceNodeStopDueToError(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeStopDueToError() In"));
if (aNodeResp.GetCmdStatus() == PVMFErrInvalidState &&
iSourceNode->GetState() == EPVMFNodeInitialized &&
iErrorOccurredDuringErrorHandling == false)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeStopDueToError() Source node is already stopped"));
}
else if (aNodeResp.GetCmdStatus() != PVMFSuccess && iErrorOccurredDuringErrorHandling == false)
{
// Issue a reset command
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeStopDueToError() Stop on source node failed so issue reset command"));
iErrorOccurredDuringErrorHandling = true;
}
// Initiate teardown or reset sequence for each active datapath
iNumPendingDatapathCmd = 0;
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackActive == true)
{
PVMFStatus retcode = DoDatapathTeardownDueToError(iDatapathList[i], aNodeContext.iCmdId, aNodeContext.iCmdContext);
if (retcode == PVMFSuccess)
{
++iNumPendingDatapathCmd;
}
else
{
retcode = DoDatapathResetDueToError(iDatapathList[i], aNodeContext.iCmdId, aNodeContext.iCmdContext);
if (retcode == PVMFSuccess)
{
++iNumPendingDatapathCmd;
}
}
}
}
if (iNumPendingDatapathCmd == 0)
{
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
// make copy of context data and reschedule for deletion
PVPlayerEngineContext* newContext = AllocateEngineContext(
&(iDatapathList[i]), NULL, NULL, 0, NULL, 0);
AddCommandToQueue(PVP_ENGINE_COMMAND_DATAPATH_DELETE, newContext, NULL, NULL, false);
iNumPendingDatapathCmd++; // datapathdelete pending
}
if (iNumPendingDatapathCmd == 0)
{
OSCL_ASSERT(iDatapathList.empty());
// reset source node, usually called by datapathDelete but since there are no datapaths..
if (iErrorOccurredDuringErrorHandling)
{
AddCommandToQueue(PVP_ENGINE_COMMAND_RESET_DUE_TO_ERROR, NULL, NULL, NULL, false);
}
}
// done with STOP_DUE_TO_ERROR, clear current Cmd so that either DatapathDelete or ResetDueToError get run
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext,
iErrorOccurredDuringErrorHandling ? PVMFFailure : PVMFSuccess);
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeStopDueToError() Out"));
}
void PVPlayerEngine::HandleSourceNodeResetDueToError(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeResetDueToError() In"));
if (aNodeResp.GetCmdStatus() == PVMFSuccess)
{
SetEngineState(PVP_ENGINE_STATE_IDLE);
// we need to delete src node & cmdComplete from engine Run while CMD_Reset_DUE_TO_ERROR is still pending:
OSCL_ASSERT(iCommandCompleteInEngineAOPending == false);
iCommandCompleteInEngineAOPending = true;
RunIfNotReady();
}
else
{
// Error occurred for Reset() command but complete it and issue a cleanup command
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeResetDueToError() Reset on source node failed so issue cleanup command"));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFFailure);
SetEngineState(PVP_ENGINE_STATE_ERROR);
AddCommandToQueue(PVP_ENGINE_COMMAND_CLEANUP_DUE_TO_ERROR, NULL, NULL, NULL, false);
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeResetDueToError() Out"));
}
void PVPlayerEngine::HandleDatapathPrepare(PVPlayerEngineContext& aDatapathContext, PVMFStatus aDatapathStatus, PVMFCmdResp* aCmdResp)
{
OSCL_ASSERT(aDatapathContext.iEngineDatapath != NULL);
OSCL_ASSERT(aDatapathContext.iEngineDatapath->iTrackInfo != NULL);
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
OSCL_ASSERT(iNumPendingDatapathCmd > 0);
--iNumPendingDatapathCmd;
if (aDatapathStatus != PVMFSuccess)
{
HandleErrorBasedOnPlayerState();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aCmdResp)
{
if (aCmdResp->GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aCmdResp->GetEventExtensionInterface()));
}
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathInit, puuid, nextmsg));
EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, aDatapathStatus, OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
// Cancel any pending node/datapath commands
DoCancelDueToError();
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"));
EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, cmdstatus);
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathPrepare() Out"));
}
void PVPlayerEngine::HandleDatapathStart(PVPlayerEngineContext& aDatapathContext, PVMFStatus aDatapathStatus, PVMFCmdResp* aCmdResp)
{
OSCL_ASSERT(aDatapathContext.iEngineDatapath != NULL);
OSCL_ASSERT(aDatapathContext.iEngineDatapath->iTrackInfo != NULL);
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
OSCL_ASSERT(iNumPendingDatapathCmd > 0);
--iNumPendingDatapathCmd;
if (aDatapathStatus != PVMFSuccess)
{
HandleErrorBasedOnPlayerState();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aCmdResp)
{
if (aCmdResp->GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aCmdResp->GetEventExtensionInterface()));
}
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathFatal, puuid, nextmsg));
EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, aDatapathStatus, OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
// Cancel any pending node/datapath commands
DoCancelDueToError();
return;
}
if (iNumPendingDatapathCmd == 0)
{
// Skip some media data in sink node if necessary
PVMFStatus cmdstatus = DoSinkNodeSkipMediaData(aDatapathContext.iCmdId, aDatapathContext.iCmdContext);
if (cmdstatus != PVMFSuccess)
{
// No skipping so complete the commmand
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathStart() Skip of sink node failed, but report command as completed"));
SetEngineState(PVP_ENGINE_STATE_PREPARED);
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)
{
OSCL_ASSERT(aDatapathContext.iEngineDatapath != NULL);
OSCL_ASSERT(aDatapathContext.iEngineDatapath->iTrackInfo != NULL);
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
OSCL_ASSERT(iNumPendingDatapathCmd > 0);
--iNumPendingDatapathCmd;
if (aDatapathStatus != PVMFSuccess)
{
HandleErrorBasedOnPlayerState();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aCmdResp)
{
if (aCmdResp->GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aCmdResp->GetEventExtensionInterface()));
}
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathFatal, puuid, nextmsg));
EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, aDatapathStatus, OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
// Cancel any pending node/datapath commands
DoCancelDueToError();
return;
}
if (iNumPendingDatapathCmd == 0)
{
// Continue on by pauseing the source node
PVMFStatus cmdstatus = DoSourceNodePause(aDatapathContext.iCmdId, aDatapathContext.iCmdContext);
if (cmdstatus != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathPause() Report command as failed"));
EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, cmdstatus);
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathPause() Out"));
}
void PVPlayerEngine::HandleDatapathResume(PVPlayerEngineContext& aDatapathContext, PVMFStatus aDatapathStatus, PVMFCmdResp* aCmdResp)
{
OSCL_ASSERT(aDatapathContext.iEngineDatapath != NULL);
OSCL_ASSERT(aDatapathContext.iEngineDatapath->iTrackInfo != NULL);
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
OSCL_ASSERT(iNumPendingDatapathCmd > 0);
--iNumPendingDatapathCmd;
if (aDatapathStatus != PVMFSuccess)
{
HandleErrorBasedOnPlayerState();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aCmdResp)
{
if (aCmdResp->GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aCmdResp->GetEventExtensionInterface()));
}
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathFatal, puuid, nextmsg));
EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, aDatapathStatus, OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
// Cancel any pending node/datapath commands
DoCancelDueToError();
return;
}
if (iNumPendingDatapathCmd == 0)
{
if (iChangePlaybackPositionWhenResuming || iChangePlaybackDirectionWhenResuming)
{
iResumeAfterReposition = true;
}
if (!iResumeAfterReposition)
{
// Resume the playback clock - only if we have come out of any previous auto pause, if any
if (iPlaybackClock.GetState() == OsclClock::PAUSED)
{
iPlaybackClock.Start();
// To get regular play status events
StartPlaybackStatusTimer();
// Notify all sink nodes that have sync control IF that clock has started
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackActive && 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);
if (iChangePlaybackPositionWhenResuming || iChangePlaybackDirectionWhenResuming)
{
iChangePlaybackPositionWhenResuming = false;
iChangePlaybackDirectionWhenResuming = false;
iResumeAfterReposition = true;
PVMFStatus retval = DoSinkNodeSkipMediaDataDuringPlayback(aDatapathContext.iCmdId, aDatapathContext.iCmdContext);
if (retval != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathResume() 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 Resume() command as failed
EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, retval, OSCL_STATIC_CAST(PVInterface*, errmsg));
// Report an error event
SendErrorEvent(retval, OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
errmsg = NULL;
}
return;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathResume() Report command as completed"));
EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, PVMFSuccess);
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathResume() Out"));
}
void PVPlayerEngine::HandleDatapathStop(PVPlayerEngineContext& aDatapathContext, PVMFStatus aDatapathStatus, PVMFCmdResp* aCmdResp)
{
OSCL_ASSERT(aDatapathContext.iEngineDatapath != NULL);
OSCL_ASSERT(aDatapathContext.iEngineDatapath->iTrackInfo != NULL);
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
OSCL_ASSERT(iNumPendingDatapathCmd > 0);
--iNumPendingDatapathCmd;
if (aDatapathStatus != PVMFSuccess)
{
HandleErrorBasedOnPlayerState();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aCmdResp)
{
if (aCmdResp->GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aCmdResp->GetEventExtensionInterface()));
}
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathFatal, puuid, nextmsg));
EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, aDatapathStatus, OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
// Cancel any pending node/datapath commands
DoCancelDueToError();
return;
}
if (iNumPendingDatapathCmd == 0)
{
// Continue on by stopping the source node
PVMFStatus cmdstatus = DoSourceNodeStop(aDatapathContext.iCmdId, aDatapathContext.iCmdContext);
if (cmdstatus != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathStop() Report command as failed"));
EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, cmdstatus);
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathStop() Out"));
}
void PVPlayerEngine::HandleDatapathTeardown(PVPlayerEngineContext& aDatapathContext, PVMFStatus aDatapathStatus, PVMFCmdResp* aCmdResp)
{
OSCL_ASSERT(aDatapathContext.iEngineDatapath != NULL);
OSCL_ASSERT(aDatapathContext.iEngineDatapath->iTrackInfo != NULL);
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
OSCL_ASSERT(aDatapathContext.iEngineDatapath != NULL);
cmdstatus = DoDatapathReset(*(aDatapathContext.iEngineDatapath), aDatapathContext.iCmdId, aDatapathContext.iCmdContext);
break;
default:
{
HandleErrorBasedOnPlayerState();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aCmdResp)
{
if (aCmdResp->GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aCmdResp->GetEventExtensionInterface()));
}
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathShutdown, puuid, nextmsg));
EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, aDatapathStatus, OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
// Cancel any pending node/datapath commands
DoCancelDueToError();
return;
}
}
if (cmdstatus != PVMFSuccess)
{
HandleErrorBasedOnPlayerState();
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathTeardown() Report command as failed"));
EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, cmdstatus);
// Cancel any pending node/datapath commands
DoCancelDueToError();
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleVideoDatapathTeardown() Out"));
}
void PVPlayerEngine::HandleDatapathReset(PVPlayerEngineContext& aDatapathContext, PVMFStatus aDatapathStatus, PVMFCmdResp* aCmdResp)
{
OSCL_ASSERT(aDatapathContext.iEngineDatapath != NULL);
OSCL_ASSERT(aDatapathContext.iEngineDatapath->iTrackInfo != NULL);
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
OSCL_ASSERT(iNumPendingDatapathCmd > 0);
--iNumPendingDatapathCmd;
if (aDatapathStatus != PVMFSuccess)
{
HandleErrorBasedOnPlayerState();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aCmdResp)
{
if (aCmdResp->GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aCmdResp->GetEventExtensionInterface()));
}
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathShutdown, puuid, nextmsg));
EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, aDatapathStatus, OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
// Cancel any pending node/datapath commands
DoCancelDueToError();
return;
}
else
{
// Reset for this datapath is complete
OSCL_ASSERT(aDatapathContext.iEngineDatapath != NULL);
DoEngineDatapathTeardown(*(aDatapathContext.iEngineDatapath));
}
if (iNumPendingDatapathCmd == 0)
{
// Stop is complete
SetEngineState(PVP_ENGINE_STATE_INITIALIZED);
EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, PVMFSuccess);
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathReset() Out"));
}
void PVPlayerEngine::HandleDatapathStopDueToError(PVPlayerEngineContext& aDatapathContext, PVMFStatus aDatapathStatus, PVMFCmdResp* /*aCmdResp*/)
{
OSCL_ASSERT(aDatapathContext.iEngineDatapath != NULL);
OSCL_ASSERT(aDatapathContext.iEngineDatapath->iTrackInfo != NULL);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathStopDueToError() In %s", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr()));
// Decrement the counter for pending datapath cmds
OSCL_ASSERT(iNumPendingDatapathCmd > 0);
--iNumPendingDatapathCmd;
if (aDatapathStatus != PVMFSuccess && iErrorOccurredDuringErrorHandling == false)
{
// Issue a reset command
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathStopDueToError() Stop on datapath failed so issue reset command"));
iErrorOccurredDuringErrorHandling = true;
}
PVMFStatus cmdstatus = PVMFFailure;
if (iNumPendingDatapathCmd == 0)
{
// Trying stopping the source node
cmdstatus = DoSourceNodeStopDueToError(aDatapathContext.iCmdId, aDatapathContext.iCmdContext);
if (cmdstatus != PVMFSuccess)
{
// Try starting teardown or reset sequence for each active datapath
iNumPendingDatapathCmd = 0;
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
if (iDatapathList[i].iTrackActive == true)
{
PVMFStatus retcode = DoDatapathTeardownDueToError(iDatapathList[i], aDatapathContext.iCmdId, aDatapathContext.iCmdContext);
if (retcode == PVMFSuccess)
{
++iNumPendingDatapathCmd;
}
else
{
retcode = DoDatapathResetDueToError(iDatapathList[i], aDatapathContext.iCmdId, aDatapathContext.iCmdContext);
if (retcode == PVMFSuccess)
{
++iNumPendingDatapathCmd;
}
}
}
}
if (iNumPendingDatapathCmd == 0)
{
// Nothing initiated so just shutdown
SetEngineState(PVP_ENGINE_STATE_INITIALIZED);
// Clean up the datapaths
for (uint32 i = 0; i < iDatapathList.size(); ++i)
{
DoEngineDatapathCleanup(iDatapathList[i]);
}
iDatapathList.clear();
if (iErrorOccurredDuringErrorHandling)
{
EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, PVMFFailure);
}
else
{
EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, PVMFSuccess);
}
}
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathStopDueToError() Out"));
}
void PVPlayerEngine::HandleDatapathTeardownDueToError(PVPlayerEngineContext& aDatapathContext, PVMFStatus aDatapathStatus, PVMFCmdResp* /*aCmdResp*/)
{
OSCL_ASSERT(aDatapathContext.iEngineDatapath != NULL);
OSCL_ASSERT(aDatapathContext.iEngineDatapath->iTrackInfo != NULL);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathTeardownDueToError() In %s", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr()));
if (aDatapathStatus != PVMFSuccess && iErrorOccurredDuringErrorHandling == false)
{
// Issue a reset command
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathTeardownDueToError() Teardown on datapath failed so issue reset command"));
iErrorOccurredDuringErrorHandling = true;
}
PVMFStatus cmdstatus = PVMFFailure;
// Try resetting this datapath
OSCL_ASSERT(aDatapathContext.iEngineDatapath);
cmdstatus = DoDatapathResetDueToError(*(aDatapathContext.iEngineDatapath), aDatapathContext.iCmdId, aDatapathContext.iCmdContext);
if (cmdstatus != PVMFSuccess)
{
// Couldn't continue with reset of this datapath so decrement the pending datapath cmd counter
--iNumPendingDatapathCmd;
if (iNumPendingDatapathCmd == 0)
{
// make copy of context data and reschedule for deletion
PVPlayerEngineContext* newContext = AllocateEngineContext(
aDatapathContext.iEngineDatapath, NULL, NULL, 0, NULL, 0);
AddCommandToQueue(PVP_ENGINE_COMMAND_DATAPATH_DELETE, newContext, NULL, NULL, false);
iNumPendingDatapathCmd++; // datapathdelete pending
// a delete cmd has been added to the queue, but it can only be processed once current cmd is completed:
// cmdId is shared by multiple datapath commands. if we have not sent confirmation previously do now
if (iCurrentCmd.size() == 1 && iCurrentCmd[0].GetCmdId() == aDatapathContext.iCmdId)
{
EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext,
iErrorOccurredDuringErrorHandling ? PVMFFailure : PVMFSuccess);
}
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathTeardownDueToError() Out"));
}
// schedule async deletion of aDatapathContext.iEngineDatapath
void PVPlayerEngine::HandleDatapathResetDueToError(PVPlayerEngineContext& aContext, PVMFStatus aDatapathStatus, PVMFCmdResp* /*aCmdResp*/)
{
OSCL_ASSERT(aContext.iEngineDatapath != NULL);
OSCL_ASSERT(aContext.iEngineDatapath->iTrackInfo != NULL);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathResetDueToError() In %s", aContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr()));
// make copy of context data and reschedule for deletion
PVPlayerEngineContext* newContext = AllocateEngineContext(
aContext.iEngineDatapath, NULL, NULL, 0, NULL, 0);
AddCommandToQueue(PVP_ENGINE_COMMAND_DATAPATH_DELETE, newContext, NULL, NULL, false);
if (aDatapathStatus != PVMFSuccess && iErrorOccurredDuringErrorHandling == false)
{
// Issue a reset command if not done so previously
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathResetDueToError() Reset on datapath failed so issue reset command"));
iErrorOccurredDuringErrorHandling = true;
}
// a delete cmd has been added to the queue, but it can only be processed once current cmd is completed:
// cmdId is shared by multiple datapath commands. if we have not sent confirmation previously do now
if (iCurrentCmd.size() == 1 && iCurrentCmd[0].GetCmdId() == aContext.iCmdId)
{
EngineCommandCompleted(aContext.iCmdId, aContext.iCmdContext,
iErrorOccurredDuringErrorHandling ? PVMFFailure : PVMFSuccess);
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathResetDueToError() Out"));
}
// delete aDatapathContext.iEngineDatapath
PVMFStatus PVPlayerEngine::DoDatapathDelete(PVPlayerEngineCommand &aCmd)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathDelete() In"));
PVPlayerEngineContext* aDatapathContext = (PVPlayerEngineContext*) aCmd.GetContext();
OSCL_ASSERT(aDatapathContext != NULL);
OSCL_ASSERT(aDatapathContext->iEngineDatapath != NULL);
if (aDatapathContext->iEngineDatapath->iTrackActive)
{
OSCL_ASSERT(aDatapathContext->iEngineDatapath->iTrackInfo != NULL);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathDelete() In %s", aDatapathContext->iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr()));
}
// Clean up objects associated with the current datapath
DoEngineDatapathCleanup(*(aDatapathContext->iEngineDatapath));
OSCL_ASSERT(iNumPendingDatapathCmd > 0);
--iNumPendingDatapathCmd;
// all datapath resets have been handled
if (iNumPendingDatapathCmd == 0)
{
iDatapathList.clear();
// reset source node
AddCommandToQueue(PVP_ENGINE_COMMAND_RESET_DUE_TO_ERROR, NULL, NULL, NULL, false);
}
// delete request handled
EngineCommandCompleted(aCmd.GetCmdId(), aDatapathContext, PVMFSuccess);
FreeEngineContext(aDatapathContext);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathDelete() Out"));
return PVMFSuccess;
}
void PVPlayerEngine::HandleCPMPluginQueryCapConfigIF(const PVMFCmdResp& aCmdResp)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleCPMPluginQueryCapConfigIF() In"));
if (aCmdResp.GetCmdStatus() == PVMFSuccess)
{
// CapConfig interface available. Proceed to set user-agent
DoCPMPluginSetUserAgentHeader(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext());
}
else
{
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aCmdResp.GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aCmdResp.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
iCommandCompleteInEngineAOErrMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrCPMPlugin, puuid, nextmsg));
// There shouldn't be any other command pending to complete in engine's AO
OSCL_ASSERT(iCommandCompleteInEngineAOPending == false);
iCommandCompleteInEngineAOPending = true;
iCommandCompleteInEngineAOCmdStatus = aCmdResp.GetCmdStatus();
}
// Proceed to acquire licence
// if CapConfig UUID is not supported
PVMFStatus retval = DoCPMPluginGetLicense(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext());
if (retval != PVMFSuccess)
{
// There shouldn't be any other command pending to complete in engine's AO
OSCL_ASSERT(iCommandCompleteInEngineAOPending == false);
iCommandCompleteInEngineAOPending = true;
iCommandCompleteInEngineAOCmdStatus = retval;
iCommandCompleteInEngineAOErrMsg = NULL;
}
if (iCommandCompleteInEngineAOPending)
{
if (IsBusy())
{
Cancel();
}
RunIfNotReady();
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleCPMPluginQueryCapConfigIF() Out"));
}
void PVPlayerEngine::HandleCPMPluginQueryLicenseIF(const PVMFCmdResp& aCmdResp)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleCPMPluginQueryLicenseIF() In"));
if (aCmdResp.GetCmdStatus() == PVMFSuccess)
{
//
// License interface available. Proceed to query for CapConfig interface
iCPMPlugin->QueryInterface(iCPMPluginSessionId, PVMI_CAPABILITY_AND_CONFIG_PVUUID, (PVInterface*&)iCPMPluginCapConfigIf, NULL);
if (NULL == iCPMPluginCapConfigIf)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleCPMPluginQueryLicenseIF queryInterface on CPMPluginCapConfigIf returned error"));
}
iCPMPluginCommand = PVP_CMD_CPMQueryCapConfigIF;
}
else
{
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aCmdResp.GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aCmdResp.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
iCommandCompleteInEngineAOErrMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrCPMPlugin, puuid, nextmsg));
// There shouldn't be any other command pending to complete in engine's AO
OSCL_ASSERT(iCommandCompleteInEngineAOPending == false);
iCommandCompleteInEngineAOPending = true;
iCommandCompleteInEngineAOCmdStatus = aCmdResp.GetCmdStatus();
}
if (iCommandCompleteInEngineAOPending)
{
if (IsBusy())
{
Cancel();
}
RunIfNotReady();
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleCPMPluginQueryLicenseIF() Out"));
}
void PVPlayerEngine::HandleCPMPluginGetLicense(const PVMFCmdResp& aCmdResp)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleCPMPluginGetLicense() In"));
if (aCmdResp.GetCmdStatus() == PVMFSuccess)
{
// License acquisition is successful.
// There shouldn't be any other command pending to complete in engine's AO
OSCL_ASSERT(iCommandCompleteInEngineAOPending == false);
iCommandCompleteInEngineAOPending = true;
iCommandCompleteInEngineAOCmdStatus = PVMFSuccess;
iCommandCompleteInEngineAOErrMsg = NULL;
}
else
{
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aCmdResp.GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aCmdResp.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
iCommandCompleteInEngineAOErrMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrCPMPlugin, puuid, nextmsg));
// There shouldn't be any other command pending to complete in engine's AO
OSCL_ASSERT(iCommandCompleteInEngineAOPending == false);
iCommandCompleteInEngineAOPending = true;
iCommandCompleteInEngineAOCmdStatus = aCmdResp.GetCmdStatus();
}
if (IsBusy())
{
Cancel();
}
RunIfNotReady();
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleCPMPluginGetLicense() Out"));
}
void PVPlayerEngine::HandleSourceNodeGetLicense(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeGetLicense() In"));
switch (aNodeResp.GetCmdStatus())
{
case PVMFSuccess:
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess);
break;
case PVMFErrCancelled:
default:
{
// report command complete
PVMFStatus cmdstatus = aNodeResp.GetCmdStatus();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aNodeResp.GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSource, puuid, nextmsg));
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus, OSCL_STATIC_CAST(PVInterface*, errmsg));
errmsg->removeRef();
}
break;
}
/* Set CancelAcquireLicense cmd in current cmd */
if (!iCmdToDlaCancel.empty())
{
iCurrentCmd.push_front(iCmdToDlaCancel[0]);
iCmdToDlaCancel.clear();
}
}
void PVPlayerEngine::HandleSourceNodeCancelGetLicense(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeCancelGetLicense() In"));
switch (aNodeResp.GetCmdStatus())
{
case PVMFSuccess:
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess);
break;
default:
{
/* report command complete */
PVMFStatus cmdstatus = aNodeResp.GetCmdStatus();
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aNodeResp.GetEventExtensionInterface())
{
nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSource, puuid, nextmsg));
if (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_CHAR
|| iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_WCHAR)
{
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(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus, OSCL_STATIC_CAST(PVInterface*, errmsg));
iCurrentCmd.push_front(currentcmd);
iCmdToDlaCancel.erase(iCmdToDlaCancel.begin());
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeCancelGetLicense() ASSERT"));
OSCL_ASSERT(false);
}
}
else if (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_CANCEL_ACQUIRE_LICENSE)
{
EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus, OSCL_STATIC_CAST(PVInterface*, errmsg));
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeCancelGetLicense() ASSERT"));
OSCL_ASSERT(false);
}
errmsg->removeRef();
}
break;
}
}
void PVPlayerEngine::HandleSourceNodeErrorEvent(const PVMFAsyncEvent& aEvent)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeErrorEvent() In"));
PVMFEventType event = aEvent.GetEventType();
switch (event)
{
case PVMFErrCorrupt:
case PVMFErrOverflow:
case PVMFErrResource:
case PVMFErrProcessing:
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeErrorEvent() Sending PVPlayerErrSourceMediaData for error event %d", event));
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aEvent.GetEventExtensionInterface() != NULL)
{
nextmsg = GetErrorInfoMessageInterface(*(aEvent.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceMediaData, puuid, nextmsg));
if (HandleAsyncErrorBasedOnPlayerState(event, errmsg) == true)
{
SendErrorEvent(event, OSCL_STATIC_CAST(PVInterface*, errmsg), aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
}
errmsg->removeRef();
errmsg = NULL;
}
break;
case PVMFErrUnderflow:
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeErrorEvent() Sending PVPlayerErrSourceMediaDataUnavailable for error event %d", event));
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aEvent.GetEventExtensionInterface() != NULL)
{
nextmsg = GetErrorInfoMessageInterface(*(aEvent.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceMediaDataUnavailable, puuid, nextmsg));
if (HandleAsyncErrorBasedOnPlayerState(event, errmsg) == true)
{
SendErrorEvent(event, OSCL_STATIC_CAST(PVInterface*, errmsg), aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
}
errmsg->removeRef();
errmsg = NULL;
}
break;
case PVMFErrNoResources:
case PVMFErrResourceConfiguration:
case PVMFErrTimeout:
case PVMFErrNoMemory:
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeErrorEvent() Sending PVPlayerErrSourceFatal for error event %d", event));
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aEvent.GetEventExtensionInterface() != NULL)
{
nextmsg = GetErrorInfoMessageInterface(*(aEvent.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg));
if (HandleAsyncErrorBasedOnPlayerState(event, errmsg) == true)
{
SendErrorEvent(event, OSCL_STATIC_CAST(PVInterface*, errmsg), aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
}
errmsg->removeRef();
errmsg = NULL;
}
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;
}
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_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeErrorEvent() In"));
OSCL_UNUSED_ARG(aDatapathIndex);
PVMFEventType event = aEvent.GetEventType();
switch (event)
{
case PVMFErrCorrupt:
case PVMFErrOverflow:
case PVMFErrUnderflow:
case PVMFErrProcessing:
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeErrorEvent() Sending PVPlayerErrDatapathMediaData for error event %d", event));
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aEvent.GetEventExtensionInterface() != NULL)
{
nextmsg = GetErrorInfoMessageInterface(*(aEvent.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathMediaData, puuid, nextmsg));
if (HandleAsyncErrorBasedOnPlayerState(event, errmsg) == true)
{
SendErrorEvent(event, OSCL_STATIC_CAST(PVInterface*, errmsg), aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
}
errmsg->removeRef();
errmsg = NULL;
}
break;
case PVMFErrTimeout:
case PVMFErrNoResources:
case PVMFErrResourceConfiguration:
case PVMFErrResource:
case PVMFErrNoMemory:
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeErrorEvent() Sending PVPlayerErrDatapathFatal for error event %d", event));
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aEvent.GetEventExtensionInterface() != NULL)
{
nextmsg = GetErrorInfoMessageInterface(*(aEvent.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathFatal, puuid, nextmsg));
if (HandleAsyncErrorBasedOnPlayerState(event, errmsg) == true)
{
SendErrorEvent(event, OSCL_STATIC_CAST(PVInterface*, errmsg), aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
}
errmsg->removeRef();
errmsg = NULL;
}
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;
}
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_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeErrorEvent() In"));
OSCL_UNUSED_ARG(aDatapathIndex);
PVMFEventType event = aEvent.GetEventType();
switch (event)
{
case PVMFErrCorrupt:
case PVMFErrOverflow:
case PVMFErrUnderflow:
case PVMFErrProcessing:
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeErrorEvent() Sending PVPlayerErrDatapathMediaData for error event %d", event));
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aEvent.GetEventExtensionInterface() != NULL)
{
nextmsg = GetErrorInfoMessageInterface(*(aEvent.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSinkMediaData, puuid, nextmsg));
if (HandleAsyncErrorBasedOnPlayerState(event, errmsg) == true)
{
SendErrorEvent(event, OSCL_STATIC_CAST(PVInterface*, errmsg), aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
}
errmsg->removeRef();
errmsg = NULL;
}
break;
case PVMFErrTimeout:
case PVMFErrNoResources:
case PVMFErrResourceConfiguration:
case PVMFErrResource:
case PVMFErrNoMemory:
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeErrorEvent() Sending PVPlayerErrSinkFatal for error event %d", event));
PVMFErrorInfoMessageInterface* nextmsg = NULL;
if (aEvent.GetEventExtensionInterface() != NULL)
{
nextmsg = GetErrorInfoMessageInterface(*(aEvent.GetEventExtensionInterface()));
}
PVUuid puuid = PVPlayerErrorInfoEventTypesUUID;
PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSinkFatal, puuid, nextmsg));
if (HandleAsyncErrorBasedOnPlayerState(event, errmsg) == true)
{
SendErrorEvent(event, OSCL_STATIC_CAST(PVInterface*, errmsg), aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
}
errmsg->removeRef();
errmsg = NULL;
}
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;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeErrorEvent() Out"));
}
void PVPlayerEngine::HandleErrorBasedOnPlayerState(void)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleErrorBasedOnPlayerState() In"));
switch (iState)
{
case PVP_ENGINE_STATE_PREPARED:
case PVP_ENGINE_STATE_STARTED:
case PVP_ENGINE_STATE_PAUSED:
case PVP_ENGINE_STATE_AUTO_PAUSED:
// Issue emergency stop command
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleErrorBasedOnPlayerState() Error while Prepared, Started, or Paused. Issue stop due to error"));
SetEngineState(PVP_ENGINE_STATE_ERROR);
AddCommandToQueue(PVP_ENGINE_COMMAND_STOP_DUE_TO_ERROR, NULL, NULL, NULL, false);
break;
case PVP_ENGINE_STATE_INITIALIZED:
// Issue emergency reset command
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleErrorBasedOnPlayerState() Error while Initialized. Issue reset due to error"));
SetEngineState(PVP_ENGINE_STATE_ERROR);
AddCommandToQueue(PVP_ENGINE_COMMAND_RESET_DUE_TO_ERROR, NULL, NULL, NULL, false);
break;
case PVP_ENGINE_STATE_INITIALIZING:
{
// Initialization of source node failed so go to idle state
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleErrorBasedOnPlayerState() Error while Initializing. Go back to idle state"));
SetEngineState(PVP_ENGINE_STATE_IDLE);
}
break;
case PVP_ENGINE_STATE_STARTING:
case PVP_ENGINE_STATE_PAUSING:
case PVP_ENGINE_STATE_RESUMING:
case PVP_ENGINE_STATE_AUTO_PAUSING:
case PVP_ENGINE_STATE_AUTO_RESUMING:
// Issue emergency stop command
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleErrorBasedOnPlayerState() Error while Preparing, Starting, Resuming, or Pausing. Issue stop due to error"));
SetEngineState(PVP_ENGINE_STATE_ERROR);
AddCommandToQueue(PVP_ENGINE_COMMAND_STOP_DUE_TO_ERROR, NULL, NULL, NULL, false);
break;
//call RESET when in preparing state
case PVP_ENGINE_STATE_PREPARING:
case PVP_ENGINE_STATE_STOPPING:
// Issue emergency reset command
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleErrorBasedOnPlayerState() Error while Preparing/Stopping. Issue stop due to error"));
SetEngineState(PVP_ENGINE_STATE_ERROR);
AddCommandToQueue(PVP_ENGINE_COMMAND_STOP_DUE_TO_ERROR, NULL, NULL, NULL, false);
break;
case PVP_ENGINE_STATE_RESETTING:
// Issue emergency cleanup command
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleErrorBasedOnPlayerState() Error while resetting. Issue cleanup due to error"));
SetEngineState(PVP_ENGINE_STATE_ERROR);
AddCommandToQueue(PVP_ENGINE_COMMAND_CLEANUP_DUE_TO_ERROR, NULL, NULL, NULL, false);
break;
case PVP_ENGINE_STATE_IDLE:
// Should not receive any error events when idle
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleErrorBasedOnPlayerState() Error event received while idle. Do nothing"));
OSCL_ASSERT(false);
break;
case PVP_ENGINE_STATE_HANDLINGERROR:
case PVP_ENGINE_STATE_ERROR:
// Do nothing
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleErrorBasedOnPlayerState() Error event received while handling error. Do nothing"));
break;
default:
// Unknown state
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleErrorBasedOnPlayerState() Error event received while in state %d. Do nothing", iState));
OSCL_ASSERT(false);
break;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleErrorBasedOnPlayerState() Out"));
}
bool PVPlayerEngine::HandleAsyncErrorBasedOnPlayerState(PVMFEventType aErrorCode, PVMFBasicErrorInfoMessage* aErrMsg)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleAsyncErrorBasedOnPlayerState() In"));
if (PVP_ENGINE_COMMAND_CANCEL_ALL_COMMANDS == iCurrentCmd[0].GetCmdType() && iPendingResetDueToCancelRequest > 0)
{
return false;
}
bool senderrorevent = true;
switch (iState)
{
case PVP_ENGINE_STATE_PREPARED:
case PVP_ENGINE_STATE_STARTED:
case PVP_ENGINE_STATE_PAUSED:
case PVP_ENGINE_STATE_AUTO_PAUSED:
// Issue emergency stop command
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleAsyncErrorBasedOnPlayerState() Error while Prepared, Started, or Paused. Issue stop due to error"));
// Change to error state
SetEngineState(PVP_ENGINE_STATE_ERROR);
if (iCurrentCmd.empty() == false)
{
// Report the error by completing the current command with error
EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), aErrorCode, aErrMsg);
senderrorevent = false;
// Cancel any pending node/datapath commands
DoCancelDueToError();
}
AddCommandToQueue(PVP_ENGINE_COMMAND_STOP_DUE_TO_ERROR, NULL, NULL, NULL, false);
break;
case PVP_ENGINE_STATE_INITIALIZED:
// Issue emergency reset command
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleAsyncErrorBasedOnPlayerState() Error while Initialized. Issue reset due to error"));
// Change to error state
SetEngineState(PVP_ENGINE_STATE_ERROR);
if (iCurrentCmd.empty() == false)
{
// Report the error by completing the current command with error
EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), aErrorCode, aErrMsg);
senderrorevent = false;
// Cancel any pending node/datapath commands
DoCancelDueToError();
}
AddCommandToQueue(PVP_ENGINE_COMMAND_RESET_DUE_TO_ERROR, NULL, NULL, NULL, false);
break;
case PVP_ENGINE_STATE_INITIALIZING:
// Initialization of source node failed so go to idle state
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleAsyncErrorBasedOnPlayerState() Error while Initializing. Go back to idle state"));
// Change to error state
SetEngineState(PVP_ENGINE_STATE_ERROR);
if (iCurrentCmd.empty() == false)
{
// Report the error by completing the current command with error
EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), aErrorCode, aErrMsg);
senderrorevent = false;
// Cancel any pending node/datapath commands
DoCancelDueToError();
}
AddCommandToQueue(PVP_ENGINE_COMMAND_RESET_DUE_TO_ERROR, NULL, NULL, NULL, false);
break;
case PVP_ENGINE_STATE_PREPARING:
case PVP_ENGINE_STATE_STARTING:
case PVP_ENGINE_STATE_PAUSING:
case PVP_ENGINE_STATE_RESUMING:
// Issue emergency stop command
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleAsyncErrorBasedOnPlayerState() Error while Preparing, Starting, Resuming, or Pausing. Issue stop due to error"));
// Change to error state
SetEngineState(PVP_ENGINE_STATE_ERROR);
if (iCurrentCmd.empty() == false)
{
// Report the error by completing the current command with error
EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), aErrorCode, aErrMsg);
senderrorevent = false;
// Cancel any pending node/datapath commands
DoCancelDueToError();
}
AddCommandToQueue(PVP_ENGINE_COMMAND_STOP_DUE_TO_ERROR, NULL, NULL, NULL, false);
break;
case PVP_ENGINE_STATE_STOPPING:
// Issue emergency reset command
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleAsyncErrorBasedOnPlayerState() Error while Stopping. Issue reset due to error"));
// Change to error state
SetEngineState(PVP_ENGINE_STATE_ERROR);
if (iCurrentCmd.empty() == false)
{
// Report the error by completing the current command with error
EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), aErrorCode, aErrMsg);
senderrorevent = false;
// Cancel any pending node/datapath commands
DoCancelDueToError();
}
AddCommandToQueue(PVP_ENGINE_COMMAND_RESET_DUE_TO_ERROR, NULL, NULL, NULL, false);
break;
case PVP_ENGINE_STATE_RESETTING:
// Issue emergency cleanup command
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleAsyncErrorBasedOnPlayerState() Error while resetting. Issue cleanup due to error"));
// Change to error state
SetEngineState(PVP_ENGINE_STATE_ERROR);
if (iCurrentCmd.empty() == false)
{
// Report the error by completing the current command with error
EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), aErrorCode, aErrMsg);
senderrorevent = false;
// Cancel any pending node/datapath commands
DoCancelDueToError();
}
AddCommandToQueue(PVP_ENGINE_COMMAND_CLEANUP_DUE_TO_ERROR, NULL, NULL, NULL, false);
break;
case PVP_ENGINE_STATE_IDLE:
// Should not receive any error events when idle
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleAsyncErrorBasedOnPlayerState() Error event received while idle. Do nothing"));
OSCL_ASSERT(false);
break;
case PVP_ENGINE_STATE_HANDLINGERROR:
case PVP_ENGINE_STATE_ERROR:
// Do nothing
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleAsyncErrorBasedOnPlayerState() Error event received while handling error. Do nothing"));
break;
default:
// Unknown state
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleAsyncErrorBasedOnPlayerState() Error event received while in state %d. Do nothing", iState));
OSCL_ASSERT(false);
break;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleAsyncErrorBasedOnPlayerState() Out"));
return senderrorevent;
}
//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"));
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)))
{
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:
{
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 PVMFInfoDurationAvailable:
{
PVUuid infomsguuid = PVMFDurationInfoMessageInterfaceUUID;
PVMFDurationInfoMessageInterface* eventMsg = NULL;
PVInterface* infoExtInterface = aEvent.GetEventExtensionInterface();
if (infoExtInterface &&
infoExtInterface->queryInterface(infomsguuid, (PVInterface*&)eventMsg))
{
PVUuid eventuuid;
int32 infoCode;
eventMsg->GetCodeUUID(infoCode, eventuuid);
if (eventuuid == infomsguuid)
{
iSourceDurationInMS = eventMsg->GetDuration();
iSourceDurationAvailable = true;
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 PVMFInfoMetadataAvailable:
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Sending meta data Info %d", event));
SendInformationalEvent(event, NULL, aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize());
}
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 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"));
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"));
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)
{
// recieved StartOfData for previous streamId, ignoring these events
break;
}
if (iNumPVMFInfoStartOfDataPending > 0)
{
--iNumPVMFInfoStartOfDataPending;
}
if ((iNumPendingSkipCompleteEvent == 0) && (iNumPVMFInfoStartOfDataPending == 0))
{
if (iWatchDogTimer->IsBusy())
{
iWatchDogTimer->Cancel();
}
// we have received all the bos event for
// playback hasnt started yet
StartPlaybackClock();
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() - PlayClock Started"));
}
//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)
{
// recieved EndOfData for previous streamId, ignoring these events
break;
}
if (iDatapathList[aDatapathIndex].iTrackActive && iDatapathList[aDatapathIndex].iEndOfDataReceived == false)
{
iDatapathList[aDatapathIndex].iEndOfDataReceived = true;
// If all datapath received EOS, initiate a pause-due-to-EOS
if (AllDatapathReceivedEndOfData() == true)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() Issue Pause due to end of clip"));
AddCommandToQueue(PVP_ENGINE_COMMAND_PAUSE_DUE_TO_ENDOFCLIP, NULL, NULL, NULL, false);
}
}
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());
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].iTrackActive == true &&
iDatapathList[i].iEndOfDataReceived == false)
{
return false;
}
}
return true;
}
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)
{
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)
{
if (!iDataReadySent)
{
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"));
}
void PVPlayerEngine::SendErrorHandlingCompleteEvent(PVMFStatus aStatus, PVInterface* /*aExtInterface*/)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::SendErrorHandlingCompleteEvent() In"));
if (aStatus == PVMFSuccess)
{
SendInformationalEvent(PVMFInfoErrorHandlingComplete, NULL);
}
else
{
// Don't send any event since error handling is still not complete
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::SendErrorHandlingCompleteEvent() Out"));
}
PVMFErrorInfoMessageInterface* PVPlayerEngine::GetErrorInfoMessageInterface(PVInterface& aInterface)
{
PVMFErrorInfoMessageInterface* extiface = NULL;
if (aInterface.queryInterface(PVMFErrorInfoMessageInterfaceUUID, (PVInterface*&)extiface))
{
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;
// Determine the check cycle based on interval setting in milliseconds
// and timer frequency of 100 millisec
int32 checkcycle = iPBPosStatusInterval / 100;
if (checkcycle == 0)
{
++checkcycle;
}
OSCL_ASSERT(iPollingCheckTimer);
iPollingCheckTimer->Request(PVPLAYERENGINE_TIMERID_PLAY_STATUS, 0, checkcycle, this, true);
}
void PVPlayerEngine::StopPlaybackStatusTimer(void)
{
// Stop the playback position status timer
iPlayStatusTimerEnabled = false;
OSCL_ASSERT(iPollingCheckTimer);
iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_PLAY_STATUS);
}
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_DATA_SOURCE_REAL_HTTP_CLOAKING_URL,
* implying that we would attempt a real media cloaking session
*
* 4) Third alternate source format would be PVMF_DATA_SOURCE_MS_HTTP_STREAMING_URL,
* implying that we would attempt a MS HTTP streaming session
*/
iSourceFormatType = PVMF_DATA_SOURCE_RTSP_URL; ;
if (iDataSource->SetAlternateSourceFormatType(PVMF_DATA_SOURCE_HTTP_URL) != true)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::SetupDataSourceForUnknownURLAccess() - SetAlternateSourceFormatType Failed"));
return PVMFFailure;
}
if (iDataSource->SetAlternateSourceFormatType(PVMF_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_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));
// Currently support only one element. Future support will be based on length.
}
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));
// Currently support only one element. Future support will be based on length.
}
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));
// Currently support only one element. Future support will be based on length.
}
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));
// Currently support only one element. Future support will be based on length.
}
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));
// Currently support only one element. Future support will be based on length.
}
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));
// Currently support only one element. Future support will be based on length.
}
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));
// Currently support only one element. Future support will be based on length.
}
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));
// Currently support only one element. Future support will be based on length.
}
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()
{
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()
{
iWatchDogTimer->Cancel();
if (GetPVPlayerState() != PVP_STATE_STARTED)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::StartPlaybackClock() wrong engine state"));
return;
}
if (iPlaybackClock.GetState() == OsclClock::RUNNING)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (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].iTrackActive && 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;
}
#ifdef HAS_OSCL_LIB_SUPPORT
void PVPlayerEngine::PopulateNodeRegistry(const OSCL_String& aConfigFilePath)
{
OsclLibraryList libList;
// Check the current directory for a config file first. This way you can
// override the config file set by the tunables.
OSCL_StackString<PVPLAYERENGINE_DEFAULT_CONFIG_PATH_SIZE> defaultConfig("./pvplayer.conf");
if (OsclLibFail == libList.Populate(PV_NODE_REGISTRY_INTERFACE, defaultConfig))
{
libList.Populate(PV_NODE_REGISTRY_INTERFACE, aConfigFilePath);
}
for (unsigned int i = 0; i < libList.Size(); i++)
{
OsclSharedLibrary* lib = OSCL_NEW(OsclSharedLibrary, ());
if (lib->LoadLib(libList.GetLibraryPathAt(i)) == OsclLibSuccess)
{
OsclAny* interfacePtr = NULL;
OsclLibStatus result = lib->QueryInterface(PV_NODE_REGISTRY_INTERFACE, (OsclAny*&)interfacePtr);
if (result == OsclLibSuccess && interfacePtr != NULL)
{
struct PVPlayerEngineNodeSharedLibInfo *libInfo = (struct PVPlayerEngineNodeSharedLibInfo *)oscl_malloc(sizeof(struct PVPlayerEngineNodeSharedLibInfo));
if (NULL != libInfo)
{
libInfo->iLib = lib;
NodeRegistrySharedLibraryInterface* nodeIntPtr = OSCL_DYNAMIC_CAST(NodeRegistrySharedLibraryInterface*, interfacePtr);
libInfo->iNodeLibIfacePtr = nodeIntPtr;
nodeIntPtr->RegisterAllNodes((PVPlayerNodeRegistryInterface *)&iPlayerNodeRegistry, libInfo->iContext);
// save for depopulation later
iNodeLibInfoList.push_front(libInfo);
continue;
}
}
}
lib->Close();
OSCL_DELETE(lib);
}
}
void PVPlayerEngine::PopulateRecognizerRegistry(const OSCL_String& aConfigFilePath)
{
OsclLibraryList libList;
// Check the current directory for a config file first. This way you can
// override the config file set by the tunables.
OSCL_StackString<PVPLAYERENGINE_DEFAULT_CONFIG_PATH_SIZE> defaultConfig("./pvplayer.conf");
if (OsclLibFail == libList.Populate(PV_RECOGNIZER_INTERFACE, defaultConfig))
{
libList.Populate(PV_RECOGNIZER_INTERFACE, aConfigFilePath);
}
for (unsigned int i = 0; i < libList.Size(); i++)
{
OsclSharedLibrary* lib = OSCL_NEW(OsclSharedLibrary, ());
if (lib->LoadLib(libList.GetLibraryPathAt(i)) == OsclLibSuccess)
{
OsclAny* interfacePtr = NULL;
OsclLibStatus result = lib->QueryInterface(PV_RECOGNIZER_INTERFACE, (OsclAny*&)interfacePtr);
if (result == OsclLibSuccess && interfacePtr != NULL)
{
struct PVPlayerEngineRecognizerSharedLibInfo *libInfo = (struct PVPlayerEngineRecognizerSharedLibInfo *)oscl_malloc(sizeof(struct PVPlayerEngineRecognizerSharedLibInfo));
if (NULL != libInfo)
{
libInfo->iLib = lib;
RecognizerSharedLibraryInterface* recognizerIntPtr = OSCL_DYNAMIC_CAST(RecognizerSharedLibraryInterface*, interfacePtr);
libInfo->iRecognizerLibIfacePtr = recognizerIntPtr;
recognizerIntPtr->RegisterAllRecognizers((PVPlayerRecognizerRegistryInterface *)&iPlayerRecognizerRegistry, libInfo->iContext);
// save for depopulation later
iRecognizerLibInfoList.push_front(libInfo);
continue;
}
}
}
lib->Close();
OSCL_DELETE(lib);
}
}
void PVPlayerEngine::PopulateAllRegistries(const OSCL_String& aConfigFilePath)
{
PopulateNodeRegistry(aConfigFilePath);
PopulateRecognizerRegistry(aConfigFilePath);
}
void PVPlayerEngine::DepopulateNodeRegistry()
{
// remove all dynamic nodes now
// unregister node one by one
while (!iNodeLibInfoList.empty())
{
struct PVPlayerEngineNodeSharedLibInfo *libInfo = iNodeLibInfoList.front();
iNodeLibInfoList.erase(iNodeLibInfoList.begin());
OsclSharedLibrary* lib = libInfo->iLib;
NodeRegistrySharedLibraryInterface* nodeIntPtr = libInfo->iNodeLibIfacePtr;
OsclAny* context = libInfo->iContext;
oscl_free(libInfo);
nodeIntPtr->UnregisterAllNodes((PVPlayerNodeRegistryInterface *)&iPlayerNodeRegistry, context);
lib->Close();
OSCL_DELETE(lib);
}
}
void PVPlayerEngine::DepopulateRecognizerRegistry()
{
// remove all the dynamic plugins now
// unregister the plugins one by one
while (!iRecognizerLibInfoList.empty())
{
struct PVPlayerEngineRecognizerSharedLibInfo *libInfo = iRecognizerLibInfoList.front();
iRecognizerLibInfoList.erase(iRecognizerLibInfoList.begin());
OsclSharedLibrary* lib = libInfo->iLib;
RecognizerSharedLibraryInterface* recognizerIntPtr = libInfo->iRecognizerLibIfacePtr;
OsclAny* context = libInfo->iContext;
oscl_free(libInfo);
recognizerIntPtr->UnregisterAllRecognizers((PVPlayerRecognizerRegistryInterface *)&iPlayerRecognizerRegistry, context);
lib->Close();
OSCL_DELETE(lib);
}
}
void PVPlayerEngine::DepopulateAllRegistries()
{
DepopulateNodeRegistry();
DepopulateRecognizerRegistry();
}
#endif