| /* ------------------------------------------------------------------ |
| * 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, ¶mvec); |
| } |
| |
| |
| 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, ¶mvec); |
| } |
| |
| |
| 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, ¶mvec); |
| } |
| |
| |
| 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, ¶mvec); |
| } |
| |
| |
| 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, ¶mvec); |
| } |
| |
| |
| 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, ¶mvec); |
| } |
| |
| |
| 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, ¶mvec); |
| } |
| |
| |
| 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, ¶mvec, &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, ¶mvec); |
| } |
| |
| |
| 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, ¶mvec); |
| 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, ¶mvec); |
| } |
| |
| |
| 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, ¶mvec); |
| } |
| |
| 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, ¶mvec); |
| } |
| |
| |
| 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, ¶mvec); |
| } |
| |
| |
| 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, ¶mvec); |
| } |
| |
| |
| 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, ¶mvec); |
| } |
| |
| |
| 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, ¶mvec); |
| } |
| |
| |
| 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, ¶mvec); |
| 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, ¶mvec); |
| } |
| |
| |
| 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, ¶mvec); |
| } |
| |
| |
| 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, ¶mvec); |
| } |
| |
| |
| 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, ¶mvec); |
| } |
| |
| |
| 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, ¶mvec); |
| } |
| |
| |
| 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, ¶mvec); |
| |
| // 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, ¶mvec, 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, ¶mvec); |
| } |
| |
| |
| 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, ¶mvec); |
| } |
| |
| 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, ¶mvec); |
| } |
| |
| 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(¶mkvp[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 = ¶mkvp[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 = ¶mkvp[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 = ¶mkvp[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 = ¶mkvp[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 = ¶mkvp[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, ¶mkvp[paramind], 1, *retkvp); |
| ++nodeind; |
| if (*retkvp == NULL && anysuccess == false) |
| { |
| anysuccess = true; |
| } |
| } |
| if (anysuccess == false) |
| { // setParametersSync was not accepted by the node(s) |
| *retkvp = ¶mkvp[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 |
| |
| |