| /* ------------------------------------------------------------------ |
| * Copyright (C) 1998-2009 PacketVideo |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either |
| * express or implied. |
| * See the License for the specific language governing permissions |
| * and limitations under the License. |
| * ------------------------------------------------------------------- |
| */ |
| #include "pv_player_engine.h" |
| |
| #include "pv_player_config.h" |
| |
| #ifndef USE_CML2_CONFIG |
| #include "pv_player_engine_tunables.h" |
| #endif |
| |
| #include "pv_player_sdkinfo.h" |
| |
| #include "pvmf_node_interface.h" |
| |
| #include "pvmf_ffparsernode_extension.h" |
| |
| #include "pvmf_data_source_init_extension.h" |
| |
| #include "pvmf_track_selection_extension.h" |
| |
| #include "pvmf_data_source_playback_control.h" |
| |
| #include "pvmf_data_source_direction_control.h" |
| |
| #include "pvmf_track_level_info_extension.h" |
| |
| #include "pvmf_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 "pvmf_metadata_infomessage.h" |
| |
| #include "pv_mime_string_utils.h" |
| |
| #include "pvmi_kvp_util.h" |
| |
| #include "oscl_string_utils.h" |
| |
| #include "media_clock_converter.h" |
| |
| #include "time_comparison_utils.h" |
| |
| #include "pvmf_local_data_source.h" |
| |
| #include "pvmf_cpmplugin_license_interface.h" |
| |
| #include "oscl_registry_access_client.h" |
| |
| #include "pvmf_source_context_data.h" |
| |
| #include "pv_player_node_registry.h" |
| #include "pv_player_registry_interface.h" |
| |
| // For recognizer registry |
| #include "pvmf_recognizer_registry.h" |
| |
| #include "pvmi_datastreamsyncinterface_ref_factory.h" |
| |
| #include "pvmf_recognizer_plugin.h" |
| |
| // |
| |
| |
| #define PVPLAYERENGINE_NUM_COMMANDS 10 |
| |
| #define PVPLAYERENGINE_TIMERID_ENDTIMECHECK 1 |
| |
| #define PVP_MIN_PLAYSTATUS_PERCENT_OVERFLOW_THRESHOLD 1000 |
| |
| |
| |
| PVPlayerEngine* PVPlayerEngine::New(PVCommandStatusObserver* aCmdStatusObserver, |
| PVErrorEventObserver *aErrorEventObserver, |
| PVInformationalEventObserver *aInfoEventObserver, |
| bool aHwAccelerated) |
| { |
| PVPlayerEngine* engine = NULL; |
| engine = OSCL_NEW(PVPlayerEngine, (aHwAccelerated)); |
| if (engine) |
| { |
| engine->Construct(aCmdStatusObserver, |
| aErrorEventObserver, |
| aInfoEventObserver); |
| } |
| |
| return engine; |
| } |
| |
| |
| PVPlayerEngine::~PVPlayerEngine() |
| { |
| Cancel(); |
| |
| // Clear the Track selection List |
| iTrackSelectionList.clear(); |
| |
| // Remove Stored KVP Values |
| DeleteKVPValues(); |
| |
| if (!iPendingCmds.empty()) |
| { |
| iPendingCmds.pop(); |
| } |
| |
| // Clean up the datapaths |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| DoEngineDatapathCleanup(iDatapathList[i]); |
| } |
| iDatapathList.clear(); |
| |
| // Clean up the source node |
| DoSourceNodeCleanup(); |
| |
| // Shutdown and destroy the timer |
| if (iPollingCheckTimer) |
| { |
| iPollingCheckTimer->Clear(); |
| } |
| |
| if (iWatchDogTimer) |
| { |
| iWatchDogTimer->Cancel(); |
| OSCL_DELETE(iWatchDogTimer); |
| } |
| |
| OSCL_DELETE(iPollingCheckTimer); |
| |
| //Destroy media clock notifications interface |
| if (iClockNotificationsInf != NULL) |
| { |
| iPlaybackClock.DestroyMediaClockNotificationsInterface(iClockNotificationsInf); |
| iClockNotificationsInf = NULL; |
| } |
| |
| // Return all engine contexts to pool |
| while (!iCurrentContextList.empty()) |
| { |
| FreeEngineContext(iCurrentContextList[0]); |
| } |
| |
| PVPlayerRegistryPopulator::Depopulate(iPlayerNodeRegistry, iPlayerRecognizerRegistry); |
| |
| iNodeUuids.clear(); |
| |
| iCommandIdMut.Close(); |
| iOOTSyncCommandSem.Close(); |
| } |
| |
| |
| 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::CancelCommand(PVCommandId aCancelCmdId, const OsclAny* aContextData) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::CancelCommand()")); |
| Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec; |
| paramvec.reserve(1); |
| paramvec.clear(); |
| PVPlayerEngineCommandParamUnion param; |
| param.int32_value = aCancelCmdId; |
| paramvec.push_back(param); |
| return AddCommandToQueue(PVP_ENGINE_COMMAND_CANCEL_COMMAND, (OsclAny*)aContextData, ¶mvec); |
| } |
| |
| |
| 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); |
| if (iThreadSafeQueue.IsInThread()) |
| { |
| PVPlayerEngineCommand cmd(PVP_ENGINE_COMMAND_GET_PVPLAYER_STATE, -1, NULL, ¶mvec); |
| return DoGetPVPlayerState(cmd, true); |
| } |
| else |
| { |
| return DoOOTSyncCommand(PVP_ENGINE_COMMAND_GET_PVPLAYER_STATE_OOTSYNC, ¶mvec); |
| } |
| } |
| |
| |
| 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, bool aMetadataValuesCopiedInCallBack) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::GetMetadataValues()")); |
| Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec; |
| paramvec.reserve(6); |
| paramvec.clear(); |
| PVPlayerEngineCommandParamUnion param; |
| |
| param.pOsclAny_value = (OsclAny*) & aKeyList; |
| paramvec.push_back(param); |
| param.int32_value = aStartingValueIndex; |
| paramvec.push_back(param); |
| param.int32_value = aMaxValueEntries; |
| paramvec.push_back(param); |
| param.pOsclAny_value = (OsclAny*) & aNumAvailableValueEntries; |
| paramvec.push_back(param); |
| param.pOsclAny_value = (OsclAny*) & aValueList; |
| paramvec.push_back(param); |
| param.bool_value = aMetadataValuesCopiedInCallBack; |
| paramvec.push_back(param); |
| |
| return AddCommandToQueue(PVP_ENGINE_COMMAND_GET_METADATA_VALUE, (OsclAny*)aContextData, ¶mvec); |
| } |
| |
| PVCommandId PVPlayerEngine::ReleaseMetadataValues(Oscl_Vector<PvmiKvp, OsclMemAllocator>& aValueList, const OsclAny* aContextData) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::ReleaseMetadataValues()")); |
| Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec; |
| paramvec.reserve(1); |
| paramvec.clear(); |
| PVPlayerEngineCommandParamUnion param; |
| |
| param.pOsclAny_value = (OsclAny*) & aValueList; |
| paramvec.push_back(param); |
| |
| return AddCommandToQueue(PVP_ENGINE_COMMAND_RELEASE_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; |
| |
| // Additional checks to ensure a valid mode is |
| // used for the begin position. |
| // Assumes: aBegin.iPosUnit is always valid (when applicable). |
| |
| // Check 1 || Check 2 |
| // Check 1: Is the begin position indeterminate? |
| // Check 2: Is the position unit something other than playlist? |
| // If so, set mode to NOW. |
| if ((aBeginPos.iIndeterminate) || (aBeginPos.iPosUnit != PVPPBPOSUNIT_PLAYLIST)) |
| { |
| aBeginPos.iMode = PVPPBPOS_MODE_NOW; |
| } |
| // Check 3: Is the position unit playlist and the mode something other than the three valid |
| // modes? If so, set mode to NOW. |
| else if (aBeginPos.iPosUnit == PVPPBPOSUNIT_PLAYLIST) |
| { |
| switch (aBeginPos.iMode) |
| { |
| case PVPPBPOS_MODE_NOW: |
| case PVPPBPOS_MODE_END_OF_CURRENT_PLAY_ELEMENT: |
| case PVPPBPOS_MODE_END_OF_CURRENT_PLAY_SESSION: |
| break; |
| case PVPPBPOS_MODE_UNKNOWN: |
| default: |
| aBeginPos.iMode = PVPPBPOS_MODE_NOW; |
| break; |
| } |
| } |
| 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); |
| if (!iOverflowFlag) |
| { |
| return AddCommandToQueue(PVP_ENGINE_COMMAND_SET_PLAYBACK_RANGE, (OsclAny*)aContextData, ¶mvec); |
| } |
| else |
| { |
| return AddCommandToQueue(PVP_ENGINE_COMMAND_SET_PLAYBACK_RANGE, (OsclAny*)aContextData, ¶mvec, NULL, false); |
| } |
| } |
| |
| |
| PVCommandId PVPlayerEngine::GetPlaybackRange(PVPPlaybackPosition &aBeginPos, PVPPlaybackPosition &aEndPos, bool aQueued, const OsclAny* aContextData) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::GetPlaybackRange()")); |
| Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec; |
| paramvec.reserve(3); |
| paramvec.clear(); |
| PVPlayerEngineCommandParamUnion param; |
| param.pPlaybackpos_value = &aBeginPos; |
| paramvec.push_back(param); |
| param.pPlaybackpos_value = &aEndPos; |
| paramvec.push_back(param); |
| param.bool_value = aQueued; |
| paramvec.push_back(param); |
| return AddCommandToQueue(PVP_ENGINE_COMMAND_GET_PLAYBACK_RANGE, (OsclAny*)aContextData, ¶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); |
| if (iThreadSafeQueue.IsInThread()) |
| { |
| PVPlayerEngineCommand cmd(PVP_ENGINE_COMMAND_GET_CURRENT_POSITION, -1, NULL, ¶mvec); |
| return DoGetCurrentPosition(cmd, true); |
| } |
| else |
| { |
| return DoOOTSyncCommand(PVP_ENGINE_COMMAND_GET_CURRENT_POSITION_OOTSYNC, ¶mvec); |
| } |
| } |
| |
| |
| PVCommandId PVPlayerEngine::SetPlaybackRate(int32 aRate, PVMFTimebase* aTimebase, const OsclAny* aContextData) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::SetPlaybackRate()")); |
| Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec; |
| paramvec.reserve(2); |
| paramvec.clear(); |
| PVPlayerEngineCommandParamUnion param; |
| param.int32_value = aRate; |
| paramvec.push_back(param); |
| param.pOsclAny_value = (OsclAny*)aTimebase; |
| paramvec.push_back(param); |
| return AddCommandToQueue(PVP_ENGINE_COMMAND_SET_PLAYBACK_RATE, (OsclAny*)aContextData, ¶mvec); |
| } |
| |
| |
| PVCommandId PVPlayerEngine::GetPlaybackRate(int32& aRate, PVMFTimebase*& aTimebase, const OsclAny* aContextData) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::GetPlaybackRate()")); |
| Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec; |
| paramvec.reserve(2); |
| paramvec.clear(); |
| PVPlayerEngineCommandParamUnion param; |
| param.pInt32_value = &aRate; |
| paramvec.push_back(param); |
| param.pOsclAny_value = (OsclAny*) & aTimebase; |
| paramvec.push_back(param); |
| return AddCommandToQueue(PVP_ENGINE_COMMAND_GET_PLAYBACK_RATE, (OsclAny*)aContextData, ¶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()")); |
| 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()")); |
| |
| if (iThreadSafeQueue.IsInThread()) |
| { |
| iCfgCapCmdObserver = aObserver; |
| } |
| else |
| { |
| Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec; |
| paramvec.reserve(2); |
| paramvec.clear(); |
| PVPlayerEngineCommandParamUnion param; |
| param.pOsclAny_value = aObserver; |
| paramvec.push_back(param); |
| DoOOTSyncCommand(PVP_ENGINE_COMMAND_CAPCONFIG_SET_OBSERVER_OOTSYNC, ¶mvec); |
| } |
| } |
| |
| PVMFStatus PVPlayerEngine::DoSetObserverSync(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetObserverSync() In")); |
| |
| iCfgCapCmdObserver = (PvmiConfigAndCapabilityCmdObserver*)(aCmd.GetParam(0).pOsclAny_value); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetObserverSync() Out")); |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVPlayerEngine::getParametersSync(PvmiMIOSession aSession, PvmiKeyType aIdentifier, PvmiKvp*& aParameters, int& aNumParamElements, PvmiCapabilityContext aContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::getParametersSync()")); |
| OSCL_UNUSED_ARG(aSession); |
| |
| if (iThreadSafeQueue.IsInThread()) |
| { |
| return DoCapConfigGetParametersSync(aIdentifier, aParameters, aNumParamElements, aContext); |
| } |
| else |
| { |
| Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec; |
| paramvec.reserve(5); |
| paramvec.clear(); |
| PVPlayerEngineCommandParamUnion param; |
| param.pOsclAny_value = &aIdentifier; |
| paramvec.push_back(param); |
| param.pOsclAny_value = &aParameters; |
| paramvec.push_back(param); |
| param.pOsclAny_value = &aNumParamElements; |
| paramvec.push_back(param); |
| param.pOsclAny_value = &aContext; |
| paramvec.push_back(param); |
| return DoOOTSyncCommand(PVP_ENGINE_COMMAND_CAPCONFIG_GET_PARAMETERS_OOTSYNC, ¶mvec); |
| } |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoGetParametersSync(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetParametersSync() In")); |
| |
| PVMFStatus status = DoCapConfigGetParametersSync( |
| *((PvmiKeyType*)aCmd.GetParam(0).pOsclAny_value) |
| , *((PvmiKvp**)aCmd.GetParam(1).pOsclAny_value) |
| , *((int*)aCmd.GetParam(2).pOsclAny_value) |
| , *((PvmiCapabilityContext*)aCmd.GetParam(3).pOsclAny_value)); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetParametersSync() Out")); |
| return status; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::releaseParameters(PvmiMIOSession aSession, PvmiKvp* aParameters, int aNumElements) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::releaseParameters()")); |
| OSCL_UNUSED_ARG(aSession); |
| |
| if (iThreadSafeQueue.IsInThread()) |
| { |
| return DoCapConfigReleaseParameters(aParameters, aNumElements); |
| } |
| else |
| { |
| Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec; |
| paramvec.reserve(3); |
| paramvec.clear(); |
| PVPlayerEngineCommandParamUnion param; |
| param.pOsclAny_value = aParameters; |
| paramvec.push_back(param); |
| param.int32_value = aNumElements; |
| paramvec.push_back(param); |
| return DoOOTSyncCommand(PVP_ENGINE_COMMAND_CAPCONFIG_RELEASE_PARAMETERS_OOTSYNC, ¶mvec); |
| } |
| } |
| |
| PVMFStatus PVPlayerEngine::DoReleaseParametersSync(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoReleaseParametersSync() In")); |
| |
| PVMFStatus status = DoCapConfigReleaseParameters( |
| (PvmiKvp*)aCmd.GetParam(0).pOsclAny_value |
| , aCmd.GetParam(1).int32_value); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoReleaseParametersSync() Out")); |
| return status; |
| } |
| |
| void PVPlayerEngine::createContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::createContext()")); |
| OSCL_UNUSED_ARG(aSession); |
| // Context is not really supported so just return some member variable pointer |
| 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(OsclErrNotSupported); |
| } |
| |
| |
| 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); |
| if (iThreadSafeQueue.IsInThread()) |
| { |
| PVPlayerEngineCommand cmd(PVP_ENGINE_COMMAND_CAPCONFIG_SET_PARAMETERS, -1, NULL, ¶mvec); |
| |
| // Complete the request synchronously |
| DoCapConfigSetParameters(cmd, true); |
| } |
| else |
| { |
| DoOOTSyncCommand(PVP_ENGINE_COMMAND_CAPCONFIG_SET_PARAMETERS_OOTSYNC, ¶mvec); |
| } |
| } |
| |
| |
| 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); |
| |
| if (iThreadSafeQueue.IsInThread()) |
| { |
| return DoCapConfigVerifyParameters(aParameters, aNumElements); |
| } |
| else |
| { |
| Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec; |
| paramvec.reserve(3); |
| paramvec.clear(); |
| PVPlayerEngineCommandParamUnion param; |
| param.pOsclAny_value = aParameters; |
| paramvec.push_back(param); |
| param.int32_value = aNumElements; |
| paramvec.push_back(param); |
| return DoOOTSyncCommand(PVP_ENGINE_COMMAND_CAPCONFIG_VERIFY_PARAMETERS_OOTSYNC, ¶mvec); |
| } |
| } |
| |
| PVMFStatus PVPlayerEngine::DoVerifyParametersSync(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoVerifyParametersSync() In")); |
| |
| PVMFStatus status = DoCapConfigVerifyParameters( |
| (PvmiKvp*)aCmd.GetParam(0).pOsclAny_value |
| , aCmd.GetParam(1).int32_value); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoVerifyParametersSync() Out")); |
| return status; |
| } |
| |
| PVMFCommandId PVPlayerEngine::AcquireLicense(OsclAny* aLicenseData, uint32 aDataSize, oscl_wchar* aContentName, int32 aTimeoutMsec, const OsclAny* aContextData) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::AcquireLicense() wchar")); |
| Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec; |
| paramvec.reserve(3); |
| paramvec.clear(); |
| PVPlayerEngineCommandParamUnion param; |
| param.pOsclAny_value = aLicenseData; |
| paramvec.push_back(param); |
| param.uint32_value = aDataSize; |
| paramvec.push_back(param); |
| param.pWChar_value = aContentName; |
| paramvec.push_back(param); |
| param.int32_value = aTimeoutMsec; |
| paramvec.push_back(param); |
| return AddCommandToQueue(PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_WCHAR, (OsclAny*)aContextData, ¶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 (iThreadSafeQueue.IsInThread()) |
| { |
| if (iSourceNodeCPMLicenseIF) |
| return iSourceNodeCPMLicenseIF->GetLicenseStatus(aStatus); |
| return PVMFFailure; |
| } |
| else |
| { |
| Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator> paramvec; |
| paramvec.reserve(2); |
| paramvec.clear(); |
| PVPlayerEngineCommandParamUnion param; |
| param.pOsclAny_value = &aStatus; |
| paramvec.push_back(param); |
| return DoOOTSyncCommand(PVP_ENGINE_COMMAND_GET_LICENSE_STATUS_OOTSYNC, ¶mvec); |
| } |
| } |
| |
| PVMFStatus PVPlayerEngine::DoGetLicenseStatusSync(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetLicenseStatusSync() In")); |
| |
| PVMFStatus status; |
| PVMFCPMLicenseStatus* licstatus = (PVMFCPMLicenseStatus*)(aCmd.GetParam(0).pOsclAny_value); |
| if (!licstatus) |
| { |
| return PVMFFailure; |
| } |
| |
| if (iSourceNodeCPMLicenseIF) |
| status = iSourceNodeCPMLicenseIF->GetLicenseStatus(*licstatus); |
| else |
| status = PVMFFailure; |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetLicenseStatusSync() Out")); |
| return status; |
| } |
| |
| 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(bool aHwAccelerated) : |
| iHwAccelerated(aHwAccelerated), |
| OsclTimerObject(OsclActiveObject::EPriorityNominal, "PVPlayerEngine"), |
| iCommandId(0), |
| iState(PVP_ENGINE_STATE_IDLE), |
| iCmdStatusObserver(NULL), |
| iErrorEventObserver(NULL), |
| iInfoEventObserver(NULL), |
| iCfgCapCmdObserver(NULL), |
| iPollingCheckTimer(NULL), |
| iCommandCompleteStatusInErrorHandling(PVMFSuccess), |
| iCommandCompleteErrMsgInErrorHandling(NULL), |
| iCapConfigContext(0), |
| iNumPendingNodeCmd(0), |
| iNumPendingSkipCompleteEvent(0), |
| iNumPendingDatapathCmd(0), |
| iNumPVMFInfoStartOfDataPending(0), |
| iDataSource(NULL), |
| iSourceFormatType(PVMF_MIME_FORMAT_UNKNOWN), |
| iSourceNode(NULL), |
| iSourceNodeSessionId(0), |
| iSourceNodeInitIF(NULL), |
| iSourceNodeTrackSelIF(NULL), |
| iSourceNodePBCtrlIF(NULL), |
| iSourceNodeDirCtrlIF(NULL), |
| iSourceNodeTrackLevelInfoIF(NULL), |
| iSourceNodeMetadataExtIF(NULL), |
| iSourceNodeCapConfigIF(NULL), |
| iSourceNodeRegInitIF(NULL), |
| iSourceNodeCPMLicenseIF(NULL), |
| iSourceNodePVInterfaceInit(NULL), |
| iSourceNodePVInterfaceTrackSel(NULL), |
| iSourceNodePVInterfacePBCtrl(NULL), |
| iSourceNodePVInterfaceDirCtrl(NULL), |
| iSourceNodePVInterfaceTrackLevelInfo(NULL), |
| iSourceNodePVInterfaceMetadataExt(NULL), |
| iSourceNodePVInterfaceCapConfig(NULL), |
| iSourceNodePVInterfaceRegInit(NULL), |
| iSourceNodePVInterfaceCPMLicense(NULL), |
| iCPMGetLicenseCmdId(0), |
| iMetadataValuesCopiedInCallBack(true), |
| iReleaseMetadataValuesPending(false), |
| iCurrentContextListMemPool(12), |
| iNumberCancelCmdPending(0), |
| iLogger(NULL), |
| iReposLogger(NULL), |
| iPerfLogger(NULL), |
| iClockNotificationsInf(NULL), |
| iPlayStatusCallbackTimerID(0), |
| iPlayStatusCallbackTimerMarginWindow(0), |
| iCurrCallbackTimerLatency(0), |
| iPlaybackClockRate(100000), |
| iOutsideTimebase(NULL), |
| iPlaybackClockRate_New(100000), |
| iOutsideTimebase_New(NULL), |
| iPlaybackDirection(1), |
| iPlaybackDirection_New(1), |
| iChangePlaybackDirectionWhenResuming(false), |
| iEndTimeCheckEnabled(false), |
| iQueuedRangePresent(false), |
| iChangePlaybackPositionWhenResuming(false), |
| iActualNPT(0), |
| iTargetNPT(0), |
| iActualMediaDataTS(0), |
| iSkipMediaDataTS(0), |
| iStartNPT(0), |
| iStartMediaDataTS(0), |
| iWatchDogTimerInterval(0), |
| iSeekPointBeforeTargetNPT(0), |
| iSeekPointAfterTargetNPT(0), |
| iForwardReposFlag(false), |
| iBackwardReposFlag(false), |
| iPlayStatusTimerEnabled(false), |
| iDataReadySent(false), |
| iPlaybackPausedDueToEndOfClip(false), |
| 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), |
| iBackwardRepos(false), |
| 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)), |
| iStreamID(0), |
| iAlternateSrcFormatIndex(0), |
| iRollOverState(RollOverStateIdle), |
| iTrackSelectionHelper(NULL), |
| iPlaybackPositionMode(PVPPBPOS_MODE_UNKNOWN), |
| iOverflowFlag(false) |
| { |
| iCurrentBeginPosition.iIndeterminate = true; |
| iCurrentEndPosition.iIndeterminate = true; |
| iCurrentBeginPosition.iPlayListUri = NULL; |
| iQueuedBeginPosition.iIndeterminate = true; |
| iQueuedEndPosition.iIndeterminate = true; |
| iChangeDirectionNPT.iIndeterminate = true; |
| |
| iSyncMarginVideo.min = PVPLAYERENGINE_CONFIG_SYNCMARGIN_EARLY_DEF; |
| iSyncMarginVideo.max = PVPLAYERENGINE_CONFIG_SYNCMARGIN_LATE_DEF; |
| iSyncMarginAudio.min = PVPLAYERENGINE_CONFIG_SYNCMARGIN_EARLY_DEF; |
| iSyncMarginAudio.max = PVPLAYERENGINE_CONFIG_SYNCMARGIN_LATE_DEF; |
| iSyncMarginText.min = PVPLAYERENGINE_CONFIG_SYNCMARGIN_EARLY_DEF; |
| iSyncMarginText.max = PVPLAYERENGINE_CONFIG_SYNCMARGIN_LATE_DEF; |
| |
| iNodeUuids.clear(); |
| } |
| |
| |
| void PVPlayerEngine::Construct(PVCommandStatusObserver* aCmdStatusObserver, |
| PVErrorEventObserver *aErrorEventObserver, |
| PVInformationalEventObserver *aInfoEventObserver) |
| { |
| iCommandIdMut.Create(); |
| iOOTSyncCommandSem.Create(); |
| iThreadSafeQueue.Configure(this); |
| |
| iCmdStatusObserver = aCmdStatusObserver; |
| iInfoEventObserver = aInfoEventObserver; |
| iErrorEventObserver = aErrorEventObserver; |
| |
| // Allocate memory for vectors |
| // If a leave occurs, let it bubble up |
| iCurrentCmd.reserve(1); |
| iCmdToCancel.reserve(1); |
| iCmdToDlaCancel.reserve(1); |
| iPendingCmds.reserve(PVPLAYERENGINE_NUM_COMMANDS); |
| iPvmiKvpCapNConfig.reserve(20); |
| |
| iDatapathList.reserve(3); |
| |
| iCurrentContextList.reserve(12); |
| |
| iMetadataIFList.reserve(6); |
| iMetadataIFList.clear(); |
| |
| iMetadataKeyReleaseList.reserve(6); |
| iMetadataKeyReleaseList.clear(); |
| |
| iMetadataValueReleaseList.reserve(6); |
| iMetadataValueReleaseList.clear(); |
| |
| AddToScheduler(); |
| |
| // Retrieve the logger object |
| iLogger = PVLogger::GetLoggerObject("PVPlayerEngine"); |
| iPerfLogger = PVLogger::GetLoggerObject("pvplayerdiagnostics.perf.engine"); |
| iReposLogger = PVLogger::GetLoggerObject("pvplayerrepos.engine"); |
| |
| // Initialize the playback clock to use tickcount timebase |
| iPlaybackClock.SetClockTimebase(iPlaybackTimebase); |
| uint32 starttime = 0; |
| bool overflow = 0; |
| iPlaybackClock.SetStartTime32(starttime, PVMF_MEDIA_CLOCK_MSEC, overflow); |
| iPlaybackClock.ConstructMediaClockNotificationsInterface(iClockNotificationsInf, *this, |
| iCurrCallbackTimerLatency); |
| |
| // Initialize the OSCL timer for polling checks |
| iPollingCheckTimer = OSCL_NEW(OsclTimer<OsclMemAllocator>, ("playerengine_pollingcheck")); |
| iPollingCheckTimer->SetObserver(this); |
| iPollingCheckTimer->SetFrequency(10); // 100 ms resolution |
| |
| iWatchDogTimer = OSCL_NEW(PVPlayerWatchdogTimer, (this)); |
| |
| PVPlayerRegistryPopulator::Populate(iPlayerNodeRegistry, iPlayerRecognizerRegistry); |
| |
| return; |
| } |
| |
| |
| void PVPlayerEngine::Run() |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Run() In")); |
| int32 leavecode = 0; |
| |
| /* Engine AO will execute commands in the following sequence |
| * 1) If Engine state is Resetting, which will happen when Engine does ErrorHandling, |
| * processing Reset or CancelAllCommands |
| * issued by the app, engine will not try to execute any other command during this state. |
| * 2) If Engine is not in Resetting state then it will process commands in the following order, which ever is true: |
| * (i) If Engine needs to do Error handling because of some error from Source Node or Datapath. |
| * Either start error handling or complete it. |
| * (ii) If Engine has Reset or CancelAllCommands in CurrentCommandQueue, |
| * engine will do CommandComplete for the CurrentCommand. |
| * (iii) If Engine has Prepare in CurrentCommandQueue, engine will call DoPrepare again |
| * as a part of track selection logic |
| * (iv) If Engine has CancelAllCommands or CancelAcquireLicense in Pending CommandQueue, |
| * engine will start Cancel commands. |
| * (v) Go for Rollover if in Init State and Roll-over is ongoing. |
| * (vi) Process which ever command is pushed in Pending queue. |
| * Engine will process any one of the command as listed above in the same order. |
| * Every time engine AO is scheduled, engine will go through |
| * these steps. |
| */ |
| |
| if (iState == PVP_ENGINE_STATE_RESETTING) |
| { |
| //this means error handling, reset or cancelall is still in progress |
| //pls note that the state will be set to idle |
| //in either HandleSourceNodeReset or HandleDataPathReset |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::Run() Return engine in resetting state, No processing until engine is in Idle state")); |
| return; |
| } |
| |
| /* Check if ErrorHandling request was made */ |
| if (!iPendingCmds.empty()) |
| { |
| switch (iPendingCmds.top().GetCmdType()) |
| { |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_ADD_DATA_SOURCE: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_INIT: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_PAUSE: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_SET_PLAYBACK_RANGE: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_SET_PLAYBACK_RATE: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_STOP: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_CANCEL_ALL_COMMANDS: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_GENERAL: |
| { |
| // go in error handling right away |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Run() Processing Error Handling request")); |
| PVMFStatus retVal = DoErrorHandling(); |
| if (retVal == PVMFSuccess) |
| { |
| iPendingCmds.pop(); |
| RunIfNotReady(); // schedule the engine AO to process other commands in queue if any. |
| } |
| return; |
| } |
| |
| default: |
| break; |
| } |
| } |
| |
| // if current command being processed is reset or cancelAll and |
| // Player engine state is idle then remove the data source |
| // and do reset/cancelAll command complete |
| // OR |
| // if current command being processed is prepare, need to call |
| // DoPrepare again because of track selection |
| if (!iCurrentCmd.empty()) |
| { |
| if ((iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_RESET) || |
| (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_CANCEL_COMMAND) || |
| (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_CANCEL_ALL_COMMANDS)) |
| { |
| if (iState != PVP_ENGINE_STATE_IDLE) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() Engine not in Idle State, asserting")); |
| OSCL_ASSERT(false); |
| } |
| // First destroy all datapaths. |
| DoRemoveAllSinks(); |
| // now remove the source node. |
| if (iDataSource) |
| { |
| RemoveDataSourceSync(*iDataSource); |
| } |
| |
| EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), PVMFSuccess); |
| } |
| else if (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_PREPARE) |
| { |
| PVMFStatus cmdstatus = DoPrepare(iCurrentCmd[0]); |
| |
| if (cmdstatus != PVMFSuccess && cmdstatus != PVMFPending) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() Command failed CmdId %d Status %d", |
| iCurrentCmd[0].GetCmdId(), cmdstatus)); |
| EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), cmdstatus); |
| } |
| } |
| } |
| |
| /* Check if Cancel()/CancelAll()/CancelAcquireLicense request was made */ |
| if (!iPendingCmds.empty()) |
| { |
| if (iPendingCmds.top().GetCmdType() == PVP_ENGINE_COMMAND_CANCEL_COMMAND) |
| { |
| // Process it right away |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Run() Processing Cancel() request")); |
| PVPlayerEngineCommand cmd(iPendingCmds.top()); |
| iPendingCmds.pop(); |
| if ((!iCurrentCmd.empty()) && (iCurrentCmd[0].GetCmdId() == cmd.GetParam(0).int32_value)) |
| { |
| // We need to cancel the ongoing command. In this case issue cancelAll |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::Run: Command to Cancel is ongoing so issue CancelAll")); |
| DoCancelAllCommands(cmd); |
| } |
| else |
| { |
| // The command to be cancelled is in the pending queue |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::Run: Command to Cancel is pending so just Cancel")); |
| DoCancelCommand(cmd); |
| } |
| return; |
| } |
| else if (iPendingCmds.top().GetCmdType() == PVP_ENGINE_COMMAND_CANCEL_ALL_COMMANDS) |
| { |
| // Process it right away |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Run() Processing CancelAll() request")); |
| PVPlayerEngineCommand cmd(iPendingCmds.top()); |
| iPendingCmds.pop(); |
| DoCancelAllCommands(cmd); |
| return; |
| } |
| else if (iPendingCmds.top().GetCmdType() == PVP_ENGINE_COMMAND_CANCEL_ACQUIRE_LICENSE) |
| { |
| // Process it right away |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Run() Processing CancelAcquireLicesense() request")); |
| PVPlayerEngineCommand cmd(iPendingCmds.top()); |
| iPendingCmds.pop(); |
| DoCancelAcquireLicense(cmd); |
| return; |
| } |
| } |
| |
| if (iRollOverState == RollOverStateStart) |
| { |
| if (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_INIT) |
| { |
| //implies that we are doing a source rollover |
| PVMFStatus status = |
| DoSourceNodeRollOver(iCurrentCmd[0].iCmdId, |
| iCurrentCmd[0].iContextData); |
| |
| if (status != PVMFPending) |
| { |
| if (CheckForSourceRollOver()) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() DoSourceNodeRollOver Failed, alternate source node for rollover is available")); |
| RunIfNotReady(); |
| return; |
| } |
| // roll over failed |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() DoSourceNodeRollOver Failed, go in error handling")); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() Already EH pending, should never happen")); |
| return; |
| } |
| // go in error handling |
| iCommandCompleteStatusInErrorHandling = status; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_INIT, NULL, NULL, NULL, false); |
| iRollOverState = RollOverStateIdle; |
| return; |
| } |
| else |
| { |
| iRollOverState = RollOverStateInProgress; |
| } |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() Source Roll Over In Progress But Incorrect Engine Cmd")); |
| EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), PVMFErrInvalidState); |
| } |
| return; |
| } |
| |
| if (iRollOverState == RollOverStateInProgress) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::RunL() Source Roll Over In Progress ")); |
| return; |
| } |
| |
| // Handle other requests normally |
| if (!iPendingCmds.empty() && iCurrentCmd.empty()) |
| { |
| // Retrieve the first pending command from queue |
| PVPlayerEngineCommand cmd(iPendingCmds.top()); |
| iPendingCmds.pop(); |
| |
| // Put in on the current command queue |
| leavecode = 0; |
| OSCL_TRY(leavecode, iCurrentCmd.push_front(cmd)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() Command could not be pushed onto iCurrentCmd vector")); |
| EngineCommandCompleted(cmd.GetCmdId(), cmd.GetContext(), PVMFErrNoMemory); |
| return;); |
| |
| // Process the command according to the cmd type |
| PVMFStatus cmdstatus = PVMFSuccess; |
| bool ootsync = false; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Run() Processing command with type=%d", cmd.GetCmdType())); |
| switch (cmd.GetCmdType()) |
| { |
| case PVP_ENGINE_COMMAND_GET_SDK_INFO: |
| cmdstatus = DoGetSDKInfo(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_GET_SDK_MODULE_INFO: |
| // GetSDKModuleInfo is currently not supported |
| cmdstatus = PVMFErrNotSupported; |
| break; |
| |
| case PVP_ENGINE_COMMAND_SET_LOG_APPENDER: |
| cmdstatus = DoSetLogAppender(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_REMOVE_LOG_APPENDER: |
| cmdstatus = DoRemoveLogAppender(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_SET_LOG_LEVEL: |
| cmdstatus = DoSetLogLevel(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_GET_LOG_LEVEL: |
| cmdstatus = DoGetLogLevel(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_QUERY_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_GET_PVPLAYER_STATE_OOTSYNC: |
| ootsync = true; |
| cmdstatus = DoGetPVPlayerState(cmd, true); |
| break; |
| |
| case PVP_ENGINE_COMMAND_ADD_DATA_SOURCE: |
| cmdstatus = DoAddDataSource(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_INIT: |
| cmdstatus = DoInit(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_GET_METADATA_KEY: |
| cmdstatus = DoGetMetadataKey(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_GET_METADATA_VALUE: |
| cmdstatus = DoGetMetadataValue(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_RELEASE_METADATA_VALUE: |
| cmdstatus = DoReleaseMetadataValues(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_ADD_DATA_SINK: |
| cmdstatus = DoAddDataSink(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_GET_CURRENT_POSITION: |
| cmdstatus = DoGetCurrentPosition(cmd, false); |
| break; |
| |
| case PVP_ENGINE_COMMAND_GET_CURRENT_POSITION_OOTSYNC: |
| ootsync = true; |
| cmdstatus = DoGetCurrentPosition(cmd, true); |
| break; |
| |
| case PVP_ENGINE_COMMAND_SET_PLAYBACK_RANGE: |
| cmdstatus = DoSetPlaybackRange(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_GET_PLAYBACK_RANGE: |
| cmdstatus = DoGetPlaybackRange(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_SET_PLAYBACK_RATE: |
| cmdstatus = DoSetPlaybackRate(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_GET_PLAYBACK_RATE: |
| cmdstatus = DoGetPlaybackRate(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_GET_PLAYBACK_MINMAX_RATE: |
| cmdstatus = DoGetPlaybackMinMaxRate(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_PREPARE: |
| cmdstatus = DoPrepare(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_START: |
| cmdstatus = DoStart(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_PAUSE: |
| case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_ENDOFCLIP: |
| case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_ENDTIME_REACHED: |
| cmdstatus = DoPause(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_RESUME: |
| cmdstatus = DoResume(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_STOP: |
| cmdstatus = DoStop(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_REMOVE_DATA_SINK: |
| cmdstatus = DoRemoveDataSink(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_RESET: |
| cmdstatus = DoReset(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_REMOVE_DATA_SOURCE: |
| cmdstatus = DoRemoveDataSource(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_CAPCONFIG_SET_PARAMETERS: |
| cmdstatus = DoCapConfigSetParameters(cmd, false); |
| break; |
| |
| case PVP_ENGINE_COMMAND_CAPCONFIG_SET_PARAMETERS_OOTSYNC: |
| ootsync = true; |
| cmdstatus = DoCapConfigSetParameters(cmd, true); |
| break; |
| |
| case PVP_ENGINE_COMMAND_CAPCONFIG_GET_PARAMETERS_OOTSYNC: |
| ootsync = true; |
| cmdstatus = DoGetParametersSync(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_CAPCONFIG_RELEASE_PARAMETERS_OOTSYNC: |
| ootsync = true; |
| cmdstatus = DoReleaseParametersSync(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_CAPCONFIG_VERIFY_PARAMETERS_OOTSYNC: |
| ootsync = true; |
| cmdstatus = DoVerifyParametersSync(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_WCHAR: |
| case PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_CHAR: |
| cmdstatus = DoAcquireLicense(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_BUFFER_UNDERFLOW: |
| cmdstatus = DoSourceUnderflowAutoPause(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_RESUME_DUE_TO_BUFFER_DATAREADY: |
| cmdstatus = DoSourceDataReadyAutoResume(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_CAPCONFIG_SET_OBSERVER_OOTSYNC: |
| ootsync = true; |
| cmdstatus = DoSetObserverSync(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_GET_LICENSE_STATUS_OOTSYNC: |
| ootsync = true; |
| cmdstatus = DoGetLicenseStatusSync(cmd); |
| break; |
| |
| case PVP_ENGINE_COMMAND_CANCEL_COMMAND: |
| // Cancel() should not be handled here |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() CancelCommand should be not handled in here. Return Failure")); |
| cmdstatus = PVMFFailure; |
| break; |
| |
| case PVP_ENGINE_COMMAND_CANCEL_ALL_COMMANDS: |
| // CancelAll() should not be handled here |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() CancelAllCommands should be not handled in here. Return Failure")); |
| cmdstatus = PVMFFailure; |
| break; |
| |
| default: |
| // Just handle as "not supported" |
| cmdstatus = PVMFErrNotSupported; |
| break; |
| } |
| |
| if (ootsync) |
| { |
| OOTSyncCommandComplete(cmd, cmdstatus); |
| // Empty out the current cmd vector and set active if there are other pending commands |
| iCurrentCmd.erase(iCurrentCmd.begin()); |
| if (!iPendingCmds.empty()) |
| { |
| RunIfNotReady(); |
| } |
| } |
| else if (cmdstatus != PVMFSuccess && cmdstatus != PVMFPending) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::Run() Command failed CmdId %d Status %d", |
| cmd.GetCmdId(), cmdstatus)); |
| EngineCommandCompleted(cmd.GetCmdId(), cmd.GetContext(), cmdstatus); |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::Run() Out")); |
| } |
| |
| bool PVPlayerEngine::FindNodeTypeByNode(PVMFNodeInterface* aUnknownNode, PVPlayerNodeType& aNodeType, int32& aDatapathListIndex) |
| { |
| if (aUnknownNode == NULL) |
| { |
| // Cannot check with node pointer being NULL |
| // Might bring up false positives |
| aNodeType = PVP_NODETYPE_UNKNOWN; |
| aDatapathListIndex = -1; |
| return false; |
| } |
| |
| // Go through each engine datapath and find whether |
| // the specified node is a dec node or sink node |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDecNode == aUnknownNode) |
| { |
| aNodeType = PVP_NODETYPE_DECODER; |
| aDatapathListIndex = i; |
| return true; |
| } |
| else if (iDatapathList[i].iSinkNode == aUnknownNode) |
| { |
| aNodeType = PVP_NODETYPE_SINK; |
| aDatapathListIndex = i; |
| return true; |
| } |
| } |
| |
| // Could not determine the types |
| aNodeType = PVP_NODETYPE_UNKNOWN; |
| aDatapathListIndex = -1; |
| return false; |
| } |
| |
| bool PVPlayerEngine::FindTrackForDatapathUsingMimeString(bool& aVideoTrack, bool& aAudioTrack, bool& aTextTrack, PVPlayerEngineDatapath* aDatapath) |
| { |
| if (aDatapath->iTrackInfo) |
| { |
| char* mimeString = aDatapath->iTrackInfo->getTrackMimeType().get_str(); |
| |
| if ((pv_mime_strcmp(mimeString, PVMF_MIME_YUV420) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_YUV422) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_RGB8) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_RGB12) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_RGB16) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_RGB24) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_M4V) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_H2631998) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_H2632000) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_H264_VIDEO_RAW) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_H264_VIDEO_MP4) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_H264_VIDEO) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_WMV) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_REAL_VIDEO) == 0)) |
| { |
| aVideoTrack = true; |
| aAudioTrack = false; |
| aTextTrack = false; |
| return true; |
| } |
| else if (pv_mime_strcmp(mimeString, PVMF_MIME_3GPP_TIMEDTEXT) == 0) |
| { |
| aVideoTrack = false; |
| aAudioTrack = false; |
| aTextTrack = true; |
| return true; |
| } |
| else if ((pv_mime_strcmp(mimeString, PVMF_MIME_PCM) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_PCM8) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_PCM16) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_PCM16_BE) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_ULAW) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_ALAW) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_AMR) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_AMRWB) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_AMR_IETF) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_AMRWB_IETF) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_AMR_IF2) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_EVRC) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_MP3) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_ADIF) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_ADTS) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_LATM) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_MPEG4_AUDIO) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_G723) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_G726) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_WMA) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_ASF_AMR) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_REAL_AUDIO) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_ASF_MPEG4_AUDIO) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_3640) == 0)) |
| { |
| aVideoTrack = false; |
| aAudioTrack = true; |
| aTextTrack = false; |
| return true; |
| } |
| else |
| { |
| aVideoTrack = false; |
| aAudioTrack = false; |
| aTextTrack = false; |
| return false; |
| } |
| } |
| |
| aVideoTrack = false; |
| aAudioTrack = false; |
| aTextTrack = false; |
| return false; |
| } |
| |
| bool PVPlayerEngine::FindDatapathForTrackUsingMimeString(bool aVideoTrack, bool aAudioTrack, bool aTextTrack, int32& aDatapathListIndex) |
| { |
| for (uint32 i = 0; i < iDatapathList.size(); i++) |
| { |
| if (iDatapathList[i].iTrackInfo) |
| { |
| char* mimeString = iDatapathList[i].iTrackInfo->getTrackMimeType().get_str(); |
| if (aVideoTrack) |
| { |
| // find a datapath using the mime string for Video track |
| if ((pv_mime_strcmp(mimeString, PVMF_MIME_YUV420) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_YUV422) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_RGB8) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_RGB12) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_RGB16) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_RGB24) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_M4V) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_H2631998) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_H2632000) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_H264_VIDEO_RAW) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_H264_VIDEO_MP4) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_H264_VIDEO) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_WMV) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_REAL_VIDEO) == 0)) |
| { |
| aDatapathListIndex = i; |
| return true; |
| } |
| } |
| else if (aAudioTrack) |
| { |
| // find a datapath using the mime string for Audio track |
| if ((pv_mime_strcmp(mimeString, PVMF_MIME_PCM) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_PCM8) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_PCM16) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_PCM16_BE) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_ULAW) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_ALAW) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_AMR) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_AMRWB) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_AMR_IETF) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_AMRWB_IETF) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_AMR_IF2) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_EVRC) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_MP3) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_ADIF) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_ADTS) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_LATM) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_MPEG4_AUDIO) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_G723) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_G726) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_WMA) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_ASF_AMR) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_REAL_AUDIO) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_ASF_MPEG4_AUDIO) == 0) || |
| (pv_mime_strcmp(mimeString, PVMF_MIME_3640) == 0)) |
| { |
| aDatapathListIndex = i; |
| return true; |
| } |
| } |
| else if (aTextTrack) |
| { |
| // find a datapath using the mime string for Text track |
| if (pv_mime_strcmp(mimeString, PVMF_MIME_3GPP_TIMEDTEXT) == 0) |
| { |
| aDatapathListIndex = i; |
| return true; |
| } |
| } |
| else |
| { |
| // Unknown track |
| aDatapathListIndex = -1; |
| return false; |
| } |
| } |
| } |
| |
| // Unknown track |
| aDatapathListIndex = -1; |
| return false; |
| } |
| |
| |
| void PVPlayerEngine::NodeCommandCompleted(const PVMFCmdResp& aResponse) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::NodeCommandCompleted() In")); |
| |
| int32 leavecode = 0; |
| |
| // Check if a cancel command completed |
| uint32* context_uint32 = (uint32*)(aResponse.GetContext()); |
| if (context_uint32 == &iNumberCancelCmdPending) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::NodeCommandCompleted() Cancel in node completed for cancel command. Pending %d", iNumberCancelCmdPending)); |
| --iNumberCancelCmdPending; |
| |
| // If cmd to cancel was GetMetadataKeys() or GetMetadataValues() and if these commands return with |
| // success then first release the memory for the node which return with success. |
| if (iCmdToCancel[0].GetCmdType() == PVP_ENGINE_COMMAND_GET_METADATA_KEY && |
| aResponse.GetCmdStatus() == PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::NodeCommandCompleted() Cancel in node completed for GetMetadataKeys with success, release memory.")); |
| // Release the memory allocated for the metadata keys |
| uint32 numkeysadded = iGetMetadataKeysParam.iKeyList->size() - iGetMetadataKeysParam.iNumKeyEntriesInList; |
| uint32 start = iGetMetadataKeysParam.iNumKeyEntriesInList; |
| uint32 end = iGetMetadataKeysParam.iNumKeyEntriesInList + numkeysadded - 1; |
| |
| PVMFMetadataExtensionInterface* mdif = iMetadataIFList[iGetMetadataKeysParam.iCurrentInterfaceIndex].iInterface; |
| OSCL_ASSERT(mdif != NULL); |
| mdif->ReleaseNodeMetadataKeys(*(iGetMetadataKeysParam.iKeyList), start, end); |
| } |
| else if (iCmdToCancel[0].GetCmdType() == PVP_ENGINE_COMMAND_GET_METADATA_VALUE && |
| aResponse.GetCmdStatus() == PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::NodeCommandCompleted() Cancel in node completed for GetMetadataValue with success, release memory.")); |
| // Release the memory allocated for the metadata values |
| uint32 numkeysadded = iGetMetadataValuesParam.iKeyList->size() - iGetMetadataValuesParam.iNumValueEntriesInList; |
| uint32 start = iGetMetadataValuesParam.iNumValueEntriesInList; |
| uint32 end = iGetMetadataValuesParam.iNumValueEntriesInList + numkeysadded - 1; |
| |
| PVMFMetadataExtensionInterface* mdif = iMetadataIFList[iGetMetadataValuesParam.iCurrentInterfaceIndex].iInterface; |
| OSCL_ASSERT(mdif != NULL); |
| mdif->ReleaseNodeMetadataValues(*(iGetMetadataValuesParam.iValueList), start, end); |
| |
| iReleaseMetadataValuesPending = false; |
| } |
| |
| if (iNumberCancelCmdPending == 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::NodeCommandCompleted() Cancelling of all node/datapath commands complete, now reset all nodes")); |
| // Clear the CancelCmd queue as the cmd has been cancelled. |
| iCmdToCancel.clear(); |
| |
| RemoveDatapathContextFromList(); // empty left over contexts from cancelled datapath commands |
| // Now reset the source node |
| PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, -1, NULL, -1); |
| |
| PVMFCommandId cmdid = -1; |
| int32 leavecode = 0; |
| OSCL_TRY(leavecode, cmdid = iSourceNode->Reset(iSourceNodeSessionId, (OsclAny*)context)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::NodeCommandCompleted() Reset on iSourceNode did a leave!")); |
| FreeEngineContext(context); |
| OSCL_ASSERT(false); |
| return); |
| |
| SetEngineState(PVP_ENGINE_STATE_RESETTING); |
| } |
| return; |
| } |
| |
| PVPlayerEngineContext* nodecontext = (PVPlayerEngineContext*)(aResponse.GetContext()); |
| OSCL_ASSERT(nodecontext); |
| |
| // Ignore other node completion if cancelling |
| if (!iCmdToCancel.empty() || (CheckForPendingErrorHandlingCmd() && aResponse.GetCmdStatus() == PVMFErrCancelled)) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::NodeCommandCompleted() Node command completion ignored due to cancel process, id=%d", aResponse.GetCmdId())); |
| // Remove the context from the list |
| FreeEngineContext(nodecontext); |
| return; |
| } |
| |
| // Process according to cmd type in the engine context data, node type, or engine state |
| if (nodecontext->iCmdType == PVP_CMD_SinkNodeSkipMediaData) |
| { |
| HandleSinkNodeSkipMediaData(*nodecontext, aResponse); |
| } |
| else if (nodecontext->iCmdType == PVP_CMD_SinkNodeSkipMediaDataDuringPlayback) |
| { |
| HandleSinkNodeSkipMediaDataDuringPlayback(*nodecontext, aResponse); |
| } |
| else if (nodecontext->iCmdType == PVP_CMD_SinkNodeAutoPause) |
| { |
| HandleSinkNodePause(*nodecontext, aResponse); |
| } |
| else if (nodecontext->iCmdType == PVP_CMD_SinkNodeAutoResume) |
| { |
| HandleSinkNodeResume(*nodecontext, aResponse); |
| } |
| else if (nodecontext->iCmdType == PVP_CMD_DecNodeReset) |
| { |
| HandleDecNodeReset(*nodecontext, aResponse); |
| } |
| else if (nodecontext->iCmdType == PVP_CMD_SinkNodeReset) |
| { |
| HandleSinkNodeReset(*nodecontext, aResponse); |
| } |
| else if (nodecontext->iCmdType == PVP_CMD_GetNodeMetadataKey) |
| { |
| // Ignore the command status since it does not matter and continue going through the metadata interface list |
| |
| // Determine the number of keys were added |
| uint32 numkeysadded = iGetMetadataKeysParam.iKeyList->size() - iGetMetadataKeysParam.iNumKeyEntriesInList; |
| if (numkeysadded > 0) |
| { |
| // Create an entry for the metadata key release list |
| PVPlayerEngineMetadataReleaseEntry releaseentry; |
| releaseentry.iMetadataIFListIndex = iGetMetadataKeysParam.iCurrentInterfaceIndex; |
| // Save the start and end indices into the key list for keys that this node added |
| releaseentry.iStartIndex = iGetMetadataKeysParam.iNumKeyEntriesInList; |
| releaseentry.iEndIndex = iGetMetadataKeysParam.iNumKeyEntriesInList + numkeysadded - 1; |
| |
| leavecode = 0; |
| OSCL_TRY(leavecode, iMetadataKeyReleaseList.push_back(releaseentry)); |
| if (leavecode != 0) |
| { |
| // An element could not be added to the release list vector |
| // so notify completion of GetMetadataKey() command with memory failure |
| EngineCommandCompleted(nodecontext->iCmdId, (OsclAny*)nodecontext->iCmdContext, PVMFErrNoMemory); |
| |
| // Release the last requested keys |
| PVMFMetadataExtensionInterface* mdif = iMetadataIFList[releaseentry.iMetadataIFListIndex].iInterface; |
| OSCL_ASSERT(mdif != NULL); |
| mdif->ReleaseNodeMetadataKeys(*(iGetMetadataKeysParam.iKeyList), releaseentry.iStartIndex, releaseentry.iEndIndex); |
| |
| // Release the memory allocated for rest of the metadata keys |
| while (iMetadataKeyReleaseList.empty() == false) |
| { |
| mdif = iMetadataIFList[iMetadataKeyReleaseList[0].iMetadataIFListIndex].iInterface; |
| OSCL_ASSERT(mdif != NULL); |
| mdif->ReleaseNodeMetadataKeys(*(iGetMetadataKeysParam.iKeyList), iMetadataKeyReleaseList[0].iStartIndex, iMetadataKeyReleaseList[0].iEndIndex); |
| iMetadataKeyReleaseList.erase(iMetadataKeyReleaseList.begin()); |
| } |
| |
| // Remove the context from the list |
| // Need to do this since we're calling return from here |
| FreeEngineContext(nodecontext); |
| return; |
| } |
| |
| // Update the variables tracking the key list |
| if (iGetMetadataKeysParam.iNumKeyEntriesToFill != -1) |
| { |
| iGetMetadataKeysParam.iNumKeyEntriesToFill -= numkeysadded; |
| } |
| iGetMetadataKeysParam.iNumKeyEntriesInList += numkeysadded; |
| } |
| |
| // Update the interface index to the next one |
| ++iGetMetadataKeysParam.iCurrentInterfaceIndex; |
| |
| // Loop until GetNodeMetadataKeys() is called or command is completed |
| bool endloop = false; |
| while (endloop == false) |
| { |
| // Check if there is another metadata interface to check |
| if (iGetMetadataKeysParam.iCurrentInterfaceIndex < iMetadataIFList.size()) |
| { |
| PVMFMetadataExtensionInterface* mdif = iMetadataIFList[iGetMetadataKeysParam.iCurrentInterfaceIndex].iInterface; |
| OSCL_ASSERT(mdif != NULL); |
| PVMFSessionId sessionid = iMetadataIFList[iGetMetadataKeysParam.iCurrentInterfaceIndex].iSessionId; |
| |
| // Determine the number of keys available for the specified query key |
| int32 numkeys = mdif->GetNumMetadataKeys(iGetMetadataKeysParam.iQueryKey); |
| if (numkeys <= 0) |
| { |
| // Since there is no keys from this node, go to the next one |
| ++iGetMetadataKeysParam.iCurrentInterfaceIndex; |
| continue; |
| } |
| |
| // If more key entries can be added, retrieve from the node |
| if (iGetMetadataKeysParam.iNumKeyEntriesToFill > 0 || iGetMetadataKeysParam.iNumKeyEntriesToFill == -1) |
| { |
| int32 leavecode = 0; |
| PVMFCommandId cmdid = -1; |
| PVPlayerEngineContext* newcontext = AllocateEngineContext(iMetadataIFList[iGetMetadataKeysParam.iCurrentInterfaceIndex].iEngineDatapath, iMetadataIFList[iGetMetadataKeysParam.iCurrentInterfaceIndex].iNode, NULL, nodecontext->iCmdId, nodecontext->iCmdContext, PVP_CMD_GetNodeMetadataKey); |
| OSCL_TRY(leavecode, cmdid = mdif->GetNodeMetadataKeys(sessionid, |
| *(iGetMetadataKeysParam.iKeyList), |
| 0, |
| iGetMetadataKeysParam.iNumKeyEntriesToFill, |
| iGetMetadataKeysParam.iQueryKey, |
| (OsclAny*)newcontext)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::NodeCommandCompleted() GetNodeMetadataKeys on a node did a leave!")); |
| FreeEngineContext(newcontext); |
| // Go to the next metadata IF in the list and continue |
| ++iGetMetadataKeysParam.iCurrentInterfaceIndex; |
| continue;); |
| |
| // End the loop since GetNodeMetadataKeys() was called |
| endloop = true; |
| } |
| else |
| { |
| // Retrieved the requested number of keys so notify completion of GetMetadataKey() command |
| EngineCommandCompleted(nodecontext->iCmdId, (OsclAny*)nodecontext->iCmdContext, aResponse.GetCmdStatus()); |
| |
| // Release the memory allocated for the metadata keys |
| while (iMetadataKeyReleaseList.empty() == false) |
| { |
| mdif = iMetadataIFList[iMetadataKeyReleaseList[0].iMetadataIFListIndex].iInterface; |
| OSCL_ASSERT(mdif != NULL); |
| mdif->ReleaseNodeMetadataKeys(*(iGetMetadataKeysParam.iKeyList), iMetadataKeyReleaseList[0].iStartIndex, iMetadataKeyReleaseList[0].iEndIndex); |
| iMetadataKeyReleaseList.erase(iMetadataKeyReleaseList.begin()); |
| } |
| |
| // End the loop since finished command |
| endloop = true; |
| } |
| } |
| else |
| { |
| // No more so notify completion of GetMetadataKey() command |
| EngineCommandCompleted(nodecontext->iCmdId, (OsclAny*)nodecontext->iCmdContext, aResponse.GetCmdStatus()); |
| |
| // Release the memory allocated for the metadata keys |
| while (iMetadataKeyReleaseList.empty() == false) |
| { |
| PVMFMetadataExtensionInterface* mdif = iMetadataIFList[iMetadataKeyReleaseList[0].iMetadataIFListIndex].iInterface; |
| OSCL_ASSERT(mdif != NULL); |
| mdif->ReleaseNodeMetadataKeys(*(iGetMetadataKeysParam.iKeyList), iMetadataKeyReleaseList[0].iStartIndex, iMetadataKeyReleaseList[0].iEndIndex); |
| iMetadataKeyReleaseList.erase(iMetadataKeyReleaseList.begin()); |
| } |
| |
| // End the loop since reached the end of the metadata IF list |
| endloop = true; |
| } |
| } |
| } |
| else if (nodecontext->iCmdType == PVP_CMD_GetNodeMetadataValue) |
| { |
| // Ignore the command status since it does not matter and continue going through the metadata interface list |
| |
| // Determine the number of values were added |
| uint32 numvaluesadded = iGetMetadataValuesParam.iValueList->size() - iGetMetadataValuesParam.iNumValueEntriesInList; |
| if (numvaluesadded > 0) |
| { |
| // Create an entry for the metadata value release list |
| PVPlayerEngineMetadataReleaseEntry releaseentry; |
| releaseentry.iMetadataIFListIndex = iGetMetadataValuesParam.iCurrentInterfaceIndex; |
| // Save the start and end indices into the value list for values that this node added |
| releaseentry.iStartIndex = iGetMetadataValuesParam.iNumValueEntriesInList; |
| releaseentry.iEndIndex = iGetMetadataValuesParam.iNumValueEntriesInList + numvaluesadded - 1; |
| |
| leavecode = 0; |
| OSCL_TRY(leavecode, iMetadataValueReleaseList.push_back(releaseentry)); |
| if (leavecode != 0) |
| { |
| // An element could not be added to the release list vector |
| // so notify completion of GetMetadataValue() command with memory failure |
| EngineCommandCompleted(nodecontext->iCmdId, (OsclAny*)nodecontext->iCmdContext, PVMFErrNoMemory); |
| |
| // Release the last requested values |
| PVMFMetadataExtensionInterface* mdif = iMetadataIFList[releaseentry.iMetadataIFListIndex].iInterface; |
| OSCL_ASSERT(mdif != NULL); |
| mdif->ReleaseNodeMetadataValues(*(iGetMetadataValuesParam.iValueList), releaseentry.iStartIndex, releaseentry.iEndIndex); |
| |
| // Release the memory allocated for rest of the metadata values |
| while (iMetadataValueReleaseList.empty() == false) |
| { |
| mdif = iMetadataIFList[iMetadataValueReleaseList[0].iMetadataIFListIndex].iInterface; |
| OSCL_ASSERT(mdif != NULL); |
| mdif->ReleaseNodeMetadataValues(*(iGetMetadataValuesParam.iValueList), iMetadataValueReleaseList[0].iStartIndex, iMetadataValueReleaseList[0].iEndIndex); |
| iMetadataValueReleaseList.erase(iMetadataValueReleaseList.begin()); |
| } |
| |
| // Remove the context from the list |
| // Need to do this since we're calling return from here |
| FreeEngineContext(nodecontext); |
| return; |
| } |
| |
| // Update the variables tracking the value list |
| if (iGetMetadataValuesParam.iNumValueEntriesToFill != -1) |
| { |
| iGetMetadataValuesParam.iNumValueEntriesToFill -= numvaluesadded; |
| } |
| iGetMetadataValuesParam.iNumValueEntriesInList += numvaluesadded; |
| } |
| |
| // Update the interface index to the next one |
| ++iGetMetadataValuesParam.iCurrentInterfaceIndex; |
| |
| // Loop until GetNodeMetadataValues() is called or command is completed |
| bool endloop = false; |
| while (endloop == false) |
| { |
| // Check if there is another metadata interface to check |
| if (iGetMetadataValuesParam.iCurrentInterfaceIndex < iMetadataIFList.size()) |
| { |
| PVMFMetadataExtensionInterface* mdif = iMetadataIFList[iGetMetadataValuesParam.iCurrentInterfaceIndex].iInterface; |
| OSCL_ASSERT(mdif != NULL); |
| PVMFSessionId sessionid = iMetadataIFList[iGetMetadataValuesParam.iCurrentInterfaceIndex].iSessionId; |
| |
| // Determine the number of values available for the specified key list |
| int32 numvalues = mdif->GetNumMetadataValues(*(iGetMetadataValuesParam.iKeyList)); |
| if (numvalues > 0) |
| { |
| // Add it to the total available |
| *(iGetMetadataValuesParam.iNumAvailableValues) += numvalues; |
| } |
| else |
| { |
| // Since there is no values from this node, go to the next one |
| ++iGetMetadataValuesParam.iCurrentInterfaceIndex; |
| continue; |
| } |
| |
| // If more value entries can be added, retrieve from the node |
| if (iGetMetadataValuesParam.iNumValueEntriesToFill > 0 || iGetMetadataValuesParam.iNumValueEntriesToFill == -1) |
| { |
| int32 leavecode = 0; |
| PVMFCommandId cmdid = -1; |
| PVPlayerEngineContext* newcontext = AllocateEngineContext(iMetadataIFList[iGetMetadataValuesParam.iCurrentInterfaceIndex].iEngineDatapath, iMetadataIFList[iGetMetadataValuesParam.iCurrentInterfaceIndex].iNode, NULL, nodecontext->iCmdId, nodecontext->iCmdContext, PVP_CMD_GetNodeMetadataValue); |
| OSCL_TRY(leavecode, cmdid = mdif->GetNodeMetadataValues(sessionid, |
| *(iGetMetadataValuesParam.iKeyList), |
| *(iGetMetadataValuesParam.iValueList), |
| 0, |
| iGetMetadataValuesParam.iNumValueEntriesToFill, |
| (OsclAny*)newcontext)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::NodeCommandCompleted() GetNodeMetadataValues on a node did a leave!")); |
| FreeEngineContext(newcontext); |
| // Go to the next metadata IF in the list and continue |
| ++iGetMetadataValuesParam.iCurrentInterfaceIndex; |
| continue;); |
| |
| // End the loop since GetNodeMetadataValues() was called |
| endloop = true; |
| } |
| else |
| { |
| // Retrieved requested number of values so notify completion of GetMetadataValue() command |
| EngineCommandCompleted(nodecontext->iCmdId, (OsclAny*)nodecontext->iCmdContext, aResponse.GetCmdStatus()); |
| |
| if (iMetadataValuesCopiedInCallBack) |
| { |
| // Release the memory allocated for the metadata values |
| while (iMetadataValueReleaseList.empty() == false) |
| { |
| mdif = iMetadataIFList[iMetadataValueReleaseList[0].iMetadataIFListIndex].iInterface; |
| OSCL_ASSERT(mdif != NULL); |
| mdif->ReleaseNodeMetadataValues(*(iGetMetadataValuesParam.iValueList), iMetadataValueReleaseList[0].iStartIndex, iMetadataValueReleaseList[0].iEndIndex); |
| iMetadataValueReleaseList.erase(iMetadataValueReleaseList.begin()); |
| } |
| } |
| else |
| { |
| iReleaseMetadataValuesPending = true; |
| } |
| |
| // End the loop since finished command |
| endloop = true; |
| } |
| } |
| else |
| { |
| // No more so notify completion of GetMetadataValue() command |
| EngineCommandCompleted(nodecontext->iCmdId, (OsclAny*)nodecontext->iCmdContext, aResponse.GetCmdStatus()); |
| |
| if (iMetadataValuesCopiedInCallBack) |
| { |
| // Release the memory allocated for the metadata values |
| while (iMetadataValueReleaseList.empty() == false) |
| { |
| PVMFMetadataExtensionInterface* mdif = iMetadataIFList[iMetadataValueReleaseList[0].iMetadataIFListIndex].iInterface; |
| OSCL_ASSERT(mdif != NULL); |
| mdif->ReleaseNodeMetadataValues(*(iGetMetadataValuesParam.iValueList), iMetadataValueReleaseList[0].iStartIndex, iMetadataValueReleaseList[0].iEndIndex); |
| iMetadataValueReleaseList.erase(iMetadataValueReleaseList.begin()); |
| } |
| } |
| else |
| { |
| iReleaseMetadataValuesPending = true; |
| } |
| |
| // End the loop since reached the end of the metadata IF list |
| endloop = true; |
| } |
| } |
| } |
| else if (nodecontext->iNode == iSourceNode) |
| { |
| if (nodecontext->iCmdType == PVP_CMD_SourceNodeQueryDataSourcePositionDuringPlayback) |
| { |
| HandleSourceNodeQueryDataSourcePositionDuringPlayback(*nodecontext, aResponse); |
| } |
| else if (nodecontext->iCmdType == PVP_CMD_SourceNodeSetDataSourcePositionDuringPlayback) |
| { |
| HandleSourceNodeSetDataSourcePositionDuringPlayback(*nodecontext, aResponse); |
| } |
| else if (nodecontext->iCmdType == PVP_CMD_SourceNodeSetDataSourceDirection) |
| { |
| HandleSourceNodeSetDataSourceDirection(*nodecontext, aResponse); |
| } |
| else if (nodecontext->iCmdType == PVP_CMD_SourceNodeSetDataSourceRate) |
| { |
| HandleSourceNodeSetDataSourceRate(*nodecontext, aResponse); |
| } |
| else |
| { |
| 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: |
| HandleSourceNodeQueryInterfaceOptional(*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; |
| |
| default: |
| break; |
| } |
| } |
| } |
| else if (iState == PVP_ENGINE_STATE_PREPARING) |
| { |
| switch (nodecontext->iCmdType) |
| { |
| case PVP_CMD_SinkNodeQueryCapConfigIF: |
| HandleSinkNodeQueryCapConfigIF(*nodecontext, aResponse); |
| break; |
| |
| case PVP_CMD_SinkNodeInit: |
| HandleSinkNodeInit(*nodecontext, aResponse); |
| break; |
| |
| case PVP_CMD_DecNodeQueryCapConfigIF: |
| HandleDecNodeQueryCapConfigIF(*nodecontext, aResponse); |
| break; |
| |
| case PVP_CMD_DecNodeInit: |
| HandleDecNodeInit(*nodecontext, aResponse); |
| break; |
| |
| case PVP_CMD_SinkNodeDecNodeReset: |
| HandleSinkNodeDecNodeReset(*nodecontext, aResponse); |
| break; |
| |
| case PVP_CMD_SinkNodeQuerySyncCtrlIF: |
| case PVP_CMD_SinkNodeQueryMetadataIF: |
| HandleSinkNodeQueryInterfaceOptional(*nodecontext, aResponse); |
| break; |
| |
| case PVP_CMD_DecNodeQueryMetadataIF: |
| HandleDecNodeQueryInterfaceOptional(*nodecontext, aResponse); |
| break; |
| |
| default: |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::NodeCommandCompleted() Invalid node command type in PVP_ENGINE_STATE_PREPARING. Asserting")); |
| OSCL_ASSERT(false); |
| break; |
| } |
| } |
| else |
| { |
| // Unknown node command completion. Assert |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::NodeCommandCompleted() Unknown node command completion")); |
| OSCL_ASSERT(false); |
| } |
| |
| // Remove the context from the list |
| FreeEngineContext(nodecontext); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::NodeCommandCompleted() Out")); |
| } |
| |
| |
| void PVPlayerEngine::HandleNodeInformationalEvent(const PVMFAsyncEvent& aEvent) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleNodeInformationalEvent() In")); |
| |
| PVMFNodeInterface* nodeorigin = (PVMFNodeInterface*)(aEvent.GetContext()); |
| |
| PVPlayerNodeType nodetype = PVP_NODETYPE_UNKNOWN; |
| int32 datapathindex = -1; |
| |
| // Process the info event based on the node type reporting the event |
| if (nodeorigin == iSourceNode) |
| { |
| HandleSourceNodeInfoEvent(aEvent); |
| } |
| else if (FindNodeTypeByNode(nodeorigin, nodetype, datapathindex) == true) |
| { |
| if (nodetype == PVP_NODETYPE_SINK) |
| { |
| HandleSinkNodeInfoEvent(aEvent, datapathindex); |
| } |
| else 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 == &iNumberCancelCmdPending) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Cancel in datapath completed for cancel command. Pending %d", iNumberCancelCmdPending)); |
| --iNumberCancelCmdPending; |
| if (iNumberCancelCmdPending == 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Cancelling of all node/datapath commands complete, now reset all nodes")); |
| // Clear the CancelCmd queue as the cmd has been cancelled. |
| iCmdToCancel.clear(); |
| |
| RemoveDatapathContextFromList(); // empty left over contexts from cancelled datapath commands |
| // Now reset the source node |
| PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, -1, NULL, -1); |
| |
| PVMFCommandId cmdid = -1; |
| int32 leavecode = 0; |
| OSCL_TRY(leavecode, cmdid = iSourceNode->Reset(iSourceNodeSessionId, (OsclAny*)context)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Reset on iSourceNode did a leave!")); |
| FreeEngineContext(context); |
| OSCL_ASSERT(false); |
| return); |
| |
| SetEngineState(PVP_ENGINE_STATE_RESETTING); |
| } |
| return; |
| } |
| |
| PVPlayerEngineContext* datapathcontext = (PVPlayerEngineContext*)aContext; |
| OSCL_ASSERT(datapathcontext); |
| |
| // Ignore other datapath event if cancelling |
| if (!iCmdToCancel.empty() || (CheckForPendingErrorHandlingCmd() && (aCmdResp && aCmdResp->GetCmdStatus() == PVMFErrCancelled))) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Datapath event ignored due to cancel process")); |
| // Remove the context from the list |
| FreeEngineContext(datapathcontext); |
| return; |
| } |
| |
| // Process the datapath event based on the engine state |
| if (iState == PVP_ENGINE_STATE_PREPARING) |
| { |
| switch (datapathcontext->iCmdType) |
| { |
| case PVP_CMD_DPPrepare: |
| HandleDatapathPrepare(*datapathcontext, aEventStatus, aCmdResp); |
| break; |
| |
| case PVP_CMD_DPStart: |
| HandleDatapathStart(*datapathcontext, aEventStatus, aCmdResp); |
| break; |
| |
| default: |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Invalid datapath command type in PVP_ENGINE_STATE_PREPARING.")); |
| break; |
| } |
| } |
| else if (iState == PVP_ENGINE_STATE_PAUSING) |
| { |
| 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.")); |
| break; |
| } |
| } |
| else if (iState == PVP_ENGINE_STATE_RESETTING) |
| { |
| switch (datapathcontext->iCmdType) |
| { |
| case PVP_CMD_DPReset: |
| HandleDatapathReset(*datapathcontext, aEventStatus, aCmdResp); |
| break; |
| |
| default: |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Invalid datapath command type in PVP_ENGINE_STATE_RESETTING")); |
| break; |
| } |
| } |
| else |
| { |
| // Unknown datapath. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Invalid state for datapath command completion.")); |
| } |
| |
| // Remove the context from the list |
| FreeEngineContext(datapathcontext); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandlePlayerDatapathEvent() Out")); |
| } |
| |
| void PVPlayerEngine::NotificationsInterfaceDestroyed() |
| { |
| iClockNotificationsInf = NULL; |
| } |
| |
| void PVPlayerEngine::ProcessCallBack(uint32 aCallBackID, PVTimeComparisonUtils::MediaTimeStatus aTimerAccuracy, uint32 aDelta, |
| const OsclAny* acontextData, PVMFStatus aStatus) |
| { |
| OSCL_UNUSED_ARG(aTimerAccuracy); |
| OSCL_UNUSED_ARG(aDelta); |
| OSCL_UNUSED_ARG(acontextData); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::TimeoutOccurred() Timer for PlayStatus event triggered")); |
| |
| if (aCallBackID == iPlayStatusCallbackTimerID) |
| { |
| //Callback timer needs to be restarted if status is success |
| if ((PVMFSuccess == aStatus) && iPlayStatusTimerEnabled) |
| { |
| SendPositionStatusUpdate(); |
| iPlayStatusTimerEnabled = false; |
| iPlayStatusCallbackTimerID = 0; |
| |
| StartPlaybackStatusTimer(); |
| } |
| else |
| { |
| if (aStatus == PVMFErrCallbackClockStopped) |
| { |
| iPlayStatusTimerEnabled = false; |
| iPlayStatusCallbackTimerID = 0; |
| } |
| } |
| } |
| } |
| void PVPlayerEngine::SendPositionStatusUpdate(void) |
| { |
| PVPPlaybackPosition curpos; |
| curpos.iPosUnit = iPBPosStatusUnit; |
| GetPlaybackClockPosition(curpos); |
| |
| uint8 poslocalbuffer[8]; |
| oscl_memset(poslocalbuffer, 0, 8); |
| poslocalbuffer[0] = 1; |
| switch (iPBPosStatusUnit) |
| { |
| case PVPPBPOSUNIT_SEC: |
| oscl_memcpy(&poslocalbuffer[4], &(curpos.iPosValue.sec_value), sizeof(uint32)); |
| break; |
| |
| case PVPPBPOSUNIT_MIN: |
| oscl_memcpy(&poslocalbuffer[4], &(curpos.iPosValue.min_value), sizeof(uint32)); |
| break; |
| |
| case PVPPBPOSUNIT_MILLISEC: |
| default: |
| oscl_memcpy(&poslocalbuffer[4], &(curpos.iPosValue.millisec_value), sizeof(uint32)); |
| break; |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| PVMFBasicErrorInfoMessage* infomsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoPlaybackPositionStatus, puuid, NULL)); |
| // EventData parameter will be deprecated, and curpos will not be sent through EventData in future. |
| SendInformationalEvent(PVMFInfoPositionStatus, OSCL_STATIC_CAST(PVInterface*, infomsg), (OsclAny*)&curpos, poslocalbuffer, 8); |
| infomsg->removeRef(); |
| } |
| |
| |
| void PVPlayerEngine::TimeoutOccurred(int32 timerID, int32 /*timeoutInfo*/) |
| { |
| if (timerID == PVPLAYERENGINE_TIMERID_ENDTIMECHECK) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::TimeoutOccurred() Timer for EndTime check triggered")); |
| |
| PVPPlaybackPosition curpos; |
| curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| GetPlaybackClockPosition(curpos); |
| |
| if (iCurrentEndPosition.iIndeterminate || iCurrentEndPosition.iPosUnit != PVPPBPOSUNIT_MILLISEC) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::TimeoutOccurred() End time unit is invalid. Disabling end time check.")); |
| iEndTimeCheckEnabled = false; |
| iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_ENDTIMECHECK); |
| OSCL_ASSERT(false); |
| return; |
| } |
| |
| if (curpos.iPosValue.millisec_value >= iCurrentEndPosition.iPosValue.millisec_value) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::TimeoutOccurred() Specified end time reached so issuing pause command")); |
| |
| iEndTimeCheckEnabled = false; |
| iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_ENDTIMECHECK); |
| // Issues end time reached command |
| AddCommandToQueue(PVP_ENGINE_COMMAND_PAUSE_DUE_TO_ENDTIME_REACHED, NULL, NULL, NULL, false); |
| } |
| else if (!iEndTimeCheckEnabled) |
| { |
| iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_ENDTIMECHECK); |
| } |
| } |
| } |
| |
| void PVPlayerEngine::RecognizeCompleted(PVMFFormatType aSourceFormatType, OsclAny* aContext) |
| { |
| // Check if a cancel command completed |
| uint32* context_uint32 = (uint32*)(aContext); |
| if (context_uint32 == &iNumberCancelCmdPending) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::RecognizeCompleted() Recognize request cancelled")); |
| --iNumberCancelCmdPending; |
| if (iNumberCancelCmdPending == 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::RecognizeCompleted() Cancelling of all node/datapath commands complete, now reset all nodes")); |
| // Clear the CancelCmd queue as the cmd has been cancelled. |
| iCmdToCancel.clear(); |
| |
| RemoveDatapathContextFromList(); // empty left over contexts from cancelled datapath commands |
| // Now reset the source node |
| PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, -1, NULL, -1); |
| |
| PVMFCommandId cmdid = -1; |
| int32 leavecode = 0; |
| OSCL_TRY(leavecode, cmdid = iSourceNode->Reset(iSourceNodeSessionId, (OsclAny*)context)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::RecognizeCompleted() Reset on iSourceNode did a leave!")); |
| FreeEngineContext(context); |
| OSCL_ASSERT(false); |
| return); |
| |
| SetEngineState(PVP_ENGINE_STATE_RESETTING); |
| } |
| return; |
| } |
| |
| // Ignore recognize completion if cancelling |
| if (!iCmdToCancel.empty() || CheckForPendingErrorHandlingCmd()) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::RecognizeCompleted() Recognize completion ignored due to cancel process")); |
| // Remove the context from the list |
| FreeEngineContext((PVPlayerEngineContext*)(aContext)); |
| return; |
| } |
| |
| // Save the recognized source format |
| iSourceFormatType = aSourceFormatType; |
| |
| // Free the engine context after saving the cmd id and context |
| PVPlayerEngineContext* reccontext = (PVPlayerEngineContext*)(aContext); |
| OSCL_ASSERT(reccontext != NULL); |
| PVCommandId cmdid = reccontext->iCmdId; |
| OsclAny* cmdcontext = reccontext->iCmdContext; |
| FreeEngineContext(reccontext); |
| |
| // Start the source node creation and setup sequence |
| PVMFStatus retval = DoSetupSourceNode(cmdid, cmdcontext); |
| |
| if (retval != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::RecognizeCompleted() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| // Queue up Error Handling |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::RecognizeCompleted() DoSetupSourceNode failed, Add EH command")); |
| iCommandCompleteStatusInErrorHandling = retval; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_ADD_DATA_SOURCE, NULL, NULL, NULL, false); |
| } |
| return; |
| } |
| } |
| |
| //A callback from the threadsafe queue |
| void PVPlayerEngine::ThreadSafeQueueDataAvailable(ThreadSafeQueue* aQueue) |
| { |
| OSCL_UNUSED_ARG(aQueue); |
| |
| //pull all available data off the thread-safe queue and transfer |
| //it to the internal queue. |
| for (uint32 ndata = 1; ndata;) |
| { |
| ThreadSafeQueueId id; |
| OsclAny* data; |
| ndata = iThreadSafeQueue.DeQueue(id, data); |
| if (ndata) |
| { |
| PVPlayerEngineCommand* cmd = (PVPlayerEngineCommand*)data; |
| AddCommandToQueue(cmd->iCmdType |
| , cmd->iContextData |
| , &cmd->iParamVector |
| , &cmd->iUuid |
| , true//assume all out-of-thread data is an API command. |
| , (PVCommandId*)&id);//use the command ID that was returned to the caller. |
| OSCL_DELETE(cmd); |
| } |
| } |
| } |
| |
| PVMFStatus PVPlayerEngine::DoOOTSyncCommand(int32 aCmdType, |
| Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator>* aParamVector, |
| const PVUuid* aUuid) |
| { |
| //Called from out-of-thread to perform a synchronous command |
| |
| |
| //Add a PVMFStatus* to the end of the command param vec to hold the result. |
| PVMFStatus status; |
| PVPlayerEngineCommandParamUnion param; |
| param.pOsclAny_value = (OsclAny*) & status; |
| aParamVector->push_back(param); |
| |
| //push the command across the thread boundary |
| PVCommandId id = 0; |
| PVPlayerEngineCommand* cmd = OSCL_NEW(PVPlayerEngineCommand, (aCmdType, id, NULL, aParamVector)); |
| if (aUuid) |
| cmd->SetUuid(*aUuid); |
| iThreadSafeQueue.AddToQueue(cmd); |
| |
| //block and wait for completion by engine thread. |
| iOOTSyncCommandSem.Wait(); |
| return status; |
| } |
| |
| void PVPlayerEngine::OOTSyncCommandComplete(PVPlayerEngineCommand& aCmd, PVMFStatus aStatus) |
| { |
| //Called in engine thread to complete an out-of-thread synchronous command |
| |
| //Put the result status into the last element of the command param vector. |
| PVMFStatus* status = (PVMFStatus*)(aCmd.GetParam(aCmd.iParamVector.size() - 1).pOsclAny_value); |
| OSCL_ASSERT(status); |
| *status = aStatus; |
| |
| //Signal the calling thread. |
| iOOTSyncCommandSem.Signal(); |
| } |
| |
| PVCommandId PVPlayerEngine::AddCommandToQueue(int32 aCmdType, OsclAny* aContextData, |
| Oscl_Vector<PVPlayerEngineCommandParamUnion, OsclMemAllocator>* aParamVector, |
| const PVUuid* aUuid, bool aAPICommand, PVCommandId* aId) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::AddCommandToQueue() In CmdType %d, CmdId %d", aCmdType, iCommandId)); |
| |
| PVCommandId commandId; |
| if (aId) |
| { |
| //This command is being transferred from the thread-safe queue to the |
| //internal queue, in engine thread context. |
| //The input ID is the one that was returned to the |
| //caller, so use that ID instead of generating a new one. |
| commandId = *aId; |
| } |
| else |
| { |
| //Generate the next command ID, being careful to avoid thread contention |
| //for "iCommandId". |
| iCommandIdMut.Lock(); |
| commandId = iCommandId; |
| ++iCommandId; |
| if (iCommandId == 0x7FFFFFFF) |
| { |
| iCommandId = 0; |
| } |
| iCommandIdMut.Unlock(); |
| |
| //If this is from outside engine thread context, then push the command across the |
| //thread boundary. |
| if (!iThreadSafeQueue.IsInThread()) |
| { |
| PVPlayerEngineCommand* cmd = OSCL_NEW(PVPlayerEngineCommand, (aCmdType, commandId, aContextData, aParamVector, aAPICommand)); |
| if (aUuid) |
| cmd->SetUuid(*aUuid); |
| iThreadSafeQueue.AddToQueue(cmd, (ThreadSafeQueueId*)&commandId); |
| return commandId; |
| } |
| } |
| |
| PVPlayerEngineCommand cmd(aCmdType, commandId, aContextData, aParamVector, aAPICommand); |
| if (aUuid) |
| { |
| cmd.SetUuid(*aUuid); |
| } |
| |
| int32 leavecode = 0; |
| OSCL_TRY(leavecode, iPendingCmds.push(cmd)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::AddCommandToQueue() Adding command to pending command list did a leave!")); |
| OSCL_ASSERT(false); |
| return -1;); |
| |
| // if engine needs to queue any error handling command set the engine state as PVP_ENGINE_STATE_ERROR. |
| switch (aCmdType) |
| { |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_ADD_DATA_SOURCE: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_INIT: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_PAUSE: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_SET_PLAYBACK_RANGE: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_SET_PLAYBACK_RATE: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_STOP: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_CANCEL_ALL_COMMANDS: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_GENERAL: |
| SetEngineState(PVP_ENGINE_STATE_ERROR); |
| SendInformationalEvent(PVMFInfoErrorHandlingStart, NULL); |
| break; |
| |
| default: |
| break; |
| } |
| |
| RunIfNotReady(); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE, |
| (0, "PVPlayerEngine::AddCommandToQueue() Type=%d ID=%d APIcmd=%d Tick=%d", |
| aCmdType, cmd.GetCmdId(), aAPICommand, OsclTickCount::TickCount())); |
| |
| return cmd.GetCmdId(); |
| } |
| |
| |
| void PVPlayerEngine::SetEngineState(PVPlayerEngineState aState) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::SetEngineState() In Current state %d, New state %d", iState, aState)); |
| iState = aState; |
| } |
| |
| |
| PVPlayerState PVPlayerEngine::GetPVPlayerState(void) |
| { |
| switch (iState) |
| { |
| case PVP_ENGINE_STATE_IDLE: |
| case PVP_ENGINE_STATE_INITIALIZING: |
| return PVP_STATE_IDLE; |
| |
| case PVP_ENGINE_STATE_INITIALIZED: |
| case PVP_ENGINE_STATE_PREPARING: |
| case PVP_ENGINE_STATE_TRACK_SELECTION_1_DONE: |
| case PVP_ENGINE_STATE_TRACK_SELECTION_2_DONE: |
| case PVP_ENGINE_STATE_TRACK_SELECTION_3_DONE: |
| return PVP_STATE_INITIALIZED; |
| |
| case PVP_ENGINE_STATE_PREPARED: |
| case PVP_ENGINE_STATE_STARTING: |
| return PVP_STATE_PREPARED; |
| |
| case PVP_ENGINE_STATE_STARTED: |
| case PVP_ENGINE_STATE_AUTO_PAUSING: |
| case PVP_ENGINE_STATE_AUTO_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_RESETTING: |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| return PVP_STATE_ERROR; |
| } |
| else |
| { |
| return PVP_STATE_IDLE; |
| } |
| } |
| |
| case PVP_ENGINE_STATE_ERROR: |
| return PVP_STATE_ERROR; |
| |
| default: |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::GetPVPlayerState() Unknown engine state. Asserting")); |
| OSCL_ASSERT(false); |
| break; |
| } |
| |
| return PVP_STATE_ERROR; |
| } |
| |
| |
| void PVPlayerEngine::GetPlaybackClockPosition(PVPPlaybackPosition& aClockPos) |
| { |
| 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, PVMF_MEDIA_CLOCK_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; |
| int32 datapathIndex = -1; |
| |
| // Search from the datapath list. |
| // 1) Try for video track |
| bool retVal = FindDatapathForTrackUsingMimeString(true, false, false, datapathIndex); |
| if (retVal == false) |
| { |
| // Video track not available, look for text track |
| retVal = FindDatapathForTrackUsingMimeString(false, false, true, datapathIndex); |
| if (retVal == false) |
| { |
| // Text track also not avaliable, look for audio track |
| retVal = FindDatapathForTrackUsingMimeString(false, true, false, datapathIndex); |
| if (retVal == false) |
| { |
| // Track is not available to do the conversion |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertToMillisec() Track not selected for conversion")); |
| return PVMFErrArgument; |
| } |
| } |
| } |
| |
| // Track avalaible. |
| track = iDatapathList[datapathIndex].iTrackInfo; |
| |
| // Convert the sample number to time in milliseconds |
| PVMFTimestamp framets = 0; |
| if (iSourceNodeTrackLevelInfoIF->GetTimestampForSampleNumber(*track, aPBPos.iPosValue.samplenum_value, framets) != PVMFSuccess) |
| { |
| // Conversion failed |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertToMillisec() Sample number to time conversion failed")); |
| return PVMFErrArgument; |
| } |
| |
| aTimeMS = framets; |
| } |
| break; |
| |
| case PVPPBPOSUNIT_DATAPOSITION: |
| { |
| if (iSourceNodeTrackLevelInfoIF == NULL) |
| { |
| // The source node doesn't have the ext IF to convert data position to time |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertToMillisec() Data position to time conversion not available")); |
| return PVMFErrArgument; |
| } |
| |
| // Go through each active track and find the minimum time for given data position |
| bool mintsvalid = false; |
| PVMFTimestamp mints = 0xFFFFFFFF; |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath) |
| { |
| PVMFTimestamp curts = 0; |
| if (iSourceNodeTrackLevelInfoIF->GetTimestampForDataPosition(*(iDatapathList[i].iTrackInfo), aPBPos.iPosValue.datapos_value, curts) != PVMFSuccess) |
| { |
| // Conversion failed |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertToMillisec() Data position to time conversion failed")); |
| } |
| else |
| { |
| // Conversion succeeded. Save only if it is the minimum encountered so far. |
| mintsvalid = true; |
| if (curts < mints) |
| { |
| mints = curts; |
| } |
| } |
| } |
| } |
| |
| if (mintsvalid == false) |
| { |
| // Conversion on all active tracks failed |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertToMillisec() Data position to time conversion could not be done on any active track")); |
| return PVMFErrArgument; |
| } |
| |
| aTimeMS = mints; |
| } |
| break; |
| |
| case PVPPBPOSUNIT_PLAYLIST: |
| { |
| switch (aPBPos.iPlayListPosUnit) |
| { |
| case PVPPBPOSUNIT_MILLISEC: |
| aTimeMS = aPBPos.iPlayListPosValue.millisec_value; |
| break; |
| |
| case PVPPBPOSUNIT_SEC: |
| aTimeMS = aPBPos.iPlayListPosValue.sec_value * 1000; |
| break; |
| |
| case PVPPBPOSUNIT_MIN: |
| aTimeMS = aPBPos.iPlayListPosValue.min_value * 60000; |
| break; |
| |
| case PVPPBPOSUNIT_HOUR: |
| aTimeMS = aPBPos.iPlayListPosValue.hour_value * 3600000; |
| break; |
| |
| default: |
| // Don't support the other units for now |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertToMillisec() Unsupported playlist position units")); |
| return PVMFErrArgument; |
| } |
| } |
| break; |
| |
| default: |
| // Don't support the other units for now |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertToMillisec() Unsupported position units")); |
| return PVMFErrArgument; |
| } |
| |
| if (owallclockunits == true) |
| { |
| if ((aTimeMS > iSourceDurationInMS) && (iSourceDurationAvailable == true)) |
| { |
| //cap time to clip duration |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVPlayerEngine::ConvertToMillisec() Capping value - Acutal=%d, CappedValue=%d", |
| aTimeMS, iSourceDurationInMS)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_DEBUG, (0, "PVPlayerEngine::ConvertToMillisec() Capping value - Acutal=%d, CappedValue=%d", |
| aTimeMS, iSourceDurationInMS)); |
| aTimeMS = iSourceDurationInMS; |
| } |
| else |
| { |
| // just pass the converted time even if duration is not available and let |
| // source node handle the request. |
| } |
| } |
| |
| if (aPBPos.iPosUnit == PVPPBPOSUNIT_PLAYLIST) |
| { |
| aPBPos.iPlayListPosValue.millisec_value = aTimeMS; |
| aPBPos.iPlayListPosUnit = PVPPBPOSUNIT_MILLISEC; |
| } |
| else |
| { |
| aPBPos.iPosValue.millisec_value = aTimeMS; |
| aPBPos.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| } |
| iTargetNPT = aTimeMS; |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::ConvertToMillisec() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::ConvertFromMillisec(uint32 aTimeMS, PVPPlaybackPosition& aPBPos) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::ConvertFromMillisec() In")); |
| |
| // Convert to specified time units |
| switch (aPBPos.iPosUnit) |
| { |
| case PVPPBPOSUNIT_MILLISEC: |
| aPBPos.iPosValue.millisec_value = aTimeMS; |
| break; |
| |
| case PVPPBPOSUNIT_SEC: |
| aPBPos.iPosValue.sec_value = aTimeMS / 1000; |
| break; |
| |
| case PVPPBPOSUNIT_MIN: |
| aPBPos.iPosValue.min_value = aTimeMS / 60000; |
| break; |
| |
| case PVPPBPOSUNIT_HOUR: |
| aPBPos.iPosValue.hour_value = aTimeMS / 3600000; |
| break; |
| |
| case PVPPBPOSUNIT_SMPTE: |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::ConvertFromMillisec() SMPTE units not supported yet")); |
| return PVMFErrArgument; |
| |
| case PVPPBPOSUNIT_PERCENT: |
| { |
| if (iSourceDurationAvailable == false) |
| { |
| // Duration info not available from source node so can't convert |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertFromMillisec() Duration not available so can't convert")); |
| return PVMFErrArgument; |
| } |
| |
| if (iSourceDurationInMS == 0) |
| { |
| // Duration is 0 so can't convert |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertFromMillisec() Duration value is 0 so can't convert")); |
| return PVMFErrArgument; |
| } |
| |
| if (aTimeMS >= iSourceDurationInMS) |
| { |
| // Put a ceiling of 100% |
| aPBPos.iPosValue.percent_value = 100; |
| } |
| else |
| { |
| // Calculate percentage of playback, avoiding overflow |
| if (iSourceDurationInMS >= PVP_MIN_PLAYSTATUS_PERCENT_OVERFLOW_THRESHOLD) |
| { |
| aPBPos.iPosValue.percent_value = aTimeMS / (iSourceDurationInMS / 100); |
| } |
| else |
| { |
| aPBPos.iPosValue.percent_value = (aTimeMS * 100) / iSourceDurationInMS; |
| } |
| } |
| } |
| break; |
| |
| case PVPPBPOSUNIT_SAMPLENUMBER: |
| { |
| if (iSourceNodeTrackLevelInfoIF == NULL) |
| { |
| // The source node doesn't have the query IF to convert time to sample number |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertFromMillisec() Time to sample numberconversion not available")); |
| return PVMFErrArgument; |
| } |
| |
| // Determine which track to use for conversion. |
| // Give preference to video track, then text, and finally audio |
| PVMFTrackInfo* track = NULL; |
| int32 datapathIndex = -1; |
| |
| // Search from the datapath list. |
| // 1) Try for video track |
| bool retVal = FindDatapathForTrackUsingMimeString(true, false, false, datapathIndex); |
| if (retVal == false) |
| { |
| // Video track not available, look for text track |
| retVal = FindDatapathForTrackUsingMimeString(false, false, true, datapathIndex); |
| if (retVal == false) |
| { |
| // Text track also not avaliable, look for audio track |
| retVal = FindDatapathForTrackUsingMimeString(false, true, false, datapathIndex); |
| if (retVal == false) |
| { |
| // Track is not available to do the conversion |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertToMillisec() Track not selected for conversion")); |
| return PVMFErrArgument; |
| } |
| } |
| } |
| |
| // Track avalaible. |
| track = iDatapathList[datapathIndex].iTrackInfo; |
| |
| // Convert the time to sample number |
| PVMFTimestamp ts = aTimeMS; |
| uint32 samplenum = 0; |
| if (iSourceNodeTrackLevelInfoIF->GetSampleNumberForTimestamp(*track, ts, samplenum) != PVMFSuccess) |
| { |
| // Conversion failed |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertFromMillisec() Sample number to time conversion failed")); |
| return PVMFErrArgument; |
| } |
| |
| aPBPos.iPosValue.samplenum_value = samplenum; |
| } |
| break; |
| |
| case PVPPBPOSUNIT_DATAPOSITION: |
| { |
| if (iSourceNodeTrackLevelInfoIF == NULL) |
| { |
| // The source node doesn't have the ext IF to convert time to data position |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertFromMillisec() Time to data position conversion not available in source node")); |
| return PVMFErrArgument; |
| } |
| |
| // Query each active track for its data position |
| // Return the max data position |
| PVMFTimestamp ts = aTimeMS; |
| uint32 maxdatapos = 0; |
| bool maxdataposvalid = false; |
| |
| // Go through each active track |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath) |
| { |
| uint32 curdatapos = 0; |
| // Convert the time to data position |
| if (iSourceNodeTrackLevelInfoIF->GetDataPositionForTimestamp(*(iDatapathList[i].iTrackInfo), ts, curdatapos) != PVMFSuccess) |
| { |
| // Conversion failed |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertFromMillisec() Time to data position conversion failed")); |
| } |
| else |
| { |
| // Save the data position if it is greater than |
| // any position encountered so far. |
| maxdataposvalid = true; |
| if (curdatapos > maxdatapos) |
| { |
| maxdatapos = curdatapos; |
| } |
| } |
| } |
| } |
| |
| if (maxdataposvalid == false) |
| { |
| // Conversion failed for all active tracks |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::ConvertFromMillisec() Track not selected for conversion")); |
| return PVMFErrArgument; |
| } |
| // Save the data position to return |
| aPBPos.iPosValue.datapos_value = maxdatapos; |
| } |
| break;; |
| |
| default: |
| // Don't support the other units for now |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::ConvertFromMillisec() Unsupported position units")); |
| return PVMFErrArgument; |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::ConvertFromMillisec() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| void PVPlayerEngine::EngineCommandCompleted(PVCommandId aId, OsclAny* aContext, PVMFStatus aStatus, PVInterface* aExtInterface, OsclAny* aEventData, int32 aEventDataSize) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::EngineCommandCompleted() In CmdId %d, Status %d", aId, aStatus)); |
| |
| // Update the current command vector |
| |
| // Assert if the current cmd is not saved or the cmd ID does not match |
| OSCL_ASSERT(iCurrentCmd.size() == 1); |
| OSCL_ASSERT(iCurrentCmd[0].GetCmdId() == aId); |
| |
| // Empty out the current cmd vector and set active if there are other pending commands |
| PVPlayerEngineCommand completedcmd(iCurrentCmd[0]); |
| iCurrentCmd.erase(iCurrentCmd.begin()); |
| if (!iPendingCmds.empty()) |
| { |
| RunIfNotReady(); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE, |
| (0, "PVPlayerEngine::EngineCommandCompleted() Type=%d ID=%d APIcmd=%d Tick=%d", |
| completedcmd.GetCmdType(), completedcmd.GetCmdId(), completedcmd.IsAPICommand(), OsclTickCount::TickCount())); |
| |
| // Send informational event or send other callback if needed |
| switch (completedcmd.GetCmdType()) |
| { |
| case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_ENDOFCLIP: |
| SendEndOfClipInfoEvent(aStatus, aExtInterface); |
| break; |
| |
| case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_ENDTIME_REACHED: |
| SendEndTimeReachedInfoEvent(aStatus, aExtInterface); |
| break; |
| |
| case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_BUFFER_UNDERFLOW: |
| SendSourceUnderflowInfoEvent(aStatus, aExtInterface); |
| break; |
| |
| case PVP_ENGINE_COMMAND_RESUME_DUE_TO_BUFFER_DATAREADY: |
| SendSourceDataReadyInfoEvent(aStatus, aExtInterface); |
| break; |
| |
| case PVP_ENGINE_COMMAND_CAPCONFIG_SET_PARAMETERS: |
| // Send callback to the specified observer |
| if (iCfgCapCmdObserver) |
| { |
| iCfgCapCmdObserver->SignalEvent(aId); |
| } |
| break; |
| |
| default: |
| // None to be sent |
| break; |
| } |
| |
| // Send the command completed event |
| if (iCmdStatusObserver) |
| { |
| if (aId != -1 && completedcmd.IsAPICommand()) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::EngineCommandCompleted() Notifying engine command as completed. CmdId %d Status %d", aId, aStatus)); |
| PVCmdResponse cmdcompleted(aId, aContext, aStatus, aExtInterface, aEventData, aEventDataSize); |
| iCmdStatusObserver->CommandCompleted(cmdcompleted); |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::EngineCommandCompleted() aId is -1 or not an API command. CmdType %d", completedcmd.GetCmdType())); |
| } |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::EngineCommandCompleted() iCmdStatusObserver is NULL")); |
| } |
| } |
| |
| |
| void PVPlayerEngine::SendInformationalEvent(PVMFEventType aEventType, PVInterface* aExtInterface, OsclAny* aEventData, uint8* aLocalBuffer, uint32 aLocalBufferSize) |
| { |
| // Send the info event if observer has been specified |
| if (iInfoEventObserver) |
| { |
| PVAsyncInformationalEvent infoevent((PVEventType)aEventType, NULL, aExtInterface, (PVExclusivePtr)aEventData, aLocalBuffer, aLocalBufferSize); |
| iInfoEventObserver->HandleInformationalEvent(infoevent); |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::SendInformationalEvent() iInfoEventObserver is NULL")); |
| } |
| } |
| |
| |
| void PVPlayerEngine::SendErrorEvent(PVMFEventType aEventType, PVInterface* aExtInterface, OsclAny* aEventData, uint8* aLocalBuffer, uint32 aLocalBufferSize) |
| { |
| // Send the error event if observer has been specified |
| if (iErrorEventObserver) |
| { |
| PVAsyncErrorEvent errorevent((PVEventType)aEventType, NULL, aExtInterface, (PVExclusivePtr)aEventData, aLocalBuffer, aLocalBufferSize); |
| iErrorEventObserver->HandleErrorEvent(errorevent); |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::SendErrorEvent() iErrorEventObserver is NULL")); |
| } |
| } |
| |
| |
| void PVPlayerEngine::DoCancelCommand(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelCommand() In")); |
| |
| // Boolean to check if the command is cancelled or not. |
| bool commandCancelled = false; |
| |
| // cmd to cancel either has been completed or is in pending queue. |
| // Create a temporary queue for pending commands and current command if any. |
| OsclPriorityQueue<PVPlayerEngineCommand, OsclMemAllocator, Oscl_Vector<PVPlayerEngineCommand, OsclMemAllocator>, PVPlayerEngineCommandCompareLess> iTempPendingCmds; |
| Oscl_Vector<PVPlayerEngineCommand, OsclMemAllocator> iTempCurrentCmd; |
| // Copy the pending commands to the new queue |
| iTempPendingCmds = iPendingCmds; |
| while (!iTempPendingCmds.empty()) |
| { |
| // Get the queue from the top |
| PVPlayerEngineCommand cmd(iTempPendingCmds.top()); |
| // Check if it needs to be cancelled |
| if (aCmd.GetParam(0).int32_value == cmd.GetCmdId()) |
| { |
| // Found command to be cancelled in the Pending Queue, set the |
| // commandCancelled boolean to true. |
| commandCancelled = true; |
| |
| // Remove it from the pending commands queue |
| iPendingCmds.remove(cmd); |
| // Save it temporary as "current command" and then cancel it. If CurrentCmd has some |
| // command, first move it to TempCurrentCmd queue. |
| if (!iCurrentCmd.empty()) |
| { |
| iTempCurrentCmd.push_front(iCurrentCmd[0]); |
| iCurrentCmd.erase(iCurrentCmd.begin()); |
| } |
| |
| iCurrentCmd.push_front(cmd); |
| EngineCommandCompleted(cmd.GetCmdId(), cmd.GetContext(), PVMFErrCancelled); |
| |
| // send command complete for CancelCommand also. |
| iCurrentCmd.push_front(aCmd); |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| |
| // If TempCurrentCmd queue is holding up any command, move it back to CurrentCmd queue. |
| if (!iTempCurrentCmd.empty()) |
| { |
| iCurrentCmd.push_front(iTempCurrentCmd[0]); |
| iTempCurrentCmd.erase(iTempCurrentCmd.begin()); |
| } |
| } |
| // Pop each cmd from the temporary queue |
| iTempPendingCmds.pop(); |
| } |
| |
| if (!commandCancelled) |
| { |
| // There was no command cancelled, user might have given a wrong Argument |
| // Fail the command with PVMFErrArgument |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelCommand() Wrong Argument, No comand cancelled")); |
| if (!iCurrentCmd.empty()) |
| { |
| PVPlayerEngineCommand currentcmd(iCurrentCmd[0]); |
| iCurrentCmd.erase(iCurrentCmd.begin()); |
| iCurrentCmd.push_front(aCmd); |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFErrArgument); |
| iCurrentCmd.push_front(currentcmd); |
| } |
| else |
| { |
| // Current Command is empty, just push CancelCommand and do Command Complete. |
| iCurrentCmd.push_front(aCmd); |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFErrArgument); |
| } |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelCommand() Out")); |
| } |
| |
| |
| void PVPlayerEngine::DoCancelAllCommands(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelAllCommands() In")); |
| |
| |
| // Engine cannot be processing another cancel command |
| OSCL_ASSERT(iCmdToCancel.empty() == true); |
| |
| // While AcquireLicense and CancelAcquireLicense is processing, CancelAllCommands is prohibited. |
| if (!iCmdToDlaCancel.empty() || |
| (!iCurrentCmd.empty() && |
| (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_CANCEL_ACQUIRE_LICENSE || |
| iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_WCHAR || |
| iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_CHAR))) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelAllCommands() Error due to processing AcquireLicense or CancelAcquireLicense,CmdType=%d", iCurrentCmd[0].GetCmdType())); |
| PVPlayerEngineCommand currentcmd(iCurrentCmd[0]); |
| iCurrentCmd.erase(iCurrentCmd.begin()); |
| iCurrentCmd.push_front(aCmd); |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFErrArgument); |
| iCurrentCmd.push_front(currentcmd); |
| return; |
| } |
| // set engine state to Resetting, as cancel command completion will take Engine to Idle state, after internal reset. |
| SetEngineState(PVP_ENGINE_STATE_RESETTING); |
| iRollOverState = RollOverStateIdle; //reset roll over state to Idle, as engine is resetting itself |
| // Stop the playback clock |
| iPlaybackClock.Stop(); |
| // Cancel the current command first |
| if (iCurrentCmd.size() == 1) |
| { |
| // First save the current command being processed |
| iCmdToCancel.push_front(iCurrentCmd[0]); |
| // Cancel it |
| EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), PVMFErrCancelled); |
| } |
| |
| // Cancel all the pending commands |
| |
| // Create a temporary queue for pending commands |
| OsclPriorityQueue<PVPlayerEngineCommand, OsclMemAllocator, Oscl_Vector<PVPlayerEngineCommand, OsclMemAllocator>, PVPlayerEngineCommandCompareLess> iTempPendingCmds; |
| // Copy the pending commands to the new queue |
| iTempPendingCmds = iPendingCmds; |
| while (!iTempPendingCmds.empty()) |
| { |
| // Get the queue from the top |
| PVPlayerEngineCommand cmd(iTempPendingCmds.top()); |
| // Check if it needs to be cancelled |
| if ((aCmd.GetCmdId() > cmd.GetCmdId()) && !((aCmd.GetCmdId() - cmd.GetCmdId()) > 0x7FFFFFFF)) |
| { |
| // Remove it from the pending commands queue |
| iPendingCmds.remove(cmd); |
| // Save it temporary as "current command" and then cancel it |
| iCurrentCmd.push_front(cmd); |
| EngineCommandCompleted(cmd.GetCmdId(), cmd.GetContext(), PVMFErrCancelled); |
| } |
| // Pop each cmd from the temporary queue |
| iTempPendingCmds.pop(); |
| } |
| |
| |
| // Make the CancelAll() command the current command |
| iCurrentCmd.push_front(aCmd); |
| |
| // Check if there was an ongoing command that needs to be properly cancelled |
| if (!iCmdToCancel.empty()) |
| { |
| |
| // Properly cancel a command being currently processed |
| DoCancelCommandBeingProcessed(); |
| } |
| else |
| { |
| // Nothing to cancel, move on to resetting Source Nodes and Datapaths |
| if (iSourceNode) |
| { |
| int32 leavecode = 0; |
| // call reset on source node if not in created state |
| if (iSourceNode->GetState() != EPVMFNodeCreated) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::DoCancelAllCommands() Issue reset on Source Node")); |
| // error handling code set engine state to resetting |
| SetEngineState(PVP_ENGINE_STATE_RESETTING); |
| |
| PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, -1, NULL, -1); |
| |
| PVMFCommandId cmdid = -1; |
| leavecode = 0; |
| OSCL_TRY(leavecode, cmdid = iSourceNode->Reset(iSourceNodeSessionId, (OsclAny*)context)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::DoCancelAllCommands() Reset on iSourceNode did a leave!")); |
| FreeEngineContext(context); |
| OSCL_ASSERT(false);); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelAllCommands() Out")); |
| return; |
| } |
| } |
| |
| if (iDataSource) |
| { |
| RemoveDataSourceSync(*iDataSource); |
| } |
| SetEngineState(PVP_ENGINE_STATE_IDLE); |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelAllCommands() Out")); |
| } |
| |
| |
| void PVPlayerEngine::DoCancelCommandBeingProcessed(void) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelCommandBeingProcessed() In")); |
| |
| // There should be a command to cancel |
| OSCL_ASSERT(iCmdToCancel.empty() == false); |
| |
| // If cmd to cancel is GetMetadataKeys() or GetMetadataValues(), first release the memory for |
| // nodes which have already completed the call and then issue cancel on other nodes. |
| switch (iCmdToCancel[0].GetCmdType()) |
| { |
| case PVP_ENGINE_COMMAND_GET_METADATA_KEY: |
| { |
| // Release the memory allocated for the metadata keys |
| while (iMetadataKeyReleaseList.empty() == false) |
| { |
| PVMFMetadataExtensionInterface* mdif = iMetadataIFList[iMetadataKeyReleaseList[0].iMetadataIFListIndex].iInterface; |
| OSCL_ASSERT(mdif != NULL); |
| mdif->ReleaseNodeMetadataKeys(*(iGetMetadataKeysParam.iKeyList), iMetadataKeyReleaseList[0].iStartIndex, iMetadataKeyReleaseList[0].iEndIndex); |
| iMetadataKeyReleaseList.erase(iMetadataKeyReleaseList.begin()); |
| } |
| // no need to break from the current switch, as we need to issue Cancel on nodes. Continue. |
| } |
| case PVP_ENGINE_COMMAND_GET_METADATA_VALUE: |
| { |
| // Release the memory allocated for the metadata values |
| while (iMetadataValueReleaseList.empty() == false) |
| { |
| PVMFMetadataExtensionInterface* mdif = iMetadataIFList[iMetadataValueReleaseList[0].iMetadataIFListIndex].iInterface; |
| OSCL_ASSERT(mdif != NULL); |
| mdif->ReleaseNodeMetadataValues(*(iGetMetadataValuesParam.iValueList), iMetadataValueReleaseList[0].iStartIndex, iMetadataValueReleaseList[0].iEndIndex); |
| iMetadataValueReleaseList.erase(iMetadataValueReleaseList.begin()); |
| } |
| |
| iReleaseMetadataValuesPending = false; |
| // no need to break from the current switch, as we need to issue Cancel on nodes. Continue. |
| } |
| case PVP_ENGINE_COMMAND_ADD_DATA_SOURCE: |
| case PVP_ENGINE_COMMAND_INIT: |
| case PVP_ENGINE_COMMAND_PREPARE: |
| case PVP_ENGINE_COMMAND_PAUSE: |
| case PVP_ENGINE_COMMAND_RESUME: |
| case PVP_ENGINE_COMMAND_SET_PLAYBACK_RANGE: |
| case PVP_ENGINE_COMMAND_SET_PLAYBACK_RATE: |
| case PVP_ENGINE_COMMAND_CANCEL_COMMAND: |
| case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_ENDTIME_REACHED: |
| case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_ENDOFCLIP: |
| case PVP_ENGINE_COMMAND_PAUSE_DUE_TO_BUFFER_UNDERFLOW: |
| case PVP_ENGINE_COMMAND_RESUME_DUE_TO_BUFFER_DATAREADY: |
| case PVP_ENGINE_COMMAND_STOP: |
| { |
| // go ahead and issue cancel on nodes and datapath if needed. |
| if (!iCurrentContextList.empty()) |
| { |
| // Since there is a pending node or datapath, cancel it |
| PVMFStatus status = DoCancelPendingNodeDatapathCommand(); |
| if (status == PVMFPending) |
| { |
| // There are some commands which need to be cancelled so wait for cancel complete |
| // once cancels complete, we would start the reset sequence from either |
| // NodeCommandComplete, HandlePlayerDataPathEvent, RecognizeComplete |
| break; |
| } |
| } |
| |
| // No pending command so reset the nodes now |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelCommandBeingProcessed() No command to cancel, now reset all nodes")); |
| |
| // reset the source node |
| PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, -1, NULL, -1); |
| |
| PVMFCommandId cmdid = -1; |
| int32 leavecode = 0; |
| OSCL_TRY(leavecode, cmdid = iSourceNode->Reset(iSourceNodeSessionId, (OsclAny*)context)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelCommandBeingProcessed() Reset on iSourceNode did a leave!")); |
| FreeEngineContext(context); |
| OSCL_ASSERT(false); |
| return); |
| |
| SetEngineState(PVP_ENGINE_STATE_RESETTING); |
| break; |
| } |
| |
| case PVP_ENGINE_COMMAND_QUERY_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")); |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoCancelPendingNodeDatapathCommand() |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() In")); |
| |
| OSCL_ASSERT(iCurrentContextList.empty() == false); |
| |
| // Determine where the pending commands were issued to and then cancel them |
| int32 leavecode = 0; |
| iNumberCancelCmdPending = 0; |
| for (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 = IssueNodeCancelCommand(iCurrentContextList[i], iSourceNodeSessionId, (OsclAny*) & iNumberCancelCmdPending); |
| if (leavecode == 0) |
| { |
| ++iNumberCancelCmdPending; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() CancelAllCommands() on source node did a leave")); |
| FreeEngineContext(iCurrentContextList[i]); |
| } |
| } |
| else if (iCurrentContextList[i]->iEngineDatapath != NULL) |
| { |
| if (iCurrentContextList[i]->iNode == iCurrentContextList[i]->iEngineDatapath->iSinkNode) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() Calling CancelAllCommands() on sink node")); |
| leavecode = IssueNodeCancelCommand(iCurrentContextList[i], iCurrentContextList[i]->iEngineDatapath->iSinkNodeSessionId, (OsclAny*) & iNumberCancelCmdPending); |
| if (leavecode == 0) |
| { |
| ++iNumberCancelCmdPending; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() CancelAllCommands() on sink node did a leave")); |
| FreeEngineContext(iCurrentContextList[i]); |
| } |
| } |
| else if (iCurrentContextList[i]->iNode == iCurrentContextList[i]->iEngineDatapath->iDecNode) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() Calling CancelAllCommands() on dec node")); |
| leavecode = IssueNodeCancelCommand(iCurrentContextList[i], iCurrentContextList[i]->iEngineDatapath->iDecNodeSessionId, (OsclAny*) & iNumberCancelCmdPending); |
| if (leavecode == 0) |
| { |
| ++iNumberCancelCmdPending; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() CancelAllCommands() on dec node did a leave")); |
| FreeEngineContext(iCurrentContextList[i]); |
| } |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() Unknown node type. Asserting")); |
| OSCL_ASSERT(false); |
| } |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() Unknown node. Asserting")); |
| OSCL_ASSERT(false); |
| } |
| } |
| else if (iCurrentContextList[i]->iDatapath != NULL) |
| { |
| if (iCurrentContextList[i]->iEngineDatapath != NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() Calling CancelAllCommands() on datapath")); |
| leavecode = IssueDatapathCancelCommand(iCurrentContextList[i], (OsclAny*) & iNumberCancelCmdPending); |
| if (leavecode == 0) |
| { |
| ++iNumberCancelCmdPending; |
| } |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() Unknown datapath. Asserting")); |
| OSCL_ASSERT(false); |
| } |
| } |
| else if (iCurrentContextList[i]->iCmdType == PVP_CMD_QUERYSOURCEFORMATTYPE) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() Calling CancelAllCommands() on recognizer")); |
| leavecode = IssueRecognizerRegistryCancel((OsclAny*) & iNumberCancelCmdPending); |
| if (leavecode == 0) |
| { |
| ++iNumberCancelCmdPending; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() CancelAllCommands() on recognizer node did a leave")); |
| FreeEngineContext(iCurrentContextList[i]); |
| } |
| } |
| else |
| { |
| // Either a node or datapath should be pending |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() No pending node or datapath. Asserting")); |
| OSCL_ASSERT(false); |
| } |
| } |
| |
| if (iNumberCancelCmdPending == 0) |
| { |
| // Cancel on the node / datapath failed so go to next step |
| // Note that we do not care about not being able to queue cancel since |
| // we are going to reset the components anyway |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() CancelAllCommands() on the node did a leave")); |
| RemoveDatapathContextFromList(); // remove left-over datapath contexts |
| return PVMFSuccess; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() %d CancelAllCommands are pending", iNumberCancelCmdPending)); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelPendingNodeDatapathCommand() Out")); |
| return PVMFPending; |
| } |
| |
| PVMFStatus PVPlayerEngine::DoGetSDKInfo(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetSDKInfo() In")); |
| |
| PVSDKInfo* sdkinfo = (PVSDKInfo*)(aCmd.GetParam(0).pOsclAny_value); |
| if (sdkinfo == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetSDKInfo() Passed in parameter invalid.")); |
| return PVMFErrArgument; |
| } |
| |
| // Set the SDK info to the ones defined in the header file pv_player_sdkinfo.h generated at build time |
| sdkinfo->iLabel = PVPLAYER_ENGINE_SDKINFO_LABEL; |
| sdkinfo->iDate = PVPLAYER_ENGINE_SDKINFO_DATE; |
| |
| EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), iCurrentCmd[0].GetContext(), PVMFSuccess); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetSDKInfo() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoSetLogAppender(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetLogAppender() In")); |
| |
| char* tag = (char*)(aCmd.GetParam(0).pChar_value); |
| OsclSharedPtr<PVLoggerAppender>* appender = (OsclSharedPtr<PVLoggerAppender>*)(aCmd.GetParam(1).pOsclAny_value); |
| |
| if (tag == NULL || appender == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetLogAppender() Passed in parameter invalid.")); |
| return PVMFErrArgument; |
| } |
| |
| // Get the logger node based on the specified tag |
| PVLogger *rootnode = PVLogger::GetLoggerObject(tag); |
| if (rootnode == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetLogAppender() Node specified by tag is invalid")); |
| return PVMFErrBadHandle; |
| } |
| |
| // Add the specified appender to this node |
| rootnode->AddAppender(*appender); |
| |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetLogAppender() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoRemoveLogAppender(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoRemoveLogAppender() In")); |
| |
| char* tag = (char*)(aCmd.GetParam(0).pChar_value); |
| OsclSharedPtr<PVLoggerAppender>* appender = (OsclSharedPtr<PVLoggerAppender>*)(aCmd.GetParam(1).pOsclAny_value); |
| |
| if (tag == NULL || appender == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoRemoveLogAppender() Passed in parameter invalid.")); |
| return PVMFErrArgument; |
| } |
| |
| // Get the logger node based on the specified tag |
| PVLogger *lognode = PVLogger::GetLoggerObject(tag); |
| if (lognode == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoRemoveLogAppender() Node specified by tag is invalid")); |
| return PVMFErrBadHandle; |
| } |
| |
| // Remove the specified appender to this node |
| lognode->RemoveAppender(*appender); |
| |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoRemoveLogAppender() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoSetLogLevel(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetLogLevel() In")); |
| |
| char* tag = (char*)(aCmd.GetParam(0).pChar_value); |
| int32 level = aCmd.GetParam(1).int32_value; |
| bool subtree = aCmd.GetParam(2).bool_value; |
| |
| if (tag == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetLogLevel() Passed in parameter invalid.")); |
| return PVMFErrArgument; |
| } |
| |
| // Get the logger node based on the specified tag |
| PVLogger *lognode = PVLogger::GetLoggerObject(tag); |
| if (lognode == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetLogLevel() Node specified by tag is invalid")); |
| return PVMFErrBadHandle; |
| } |
| |
| // Set the log level |
| if (subtree) |
| { |
| lognode->SetLogLevelAndPropagate(level); |
| } |
| else |
| { |
| lognode->SetLogLevel(level); |
| } |
| |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetLogLevel() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoGetLogLevel(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetLogLevel() In")); |
| |
| char* tag = (char*)(aCmd.GetParam(0).pChar_value); |
| PVLogLevelInfo* levelinfo = (PVLogLevelInfo*)(aCmd.GetParam(1).pOsclAny_value); |
| |
| if (tag == NULL || levelinfo == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetLogLevel() Passed in parameter invalid.")); |
| return PVMFErrArgument; |
| } |
| |
| // Get the logger node based on the specified tag |
| PVLogger *lognode = PVLogger::GetLoggerObject(tag); |
| if (lognode == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetLogLevel() Node specified by tag is invalid")); |
| return PVMFErrBadHandle; |
| } |
| |
| // Get the log level info |
| *levelinfo = lognode->GetLogLevel(); |
| |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetLogLevel() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::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; |
| |
| // For now just return all available extension interface UUID |
| OSCL_TRY(leavecode, |
| // Capability and config interface |
| uuidvec->push_back(PVMI_CAPABILITY_AND_CONFIG_PVUUID); |
| // License acquisition interface |
| uuidvec->push_back(PVPlayerLicenseAcquisitionInterfaceUuid); |
| // Track level info interface from source node |
| if (iSourceNodeTrackLevelInfoIF) |
| { |
| uuidvec->push_back(PVMF_TRACK_LEVEL_INFO_INTERFACE_UUID); |
| } |
| ); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoQueryUUID() Leaved")); |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFErrNoMemory); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoQueryUUID() Out")); |
| return PVMFSuccess;); |
| |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| |
| 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); |
| |
| // (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_MIME_FORMAT_UNKNOWN) |
| { |
| retval = DoQuerySourceFormatType(aCmd.GetCmdId(), aCmd.GetContext()); |
| } |
| else |
| { |
| if (iSourceFormatType == PVMF_MIME_DATA_SOURCE_UNKNOWN_URL) |
| { |
| retval = SetupDataSourceForUnknownURLAccess(); |
| if (retval != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoAddDataSource() - SetupDataSourceForUnknownURLAccess Failed")); |
| return retval; |
| } |
| } |
| |
| // Start the source node creation and setup sequence |
| retval = DoSetupSourceNode(aCmd.GetCmdId(), aCmd.GetContext()); |
| |
| if (retval != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAddDataSource() Already EH pending, should never happen")); |
| return PVMFPending; |
| } |
| // Queue up Error Handling |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAddDataSource() DoSetupSourceNode failed, Add EH command")); |
| iCommandCompleteStatusInErrorHandling = retval; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_ADD_DATA_SOURCE, NULL, NULL, NULL, false); |
| return PVMFPending; |
| } |
| } |
| |
| 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; |
| |
| OsclAny * opaqueData = iDataSource->GetDataSourceContextData(); |
| PVInterface* pvInterface = OSCL_STATIC_CAST(PVInterface*, opaqueData); |
| PVInterface* SourceContextData = NULL; |
| PVUuid SourceContextDataUuid(PVMF_SOURCE_CONTEXT_DATA_UUID); |
| PVMFCPMPluginAccessInterfaceFactory * DataStreamDataFactory = NULL; |
| |
| if (pvInterface != NULL && pvInterface->queryInterface(SourceContextDataUuid, SourceContextData)) |
| { |
| PVMFSourceContextData * aSourceContextData = OSCL_STATIC_CAST(PVMFSourceContextData*, SourceContextData); |
| PVMFSourceContextDataCommon * aSourceContextDataCommon = aSourceContextData->CommonData(); |
| if (aSourceContextDataCommon) |
| { |
| DataStreamDataFactory = aSourceContextDataCommon->iRecognizerDataStreamFactory; |
| } |
| } |
| |
| if (DataStreamDataFactory) |
| { |
| OSCL_TRY(leavecode, retval = iPlayerRecognizerRegistry.QueryFormatType(DataStreamDataFactory, *this, (OsclAny*) context)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| FreeEngineContext(context); |
| return PVMFErrNotSupported; |
| ); |
| } |
| else |
| { |
| 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_MIME_FORMAT_UNKNOWN ; |
| |
| Oscl_Vector<PVUuid, OsclMemAllocator> foundUuids; |
| // Query the node registry |
| if (iPlayerNodeRegistry.QueryRegistry(iSourceFormatType, outputformattype, foundUuids) == PVMFSuccess) |
| { |
| if (foundUuids.empty()) |
| { |
| // No matching node found |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::DoSetupSourceNode() Query Regsitry successful, No matching source node found.")); |
| return PVMFErrNotSupported; |
| } |
| |
| int32 leavecode = 0; |
| OSCL_TRY(leavecode, iSourceNode = iPlayerNodeRegistry.CreateNode(foundUuids[0], true)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupDecNode() Error in creating SourceNode")); |
| return PVMFFailure;); |
| |
| iNodeUuids.push_back(PVPlayerEngineUuidNodeMapping(foundUuids[0], iSourceNode)); |
| |
| if (iSourceNode == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupSourceNode() Source node create failed")); |
| return PVMFErrNoMemory; |
| } |
| } |
| else |
| { |
| // Registry query failed |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupSourceNode() Registry query for source node failed")); |
| return PVMFErrNotSupported; |
| } |
| } |
| |
| if (iSourceNode->ThreadLogon() != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupSourceNode() ThreadLogon() on the source node failed")); |
| OSCL_ASSERT(false); |
| return PVMFFailure; |
| } |
| |
| PVMFNodeSessionInfo nodesessioninfo(this, this, (OsclAny*)iSourceNode, this, (OsclAny*)iSourceNode); |
| int32 leavecode = 0; |
| OSCL_TRY(leavecode, iSourceNodeSessionId = iSourceNode->Connect(nodesessioninfo)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupSourceNode() Connect on iSourceNode did a leave!")); |
| OSCL_ASSERT(false); |
| return PVMFFailure); |
| |
| PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQueryInitIF); |
| |
| PVUuid sourceinituuid = PVMF_DATA_SOURCE_INIT_INTERFACE_UUID; |
| leavecode = 0; |
| PVMFCommandId cmdid = -1; |
| iSourceNodePVInterfaceInit = NULL; |
| OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, sourceinituuid, iSourceNodePVInterfaceInit, (OsclAny*)context)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| iSourceNodePVInterfaceInit = NULL; |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetupSourceNode() QueryInterface on iSourceNode did a leave!")); |
| return PVMFFailure); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetupSourceNode() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoSourceNodeQueryTrackSelIF(PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::DoSourceNodeQueryTrackSelIF() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeQueryTrackSelIF() In")); |
| |
| int32 leavecode = 0; |
| |
| if (iDataSource->GetDataSourceType() == PVP_DATASRCTYPE_URL) |
| { |
| // Setup the source node via the initialization IF |
| OSCL_ASSERT(iSourceFormatType != PVMF_MIME_FORMAT_UNKNOWN); |
| |
| OSCL_wHeapString<OsclMemAllocator> sourceURL; |
| // In case the URL starts with file:// skip it |
| OSCL_wStackString<8> fileScheme(_STRLIT_WCHAR("file")); |
| OSCL_wStackString<8> schemeDelimiter(_STRLIT_WCHAR("://")); |
| const oscl_wchar* actualURL = NULL; |
| |
| if (oscl_strncmp(fileScheme.get_cstr(), iDataSource->GetDataSourceURL().get_cstr(), 4) == 0) |
| { |
| actualURL = oscl_strstr(iDataSource->GetDataSourceURL().get_cstr(), schemeDelimiter.get_cstr()); |
| if (actualURL == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryTrackSelIF() Unable to skip over file://")); |
| return PVMFErrArgument; |
| } |
| //skip over :// |
| actualURL += schemeDelimiter.get_size(); |
| sourceURL += actualURL; |
| } |
| else |
| { |
| sourceURL += iDataSource->GetDataSourceURL().get_cstr(); |
| } |
| |
| PVMFStatus retval = iSourceNodeInitIF->SetSourceInitializationData(sourceURL, iSourceFormatType, iDataSource->GetDataSourceContextData()); |
| if (retval != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryTrackSelIF() SetSourceInitializationData failed")); |
| return PVMFFailure; |
| } |
| // Set Playback Clock |
| retval = iSourceNodeInitIF->SetClientPlayBackClock(&iPlaybackClock); |
| if (retval != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryTrackSelIF() SetClientPlayBackClock failed!")); |
| return PVMFFailure; |
| } |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryTrackSelIF() Data source type not supported yet so asserting")); |
| OSCL_ASSERT(false); |
| return PVMFFailure; |
| } |
| |
| PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQueryTrackSelIF); |
| |
| // Query the source node for the track selection IF |
| PVUuid trackseluuid = PVMF_TRACK_SELECTION_INTERFACE_UUID; |
| PVMFCommandId cmdid = -1; |
| leavecode = 0; |
| iSourceNodePVInterfaceTrackSel = NULL; |
| OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, trackseluuid, iSourceNodePVInterfaceTrackSel, (OsclAny*)context)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| iSourceNodePVInterfaceTrackSel = NULL; |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryTrackSelIF() QueryInterface on iSourceNode did a leave!")); |
| return PVMFFailure); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeQueryTrackSelIF() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoSourceNodeQueryInterfaceOptional(PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::DoSourceNodeQueryInterfaceOptional() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeQueryInterfaceOptional() In")); |
| |
| PVPlayerEngineContext* context = NULL; |
| PVMFCommandId cmdid = -1; |
| int32 leavecode = 0; |
| |
| iNumPendingNodeCmd = 0; |
| |
| // Query for Track Level Info IF |
| context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQueryTrackLevelInfoIF); |
| PVUuid tracklevelinfouuid = PVMF_TRACK_LEVEL_INFO_INTERFACE_UUID; |
| cmdid = -1; |
| leavecode = 0; |
| iSourceNodePVInterfaceTrackLevelInfo = NULL; |
| OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, tracklevelinfouuid, iSourceNodePVInterfaceTrackLevelInfo, (OsclAny*)context)); |
| if (leavecode) |
| { |
| iSourceNodePVInterfaceTrackLevelInfo = NULL; |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryInterfaceOptional() QueryInterface on iSourceNode did a leave!")); |
| } |
| else |
| { |
| ++iNumPendingNodeCmd; |
| } |
| |
| // Query for Playback Control IF |
| context = NULL; |
| context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQueryPBCtrlIF); |
| PVUuid pbctrluuid = PvmfDataSourcePlaybackControlUuid; |
| cmdid = -1; |
| leavecode = 0; |
| iSourceNodePVInterfacePBCtrl = NULL; |
| OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, pbctrluuid, iSourceNodePVInterfacePBCtrl, (OsclAny*)context)); |
| if (leavecode) |
| { |
| iSourceNodePVInterfacePBCtrl = NULL; |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryInterfaceOptional() QueryInterface on iSourceNode did a leave!")); |
| } |
| else |
| { |
| ++iNumPendingNodeCmd; |
| } |
| |
| // Query for direction control IF |
| context = NULL; |
| context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQueryDirCtrlIF); |
| PVUuid dirctrluuid = PvmfDataSourceDirectionControlUuid; |
| cmdid = -1; |
| leavecode = 0; |
| iSourceNodePVInterfaceDirCtrl = NULL; |
| OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, dirctrluuid, iSourceNodePVInterfaceDirCtrl, (OsclAny*)context)); |
| if (leavecode) |
| { |
| iSourceNodePVInterfaceDirCtrl = NULL; |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryInterfaceOptional() QueryInterface on iSourceNode did a leave!")); |
| } |
| else |
| { |
| ++iNumPendingNodeCmd; |
| } |
| |
| // Query for Metadata IF |
| context = NULL; |
| context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQueryMetadataIF); |
| PVUuid metadatauuid = KPVMFMetadataExtensionUuid; |
| cmdid = -1; |
| leavecode = 0; |
| iSourceNodePVInterfaceMetadataExt = NULL; |
| OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, metadatauuid, iSourceNodePVInterfaceMetadataExt, (OsclAny*)context)); |
| if (leavecode) |
| { |
| iSourceNodePVInterfaceMetadataExt = NULL; |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryInterfaceOptional() QueryInterface on iSourceNode did a leave!")); |
| } |
| else |
| { |
| ++iNumPendingNodeCmd; |
| } |
| |
| // Query for Cap-Config IF |
| context = NULL; |
| context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQueryCapConfigIF); |
| PVUuid capconfiguuid = PVMI_CAPABILITY_AND_CONFIG_PVUUID; |
| cmdid = -1; |
| leavecode = 0; |
| iSourceNodePVInterfaceCapConfig = NULL; |
| OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, capconfiguuid, iSourceNodePVInterfaceCapConfig, (OsclAny*)context)); |
| if (leavecode) |
| { |
| iSourceNodePVInterfaceCapConfig = NULL; |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryInterfaceOptional() QueryInterface on iSourceNode did a leave!")); |
| } |
| else |
| { |
| ++iNumPendingNodeCmd; |
| } |
| |
| // Query for CPM License interface |
| context = NULL; |
| context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQueryCPMLicenseIF); |
| PVUuid licUuid = PVMFCPMPluginLicenseInterfaceUuid; |
| cmdid = -1; |
| leavecode = 0; |
| iSourceNodePVInterfaceCPMLicense = NULL; |
| OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, licUuid, iSourceNodePVInterfaceCPMLicense, (OsclAny*)context)); |
| if (leavecode) |
| { |
| iSourceNodePVInterfaceCPMLicense = NULL; |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryInterfaceOptional() QueryInterface on iSourceNode did a leave!")); |
| } |
| else |
| { |
| ++iNumPendingNodeCmd; |
| } |
| |
| // Query for source node registry init extension IF |
| context = NULL; |
| context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQuerySrcNodeRegInitIF); |
| PVUuid regInitUuid = PVMF_DATA_SOURCE_NODE_REGISRTY_INIT_INTERFACE_UUID; |
| cmdid = -1; |
| leavecode = 0; |
| iSourceNodePVInterfaceRegInit = NULL; |
| OSCL_TRY(leavecode, cmdid = iSourceNode->QueryInterface(iSourceNodeSessionId, regInitUuid, iSourceNodePVInterfaceRegInit, (OsclAny*)context)); |
| if (leavecode) |
| { |
| iSourceNodePVInterfaceRegInit = NULL; |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryInterfaceOptional() QueryInterface on iSourceNode did a leave!")); |
| } |
| else |
| { |
| ++iNumPendingNodeCmd; |
| } |
| |
| if (iNumPendingNodeCmd > 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeQueryInterfaceOptional() Out")); |
| return PVMFSuccess; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeQueryInterfaceOptional() Out No pending QueryInterface() on source node")); |
| return PVMFFailure; |
| } |
| } |
| |
| PVMFStatus PVPlayerEngine::DoGetMetadataKey(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE, |
| (0, "PVPlayerEngine::DoGetMetadataKey() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetMetadataKey() In")); |
| |
| if (GetPVPlayerState() == PVP_STATE_ERROR) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetMetadataKey() Wrong engine state.")); |
| return PVMFFailure; |
| } |
| |
| iGetMetadataKeysParam.iKeyList = (PVPMetadataList*)(aCmd.GetParam(0).pOsclAny_value); |
| iGetMetadataKeysParam.iStartingKeyIndex = aCmd.GetParam(1).int32_value; |
| iGetMetadataKeysParam.iMaxKeyEntries = aCmd.GetParam(2).int32_value; |
| iGetMetadataKeysParam.iQueryKey = aCmd.GetParam(3).pChar_value; |
| |
| if (iGetMetadataKeysParam.iKeyList == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetMetadataKey() Passed in parameter invalid.")); |
| return PVMFErrArgument; |
| } |
| |
| if (iGetMetadataKeysParam.iMaxKeyEntries < -1 || iGetMetadataKeysParam.iMaxKeyEntries == 0 || iGetMetadataKeysParam.iStartingKeyIndex < 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetMetadataKey() Passed in parameter invalid.")); |
| return PVMFErrArgument; |
| } |
| |
| // Determine which node's metadata interface to start the retrieval based on the starting index |
| uint32 i = 0; |
| int32 totalnumkey = 0; |
| uint32 nodestartindex = 0; |
| while (i < iMetadataIFList.size()) |
| { |
| int32 numkey = iMetadataIFList[i].iInterface->GetNumMetadataKeys(iGetMetadataKeysParam.iQueryKey); |
| if (iGetMetadataKeysParam.iStartingKeyIndex < (totalnumkey + numkey)) |
| { |
| // Found the node to start the key retrieval |
| // Determine the start index for this node |
| nodestartindex = iGetMetadataKeysParam.iStartingKeyIndex - totalnumkey; |
| break; |
| } |
| else |
| { |
| // Keep checking |
| totalnumkey += numkey; |
| ++i; |
| } |
| } |
| |
| // Check if the search succeeded |
| if (i == iMetadataIFList.size() || iMetadataIFList.size() == 0) |
| { |
| // Starting index is too large or there is no metadata interface available |
| return PVMFErrArgument; |
| } |
| |
| // Retrieve the metadata key from the first node |
| PVPlayerEngineContext* context = AllocateEngineContext(iMetadataIFList[i].iEngineDatapath, iMetadataIFList[i].iNode, NULL, aCmd.GetCmdId(), aCmd.GetContext(), PVP_CMD_GetNodeMetadataKey); |
| PVMFMetadataExtensionInterface* metadataif = iMetadataIFList[i].iInterface; |
| PVMFSessionId sessionid = iMetadataIFList[i].iSessionId; |
| PVMFCommandId cmdid = -1; |
| cmdid = metadataif->GetNodeMetadataKeys(sessionid, |
| *(iGetMetadataKeysParam.iKeyList), |
| nodestartindex, |
| iGetMetadataKeysParam.iMaxKeyEntries, |
| iGetMetadataKeysParam.iQueryKey, |
| (OsclAny*)context); |
| if (cmdid == -1) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::DoGetMetadataKey() GetNodeMetadataKeys failed")); |
| return PVMFFailure; |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetMetadataKey() Out")); |
| |
| // Save the current metadata value retrieval status |
| iGetMetadataKeysParam.iCurrentInterfaceIndex = i; |
| iGetMetadataKeysParam.iNumKeyEntriesToFill = iGetMetadataKeysParam.iMaxKeyEntries; |
| iGetMetadataKeysParam.iNumKeyEntriesInList = iGetMetadataKeysParam.iKeyList->size(); |
| |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoGetMetadataValue(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE, |
| (0, "PVPlayerEngine::DoGetMetadataValue() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetMetadataValue() In")); |
| |
| if (GetPVPlayerState() == PVP_STATE_ERROR) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetMetadataValue() Wrong engine state")); |
| return PVMFErrInvalidState; |
| } |
| |
| if (iReleaseMetadataValuesPending) |
| { |
| // App has called GetMetadataValues without calling ReleaseMetadata values on previous list. Wrong |
| // usage. Failure needs to be returned in this case. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::GetMetadataValues() Wrong usage, called again without releasing earlier metadata list")); |
| return PVMFErrReleaseMetadataValueNotDone; |
| } |
| |
| iGetMetadataValuesParam.iKeyList = (PVPMetadataList*)(aCmd.GetParam(0).pOsclAny_value); |
| iGetMetadataValuesParam.iStartingValueIndex = aCmd.GetParam(1).int32_value; |
| iGetMetadataValuesParam.iMaxValueEntries = aCmd.GetParam(2).int32_value; |
| iGetMetadataValuesParam.iNumAvailableValues = (int32*)(aCmd.GetParam(3).pOsclAny_value); |
| iGetMetadataValuesParam.iValueList = (Oscl_Vector<PvmiKvp, OsclMemAllocator>*)(aCmd.GetParam(4).pOsclAny_value); |
| iMetadataValuesCopiedInCallBack = aCmd.GetParam(5).bool_value; |
| |
| 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(iMetadataIFList[i].iEngineDatapath, iMetadataIFList[i].iNode, NULL, aCmd.GetCmdId(), aCmd.GetContext(), PVP_CMD_GetNodeMetadataValue); |
| PVMFMetadataExtensionInterface* metadataif = iMetadataIFList[i].iInterface; |
| PVMFSessionId sessionid = iMetadataIFList[i].iSessionId; |
| PVMFCommandId cmdid = -1; |
| cmdid = metadataif->GetNodeMetadataValues(sessionid, |
| *(iGetMetadataValuesParam.iKeyList), |
| *(iGetMetadataValuesParam.iValueList), |
| nodestartindex, |
| iGetMetadataValuesParam.iMaxValueEntries, |
| (OsclAny*)context); |
| |
| if (cmdid == -1) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::DoGetMetadataValue() GetNodeMetadataValues failed")); |
| return PVMFFailure; |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetMetadataValue() Out")); |
| |
| // Save the current metadata value retrieval status |
| iGetMetadataValuesParam.iCurrentInterfaceIndex = i; |
| iGetMetadataValuesParam.iNumValueEntriesToFill = iGetMetadataValuesParam.iMaxValueEntries; |
| iGetMetadataValuesParam.iNumValueEntriesInList = iGetMetadataValuesParam.iValueList->size(); |
| |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVPlayerEngine::DoReleaseMetadataValues(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE, |
| (0, "PVPlayerEngine::DoReleaseMetadataValues() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoReleaseMetadataValues() In")); |
| |
| if (GetPVPlayerState() == PVP_STATE_ERROR || |
| GetPVPlayerState() == PVP_STATE_IDLE) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoReleaseMetadataValues() Wrong engine state")); |
| return PVMFErrInvalidState; |
| } |
| |
| iGetMetadataValuesParam.iValueList = (Oscl_Vector<PvmiKvp, OsclMemAllocator>*)(aCmd.GetParam(0).pOsclAny_value); |
| |
| if (iGetMetadataValuesParam.iValueList == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoReleaseMetadataValues() Passed in parameter invalid.")); |
| return PVMFErrArgument; |
| } |
| |
| // Release the memory allocated for the metadata values |
| while (iMetadataValueReleaseList.empty() == false) |
| { |
| PVMFMetadataExtensionInterface* mdif = iMetadataIFList[iMetadataValueReleaseList[0].iMetadataIFListIndex].iInterface; |
| OSCL_ASSERT(mdif != NULL); |
| mdif->ReleaseNodeMetadataValues(*(iGetMetadataValuesParam.iValueList), iMetadataValueReleaseList[0].iStartIndex, iMetadataValueReleaseList[0].iEndIndex); |
| iMetadataValueReleaseList.erase(iMetadataValueReleaseList.begin()); |
| } |
| |
| iReleaseMetadataValuesPending = false; |
| |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVPlayerEngine::DoInit(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE, |
| (0, "PVPlayerEngine::DoInit() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoInit() In")); |
| |
| if (GetPVPlayerState() == PVP_STATE_INITIALIZED) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoInit() Engine already in Initialized State")); |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| return PVMFSuccess; |
| } |
| |
| if ((GetPVPlayerState() != PVP_STATE_IDLE) || (iSourceNode == NULL)) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoInit() Wrong engine state")); |
| return PVMFErrInvalidState; |
| } |
| |
| iRollOverState = RollOverStateIdle; |
| |
| PVMFStatus retval = DoSourceNodeInit(aCmd.GetCmdId(), aCmd.GetContext()); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoInit() Out")); |
| |
| if (retval == PVMFSuccess) |
| { |
| SetEngineState(PVP_ENGINE_STATE_INITIALIZING); |
| return PVMFSuccess; |
| } |
| else |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoInit() Already EH pending, should never happen")); |
| return PVMFPending; |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoInit() DoSourceNodeInit failed, Add EH command")); |
| iCommandCompleteStatusInErrorHandling = retval; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_INIT, NULL, NULL, NULL, false); |
| return PVMFPending; |
| } |
| } |
| |
| |
| 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) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeRollOver() SourceNodeRollOver Failed, return status")); |
| return status; |
| } |
| //roll over pending |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeRollOver() SourceNodeRollOver In Progress")); |
| return PVMFPending; |
| } |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeRollOver() Invalid State")); |
| return PVMFErrInvalidState; |
| } |
| |
| PVMFStatus PVPlayerEngine::DoAcquireLicense(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE, |
| (0, "PVPlayerEngine::DoAcquireLicense() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoAcquireLicense() In")); |
| |
| // Retrieve the command parameters and validate |
| iCPMAcquireLicenseParam.iContentNameChar = NULL; |
| iCPMAcquireLicenseParam.iContentNameWChar = NULL; |
| iCPMAcquireLicenseParam.iTimeoutMsec = (-1); |
| iCPMAcquireLicenseParam.iLicenseData = NULL; |
| iCPMAcquireLicenseParam.iLicenseDataSize = 0; |
| |
| if (aCmd.GetParam(0).pOsclAny_value != NULL) |
| { |
| iCPMAcquireLicenseParam.iLicenseData = aCmd.GetParam(0).pOsclAny_value; |
| } |
| |
| if (aCmd.GetParam(1).uint32_value != 0) |
| { |
| iCPMAcquireLicenseParam.iLicenseDataSize = aCmd.GetParam(1).uint32_value; |
| } |
| |
| if (aCmd.GetCmdType() == PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_WCHAR) |
| { |
| iCPMAcquireLicenseParam.iContentNameWChar = aCmd.GetParam(2).pWChar_value; |
| } |
| else |
| { |
| iCPMAcquireLicenseParam.iContentNameChar = aCmd.GetParam(2).pChar_value; |
| } |
| iCPMAcquireLicenseParam.iTimeoutMsec = aCmd.GetParam(3).int32_value; |
| |
| if (iCPMAcquireLicenseParam.iContentNameWChar == NULL && iCPMAcquireLicenseParam.iContentNameChar == NULL) |
| { |
| // Content name not specified |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAcquireLicense() Content name not specified.")); |
| return PVMFErrArgument; |
| } |
| |
| if (iCPMAcquireLicenseParam.iTimeoutMsec < -1) |
| { |
| // Timeout parameter not valid |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAcquireLicense() Timeout value not valid.")); |
| return PVMFErrArgument; |
| } |
| |
| // To acquire license, player data source and local data source need to be available |
| if (iDataSource == NULL) |
| { |
| // Player data source not available |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAcquireLicense() Player data source not specified.")); |
| return PVMFErrNotReady; |
| } |
| if (iDataSource->GetDataSourceContextData() == NULL) |
| { |
| // Pointer to the local data source if not available |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAcquireLicense() Local data source in player data source not specified.")); |
| return PVMFErrBadHandle; |
| } |
| |
| //If 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 status; |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoAcquireLicense() Out")); |
| // if the license interface is not available from the source node, fail the command |
| return PVMFFailure; |
| } |
| |
| void PVPlayerEngine::DoCancelAcquireLicense(PVPlayerEngineCommand& aCmd) |
| { |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE, |
| (0, "PVPlayerEngine::DoCancelAcquireLicense() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCancelAcquireLicense() In")); |
| |
| /* Engine cannot be processing another cancel command */ |
| OSCL_ASSERT(iCmdToDlaCancel.empty() == true); |
| |
| PVMFCommandId id = aCmd.GetParam(0).int32_value; |
| PVMFStatus status = PVMFSuccess; |
| |
| if (iCurrentCmd.size() == 1) |
| { |
| /* First save the current command being processed */ |
| PVPlayerEngineCommand currentcmd(iCurrentCmd[0]); |
| |
| /* First check "current" command if any */ |
| if (id == iCurrentCmd[0].GetCmdId()) |
| { |
| /* Cancel the current command first */ |
| if (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_CHAR |
| || iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_ACQUIRE_LICENSE_WCHAR) |
| { |
| /* 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::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::DoAddDataSink(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE, |
| (0, "PVPlayerEngine::DoAddDataSink() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoAddDataSink() In")); |
| |
| if (GetPVPlayerState() != PVP_STATE_INITIALIZED) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAddDataSink() Wrong engine state")); |
| return PVMFErrInvalidState; |
| } |
| |
| if (aCmd.GetParam(0).pOsclAny_value == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoAddDataSink() Passed in parameter invalid.")); |
| return PVMFErrArgument; |
| } |
| |
| PVPlayerDataSink* datasink = (PVPlayerDataSink*)(aCmd.GetParam(0).pOsclAny_value); |
| |
| PVPlayerEngineDatapath newdatapath; |
| newdatapath.iDataSink = datasink; |
| |
| // Add a new engine datapath to the list for the data sink |
| iDatapathList.push_back(newdatapath); |
| |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoAddDataSink() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoSetPlaybackRange(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE, |
| (0, "PVPlayerEngine::DoSetPlaybackRange() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetPlaybackRange() In")); |
| |
| PVMFStatus retval; |
| |
| if (GetPVPlayerState() == PVP_STATE_ERROR) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRange() Wrong engine state")); |
| return PVMFErrInvalidState; |
| } |
| |
| if (aCmd.GetParam(2).bool_value) |
| { |
| // Queueing of playback range is not supported yet |
| iQueuedRangePresent = false; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRange() Queued playback range is not supported yet")); |
| return PVMFErrNotSupported; |
| } |
| |
| // Change the end position |
| iCurrentEndPosition = aCmd.GetParam(1).playbackpos_value; |
| retval = UpdateCurrentEndPosition(iCurrentEndPosition); |
| if (retval != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRange() Changing end position failed")); |
| return retval; |
| } |
| |
| if (aCmd.GetParam(0).playbackpos_value.iIndeterminate) |
| { |
| // Start position not specified so return as success |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| return PVMFSuccess; |
| } |
| |
| // reset repos related variables except the StreamID. |
| ResetReposVariables(false); |
| iStreamID++; |
| |
| // Reset the paused-due-to-EOS flag |
| iPlaybackPausedDueToEndOfClip = false; |
| |
| // Change the begin position |
| iCurrentBeginPosition = aCmd.GetParam(0).playbackpos_value; |
| iTargetNPT = iCurrentBeginPosition.iPosValue.millisec_value; |
| retval = UpdateCurrentBeginPosition(iCurrentBeginPosition, aCmd); |
| |
| if (retval == PVMFSuccess) |
| { |
| // Notify completion of engine command |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| } |
| else if (retval == PVMFPending) |
| { |
| // SetPlaybackRange command is still being processed |
| // so change the return status so command is not completed yet |
| retval = PVMFSuccess; |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetPlaybackRange() Out")); |
| return retval; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::UpdateCurrentEndPosition(PVPPlaybackPosition& aEndPos) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateCurrentEndPosition() In")); |
| |
| if (aEndPos.iIndeterminate) |
| { |
| // Disable end time checking if running |
| if (iEndTimeCheckEnabled) |
| { |
| iEndTimeCheckEnabled = false; |
| iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_ENDTIMECHECK); |
| } |
| } |
| else |
| { |
| // Convert the end time to milliseconds to have consistent units internally |
| uint32 timems = 0; |
| PVMFStatus retval = ConvertToMillisec(aEndPos, timems); |
| if (retval != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::UpdateCurrentEndPosition() Converting to millisec failed")); |
| return retval; |
| } |
| aEndPos.iPosValue.millisec_value = timems; |
| aEndPos.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateCurrentEndPosition() Changing end time to %d ms", timems)); |
| |
| // Enable the end time checking if not running |
| if (!iEndTimeCheckEnabled) |
| { |
| iEndTimeCheckEnabled = true; |
| |
| if (GetPVPlayerState() == PVP_STATE_STARTED) |
| { |
| // Determine the check cycle based on interval setting in milliseconds |
| // and timer frequency of 100 millisec |
| int32 checkcycle = iEndTimeCheckInterval / 100; |
| if (checkcycle == 0) |
| { |
| ++checkcycle; |
| } |
| iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_ENDTIMECHECK); |
| iPollingCheckTimer->Request(PVPLAYERENGINE_TIMERID_ENDTIMECHECK, 0, checkcycle, this, true); |
| } |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateCurrentEndPosition() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::UpdateCurrentBeginPosition(PVPPlaybackPosition& aBeginPos, PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateCurrentBeginPosition() In")); |
| |
| PVMFStatus retval = PVMFSuccess; |
| uint32 timems = 0; |
| |
| switch (GetPVPlayerState()) |
| { |
| case PVP_STATE_PREPARED: |
| case PVP_STATE_STARTED: |
| { |
| // Change the playback position immediately |
| retval = ConvertToMillisec(aBeginPos, timems); |
| if (retval != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::UpdateCurrentBeginPosition() Converting to millisec failed")); |
| return retval; |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateCurrentBeginPosition() Requested begin position is %d ms", timems)); |
| |
| retval = DoChangePlaybackPosition(aCmd.GetCmdId(), aCmd.GetContext()); |
| } |
| break; |
| |
| case PVP_STATE_PAUSED: |
| { |
| // This is for use-case: Pause - SetPlaybackRate - Resume. |
| // In DoResume engine will call SetDataSourceDirection and then from HandleSourceNodeSetDataSourceDirection |
| // will call UpdateCurrentBeginPosition. |
| if (iCurrentCmd[0].GetCmdType() == PVP_ENGINE_COMMAND_RESUME) |
| { |
| // Reposition occurred during the paused state so need to change the source position first |
| retval = DoSourceNodeQueryDataSourcePosition(aCmd.GetCmdId(), aCmd.GetContext()); |
| if (retval == PVMFSuccess) |
| { |
| //return Pending to indicate a node command was issued |
| return PVMFPending; |
| } |
| else |
| { |
| //ignore failure, continue with resume sequence |
| return PVMFSuccess; |
| } |
| } |
| else |
| { |
| //if there's already a direction change pending, then don't |
| //allow a reposition also |
| if (iChangePlaybackDirectionWhenResuming) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::UpdateCurrentBeginPosition() Direction change already pending, fail.")); |
| return PVMFErrInvalidState; |
| } |
| |
| // Convert the time units but flag to change playback position when resuming |
| retval = ConvertToMillisec(aBeginPos, timems); |
| if (retval != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::UpdateCurrentBeginPosition() Converting to millisec failed in paused state")); |
| return retval; |
| } |
| |
| 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) |
| { |
| PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQueryDataSourcePositionDuringPlayback); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoChangePlaybackPosition() Querying source position. Position %d ms, SeekToSyncPt %d", iTargetNPT, iSeekToSyncPoint)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoChangePlaybackPosition() Querying source position. Position %d ms, SeekToSyncPt %d", iTargetNPT, iSeekToSyncPoint)); |
| int32 leavecode = 0; |
| |
| // As in case of MP4 file we need to call overload function of QueryDataSourcePosition which retruns |
| // I frame before and after instead of actaul NPT, format type will be checked here to first find if |
| // format-type is one of the MP4 varient |
| |
| PVMFNodeCapability nodeCapability; |
| iSourceNode->GetCapability(nodeCapability); |
| PVMFFormatType * formatType = nodeCapability.iInputFormatCapability.begin(); |
| bool mpeg4FormatType = false; |
| if (formatType != NULL) |
| { |
| if ((pv_mime_strcmp((char*)formatType->getMIMEStrPtr(), PVMF_MIME_MPEG4FF)) == 0) |
| { |
| mpeg4FormatType = true; |
| } |
| else |
| { |
| mpeg4FormatType = false; |
| } |
| } |
| |
| if (mpeg4FormatType) |
| { |
| OSCL_TRY(leavecode, cmdid = iSourceNodePBCtrlIF->QueryDataSourcePosition(iSourceNodeSessionId, iTargetNPT, |
| iSeekPointBeforeTargetNPT, iSeekPointAfterTargetNPT, (OsclAny*)context, iSeekToSyncPoint)); |
| } |
| else |
| { |
| OSCL_TRY(leavecode, cmdid = iSourceNodePBCtrlIF->QueryDataSourcePosition(iSourceNodeSessionId, iTargetNPT, iActualNPT, |
| iSeekToSyncPoint, (OsclAny*)context)); |
| } |
| |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoChangePlaybackPosition() QueryDataSourcePosition on iSourceNodePBCtrlIF did a leave!")); |
| if (leavecode == PVMFErrNotSupported || leavecode == PVMFErrArgument) |
| { |
| return leavecode; |
| } |
| else |
| { |
| return PVMFFailure; |
| } |
| ); |
| } |
| else |
| { |
| // Go straight to repositioning the data source |
| PVMFStatus retval = DoSourceNodeSetDataSourcePositionDuringPlayback(aCmdId, aCmdContext); |
| if (retval == PVMFSuccess) |
| { |
| return PVMFPending; |
| } |
| else |
| { |
| return retval; |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoChangePlaybackPosition() Out")); |
| |
| return PVMFPending; |
| } |
| |
| PVMFStatus PVPlayerEngine::DoSourceNodeSetDataSourcePositionDuringPlayback(PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePositionDuringPlayback() In")); |
| |
| // Check if the source node has position control IF |
| if (iSourceNodePBCtrlIF == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePositionDuringPlayback() No source playback control IF")); |
| return PVMFFailure; |
| } |
| bool clockpausedhere = false; |
| switch (iPlaybackPositionMode) |
| { |
| case PVPPBPOS_MODE_END_OF_CURRENT_PLAY_ELEMENT: |
| case PVPPBPOS_MODE_END_OF_CURRENT_PLAY_SESSION: |
| break; |
| case PVPPBPOS_MODE_NOW: |
| default: |
| // Pause the playback clock |
| clockpausedhere = iPlaybackClock.Pause(); |
| |
| // Stop the playback position status timer |
| StopPlaybackStatusTimer(); |
| break; |
| } |
| // Set the new position on the source node |
| PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeSetDataSourcePositionDuringPlayback); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePositionDuringPlayback() Calling SetDataSourcePosition() on source node. TargetNPT %d ms, SeekToSyncPoint %d", iTargetNPT, iSeekToSyncPoint)); |
| |
| int32 leavecode = 0; |
| if (iCurrentBeginPosition.iPosUnit == PVPPBPOSUNIT_PLAYLIST) |
| { |
| iDataSourcePosParams.iActualMediaDataTS = 0; |
| iDataSourcePosParams.iActualNPT = 0; |
| if ((iCurrentBeginPosition.iMode == PVPPBPOS_MODE_UNKNOWN) || |
| (iCurrentBeginPosition.iMode == PVPPBPOS_MODE_NOW)) |
| { |
| iDataSourcePosParams.iMode = PVMF_SET_DATA_SOURCE_POSITION_MODE_NOW; |
| } |
| else if (iCurrentBeginPosition.iMode == PVPPBPOS_MODE_END_OF_CURRENT_PLAY_ELEMENT) |
| { |
| iDataSourcePosParams.iMode = PVMF_SET_DATA_SOURCE_POSITION_END_OF_CURRENT_PLAY_ELEMENT; |
| } |
| else if (iCurrentBeginPosition.iMode == PVPPBPOS_MODE_END_OF_CURRENT_PLAY_SESSION) |
| { |
| iDataSourcePosParams.iMode = PVMF_SET_DATA_SOURCE_POSITION_MODE_END_OF_CURRENT_PLAY_SESSION; |
| } |
| iDataSourcePosParams.iPlayElementIndex = iCurrentBeginPosition.iPlayElementIndex; |
| iDataSourcePosParams.iSeekToSyncPoint = iSeekToSyncPoint; |
| iDataSourcePosParams.iTargetNPT = iCurrentBeginPosition.iPlayListPosValue.millisec_value; |
| iDataSourcePosParams.iStreamID = iStreamID; |
| iDataSourcePosParams.iPlaylistUri = iCurrentBeginPosition.iPlayListUri; |
| |
| leavecode = IssueSourceSetDataSourcePosition(true, (OsclAny*)context); |
| if (leavecode != 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePositionDuringPlayback() SetDataSourcePosition on iSourceNodePBCtrlIF did a leave!")); |
| FreeEngineContext(context); |
| if (clockpausedhere) |
| { |
| // Resume the clock if paused in this function |
| StartPlaybackClock(); |
| } |
| |
| --iStreamID; |
| |
| if (leavecode == PVMFErrNotSupported || leavecode == PVMFErrArgument) |
| { |
| return leavecode; |
| } |
| else |
| { |
| return PVMFFailure; |
| } |
| } |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePositionDuringPlayback() SetDataSourcePosition on iSourceNodePBCtrlIF - TargetNPT=%d, SeekToSyncPoint=%d", iTargetNPT, iSeekToSyncPoint)); |
| leavecode = IssueSourceSetDataSourcePosition(false, (OsclAny*)context); |
| |
| if (leavecode != 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePositionDuringPlayback() SetDataSourcePosition on iSourceNodePBCtrlIF did a leave!")); |
| FreeEngineContext(context); |
| if (clockpausedhere) |
| { |
| // Resume the clock if paused in this function |
| StartPlaybackClock(); |
| } |
| --iStreamID; |
| if (leavecode == PVMFErrNotSupported || leavecode == PVMFErrArgument) |
| { |
| return leavecode; |
| } |
| else |
| { |
| return PVMFFailure; |
| } |
| } |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePositionDuringPlayback() Out")); |
| |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVPlayerEngine::DoSinkNodeSkipMediaDataDuringPlayback(PVCommandId aCmdId, |
| OsclAny* aCmdContext, |
| bool aSFR) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::DoSinkNodeSkipMediaDataDuringPlayback() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeSkipMediaDataDuringPlayback() In")); |
| |
| // Pause the playback clock |
| bool clockpausedhere = iPlaybackClock.Pause(); |
| |
| // Tell the sink nodes to skip the unneeded media data |
| iNumPendingNodeCmd = 0; |
| 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", iActualMediaDataTS, iSkipMediaDataTS)); |
| |
| 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", iActualMediaDataTS, iSkipMediaDataTS)); |
| |
| if (iDatapathList[i].iDatapath && |
| iDatapathList[i].iEndOfDataReceived == false && |
| iDatapathList[i].iSinkNodeSyncCtrlIF != NULL) |
| { |
| PVPlayerEngineContext* context = AllocateEngineContext(&(iDatapathList[i]), iDatapathList[i].iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeSkipMediaDataDuringPlayback); |
| leavecode = IssueSinkSkipMediaData(&(iDatapathList[i]), 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 |
| StartPlaybackClock(); |
| } |
| |
| 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 (retval != PVMFSuccess) |
| { |
| // The conversion failed. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlaybackRange() Conversion from millisec failed (1)")); |
| return retval; |
| } |
| } |
| |
| if (iCurrentEndPosition.iIndeterminate) |
| { |
| // Since indeterminate, just directly copy |
| *(aCmd.GetParam(1).pPlaybackpos_value) = iCurrentEndPosition; |
| } |
| else |
| { |
| retval = ConvertFromMillisec(iCurrentEndPosition.iPosValue.millisec_value, *(aCmd.GetParam(1).pPlaybackpos_value)); |
| if (retval != PVMFSuccess) |
| { |
| // The conversion failed. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlaybackRange() Conversion from millisec failed (2)")); |
| return retval; |
| } |
| } |
| } |
| |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetPlaybackRange() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoGetCurrentPosition(PVPlayerEngineCommand& aCmd, bool aSyncCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetCurrentPosition() In")); |
| |
| PVPPlaybackPosition* pbpos = aCmd.GetParam(0).pPlaybackpos_value; |
| |
| if (GetPVPlayerState() == PVP_STATE_IDLE || |
| GetPVPlayerState() == PVP_STATE_ERROR) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetCurrentPosition() Wrong engine state")); |
| return PVMFErrInvalidState; |
| } |
| |
| if (pbpos == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetCurrentPosition() Passed in parameter invalid.")); |
| return PVMFErrArgument; |
| } |
| |
| // Query playback clock for current playback position |
| GetPlaybackClockPosition(*pbpos); |
| |
| if (pbpos->iIndeterminate) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetCurrentPosition() Passed in parameter invalid.")); |
| return PVMFErrArgument; |
| } |
| |
| if (!aSyncCmd) |
| { |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetCurrentPosition() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoSetPlaybackRate(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetPlaybackRate() In")); |
| |
| int32 rate = aCmd.GetParam(0).int32_value; |
| PVMFTimebase* timebase = (PVMFTimebase*)(aCmd.GetParam(1).pOsclAny_value); |
| |
| // Split the rate into the absolute value plus the direction 1 or -1. |
| int32 direction = 1; |
| if (rate < 0) |
| { |
| direction = (-1); |
| rate = (-rate); |
| } |
| |
| // Check if called in valid states. |
| if (GetPVPlayerState() != PVP_STATE_PREPARED |
| && GetPVPlayerState() != PVP_STATE_STARTED |
| && GetPVPlayerState() != PVP_STATE_PAUSED) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRate() Wrong engine state to change rate")); |
| return PVMFErrInvalidState; |
| } |
| |
| // Timebase can only be changed when prepared or paused. |
| if (timebase != iOutsideTimebase |
| && GetPVPlayerState() != PVP_STATE_PREPARED |
| && GetPVPlayerState() != PVP_STATE_PAUSED) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRate() Wrong engine state to change timebase")); |
| return PVMFErrInvalidState; |
| } |
| |
| // Don't allow a direction change while paused, if there's already |
| // a pending reposition. Engine doesn't have logic to handle both repos and |
| // direction change during the Resume. |
| if (direction != iPlaybackDirection |
| && GetPVPlayerState() == PVP_STATE_PAUSED |
| && iChangePlaybackPositionWhenResuming) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRate() Repos already pending-- can't change direction.")); |
| return PVMFErrInvalidState; |
| } |
| |
| // Switching from forward to backward really only makes sense when playing or paused, |
| // otherwise we'll be at the end of clip. If we ever allow combined repositioning |
| // and direction change, this restriction could be removed. |
| if (direction != iPlaybackDirection |
| && direction < 0 |
| && GetPVPlayerState() != PVP_STATE_STARTED |
| && GetPVPlayerState() != PVP_STATE_PAUSED) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRate() Wrong engine state to go backward")); |
| return PVMFErrInvalidState; |
| } |
| |
| // Validate the playback rate parameters. |
| |
| // Rate zero is only valid with an outside timebase. |
| if (rate == 0 |
| && timebase == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRate() Invalid parameter-- rate 0 with no outside timbase.")); |
| return PVMFErrArgument; |
| } |
| |
| // Rate must be within allowed range |
| if (rate > 0 |
| && (rate < PVP_PBRATE_MIN || rate > PVP_PBRATE_MAX)) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRate() Invalid parameter-- rate outside allowed range")); |
| return PVMFErrArgument; |
| } |
| |
| // With an outside timebase, we can't really support rates. If -1x is input, |
| // it means backward direction, but otherwise, rate is ignored. |
| // So flag an error for any rate other than zero, 1x, or -1x. |
| if (timebase != NULL |
| && (rate != 0 && rate != 100000)) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRate() Invalid rate with outside timebase")); |
| return PVMFErrInvalidState; |
| } |
| |
| // To do any rate change, the source node must have the playback control IF. |
| if (rate != iPlaybackClockRate |
| && iSourceNodePBCtrlIF == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRate() iSourceNodePBCtrlIF is NULL")); |
| return 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; |
| //a direction change also involves an internal repositioning |
| //so reset repos related variables and increment iStreamID |
| ResetReposVariables(false); |
| iStreamID++; |
| } |
| |
| // Save the new values. They won't be installed until they're verified |
| iOutsideTimebase_New = timebase; |
| iPlaybackDirection_New = direction; |
| iPlaybackClockRate_New = rate; |
| |
| // Start the sequence. |
| |
| if (iPlaybackClockRate_New != iPlaybackClockRate) |
| { |
| // This code starts a rate change. Any direction and/or timebase change |
| // will happen once the rate change is complete. |
| |
| // Query the source node if the new playback rate is supported |
| PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmd.GetCmdId(), aCmd.GetContext(), PVP_CMD_SourceNodeSetDataSourceRate); |
| |
| PVMFCommandId cmdid = -1; |
| int32 leavecode = 0; |
| OSCL_TRY(leavecode, cmdid = iSourceNodePBCtrlIF->SetDataSourceRate(iSourceNodeSessionId, iPlaybackClockRate_New, iOutsideTimebase_New, (OsclAny*)context)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetPlaybackRate() SetDataSourceRate on iSourceNodePBCtrlIF did a leave!")); |
| return PVMFFailure); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetPlaybackRate() Out")); |
| |
| return PVMFSuccess; |
| // wait for the source node callback, then HandleSourceNodeSetDataSourceRate |
| } |
| |
| if (iPlaybackDirection_New != iPlaybackDirection) |
| { |
| // Do a direction change without a rate change. |
| PVMFStatus status = UpdateCurrentDirection(aCmd.GetCmdId(), aCmd.GetContext()); |
| switch (status) |
| { |
| case PVMFPending: |
| // If we get here, engine is Prepared or Started, and we're now |
| // waiting on source node command completion followed |
| // by a call to HandleSourceNodeSetDataSource. |
| // Set the return status to Success, since the caller does not expect |
| // PVMFPending. |
| status = PVMFSuccess; |
| break; |
| case PVMFSuccess: |
| // If we get here, engine is Paused or Stopped. The SetPlaybackRate |
| // command is done for now, but we need to set the direction when the |
| // engine is resumed or prepared. |
| if (iOutsideTimebase_New != iOutsideTimebase) |
| { |
| UpdateTimebaseAndRate(); |
| } |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| break; |
| default: |
| //failure! |
| break; |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetPlaybackRate() Out")); |
| return status; |
| } |
| |
| //If we get here it's either a timebase change, or no change at all, so |
| //the engine command is complete. |
| if (iOutsideTimebase_New != iOutsideTimebase) |
| { |
| UpdateTimebaseAndRate(); |
| } |
| |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetPlaybackRate() Out")); |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVPlayerEngine::UpdateCurrentDirection(PVMFCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateCurrentDirection() In")); |
| |
| // Launch a direction change sequence. |
| |
| PVMFStatus status = PVMFFailure; |
| |
| // Check if the source node has direction control |
| if (!iSourceNodeDirCtrlIF) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::UpdateCurrentDirection() Direction control IF on source node not available ")); |
| status = 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; |
| PVMFTimebase** timebase = (PVMFTimebase**)(aCmd.GetParam(1).pOsclAny_value); |
| |
| if (rate == NULL || timebase == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlaybackRate() Passed in parameter invalid")); |
| return PVMFErrArgument; |
| } |
| |
| if (GetPVPlayerState() != PVP_STATE_PREPARED && |
| GetPVPlayerState() != PVP_STATE_STARTED && |
| GetPVPlayerState() != PVP_STATE_PAUSED) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlaybackRate() Wrong engine state")); |
| return PVMFErrInvalidState; |
| } |
| |
| // Fill in with current engine settings for playback rate |
| *rate = iPlaybackClockRate * iPlaybackDirection; |
| *timebase = iOutsideTimebase; |
| |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetPlaybackRate() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoGetPlaybackMinMaxRate(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetPlaybackMinMaxRate() In")); |
| |
| int32* minrate = aCmd.GetParam(0).pInt32_value; |
| int32* maxrate = aCmd.GetParam(1).pInt32_value; |
| |
| if (minrate == NULL || maxrate == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlaybackMinMaxRate() Passed in parameter invalid")); |
| return PVMFErrArgument; |
| } |
| |
| // Use hardcoded ranges for now |
| *minrate = PVP_PBRATE_MIN; |
| *maxrate = PVP_PBRATE_MAX; |
| |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetPlaybackMinMaxRate() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoPrepare(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE, |
| (0, "PVPlayerEngine::DoPrepare() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoPrepare() In")); |
| |
| if (GetPVPlayerState() == PVP_STATE_PREPARED) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPrepare() Engine already in Prepared State")); |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| return PVMFSuccess; |
| } |
| |
| if (GetPVPlayerState() != PVP_STATE_INITIALIZED) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPrepare() Wrong engine state")); |
| return PVMFErrInvalidState; |
| } |
| |
| if (iState == PVP_ENGINE_STATE_PREPARING) |
| { |
| // Engine is already in PREPARING STATE and doing Track selection. DoPrepare will be called everytime |
| // engine completes a stage of track selection and flips the state to _TRACK_SELECTION_1_DONE etc. |
| // If DoPrepare called without flipping the state, that means in _PREPARING state, do nothing here |
| // just return. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::DoPrepare() Engine state PVP_ENGINE_STATE_PREPARING - Do Nothing")); |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus cmdstatus = PVMFFailure; |
| |
| /* Engine will call DoPrepare 4 times |
| * 1) When Engine is in PVP_ENGINE_STATE_INITIALIZED state, here engine will start the Track Selection, which |
| * will start with Sink Nodes. |
| * 2) After Init completes on Sink nodes Engine will be in PVP_ENGINE_STATE_TRACK_SELECTION_1_DONE and Engine will |
| * start creating Dec nodes and call Init on dec nodes, if needed. |
| * 3) Init completion on Dec nodes will take Engine to PVP_ENGINE_STATE_TRACK_SELECTION_2_DONE and Engine will |
| * start populating the Playable List after verifying parameters of different tracks. Engine after selecting |
| * tracks will call Reset on Sink and Dec nodes. |
| * 4) Once Reset completes on Sink and Dec nodes, Engine will be in PVP_ENGINE_STATE_TRACK_SELECTION_3_DONE and then |
| * Engine will delete all the unused dec nodes. |
| */ |
| if (iState == PVP_ENGINE_STATE_INITIALIZED) |
| { |
| SetEngineState(PVP_ENGINE_STATE_PREPARING); |
| |
| // Reset the paused-due-to-EOS flag |
| iPlaybackPausedDueToEndOfClip = false; |
| |
| if (iDatapathList.empty() == true) |
| { |
| // No sink added so fail |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPrepare() Data sinks not added.")); |
| return PVMFErrNotReady; |
| } |
| |
| // Query cap-config based on available engine datapaths |
| cmdstatus = DoSinkNodeQueryCapConfigIF(aCmd.GetCmdId(), aCmd.GetContext()); |
| if (cmdstatus != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPrepare() Already EH pending, should never happen")); |
| return PVMFPending; |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPrepare() DoSinkNodeQueryCapConfigIF: failed, Add EH command")); |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| return PVMFPending; |
| } |
| } |
| else if (iState == PVP_ENGINE_STATE_TRACK_SELECTION_1_DONE) |
| { |
| SetEngineState(PVP_ENGINE_STATE_PREPARING); |
| |
| // Now check for the tracks which can be played only using the Sink nodes, that means no Decoder node needed. |
| cmdstatus = DoSinkNodeTrackSelection(aCmd.GetCmdId(), aCmd.GetContext()); |
| if (cmdstatus != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPrepare() Already EH pending, should never happen")); |
| return PVMFPending; |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPrepare() DoSinkNodeTrackSelection: failed, Add EH command")); |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| return PVMFPending; |
| } |
| |
| // For the tracks which cannot be played by Sink nodes only, we need to instantiate decoder nodes. |
| // Create Decoder nodes and query for the cap and config IF here. |
| cmdstatus = DoDecNodeQueryCapConfigIF(aCmd.GetCmdId(), aCmd.GetContext()); |
| if (cmdstatus != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPrepare() Already EH pending, should never happen")); |
| return PVMFPending; |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPrepare() DoDecNodeQueryCapConfigIF: failed, Add EH command")); |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| return PVMFPending; |
| } |
| } |
| else if (iState == PVP_ENGINE_STATE_TRACK_SELECTION_2_DONE) |
| { |
| SetEngineState(PVP_ENGINE_STATE_PREPARING); |
| |
| cmdstatus = DoSourceNodeTrackSelection(aCmd.GetCmdId(), aCmd.GetContext()); |
| if (cmdstatus != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPrepare() Already EH pending, should never happen")); |
| return PVMFPending; |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPrepare() DoSourceNodeTrackSelection: failed, Add EH command")); |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| return PVMFPending; |
| } |
| // Reset all the sink and decoder nodes. |
| cmdstatus = DoSinkNodeDecNodeReset(aCmd.GetCmdId(), aCmd.GetContext()); |
| if (cmdstatus != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPrepare() Already EH pending, should never happen")); |
| return PVMFPending; |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPrepare() DoSinkNodeDecNodeReset: failed, Add EH command")); |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| return PVMFPending; |
| } |
| } |
| else if (iState == PVP_ENGINE_STATE_TRACK_SELECTION_3_DONE) |
| { |
| SetEngineState(PVP_ENGINE_STATE_PREPARING); |
| |
| cmdstatus = DoSinkDecCleanupSourcePrepare(aCmd.GetCmdId(), aCmd.GetContext()); |
| if (cmdstatus != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPrepare() Already EH pending, should never happen")); |
| return PVMFPending; |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPrepare() DoDecNodeCleanup: failed, Add EH command")); |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| return PVMFPending; |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoPrepare() Out")); |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVPlayerEngine::DoSinkNodeQueryCapConfigIF(PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeQueryCapConfigIF() In")); |
| |
| if (iSourceNodeTrackSelIF == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeQueryCapConfigIF() Source node track sel IF not available. Asserting")); |
| return PVMFFailure; |
| } |
| |
| uint32 i = 0; |
| int32 leavecode = 0; |
| uint32 numTracks = 0; |
| PVPlayerEngineContext* context = NULL; |
| PVMFCommandId cmdid = -1; |
| iNumPendingNodeCmd = 0; |
| |
| if (iSourceNodeTrackSelIF->GetMediaPresentationInfo(iSourcePresInfoList) != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeQueryCapConfigIF() GetMediaPresentationInfo() call on source node failed")); |
| return PVMFFailure; |
| } |
| |
| numTracks = iSourcePresInfoList.getNumTracks(); |
| iTrackSelectionList.reserve(numTracks); |
| |
| for (i = 0; i < numTracks; i++) |
| { |
| // Create the track selection list, which will store a set of sink and dec node (if needed) for each track. |
| PVPlayerEngineTrackSelection trackSelection; |
| |
| PVMFTrackInfo* trackInfo = iSourcePresInfoList.getTrackInfo(i); |
| trackSelection.iTsTrackID = trackInfo->getTrackID(); |
| |
| iTrackSelectionList.push_back(trackSelection); |
| } |
| |
| for (i = 0; i < iDatapathList.size(); ++i) |
| { |
| // Destroy the track info if present |
| if (iDatapathList[i].iTrackInfo) |
| { |
| OSCL_DELETE(iDatapathList[i].iTrackInfo); |
| iDatapathList[i].iTrackInfo = NULL; |
| } |
| |
| if (iDatapathList[i].iDataSink->GetDataSinkType() == PVP_DATASINKTYPE_FILENAME) |
| { |
| // Create file output node for sink |
| leavecode = 0; |
| OSCL_TRY(leavecode, iDatapathList[i].iSinkNode = PVFileOutputNodeFactory::CreateFileOutput()); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeQueryCapConfigIF() Creation of file output node did a leave!")); |
| return PVMFErrNoMemory); |
| } |
| else if (iDatapathList[i].iDataSink->GetDataSinkType() == PVP_DATASINKTYPE_SINKNODE) |
| { |
| // Use the specified output node for sink node |
| iDatapathList[i].iSinkNode = iDatapathList[i].iDataSink->GetDataSinkNodeInterface(); |
| if (iDatapathList[i].iSinkNode == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeQueryCapConfigIF() Passed in sink node is NULL")); |
| return PVMFFailure; |
| } |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeQueryCapConfigIF() Unsupported player data sink type")); |
| return PVMFErrNotSupported; |
| } |
| |
| if (iDatapathList[i].iSinkNode->ThreadLogon() != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeQueryCapConfigIF() ThreadLogon() on passed-in sink node failed")); |
| OSCL_ASSERT(false); |
| return PVMFFailure; |
| } |
| |
| PVMFNodeSessionInfo nodesessioninfo(this, this, (OsclAny*)iDatapathList[i].iSinkNode, this, (OsclAny*)iDatapathList[i].iSinkNode); |
| iDatapathList[i].iSinkNodeSessionId = iDatapathList[i].iSinkNode->Connect(nodesessioninfo); |
| |
| // Query for Cap-Config IF |
| context = AllocateEngineContext(&iDatapathList[i], iDatapathList[i].iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeQueryCapConfigIF); |
| |
| PVUuid capconfiguuid = PVMI_CAPABILITY_AND_CONFIG_PVUUID; |
| cmdid = -1; |
| leavecode = 0; |
| iDatapathList[i].iSinkNodePVInterfaceCapConfig = NULL; |
| leavecode = IssueQueryInterface(iDatapathList[i].iSinkNode, iDatapathList[i].iSinkNodeSessionId, capconfiguuid, iDatapathList[i].iSinkNodePVInterfaceCapConfig, (OsclAny*)context, cmdid); |
| if (leavecode != 0 || cmdid == -1) |
| { |
| iDatapathList[i].iSinkNodePVInterfaceCapConfig = NULL; |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeQueryCapConfigIF() QueryInterface on sink node for cap-config IF did a leave!")); |
| return PVMFFailure; |
| } |
| else |
| { |
| ++iNumPendingNodeCmd; |
| } |
| } |
| |
| if (iNumPendingNodeCmd <= 0) |
| { |
| // NumPendingNodeCmd less than or equal to zero means that none of the Sink nodes support Cap-Config interface, which means that these |
| // sinks cannot be used for playing the content. Return PVMFErrNotSupported from here which will take engine into Error handling and will fail |
| // Prepare command. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeQueryCapConfigIF() Out No pending QueryInterface() on sink node")); |
| return PVMFErrNotSupported; |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeQueryCapConfigIF() Out")); |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVPlayerEngine::DoSinkNodeInit(PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::DoSinkNodeInit() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeInit() In")); |
| |
| iNumPendingNodeCmd = 0; |
| PVMFCommandId cmdid = -1; |
| int32 leavecode = 0; |
| |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iSinkNode != NULL) |
| { |
| // Call Init() on the sink node |
| PVPlayerEngineContext* context = AllocateEngineContext(&(iDatapathList[i]), iDatapathList[i].iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeInit); |
| |
| leavecode = IssueSinkNodeInit(&(iDatapathList[i]), (OsclAny*) context, cmdid); |
| |
| if (cmdid != -1 && leavecode == 0) |
| { |
| ++iNumPendingNodeCmd; |
| } |
| else |
| { |
| FreeEngineContext(context); |
| return PVMFFailure; |
| } |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeInit() Out")); |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVPlayerEngine::DoSinkNodeTrackSelection(PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| OSCL_UNUSED_ARG(aCmdId); |
| OSCL_UNUSED_ARG(aCmdContext); |
| // For a track to be playable only by sink node, the Sink node should support the Format Type and Format Specific Info |
| // for the track. If any of the 2 variables are not supported by the sink node, the track needs to have a decoder which |
| // will be created in next stage of track selection. If Sink node supports both the above variables for a particular |
| // track, the track will make to the Playable list without any decoder node. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeTrackSelection() In")); |
| |
| PVMFStatus status = PVMFFailure; |
| |
| PvmiKvp kvpFormatType; |
| PvmiKvp kvpFSI; |
| |
| OSCL_StackString<64> iKVPFormatType = _STRLIT_CHAR(PVMF_FORMAT_TYPE_VALUE_KEY); |
| |
| const char* aFormatValType = PVMF_FORMAT_SPECIFIC_INFO_KEY; |
| |
| OsclMemAllocator alloc; |
| |
| kvpFormatType.key = NULL; |
| kvpFSI.key = NULL; |
| |
| kvpFormatType.key = iKVPFormatType.get_str(); |
| |
| kvpFSI.length = oscl_strlen(aFormatValType) + 1; // +1 for \0 |
| kvpFSI.key = (PvmiKeyType)alloc.ALLOCATE(kvpFSI.length); |
| if (kvpFSI.key == NULL) |
| { |
| return PVMFErrNoMemory; |
| } |
| oscl_strncpy(kvpFSI.key, aFormatValType, kvpFSI.length); |
| |
| for (uint32 i = 0; i < iDatapathList.size(); i++) |
| { |
| if (iDatapathList[i].iSinkNodeCapConfigIF != NULL) |
| { |
| for (uint32 j = 0; j < iSourcePresInfoList.getNumTracks(); j++) |
| { |
| // if any track is already been added to the playlist then no need to check with the next Datapath |
| // go onto the next track |
| if (!iTrackSelectionList[j].iTsTrackValidForPlayableList) |
| { |
| OsclRefCounterMemFrag aConfig; |
| PVMFTrackInfo* currTrack = iSourcePresInfoList.getTrackInfo(j); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeTrackSelection() Check format type for %s", currTrack->getTrackMimeType().get_cstr())); |
| |
| kvpFormatType.value.pChar_value = currTrack->getTrackMimeType().get_str(); |
| |
| // Check for the format type of the track first. If Supported move to Format specific info, if not |
| // move on to the next track. |
| |
| status = iDatapathList[i].iSinkNodeCapConfigIF->verifyParametersSync(NULL, &kvpFormatType, 1); |
| |
| if (status == PVMFSuccess) |
| { |
| // go ahead and check for Format specific info |
| aConfig = currTrack->getTrackConfigInfo(); |
| kvpFSI.value.key_specific_value = (OsclAny*)(aConfig.getMemFragPtr()); |
| kvpFSI.capacity = aConfig.getMemFragSize(); |
| |
| status = iDatapathList[i].iSinkNodeCapConfigIF->verifyParametersSync(NULL, &kvpFSI, 1); |
| |
| if (status == PVMFSuccess) |
| { |
| // This track can be played just using the Sink nodes we need not have decoders for this track |
| // Set the boolean iTsTrackValidForPlayableList to true in the TrackSelectionList. |
| // Check the boolean iTsTrackValidForPlayableList before creating the decoder nodes, if |
| // already set no need for decoders. |
| iTrackSelectionList[j].iTsSinkNode = iDatapathList[i].iSinkNode; |
| iTrackSelectionList[j].iTsSinkNodeCapConfigIF = iDatapathList[i].iSinkNodeCapConfigIF; |
| iTrackSelectionList[j].iTsTrackValidForPlayableList = true; |
| } |
| } |
| } |
| // if any of the above verifyParameterSync returns a failure, just move onto the next track. |
| } |
| } |
| } |
| |
| alloc.deallocate((OsclAny*)(kvpFSI.key)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeTrackSelection() Out")); |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVPlayerEngine::DoDecNodeQueryCapConfigIF(PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDecNodeQueryCapConfigIF() In")); |
| |
| int32 leavecode = 0; |
| PVPlayerEngineContext* context = NULL; |
| PVMFCommandId cmdid = -1; |
| |
| PVMFFormatType iSrcFormat = 0; |
| PVMFFormatType iSinkFormat = 0; |
| |
| iNumPendingNodeCmd = 0; |
| |
| uint32 numTracks = iSourcePresInfoList.getNumTracks(); |
| |
| for (uint32 i = 0; i < numTracks; i++) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDecNodeQueryCapConfigIF() Check the track")); |
| for (uint32 j = 0; j < iDatapathList.size(); j++) |
| { |
| // Start creating decoder nodes for tracks which cannot be played with Sink nodes alone. |
| // It is also possible that there can be similar tracks with same mime strings but with |
| // different config parameters which share the same decoder node. For these similar tracks |
| // engine should not create decoder nodes again, it should use the same decoder node instance. |
| if (iTrackSelectionList[i].iTsDecNode == NULL && !iTrackSelectionList[i].iTsTrackValidForPlayableList) |
| { |
| PVMFTrackInfo* currTrack = iSourcePresInfoList.getTrackInfo(i); |
| iSrcFormat = currTrack->getTrackMimeType().get_str(); |
| |
| //Try to get supported formats from the media I/O component. |
| PvmiKvp* kvp = NULL; |
| int numParams = 0; |
| PVMFStatus status = iDatapathList[j].iSinkNodeCapConfigIF->getParametersSync(NULL, (char*)INPUT_FORMATS_CAP_QUERY, kvp, numParams, NULL); |
| if (status == PVMFSuccess) |
| { |
| for (int k = 0; k < numParams; k++) |
| { |
| iSinkFormat = kvp[k].value.pChar_value; |
| |
| Oscl_Vector<PVUuid, OsclMemAllocator> foundUuids; |
| // Query the player node registry for the required decoder node |
| if (iPlayerNodeRegistry.QueryRegistry(iSrcFormat, iSinkFormat, foundUuids) == PVMFSuccess) |
| { |
| if (!foundUuids.empty()) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDecNodeQueryCapConfigIF() Node found for %s, sink %s", currTrack->getTrackMimeType().get_str(), iSinkFormat.getMIMEStrPtr())); |
| iTrackSelectionList[i].iTsDecNode = iPlayerNodeRegistry.CreateNode(foundUuids[0], iHwAccelerated); |
| |
| if (iTrackSelectionList[i].iTsDecNode != NULL) |
| { |
| iNodeUuids.push_back(PVPlayerEngineUuidNodeMapping(foundUuids[0], iTrackSelectionList[i].iTsDecNode)); |
| |
| if (iTrackSelectionList[i].iTsDecNode->ThreadLogon() != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDecNodeQueryCapConfigIF() ThreadLogon() on dec node failed")); |
| OSCL_ASSERT(false); |
| } |
| |
| PVMFNodeSessionInfo nodesessioninfo(this, this, (OsclAny*)iTrackSelectionList[i].iTsDecNode, this, (OsclAny*)iTrackSelectionList[i].iTsDecNode); |
| iTrackSelectionList[i].iTsDecNodeSessionId = iTrackSelectionList[i].iTsDecNode->Connect(nodesessioninfo); |
| |
| // Query for CapConfig IF |
| context = AllocateEngineContext(NULL, iTrackSelectionList[i].iTsDecNode, NULL, aCmdId, aCmdContext, PVP_CMD_DecNodeQueryCapConfigIF); |
| |
| PVUuid capconfiguuid = PVMI_CAPABILITY_AND_CONFIG_PVUUID; |
| cmdid = -1; |
| iTrackSelectionList[i].iTsDecNodePVInterfaceCapConfig = NULL; |
| leavecode = IssueQueryInterface(iTrackSelectionList[i].iTsDecNode, iTrackSelectionList[i].iTsDecNodeSessionId, capconfiguuid, iTrackSelectionList[i].iTsDecNodePVInterfaceCapConfig, (OsclAny*)context, cmdid); |
| if (cmdid == -1 || leavecode != 0) |
| { |
| iTrackSelectionList[i].iTsDecNodePVInterfaceCapConfig = NULL; |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDecNodeQueryCapConfigIF() QueryInterface on dec node for cap-config IF did a leave!")); |
| } |
| else |
| { |
| ++iNumPendingNodeCmd; |
| } |
| |
| // A decoder is found in the registry and succesfully created for the particular set of track and datapath. |
| // Set the sink nodes and its cap and config IF for the track in trackSelectionList |
| iTrackSelectionList[i].iTsSinkNode = iDatapathList[j].iSinkNode; |
| iTrackSelectionList[i].iTsSinkNodeCapConfigIF = iDatapathList[j].iSinkNodeCapConfigIF; |
| iTrackSelectionList[i].iTsSinkNodeSessionId = iDatapathList[j].iSinkNodeSessionId; |
| |
| // Set the sink format for the datapath. |
| iDatapathList[j].iSinkFormat = iSinkFormat; |
| |
| // Valid decoder node set in TrackSelectionList. Scan the TrackSelectionList further and if |
| // any similar MIME track is there just use the same decoder and the same sink nodes. |
| for (uint32 s = i + 1; s < numTracks; s++) |
| { |
| PVMFTrackInfo* tmpTrack = iSourcePresInfoList.getTrackInfo(s); |
| if (!(pv_mime_strcmp(currTrack->getTrackMimeType().get_str(), tmpTrack->getTrackMimeType().get_str()))) |
| { |
| iTrackSelectionList[s].iTsSinkNode = iTrackSelectionList[i].iTsSinkNode; |
| iTrackSelectionList[s].iTsSinkNodeCapConfigIF = iTrackSelectionList[i].iTsSinkNodeCapConfigIF; |
| iTrackSelectionList[s].iTsSinkNodeSessionId = iTrackSelectionList[i].iTsSinkNodeSessionId; |
| |
| iTrackSelectionList[s].iTsDecNode = iTrackSelectionList[i].iTsDecNode; |
| iTrackSelectionList[s].iTsDecNodeSessionId = iTrackSelectionList[i].iTsDecNodeSessionId; |
| } |
| } |
| |
| k = numParams; |
| } |
| else |
| { |
| // Create node on decoder failed, check with the next sink format |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDecNodeQueryCapConfigIF() Dec node creation failed")); |
| } |
| } |
| else |
| { |
| // No matching node found with the given Sinkformat, check with the next Sink Format |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDecNodeQueryCapConfigIF() No matching decoder node found")); |
| } |
| } |
| else |
| { |
| // Registry query failed with the given Sinkformat, check with the next Sink Format. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDecNodeQueryCapConfigIF() Registry query for dec node failed")); |
| } |
| } |
| iDatapathList[j].iSinkNodeCapConfigIF->releaseParameters(0, kvp, numParams); |
| } |
| else |
| { |
| // getParamterSync on MIO node to get the supported formats by MIO failed |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDecNodeQueryCapConfigIF() getParamterSync on MIO node to get the supported formats by MIO failed")); |
| } |
| } |
| } |
| } |
| |
| if (iNumPendingNodeCmd == 0) |
| { |
| // no decoder nodes are needed, go ahead for track selection logic |
| SetEngineState(PVP_ENGINE_STATE_TRACK_SELECTION_2_DONE); |
| RunIfNotReady(); |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDecNodeQueryCapConfigIF() Out")); |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVPlayerEngine::DoDecNodeInit(PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::DoDecNodeInit() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDecNodeInit() In")); |
| |
| iNumPendingNodeCmd = 0; |
| PVMFCommandId cmdid = -1; |
| int32 leavecode = 0; |
| |
| for (uint32 i = 0; i < iTrackSelectionList.size(); ++i) |
| { |
| if (iTrackSelectionList[i].iTsDecNode != NULL) |
| { |
| // Call Init() on the dec node |
| PVPlayerEngineContext* context = AllocateEngineContext(NULL, iTrackSelectionList[i].iTsDecNode, NULL, aCmdId, aCmdContext, PVP_CMD_DecNodeInit); |
| |
| leavecode = IssueDecNodeInit(iTrackSelectionList[i].iTsDecNode, iTrackSelectionList[i].iTsDecNodeSessionId, (OsclAny*) context, cmdid); |
| |
| if (cmdid != -1 && leavecode == 0) |
| { |
| ++iNumPendingNodeCmd; |
| } |
| else |
| { |
| FreeEngineContext(context); |
| return PVMFFailure; |
| } |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDecNodeInit() Out")); |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVPlayerEngine::DoSourceNodeTrackSelection(PVCommandId /*aCmdId*/, OsclAny* /*aCmdContext*/) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeTrackSelection() In")); |
| |
| if (iSourceNodeTrackSelIF == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeTrackSelection() Source node track sel IF not available.")); |
| return PVMFFailure; |
| } |
| |
| //populate playable list first |
| PVMFStatus retval = DoTrackSelection(true, false); |
| if (retval != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeTrackSelection() DoTrackSelection - Populating playable list Failed")); |
| return retval; |
| } |
| |
| bool usepreferencelist = false; |
| if (iTrackSelectionHelper != NULL) |
| { |
| PVMFMediaPresentationInfo localList; |
| iPreferenceList.Reset(); |
| localList.setPresentationType(iPlayableList.getPresentationType()); |
| localList.setSeekableFlag(iPlayableList.IsSeekable()); |
| localList.SetDurationAvailable(iPlayableList.IsDurationAvailable()); |
| localList.setDurationValue(iPlayableList.getDurationValue()); |
| localList.setDurationTimeScale(iPlayableList.getDurationTimeScale()); |
| //if track selection helper is present, it means that |
| //user of engine wants to provide inputs |
| //the reason we use a local list instead of iPreferenceList is |
| //due to memory consideration. This call to "SelectTracks" goes |
| //to the app and the app allocates memory to populate the local list |
| //This memory needs to be released right away. So we make a copy |
| //and release the memory for local list. |
| PVMFStatus status = |
| iTrackSelectionHelper->SelectTracks(iPlayableList, localList); |
| if ((status == PVMFSuccess) && |
| (localList.getNumTracks() != 0)) |
| { |
| usepreferencelist = true; |
| iPreferenceList = localList; |
| } |
| //release memory now that we have made a copy |
| iTrackSelectionHelper->ReleasePreferenceList(localList); |
| //else user made no choice, use playable list |
| } |
| |
| retval = DoTrackSelection(false, usepreferencelist); |
| if (retval != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeTrackSelection() DoTrackSelection - TrackSelection Failed")); |
| return retval; |
| } |
| |
| uint32 i = 0; |
| |
| // Create a selected track list |
| PVMFMediaPresentationInfo selectedtracks; |
| for (i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iTrackInfo != NULL) |
| { |
| selectedtracks.addTrackInfo(*(iDatapathList[i].iTrackInfo)); |
| } |
| } |
| |
| // Check that at least one track was selected |
| if (selectedtracks.getNumTracks() == 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeTrackSelection() No tracks were selected")); |
| // @TODO Provide a more specific error info |
| return PVMFErrResourceConfiguration; |
| } |
| |
| // Select in source node |
| retval = iSourceNodeTrackSelIF->SelectTracks(selectedtracks); |
| if (retval != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeTrackSelection() SelectTracks() on source node failed")); |
| return retval; |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeTrackSelection() Out")); |
| return retval; |
| } |
| |
| PVMFStatus PVPlayerEngine::DoTrackSelection(bool oPopulatePlayableListOnly, bool oUsePreferenceList) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoTrackSelection() In")); |
| |
| if (iSourceNodeTrackSelIF == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoTrackSelection() Source node track sel IF not available.")); |
| return PVMFFailure; |
| } |
| |
| PVMFMediaPresentationInfo sourcepresinfo; |
| if (oPopulatePlayableListOnly) |
| { |
| // use already saved presentation info list from source node |
| sourcepresinfo = iSourcePresInfoList; |
| |
| iPlayableList.Reset(); |
| |
| iPlayableList.setPresentationType(iSourcePresInfoList.getPresentationType()); |
| iPlayableList.setSeekableFlag(iSourcePresInfoList.IsSeekable()); |
| iPlayableList.SetDurationAvailable(iSourcePresInfoList.IsDurationAvailable()); |
| iPlayableList.setDurationValue(iSourcePresInfoList.getDurationValue()); |
| iPlayableList.setDurationTimeScale(iSourcePresInfoList.getDurationTimeScale()); |
| } |
| else |
| { |
| if (oUsePreferenceList) |
| { |
| //perform track selection based on playable list |
| sourcepresinfo = iPreferenceList; |
| } |
| else |
| { |
| //perform track selection based on playable list |
| sourcepresinfo = iPlayableList; |
| } |
| } |
| |
| PVMFStatus retVal = PVMFSuccess; |
| uint32 i = 0; |
| uint32 k = 0; |
| |
| if (oPopulatePlayableListOnly) |
| { |
| for (i = 0; i < iDatapathList.size(); i++) |
| { |
| // Destroy the track info if present |
| if (iDatapathList[i].iTrackInfo) |
| { |
| OSCL_DELETE(iDatapathList[i].iTrackInfo); |
| iDatapathList[i].iTrackInfo = NULL; |
| } |
| } |
| |
| for (i = 0; i < sourcepresinfo.getNumTracks(); i++) |
| { |
| PVMFStatus checkcodec = PVMFFailure; |
| int32 trackId = -1; |
| |
| // Go through each track, check codec type, and save the track info |
| PVMFTrackInfo* curtrack = sourcepresinfo.getTrackInfo(i); |
| trackId = curtrack->getTrackID(); |
| |
| // check if this track can be directly pushed in playable list. This will be the case where decoder node is not needed |
| // and Sink node supports the format and format specific info. OR |
| // The track is a text track. |
| |
| if (iTrackSelectionList[i].iTsDecNode == NULL) |
| { |
| // check if it is a valid track or not, decoder node can be NULL only in 2 cases |
| // 1) Track can be played without decoder nodes, here iTsTrackValidForPlayableList should be true OR track is TEXT track |
| // 2) If the track is not valid at all, if this is the case, move onto next track. |
| |
| if (iTrackSelectionList[i].iTsTrackValidForPlayableList || |
| (pv_mime_strcmp(curtrack->getTrackMimeType().get_str(), PVMF_MIME_3GPP_TIMEDTEXT)) == 0) |
| { |
| // this can make directly to the Playable list, since it satisfies condition# 1 above. |
| iPlayableList.addTrackInfo(*curtrack); |
| iTrackSelectionList[i].iTsTrackValidForPlayableList = false; |
| checkcodec = PVMFSuccess; |
| } |
| } |
| else |
| { |
| // if sink node alone does not support this track verify its parameters. |
| retVal = DoVerifyTrackInfo(iTrackSelectionList[i], curtrack, checkcodec); |
| if (retVal != PVMFSuccess) |
| return retVal; |
| |
| if (checkcodec == PVMFSuccess) |
| { |
| //add it to playable list |
| iPlayableList.addTrackInfo(*curtrack); |
| } |
| } |
| |
| if (checkcodec != PVMFSuccess && trackId >= 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoTrackSelection() Bad track config for TrackId=%d", trackId)); |
| SendInformationalEvent(PVMFInfoTrackDisable, NULL, (OsclAny*)trackId, NULL, 0); |
| } |
| } |
| } |
| else |
| { |
| for (i = 0; i < sourcepresinfo.getNumTracks(); i++) |
| { |
| PVMFTrackInfo* curtrack = sourcepresinfo.getTrackInfo(i); |
| |
| for (k = 0; k < iTrackSelectionList.size(); k++) |
| { |
| // check which track is selected by comparing the TrackId |
| int32 trackId = curtrack->getTrackID(); |
| if (trackId == iTrackSelectionList[k].iTsTrackID) |
| { |
| for (uint32 j = 0; j < iDatapathList.size(); j++) |
| { |
| // if a track has already been added to the datapath, move onto the next datapath. |
| if (!iDatapathList[j].iTrackInfo) |
| { |
| // check for the corresponding datapath to the track |
| if (iDatapathList[j].iSinkNode == iTrackSelectionList[k].iTsSinkNode) |
| { |
| if (curtrack->DoesTrackHaveDependency() == true) |
| { |
| // Track has dependency, move onto next track |
| j = iDatapathList.size(); |
| k = iTrackSelectionList.size(); |
| } |
| else |
| { |
| // The track has been added to the final list, this means that this track is valid |
| // and will make to DatapathList and all other video decoders will be destroyed. |
| iDatapathList[j].iTrackInfo = OSCL_NEW(PVMFTrackInfo, (*curtrack)); |
| |
| // set the decoder node, its session id and decoder cap&config IF in the Datapath, since the track is the |
| // selected one. |
| if (iTrackSelectionList[k].iTsDecNode) |
| { |
| iDatapathList[j].iDecNode = iTrackSelectionList[k].iTsDecNode; |
| iDatapathList[j].iDecNodeSessionId = iTrackSelectionList[k].iTsDecNodeSessionId; |
| iDatapathList[j].iDecNodeCapConfigIF = iTrackSelectionList[k].iTsDecNodeCapConfigIF; |
| } |
| |
| iTrackSelectionList[k].iTsSinkNode = NULL; |
| iTrackSelectionList[k].iTsSinkNodeSessionId = 0; |
| iTrackSelectionList[k].iTsSinkNodeCapConfigIF = NULL; |
| |
| iTrackSelectionList[k].iTsDecNode = NULL; |
| iTrackSelectionList[k].iTsDecNodeSessionId = 0; |
| iTrackSelectionList[k].iTsDecNodeCapConfigIF = NULL; |
| iTrackSelectionList[k].iTsDecNodePVInterfaceCapConfig = NULL; |
| |
| iTrackSelectionList[k].iTsTrackID = -1; |
| iTrackSelectionList[k].iTsTrackValidForPlayableList = false; |
| } |
| j = iDatapathList.size(); |
| } |
| // Datapath sinknode does not match, check the next datapath for the track |
| } |
| // a track has already been assigned for the datapath, check next datapath for the track |
| } |
| k = iTrackSelectionList.size(); |
| } |
| // The trackId of the track does not match with the track in the List, check the next track. |
| } |
| } |
| |
| // Go through the track selection list and set similar decoder nodes to NULL. There should be only 1 entry |
| // of a decoder node either in DatapathList (this will be for the final playable track) or in |
| // TrackSelectionList which will be for tracks which will not be used for playback. |
| for (i = 0; i < iTrackSelectionList.size(); i++) |
| { |
| PVMFTrackInfo* currTrack = iSourcePresInfoList.getTrackInfo(i); |
| for (uint32 j = i + 1; j < iTrackSelectionList.size(); j++) |
| { |
| PVMFTrackInfo* tmpTrack = iSourcePresInfoList.getTrackInfo(j); |
| if (!(pv_mime_strcmp(currTrack->getTrackMimeType().get_str(), tmpTrack->getTrackMimeType().get_str()))) |
| { |
| iTrackSelectionList[j].iTsDecNode = NULL; |
| iTrackSelectionList[j].iTsDecNodeSessionId = 0; |
| iTrackSelectionList[j].iTsDecNodeCapConfigIF = NULL; |
| } |
| } |
| } |
| |
| // now go through whole TrackSelectionList and look for similar sink and decoder nodes |
| // to the track selected i.e. added to datapath, set all sink and decoder nodes to NULL for the track selected |
| for (k = 0; k < iDatapathList.size(); k++) |
| { |
| for (uint32 s = 0; s < iTrackSelectionList.size(); s++) |
| { |
| if ((iDatapathList[k].iSinkNode == iTrackSelectionList[s].iTsSinkNode)) |
| { |
| iTrackSelectionList[s].iTsSinkNode = NULL; |
| iTrackSelectionList[s].iTsSinkNodeSessionId = 0; |
| iTrackSelectionList[s].iTsSinkNodeCapConfigIF = NULL; |
| } |
| |
| if ((iDatapathList[k].iDecNode != NULL) && |
| (iDatapathList[k].iDecNode == iTrackSelectionList[s].iTsDecNode)) |
| { |
| iTrackSelectionList[s].iTsDecNode = NULL; |
| iTrackSelectionList[s].iTsDecNodeSessionId = 0; |
| iTrackSelectionList[s].iTsDecNodeCapConfigIF = NULL; |
| iTrackSelectionList[s].iTsDecNodePVInterfaceCapConfig = NULL; |
| } |
| |
| iTrackSelectionList[s].iTsTrackID = -1; |
| iTrackSelectionList[s].iTsTrackValidForPlayableList = false; |
| } |
| } |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoTrackSelection() Out")); |
| return retVal; |
| } |
| |
| PVMFStatus PVPlayerEngine::DoVerifyTrackInfo(PVPlayerEngineTrackSelection &aTrackSelection, PVMFTrackInfo* aTrack, PVMFStatus& aCheckcodec) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoVerifyTrackInfo() In %s", aTrack->getTrackMimeType().get_cstr())); |
| |
| PVMFStatus status = PVMFSuccess; |
| OsclMemAllocator alloc; |
| PvmiKvp kvp; |
| kvp.key = NULL; |
| |
| const char* aFormatValType = PVMF_FORMAT_SPECIFIC_INFO_KEY; |
| OsclRefCounterMemFrag aConfig; |
| |
| kvp.length = oscl_strlen(aFormatValType) + 1; // +1 for \0 |
| kvp.key = (PvmiKeyType)alloc.ALLOCATE(kvp.length); |
| if (kvp.key == NULL) |
| { |
| return PVMFErrNoMemory; |
| } |
| oscl_strncpy(kvp.key, aFormatValType, kvp.length); |
| aConfig = aTrack->getTrackConfigInfo(); |
| kvp.value.key_specific_value = (OsclAny*)(aConfig.getMemFragPtr()); |
| kvp.capacity = aConfig.getMemFragSize(); |
| |
| //Check if we have decoder node cap-config |
| if (aTrackSelection.iTsDecNodeCapConfigIF != NULL) |
| { |
| PVMFFormatType DecnodeFormatType = aTrack->getTrackMimeType().get_str(); |
| |
| PvmiKvp* iErrorKVP = NULL; |
| PvmiKvp iKVPSetFormat; |
| iKVPSetFormat.key = NULL; |
| OSCL_StackString<64> iKeyStringSetFormat; |
| iKVPSetFormat.value.pChar_value = (char*)DecnodeFormatType.getMIMEStrPtr(); |
| |
| // Query for video decoder first with the track, if no success, then check for audio decoder. Only one query will succeed. |
| // If both fails, check the status. |
| iKeyStringSetFormat = _STRLIT_CHAR(PVMF_VIDEO_DEC_FORMAT_TYPE_VALUE_KEY); |
| iKVPSetFormat.key = iKeyStringSetFormat.get_str(); |
| |
| aTrackSelection.iTsDecNodeCapConfigIF->setParametersSync(NULL, &iKVPSetFormat, 1, iErrorKVP); |
| if (iErrorKVP == NULL) |
| { |
| //verify codec specific info |
| int32 leavecode = 0; |
| OSCL_TRY(leavecode, aCheckcodec = aTrackSelection.iTsDecNodeCapConfigIF->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; |
| |
| querykey = _STRLIT_CHAR("x-pvmf/video/render"); |
| if (aTrackSelection.iTsDecNodeCapConfigIF->getParametersSync(NULL, querykey.get_str(), kvpPtr, numKvp, NULL) == PVMFSuccess) |
| { |
| //verify width/height |
| if (aTrackSelection.iTsSinkNodeCapConfigIF != NULL) |
| aCheckcodec = aTrackSelection.iTsSinkNodeCapConfigIF->verifyParametersSync(NULL, kvpPtr, numKvp); |
| status = aTrackSelection.iTsDecNodeCapConfigIF->releaseParameters(NULL, kvpPtr, numKvp); |
| } |
| } |
| else |
| { |
| // Query failed for video decoder next try the audio decoder. |
| iErrorKVP = NULL; |
| iKeyStringSetFormat = NULL; |
| iKVPSetFormat.key = NULL; |
| |
| iKeyStringSetFormat += _STRLIT_CHAR(PVMF_AUDIO_DEC_FORMAT_TYPE_VALUE_KEY); |
| iKVPSetFormat.key = iKeyStringSetFormat.get_str(); |
| |
| aTrackSelection.iTsDecNodeCapConfigIF->setParametersSync(NULL, &iKVPSetFormat, 1, iErrorKVP); |
| |
| if (iErrorKVP == NULL) |
| { |
| //verify codec specific info |
| int32 leavecodeaudio = 0; |
| OSCL_TRY(leavecodeaudio, aCheckcodec = aTrackSelection.iTsDecNodeCapConfigIF->verifyParametersSync(NULL, &kvp, 1)); |
| OSCL_FIRST_CATCH_ANY(leavecodeaudio, |
| 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; |
| |
| querykey = _STRLIT_CHAR("x-pvmf/audio/render"); |
| if (aTrackSelection.iTsDecNodeCapConfigIF->getParametersSync(NULL, querykey.get_str(), kvpPtr, numKvp, NULL) == PVMFSuccess) |
| { |
| //verify samplerate and channels |
| if (aTrackSelection.iTsSinkNodeCapConfigIF != NULL) |
| aCheckcodec = aTrackSelection.iTsSinkNodeCapConfigIF->verifyParametersSync(NULL, kvpPtr, numKvp); |
| status = aTrackSelection.iTsDecNodeCapConfigIF->releaseParameters(NULL, kvpPtr, numKvp); |
| } |
| } |
| } |
| } |
| else |
| { |
| if (aTrackSelection.iTsSinkNodeCapConfigIF != NULL) |
| { |
| aCheckcodec = aTrackSelection.iTsSinkNodeCapConfigIF->verifyParametersSync(NULL, &kvp, 1); |
| } |
| } |
| |
| alloc.deallocate((OsclAny*)(kvp.key)); |
| if (aCheckcodec != PVMFSuccess) |
| { |
| //In case of other error code, this is operation error. |
| if (aCheckcodec != PVMFErrNotSupported) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyTrackInfo() verifyParametersSync() on sink node failed")); |
| return aCheckcodec; |
| } |
| return status; |
| } |
| |
| //verify bitrate |
| PvmiKvp iKVPBitRate; |
| iKVPBitRate.key = NULL; |
| |
| OSCL_StackString<64> iKVPStringBitRate = _STRLIT_CHAR(PVMF_BITRATE_VALUE_KEY); |
| iKVPBitRate.key = iKVPStringBitRate.get_str(); |
| iKVPBitRate.value.uint32_value = aTrack->getTrackBitRate(); |
| |
| if (aTrackSelection.iTsSinkNodeCapConfigIF != NULL) |
| aCheckcodec = aTrackSelection.iTsSinkNodeCapConfigIF->verifyParametersSync(NULL, &iKVPBitRate, 1); |
| //In case of other error code, this is operation error. |
| if (aCheckcodec != PVMFSuccess) |
| { |
| //In case of other error code, this is operation error. |
| if (aCheckcodec != PVMFErrNotSupported) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyTrackInfo() verifyParametersSync() on sinknode bitrate failed")); |
| return aCheckcodec; |
| } |
| return status; |
| } |
| |
| //verify video framerate, if track is not video, sink will return ErrNotSupported. |
| if (aTrack->getTrackFrameRate() > 0) |
| { |
| PvmiKvp iKVPFrameRate; |
| iKVPFrameRate.key = NULL; |
| |
| OSCL_StackString<64> iKVPStringFrameRate = _STRLIT_CHAR(PVMF_FRAMERATE_VALUE_KEY); |
| iKVPFrameRate.key = iKVPStringFrameRate.get_str(); |
| iKVPFrameRate.value.uint32_value = aTrack->getTrackFrameRate(); |
| |
| if (aTrackSelection.iTsSinkNodeCapConfigIF != NULL) |
| aCheckcodec = aTrackSelection.iTsSinkNodeCapConfigIF->verifyParametersSync(NULL, &iKVPFrameRate, 1); |
| //In case of other error code, this is operation error. |
| if (aCheckcodec != PVMFErrNotSupported && aCheckcodec != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyTrackInfo() verifyParametersSync() on sink node framerate failed")); |
| return aCheckcodec; |
| } |
| } |
| |
| return status; |
| } |
| |
| PVMFStatus PVPlayerEngine::DoSinkNodeDecNodeReset(PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::DoSinkNodeDecNodeReset() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeDecNodeReset() In")); |
| |
| iNumPendingNodeCmd = 0; |
| PVMFCommandId cmdid = -1; |
| int32 leavecode = 0; |
| |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iSinkNode != NULL) |
| { |
| // Call Reset() on the sink node |
| PVPlayerEngineContext* context = AllocateEngineContext(&(iDatapathList[i]), iDatapathList[i].iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeDecNodeReset); |
| |
| leavecode = IssueSinkNodeReset(&(iDatapathList[i]), (OsclAny*) context, cmdid); |
| |
| if (cmdid != -1 && leavecode == 0) |
| { |
| ++iNumPendingNodeCmd; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeDecNodeReset() Reset on sink node leaved, asserting")); |
| FreeEngineContext(context); |
| OSCL_ASSERT(false); |
| } |
| } |
| |
| if (iDatapathList[i].iDecNode != NULL) |
| { |
| // Call Reset() on the dec node |
| PVPlayerEngineContext* context = AllocateEngineContext(&(iDatapathList[i]), iDatapathList[i].iDecNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeDecNodeReset); |
| |
| leavecode = IssueDecNodeReset(iDatapathList[i].iDecNode, iDatapathList[i].iDecNodeSessionId, (OsclAny*) context, cmdid); |
| |
| if (cmdid != -1 && leavecode == 0) |
| { |
| ++iNumPendingNodeCmd; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeDecNodeReset() Reset on sink node leaved, asserting")); |
| FreeEngineContext(context); |
| OSCL_ASSERT(false); |
| } |
| } |
| } |
| |
| // There can be some more decoders in TrackSelectionList on which engine needs to call Reset. call Reset on those decoders now. |
| for (uint32 j = 0; j < iTrackSelectionList.size(); j++) |
| { |
| if (iTrackSelectionList[j].iTsDecNode != NULL) |
| { |
| // Call Reset() on the dec node |
| PVPlayerEngineContext* context = AllocateEngineContext(NULL, iTrackSelectionList[j].iTsDecNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeDecNodeReset); |
| |
| leavecode = IssueDecNodeReset(iTrackSelectionList[j].iTsDecNode, iTrackSelectionList[j].iTsDecNodeSessionId, (OsclAny*) context, cmdid); |
| |
| if (cmdid != -1 && leavecode == 0) |
| { |
| ++iNumPendingNodeCmd; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeDecNodeReset() Reset on sink node leaved, asserting")); |
| FreeEngineContext(context); |
| OSCL_ASSERT(false); |
| } |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeDecNodeReset() Out")); |
| if (iNumPendingNodeCmd == 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeDecNodeReset() No datapath could be prepared!")); |
| return PVMFFailure; |
| } |
| else |
| { |
| return PVMFSuccess; |
| } |
| } |
| |
| PVMFStatus PVPlayerEngine::DoSinkDecCleanupSourcePrepare(PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() In")); |
| |
| uint32 i = 0; |
| //Destroy created temporal decoder node and sink node |
| for (i = 0; i < iTrackSelectionList.size(); ++i) |
| { |
| if (iTrackSelectionList[i].iTsDecNode != NULL) |
| { |
| if (iTrackSelectionList[i].iTsDecNodeCapConfigIF) |
| iTrackSelectionList[i].iTsDecNodeCapConfigIF = NULL; |
| PVMFStatus status = PVMFFailure; |
| status = iTrackSelectionList[i].iTsDecNode->Disconnect(iTrackSelectionList[i].iTsDecNodeSessionId); |
| if (status == PVMFFailure) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() Disconnect on dec node Failed")); |
| OSCL_ASSERT(false); |
| } |
| status = iTrackSelectionList[i].iTsDecNode->ThreadLogoff(); |
| if (status == PVMFFailure) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() ThreadLogoff on dec node Failed")); |
| OSCL_ASSERT(false); |
| } |
| PVPlayerEngineUuidNodeMapping* iter = iNodeUuids.begin(); |
| for (; iter != iNodeUuids.end(); ++iter) |
| if (iter->iNode == iTrackSelectionList[i].iTsDecNode) |
| break; |
| |
| if (iter != iNodeUuids.end()) |
| { |
| bool release_status = false; |
| |
| release_status = iPlayerNodeRegistry.ReleaseNode(iter->iUuid, iTrackSelectionList[i].iTsDecNode); |
| if (release_status == false) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() Factory returned false while releasing the decnode")); |
| OSCL_ASSERT(false); |
| return PVMFFailure; |
| } |
| |
| iNodeUuids.erase(iter); |
| iTrackSelectionList[i].iTsDecNode = NULL; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() decnode not found")); |
| return PVMFFailure; |
| } |
| } |
| if (iTrackSelectionList[i].iTsSinkNode != NULL) |
| { |
| for (uint32 j = 0; j < iDatapathList.size(); j++) |
| { |
| if (iDatapathList[j].iSinkNode == iTrackSelectionList[i].iTsSinkNode) |
| { |
| PVMFStatus status = PVMFFailure; |
| status = iDatapathList[j].iSinkNode->Disconnect(iDatapathList[j].iSinkNodeSessionId); |
| if (status == PVMFFailure) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() Disconnect on sink node Failed")); |
| OSCL_ASSERT(false); |
| } |
| status = iDatapathList[j].iSinkNode->ThreadLogoff(); |
| if (status == PVMFFailure) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() ThreadLogoff on sink node Failed")); |
| OSCL_ASSERT(false); |
| } |
| if (iDatapathList[j].iSinkNodeCapConfigIF) |
| iDatapathList[j].iSinkNodeCapConfigIF = NULL; |
| if (iDatapathList[j].iDataSink->GetDataSinkType() == PVP_DATASINKTYPE_FILENAME) |
| { |
| PVFileOutputNodeFactory::DeleteFileOutput(iDatapathList[j].iSinkNode); |
| iDatapathList[j].iSinkNode = NULL; |
| } |
| else if (iDatapathList[j].iDataSink->GetDataSinkType() == PVP_DATASINKTYPE_SINKNODE) |
| { |
| iDatapathList[j].iSinkNode = NULL; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() Unsupported player data sink type")); |
| return PVMFFailure; |
| } |
| } |
| } |
| } |
| } |
| |
| // Also go through the datapathList and if for any datapath TrackInfo is not created, delete that datapath |
| for (i = 0; i < iDatapathList.size(); i++) |
| { |
| if (iDatapathList[i].iTrackInfo == NULL) |
| { |
| // destroy the sinks first. |
| if (iDatapathList[i].iSinkNode != NULL) |
| { |
| PVMFStatus status = PVMFFailure; |
| status = iDatapathList[i].iSinkNode->Disconnect(iDatapathList[i].iSinkNodeSessionId); |
| if (status == PVMFFailure) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() Disconnect on sink node Failed")); |
| OSCL_ASSERT(false); |
| } |
| status = iDatapathList[i].iSinkNode->ThreadLogoff(); |
| if (status == PVMFFailure) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() ThreadLogoff on sink node Failed")); |
| OSCL_ASSERT(false); |
| } |
| if (iDatapathList[i].iSinkNodeCapConfigIF) |
| iDatapathList[i].iSinkNodeCapConfigIF = 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::DoSinkDecCleanupSourcePrepare() Unsupported player data sink type")); |
| return PVMFFailure; |
| } |
| } |
| |
| // next delete the decoder nodes |
| if (iDatapathList[i].iDecNode != NULL) |
| { |
| if (iDatapathList[i].iDecNodeCapConfigIF) |
| iDatapathList[i].iDecNodeCapConfigIF = NULL; |
| PVMFStatus status = PVMFFailure; |
| status = iDatapathList[i].iDecNode->Disconnect(iDatapathList[i].iDecNodeSessionId); |
| if (status == PVMFFailure) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() Disconnect on dec node Failed")); |
| OSCL_ASSERT(false); |
| } |
| status = iDatapathList[i].iDecNode->ThreadLogoff(); |
| if (status == PVMFFailure) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() ThreadLogoff on dec node Failed")); |
| OSCL_ASSERT(false); |
| } |
| PVPlayerEngineUuidNodeMapping* iter = iNodeUuids.begin(); |
| for (; iter != iNodeUuids.end(); ++iter) |
| if (iter->iNode == iDatapathList[i].iDecNode) |
| break; |
| |
| if (iter != iNodeUuids.end()) |
| { |
| bool release_status = false; |
| |
| release_status = iPlayerNodeRegistry.ReleaseNode(iter->iUuid, iDatapathList[i].iDecNode); |
| if (release_status == false) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() Factory returned false while releasing the decnode")); |
| OSCL_ASSERT(false); |
| return PVMFFailure; |
| } |
| |
| iNodeUuids.erase(iter); |
| iDatapathList[i].iDecNode = NULL; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() decnode not found")); |
| return PVMFFailure; |
| } |
| } |
| } |
| } |
| |
| // Reset the Presentation Info list |
| iSourcePresInfoList.Reset(); |
| |
| // Clear the Track selection List |
| iTrackSelectionList.clear(); |
| |
| PVMFStatus cmdstatus = PVMFFailure; |
| |
| // Notify the TargetNPT to the source node before calling Prepare. |
| if (iSourceNodePBCtrlIF) |
| { |
| cmdstatus = iSourceNodePBCtrlIF->NotifyTargetPositionSync(iTargetNPT); |
| } |
| if (cmdstatus == PVMFSuccess || cmdstatus == PVMFErrNotSupported) |
| { |
| // Prepare the source node |
| cmdstatus = DoSourceNodePrepare(aCmdId, aCmdContext); |
| } |
| if (cmdstatus != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() Already EH pending, should never happen")); |
| return PVMFPending; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() DoSourceNodePrepare failed, Add EH command")); |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| } |
| return PVMFFailure; |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkDecCleanupSourcePrepare() Out")); |
| 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.")); |
| return PVMFFailure; |
| } |
| |
| // If source node is already in Prepared state then don't call Prepare() |
| if (iSourceNode->GetState() == EPVMFNodePrepared) |
| { |
| // Datapaths are already set during intelligent track selection, just query for optional interfaces. |
| iNumPendingDatapathCmd = 0; |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iTrackInfo != NULL) |
| { |
| PVMFStatus cmdstatus = DoSinkNodeQueryInterfaceOptional(iDatapathList[i], aCmdId, aCmdContext); |
| if (cmdstatus == PVMFSuccess) |
| { |
| ++iNumPendingDatapathCmd; |
| } |
| } |
| } |
| |
| if (iNumPendingDatapathCmd == 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodePrepare() No datapath could be prepared!")); |
| return PVMFFailure; |
| } |
| else |
| { |
| return PVMFSuccess; |
| } |
| } |
| |
| // Call Prepare() on the source node |
| PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodePrepare); |
| |
| PVMFCommandId cmdid = -1; |
| int32 leavecode = 0; |
| OSCL_TRY(leavecode, cmdid = iSourceNode->Prepare(iSourceNodeSessionId, (OsclAny*)context)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodePrepare() Prepare on iSourceNode did a leave!")); |
| return PVMFFailure); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodePrepare() Out")); |
| |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVPlayerEngine::DoSinkNodeQueryInterfaceOptional(PVPlayerEngineDatapath &aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceOptional() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceOptional() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr())); |
| |
| int32 leavecode = 0; |
| |
| // Request optional extension interface from the sink node |
| PVPlayerEngineContext* context = NULL; |
| PVMFCommandId cmdid = -1; |
| aDatapath.iNumPendingCmd = 0; |
| |
| // Request the sync control interface for the sink node |
| context = AllocateEngineContext(&aDatapath, aDatapath.iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeQuerySyncCtrlIF); |
| cmdid = -1; |
| leavecode = 0; |
| aDatapath.iSinkNodePVInterfaceSyncCtrl = NULL; |
| OSCL_TRY(leavecode, cmdid = aDatapath.iSinkNode->QueryInterface(aDatapath.iSinkNodeSessionId, PvmfNodesSyncControlUuid, aDatapath.iSinkNodePVInterfaceSyncCtrl, (OsclAny*)context)); |
| if (leavecode) |
| { |
| aDatapath.iSinkNodePVInterfaceSyncCtrl = NULL; |
| 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; |
| aDatapath.iSinkNodePVInterfaceMetadataExt = NULL; |
| OSCL_TRY(leavecode, cmdid = aDatapath.iSinkNode->QueryInterface(aDatapath.iSinkNodeSessionId, metadatauuid, aDatapath.iSinkNodePVInterfaceMetadataExt, (OsclAny*)context)); |
| if (leavecode) |
| { |
| aDatapath.iSinkNodePVInterfaceMetadataExt = NULL; |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceOptional() QueryInterface on sink node for metadata IF did a leave!")); |
| } |
| else |
| { |
| ++aDatapath.iNumPendingCmd; |
| } |
| |
| if (aDatapath.iNumPendingCmd > 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceOptional() Out")); |
| return PVMFSuccess; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeQueryInterfaceOptional() Out No pending QueryInterface() on sink node")); |
| return PVMFErrNotSupported; |
| } |
| } |
| |
| PVMFStatus PVPlayerEngine::DoDecNodeQueryInterfaceOptional(PVPlayerEngineDatapath &aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::DoDecNodeQueryInterfaceOptional() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDecNodeQueryInterfaceOptional() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr())); |
| |
| // Check if the dec node is present |
| if (aDatapath.iDecNode == NULL) |
| { |
| return PVMFErrNotSupported; |
| } |
| |
| PVPlayerEngineContext* context = NULL; |
| PVMFCommandId cmdid = -1; |
| int32 leavecode = 0; |
| |
| aDatapath.iNumPendingCmd = 0; |
| |
| // Query for Metadata IF |
| context = AllocateEngineContext(&aDatapath, aDatapath.iDecNode, NULL, aCmdId, aCmdContext, PVP_CMD_DecNodeQueryMetadataIF); |
| PVUuid metadatauuid = KPVMFMetadataExtensionUuid; |
| cmdid = -1; |
| leavecode = 0; |
| aDatapath.iDecNodePVInterfaceMetadataExt = NULL; |
| OSCL_TRY(leavecode, cmdid = aDatapath.iDecNode->QueryInterface(aDatapath.iDecNodeSessionId, metadatauuid, aDatapath.iDecNodePVInterfaceMetadataExt, (OsclAny*)context)); |
| if (leavecode) |
| { |
| aDatapath.iDecNodePVInterfaceMetadataExt = NULL; |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDecNodeQueryInterfaceOptional() QueryInterface on dec node for metadata IF did a leave!")); |
| } |
| else |
| { |
| ++aDatapath.iNumPendingCmd; |
| } |
| |
| if (aDatapath.iNumPendingCmd > 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDecNodeQueryInterfaceOptional() Out")); |
| return PVMFSuccess; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDecNodeQueryInterfaceOptional() Out No pending QueryInterface() on dec node")); |
| return PVMFErrNotSupported; |
| } |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoDatapathPrepare(PVPlayerEngineDatapath &aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::DoDatapathPrepare() for %s Tick=%d", |
| aDatapath.iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathPrepare() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr())); |
| int32 leavecode = 0; |
| |
| // Create the datapath utility object |
| if (aDatapath.iDatapath == NULL) |
| { |
| leavecode = 0; |
| OSCL_TRY(leavecode, aDatapath.iDatapath = OSCL_NEW(PVPlayerDatapath, ())); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDatapathPrepare() Could not create datapath object")); |
| return PVMFErrNoMemory); |
| } |
| |
| // Configure the datapath utility based on datapath configuration |
| aDatapath.iDatapath->SetObserver(*this, *this, *this); |
| aDatapath.iDatapath->SetSourceNode(iSourceNode); |
| aDatapath.iDatapath->SetSinkNode(aDatapath.iSinkNode); |
| |
| if (aDatapath.iDecNode) |
| { |
| aDatapath.iDatapath->SetDecNode(aDatapath.iDecNode); |
| aDatapath.iDatapath->SetSourceDecTrackInfo(*(aDatapath.iTrackInfo)); |
| aDatapath.iDatapath->SetDecSinkFormatType(aDatapath.iSinkFormat); |
| } |
| else |
| { |
| aDatapath.iDatapath->SetSourceSinkTrackInfo(*(aDatapath.iTrackInfo)); |
| } |
| |
| // Prepare the datapath |
| PVPlayerEngineContext* context = AllocateEngineContext(&aDatapath, NULL, aDatapath.iDatapath, aCmdId, aCmdContext, PVP_CMD_DPPrepare); |
| |
| PVMFStatus retval = aDatapath.iDatapath->Prepare((OsclAny*)context); |
| if (retval != PVMFSuccess) |
| { |
| FreeEngineContext(context); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathPrepare() Out")); |
| return retval; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoSourceNodeQueryDataSourcePosition(PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeQueryDataSourcePosition() In")); |
| |
| // Check if the source node has position control IF |
| if (iSourceNodePBCtrlIF == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryDataSourcePosition() Playback control IF on source node not available")); |
| return PVMFErrNotSupported; |
| } |
| |
| uint32 timems = 0; |
| if (iCurrentBeginPosition.iIndeterminate == false) |
| { |
| // Convert beginning position to milliseconds |
| PVMFStatus retval = ConvertToMillisec(iCurrentBeginPosition, timems); |
| if (retval != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryDataSourcePosition() Converting to millisec failed")); |
| return retval; |
| } |
| } |
| |
| PVMFCommandId cmdid = -1; |
| |
| if (iSeekToSyncPoint && iSyncPointSeekWindow > 0) |
| { |
| PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeQueryDataSourcePosition); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeQueryDataSourcePosition() Calling QueryDataSourcePosition() Starting pos %d ms, SeekToSyncPt %d", iTargetNPT, iSeekToSyncPoint)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeQueryDataSourcePosition() Calling QueryDataSourcePosition() Starting pos %d ms, SeekToSyncPt %d", iTargetNPT, iSeekToSyncPoint)); |
| // As in case of MP4 file we need to call overload function of QueryDataSourcePosition which retruns |
| // I frame before and after instead of actaul NPT, format type will be checked here to first find if |
| // format-type is one of the MP4 varient |
| |
| PVMFNodeCapability nodeCapability; |
| iSourceNode->GetCapability(nodeCapability); |
| PVMFFormatType * formatType = nodeCapability.iInputFormatCapability.begin(); |
| bool mpeg4FormatType = false; |
| if (formatType != NULL) |
| { |
| if ((pv_mime_strcmp((char*)formatType->getMIMEStrPtr(), PVMF_MIME_MPEG4FF)) == 0) |
| { |
| mpeg4FormatType = true; |
| } |
| else |
| { |
| mpeg4FormatType = false; |
| } |
| } |
| int32 leavecode = 0; |
| if (mpeg4FormatType) |
| { |
| OSCL_TRY(leavecode, cmdid = iSourceNodePBCtrlIF->QueryDataSourcePosition(iSourceNodeSessionId, iTargetNPT, |
| iSeekPointBeforeTargetNPT, iSeekPointAfterTargetNPT, (OsclAny*) context, iSeekToSyncPoint)); |
| } |
| else |
| { |
| OSCL_TRY(leavecode, cmdid = iSourceNodePBCtrlIF->QueryDataSourcePosition(iSourceNodeSessionId, iTargetNPT, iActualNPT, |
| iSeekToSyncPoint, (OsclAny*)context)); |
| } |
| |
| if (leavecode != 0) |
| { |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeQueryDataSourcePosition() QueryDataSourcePosition on iSourceNodePBCtrlIF did a leave!")); |
| if (leavecode == PVMFErrNotSupported || leavecode == PVMFErrArgument) |
| { |
| // Since position query is not supported, assume the repositioning will |
| // go to the requested position |
| // Do the source positioning |
| return DoSourceNodeSetDataSourcePosition(aCmdId, aCmdContext); |
| } |
| else |
| { |
| return PVMFFailure; |
| } |
| } |
| } |
| else |
| { |
| // Go straight to repositioning the data source |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeQueryDataSourcePosition: Straight call SetDataSourcePosition Starting pos %d ms, SeekToSyncPt %d", iTargetNPT, iSeekToSyncPoint)); |
| return DoSourceNodeSetDataSourcePosition(aCmdId, aCmdContext); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeQueryDataSourcePosition() Out")); |
| |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoSourceNodeSetDataSourcePosition(PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePosition() In")); |
| |
| // Check if the source node has position control IF |
| if (iSourceNodePBCtrlIF == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePosition() Playback control IF on source node not available")); |
| // Since repositioning IF is not supported by this source node, assume the playback |
| // will start from time 0 |
| iActualNPT = 0; |
| iActualMediaDataTS = 0; |
| iSkipMediaDataTS = 0; |
| // Then continue to handle like success case |
| iStartNPT = 0; |
| iStartMediaDataTS = 0; |
| // Save the actual starting position for GetPlaybackRange() query |
| iCurrentBeginPosition.iPosValue.millisec_value = iActualNPT; |
| iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| iTargetNPT = iActualNPT; |
| |
| // Repositioning so reset the EOS received flag for each active datapath |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath) |
| { |
| iDatapathList[i].iEndOfDataReceived = false; |
| } |
| } |
| |
| // Start the source node |
| return DoSourceNodeStart(aCmdId, aCmdContext); |
| } |
| |
| // Set the position of the source node |
| PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeSetDataSourcePosition); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePosition() Calling SetDataSourcePosition() TargetNPT %d ms, SeekToSyncPoint %d", iTargetNPT, iSeekToSyncPoint)); |
| |
| int32 leavecode = 0; |
| PVMFCommandId cmdid = -1; |
| |
| OSCL_TRY(leavecode, cmdid = iSourceNodePBCtrlIF->SetDataSourcePosition(iSourceNodeSessionId, iTargetNPT, iActualNPT, iActualMediaDataTS, iSeekToSyncPoint, iStreamID, (OsclAny*)context)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePosition() SetDataSourcePosition on iSourceNodePBCtrlIF did a leave!")); |
| if (leavecode == PVMFErrNotSupported || leavecode == PVMFErrArgument) |
| { |
| // Since this repositioning was not supported, assume the playback |
| // will start from same location as before reposition request. |
| PVPPlaybackPosition curpos; |
| curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| GetPlaybackClockPosition(curpos); |
| uint32 clockcurpos = 0; |
| bool tmpbool = false; |
| iPlaybackClock.GetCurrentTime32(clockcurpos, tmpbool, PVMF_MEDIA_CLOCK_MSEC); |
| |
| // since repositioning is not supported continue playing from current position. |
| iWatchDogTimerInterval = 0; |
| iActualNPT = curpos.iPosValue.millisec_value; |
| iActualMediaDataTS = clockcurpos; |
| iSkipMediaDataTS = clockcurpos; |
| |
| iStartNPT = iActualNPT; |
| iStartMediaDataTS = iSkipMediaDataTS; |
| |
| // also decrement the stream id as no skip will be called on MIO node. |
| --iStreamID; |
| |
| // Save the actual starting position for GetPlaybackRange() query |
| iCurrentBeginPosition.iPosValue.millisec_value = iActualNPT; |
| iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| iTargetNPT = iActualNPT; |
| |
| // Repositioning so reset the EOS received flag for each active datapath |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath) |
| { |
| iDatapathList[i].iEndOfDataReceived = false; |
| } |
| } |
| |
| // Start the source node |
| return DoSourceNodeStart(aCmdId, aCmdContext); |
| } |
| else |
| { |
| return PVMFFailure; |
| } |
| ); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourcePosition() Out")); |
| |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVPlayerEngine::DoSourceNodeSetDataSourceDirection(PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourceDirection() In")); |
| |
| if (iChangePlaybackDirectionWhenResuming) |
| { |
| //Setting direction during engine Resume, due to a SetPlaybackRate that |
| //occurred during engine Paused state. |
| |
| // Check if the source node has position control IF |
| if (iSourceNodeDirCtrlIF == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeSetDataSourceDirection() Direction control IF on source node not available")); |
| |
| // Since repositioning IF is not supported by this source node, assume the playback |
| // will start from time 0 |
| iActualNPT = 0; |
| iActualMediaDataTS = 0; |
| iSkipMediaDataTS = 0; |
| // Then continue to handle like success case |
| iStartNPT = 0; |
| iStartMediaDataTS = 0; |
| // Save the actual starting position for GetPlaybackRange() query |
| iCurrentBeginPosition.iPosValue.millisec_value = iActualNPT; |
| iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| iTargetNPT = iActualNPT; |
| |
| // Repositioning so reset the EOS flag for each active datapath |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath) |
| { |
| iDatapathList[i].iEndOfDataReceived = false; |
| } |
| } |
| |
| return PVMFErrNotSupported; |
| } |
| |
| // Set the position of the source node |
| PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeSetDataSourceDirection); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourceDirection() Calling SetDataSourcePosition() ")); |
| |
| int32 leavecode = 0; |
| PVMFCommandId cmdid = -1; |
| OSCL_TRY(leavecode, cmdid = iSourceNodeDirCtrlIF->SetDataSourceDirection(iSourceNodeSessionId |
| , (iPlaybackDirection_New < 0) ? PVMF_DATA_SOURCE_DIRECTION_REVERSE : PVMF_DATA_SOURCE_DIRECTION_FORWARD |
| , iActualNPT |
| , iActualMediaDataTS |
| , iOutsideTimebase |
| , (OsclAny*)context)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeSetDataSourceDirection() SetDataSourceDirection on iSourceNodeDirCtrlIF did a leave!")); |
| if (leavecode == PVMFErrNotSupported || leavecode == PVMFErrArgument) |
| { |
| // Since this repositioning was not supported, assume the playback |
| // will start from same location as before repos request. |
| PVPPlaybackPosition curpos; |
| curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| GetPlaybackClockPosition(curpos); |
| uint32 clockcurpos = 0; |
| bool tmpbool = false; |
| iPlaybackClock.GetCurrentTime32(clockcurpos, tmpbool, PVMF_MEDIA_CLOCK_MSEC); |
| |
| // since repositioning is not supported continue playing from current position. |
| iWatchDogTimerInterval = 0; |
| iActualNPT = curpos.iPosValue.millisec_value; |
| iActualMediaDataTS = clockcurpos; |
| iSkipMediaDataTS = clockcurpos; |
| |
| iStartNPT = iActualNPT; |
| iStartMediaDataTS = iSkipMediaDataTS; |
| |
| // Save the actual starting position for GetPlaybackRange() query |
| iCurrentBeginPosition.iPosValue.millisec_value = iActualNPT; |
| iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| iTargetNPT = iActualNPT; |
| |
| // Repositioning so reset the EOS flag for each active datapath |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath) |
| { |
| iDatapathList[i].iEndOfDataReceived = false; |
| } |
| } |
| |
| return PVMFErrNotSupported; |
| } |
| else |
| { |
| return PVMFFailure; |
| } |
| ); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourceDirection() Out")); |
| |
| return PVMFSuccess; |
| } |
| else |
| { |
| //changing direction during SetPlaybackRate command |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourceDirection() In")); |
| |
| // Check if the source node has direction control IF |
| if (iSourceNodeDirCtrlIF == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeSetDataSourceDirection() No source direction control IF")); |
| return PVMFFailure; |
| } |
| |
| // Pause the playback clock |
| bool clockpausedhere = iPlaybackClock.Pause(); |
| |
| // Set the new direction on the source node |
| PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeSetDataSourceDirection); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourceDirection() Calling SetDataSourceDirection() on source node.")); |
| |
| int32 leavecode = 0; |
| PVMFCommandId cmdid = -1; |
| OSCL_TRY(leavecode, cmdid = iSourceNodeDirCtrlIF->SetDataSourceDirection(iSourceNodeSessionId |
| , (iPlaybackDirection_New < 0) ? PVMF_DATA_SOURCE_DIRECTION_REVERSE : PVMF_DATA_SOURCE_DIRECTION_FORWARD |
| , iActualNPT |
| , iActualMediaDataTS |
| , iOutsideTimebase_New |
| , (OsclAny*)context)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeSetDataSourceDirection() SetDataSourceDirection on iSourceNodeDirCtrlIF did a leave!")); |
| if (clockpausedhere) |
| { |
| // Resume the clock if paused in this function |
| StartPlaybackClock(); |
| } |
| |
| if (leavecode == PVMFErrNotSupported || leavecode == PVMFErrArgument) |
| { |
| return leavecode; |
| } |
| else |
| { |
| return PVMFFailure; |
| } |
| ); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeSetDataSourceDirection() Out")); |
| |
| return PVMFSuccess; |
| //wait on node command complete and a call to HandleSourceNodeSetDataSourceDirection |
| } |
| } |
| |
| PVMFStatus PVPlayerEngine::DoSourceNodeStart(PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::DoSourceNodeStart() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeStart() In")); |
| |
| if (iSourceNode == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeStart() Source node not available.")); |
| return PVMFFailure; |
| } |
| |
| // Start the source node |
| PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, PVP_CMD_SourceNodeStart); |
| |
| PVMFCommandId cmdid = -1; |
| int32 leavecode = 0; |
| OSCL_TRY(leavecode, cmdid = iSourceNode->Start(iSourceNodeSessionId, (OsclAny*)context)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeStart() Start on iSourceNode did a leave!")); |
| return PVMFFailure); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeStart() Out")); |
| |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoDatapathStart(PVPlayerEngineDatapath &aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::DoDatapathStart() for %s Tick=%d", |
| aDatapath.iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathStart() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr())); |
| |
| // Start the datapath |
| PVPlayerEngineContext* context = AllocateEngineContext(&aDatapath, NULL, aDatapath.iDatapath, aCmdId, aCmdContext, PVP_CMD_DPStart); |
| |
| PVMFStatus retval = aDatapath.iDatapath->Start((OsclAny*)context); |
| if (retval != PVMFSuccess) |
| { |
| FreeEngineContext(context); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathStart() Out")); |
| return retval; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoSinkNodeSkipMediaData(PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::DoSinkNodeSkipMediaData() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeSkipMediaData() In")); |
| |
| // Tell the sink nodes to skip the unneeded media data |
| iNumPendingNodeCmd = 0; |
| int32 leavecode = 0; |
| |
| // Call SkipMediaData() for each active datapath with sink nodes that have the sync control IF |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath && |
| iDatapathList[i].iEndOfDataReceived == false && |
| iDatapathList[i].iSinkNodeSyncCtrlIF) |
| { |
| PVPlayerEngineContext* context = AllocateEngineContext(&(iDatapathList[i]), iDatapathList[i].iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeSkipMediaData); |
| |
| leavecode = IssueSinkSkipMediaData(&(iDatapathList[i]), 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_STARTED) |
| { |
| if (iState == PVP_ENGINE_STATE_AUTO_PAUSED) |
| { |
| // Engine in AUTO-PAUSED state since it recieved an Underflow event |
| // during Prepare. Set the engine state to STARTED and return success |
| // Wait for DataReady event for the playback to start. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::DoStart() Engine in auto-paused state, set it to started")); |
| SetEngineState(PVP_ENGINE_STATE_STARTED); |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoStart() Engine already in Started State")); |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| return PVMFSuccess; |
| } |
| |
| if (iPlaybackPausedDueToEndOfClip) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoStart() Playback already paused due to End of clip")); |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| return PVMFSuccess; |
| } |
| if (GetPVPlayerState() != PVP_STATE_PREPARED) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoStart() Wrong engine state")); |
| return PVMFErrInvalidState; |
| } |
| |
| if (iNumPVMFInfoStartOfDataPending == 0) |
| { |
| // start the clock only if Skip is complete and InfoStartOfData has been received |
| // Enable the end time check if specified |
| UpdateCurrentEndPosition(iCurrentEndPosition); |
| StartPlaybackClock(); |
| } |
| else |
| { |
| // Sink nodes have not reported InfoStartOfData yet. |
| // Check if WatchDogTimer has already been set or not, |
| // if Timer has not been set or has expired then set it to a default value timer. |
| if (!(iWatchDogTimer->IsBusy())) |
| { |
| // set a dafault timer |
| iWatchDogTimerInterval = 0; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::DoStart() Setting WatchDogTimer to a dafult value of 1 second")); |
| iWatchDogTimer->setTimerDuration(iWatchDogTimerInterval); // this will set a timer to a default |
| iWatchDogTimer->Start(); // value of 1 sec. since iWatchDogTimerInterval is zero. |
| } |
| } |
| |
| SetEngineState(PVP_ENGINE_STATE_STARTED); |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoStart() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoPause(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_NOTICE, |
| (0, "PVPlayerEngine::DoPause() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoPause() In")); |
| |
| // Check engine state |
| switch (GetPVPlayerState()) |
| { |
| case PVP_STATE_PAUSED : |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoPause() Engine already in Paused State")); |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| return PVMFSuccess; |
| |
| case PVP_STATE_STARTED : |
| break; |
| |
| case PVP_STATE_PREPARED : |
| if (aCmd.GetCmdType() == PVP_ENGINE_COMMAND_PAUSE_DUE_TO_ENDOFCLIP) |
| { |
| //It is possible in repositioning to end use-case that |
| //engine receives StartofData and EndofData before Prepare |
| //completes. So we should not fail Pause, just process it. |
| break; |
| } |
| |
| default: |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPause() Wrong engine state")); |
| return PVMFErrInvalidState; |
| } |
| |
| // Send position update to app. |
| SendPositionStatusUpdate(); |
| |
| // Stop the end time check timer |
| iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_ENDTIMECHECK); |
| |
| // Stop the watchdog timer if active. We will Start the timer again in resume. |
| // this should only be done when engine is waiting for StartofData info event |
| // after reposition. |
| if (iNumPVMFInfoStartOfDataPending > 0) |
| { |
| if (iWatchDogTimer->IsBusy()) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::DoPause - Pause after setplayback, Cancelling Watchdog timer, iNumPVMFInfoStartOfDataPending=%d", iNumPVMFInfoStartOfDataPending)); |
| iWatchDogTimer->Cancel(); |
| } |
| } |
| |
| // Pause the clock and notify sinks if not auto-paused |
| uint32 i; |
| if (iState != PVP_ENGINE_STATE_AUTO_PAUSED) |
| { |
| // Pause the playback clock |
| iPlaybackClock.Pause(); |
| // Notify data sinks that clock has paused |
| for (i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath && iDatapathList[i].iSinkNodeSyncCtrlIF) |
| { |
| iDatapathList[i].iSinkNodeSyncCtrlIF->ClockStopped(); |
| } |
| } |
| } |
| |
| PVMFStatus retval = PVMFErrNotSupported; |
| |
| // Issue pause to all active datapaths |
| iNumPendingDatapathCmd = 0; |
| |
| for (i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath) |
| { |
| if (iState == PVP_ENGINE_STATE_AUTO_PAUSED) |
| { |
| // Since sinks are already paused in auto-pause state, skip pausing the sink in the datapath |
| retval = DoDatapathPause(iDatapathList[i], 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 |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPause() Already EH pending, should never happen")); |
| return PVMFPending; |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPause() DoDatapathPause Failed, Add EH command")); |
| iCommandCompleteStatusInErrorHandling = retval; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PAUSE, NULL, NULL, NULL, false); |
| return PVMFPending; |
| } |
| } |
| } |
| |
| if (iNumPendingDatapathCmd == 0) |
| { |
| // If there are no active datapaths, continue on to pause the source node |
| retval = DoSourceNodePause(aCmd.GetCmdId(), aCmd.GetContext()); |
| } |
| |
| if (retval != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPause() Already EH pending, should never happen")); |
| return PVMFPending; |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoPause() Pausing datapath and source node failed, Add EH command")); |
| iCommandCompleteStatusInErrorHandling = retval; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PAUSE, NULL, NULL, NULL, false); |
| return PVMFPending; |
| } |
| |
| // TEMP Until queued playback range is available |
| // Reset the flag when doing a pause |
| iChangePlaybackPositionWhenResuming = false; |
| iChangePlaybackDirectionWhenResuming = false; |
| // END TEMP |
| |
| SetEngineState(PVP_ENGINE_STATE_PAUSING); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoPause() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoDatapathPause(PVPlayerEngineDatapath& aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext, bool aSinkPaused) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::DoDatapathPause() for %s Tick=%d", |
| aDatapath.iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount())); |
| |
| if (aDatapath.iTrackInfo == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDatapathPause() TrackInfo not available, failure")); |
| return PVMFFailure; |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathPause() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr())); |
| |
| // Pause the datapath |
| PVPlayerEngineContext* context = AllocateEngineContext(&aDatapath, NULL, aDatapath.iDatapath, aCmdId, aCmdContext, -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")); |
| 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)); |
| |
| if (GetPVPlayerState() == PVP_STATE_STARTED) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoResume() Engine already in Started State")); |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| return PVMFSuccess; |
| } |
| |
| // Check engine state |
| if (GetPVPlayerState() != PVP_STATE_PAUSED) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoResume() Wrong engine state")); |
| return PVMFErrInvalidState; |
| } |
| |
| // Disallow resume when paused due to EOS and position/direction |
| // hasn't been changed |
| if (iPlaybackPausedDueToEndOfClip) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoResume() Currently paused due to EOS so not allowed!")); |
| return PVMFErrInvalidState; |
| } |
| |
| PVMFStatus retval; |
| if (iChangePlaybackPositionWhenResuming) |
| { |
| // Reposition occurred during the paused state so need to change the source position first |
| retval = DoSourceNodeQueryDataSourcePosition(aCmd.GetCmdId(), aCmd.GetContext()); |
| // ignore failure, continue on to Start |
| if (retval != PVMFSuccess) |
| { |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| PVMFBasicErrorInfoMessage* infomsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoChangePlaybackPositionNotSupported, puuid, NULL)); |
| SendInformationalEvent(PVMFInfoChangePlaybackPositionNotSupported, OSCL_STATIC_CAST(PVInterface*, infomsg)); |
| infomsg->removeRef(); |
| retval = DoSourceNodeStart(aCmd.GetCmdId(), aCmd.GetContext()); |
| } |
| } |
| else if (iChangePlaybackDirectionWhenResuming) |
| { |
| // Direction change occurred during the paused state so need to change the source direction first |
| retval = DoSourceNodeSetDataSourceDirection(aCmd.GetCmdId(), aCmd.GetContext()); |
| // ignore failure, continue on to Start |
| if (retval != PVMFSuccess) |
| { |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| PVMFBasicErrorInfoMessage* infomsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoChangePlaybackPositionNotSupported, puuid, NULL)); |
| SendInformationalEvent(PVMFInfoChangePlaybackPositionNotSupported, OSCL_STATIC_CAST(PVInterface*, infomsg)); |
| infomsg->removeRef(); |
| retval = DoSourceNodeStart(aCmd.GetCmdId(), aCmd.GetContext()); |
| } |
| } |
| else |
| { |
| retval = DoSourceNodeStart(aCmd.GetCmdId(), aCmd.GetContext()); |
| } |
| |
| if (retval != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoResume() Already EH pending, should never happen")); |
| return PVMFPending; |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoResume() Resuming source node or changing position failed, Add EH command")); |
| iCommandCompleteStatusInErrorHandling = retval; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME, NULL, NULL, NULL, false); |
| return PVMFPending; |
| } |
| |
| SetEngineState(PVP_ENGINE_STATE_RESUMING); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoResume() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::AddToMetadataInterfaceList(PVMFMetadataExtensionInterface* aMetadataIF, PVMFSessionId aSessionId, PVPlayerEngineDatapath* aEngineDatapath, PVMFNodeInterface* aNode) |
| { |
| // Validate the interface ptr |
| if (aMetadataIF == NULL) |
| { |
| return PVMFErrArgument; |
| } |
| |
| // Add the specified interface ptr and session ID to the list |
| PVPlayerEngineMetadataIFInfo mdifinfo; |
| mdifinfo.iInterface = aMetadataIF; |
| mdifinfo.iSessionId = aSessionId; |
| mdifinfo.iEngineDatapath = aEngineDatapath; |
| mdifinfo.iNode = aNode; |
| int32 leavecode = 0; |
| OSCL_TRY(leavecode, iMetadataIFList.push_back(mdifinfo)); |
| OSCL_FIRST_CATCH_ANY(leavecode, return PVMFErrNoMemory); |
| |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVPlayerEngine::RemoveFromMetadataInterfaceList(PVMFMetadataExtensionInterface* aMetadataIF, PVMFSessionId aSessionId) |
| { |
| // Validate the interface ptr |
| if (aMetadataIF == NULL) |
| { |
| return PVMFErrArgument; |
| } |
| |
| // Go through the list to find the specified entry |
| for (uint32 i = 0; i < iMetadataIFList.size(); ++i) |
| { |
| if (aMetadataIF == iMetadataIFList[i].iInterface && |
| aSessionId == iMetadataIFList[i].iSessionId) |
| { |
| // Found it. Now erase it from the list |
| iMetadataIFList.erase(iMetadataIFList.begin() + i); |
| return PVMFSuccess; |
| } |
| } |
| |
| // If here that means the specified entry wasn't found in the list |
| return PVMFErrArgument; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoStop(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoStop() In")); |
| |
| if (GetPVPlayerState() == PVP_STATE_INITIALIZED) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoStop() Engine already in Initialized State")); |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| return PVMFSuccess; |
| } |
| |
| if (GetPVPlayerState() != PVP_STATE_PREPARED && |
| GetPVPlayerState() != PVP_STATE_STARTED && |
| GetPVPlayerState() != PVP_STATE_PAUSED) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoStop() Wrong engine state")); |
| return PVMFErrInvalidState; |
| } |
| |
| if (iReleaseMetadataValuesPending) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::DoStop() Wrong engine Usage, Stop called without releasing metadata values")); |
| return PVMFErrReleaseMetadataValueNotDone; |
| } |
| |
| // reset the dataReady event boolean |
| iDataReadySent = false; |
| |
| // reset all repos related variables |
| ResetReposVariables(true); |
| |
| // Stop the playback position status timer |
| StopPlaybackStatusTimer(); |
| |
| // Stop the playback clock |
| iPlaybackClock.Stop(); |
| uint32 starttime = 0; |
| bool overflow = 0; |
| iPlaybackClock.SetStartTime32(starttime, PVMF_MEDIA_CLOCK_MSEC, overflow); |
| iPlaybackDirection = 1; |
| |
| // Reset the begin/end time variables |
| iCurrentBeginPosition.iIndeterminate = true; |
| iCurrentEndPosition.iIndeterminate = true; |
| iQueuedBeginPosition.iIndeterminate = true; |
| iQueuedEndPosition.iIndeterminate = true; |
| |
| // Reset the paused-due-to-EOS flag |
| iPlaybackPausedDueToEndOfClip = false; |
| |
| // Stop the end time check |
| if (iEndTimeCheckEnabled) |
| { |
| iEndTimeCheckEnabled = false; |
| iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_ENDTIMECHECK); |
| } |
| |
| PVMFStatus retval = PVMFErrNotSupported; |
| |
| // Start the stopping sequence |
| // First stop all the active datapaths |
| iNumPendingDatapathCmd = 0; |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath) |
| { |
| PVMFStatus retcode = DoDatapathStop(iDatapathList[i], aCmd.GetCmdId(), aCmd.GetContext()); |
| if (retcode == PVMFSuccess) |
| { |
| ++iNumPendingDatapathCmd; |
| retval = PVMFSuccess; |
| } |
| else |
| { |
| retval = retcode; |
| break; |
| } |
| } |
| } |
| |
| if (iNumPendingDatapathCmd == 0 && retval == PVMFErrNotSupported) |
| { |
| // If there are no active datapath, stop the source node |
| retval = DoSourceNodeStop(aCmd.GetCmdId(), aCmd.GetContext()); |
| } |
| |
| if (retval != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoStop() Already EH pending, should never happen")); |
| return PVMFPending; |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoStop() source node failed, go in Error handling, Add EH command")); |
| iCommandCompleteStatusInErrorHandling = retval; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_STOP, NULL, NULL, NULL, false); |
| return PVMFPending; |
| } |
| |
| SetEngineState(PVP_ENGINE_STATE_STOPPING); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoStop() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoDatapathStop(PVPlayerEngineDatapath& aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathStop() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr())); |
| if (aDatapath.iTrackInfo == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDatapathStop() TrackInfo not available, failure")); |
| return PVMFFailure; |
| } |
| |
| // Stop the datapath |
| PVPlayerEngineContext* context = AllocateEngineContext(&aDatapath, NULL, aDatapath.iDatapath, aCmdId, aCmdContext, PVP_CMD_DPStop); |
| |
| PVMFStatus retval = aDatapath.iDatapath->Stop((OsclAny*)context); |
| if (retval != PVMFSuccess) |
| { |
| FreeEngineContext(context); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathStop() Out")); |
| return retval; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoSourceNodeStop(PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeStop() In")); |
| |
| if (iSourceNode == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeStop() Source node not available.")); |
| return PVMFFailure; |
| } |
| |
| // Stop the source node |
| PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, aCmdId, aCmdContext, -1); |
| |
| PVMFCommandId cmdid = -1; |
| int32 leavecode = 0; |
| OSCL_TRY(leavecode, cmdid = iSourceNode->Stop(iSourceNodeSessionId, (OsclAny*)context)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeStop() Stop on iSourceNode did a leave!")); |
| return PVMFFailure); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeStop() Out")); |
| |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoDatapathTeardown(PVPlayerEngineDatapath &aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathTeardown() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr())); |
| |
| PVPlayerEngineContext* context = AllocateEngineContext(&aDatapath, NULL, aDatapath.iDatapath, aCmdId, aCmdContext, PVP_CMD_DPTeardown); |
| |
| PVMFStatus retval = aDatapath.iDatapath->Teardown((OsclAny*)context); |
| if (retval != PVMFSuccess) |
| { |
| FreeEngineContext(context); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathTeardown() Out")); |
| return retval; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoDatapathReset(PVPlayerEngineDatapath &aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathReset() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr())); |
| |
| // Reset the datapath |
| PVPlayerEngineContext* context = AllocateEngineContext(&aDatapath, NULL, aDatapath.iDatapath, aCmdId, aCmdContext, PVP_CMD_DPReset); |
| |
| PVMFStatus retval = aDatapath.iDatapath->Reset((OsclAny*)context); |
| if (retval != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoDatapathReset() Reset failed. Asserting")); |
| FreeEngineContext(context); |
| OSCL_ASSERT(false); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoDatapathReset() Out")); |
| return retval; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoRemoveDataSink(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoRemoveDataSink() In")); |
| |
| // previously removed, e.g. during error handling ? |
| if (iDatapathList.empty() && GetPVPlayerState() == PVP_STATE_IDLE) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoRemoveDataSink() All sinks were previously deleted")); |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| return PVMFSuccess; |
| } |
| |
| if (GetPVPlayerState() != PVP_STATE_INITIALIZED) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoRemoveDataSink() Wrong engine state")); |
| return PVMFErrInvalidState; |
| } |
| |
| PVPlayerDataSink* datasink = (PVPlayerDataSink*)(aCmd.GetParam(0).pOsclAny_value); |
| |
| if (datasink == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoRemoveDataSink() Passed in parameter invalid")); |
| return PVMFErrArgument; |
| } |
| |
| // Find the track that the passed-in sink belongs to |
| PVPlayerEngineDatapath* pvpedp = NULL; |
| int32 dpindex = -1; |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDataSink == datasink) |
| { |
| pvpedp = &(iDatapathList[i]); |
| dpindex = i; |
| break; |
| } |
| } |
| |
| if (pvpedp == NULL || dpindex == -1) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoRemoveDataSink() Passed in data sink does not match with ones in engine")); |
| return PVMFFailure; |
| } |
| else |
| { |
| // Cleanup and remove the datapath associated with the data sink from the list |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoRemoveDataSink() Removing datapath")); |
| DoEngineDatapathCleanup(*pvpedp); |
| |
| iDatapathList.erase(iDatapathList.begin() + dpindex); |
| } |
| |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoRemoveDataSink() Out")); |
| return PVMFSuccess; |
| } |
| |
| void PVPlayerEngine::DoRemoveAllSinks() |
| { |
| // Clean up the datapaths |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| DoEngineDatapathCleanup(iDatapathList[i]); |
| } |
| iDatapathList.clear(); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoRemoveAllSinks() all datapaths removed")); |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoReset(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoReset() In")); |
| |
| // set engine state to Resetting |
| SetEngineState(PVP_ENGINE_STATE_RESETTING); |
| iRollOverState = RollOverStateIdle; //reset roll over state to Idle, as engine is resetting itself |
| |
| // reset all repos related variables |
| ResetReposVariables(true); |
| |
| // Stop the playback position status timer |
| StopPlaybackStatusTimer(); |
| |
| // Stop the playback clock |
| iPlaybackClock.Stop(); |
| uint32 starttime = 0; |
| bool overflow = 0; |
| iPlaybackClock.SetStartTime32(starttime, PVMF_MEDIA_CLOCK_MSEC, overflow); |
| iPlaybackDirection = 1; |
| |
| // Reset the begin/end time variables |
| iCurrentBeginPosition.iIndeterminate = true; |
| iCurrentEndPosition.iIndeterminate = true; |
| iQueuedBeginPosition.iIndeterminate = true; |
| iQueuedEndPosition.iIndeterminate = true; |
| |
| // Reset the paused-due-to-EOS flag |
| iPlaybackPausedDueToEndOfClip = false; |
| |
| // Reset the Presentation Info list |
| iSourcePresInfoList.Reset(); |
| |
| // Clear the Track selection List |
| iTrackSelectionList.clear(); |
| |
| // Stop the end time check |
| if (iEndTimeCheckEnabled) |
| { |
| iEndTimeCheckEnabled = false; |
| iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_ENDTIMECHECK); |
| } |
| |
| int32 leavecode = 0; |
| PVMFStatus status = PVMFSuccess; |
| |
| if (iSourceNode) |
| { |
| if (iSourceNode->GetState() != EPVMFNodeCreated) |
| { |
| PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, -1, NULL, -1); |
| |
| PVMFCommandId cmdid = -1; |
| leavecode = 0; |
| OSCL_TRY(leavecode, cmdid = iSourceNode->Reset(iSourceNodeSessionId, (OsclAny*)context)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoReset() Reset on iSourceNode did a leave!")); |
| FreeEngineContext(context); |
| OSCL_ASSERT(false); |
| return PVMFFailure); |
| } |
| else |
| { |
| // It is assumed that if SourceNode is in created state then datapaths if present, |
| // has to be in IDLE State |
| if (!iDatapathList.empty()) |
| { |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (!iDatapathList[i].iDatapath) |
| { |
| if (iDatapathList[i].iDatapath->iState != PVPDP_IDLE) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::DoReset() Source Node already in created state, Datapath not in idle state, asserting")); |
| OSCL_ASSERT(false); |
| } |
| } |
| } |
| DoRemoveAllSinks(); |
| } |
| if (iDataSource) |
| { |
| RemoveDataSourceSync(*iDataSource); |
| } |
| SetEngineState(PVP_ENGINE_STATE_IDLE); |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| } |
| } |
| else |
| { |
| if (iDataSource) |
| { |
| RemoveDataSourceSync(*iDataSource); |
| } |
| SetEngineState(PVP_ENGINE_STATE_IDLE); |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoReset() Out")); |
| return status; |
| } |
| |
| PVMFStatus PVPlayerEngine::RemoveDataSourceSync(PVPlayerDataSource &aSrc) |
| { |
| OSCL_UNUSED_ARG(aSrc); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::RemoveDataSourceSync() In")); |
| |
| // Destroy the source node if present |
| DoSourceNodeCleanup(); |
| |
| // Remove Stored KVP Values |
| DeleteKVPValues(); |
| |
| // Remove all metadata IF from the list |
| iMetadataIFList.clear(); |
| |
| iDataSource = NULL; |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::RemoveDataSourceSync() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoRemoveDataSource(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoRemoveDataSource() In")); |
| |
| if (GetPVPlayerState() != PVP_STATE_IDLE) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoRemoveDataSource() called when engine is not in the IDLE state")); |
| return PVMFErrInvalidState; |
| } |
| |
| if (iDataSource == NULL) // previously removed, e.g. during errorhandling |
| { |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| return PVMFSuccess; |
| } |
| |
| PVPlayerDataSource* src = (PVPlayerDataSource*)(aCmd.GetParam(0).pOsclAny_value); |
| |
| if (iDataSource != src || src == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoRemoveDataSource() Passed in parameter invalid")); |
| return PVMFErrArgument; |
| } |
| |
| PVMFStatus result = RemoveDataSourceSync(*src); |
| |
| if (result == PVMFSuccess) |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoRemoveDataSource() Out")); |
| return result; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoSourceUnderflowAutoPause(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceUnderflowAutoPause() In")); |
| |
| /* |
| * Underflow can happen in the following States |
| * Prepared - Use-cases where-in Source Node reports DataReady and goes into |
| * underflow immediately when it starts to retrieve data. |
| * Started - This will be the most generic use-case where in the source node |
| * is retreiving data and because of low bandwidth conditions runs out of data. |
| * In such case Source Node will send an Underflow event to Engine. |
| * Paused - A rare use-case but can happen. Use-case where Source Node is about |
| * to run out of data and just before Source Node sends an Underflow event to |
| * engine, user presses Pause on Engine. Engine gets Pause from user and Underflow |
| * from Source Node back-to-back. |
| */ |
| bool pauseSinkNodes = false; |
| |
| switch (iState) |
| { |
| case PVP_ENGINE_STATE_PREPARED: |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::DoSourceUnderflowAutoPause() in Prepared state")); |
| SetEngineState(PVP_ENGINE_STATE_AUTO_PAUSED); |
| break; |
| |
| case PVP_ENGINE_STATE_STARTED: |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::DoSourceUnderflowAutoPause() in Started state")); |
| pauseSinkNodes = true; |
| break; |
| |
| case PVP_ENGINE_STATE_PAUSED: |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::DoSourceUnderflowAutoPause() in Paused state")); |
| break; |
| |
| default: |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::DoSourceUnderflowAutoPause() Invalid state so cancel auto-pause request!")); |
| return PVMFErrCancelled; |
| } |
| |
| // Stop the watchdog timer if active. We will Start the timer again in auto-resume. |
| // this should only be done when engine is waiting for StartofData info event |
| // after reposition. |
| if (iNumPVMFInfoStartOfDataPending > 0) |
| { |
| if (iWatchDogTimer->IsBusy()) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::DoSourceUnderflowAutoPause - Pause after setplayback, Cancelling Watchdog timer, iNumPVMFInfoStartOfDataPending=%d", iNumPVMFInfoStartOfDataPending)); |
| iWatchDogTimer->Cancel(); |
| } |
| } |
| |
| if (!pauseSinkNodes) |
| { |
| // Sink nodes already in Paused state or have no data to process, so |
| // no need to call Pause on the sink nodes. |
| return PVMFErrNotSupported; |
| } |
| |
| // Pause the playback clock |
| iPlaybackClock.Pause(); |
| |
| uint32 i; |
| // Notify data sinks that clock has paused |
| for (i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath && iDatapathList[i].iSinkNodeSyncCtrlIF) |
| { |
| iDatapathList[i].iSinkNodeSyncCtrlIF->ClockStopped(); |
| } |
| } |
| |
| PVMFStatus retval = PVMFErrNotSupported; |
| |
| // Pause all active sink nodes |
| iNumPendingDatapathCmd = 0; |
| for (i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath) |
| { |
| retval = DoSinkNodePause(iDatapathList[i], aCmd.GetCmdId(), aCmd.GetContext()); |
| if (retval == PVMFSuccess) |
| { |
| ++iNumPendingDatapathCmd; |
| } |
| else |
| { |
| break; |
| } |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceUnderflowAutoPause() Out")); |
| if (iNumPendingDatapathCmd == 0) |
| { |
| return PVMFErrNotSupported; |
| } |
| else |
| { |
| SetEngineState(PVP_ENGINE_STATE_AUTO_PAUSING); |
| return retval; |
| } |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoSourceDataReadyAutoResume(PVPlayerEngineCommand& aCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceDataReadyAutoResume() In")); |
| |
| // Don't need to worry about transitional states(...ING). |
| // Auto-pause/resume cmds are just regular engine cmds and won't be interrupted by normal ones |
| |
| // Check if Datapaths (Sink Node) are already in Started state. |
| bool datapathSinkNodeStarted = false; |
| for (uint32 j = 0; j < iDatapathList.size(); j++) |
| { |
| if (iDatapathList[j].iSinkNode) |
| { |
| if (iDatapathList[j].iSinkNode->GetState() != EPVMFNodeStarted) |
| { |
| // One of the nodes is not in Started state break from the loop |
| // keeping the boolean datapathSinkNodeStaretd as false. |
| datapathSinkNodeStarted = false; |
| break; |
| } |
| // this will be true only when all Sink Nodes are in started state. |
| datapathSinkNodeStarted = true; |
| } |
| } |
| |
| // Next check to see if it is any one of the use-cases: |
| // Prepare->Underflow->Start->DataReady or |
| // Prepare->Underflow->DataReady->Start or |
| // Underflow->Pause->Resume->DataReady or |
| // Underflow->Pause->SetPlaybackRange->Resume->DataReady |
| // These are cases where Sink Nodes are already in Started state and |
| // engine might be still waiting for PVMFInfoStartOfData. |
| // Here if all PVMFInfoStartofData have not been received yet, |
| // then iNumPVMFInfoStartOfDataPending would be non-zero, |
| // In few of these usecase, engine starts playback clock in Resume, source nodes are sposed to pause the |
| // clock, since they are the ones in underflow. Once source nodes report dataready, engine would |
| // already be in STARTED state. So if the clock is still paused, then start it here. |
| // Here just send NotSupported so engine can send DataReady Event to the app. |
| // and set the watchdog timer which was cancelled when underflow was recieved. |
| if (datapathSinkNodeStarted) |
| { |
| if (iState == PVP_ENGINE_STATE_PREPARED) |
| { |
| // DataReady recieved during Prepare, Engine just needs to send |
| // DataReady event. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::DoSourceDataReadyAutoResume: DataReady rcvd, Engine in Prepared state")); |
| } |
| else if (iState == PVP_ENGINE_STATE_STARTED) |
| { |
| // Usecases for this scenario: |
| // Underflow->Pause->Resume->DataReady |
| // Underflow->Pause->SetPlaybackRange->Resume->DataReady |
| // Prepare->Underflow->Start->DataReady |
| // do nothing here |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::DoSourceDataReadyAutoResume: DataReady rcvd, Engine already in Started state")); |
| } |
| else if (iState == PVP_ENGINE_STATE_AUTO_PAUSED) |
| { |
| // Change state back to PREPARED, since Underflow and Dataready cancel each other out. |
| // Wait for Start command from App to Start the clock and change state to STARTED. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::DoSourceDataReadyAutoResume: DataReady rcvd in PVP_ENGINE_STATE_AUTO_PAUSED state. Set state back to PREPARED.")); |
| SetEngineState(PVP_ENGINE_STATE_PREPARED); |
| } |
| else |
| { |
| // This should never happen |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::DoSourceDataReadyAutoResume() Invalid state %d, Sinks in Started state", iState)); |
| OSCL_ASSERT(false); |
| } |
| |
| if (iNumPVMFInfoStartOfDataPending > 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::DoSourceDataReadyAutoResume: Clock in Stopped state, waiting for StartofData")); |
| |
| if (iWatchDogTimerInterval > 0) |
| { |
| if (iWatchDogTimer->IsBusy()) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::DoSourceDataReadyAutoResume - Pause after setplayback, Cancelling Watchdog timer, iNumPVMFInfoStartOfDataPending=%d", iNumPVMFInfoStartOfDataPending)); |
| iWatchDogTimer->Cancel(); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::DoSourceDataReadyAutoResume Setting WatchDogTimer for %d ms, iNumPVMFInfoStartOfDataPending=%d", |
| iWatchDogTimerInterval, iNumPVMFInfoStartOfDataPending)); |
| iWatchDogTimer->setTimerDuration(iWatchDogTimerInterval); |
| iWatchDogTimer->Start(); |
| } |
| } |
| else if ((iNumPVMFInfoStartOfDataPending == 0) && (iState == PVP_ENGINE_STATE_STARTED)) |
| { |
| StartPlaybackClock(); |
| |
| // Notify data sinks that clock has started |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath && iDatapathList[i].iSinkNodeSyncCtrlIF) |
| { |
| iDatapathList[i].iSinkNodeSyncCtrlIF->ClockStarted(); |
| } |
| } |
| } |
| //return PVMFErrNotSupported so the the DataReady can be sent, depending on iDataReadySent flag. |
| return PVMFErrNotSupported; |
| } |
| |
| // Next check to see if it is Underflow->Pause->DataReady->Resume usecase. |
| // Then we CANNOT start clock in here, because clock is paused by app. |
| // After Pause done, the engine is in PAUSED state. By allowing auto-resume only when |
| // auto-paused we deal with this usecase ok. |
| if (iState != PVP_ENGINE_STATE_AUTO_PAUSED) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceDataReadyAutoResume() Invalid state %d", iState)); |
| //return PVMFErrNotSupported so the the DataReady can be sent, depending on iDataReadySent flag. |
| return PVMFErrNotSupported; |
| } |
| |
| PVMFStatus retval = PVMFErrNotSupported; |
| |
| // Resume all active sink nodes |
| iNumPendingDatapathCmd = 0; |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath) |
| { |
| retval = DoSinkNodeResume(iDatapathList[i], aCmd.GetCmdId(), aCmd.GetContext()); |
| if (retval == PVMFSuccess) |
| { |
| ++iNumPendingDatapathCmd; |
| } |
| else |
| { |
| break; |
| } |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceDataReadyAutoResume() Out")); |
| if (iNumPendingDatapathCmd == 0) |
| { |
| return PVMFErrNotSupported; |
| } |
| else |
| { |
| SetEngineState(PVP_ENGINE_STATE_AUTO_RESUMING); |
| return retval; |
| } |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoSinkNodePause(PVPlayerEngineDatapath &aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodePause() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr())); |
| |
| if (!(aDatapath.iTrackInfo) || !(aDatapath.iSinkNode)) |
| { |
| return PVMFErrNotSupported; |
| } |
| |
| // Pause the sink node |
| PVPlayerEngineContext* context = AllocateEngineContext(&aDatapath, aDatapath.iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeAutoPause); |
| |
| PVMFCommandId cmdid = -1; |
| int32 leavecode = 0; |
| OSCL_TRY(leavecode, cmdid = aDatapath.iSinkNode->Pause(aDatapath.iSinkNodeSessionId, (OsclAny*)context)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodePause() Pause on sink node did a leave!")); |
| return PVMFFailure); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodePause() Out")); |
| |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoSinkNodeResume(PVPlayerEngineDatapath &aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeResume() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr())); |
| |
| if (!(aDatapath.iTrackInfo) || !(aDatapath.iSinkNode)) |
| { |
| return PVMFErrNotSupported; |
| } |
| |
| // Start the sink node to resume |
| PVPlayerEngineContext* context = AllocateEngineContext(&aDatapath, aDatapath.iSinkNode, NULL, aCmdId, aCmdContext, PVP_CMD_SinkNodeAutoResume); |
| |
| PVMFCommandId cmdid = -1; |
| int32 leavecode = 0; |
| OSCL_TRY(leavecode, cmdid = aDatapath.iSinkNode->Start(aDatapath.iSinkNodeSessionId, (OsclAny*)context)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| FreeEngineContext(context); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSinkNodeResume() Start on sink node did a leave!")); |
| return PVMFFailure); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeResume() Out")); |
| |
| return PVMFSuccess; |
| } |
| |
| void PVPlayerEngine::DoEngineDatapathTeardown(PVPlayerEngineDatapath& aDatapath) |
| { |
| if (aDatapath.iTrackInfo) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoEngineDatapathTeardown() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr())); |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoEngineDatapathTeardown() In")); |
| } |
| |
| if (aDatapath.iDatapath) |
| { |
| // Shutdown and reset the datapath |
| aDatapath.iDatapath->DisconnectNodeSession(); |
| aDatapath.iDatapath->SetSinkNode(NULL); |
| aDatapath.iDatapath->SetDecNode(NULL); |
| aDatapath.iDatapath->SetSourceNode(NULL); |
| } |
| |
| if (aDatapath.iSinkNode) |
| { |
| PVMFStatus status = PVMFFailure; |
| status = aDatapath.iSinkNode->Disconnect(aDatapath.iSinkNodeSessionId); |
| if (status == PVMFFailure) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoEngineDatapathTeardown() Disconnect on Sink Node Failed")); |
| OSCL_ASSERT(false); |
| } |
| status = aDatapath.iSinkNode->ThreadLogoff(); |
| if (status == PVMFFailure) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoEngineDatapathTeardown() Threadlogoff on SinkNode Failed")); |
| OSCL_ASSERT(false); |
| } |
| |
| // Remove sync ctrl IF if available |
| if (aDatapath.iSinkNodeSyncCtrlIF) |
| { |
| aDatapath.iSinkNodeSyncCtrlIF->SetClock(NULL); |
| aDatapath.iSinkNodeSyncCtrlIF->removeRef(); |
| aDatapath.iSinkNodeSyncCtrlIF = NULL; |
| } |
| |
| // Remove metadata IF if available |
| if (aDatapath.iSinkNodeMetadataExtIF) |
| { |
| RemoveFromMetadataInterfaceList(aDatapath.iSinkNodeMetadataExtIF, aDatapath.iSinkNodeSessionId); |
| aDatapath.iSinkNodeMetadataExtIF->removeRef(); |
| aDatapath.iSinkNodeMetadataExtIF = NULL; |
| } |
| |
| // Remove cap-config IF if available |
| if (aDatapath.iSinkNodeCapConfigIF) |
| { |
| aDatapath.iSinkNodeCapConfigIF = 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; |
| } |
| |
| PVMFStatus status = PVMFFailure; |
| status = aDatapath.iDecNode->Disconnect(aDatapath.iDecNodeSessionId); |
| if (status == PVMFFailure) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoEngineDatapathTeardown() Disconnect on dec node Failed")); |
| OSCL_ASSERT(false); |
| } |
| status = aDatapath.iDecNode->ThreadLogoff(); |
| if (status == PVMFFailure) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoEngineDatapathTeardown() ThreadLogoff on dec node Failed")); |
| OSCL_ASSERT(false); |
| } |
| |
| // search for matching uuid entry in list of instantiated nodes |
| PVPlayerEngineUuidNodeMapping* iter = iNodeUuids.begin(); |
| for (; iter != iNodeUuids.end(); ++iter) |
| if (iter->iNode == aDatapath.iDecNode) |
| break; |
| |
| if (iter != iNodeUuids.end()) |
| { |
| bool release_status = false; |
| |
| release_status = iPlayerNodeRegistry.ReleaseNode(iter->iUuid, aDatapath.iDecNode); |
| |
| if (release_status == false) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoEngineDatapathTeardown() Factory returned false while releasing the decnode")); |
| return; |
| } |
| |
| iNodeUuids.erase(iter); |
| aDatapath.iDecNode = NULL; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoEngineDatapathTeardown() decnode not found")); |
| return; |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoEngineDatapathTeardown() Out")); |
| } |
| |
| |
| void PVPlayerEngine::DoEngineDatapathCleanup(PVPlayerEngineDatapath& aDatapath) |
| { |
| if (aDatapath.iTrackInfo) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoEngineDatapathCleanup() In %s", aDatapath.iTrackInfo->getTrackMimeType().get_cstr())); |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoEngineDatapathCleanup() In")); |
| } |
| |
| DoEngineDatapathTeardown(aDatapath); |
| |
| // Destroy the datapath utility object instance |
| if (aDatapath.iDatapath) |
| { |
| OSCL_DELETE(aDatapath.iDatapath); |
| aDatapath.iDatapath = NULL; |
| } |
| |
| // Destroy the track info |
| if (aDatapath.iTrackInfo) |
| { |
| OSCL_DELETE(aDatapath.iTrackInfo); |
| aDatapath.iTrackInfo = NULL; |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoEngineDatapathCleanup() Out")); |
| } |
| |
| |
| void PVPlayerEngine::DoSourceNodeCleanup(void) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSourceNodeCleanup() In")); |
| |
| if (iSourceNode) |
| { |
| // Remove reference to the parser node init interface if available |
| if (iSourceNodeInitIF) |
| { |
| iSourceNodeInitIF->removeRef(); |
| iSourceNodeInitIF = NULL; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - iSourceNodeInitIF Released")); |
| } |
| |
| // Remove reference to the parser node track sel interface if available |
| if (iSourceNodeTrackSelIF) |
| { |
| iPlayableList.Reset(); |
| iPreferenceList.Reset(); |
| iSourceNodeTrackSelIF->removeRef(); |
| iSourceNodeTrackSelIF = NULL; |
| iTrackSelectionHelper = NULL; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - iSourceNodeTrackSelIF Released")); |
| } |
| |
| // Remove reference to the parser node track level info interface if available |
| if (iSourceNodeTrackLevelInfoIF) |
| { |
| iSourceNodeTrackLevelInfoIF->removeRef(); |
| iSourceNodeTrackLevelInfoIF = NULL; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - iSourceNodeTrackLevelInfoIF Released")); |
| } |
| |
| // Remove reference to the parser node position control interface if available |
| if (iSourceNodePBCtrlIF) |
| { |
| iSourceNodePBCtrlIF->removeRef(); |
| iSourceNodePBCtrlIF = NULL; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - iSourceNodePBCtrlIF Released")); |
| } |
| |
| // Remove reference to the parser node direction control interface if available |
| if (iSourceNodeDirCtrlIF) |
| { |
| iSourceNodeDirCtrlIF->removeRef(); |
| iSourceNodeDirCtrlIF = NULL; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - iSourceNodeDirCtrlIF Released")); |
| } |
| |
| // Remove reference to the parser node metadata interface if available |
| if (iSourceNodeMetadataExtIF) |
| { |
| RemoveFromMetadataInterfaceList(iSourceNodeMetadataExtIF, iSourceNodeSessionId); |
| iSourceNodeMetadataExtIF->removeRef(); |
| iSourceNodeMetadataExtIF = NULL; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - iSourceNodeMetadataExtIF Released")); |
| } |
| |
| // Reset the duration value retrieved from source |
| iSourceDurationAvailable = false; |
| iSourceDurationInMS = 0; |
| |
| // Remove reference to the parser node cap-config interface if available |
| if (iSourceNodeCapConfigIF) |
| { |
| iSourceNodeCapConfigIF->removeRef(); |
| iSourceNodeCapConfigIF = NULL; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - iSourceNodeCapConfigIF Released")); |
| } |
| |
| if (iSourceNodeCPMLicenseIF) |
| { |
| iSourceNodeCPMLicenseIF->removeRef(); |
| iSourceNodeCPMLicenseIF = NULL; |
| } |
| |
| // Reset the Presentation Info list |
| iSourcePresInfoList.Reset(); |
| |
| PVMFStatus status = PVMFFailure; |
| status = iSourceNode->Disconnect(iSourceNodeSessionId); |
| if (status == PVMFFailure) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeCleanup() Disconnect Failed")); |
| OSCL_ASSERT(false); |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - DisConnect Done")); |
| |
| status = iSourceNode->ThreadLogoff(); |
| if (status == PVMFFailure) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeCleanup() ThreadLogoff Failed")); |
| OSCL_ASSERT(false); |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - ThreadLogoff Done")); |
| |
| // search for matching uuid entry in list of instantiated nodes |
| PVPlayerEngineUuidNodeMapping* iter = iNodeUuids.begin(); |
| for (; iter != iNodeUuids.end(); ++iter) |
| if (iter->iNode == iSourceNode) |
| break; |
| |
| if (iter != iNodeUuids.end()) |
| { |
| bool release_status = false; |
| |
| release_status = iPlayerNodeRegistry.ReleaseNode(iter->iUuid, iSourceNode); |
| |
| if (release_status == false) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSourceNodeCleanup() Factory returned false while releasing the sourcenode")); |
| return; |
| } |
| |
| |
| iNodeUuids.erase(iter); |
| iSourceNode = NULL; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - iSourceNode Delete Done")); |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::DoSourceNodeCleanup() - iSourceNode not found")); |
| return; |
| } |
| } |
| |
| // Cleanup the control varibles related to rate & direction changes. |
| iPlaybackDirection_New = iPlaybackDirection; |
| iOutsideTimebase_New = iOutsideTimebase; |
| iPlaybackClockRate_New = iPlaybackClockRate; |
| iChangeDirectionNPT.iIndeterminate = true; |
| // Reset the flag that tracks pause-due-to-EOS |
| iPlaybackPausedDueToEndOfClip = false; |
| |
| 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 == PRODUCTINFO) |
| { |
| // "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 |
| { |
| PVMFStatus retval = PVMFFailure; |
| |
| // Go through each datapath's cap-config IF in the datapath list and check for the string. |
| for (uint32 i = 0; i < iDatapathList.size(); i++) |
| { |
| if (iDatapathList[i].iDecNodeCapConfigIF != NULL) |
| { |
| retval = iDatapathList[i].iDecNodeCapConfigIF->getParametersSync(NULL, aIdentifier, aParameters, aNumParamElements, aContext); |
| if (retval == PVMFSuccess) |
| { |
| // Key matched break the loop. |
| break; |
| } |
| } |
| |
| if (iDatapathList[i].iSinkNodeCapConfigIF != NULL) |
| { |
| retval = iDatapathList[i].iSinkNodeCapConfigIF->getParametersSync(NULL, aIdentifier, aParameters, aNumParamElements, aContext); |
| if (retval == PVMFSuccess) |
| { |
| // Key matched break the loop. |
| break; |
| } |
| } |
| } |
| |
| if (retval != PVMFSuccess) |
| { |
| return retval; |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::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); |
| } |
| // @TODO Add more types if engine starts returning more types |
| } |
| } |
| |
| // Player engine allocated its key strings in one chunk so just free the first key string ptr |
| oscl_free(aParameters[0].key); |
| |
| // Free memory for the parameter list |
| oscl_free(aParameters); |
| aParameters = NULL; |
| } |
| else |
| { |
| PVMFStatus retval = PVMFFailure; |
| |
| // Go through each datapath's cap-config IF in the datapath list and check for the string. |
| for (uint32 i = 0; i < iDatapathList.size(); i++) |
| { |
| if (iDatapathList[i].iDecNodeCapConfigIF != NULL) |
| { |
| retval = iDatapathList[i].iDecNodeCapConfigIF->releaseParameters(NULL, aParameters, aNumElements); |
| if (retval == PVMFSuccess) |
| { |
| // Key matched break the loop. |
| break; |
| } |
| } |
| |
| if (iDatapathList[i].iSinkNodeCapConfigIF != NULL) |
| { |
| retval = iDatapathList[i].iSinkNodeCapConfigIF->releaseParameters(NULL, aParameters, aNumElements); |
| if (retval == PVMFSuccess) |
| { |
| // Key matched break the loop. |
| break; |
| } |
| } |
| } |
| |
| if (retval != PVMFSuccess) |
| { |
| return retval; |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCapConfigReleaseParameters() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoCapConfigSetParameters(PVPlayerEngineCommand& aCmd, bool aSyncCmd) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCapConfigSetParameters() In")); |
| |
| PvmiKvp* paramkvp; |
| int32 numparam; |
| PvmiKvp** retkvp; |
| paramkvp = (PvmiKvp*)(aCmd.GetParam(0).pOsclAny_value); |
| numparam = aCmd.GetParam(1).int32_value; |
| retkvp = (PvmiKvp**)(aCmd.GetParam(2).pOsclAny_value); |
| |
| if (paramkvp == NULL || retkvp == NULL || numparam < 1) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigSetParameters() Passed in parameter invalid")); |
| return PVMFErrArgument; |
| } |
| |
| // Go through each parameter |
| for (int32 paramind = 0; paramind < numparam; ++paramind) |
| { |
| if (iRollOverState == RollOverStateIdle) |
| { |
| PVMFStatus ret = VerifyAndSaveKVPValues(¶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 |
| { |
| *retkvp = ¶mkvp[paramind]; |
| bool anysuccess = false; |
| |
| |
| if (iSourceNodeCapConfigIF != NULL) |
| { |
| *retkvp = NULL; |
| iSourceNodeCapConfigIF->setParametersSync(NULL, ¶mkvp[paramind], 1, *retkvp); |
| if (*retkvp == NULL) |
| { |
| anysuccess = true; |
| } |
| } |
| // Go through each datapath's cap-config IF in the datapath list and check for the string. |
| for (uint32 i = 0; i < iDatapathList.size(); i++) |
| { |
| if (iDatapathList[i].iDecNodeCapConfigIF != NULL) |
| { |
| *retkvp = NULL; |
| iDatapathList[i].iDecNodeCapConfigIF->setParametersSync(NULL, ¶mkvp[paramind], 1, *retkvp); |
| if (*retkvp == NULL) |
| { |
| anysuccess = true; |
| break; |
| } |
| } |
| |
| if (iDatapathList[i].iSinkNodeCapConfigIF != NULL) |
| { |
| *retkvp = NULL; |
| iDatapathList[i].iSinkNodeCapConfigIF->setParametersSync(NULL, ¶mkvp[paramind], 1, *retkvp); |
| if (*retkvp == NULL) |
| { |
| anysuccess = true; |
| break; |
| } |
| } |
| } |
| |
| if (anysuccess == false) |
| { |
| // setParametersSync was not accepted by the node(s) |
| *retkvp = ¶mkvp[paramind]; |
| return PVMFErrArgument; |
| } |
| } |
| |
| } |
| |
| if (!aSyncCmd) |
| { |
| EngineCommandCompleted(aCmd.GetCmdId(), aCmd.GetContext(), PVMFSuccess); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCapConfigSetParameters() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| PVMFStatus PVPlayerEngine::DoCapConfigVerifyParameters(PvmiKvp* aParameters, int aNumElements) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCapConfigVerifyParameters() In")); |
| |
| if (aParameters == NULL || aNumElements < 1) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigVerifyParameters() Passed in parameter invalid")); |
| return PVMFErrArgument; |
| } |
| |
| // Go through each parameter and verify |
| for (int32 paramind = 0; paramind < aNumElements; ++paramind) |
| { |
| // Count the number of components and parameters in the key |
| int compcount = pv_mime_string_compcnt(aParameters[paramind].key); |
| // Retrieve the first component from the key string |
| char* compstr = NULL; |
| pv_mime_string_extract_type(0, aParameters[paramind].key, compstr); |
| |
| if ((pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf")) < 0) || compcount < 2) |
| { |
| // First component should be "x-pvmf" and there must |
| // be at least two components to go past x-pvmf |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigVerifyParameters() Unsupported key")); |
| return PVMFErrArgument; |
| } |
| |
| // Retrieve the second component from the key string |
| pv_mime_string_extract_type(1, aParameters[paramind].key, compstr); |
| |
| // First check if it is key string for engine ("player") |
| if (pv_mime_strcmp(compstr, _STRLIT_CHAR("player")) >= 0) |
| { |
| if (compcount == 3) |
| { |
| // Verify the passed-in player setting |
| PVMFStatus retval = DoVerifyAndSetPlayerParameter(aParameters[paramind], false); |
| if (retval != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoCapConfigVerifyParameters() Verifying parameter %d failed", paramind)); |
| return retval; |
| } |
| } |
| else 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 |
| { |
| PVMFStatus retval = PVMFFailure; |
| |
| // Go through each datapath's cap-config IF in the datapath list and check for the string. |
| for (uint32 i = 0; i < iDatapathList.size(); i++) |
| { |
| if (iDatapathList[i].iDecNodeCapConfigIF != NULL) |
| { |
| retval = iDatapathList[i].iDecNodeCapConfigIF->verifyParametersSync(NULL, &aParameters[paramind], 1); |
| if (retval == PVMFSuccess) |
| { |
| // Key matched break the loop. |
| break; |
| } |
| } |
| |
| if (iDatapathList[i].iSinkNodeCapConfigIF != NULL) |
| { |
| retval = iDatapathList[i].iSinkNodeCapConfigIF->verifyParametersSync(NULL, &aParameters[paramind], 1); |
| if (retval == PVMFSuccess) |
| { |
| // Key matched break the loop. |
| break; |
| } |
| } |
| } |
| |
| if (retval != PVMFSuccess) |
| { |
| return retval; |
| } |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCapConfigVerifyParameters() Out")); |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVPlayerEngine::DoGetPlayerParameter(PvmiKvp*& aParameters, int& aNumParamElements, int32 aIndex, PvmiKvpAttr reqattr) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoGetPlayerParameter() In")); |
| |
| aNumParamElements = 0; |
| |
| // Allocate memory for the KVP |
| aParameters = (PvmiKvp*)oscl_malloc(sizeof(PvmiKvp)); |
| if (aParameters == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerParameter() Memory allocation for KVP failed")); |
| return PVMFErrNoMemory; |
| } |
| oscl_memset(aParameters, 0, sizeof(PvmiKvp)); |
| // Allocate memory for the key string in KVP |
| PvmiKeyType memblock = (PvmiKeyType)oscl_malloc(PVPLAYERCONFIG_KEYSTRING_SIZE * sizeof(char)); |
| if (memblock == NULL) |
| { |
| oscl_free(aParameters); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerParameter() Memory allocation for key string failed")); |
| return PVMFErrNoMemory; |
| } |
| oscl_strset(memblock, 0, PVPLAYERCONFIG_KEYSTRING_SIZE*sizeof(char)); |
| // Assign the key string buffer to KVP |
| aParameters[0].key = memblock; |
| |
| // Copy the key string |
| oscl_strncat(aParameters[0].key, _STRLIT_CHAR("x-pvmf/player/"), 14); |
| oscl_strncat(aParameters[0].key, PVPlayerConfigBaseKeys[aIndex].iString, oscl_strlen(PVPlayerConfigBaseKeys[aIndex].iString)); |
| oscl_strncat(aParameters[0].key, _STRLIT_CHAR(";type=value;valtype="), 20); |
| switch (PVPlayerConfigBaseKeys[aIndex].iValueType) |
| { |
| case PVMI_KVPVALTYPE_RANGE_INT32: |
| oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_RANGE_INT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_RANGE_INT32_STRING)); |
| break; |
| |
| case PVMI_KVPVALTYPE_KSV: |
| oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_KSV_STRING), oscl_strlen(PVMI_KVPVALTYPE_KSV_STRING)); |
| break; |
| |
| case PVMI_KVPVALTYPE_CHARPTR: |
| oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_CHARPTR_STRING), oscl_strlen(PVMI_KVPVALTYPE_CHARPTR_STRING)); |
| break; |
| |
| case PVMI_KVPVALTYPE_BOOL: |
| oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_BOOL_STRING), oscl_strlen(PVMI_KVPVALTYPE_BOOL_STRING)); |
| break; |
| |
| case PVMI_KVPVALTYPE_UINT32: |
| default: |
| if (reqattr == PVMI_KVPATTR_CAP) |
| { |
| oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_RANGE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_RANGE_UINT32_STRING)); |
| } |
| else |
| { |
| oscl_strncat(aParameters[0].key, _STRLIT_CHAR(PVMI_KVPVALTYPE_UINT32_STRING), oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING)); |
| } |
| break; |
| } |
| aParameters[0].key[PVPLAYERCONFIG_KEYSTRING_SIZE-1] = 0; |
| |
| // Copy the requested info |
| switch (aIndex) |
| { |
| case PBPOS_UNITS: // "pbpops_units" |
| if (reqattr == PVMI_KVPATTR_CUR) |
| { |
| // Return current value |
| // Allocate memory for the string |
| char* curstr = (char*)oscl_malloc(32 * sizeof(char)); |
| if (curstr == NULL) |
| { |
| oscl_free(aParameters[0].key); |
| oscl_free(aParameters); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerParameter() Memory allocation for char* string failed")); |
| return PVMFErrNoMemory; |
| } |
| oscl_strset(curstr, 0, 32); |
| // Copy the appropriate string based on units being used |
| switch (iPBPosStatusUnit) |
| { |
| case PVPPBPOSUNIT_SEC: |
| oscl_strncpy(curstr, _STRLIT_CHAR("PVPPBPOSUNIT_SEC"), 16); |
| aParameters[0].length = 16; |
| break; |
| |
| case PVPPBPOSUNIT_MIN: |
| oscl_strncpy(curstr, _STRLIT_CHAR("PVPPBPOSUNIT_MIN"), 16); |
| aParameters[0].length = 16; |
| break; |
| |
| case PVPPBPOSUNIT_MILLISEC: |
| default: |
| oscl_strncpy(curstr, _STRLIT_CHAR("PVPPBPOSUNIT_MILLISEC"), 21); |
| aParameters[0].length = 21; |
| break; |
| } |
| |
| aParameters[0].value.pChar_value = curstr; |
| aParameters[0].capacity = 32; |
| } |
| else if (reqattr == PVMI_KVPATTR_DEF) |
| { |
| // Return default |
| // Allocate memory for the string |
| int32 defstrlen = oscl_strlen(PVPLAYERENGINE_CONFIG_PBPOSSTATUSUNIT_DEF_STRING); |
| char* defstr = (char*)oscl_malloc((defstrlen + 1) * sizeof(char)); |
| if (defstr == NULL) |
| { |
| oscl_free(aParameters[0].key); |
| oscl_free(aParameters); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerParameter() Memory allocation for char* string failed")); |
| return PVMFErrNoMemory; |
| } |
| // Copy and set |
| oscl_strncpy(defstr, _STRLIT_CHAR(PVPLAYERENGINE_CONFIG_PBPOSSTATUSUNIT_DEF_STRING), defstrlen); |
| defstr[defstrlen] = 0; |
| aParameters[0].value.pChar_value = defstr; |
| aParameters[0].capacity = defstrlen + 1; |
| aParameters[0].length = defstrlen; |
| } |
| else |
| { |
| // Return capability |
| // Allocate memory for the string |
| int32 capstrlen = oscl_strlen(PVPLAYERENGINE_CONFIG_PBPOSSTATUSINTERVAL_CAP_STRING); |
| char* capstr = (char*)oscl_malloc((capstrlen + 1) * sizeof(char)); |
| if (capstr == NULL) |
| { |
| oscl_free(aParameters[0].key); |
| oscl_free(aParameters); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerParameter() Memory allocation for char* string failed")); |
| return PVMFErrNoMemory; |
| } |
| // Copy and set |
| oscl_strncpy(capstr, _STRLIT_CHAR(PVPLAYERENGINE_CONFIG_PBPOSSTATUSINTERVAL_CAP_STRING), capstrlen); |
| capstr[capstrlen] = 0; |
| aParameters[0].value.pChar_value = capstr; |
| aParameters[0].capacity = capstrlen + 1; |
| aParameters[0].length = capstrlen; |
| } |
| break; |
| |
| case PBPOS_INTERVAL: // "pbpos_interval" |
| if (reqattr == PVMI_KVPATTR_CUR) |
| { |
| // Return current value |
| aParameters[0].value.uint32_value = iPBPosStatusInterval; |
| } |
| else if (reqattr == PVMI_KVPATTR_DEF) |
| { |
| // Return default |
| aParameters[0].value.uint32_value = PVPLAYERENGINE_CONFIG_PBPOSSTATUSINTERVAL_DEF; |
| } |
| else |
| { |
| // Return capability |
| range_uint32* rui32 = (range_uint32*)oscl_malloc(sizeof(range_uint32)); |
| if (rui32 == NULL) |
| { |
| oscl_free(aParameters[0].key); |
| oscl_free(aParameters); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerParameter() Memory allocation for range uint32 failed")); |
| return PVMFErrNoMemory; |
| } |
| rui32->min = PVPLAYERENGINE_CONFIG_PBPOSSTATUSINTERVAL_MIN; |
| rui32->max = PVPLAYERENGINE_CONFIG_PBPOSSTATUSINTERVAL_MAX; |
| aParameters[0].value.key_specific_value = (void*)rui32; |
| } |
| break; |
| |
| case ENDTIMECHECK_INTERVAL: // "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 SEEKTOSYNCPOINT: // "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 SKIPTOREQUESTEDPOSITION: // "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 SYNCPOINTSEEKWINDOW: // "syncpointseekwindow" |
| if (reqattr == PVMI_KVPATTR_CUR) |
| { |
| // Return current value |
| aParameters[0].value.uint32_value = iSyncPointSeekWindow; |
| } |
| else if (reqattr == PVMI_KVPATTR_DEF) |
| { |
| // Return default |
| aParameters[0].value.uint32_value = PVPLAYERENGINE_CONFIG_SEEKTOSYNCPOINTWINDOW_DEF; |
| } |
| else |
| { |
| // Return capability |
| range_uint32* rui32 = (range_uint32*)oscl_malloc(sizeof(range_uint32)); |
| if (rui32 == NULL) |
| { |
| oscl_free(aParameters[0].key); |
| oscl_free(aParameters); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerParameter() Memory allocation for range uint32 failed")); |
| return PVMFErrNoMemory; |
| } |
| rui32->min = PVPLAYERENGINE_CONFIG_SEEKTOSYNCPOINTWINDOW_MIN; |
| rui32->max = PVPLAYERENGINE_CONFIG_SEEKTOSYNCPOINTWINDOW_MAX; |
| aParameters[0].value.key_specific_value = (void*)rui32; |
| } |
| break; |
| |
| case SYNCMARGIN_VIDEO: // "syncmargin_video" |
| case SYNCMARGIN_AUDIO: // "syncmargin_audio" |
| case SYNCMARGIN_TEXT: // "syncmargin_text" |
| { |
| range_int32* ri32 = (range_int32*)oscl_malloc(sizeof(range_int32)); |
| if (ri32 == NULL) |
| { |
| oscl_free(aParameters[0].key); |
| oscl_free(aParameters); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoGetPlayerParameter() Memory allocation for range int32 failed")); |
| return PVMFErrNoMemory; |
| } |
| |
| if (reqattr == PVMI_KVPATTR_CUR) |
| { |
| // Return current value |
| if (aIndex == SYNCMARGIN_VIDEO) |
| { |
| // Video |
| ri32->min = iSyncMarginVideo.min; |
| ri32->max = iSyncMarginVideo.max; |
| } |
| else if (aIndex == SYNCMARGIN_AUDIO) |
| { |
| // Audio |
| ri32->min = iSyncMarginAudio.min; |
| ri32->max = iSyncMarginAudio.max; |
| } |
| else |
| { |
| // Text |
| ri32->min = iSyncMarginText.min; |
| ri32->max = iSyncMarginText.max; |
| } |
| aParameters[0].value.key_specific_value = (void*)ri32; |
| } |
| else if (reqattr == PVMI_KVPATTR_DEF) |
| { |
| // Return default |
| ri32->min = PVPLAYERENGINE_CONFIG_SYNCMARGIN_EARLY_DEF; |
| ri32->max = PVPLAYERENGINE_CONFIG_SYNCMARGIN_LATE_DEF; |
| aParameters[0].value.key_specific_value = (void*)ri32; |
| } |
| else |
| { |
| // Return capability |
| ri32->min = PVPLAYERENGINE_CONFIG_SYNCMARGIN_MIN; |
| ri32->max = PVPLAYERENGINE_CONFIG_SYNCMARGIN_MAX; |
| aParameters[0].value.key_specific_value = (void*)ri32; |
| } |
| } |
| break; |
| |
| case NODECMD_TIMEOUT: // "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 NODEDATAQUEIUING_TIMEOUT: // "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 PBPOS_ENABLE: // "pbpos_enable" |
| if (reqattr == PVMI_KVPATTR_CUR) |
| { |
| // Return current value |
| aParameters[0].value.bool_value = iPBPosEnable; |
| } |
| else if (reqattr == PVMI_KVPATTR_DEF) |
| { |
| // Return default |
| aParameters[0].value.bool_value = true; |
| } |
| else |
| { |
| // Return capability |
| // Bool so no capability |
| } |
| break; |
| 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 PRODUCTNAME: // "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 PARTNUMBER: // "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 HARDWAREPLATFORM: // "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 SOFTWAREPLATFORM: // "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 DEVICE: // "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 == PRODUCTINFO) |
| { |
| // 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 PBPOS_UNITS: // "pbpos_units" |
| { |
| // Validate |
| if (aParameter.value.pChar_value == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() char* string for pbpos_units is NULL")); |
| return PVMFErrArgument; |
| } |
| |
| // Check the specified unit |
| // Use sample number as the invalid default since it is not allowed |
| PVPPlaybackPositionUnit newposunit = PVPPBPOSUNIT_UNKNOWN; |
| if (oscl_strncmp(aParameter.value.pChar_value, _STRLIT_CHAR("PVPPBPOSUNIT_SEC"), 16) == 0) |
| { |
| newposunit = PVPPBPOSUNIT_SEC; |
| } |
| else if (oscl_strncmp(aParameter.value.pChar_value, _STRLIT_CHAR("PVPPBPOSUNIT_MIN"), 16) == 0) |
| { |
| newposunit = PVPPBPOSUNIT_MIN; |
| } |
| else if (oscl_strncmp(aParameter.value.pChar_value, _STRLIT_CHAR("PVPPBPOSUNIT_MILLISEC"), 21) == 0) |
| { |
| newposunit = PVPPBPOSUNIT_MILLISEC; |
| } |
| |
| if (newposunit == PVPPBPOSUNIT_UNKNOWN) |
| { |
| // Couldn't determine the new units |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() Invalid units for pbpos_units")); |
| return PVMFErrArgument; |
| } |
| // Change the config if to set |
| if (aSetParam) |
| { |
| iPBPosStatusUnit = newposunit; |
| } |
| } |
| break; |
| |
| case PBPOS_INTERVAL: // "pbpos_interval" |
| // Check if within range |
| if (aParameter.value.uint32_value < PVPLAYERENGINE_CONFIG_PBPOSSTATUSINTERVAL_MIN || |
| aParameter.value.uint32_value > PVPLAYERENGINE_CONFIG_PBPOSSTATUSINTERVAL_MAX) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() Invalid value for pbpos_interval")); |
| return PVMFErrArgument; |
| } |
| // Change the config if to set |
| if (aSetParam) |
| { |
| iPBPosStatusInterval = aParameter.value.uint32_value; |
| } |
| break; |
| |
| case ENDTIMECHECK_INTERVAL: // "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 SEEKTOSYNCPOINT: // "seektosyncpoint" |
| // Nothing to validate since it is boolean |
| // Change the config if to set |
| if (aSetParam) |
| { |
| iSeekToSyncPoint = aParameter.value.bool_value; |
| } |
| break; |
| |
| case SKIPTOREQUESTEDPOSITION: // "skiptorequestedpos" |
| // Nothing to validate since it is boolean |
| // Change the config if to set |
| if (aSetParam) |
| { |
| iSkipToRequestedPosition = aParameter.value.bool_value; |
| } |
| break; |
| |
| case SYNCPOINTSEEKWINDOW: // "syncpointseekwindow" |
| // Check if within range |
| if (aParameter.value.uint32_value > PVPLAYERENGINE_CONFIG_SEEKTOSYNCPOINTWINDOW_MAX) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() Invalid value for syncpointseekwindow")); |
| return PVMFErrArgument; |
| } |
| // Change the config if to set |
| if (aSetParam) |
| { |
| iSyncPointSeekWindow = aParameter.value.uint32_value; |
| } |
| break; |
| |
| case SYNCMARGIN_VIDEO: // "syncmargin_video" |
| case SYNCMARGIN_AUDIO: // "syncmargin_audio" |
| case SYNCMARGIN_TEXT: // "syncmargin_text" |
| { |
| range_int32* ri32 = (range_int32*)aParameter.value.key_specific_value; |
| if (ri32 == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() ksv for syncmargin is NULL")); |
| return PVMFErrArgument; |
| } |
| |
| // Check if within range |
| if (ri32->min < PVPLAYERENGINE_CONFIG_SYNCMARGIN_MIN || |
| ri32->min > PVPLAYERENGINE_CONFIG_SYNCMARGIN_MAX || |
| ri32->max < PVPLAYERENGINE_CONFIG_SYNCMARGIN_MIN || |
| ri32->max > PVPLAYERENGINE_CONFIG_SYNCMARGIN_MAX) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() Invalid range for syncmargin")); |
| return PVMFErrArgument; |
| } |
| |
| // Change the config if to set |
| if (aSetParam) |
| { |
| return DoSetConfigSyncMargin(ri32->min, ri32->max, engcomp3ind - 7); |
| } |
| } |
| break; |
| |
| case NODECMD_TIMEOUT: // "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 NODEDATAQUEIUING_TIMEOUT: // "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 PBPOS_ENABLE: // "pbpos_enable" |
| // Nothing to validate since it is boolean |
| // Change the config if to set |
| if (aSetParam) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVPlayerEngine::DoVerifyAndSetPlayerParameter() pbpos_enable set to %d", iPBPosEnable)); |
| bool prevPBPosEnable = iPBPosEnable; |
| iPBPosEnable = aParameter.value.bool_value; |
| if (prevPBPosEnable && !(aParameter.value.bool_value)) |
| { |
| // Stop playback position reporting |
| StopPlaybackStatusTimer(); |
| } |
| else if (!prevPBPosEnable && (aParameter.value.bool_value)) |
| { |
| // Start playback position reporting only when playback clock is running |
| if (iPlaybackClock.GetState() == PVMFMediaClock::RUNNING) |
| { |
| StartPlaybackStatusTimer(); |
| } |
| } |
| |
| } |
| break; |
| |
| 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 PRODUCTNAME: // "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 PARTNUMBER: // "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 HARDWAREPLATFORM: // "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 SOFTWAREPLATFORM: // "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 DEVICE: // "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 (FindDatapathForTrackUsingMimeString(true, false, false, vdpind) == true) |
| { |
| PVPlayerEngineDatapath* pvpedp = &(iDatapathList[vdpind]); |
| if (pvpedp->iDatapath) |
| { |
| if (pvpedp->iSinkNodeSyncCtrlIF) |
| { |
| pvpedp->iSinkNodeSyncCtrlIF->SetMargins((-1*iSyncMarginVideo.min), iSyncMarginVideo.max); |
| } |
| } |
| } |
| } |
| else if (aMediaType == 1) |
| { |
| // Audio |
| iSyncMarginAudio.min = aEarlyMargin; |
| iSyncMarginAudio.max = aLateMargin; |
| |
| // Find the audio datapath in the list |
| int32 adpind = -1; |
| if (FindDatapathForTrackUsingMimeString(false, true, false, adpind) == true) |
| { |
| PVPlayerEngineDatapath* pvpedp = &(iDatapathList[adpind]); |
| if (pvpedp->iDatapath) |
| { |
| if (pvpedp->iSinkNodeSyncCtrlIF) |
| { |
| pvpedp->iSinkNodeSyncCtrlIF->SetMargins((-1*iSyncMarginAudio.min), iSyncMarginAudio.max); |
| } |
| } |
| } |
| } |
| else if (aMediaType == 2) |
| { |
| // Text |
| iSyncMarginText.min = aEarlyMargin; |
| iSyncMarginText.max = aLateMargin; |
| |
| // Find the text datapath in the list |
| int32 tdpind = -1; |
| if (FindDatapathForTrackUsingMimeString(false, false, true, tdpind) == true) |
| { |
| PVPlayerEngineDatapath* pvpedp = &(iDatapathList[tdpind]); |
| if (pvpedp->iDatapath) |
| { |
| if (pvpedp->iSinkNodeSyncCtrlIF) |
| { |
| pvpedp->iSinkNodeSyncCtrlIF->SetMargins((-1*iSyncMarginText.min), iSyncMarginText.max); |
| } |
| } |
| } |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoSetConfigSyncMargin() Invalid media type index")); |
| return PVMFErrArgument; |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSetConfigSyncMargin() Out")); |
| return PVMFSuccess; |
| } |
| |
| |
| PVPlayerEngineContext* PVPlayerEngine::AllocateEngineContext(PVPlayerEngineDatapath* aEngineDatapath, PVMFNodeInterface* aNode, PVPlayerDatapath* aDatapath, PVCommandId aCmdId, OsclAny* aCmdContext, int32 aCmdType) |
| { |
| // Allocate memory for the context from the fixed size memory pool |
| PVPlayerEngineContext* context = NULL; |
| int32 leavecode = 0; |
| OSCL_TRY(leavecode, context = (PVPlayerEngineContext*)(iCurrentContextListMemPool.allocate(sizeof(PVPlayerEngineContext)))); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::AllocateEngineContext() allocate on iCurrentContextListMemPool did a leave!")); |
| OSCL_ASSERT(false)); |
| |
| OSCL_ASSERT(context); |
| |
| // Set the context info |
| context->iEngineDatapath = aEngineDatapath; |
| context->iNode = aNode; |
| context->iDatapath = aDatapath; |
| context->iCmdId = aCmdId; |
| context->iCmdContext = aCmdContext; |
| context->iCmdType = aCmdType; |
| |
| // Save the context in the list |
| leavecode = 0; |
| OSCL_TRY(leavecode, iCurrentContextList.push_back(context)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::AllocateEngineContext() Push back on the context list did a leave!")); |
| iCurrentContextListMemPool.deallocate((OsclAny*)context); |
| OSCL_ASSERT(false); |
| return NULL;); |
| |
| return context; |
| } |
| |
| |
| void PVPlayerEngine::FreeEngineContext(PVPlayerEngineContext* aContext) |
| { |
| OSCL_ASSERT(aContext); |
| |
| // Remove the context from the list |
| uint32 i = 0; |
| bool foundcontext = false; |
| for (i = 0; i < iCurrentContextList.size(); ++i) |
| { |
| if (iCurrentContextList[i] == aContext) |
| { |
| foundcontext = true; |
| break; |
| } |
| } |
| |
| if (foundcontext) |
| { |
| iCurrentContextList.erase(iCurrentContextList.begin() + i); |
| // Free the memory used by context in the memory pool |
| iCurrentContextListMemPool.deallocate((OsclAny*)aContext); |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::FreeEngineContext() Context not on current list (0x%x). CmdType %d", aContext, aContext->iCmdType)); |
| OSCL_ASSERT(false); |
| // Don't return to memory pool since it could add multiple entries |
| // of same address in free list |
| } |
| } |
| |
| |
| void PVPlayerEngine::HandleSourceNodeQueryInitIF(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::HandleSourceNodeQueryInitIF() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryInitIF() In")); |
| |
| PVMFStatus cmdstatus; |
| bool rescheduleAO = false; |
| |
| switch (aNodeResp.GetCmdStatus()) |
| { |
| case PVMFSuccess: |
| if (iSourceNodePVInterfaceInit) |
| { |
| iSourceNodeInitIF = (PVMFDataSourceInitializationExtensionInterface*)iSourceNodePVInterfaceInit; |
| iSourceNodePVInterfaceInit = NULL; |
| } |
| // Query for track selection interface |
| cmdstatus = DoSourceNodeQueryTrackSelIF(aNodeContext.iCmdId, aNodeContext.iCmdContext); |
| if (cmdstatus != PVMFSuccess) |
| { |
| if ((CheckForSourceRollOver() == true) && (iRollOverState == RollOverStateInProgress)) |
| { |
| iRollOverState = RollOverStateStart; |
| rescheduleAO = true; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeQueryInitIF() DoSourceNodeQueryTrackSelIF failed, Add EH command")); |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| if (iRollOverState == RollOverStateInProgress) |
| { |
| // Init is the current ongoing cmd so queue Init EH cmd |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_INIT, NULL, NULL, NULL, false); |
| } |
| else |
| { |
| // AddDataSource cmd is Current Command, queue ADS EH cmd |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_ADD_DATA_SOURCE, NULL, NULL, NULL, false); |
| } |
| iRollOverState = RollOverStateIdle; |
| } |
| } |
| break; |
| |
| default: |
| { |
| iSourceNodePVInterfaceInit = NULL; |
| iSourceNodeInitIF = NULL; |
| |
| if ((CheckForSourceRollOver() == true) && (iRollOverState == RollOverStateInProgress)) |
| { |
| iRollOverState = RollOverStateStart; |
| rescheduleAO = true; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeQueryInitIF() failed, Add EH command")); |
| cmdstatus = aNodeResp.GetCmdStatus(); |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aNodeResp.GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface())); |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceInit, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| if (iRollOverState == RollOverStateInProgress) |
| { |
| // Init is the current ongoing cmd so queue Init EH cmd |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_INIT, NULL, NULL, NULL, false); |
| } |
| else |
| { |
| // AddDataSource cmd is Current Command, queue ADS EH cmd |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_ADD_DATA_SOURCE, NULL, NULL, NULL, false); |
| } |
| iRollOverState = RollOverStateIdle; |
| } |
| } |
| break; |
| } |
| if (rescheduleAO) |
| { |
| if (IsBusy()) |
| { |
| Cancel(); |
| } |
| |
| RunIfNotReady(); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryInitIF() Out")); |
| } |
| |
| |
| void PVPlayerEngine::HandleSourceNodeQueryTrackSelIF(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::HandleSourceNodeQueryTrackSelIF() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryTrackSelIF() In")); |
| |
| PVMFStatus cmdstatus; |
| bool rescheduleAO = false; |
| |
| switch (aNodeResp.GetCmdStatus()) |
| { |
| case PVMFSuccess: |
| if (iSourceNodePVInterfaceTrackSel) |
| { |
| iSourceNodeTrackSelIF = (PVMFTrackSelectionExtensionInterface*)iSourceNodePVInterfaceTrackSel; |
| iSourceNodePVInterfaceTrackSel = NULL; |
| } |
| // Query the source node for optional extension IFs |
| cmdstatus = DoSourceNodeQueryInterfaceOptional(aNodeContext.iCmdId, aNodeContext.iCmdContext); |
| if (cmdstatus != PVMFSuccess) |
| { |
| // If optional extension IFs are not available, just complete the AddDataSource command as success |
| if ((CheckForSourceRollOver() == true) && (iRollOverState == RollOverStateInProgress)) |
| { |
| iRollOverState = RollOverStateStart; |
| rescheduleAO = true; |
| } |
| else |
| { |
| iRollOverState = RollOverStateIdle; |
| EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess); |
| } |
| } |
| break; |
| |
| default: |
| { |
| iSourceNodePVInterfaceTrackSel = NULL; |
| iSourceNodeTrackSelIF = NULL; |
| |
| if ((CheckForSourceRollOver() == true) && (iRollOverState == RollOverStateInProgress)) |
| { |
| iRollOverState = RollOverStateStart; |
| rescheduleAO = true; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeQueryTrackSelIF() failed, Add EH Command")); |
| cmdstatus = aNodeResp.GetCmdStatus(); |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aNodeResp.GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface())); |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceInit, puuid, nextmsg)); |
| |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| if (iRollOverState == RollOverStateInProgress) |
| { |
| // Init is the current ongoing cmd so queue Init EH cmd |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_INIT, NULL, NULL, NULL, false); |
| } |
| else |
| { |
| // AddDataSource cmd is Current Command, queue ADS EH cmd |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_ADD_DATA_SOURCE, NULL, NULL, NULL, false); |
| } |
| iRollOverState = RollOverStateIdle; |
| } |
| } |
| break; |
| } |
| if (rescheduleAO) |
| { |
| if (IsBusy()) |
| { |
| Cancel(); |
| } |
| |
| RunIfNotReady(); |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryTrackSelIF() Out")); |
| } |
| |
| |
| void PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() In")); |
| |
| // Determine QueryInterface() for which interface completed |
| if (aNodeContext.iCmdType == PVP_CMD_SourceNodeQueryTrackLevelInfoIF) |
| { |
| if ((aNodeResp.GetCmdStatus() == PVMFSuccess) && iSourceNodePVInterfaceTrackLevelInfo) |
| { |
| iSourceNodeTrackLevelInfoIF = (PVMFTrackLevelInfoExtensionInterface*)iSourceNodePVInterfaceTrackLevelInfo; |
| iSourceNodePVInterfaceTrackLevelInfo = NULL; |
| } |
| else |
| { |
| // Track level info IF is not available in this data source |
| iSourceNodePVInterfaceTrackLevelInfo = NULL; |
| iSourceNodeTrackLevelInfoIF = NULL; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() Track level info IF not available")); |
| } |
| } |
| else if (aNodeContext.iCmdType == PVP_CMD_SourceNodeQueryPBCtrlIF) |
| { |
| if ((aNodeResp.GetCmdStatus() == PVMFSuccess) && iSourceNodePVInterfacePBCtrl) |
| { |
| iSourceNodePBCtrlIF = (PvmfDataSourcePlaybackControlInterface*)iSourceNodePVInterfacePBCtrl; |
| iSourceNodePVInterfacePBCtrl = NULL; |
| } |
| else |
| { |
| // Playback control is not available in this data source |
| iSourceNodePVInterfacePBCtrl = NULL; |
| iSourceNodePBCtrlIF = NULL; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() Position control IF not available")); |
| } |
| } |
| else if (aNodeContext.iCmdType == PVP_CMD_SourceNodeQueryDirCtrlIF) |
| { |
| if ((aNodeResp.GetCmdStatus() == PVMFSuccess) && iSourceNodePVInterfaceDirCtrl) |
| { |
| iSourceNodeDirCtrlIF = (PvmfDataSourceDirectionControlInterface*)iSourceNodePVInterfaceDirCtrl; |
| iSourceNodePVInterfaceDirCtrl = NULL; |
| } |
| else |
| { |
| // Direction control is not available in this data source |
| iSourceNodePVInterfaceDirCtrl = NULL; |
| iSourceNodeDirCtrlIF = NULL; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() Direction control IF not available")); |
| } |
| } |
| else if (aNodeContext.iCmdType == PVP_CMD_SourceNodeQueryMetadataIF) |
| { |
| if ((aNodeResp.GetCmdStatus() == PVMFSuccess) && iSourceNodePVInterfaceMetadataExt) |
| { |
| iSourceNodeMetadataExtIF = (PVMFMetadataExtensionInterface*)iSourceNodePVInterfaceMetadataExt; |
| iSourceNodePVInterfaceMetadataExt = NULL; |
| |
| // Add the parser node's metadata extension IF to the list |
| if (AddToMetadataInterfaceList(iSourceNodeMetadataExtIF, iSourceNodeSessionId, NULL, iSourceNode) != PVMFSuccess) |
| { |
| iSourceNodeMetadataExtIF->removeRef(); |
| iSourceNodeMetadataExtIF = NULL; |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() Metadata IF could not be added to list")); |
| } |
| } |
| else |
| { |
| // Metadata is not available in this data source |
| iSourceNodePVInterfaceMetadataExt = NULL; |
| iSourceNodeMetadataExtIF = NULL; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() Metadata IF not available")); |
| } |
| } |
| else if (aNodeContext.iCmdType == PVP_CMD_SourceNodeQueryCapConfigIF) |
| { |
| if ((aNodeResp.GetCmdStatus() == PVMFSuccess) && iSourceNodePVInterfaceCapConfig) |
| { |
| iSourceNodeCapConfigIF = (PvmiCapabilityAndConfig*)iSourceNodePVInterfaceCapConfig; |
| iSourceNodePVInterfaceCapConfig = NULL; |
| } |
| else |
| { |
| // Cap-config is not available in this data source |
| iSourceNodePVInterfaceCapConfig = NULL; |
| iSourceNodeCapConfigIF = NULL; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() Cap-Config IF not available")); |
| } |
| } |
| else if (aNodeContext.iCmdType == PVP_CMD_SourceNodeQueryCPMLicenseIF) |
| { |
| if ((aNodeResp.GetCmdStatus() == PVMFSuccess) && iSourceNodePVInterfaceCPMLicense) |
| { |
| iSourceNodeCPMLicenseIF = (PVMFCPMPluginLicenseInterface*)iSourceNodePVInterfaceCPMLicense; |
| iSourceNodePVInterfaceCPMLicense = NULL; |
| } |
| else |
| { |
| //CPM License is not available in this data source |
| iSourceNodePVInterfaceCPMLicense = NULL; |
| 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) && iSourceNodePVInterfaceRegInit) |
| { |
| iSourceNodeRegInitIF = (PVMFDataSourceNodeRegistryInitInterface*)iSourceNodePVInterfaceRegInit; |
| iSourceNodePVInterfaceRegInit = NULL; |
| |
| // Set source node regsitry |
| iSourceNodeRegInitIF->SetPlayerNodeRegistry(&iPlayerNodeRegistry); |
| } |
| else |
| { |
| //Node Registry Init Extension Interface is not available in this data source |
| iSourceNodePVInterfaceRegInit = NULL; |
| iSourceNodeRegInitIF = NULL; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() Src Node Registry Init IF not available")); |
| } |
| } |
| |
| // Decrement the pending counter and complete the AddDataSource command if 0. |
| --iNumPendingNodeCmd; |
| if (iNumPendingNodeCmd == 0) |
| { |
| if (iRollOverState == RollOverStateInProgress) |
| { |
| SetRollOverKVPValues(); |
| PVMFStatus retval = DoSourceNodeInit(aNodeContext.iCmdId, aNodeContext.iCmdContext); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() - Source Roll Over In Progress - Doing Source Node Init")); |
| |
| if (retval == PVMFSuccess) |
| { |
| SetEngineState(PVP_ENGINE_STATE_INITIALIZING); |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() - Source Roll Over In Progress - DoSourceNodeInit Failed")); |
| if ((CheckForSourceRollOver() == true) && (iRollOverState == RollOverStateInProgress)) |
| { |
| iRollOverState = RollOverStateStart; |
| RunIfNotReady(); |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() DoSourceNodeInit failed, Add EH Command")); |
| iRollOverState = RollOverStateIdle; |
| iCommandCompleteStatusInErrorHandling = retval; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_INIT, NULL, NULL, NULL, false); |
| } |
| } |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() All QueryInterface() commands complete so AddDataSource is complete")); |
| EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess); |
| } |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() %d QueryInterface() commands are still pending", iNumPendingNodeCmd)); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryInterfaceOptional() Out")); |
| } |
| |
| void PVPlayerEngine::HandleSourceNodeInit(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleSourceNodeInit() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInit() In")); |
| |
| iRollOverState = RollOverStateIdle; |
| PVMFStatus cmdstatus; |
| |
| 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: |
| case PVMFErrRedirect: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInit() PVMFErrLicenseRequired/PVMFErrHTTPAuthenticationRequired/PVMFErrRedirect")); |
| |
| SetEngineState(PVP_ENGINE_STATE_IDLE); |
| cmdstatus = aNodeResp.GetCmdStatus(); |
| |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aNodeResp.GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface())); |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceInit, puuid, nextmsg)); |
| |
| EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus, OSCL_STATIC_CAST(PVInterface*, errmsg), aNodeResp.GetEventData()); |
| errmsg->removeRef(); |
| |
| } |
| break; |
| case PVMFErrContentInvalidForProgressivePlayback: |
| { |
| SetEngineState(PVP_ENGINE_STATE_ERROR); |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_INIT, NULL, NULL, NULL, 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(); |
| } |
| break; |
| |
| default: |
| { |
| if (iState == PVP_ENGINE_STATE_INITIALIZING) |
| { |
| SetEngineState(PVP_ENGINE_STATE_IDLE); |
| if (CheckForSourceRollOver() == false) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeInit() failed, Add EH Command")); |
| cmdstatus = aNodeResp.GetCmdStatus(); |
| |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aNodeResp.GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface())); |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceInit, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_INIT, NULL, NULL, NULL, false); |
| } |
| else |
| { |
| // Initialization of source node failed so try alternates |
| //reschedule to do source node roll over |
| iRollOverState = RollOverStateStart; |
| //remove any queued up auto-pause/auto-resume commands |
| //they are no longer applicable since we are doing a change of sourcenode |
| removeCmdFromQ(iPendingCmds, PVP_ENGINE_COMMAND_PAUSE_DUE_TO_BUFFER_UNDERFLOW, true); |
| removeCmdFromQ(iPendingCmds, PVP_ENGINE_COMMAND_RESUME_DUE_TO_BUFFER_DATAREADY, true); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeInit() - Rescheduling to do source roll over")); |
| RunIfNotReady(); |
| } |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeInit() - Incorrect State - Asserting")); |
| OSCL_ASSERT(false); |
| } |
| } |
| break; |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInit() Out")); |
| } |
| |
| |
| void PVPlayerEngine::HandleSourceNodeGetDurationValue(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::HandleSourceNodeGetDurationValue() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeGetDurationValue() In")); |
| |
| switch (aNodeResp.GetCmdStatus()) |
| { |
| case PVMFSuccess: |
| { |
| // Extract the duration and save it |
| // Check that there is one KVP in value list |
| if (iSourceDurationValueList.size() != 1) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSourceNodeGetDurationValue() Value list size is not 1 (size=%d)", |
| iSourceDurationValueList.size())); |
| break; |
| } |
| |
| // Check that the key in KVP is not NULL |
| if (iSourceDurationValueList[0].key == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSourceNodeGetDurationValue() Value list key string is NULL")); |
| break; |
| } |
| |
| // Check that value is for duration |
| int retval = pv_mime_strstr(iSourceDurationValueList[0].key, (char*)_STRLIT_CHAR("duration")); |
| if (retval == -1) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSourceNodeGetDurationValue() Key string does not contain duration")); |
| break; |
| } |
| |
| // Check that duration value is uint32. If not available assume uint32. |
| PvmiKvpValueType durvaltype = GetValTypeFromKeyString(iSourceDurationValueList[0].key); |
| if (durvaltype != PVMI_KVPVALTYPE_UINT32 && durvaltype != PVMI_KVPVALTYPE_UNKNOWN) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSourceNodeGetDurationValue() Value type is not uint32 or unknown")); |
| break; |
| } |
| iSourceDurationInMS = iSourceDurationValueList[0].value.uint32_value; |
| |
| // Check the timescale. If not available, assume millisecond (1000) |
| const char* retsubstr = NULL; |
| uint32 retsubstrlen = 0; |
| uint32 tsparamlen = oscl_strlen(_STRLIT_CHAR("timescale=")); |
| retsubstr = oscl_strstr(iSourceDurationValueList[0].key, _STRLIT_CHAR("timescale=")); |
| if (retsubstr != NULL) |
| { |
| retsubstrlen = oscl_strlen(retsubstr); |
| if (retsubstrlen > tsparamlen) |
| { |
| uint32 timescale = 0; |
| PV_atoi((char*)(retsubstr + tsparamlen), 'd', (retsubstrlen - tsparamlen), timescale); |
| if (timescale > 0 && timescale != 1000) |
| { |
| // Convert to milliseconds |
| MediaClockConverter mcc(timescale); |
| mcc.update_clock(iSourceDurationInMS); |
| iSourceDurationInMS = mcc.get_converted_ts(1000); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSourceNodeGetDurationValue() Timescale for duration is %d", |
| timescale)); |
| } |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSourceNodeGetDurationValue() Duration in millisec is %d", |
| iSourceDurationInMS)); |
| iSourceDurationAvailable = true; |
| } |
| break; |
| |
| default: |
| { |
| // Duration is not available |
| // Do nothing |
| } |
| break; |
| } |
| |
| // Release any metadata values back to source node |
| // and then clear it |
| if (iSourceDurationValueList.empty() == false) |
| { |
| if (iSourceNodeMetadataExtIF != NULL) |
| { |
| iSourceNodeMetadataExtIF->ReleaseNodeMetadataValues(iSourceDurationValueList, 0, iSourceDurationValueList.size()); |
| } |
| iSourceDurationValueList.clear(); |
| } |
| |
| // Engine's Init() is now complete |
| SetEngineState(PVP_ENGINE_STATE_INITIALIZED); |
| EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeGetDurationValue() Out")); |
| } |
| |
| void PVPlayerEngine::HandleSourceNodeSetDataSourceRate(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceRate() In")); |
| |
| PVMFStatus cmdstatus = aNodeResp.GetCmdStatus(); |
| |
| if (cmdstatus != PVMFSuccess) |
| { |
| EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus); |
| } |
| else |
| { |
| //Continue on to sink rate change. |
| cmdstatus = DoSinkNodeChangeClockRate(); |
| if (cmdstatus != PVMFSuccess) |
| { |
| EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus); |
| } |
| else |
| { |
| //Rate Change is complete. |
| |
| //Install the updated rate and timebase. |
| UpdateTimebaseAndRate(); |
| |
| //Start direction change sequence if needed. |
| if (iPlaybackDirection_New != iPlaybackDirection) |
| { |
| cmdstatus = UpdateCurrentDirection(aNodeContext.iCmdId, aNodeContext.iCmdContext); |
| switch (cmdstatus) |
| { |
| case PVMFPending: |
| //wait on node command completion and call to HandleSourceNodeSetDataSourceDirection |
| break; |
| case PVMFSuccess: |
| //engine command is done, but direction is not actually set on the |
| //source until the Resume or Prepare happens. |
| EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess); |
| break; |
| default: |
| //failed! |
| EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, cmdstatus); |
| break; |
| } |
| } |
| else |
| { |
| //SetPlaybackRate is complete! |
| EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess); |
| } |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceRate() Out")); |
| } |
| |
| PVMFStatus PVPlayerEngine::DoSinkNodeChangeClockRate() |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeChangeClockRate() In")); |
| |
| // Check with sink nodes |
| PVMFStatus cmdstatus = PVMFSuccess; |
| |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath && iDatapathList[i].iSinkNodeSyncCtrlIF) |
| { |
| cmdstatus = iDatapathList[i].iSinkNodeSyncCtrlIF->ChangeClockRate(iPlaybackClockRate_New); |
| |
| if (cmdstatus != PVMFSuccess) |
| { |
| // One of the sinks reported not supported so don't allow the clock rate change. |
| break; |
| } |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoSinkNodeChangeClockRate() Out")); |
| return cmdstatus; |
| } |
| |
| void PVPlayerEngine::UpdateDirection(PVMFTimestamp aNPT, PVMFTimestamp aMediaTS, PVPPlaybackPosition& aPos) |
| { |
| //First note the current observed NPT value. We will reposition to this |
| //value. |
| PVPPlaybackPosition curpos; |
| curpos.iIndeterminate = false; |
| curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| GetPlaybackClockPosition(curpos); |
| aPos = curpos; |
| |
| //Install the new value for direction. |
| iPlaybackDirection = iPlaybackDirection_New; |
| |
| //Save the start NPT and TS |
| iStartNPT = aNPT; |
| iStartMediaDataTS = aMediaTS; |
| |
| if (iPlaybackDirection_New < 0) |
| { |
| if (aPos.iPosValue.millisec_value >= iSourceDurationInMS) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::UpdateDirection() Current pos %dms is more than Duration %dms", aPos.iPosValue.millisec_value, iSourceDurationInMS)); |
| if (ConvertFromMillisec((uint32)(iSourceDurationInMS - 1), aPos) != PVMFSuccess) |
| { |
| // Other position units are not supported yet |
| aPos.iIndeterminate = true; |
| } |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::UpdateDirection() Direction %d New Start NPT %d Start Media Data TS %d, Repos NPT %d, Pos Indeterminate %d" |
| , iPlaybackDirection |
| , iStartNPT |
| , iStartMediaDataTS |
| , aPos.iPosValue.millisec_value |
| , aPos.iIndeterminate)); |
| } |
| |
| void PVPlayerEngine::UpdateTimebaseAndRate() |
| { |
| if (iPlaybackClockRate_New == iPlaybackClockRate |
| && iOutsideTimebase_New == iOutsideTimebase) |
| return;//no update needed |
| |
| //Install the new values for rate & timebase. |
| iPlaybackClockRate = iPlaybackClockRate_New; |
| iOutsideTimebase = iOutsideTimebase_New; |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::UpdateTimebaseAndRate() Rate %d OutsideTB 0x%x CurDir %d NewDir %d" |
| , iPlaybackClockRate, iOutsideTimebase |
| , iPlaybackDirection, iPlaybackDirection_New)); |
| |
| // Pause the clock if running. If already stopped or paused, the call would fail |
| bool clockpaused = iPlaybackClock.Pause(); |
| |
| if (iOutsideTimebase) |
| { |
| //use the outside timebase & ignore the rate. |
| iPlaybackClock.SetClockTimebase(*iOutsideTimebase); |
| } |
| else |
| { |
| //use the player timebase and set the rate. |
| iPlaybackTimebase.SetRate(iPlaybackClockRate); |
| iPlaybackClock.SetClockTimebase(iPlaybackTimebase); |
| } |
| |
| // Only restart the clock if the clock was paused in this function |
| if (clockpaused) |
| { |
| StartPlaybackClock(); |
| } |
| } |
| |
| void PVPlayerEngine::HandleSinkNodeQueryCapConfigIF(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::HandleSinkNodeQueryCapConfigIF() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeQueryCapConfigIF() In")); |
| |
| switch (aNodeResp.GetCmdStatus()) |
| { |
| case PVMFSuccess: |
| { |
| if (aNodeContext.iEngineDatapath->iSinkNodePVInterfaceCapConfig) |
| { |
| aNodeContext.iEngineDatapath->iSinkNodeCapConfigIF = (PvmiCapabilityAndConfig*)aNodeContext.iEngineDatapath->iSinkNodePVInterfaceCapConfig; |
| aNodeContext.iEngineDatapath->iSinkNodePVInterfaceCapConfig = NULL; |
| } |
| } |
| break; |
| |
| default: |
| { |
| if (aNodeContext.iNode == aNodeContext.iEngineDatapath->iSinkNode) |
| { |
| aNodeContext.iEngineDatapath->iSinkNodePVInterfaceCapConfig = NULL; |
| aNodeContext.iEngineDatapath->iSinkNodeCapConfigIF = NULL; |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSinkNodeQueryCapConfigIF() Node dont support Cap-Config Interface, ignoring")); |
| } |
| break; |
| } |
| |
| // Decrement the pending counter and go to next step if 0. |
| --iNumPendingNodeCmd; |
| if (iNumPendingNodeCmd == 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::HandleSinkNodeQueryCapConfigIF() All QueryInterface() commands complete")); |
| |
| PVMFStatus cmdstatus = DoSinkNodeInit(aNodeContext.iCmdId, aNodeContext.iCmdContext); |
| if (cmdstatus != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeQueryCapConfigIF() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSinkNodeQueryCapConfigIF() DoSinkNodeInit failed, Add EH Command")); |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| } |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeQueryCapConfigIF() Out")); |
| } |
| |
| void PVPlayerEngine::HandleSinkNodeInit(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| OSCL_UNUSED_ARG(aNodeContext); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::HandleSinkNodeInit() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeInit() In")); |
| |
| if (aNodeResp.GetCmdStatus() != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeInit() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSinkNodeInit() cmd response is failure, Add EH Command")); |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aNodeResp.GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface())); |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSinkInit, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = aNodeResp.GetCmdStatus(); |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| return; |
| } |
| } |
| |
| // Decrement the pending counter and go to next step if 0. |
| --iNumPendingNodeCmd; |
| if (iNumPendingNodeCmd == 0) |
| { |
| // Init on sink nodes is complete, next step in track selection is to check with the sink nodes alone if the track is |
| // playable or not. If track can be played using sink nodes only move to track selection or else go further to |
| // instantiate decoder nodes for the tracks. |
| |
| // set the Engine state to Track selection so that engine calls DoPrepare and do further processing in Track selection |
| |
| SetEngineState(PVP_ENGINE_STATE_TRACK_SELECTION_1_DONE); |
| RunIfNotReady(); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeInit() Out")); |
| |
| return; |
| } |
| |
| void PVPlayerEngine::HandleDecNodeQueryCapConfigIF(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::HandleDecNodeQueryCapConfigIF() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeQueryCapConfigIF() In")); |
| |
| for (uint32 i = 0; i < iTrackSelectionList.size(); i++) |
| { |
| switch (aNodeResp.GetCmdStatus()) |
| { |
| case PVMFSuccess: |
| { |
| if (aNodeContext.iNode == iTrackSelectionList[i].iTsDecNode && iTrackSelectionList[i].iTsDecNodePVInterfaceCapConfig) |
| { |
| iTrackSelectionList[i].iTsDecNodeCapConfigIF = (PvmiCapabilityAndConfig*)iTrackSelectionList[i].iTsDecNodePVInterfaceCapConfig; |
| iTrackSelectionList[i].iTsDecNodePVInterfaceCapConfig = NULL; |
| |
| PVMFTrackInfo* currTrack = iSourcePresInfoList.getTrackInfo(i); |
| // Valid decoder node set in TrackSelectionList. Scan the TrackSelectionList further and if |
| // any similar MIME track is present just set the decoders to NULL for now. |
| // This is to avoid multiple Init calls on same decoder nodes for similar tracks. |
| // Set the decoder nodes and its cap and config I/F once decoder node Inits complete. |
| for (uint32 j = i + 1; j < iTrackSelectionList.size(); j++) |
| { |
| PVMFTrackInfo* tmpTrack = iSourcePresInfoList.getTrackInfo(j); |
| if (!(pv_mime_strcmp(currTrack->getTrackMimeType().get_str(), tmpTrack->getTrackMimeType().get_str()))) |
| { |
| // These were earlier set in DoDecNodeQueryCapConfifIF to avoid multiple creation of same |
| // decoder nodes. |
| iTrackSelectionList[j].iTsDecNode = NULL; |
| iTrackSelectionList[j].iTsDecNodeSessionId = 0; |
| iTrackSelectionList[j].iTsDecNodeCapConfigIF = NULL; |
| } |
| } |
| } |
| } |
| break; |
| |
| default: |
| { |
| if (aNodeContext.iNode == iTrackSelectionList[i].iTsDecNode) |
| { |
| iTrackSelectionList[i].iTsDecNodePVInterfaceCapConfig = NULL; |
| iTrackSelectionList[i].iTsDecNodeCapConfigIF = NULL; |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleDecNodeQueryCapConfigIF() Node dont support Cap-Config Interface, ignoring")); |
| } |
| break; |
| } |
| } |
| |
| // Decrement the pending counter and go to next step if 0. |
| --iNumPendingNodeCmd; |
| if (iNumPendingNodeCmd == 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::HandleDecNodeQueryCapConfigIF() All QueryInterface() commands complete")); |
| |
| PVMFStatus cmdstatus = DoDecNodeInit(aNodeContext.iCmdId, aNodeContext.iCmdContext); |
| if (cmdstatus != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDecNodeQueryCapConfigIF() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleDecNodeQueryCapConfigIF() DoDecNodeInit failed, Add EH Command")); |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| } |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeQueryCapConfigIF() Out")); |
| } |
| |
| void PVPlayerEngine::HandleDecNodeInit(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| OSCL_UNUSED_ARG(aNodeContext); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::HandleDecNodeInit() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeInit() In")); |
| |
| if (aNodeResp.GetCmdStatus() != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDecNodeInit() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleDecNodeInit() cmd response is failure, Add EH Command")); |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aNodeResp.GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface())); |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapath, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = aNodeResp.GetCmdStatus(); |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| return; |
| } |
| } |
| |
| // Decrement the pending counter and go to next step if 0. |
| --iNumPendingNodeCmd; |
| if (iNumPendingNodeCmd == 0) |
| { |
| // All decoder node Init is complete, now set the decoder node for similar tracks in TrackSelectionList. |
| for (uint32 i = 0; i < iTrackSelectionList.size(); i++) |
| { |
| PVMFTrackInfo* currTrack = iSourcePresInfoList.getTrackInfo(i); |
| |
| for (uint32 j = i + 1; j < iTrackSelectionList.size(); j++) |
| { |
| // If the track has the same MIME type and needs to have a decoder node for it to be playabale track |
| // use the already created decoder node for the track. |
| PVMFTrackInfo* tmpTrack = iSourcePresInfoList.getTrackInfo(j); |
| |
| if ((iTrackSelectionList[i].iTsDecNode != NULL) && |
| !(pv_mime_strcmp(currTrack->getTrackMimeType().get_str(), tmpTrack->getTrackMimeType().get_str())) && |
| !(iTrackSelectionList[j].iTsTrackValidForPlayableList)) |
| { |
| // These were earlier set in DoDecNodeQueryCapConfifIF to avoid multiple creation of same |
| // decoder nodes. |
| iTrackSelectionList[j].iTsDecNode = iTrackSelectionList[i].iTsDecNode; |
| iTrackSelectionList[j].iTsDecNodeSessionId = iTrackSelectionList[i].iTsDecNodeSessionId; |
| iTrackSelectionList[j].iTsDecNodeCapConfigIF = iTrackSelectionList[i].iTsDecNodeCapConfigIF; |
| } |
| } |
| } |
| |
| // Now engine has all decoder and sink nodes setup for each valid track. Engine will now do the track selection based |
| // on config paramters of each track |
| |
| SetEngineState(PVP_ENGINE_STATE_TRACK_SELECTION_2_DONE); |
| RunIfNotReady(); |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeInit() Out")); |
| return; |
| } |
| |
| void PVPlayerEngine::HandleSourceNodePrepare(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleSourceNodePrepare() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodePrepare() In")); |
| |
| PVMFStatus cmdstatus = PVMFErrNotSupported; |
| |
| switch (aNodeResp.GetCmdStatus()) |
| { |
| case PVMFSuccess: |
| { |
| // Datapaths are already set during intelligent track selection, just query for optional interfaces. |
| iNumPendingDatapathCmd = 0; |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iTrackInfo != NULL) |
| { |
| PVMFStatus retcode = DoSinkNodeQueryInterfaceOptional(iDatapathList[i], aNodeContext.iCmdId, aNodeContext.iCmdContext); |
| if (retcode == PVMFSuccess) |
| { |
| ++iNumPendingDatapathCmd; |
| cmdstatus = PVMFSuccess; |
| } |
| else |
| { |
| cmdstatus = retcode; |
| } |
| } |
| } |
| |
| if (iNumPendingDatapathCmd == 0) |
| { |
| if (cmdstatus == PVMFErrNotSupported) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodePrepare() No datapath could be setup. Asserting")); |
| OSCL_ASSERT(false); |
| } |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodePrepare() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodePrepare() Report command as failed, Add EH Command")); |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| } |
| } |
| } |
| break; |
| |
| default: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodePrepare() failed, Add EH Command")); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodePrepare() Already EH pending, should never happen")); |
| return; |
| } |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aNodeResp.GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface())); |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = aNodeResp.GetCmdStatus(); |
| |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| } |
| break; |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodePrepare() Out")); |
| } |
| |
| void PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional() In %s", aNodeContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr())); |
| |
| // Determine QueryInterface() for which interface completed |
| if (aNodeContext.iCmdType == PVP_CMD_SinkNodeQuerySyncCtrlIF) |
| { |
| if (aNodeResp.GetCmdStatus() == PVMFSuccess && aNodeContext.iEngineDatapath->iSinkNodePVInterfaceSyncCtrl) |
| { |
| aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF = (PvmfNodesSyncControlInterface*)aNodeContext.iEngineDatapath->iSinkNodePVInterfaceSyncCtrl; |
| aNodeContext.iEngineDatapath->iSinkNodePVInterfaceSyncCtrl = NULL; |
| |
| // Pass the playback clock to the sync control |
| aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF->SetClock(&iPlaybackClock); |
| |
| // Set the sync margin, find corresponding track for the datapath using mime string |
| bool videoTrack = false; |
| bool audioTrack = false; |
| bool textTrack = false; |
| bool retVal = FindTrackForDatapathUsingMimeString(videoTrack, audioTrack, textTrack, aNodeContext.iEngineDatapath); |
| if (textTrack && retVal) |
| { |
| // Text track |
| aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF->SetMargins((-1*iSyncMarginText.min), iSyncMarginText.max); |
| } |
| else if (audioTrack && retVal) |
| { |
| // Audio track |
| aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF->SetMargins((-1*iSyncMarginAudio.min), iSyncMarginAudio.max); |
| } |
| else |
| { |
| // Video track available or an unknown datapath |
| aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF->SetMargins((-1*iSyncMarginVideo.min), iSyncMarginVideo.max); |
| } |
| } |
| else |
| { |
| // sync control interface is not available in this sink node |
| aNodeContext.iEngineDatapath->iSinkNodePVInterfaceSyncCtrl = NULL; |
| aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF = NULL; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional() Metadata IF not available")); |
| OSCL_ASSERT(false); |
| } |
| } |
| else if (aNodeContext.iCmdType == PVP_CMD_SinkNodeQueryMetadataIF) |
| { |
| if (aNodeResp.GetCmdStatus() == PVMFSuccess && aNodeContext.iEngineDatapath->iSinkNodePVInterfaceMetadataExt) |
| { |
| aNodeContext.iEngineDatapath->iSinkNodeMetadataExtIF = (PVMFMetadataExtensionInterface*)aNodeContext.iEngineDatapath->iSinkNodePVInterfaceMetadataExt; |
| aNodeContext.iEngineDatapath->iSinkNodePVInterfaceMetadataExt = NULL; |
| |
| // Add the video sink node's metadata extension IF to the list |
| if (AddToMetadataInterfaceList(aNodeContext.iEngineDatapath->iSinkNodeMetadataExtIF, aNodeContext.iEngineDatapath->iSinkNodeSessionId, aNodeContext.iEngineDatapath, aNodeContext.iEngineDatapath->iSinkNode) != PVMFSuccess) |
| { |
| aNodeContext.iEngineDatapath->iSinkNodeMetadataExtIF->removeRef(); |
| aNodeContext.iEngineDatapath->iSinkNodeMetadataExtIF = NULL; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional() Metadata IF could not be added to list")); |
| } |
| } |
| else |
| { |
| // Metadata is not available in this video sink node |
| aNodeContext.iEngineDatapath->iSinkNodePVInterfaceMetadataExt = NULL; |
| aNodeContext.iEngineDatapath->iSinkNodeMetadataExtIF = NULL; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional() Metadata IF not available")); |
| } |
| } |
| 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 = DoDecNodeQueryInterfaceOptional(*(aNodeContext.iEngineDatapath), aNodeContext.iCmdId, aNodeContext.iCmdContext); |
| if (cmdstatus == PVMFErrNotSupported) |
| { |
| cmdstatus = DoDatapathPrepare(*(aNodeContext.iEngineDatapath), aNodeContext.iCmdId, aNodeContext.iCmdContext); |
| } |
| |
| if (cmdstatus != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional() Report command as failed, Add EH Command")); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| } |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeQueryInterfaceOptional() Out")); |
| } |
| |
| void PVPlayerEngine::HandleSinkNodeDecNodeReset(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| OSCL_UNUSED_ARG(aNodeContext); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::HandleSinkNodeDecNodeReset() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeDecNodeReset() In")); |
| |
| if (aNodeResp.GetCmdStatus() != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSinkNodeDecNodeReset() Reset failed, assert")); |
| OSCL_ASSERT(false); |
| return; |
| } |
| |
| // Decrement the pending counter and go to next step if 0. |
| --iNumPendingNodeCmd; |
| if (iNumPendingNodeCmd == 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeDecNodeReset() All Sinknode and decnode Reset() commands complete")); |
| SetEngineState(PVP_ENGINE_STATE_TRACK_SELECTION_3_DONE); |
| RunIfNotReady(); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeDecNodeReset() Out")); |
| } |
| |
| void PVPlayerEngine::HandleDecNodeQueryInterfaceOptional(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() Tick=%d", OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() In %s", aNodeContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr())); |
| |
| // Determine QueryInterface() for which interface completed |
| if (aNodeContext.iCmdType == PVP_CMD_DecNodeQueryMetadataIF) |
| { |
| if (aNodeResp.GetCmdStatus() == PVMFSuccess && aNodeContext.iEngineDatapath->iDecNodePVInterfaceMetadataExt) |
| { |
| aNodeContext.iEngineDatapath->iDecNodeMetadataExtIF = (PVMFMetadataExtensionInterface*)aNodeContext.iEngineDatapath->iDecNodePVInterfaceMetadataExt; |
| aNodeContext.iEngineDatapath->iDecNodePVInterfaceMetadataExt = NULL; |
| |
| // Add the video dec node's metadata extension IF to the list |
| if (AddToMetadataInterfaceList(aNodeContext.iEngineDatapath->iDecNodeMetadataExtIF, aNodeContext.iEngineDatapath->iDecNodeSessionId, aNodeContext.iEngineDatapath, aNodeContext.iEngineDatapath->iDecNode) != PVMFSuccess) |
| { |
| aNodeContext.iEngineDatapath->iDecNodeMetadataExtIF->removeRef(); |
| aNodeContext.iEngineDatapath->iDecNodeMetadataExtIF = NULL; |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() Metadata IF could not be added to list")); |
| } |
| } |
| else |
| { |
| // Metadata is not available in this dec node |
| aNodeContext.iEngineDatapath->iDecNodePVInterfaceMetadataExt = NULL; |
| aNodeContext.iEngineDatapath->iDecNodeMetadataExtIF = NULL; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() Metadata IF not available")); |
| } |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() Unknown cmd type. Asserting")); |
| OSCL_ASSERT(false); |
| } |
| |
| if (aNodeContext.iEngineDatapath->iDecNodeCapConfigIF) |
| { |
| // Configure the dec node for player use |
| PvmiKvp kvpparam; |
| PvmiKvp* retkvp = NULL; |
| OSCL_StackString<64> kvpparamkey; |
| |
| bool videoTrack = false; |
| bool audioTrack = false; |
| bool textTrack = false; |
| bool retVal = FindTrackForDatapathUsingMimeString(videoTrack, audioTrack, textTrack, aNodeContext.iEngineDatapath); |
| if (videoTrack && retVal) |
| { |
| // Video track |
| // Disable drop frame mode |
| kvpparamkey = _STRLIT_CHAR("x-pvmf/video/decoder/dropframe_enable;valtype=bool"); |
| kvpparam.value.bool_value = false; |
| } |
| else if (audioTrack && retVal) |
| { |
| // Audio track |
| // Disable silence insertion |
| kvpparamkey = _STRLIT_CHAR("x-pvmf/audio/decoder/silenceinsertion_enable;valtype=bool"); |
| kvpparam.value.bool_value = false; |
| aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF->SetMargins((-1*iSyncMarginAudio.min), iSyncMarginAudio.max); |
| } |
| |
| if (kvpparamkey.get_size() > 0) |
| { |
| kvpparam.key = kvpparamkey.get_str(); |
| aNodeContext.iEngineDatapath->iDecNodeCapConfigIF->setParametersSync(NULL, &kvpparam, 1, retkvp); |
| if (retkvp != NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() Configuring dec node for player use via cap-config IF failed")); |
| } |
| } |
| } |
| |
| // Decrement the pending counter and go to next step if 0. |
| OSCL_ASSERT(aNodeContext.iEngineDatapath->iNumPendingCmd > 0); |
| --aNodeContext.iEngineDatapath->iNumPendingCmd; |
| if (aNodeContext.iEngineDatapath->iNumPendingCmd == 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() All QueryInterface() commands complete")); |
| |
| // Prepare the datapath |
| PVMFStatus cmdstatus = DoDatapathPrepare(*(aNodeContext.iEngineDatapath), aNodeContext.iCmdId, aNodeContext.iCmdContext); |
| |
| if (cmdstatus != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() Report command as failed, Add EH command")); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| } |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeQueryInterfaceOptional() Out")); |
| } |
| |
| |
| void PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() In")); |
| |
| PVMFTimestamp requesttime = iTargetNPT; |
| |
| if (aNodeResp.GetCmdStatus() == PVMFErrNotSupported || aNodeResp.GetCmdStatus() == PVMFErrArgument) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() QueryDataSourcePosition failed. Assume position goes to requested position")); |
| } |
| else if (aNodeResp.GetCmdStatus() != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() QueryDataSourcePosition failed, Add EH command")); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodePause() Already EH pending, should never happen")); |
| return; |
| } |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aNodeResp.GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface())); |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = aNodeResp.GetCmdStatus(); |
| |
| if (iState == PVP_ENGINE_STATE_PREPARING) |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| else if (iState == PVP_ENGINE_STATE_RESUMING) |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME, NULL, NULL, NULL, false); |
| return; |
| } |
| else |
| { |
| PVMFNodeCapability nodeCapability; |
| iSourceNode->GetCapability(nodeCapability); |
| PVMFFormatType * formatType = nodeCapability.iInputFormatCapability.begin(); |
| bool mpeg4FormatType = false; |
| if (formatType != NULL) |
| { |
| if ((pv_mime_strcmp((char*)formatType->getMIMEStrPtr(), PVMF_MIME_MPEG4FF)) == 0) |
| { |
| mpeg4FormatType = true; |
| } |
| else |
| { |
| mpeg4FormatType = false; |
| } |
| } |
| |
| if (mpeg4FormatType) |
| { |
| // Every thing is OK.. Calculate the modified target position depending upon nearest before and after syncPoints. |
| // For MPEG4 files |
| CalculateActualPlaybackPosition(); |
| } |
| } |
| |
| // Determine the SetDataSourcePosition parameter based on query result and reposition settings |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, |
| "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition()" |
| "Requested NPT %d, Modified Target NPT %d", requesttime, iTargetNPT)); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, |
| "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition()" |
| "Requested NPT %d, Modified Target NPT %d", requesttime, iTargetNPT)); |
| |
| uint32 startOfSeekWindow = 0; |
| if (requesttime > iSyncPointSeekWindow) |
| { |
| startOfSeekWindow = (requesttime - iSyncPointSeekWindow); |
| } |
| uint32 endOfSeekWindow = requesttime + iSyncPointSeekWindow; |
| |
| // 1) Check if the modified target position falls within the window |
| if ((iTargetNPT >= startOfSeekWindow) && |
| (iTargetNPT <= endOfSeekWindow)) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, |
| "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() - " |
| "RequestedNPT(%d) ModifiedTargetNPT(%d) is in the window (%d, %d), Seeking To %d", |
| requesttime, iTargetNPT, startOfSeekWindow, endOfSeekWindow, iTargetNPT)); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, |
| "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() - " |
| "RequestedNPT(%d) ModifiedTargetNPT(%d) is in the window (%d, %d), Seeking To %d", |
| requesttime, iTargetNPT, startOfSeekWindow, endOfSeekWindow, iTargetNPT)); |
| |
| requesttime = iTargetNPT; |
| } |
| else |
| { |
| // 1) Check if the actual seek point is before the window start, then set the |
| // request time to start of the window |
| // 2) Check if the actual seek point is after the window end, then |
| // go back to start of the seek window |
| // SFR is not really an option here since we are not playing yet, therefore always |
| // go to start of the window |
| if ((iTargetNPT < startOfSeekWindow) || |
| (iTargetNPT > endOfSeekWindow)) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, |
| "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() - " |
| "RequestedNPT(%d) ModifiedTargetNPT(%d) is outside the window (%d, %d), Seeking To %d Seek-To-SyncPt False", |
| requesttime, iTargetNPT, startOfSeekWindow, endOfSeekWindow, startOfSeekWindow)); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, |
| "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() - " |
| "RequestedNPT(%d) ModifiedTargetNPT(%d) is outside the window (%d, %d), Seeking To %d Seek-To-SyncPt False", |
| requesttime, iTargetNPT, startOfSeekWindow, endOfSeekWindow, startOfSeekWindow)); |
| |
| requesttime = startOfSeekWindow; |
| iTargetNPT = requesttime; |
| } |
| else |
| { |
| //error |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, |
| "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() - " |
| "RequestedNPT(%d) ModifiedTargetNPT(%d) window (%d, %d), Error Condition Asserting", |
| requesttime, iTargetNPT, startOfSeekWindow, endOfSeekWindow)); |
| OSCL_ASSERT(false); |
| } |
| } |
| |
| // Do the source positioning |
| PVMFStatus retval = DoSourceNodeSetDataSourcePosition(aNodeContext.iCmdId, aNodeContext.iCmdContext); |
| if (retval != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() Report command as failed, Add EH command")); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| iCommandCompleteStatusInErrorHandling = retval; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| if (iState == PVP_ENGINE_STATE_PREPARING) |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| else if (iState == PVP_ENGINE_STATE_RESUMING) |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME, NULL, NULL, NULL, false); |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePosition() Out")); |
| } |
| |
| |
| void PVPlayerEngine::HandleSourceNodeSetDataSourcePosition(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() In")); |
| |
| PVMFStatus cmdstatus = PVMFFailure; |
| |
| switch (aNodeResp.GetCmdStatus()) |
| { |
| case PVMFErrArgument: |
| case PVMFErrNotSupported: |
| { |
| if (iChangePlaybackPositionWhenResuming) |
| { |
| PVPPlaybackPosition curpos; |
| curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| GetPlaybackClockPosition(curpos); |
| uint32 clockcurpos = 0; |
| bool tmpbool = false; |
| iPlaybackClock.GetCurrentTime32(clockcurpos, tmpbool, PVMF_MEDIA_CLOCK_MSEC); |
| |
| // since repositioning is not supported and if the playback position change request was |
| // issued during paused state, then continue from paused position. |
| iChangePlaybackPositionWhenResuming = false; |
| iWatchDogTimerInterval = 0; |
| iActualNPT = curpos.iPosValue.millisec_value; |
| iActualMediaDataTS = clockcurpos; |
| iSkipMediaDataTS = clockcurpos; |
| |
| iStartNPT = iActualNPT; |
| iStartMediaDataTS = iSkipMediaDataTS; |
| |
| // also decrement the stream id as no skip will be called on MIO node. |
| --iStreamID; |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| PVMFBasicErrorInfoMessage* infomsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoChangePlaybackPositionNotSupported, puuid, NULL)); |
| SendInformationalEvent(PVMFInfoChangePlaybackPositionNotSupported, OSCL_STATIC_CAST(PVInterface*, infomsg)); |
| infomsg->removeRef(); |
| } |
| else |
| { |
| // This happens when we are in preparing state |
| // Since this repositioning was not supported, assume the playback |
| // will start from time 0 |
| iWatchDogTimerInterval = 0; |
| iActualNPT = 0; |
| iActualMediaDataTS = 0; |
| iSkipMediaDataTS = 0; |
| // Then continue to handle like success case |
| iStartNPT = 0; |
| iStartMediaDataTS = 0; |
| } |
| |
| // Save the actual starting position for GetPlaybackRange() query |
| iTargetNPT = iActualNPT; |
| iCurrentBeginPosition.iPosValue.millisec_value = iActualNPT; |
| iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() Requested begin position(%d ms) is not supported so start from prev location.", |
| iTargetNPT)); |
| } |
| break; |
| |
| case PVMFSuccess: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() SetDataSourcePosition() successful. StartMediaTS %d ms, ActualNPT %d ms, TargetNPT %d ms", |
| iActualMediaDataTS, iActualNPT, iTargetNPT)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() SetDataSourcePosition() successful. StartMediaTS %d ms, ActualNPT %d ms, TargetNPT %d ms", |
| iActualMediaDataTS, iActualNPT, iTargetNPT)); |
| // Compute the difference between actualNPT and targetNPT before any adjustments |
| if (iTargetNPT >= iActualNPT) |
| { |
| iWatchDogTimerInterval = iTargetNPT - iActualNPT; |
| } |
| |
| // Determine if adjustment needed to skip to requested time |
| if (iSkipToRequestedPosition && (iActualNPT < iTargetNPT)) |
| { |
| if (iTargetNPT - iActualNPT > iNodeDataQueuingTimeout) |
| { |
| // Sync point seems to be far away in the stream |
| // Can't adjust the skip time back so use the returned values to skip to |
| iSkipMediaDataTS = iActualMediaDataTS; |
| iTargetNPT = iActualNPT; |
| iWatchDogTimerInterval = 0; |
| iCurrentBeginPosition.iPosValue.millisec_value = iActualNPT; |
| } |
| else |
| { |
| //check if source node wants to override |
| uint32 startNPTFrmSource = iActualNPT; |
| if (iSourceNodePBCtrlIF->ComputeSkipTimeStamp(iTargetNPT, |
| iActualNPT, |
| iActualMediaDataTS, |
| iSkipMediaDataTS, |
| startNPTFrmSource) == PVMFSuccess) |
| { |
| iWatchDogTimerInterval = startNPTFrmSource - iActualNPT; |
| iActualNPT = startNPTFrmSource; |
| iTargetNPT = iActualNPT; |
| iCurrentBeginPosition.iPosValue.millisec_value = iActualNPT; |
| } |
| else |
| { |
| // Adjust the media data time to skip-to to correspond to the requested time |
| // Add the difference of target NPT with actual playback position in NPT to the actual media data time to get time to skip to. |
| iSkipMediaDataTS = iActualMediaDataTS + (iTargetNPT - iActualNPT); |
| iActualNPT = iTargetNPT; |
| } |
| } |
| } |
| else |
| { |
| // Can't adjust the skip time back so use the returned values to skip to |
| iSkipMediaDataTS = iActualMediaDataTS; |
| iTargetNPT = iActualNPT; |
| iCurrentBeginPosition.iPosValue.millisec_value = iActualNPT; |
| iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| iWatchDogTimerInterval = 0; |
| } |
| |
| // Save initial NTP and TS values |
| iStartNPT = iActualNPT; |
| iStartMediaDataTS = iSkipMediaDataTS; |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() After adjustment StartMediaTS %d ms, AdjustedMediaTS %d ms, ActualPBPos %d ms Start NPT %d Start TS %d", |
| iActualMediaDataTS, iSkipMediaDataTS, iActualNPT, iStartNPT, iStartMediaDataTS)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() After adjustment StartMediaTS %d ms, AdjustedMediaTS %d ms, ActualNPT %d ms StartNPT %d StartTS %d", |
| iActualMediaDataTS, iSkipMediaDataTS, iActualNPT, iStartNPT, iStartMediaDataTS)); |
| } |
| break; |
| |
| default: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() failed, Add EH command")); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() Already EH pending, should never happen")); |
| return; |
| } |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aNodeResp.GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface())); |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = aNodeResp.GetCmdStatus(); |
| |
| if (iState == PVP_ENGINE_STATE_PREPARING) |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| else if (iState == PVP_ENGINE_STATE_RESUMING) |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME, NULL, NULL, NULL, false); |
| |
| return; |
| } |
| } |
| // Repositioning so reset the EOS flag for each active datapath |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath) |
| { |
| iDatapathList[i].iEndOfDataReceived = false; |
| } |
| } |
| |
| // Contine on and start the source node |
| cmdstatus = DoSourceNodeStart(aNodeContext.iCmdId, aNodeContext.iCmdContext); |
| if (cmdstatus != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() Report command as failed, Add EH command")); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| if (iState == PVP_ENGINE_STATE_PREPARING) |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| else if (iState == PVP_ENGINE_STATE_RESUMING) |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME, NULL, NULL, NULL, false); |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() Out")); |
| } |
| |
| void PVPlayerEngine::HandleSourceNodeSetDataSourceDirection(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() In")); |
| |
| if (iChangePlaybackDirectionWhenResuming) |
| { |
| // Continuation of Engine Resume sequence. |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Context RESUME")); |
| PVMFStatus cmdstatus = PVMFFailure; |
| |
| switch (aNodeResp.GetCmdStatus()) |
| { |
| case PVMFErrArgument: |
| case PVMFErrNotSupported: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Requested direction is not supported!")); |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| PVMFBasicErrorInfoMessage* infomsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoChangePlaybackPositionNotSupported, puuid, NULL)); |
| SendInformationalEvent(PVMFInfoChangePlaybackPositionNotSupported, OSCL_STATIC_CAST(PVInterface*, infomsg)); |
| infomsg->removeRef(); |
| } |
| break; |
| |
| case PVMFSuccess: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() SetDataSourceDirection() successful. StartMediaTS %d ms, ActualPBPos %d ms", |
| iActualMediaDataTS, iActualNPT)); |
| |
| //there's no adjustment to the media TS here. |
| iSkipMediaDataTS = iActualMediaDataTS; |
| iCurrentBeginPosition.iPosValue.millisec_value = iActualNPT; |
| iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| |
| //Install the new direction and get the repositioning target. |
| UpdateDirection(iActualNPT, iSkipMediaDataTS, iChangeDirectionNPT); |
| |
| //Reposition the source to the desired playback time |
| if (!iChangeDirectionNPT.iIndeterminate) |
| { |
| iChangePlaybackDirectionWhenResuming = false; |
| iChangePlaybackPositionWhenResuming = true; |
| PVPlayerEngineCommand cmd(0, aNodeContext.iCmdId, aNodeContext.iCmdContext, NULL, false); |
| iCurrentBeginPosition = iChangeDirectionNPT; |
| PVMFStatus retval = UpdateCurrentBeginPosition(iCurrentBeginPosition, cmd); |
| if (retval == PVMFPending) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Repos to %d started", iChangeDirectionNPT.iPosValue)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Out")); |
| return;//wait on the repos sequence... |
| } |
| else if (retval != PVMFSuccess) |
| { |
| //else can't reposition, ignore failure and continue. |
| iChangeDirectionNPT.iIndeterminate = true; |
| iChangePlaybackPositionWhenResuming = false; |
| //need to leave the flag set for later in HandleDatapathResume, |
| //to trigger the skip media data. |
| iChangePlaybackDirectionWhenResuming = true; |
| } |
| } |
| } |
| break; |
| |
| default: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() failed, Add EH command")); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Already EH pending, should never happen")); |
| return; |
| } |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aNodeResp.GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface())); |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = aNodeResp.GetCmdStatus(); |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME, NULL, NULL, NULL, false); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Out")); |
| return; |
| } |
| } |
| |
| |
| // Repositioning so reset the EOS flag for each active datapath |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath) |
| { |
| iDatapathList[i].iEndOfDataReceived = false; |
| } |
| } |
| |
| // Start the source node. |
| cmdstatus = DoSourceNodeStart(aNodeContext.iCmdId, aNodeContext.iCmdContext); |
| if (cmdstatus != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePosition() Report command as failed, Add EH command")); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME, NULL, NULL, NULL, false); |
| } |
| } |
| } |
| else |
| { |
| //Continuation of SetPlaybackRate sequence. |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Context SETPLAYBACKRATE")); |
| |
| if (aNodeResp.GetCmdStatus() != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() SetDataSourceDirection failed. Playback position change has been cancelled")); |
| |
| if (aNodeResp.GetCmdStatus() == PVMFErrNotSupported || aNodeResp.GetCmdStatus() == PVMFErrArgument) |
| { |
| // For non-fatal error, continue playback by resuming the clock |
| StartPlaybackClock(); |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() failed, Add EH command")); |
| // Initiate error handling |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Already EH pending, should never happen")); |
| return; |
| } |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aNodeResp.GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface())); |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = aNodeResp.GetCmdStatus(); |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_SET_PLAYBACK_RATE, NULL, NULL, NULL, false); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Out")); |
| return; |
| } |
| |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aNodeResp.GetEventExtensionInterface() != NULL) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface())); |
| } |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSource, puuid, nextmsg)); |
| |
| // Complete the SetPlaybackRate() command as failed |
| EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, aNodeResp.GetCmdStatus(), OSCL_STATIC_CAST(PVInterface*, errmsg)); |
| |
| errmsg->removeRef(); |
| errmsg = NULL; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Out")); |
| return; |
| } |
| |
| // no adjustement here. |
| iSkipMediaDataTS = iActualMediaDataTS; |
| iCurrentBeginPosition.iPosValue.millisec_value = iActualNPT; |
| iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| |
| //Install the new direction and get the repositioning target |
| UpdateDirection(iActualNPT, iSkipMediaDataTS, iChangeDirectionNPT); |
| |
| //Launch a repositioning sequence now. |
| if (!iChangeDirectionNPT.iIndeterminate) |
| { |
| PVPlayerEngineCommand cmd(0, aNodeContext.iCmdId, aNodeContext.iCmdContext, NULL, false); |
| iCurrentBeginPosition = iChangeDirectionNPT; |
| PVMFStatus retval = UpdateCurrentBeginPosition(iCurrentBeginPosition, cmd); |
| if (retval == PVMFPending) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Repos to %d started", iChangeDirectionNPT.iPosValue)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Out")); |
| return;//wait on the repos sequence... |
| } |
| else if (retval != PVMFSuccess) |
| { |
| //the direction is already changed, so just ignore this failure and continue |
| iChangeDirectionNPT.iIndeterminate = true; |
| } |
| } |
| |
| // Repositioning so reset the EOS flag for each active datapath |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath) |
| { |
| iDatapathList[i].iEndOfDataReceived = false; |
| } |
| } |
| |
| // Skip to the new source node position, so that all the data that was queued |
| // when the command was received will get flushed. |
| |
| PVMFStatus retval = DoSinkNodeSkipMediaDataDuringPlayback(aNodeContext.iCmdId, aNodeContext.iCmdContext); |
| if (retval != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Skipping media data request in sink nodes failed. Repositioning did not complete.")); |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSink, puuid, NULL)); |
| |
| //clear the pending direction change NPT. |
| iChangeDirectionNPT.iIndeterminate = true; |
| |
| // Complete the SetPlaybackRate() command as failed |
| EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, retval, OSCL_STATIC_CAST(PVInterface*, errmsg)); |
| |
| errmsg->removeRef(); |
| errmsg = NULL; |
| } |
| // else wait on HandleSinkNodeSkipMediaDataDuringPlayback. |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourceDirection() Out")); |
| } |
| |
| void PVPlayerEngine::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: |
| { |
| // Issue Skip on Sink Node and Start on datapaths back to back. This is done to make sure that |
| // sink node is started only after discarding the data from an earlier stream. |
| cmdstatus = DoSinkNodeSkipMediaData(aNodeContext.iCmdId, aNodeContext.iCmdContext); |
| if (cmdstatus != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeStart() Skip of sink node did a leave, asserting")); |
| OSCL_ASSERT(false); |
| } |
| |
| // Start the available datapaths |
| iNumPendingDatapathCmd = 0; |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath) |
| { |
| PVMFStatus retval = DoDatapathStart(iDatapathList[i], aNodeContext.iCmdId, aNodeContext.iCmdContext); |
| if (retval == PVMFSuccess) |
| { |
| ++iNumPendingDatapathCmd; |
| cmdstatus = PVMFSuccess; |
| } |
| else |
| { |
| cmdstatus = retval; |
| break; |
| } |
| } |
| } |
| if (iNumPendingDatapathCmd == 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine:HandleSourceNodeStart() DoDatapathStart failed, Add EH command")); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine:HandleSourceNodeStart() Already EH pending, should never happen")); |
| return; |
| } |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| } |
| } |
| break; |
| |
| default: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine:HandleSourceNodeStart() failed, Add EH command")); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine:HandleSourceNodeStart() Already EH pending, should never happen")); |
| return; |
| } |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aNodeResp.GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface())); |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = aNodeResp.GetCmdStatus(); |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| } |
| break; |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeStart() Out")); |
| } |
| |
| |
| void PVPlayerEngine::HandleSinkNodeSkipMediaData(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| OSCL_UNUSED_ARG(aNodeContext); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleSinkNodeSkipMediaData() for %s Tick=%d", |
| aNodeContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleSinkNodeSkipMediaData() for %s, iNumPVMFInfoStartOfDataPending=%d", |
| aNodeContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr(), iNumPVMFInfoStartOfDataPending)); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::HandleSinkNodeSkipMediaData() In")); |
| |
| --iNumPendingNodeCmd; |
| |
| if (aNodeResp.GetCmdStatus() != PVMFSuccess) |
| { |
| // Sink node report error with SkipMediaData() |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeSkipMediaData() Sink node report error for SkipMediaData(). Asserting")); |
| OSCL_ASSERT(false); |
| } |
| |
| --iNumPendingSkipCompleteEvent; |
| |
| if (iNumPendingNodeCmd == 0) |
| { |
| // We dont start the playback clock here since engine is waiting for Start on Sink nodes to complete |
| // This will also check the order in which Sink Node completes the command. Sinks should complete Skip |
| // first and then Start, therefore iNumPendingDatapathCmd should always be greater than zero when |
| // this happens. If not just assert. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleSinkNodeSkipMediaData() Skip Complete")); |
| } |
| |
| if ((iNumPendingSkipCompleteEvent == 0) && (iNumPVMFInfoStartOfDataPending == 0)) |
| { |
| // we have received all the bos event so cancel the watchDogTimer if any. |
| if (iWatchDogTimer->IsBusy()) |
| { |
| iWatchDogTimer->Cancel(); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSinkNodeSkipMediaData - WatchDogTimer cancelled")); |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeSkipMediaData() Out")); |
| } |
| |
| |
| void PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() In")); |
| |
| PVMFTimestamp requesttime = iTargetNPT; |
| if (aNodeResp.GetCmdStatus() != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() QueryDataSourcePosition failed. Assume position goes to requested position")); |
| } |
| else |
| { |
| PVMFNodeCapability nodeCapability; |
| iSourceNode->GetCapability(nodeCapability); |
| PVMFFormatType * formatType = nodeCapability.iInputFormatCapability.begin(); |
| bool mpeg4FormatType = false; |
| if (formatType != NULL) |
| { |
| if ((pv_mime_strcmp((char*)formatType->getMIMEStrPtr(), PVMF_MIME_MPEG4FF)) == 0) |
| { |
| mpeg4FormatType = true; |
| } |
| else |
| { |
| mpeg4FormatType = false; |
| } |
| } |
| if (mpeg4FormatType) |
| { |
| // Every thing is OK.. Calculate the modified target position depending upon nearest before and after syncPoints. |
| // For MPEG4 files |
| CalculateActualPlaybackPosition(); |
| } |
| } |
| |
| // Determine the SetDataSourcePosition parameter based on query result and reposition settings |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, |
| "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback()" |
| "Requested NPT %d, ModifiedTarget NPT %d", requesttime, iTargetNPT)); |
| |
| uint32 startOfSeekWindow = 0; |
| if (requesttime > iSyncPointSeekWindow) |
| { |
| startOfSeekWindow = (requesttime - iSyncPointSeekWindow); |
| } |
| uint32 endOfSeekWindow = requesttime + iSyncPointSeekWindow; |
| |
| PVPPlaybackPosition curpos; |
| curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| GetPlaybackClockPosition(curpos); |
| bool oSFR = false; |
| |
| //depending on whether it is fwd or rwnd, the window is different |
| //if doing a rwnd, the worst case window is (0, currentplaybackposition) |
| //if doing a fwd, the worst case window is (currentplaybackposition, endofclip) |
| if (requesttime <= curpos.iPosValue.millisec_value) |
| { |
| //requested pos <= currpos => rwnd |
| //cap end of seek window to be the current play back pos |
| endOfSeekWindow = curpos.iPosValue.millisec_value; |
| } |
| if (requesttime > curpos.iPosValue.millisec_value) |
| { |
| //requested pos > currpos => fwd |
| //cap start of seek window to be the current play back pos |
| startOfSeekWindow = curpos.iPosValue.millisec_value; |
| } |
| |
| // 1) Check if the Modified target position falls within the window |
| if ((iTargetNPT >= startOfSeekWindow) && |
| (iTargetNPT <= endOfSeekWindow)) |
| { |
| // Check for SFR |
| // In case if actual playback position |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, |
| "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() - " |
| "RequestedNPT(%d) ModifiedTargetNPT(%d) is in the window (%d, %d), Seeking To %d", |
| requesttime, iTargetNPT, startOfSeekWindow, endOfSeekWindow, iTargetNPT)); |
| |
| requesttime = iTargetNPT; |
| } |
| else |
| { |
| // Check for SFR |
| // SFR means currplaybackpos < requestedpos |
| if (curpos.iPosValue.millisec_value < requesttime) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, |
| "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() - " |
| "CurrNPT(%d) less than RequestedNPT(%d) Ignoring ModifiedTargetNPT(%d) and the window (%d, %d), Doing SFR", |
| curpos.iPosValue.millisec_value, requesttime, iTargetNPT, startOfSeekWindow, endOfSeekWindow, startOfSeekWindow)); |
| |
| oSFR = true; |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| PVMFBasicErrorInfoMessage* infomsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoAttemptingSFRAsPartOfSetPlayBackRange, puuid, NULL)); |
| SendInformationalEvent(PVMFInfoPositionStatus, OSCL_STATIC_CAST(PVInterface*, infomsg)); |
| infomsg->removeRef(); |
| |
| } |
| else |
| { |
| // if the actual seek point is before the window start, |
| // or if the actual seek point is after the window end, |
| // then go back to start of the seek window only in case of a finite window |
| // in case of infinite window just go to the requested position and do normal |
| // repositioning |
| if (iSyncPointSeekWindow == 0x7FFFFFFF) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, |
| "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() - " |
| "RequestedNPT(%d) ModifiedTargetNPT(%d) is outside the window (%d, %d), Seeking To %d Seek-To-SyncPt True", |
| requesttime, iTargetNPT, startOfSeekWindow, endOfSeekWindow, startOfSeekWindow)); |
| |
| iTargetNPT = requesttime; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, |
| "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() - " |
| "RequestedNPT(%d) ModifiedTargetNPT(%d) is outside the window (%d, %d), Seeking To %d Seek-To-SyncPt False", |
| requesttime, iTargetNPT, startOfSeekWindow, endOfSeekWindow, startOfSeekWindow)); |
| |
| requesttime = startOfSeekWindow; |
| iTargetNPT = requesttime; |
| } |
| } |
| } |
| |
| if (oSFR) |
| { |
| // No need to change source position so go to skipping at sink nodes |
| // First determine to what time sink nodes should skip to |
| // Get current playback clock position in media data time |
| uint32 clockcurpos = 0; |
| bool tmpbool = false; |
| iPlaybackClock.GetCurrentTime32(clockcurpos, tmpbool, PVMF_MEDIA_CLOCK_MSEC); |
| |
| // for SFR since the source node is bypassed, there will be no frames generated with new |
| // Stream ID so, for skip to complete on Sink Node, Stream ID needs to be decremented. As |
| // there will be no new Stream in case of SFR. |
| --iStreamID; |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() New source reposition before current position so no need to change source position.")); |
| |
| if (iSkipToRequestedPosition) |
| { |
| // Skip to the requested begin position |
| // Add the difference of target NPT with current time in NPT to the current clock to get media data time to skip to. |
| iActualMediaDataTS = clockcurpos; |
| iSkipMediaDataTS = (requesttime - curpos.iPosValue.millisec_value) + clockcurpos; |
| iActualNPT = requesttime; |
| iWatchDogTimerInterval = requesttime - curpos.iPosValue.millisec_value; |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() Skip-to-requested position SET. ActualNPT=%d, ActualMediaTS=%d, AdjustedMediaTS=%d", |
| iActualNPT, iActualMediaDataTS, iSkipMediaDataTS)); |
| } |
| else |
| { |
| // Just continue playback from current position |
| iActualMediaDataTS = clockcurpos; |
| iSkipMediaDataTS = clockcurpos; |
| iActualNPT = curpos.iPosValue.millisec_value; |
| iWatchDogTimerInterval = 0; |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() Skip-to-requested position NOT SET so continue playing. ActualNPT=%d, ActualMediaTS=%d, AdjustedMediaTS=%d", |
| iActualNPT, iActualMediaDataTS, iSkipMediaDataTS)); |
| } |
| |
| PVMFStatus retval = DoSinkNodeSkipMediaDataDuringPlayback(aNodeContext.iCmdId, aNodeContext.iCmdContext, true); |
| if (retval != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() Skipping media data request in sink nodes failed. Repositioning did not complete.")); |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSink, puuid, NULL)); |
| |
| //clear the pending direction change NPT. |
| iChangeDirectionNPT.iIndeterminate = true; |
| |
| // Complete the SetPlaybackRange() command as failed |
| EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, retval, OSCL_STATIC_CAST(PVInterface*, errmsg)); |
| |
| errmsg->removeRef(); |
| errmsg = NULL; |
| } |
| |
| } |
| else |
| { |
| // Do the source positioning |
| PVMFStatus retval = DoSourceNodeSetDataSourcePositionDuringPlayback(aNodeContext.iCmdId, aNodeContext.iCmdContext); |
| if (retval != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() SetDataSourcePosition failed. Playback position change has been cancelled")); |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSource, puuid, NULL)); |
| |
| // Complete the SetPlaybackRange() command as failed |
| EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, retval, OSCL_STATIC_CAST(PVInterface*, errmsg)); |
| |
| errmsg->removeRef(); |
| errmsg = NULL; |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeQueryDataSourcePositionDuringPlayback() Out")); |
| } |
| |
| void PVPlayerEngine::CalculateActualPlaybackPosition() |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::CalculateActualPlaybackPosition In")); |
| |
| PVPPlaybackPosition curpos; |
| curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| GetPlaybackClockPosition(curpos); |
| |
| // Following code has been taken from MP4 parser node, all the vars are kept very near to the MP4 parser node. |
| // Previously the calculation of before and after sync point was done in MP4 parser node. |
| |
| if (curpos.iPosValue.millisec_value > iTargetNPT) |
| { |
| // curpos.iPosValue.millisec_value was passed as iActualNPT in QueryDataSourcePosition |
| // which became aActualNPT while collection, and used to decide forward and reverse repos. |
| iBackwardReposFlag = true; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::CalculateActualPlaybackPosition In: Backward Reposition")); |
| } |
| else |
| { |
| iForwardReposFlag = true; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::CalculateActualPlaybackPosition In: Forward Reposition")); |
| } |
| |
| // pick the closest time to targetNPT |
| uint32 delta = 0; |
| uint32 diffBetSeekPointBeforeAndTarget = 0; |
| if (PVTimeComparisonUtils::IsEarlier(iSeekPointBeforeTargetNPT, iTargetNPT, delta)) |
| { |
| // this should always be true when checking the SeekPointBefore with |
| // targetNPT. |
| diffBetSeekPointBeforeAndTarget = delta; |
| delta = 0; |
| } |
| else |
| { |
| // this will only happen when mp4ff library returns an SeekPointBefore which |
| // is after targetNPT with small delta because of some rounding off error in |
| // media clock converter class. |
| diffBetSeekPointBeforeAndTarget = delta; |
| delta = 0; |
| } |
| |
| uint32 diffBetSeekPointAfterAndTarget = 0; |
| if (PVTimeComparisonUtils::IsEarlier(iTargetNPT, iSeekPointAfterTargetNPT, delta)) |
| { |
| // this should always be true when checking the SeekPointAfter with |
| // targetNPT. |
| diffBetSeekPointAfterAndTarget = delta; |
| delta = 0; |
| } |
| else |
| { |
| // this should never happen. |
| diffBetSeekPointAfterAndTarget = delta; |
| delta = 0; |
| } |
| |
| // modify the target NPT and set it to the closest I-frame returned by parser node. |
| if (diffBetSeekPointAfterAndTarget < diffBetSeekPointBeforeAndTarget) |
| { |
| iTargetNPT = iSeekPointAfterTargetNPT; |
| } |
| else |
| { |
| if (iSeekPointBeforeTargetNPT < curpos.iPosValue.millisec_value && iForwardReposFlag) |
| { |
| iTargetNPT = iSeekPointAfterTargetNPT; |
| iForwardReposFlag = false; |
| } |
| else |
| { |
| iTargetNPT = iSeekPointBeforeTargetNPT; |
| iForwardReposFlag = false; |
| } |
| } |
| if (iBackwardReposFlag) // To avoid backwardlooping :: A flag to remember backward repositioning |
| { |
| iTargetNPT = iSeekPointBeforeTargetNPT; |
| iBackwardReposFlag = false; |
| } |
| |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, |
| "PVPlayerEngine::CalculateActualPlaybackPosition()" |
| "targetNPT %d Current NPT %d, Modified Target NPT %d, SeekPointBeforeTargetNPT %d, SeekPointAfterTargetNPT %d ", |
| iCurrentBeginPosition.iPosValue.millisec_value, curpos.iPosValue.millisec_value, iTargetNPT, iSeekPointBeforeTargetNPT, iSeekPointAfterTargetNPT)); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::CalculateActualPlaybackPosition Out")); |
| } |
| |
| void PVPlayerEngine::HandleSourceNodeSetDataSourcePositionDuringPlayback(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePositionDuringPlayback() In")); |
| |
| if (aNodeResp.GetCmdStatus() != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePositionDuringPlayback() SetDataSourcePosition failed. Playback position change has been cancelled")); |
| |
| if (aNodeResp.GetCmdStatus() == PVMFErrNotSupported || aNodeResp.GetCmdStatus() == PVMFErrArgument) |
| { |
| PVPPlaybackPosition curpos; |
| curpos.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| GetPlaybackClockPosition(curpos); |
| uint32 clockcurpos = 0; |
| bool tmpbool = false; |
| iPlaybackClock.GetCurrentTime32(clockcurpos, tmpbool, PVMF_MEDIA_CLOCK_MSEC); |
| |
| // since repositioning is not supported continue playing from current position. |
| iWatchDogTimerInterval = 0; |
| iActualNPT = curpos.iPosValue.millisec_value; |
| iActualMediaDataTS = clockcurpos; |
| iSkipMediaDataTS = clockcurpos; |
| |
| iStartNPT = iActualNPT; |
| iStartMediaDataTS = iSkipMediaDataTS; |
| |
| // also decrement the stream id as no skip will be called on MIO node. |
| --iStreamID; |
| |
| // For non-fatal error, continue playback by resuming the clock |
| StartPlaybackClock(); |
| // Complete the SetPlaybackRange() command as notsupported / failed |
| EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, aNodeResp.GetCmdStatus()); |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePositionDuringPlayback() failed, Add EH command")); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePositionDuringPlayback() Already EH pending, should never happen")); |
| return; |
| } |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aNodeResp.GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface())); |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = aNodeResp.GetCmdStatus(); |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_SET_PLAYBACK_RANGE, NULL, NULL, NULL, false); |
| } |
| return; |
| } |
| |
| if ((iCurrentBeginPosition.iMode != PVPPBPOS_MODE_END_OF_CURRENT_PLAY_ELEMENT) && |
| (iCurrentBeginPosition.iMode != PVPPBPOS_MODE_END_OF_CURRENT_PLAY_SESSION)) |
| { |
| if (iCurrentBeginPosition.iPosUnit == PVPPBPOSUNIT_PLAYLIST) |
| { |
| iActualMediaDataTS = iDataSourcePosParams.iActualMediaDataTS; |
| iActualNPT = iDataSourcePosParams.iActualNPT; |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePositionDuringPlayback() SetDataSourcePosition() successful. StartMediaTS %d ms, ActualPBPos %d ms", |
| iActualMediaDataTS, iActualNPT)); |
| |
| if (iCurrentBeginPosition.iPosUnit == PVPPBPOSUNIT_PLAYLIST) |
| { |
| if (iTargetNPT >= iActualNPT) |
| { |
| iWatchDogTimerInterval = iTargetNPT - iActualNPT; |
| } |
| } |
| // Compute the difference between actualNPT and targetNPT before any adjustments |
| else if (iTargetNPT >= iActualNPT) |
| { |
| iWatchDogTimerInterval = iTargetNPT - iActualNPT; |
| } |
| |
| //iCurrentBeginPosition.iPosUnit has served its purpose, it is ok if it is overwritten |
| if (iSkipToRequestedPosition && (iActualNPT < iTargetNPT)) |
| { |
| if (iTargetNPT - iActualNPT >= iNodeDataQueuingTimeout) |
| { |
| // Can't adjust the skip time back so use the returned values to skip to |
| iSkipMediaDataTS = iActualMediaDataTS; |
| iTargetNPT = iActualNPT; |
| iWatchDogTimerInterval = 0; |
| } |
| else |
| { |
| //check if source node wants to override |
| uint32 startNPTFrmSource = iActualNPT; |
| if (iSourceNodePBCtrlIF->ComputeSkipTimeStamp(iTargetNPT, |
| iActualNPT, |
| iActualMediaDataTS, |
| iSkipMediaDataTS, |
| startNPTFrmSource) == PVMFSuccess) |
| { |
| iWatchDogTimerInterval = startNPTFrmSource - iActualNPT; |
| iActualNPT = startNPTFrmSource; |
| } |
| else |
| { |
| // Adjust the media data time to skip-to to correspond to the requested time |
| // Add the difference of target NPT with actual playback position in NPT to the actual media data time to get time to skip to. |
| iSkipMediaDataTS = iActualMediaDataTS + (iTargetNPT - iActualNPT); |
| // Set the actual playback position to the requested time since actual media data TS was adjusted |
| // This is important since the difference between the two is used to calculate the NPT to media data offset in HandleSinkNodeskipMediaDataDuringPlayback() |
| iActualNPT = iTargetNPT; |
| } |
| |
| } |
| iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| } |
| else |
| { |
| // Can't adjust the skip time back so just use the returned values to skip to |
| iSkipMediaDataTS = iActualMediaDataTS; |
| iTargetNPT = iActualNPT; |
| iCurrentBeginPosition.iPosValue.millisec_value = iActualNPT; |
| iCurrentBeginPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| iWatchDogTimerInterval = 0; |
| } |
| |
| uint32 clockcurpos = 0; |
| bool tmpbool; |
| // Get current playback clock position |
| iPlaybackClock.GetCurrentTime32(clockcurpos, tmpbool, PVMF_MEDIA_CLOCK_MSEC); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePositionDuringPlayback() After adjustment StartMediaTS %d ms, AdjustedMediaTS %d ms, ActualPBPos %d ms Clock %d ms", |
| iActualMediaDataTS, iSkipMediaDataTS, iActualNPT, clockcurpos)); |
| |
| // Repositioning so reset the EOS flag for each active datapath |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath) |
| { |
| iDatapathList[i].iEndOfDataReceived = false; |
| } |
| } |
| |
| PVMFStatus retval = DoSinkNodeSkipMediaDataDuringPlayback(aNodeContext.iCmdId, aNodeContext.iCmdContext); |
| if (retval != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePositionDuringPlayback() Skipping media data request in sink nodes failed. Repositioning did not complete.")); |
| |
| // clear the pending direction change NPT. |
| iChangeDirectionNPT.iIndeterminate = true; |
| |
| // Complete the SetPlaybackRange() command as failed |
| EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, retval); |
| } |
| } |
| else |
| { |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aNodeResp.GetEventExtensionInterface() != NULL) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface())); |
| } |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| PVMFBasicErrorInfoMessage* errmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSource, puuid, nextmsg)); |
| |
| // Complete the SetPlaybackRange() command as Success |
| EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, aNodeResp.GetCmdStatus(), OSCL_STATIC_CAST(PVInterface*, errmsg)); |
| if (errmsg) |
| { |
| errmsg->removeRef(); |
| errmsg = NULL; |
| } |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeSetDataSourcePositionDuringPlayback() Out")); |
| } |
| |
| void PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() for %s Tick=%d", |
| aNodeContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() for %s, iNumPVMFInfoStartOfDataPending=%d", |
| aNodeContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr(), iNumPVMFInfoStartOfDataPending)); |
| |
| if (aNodeResp.GetCmdStatus() != PVMFSuccess) |
| { |
| // Sink node report error with SkipMediaData() |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() Sink node report error for SkipMediaData(). Asserting")); |
| OSCL_ASSERT(false); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() In %s", aNodeContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr())); |
| |
| // Stop the sink that has reached the skipping end point until other sinks are ready |
| if (aNodeContext.iEngineDatapath->iDatapath && aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF) |
| { |
| aNodeContext.iEngineDatapath->iSinkNodeSyncCtrlIF->ClockStopped(); |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() Datapath does not exist or sync control IF not available.")); |
| } |
| |
| --iNumPendingSkipCompleteEvent; |
| |
| --iNumPendingNodeCmd; |
| |
| if (iNumPendingNodeCmd == 0) |
| { |
| // Set the clock to the specified begin time just before Start of playback Clock |
| iPlaybackClock.Stop(); |
| bool overflow = 0; |
| iPlaybackClock.SetStartTime32(iSkipMediaDataTS, PVMF_MEDIA_CLOCK_MSEC, overflow); |
| |
| if (iOverflowFlag) |
| { |
| iOverflowFlag = false; |
| iActualNPT = iSkipMediaDataTS; |
| } |
| if ((iNumPVMFInfoStartOfDataPending == 0) && |
| (iState == PVP_ENGINE_STATE_STARTED)) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() Skipping WatchDogTimer - Starting PlayBackClock")); |
| StartPlaybackClock(); |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() Setting WatchDogTimer for %d ms, TargetNPT=%d ActualNPT=%d, if interval zero set to default 1 second", |
| iWatchDogTimerInterval, iTargetNPT, iActualNPT)); |
| // There can be a case in which WatchDogTimerInterval is zero and iNumPVMFInfoStartOfDataPending is greater than zero. |
| // In this case it is possible InfoStartofData is not sent by Sink Nodes for some time and player hangs. To avoid the player hang |
| // set the watchdog timer Interval to the default value of 1 second. If interval is 0, it will be set to default 1 second. |
| iWatchDogTimer->setTimerDuration(iWatchDogTimerInterval); |
| iWatchDogTimer->Start(); |
| } |
| |
| // Set the actual playback position to the requested time since actual media data TS was adjusted |
| // This is important since the difference between the two is used to calculate the NPT to media data offset |
| // This is not required here as the ActualPlaybackPosition is already adjusted before calling Skip on Sink Node. |
| // iActualNPT=iCurrentBeginPosition.iPosValue.millisec_value; |
| |
| //clear the pending direction change NPT. |
| iChangeDirectionNPT.iIndeterminate = true; |
| // Save the start NPT and TS |
| iStartNPT = iActualNPT; |
| iStartMediaDataTS = iSkipMediaDataTS; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() TargetNPT %d, ActualNPT %d StartTS %d", |
| iTargetNPT, iStartNPT, iStartMediaDataTS)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() TargetNPT %d, ActualNPT %d StartTS %d", |
| iTargetNPT, iStartNPT, iStartMediaDataTS)); |
| |
| // Send event to the observer indicating start of data |
| if (iDataSourcePosParams.iMode == PVMF_SET_DATA_SOURCE_POSITION_MODE_NOW) |
| { |
| /* Reset */ |
| iDataSourcePosParams.iActualMediaDataTS = 0; |
| iDataSourcePosParams.iActualNPT = 0; |
| iDataSourcePosParams.iMode = PVMF_SET_DATA_SOURCE_POSITION_MODE_UNKNOWN; |
| iDataSourcePosParams.iPlayElementIndex = -1; |
| iDataSourcePosParams.iSeekToSyncPoint = true; |
| iDataSourcePosParams.iTargetNPT = 0; |
| SendInformationalEvent(PVMFInfoStartOfData); |
| } |
| |
| // send the actual playback position from where playback will resume after reposition. |
| PVPPlaybackPosition actualPlaybackPosition; |
| actualPlaybackPosition.iPosValue.millisec_value = iStartNPT; |
| actualPlaybackPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| PVMFBasicErrorInfoMessage* infomsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoPlaybackFromBeginTime, puuid, NULL)); |
| SendInformationalEvent(PVMFInfoActualPlaybackPosition, OSCL_STATIC_CAST(PVInterface*, infomsg), (OsclAny*)&actualPlaybackPosition); |
| infomsg->removeRef(); |
| |
| // Complete the SetPlaybackRange() or SetPlaybackRate() |
| EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess); |
| } |
| |
| if ((iNumPendingSkipCompleteEvent == 0) && (iNumPVMFInfoStartOfDataPending == 0)) |
| { |
| if (iWatchDogTimer->IsBusy()) |
| { |
| iWatchDogTimer->Cancel(); |
| } |
| // we have received all the bos event for |
| // playback hasnt started yet |
| |
| StartPlaybackClock(); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback - PlayClock Started")); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeSkipMediaDataDuringPlayback() Out")); |
| } |
| |
| |
| void PVPlayerEngine::HandleSourceNodePause(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodePause() In")); |
| |
| switch (aNodeResp.GetCmdStatus()) |
| { |
| case PVMFSuccess: |
| { |
| // Pause command is complete |
| SetEngineState(PVP_ENGINE_STATE_PAUSED); |
| EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess); |
| } |
| break; |
| |
| default: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodePause() failed, Add EH command")); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodePause() Already EH pending, should never happen")); |
| return; |
| } |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aNodeResp.GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface())); |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = aNodeResp.GetCmdStatus(); |
| |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PAUSE, NULL, NULL, NULL, false); |
| } |
| 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 Skip on Sink Node and Start on datapaths back to back. This is done to make sure that |
| // sink node is started only after discarding the data from an earlier stream. |
| if (iChangePlaybackPositionWhenResuming || iChangePlaybackDirectionWhenResuming) |
| { |
| PVMFStatus cmdstatus = DoSinkNodeSkipMediaData(aNodeContext.iCmdId, aNodeContext.iCmdContext); |
| if (cmdstatus != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeResume() Skip of sink node did a leave, asserting")); |
| OSCL_ASSERT(false); |
| } |
| } |
| // Issue start to all active datapaths |
| iNumPendingDatapathCmd = 0; |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath) |
| { |
| PVMFStatus retval = DoDatapathStart(iDatapathList[i], aNodeContext.iCmdId, aNodeContext.iCmdContext); |
| if (retval == PVMFSuccess) |
| { |
| ++iNumPendingDatapathCmd; |
| cmdstatus = PVMFSuccess; |
| } |
| else |
| { |
| cmdstatus = retval; |
| break; |
| } |
| } |
| } |
| |
| if (iNumPendingDatapathCmd == 0) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeResume() Already EH pending, should never happen")); |
| return; |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeResume() Report command as failed, Add EH command")); |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME, NULL, NULL, NULL, false); |
| } |
| } |
| break; |
| |
| default: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeResume() failed, Add EH command")); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeResume() Already EH pending, should never happen")); |
| return; |
| } |
| cmdstatus = aNodeResp.GetCmdStatus(); |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aNodeResp.GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface())); |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME, NULL, NULL, NULL, false); |
| } |
| 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 = PVMFFailure; |
| |
| switch (aNodeResp.GetCmdStatus()) |
| { |
| case PVMFSuccess: |
| { |
| // Issue teardown sequence to all active datapaths |
| iNumPendingDatapathCmd = 0; |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath) |
| { |
| PVMFStatus retval = DoDatapathTeardown(iDatapathList[i], aNodeContext.iCmdId, aNodeContext.iCmdContext); |
| if (retval == PVMFSuccess) |
| { |
| ++iNumPendingDatapathCmd; |
| cmdstatus = PVMFSuccess; |
| } |
| else |
| { |
| cmdstatus = retval; |
| break; |
| } |
| } |
| } |
| } |
| |
| if (iNumPendingDatapathCmd == 0) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeStop() Already EH pending, should never happen")); |
| return; |
| } |
| // No active datapath to shutdown - not possible in stop |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeStop() Datapath Teardown failed, Add EH command")); |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_STOP, NULL, NULL, NULL, false); |
| } |
| break; |
| |
| default: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeStop() Source node stop failed, go in error handling, Add EH command")); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeStop() Already EH pending, should never happen")); |
| return; |
| } |
| cmdstatus = aNodeResp.GetCmdStatus(); |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aNodeResp.GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface())); |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_STOP, NULL, NULL, NULL, false); |
| } |
| break; |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeStop() Out")); |
| } |
| |
| |
| void PVPlayerEngine::HandleSourceNodeReset(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeReset() In")); |
| |
| PVMFStatus cmdstatus = PVMFErrNotSupported; |
| |
| if (aNodeResp.GetCmdStatus() == PVMFSuccess) |
| { |
| if (iSourceNode->GetState() != EPVMFNodeIdle) |
| { |
| // when reset completes on Source node, source node should be in Idle State, |
| // If not then just assert. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeReset() Source Node not in a idle state after reset, Asserting")); |
| OSCL_ASSERT(false); |
| } |
| |
| PVMFStatus status = PVMFFailure; |
| status = iSourceNode->ThreadLogoff(); |
| if (status != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoEngineDatapathTeardown() Threadlogoff on SourceNode Failed")); |
| OSCL_ASSERT(false); |
| } |
| |
| if (iSourceNode->GetState() != EPVMFNodeCreated) |
| { |
| // when reset completes on Source node, source node should be in Idle State, |
| // If not then just assert. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeReset() Source Node not in a created state after threadlogoff, Asserting")); |
| OSCL_ASSERT(false); |
| } |
| |
| // Reset active datapaths |
| if (!iDatapathList.empty()) |
| { |
| iNumPendingDatapathCmd = 0; |
| PVMFCommandId cmdid = -1; |
| int32 leavecode = 0; |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if ((iDatapathList[i].iDatapath != NULL) && |
| (iDatapathList[i].iTrackInfo != NULL) && |
| (iDatapathList[i].iDatapath->iState != PVPDP_IDLE)) |
| { |
| PVMFStatus retval = DoDatapathReset(iDatapathList[i], aNodeContext.iCmdId, aNodeContext.iCmdContext); |
| if (retval == PVMFSuccess) |
| { |
| ++iNumPendingDatapathCmd; |
| cmdstatus = PVMFSuccess; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeReset() Reset failed, Asserting")); |
| OSCL_ASSERT(false); |
| break; |
| } |
| } |
| else if (iDatapathList[i].iDecNode != NULL) |
| { |
| // This happens in case of error during prepare, when datapaths have not yet |
| // been fully constructed. |
| // reset the decoder node during inteligent track selection |
| // Call Reset() on the decoder node |
| PVPlayerEngineContext* context = AllocateEngineContext(&(iDatapathList[i]), iDatapathList[i].iDecNode, NULL, aNodeContext.iCmdId, aNodeContext.iCmdContext, PVP_CMD_DecNodeReset); |
| |
| leavecode = IssueDecNodeReset(iDatapathList[i].iDecNode, iDatapathList[i].iDecNodeSessionId, (OsclAny*) context, cmdid); |
| |
| if (cmdid != -1 && leavecode == 0) |
| { |
| ++iNumPendingDatapathCmd; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeReset() Reset on dec node leaved, asserting")); |
| FreeEngineContext(context); |
| OSCL_ASSERT(false); |
| } |
| } |
| else if (iDatapathList[i].iSinkNode != NULL) |
| { |
| // This happens in case of error during prepare, when datapaths have not yet |
| // been fully constructed. |
| // reset the sink node during inteligent track selection |
| // Call Reset() on the sink node |
| PVPlayerEngineContext* context = AllocateEngineContext(&(iDatapathList[i]), iDatapathList[i].iSinkNode, NULL, aNodeContext.iCmdId, aNodeContext.iCmdContext, PVP_CMD_SinkNodeReset); |
| |
| leavecode = IssueSinkNodeReset(&(iDatapathList[i]), (OsclAny*) context, cmdid); |
| |
| if (cmdid != -1 && leavecode == 0) |
| { |
| ++iNumPendingDatapathCmd; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeReset() Reset on sink node leaved, asserting")); |
| FreeEngineContext(context); |
| OSCL_ASSERT(false); |
| } |
| } |
| else |
| { |
| // No Sink nodes and no datapaths created yet so just do Enginedatapath Teardown. |
| DoEngineDatapathTeardown(iDatapathList[i]); |
| } |
| } |
| |
| if (iNumPendingDatapathCmd == 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeReset() Reset on SourceNode completed and no datapath or sink node to reset.")); |
| // Reset on source node is complete and there are no datapaths or sink nodes to reset, |
| // now need to remove the data sinks and sources |
| // so schedule engine AO - we cannnot delete datapaths in callback, hence the reschedule |
| SetEngineState(PVP_ENGINE_STATE_IDLE); |
| RunIfNotReady(); |
| } |
| } |
| else |
| { |
| // Reset on source node is complete and there are no datapaths or sink nodes to reset, |
| // now need to remove the data sinks and sources |
| // so schedule engine AO - we cannnot delete datapaths in callback, hence the reschedule |
| SetEngineState(PVP_ENGINE_STATE_IDLE); |
| RunIfNotReady(); |
| } |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeReset() Reset failed on Source Node, Asserting")); |
| OSCL_ASSERT(false); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeReset() Out")); |
| } |
| |
| |
| void PVPlayerEngine::HandleSinkNodePause(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodePause() In %s", aNodeContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr())); |
| |
| // Decrement the counter for pending cmds |
| --iNumPendingDatapathCmd; |
| |
| if (aNodeResp.GetCmdStatus() != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodePause() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| // Cancel any pending node/datapath commands |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodePause() Failed, Add EH command")); |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aNodeResp.GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface())); |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSinkFatal, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = aNodeResp.GetCmdStatus(); |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PAUSE, NULL, NULL, NULL, false); |
| } |
| |
| return; |
| } |
| |
| if (iNumPendingDatapathCmd == 0) |
| { |
| // Auto-pause is complete |
| SetEngineState(PVP_ENGINE_STATE_AUTO_PAUSED); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodePause() Report command as success")); |
| EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodePause() Out")); |
| } |
| |
| |
| void PVPlayerEngine::HandleSinkNodeResume(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeResume() In %s", aNodeContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr())); |
| |
| // Decrement the counter for pending cmds |
| --iNumPendingDatapathCmd; |
| |
| if (aNodeResp.GetCmdStatus() != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeResume() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| // Cancel any pending node/datapath commands |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeResume() Failed, Add EH command")); |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aNodeResp.GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aNodeResp.GetEventExtensionInterface())); |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSinkFatal, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = aNodeResp.GetCmdStatus(); |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME, NULL, NULL, NULL, false); |
| } |
| return; |
| } |
| |
| if (iNumPendingDatapathCmd == 0) |
| { |
| // Auto-resume is complete |
| // Resume the playback clock only if InfoStartofData has been received for all tracks. |
| // If SetPlaybackRange is called in Auto-Pause state, its possible that engine is waiting for InfoStartofData. |
| // If waiting, restart the watchdog timer which was cancelled in Auto-Pause command. |
| // this should only be done when engine is waiting for StartofData info event |
| // after reposition. If already busy after SetPlaybackRange command complete, |
| // then cancel it and start again. Playback clock will be started in either HandleSinkNodeInfoEvent or |
| // PVPlayerWatchdogTimerEvent |
| if (iNumPVMFInfoStartOfDataPending > 0) |
| { |
| if (iWatchDogTimerInterval > 0) |
| { |
| if (iWatchDogTimer->IsBusy()) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleSinkNodeResume - Pause after setplayback, Cancelling Watchdog timer, iNumPVMFInfoStartOfDataPending=%d", iNumPVMFInfoStartOfDataPending)); |
| iWatchDogTimer->Cancel(); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleSinkNodeResume Setting WatchDogTimer for %d ms, iNumPVMFInfoStartOfDataPending=%d", |
| iWatchDogTimerInterval, iNumPVMFInfoStartOfDataPending)); |
| iWatchDogTimer->setTimerDuration(iWatchDogTimerInterval); |
| iWatchDogTimer->Start(); |
| } |
| } |
| // Auto-resume is complete & not waiting on PVMFInfoStartOfData, so go ahead and |
| // start the clock |
| if (iNumPVMFInfoStartOfDataPending == 0) |
| { |
| StartPlaybackClock(); |
| |
| // Notify data sinks that clock has started |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath && iDatapathList[i].iSinkNodeSyncCtrlIF) |
| { |
| iDatapathList[i].iSinkNodeSyncCtrlIF->ClockStarted(); |
| } |
| } |
| } |
| |
| SetEngineState(PVP_ENGINE_STATE_STARTED); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeResume() Report command as success")); |
| EngineCommandCompleted(aNodeContext.iCmdId, aNodeContext.iCmdContext, PVMFSuccess); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeResume() Out")); |
| } |
| |
| void PVPlayerEngine::HandleSinkNodeReset(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| OSCL_ASSERT(aNodeContext.iEngineDatapath != NULL); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeReset() In")); |
| |
| // Decrement the counter for pending cmds |
| --iNumPendingDatapathCmd; |
| |
| if (aNodeResp.GetCmdStatus() != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSinkNodeReset() Reset failed, assert")); |
| OSCL_ASSERT(false); |
| return; |
| } |
| else |
| { |
| // Reset for this sink node is complete |
| //a sync call in engine - no async cmds issued here |
| DoEngineDatapathTeardown(*(aNodeContext.iEngineDatapath)); |
| } |
| |
| if (iNumPendingDatapathCmd == 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSinkNodeReset() Reset on SourceNode and Sink nodes completed")); |
| // Reset on source node and sink node is complete, now need to remove the data sinks and sources |
| // so schedule engine AO - we cannnot delete datapaths in callback, hence the reschedule |
| SetEngineState(PVP_ENGINE_STATE_IDLE); |
| RunIfNotReady(); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeReset() Out")); |
| } |
| |
| void PVPlayerEngine::HandleDecNodeReset(PVPlayerEngineContext& aNodeContext, const PVMFCmdResp& aNodeResp) |
| { |
| OSCL_ASSERT(aNodeContext.iEngineDatapath != NULL); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeReset() In")); |
| |
| // Decrement the counter for pending cmds |
| --iNumPendingDatapathCmd; |
| |
| if (aNodeResp.GetCmdStatus() != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleDecNodeReset() Reset failed, assert")); |
| OSCL_ASSERT(false); |
| return; |
| } |
| |
| if (iNumPendingDatapathCmd == 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleDecNodeReset() Reset on SourceNode and dec nodes completed, now reset Sink nodes")); |
| // Reset on source node and dec node is complete, now need to reset the sink nodes |
| if (!iDatapathList.empty()) |
| { |
| iNumPendingDatapathCmd = 0; |
| PVMFCommandId cmdid = -1; |
| int32 leavecode = 0; |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iSinkNode != NULL) |
| { |
| // This happens in case of error during prepare, when datapaths have not yet |
| // been fully constructed. |
| // reset the sink node during inteligent track selection |
| // Call Reset() on the sink node |
| PVPlayerEngineContext* context = AllocateEngineContext(&(iDatapathList[i]), iDatapathList[i].iSinkNode, NULL, aNodeContext.iCmdId, aNodeContext.iCmdContext, PVP_CMD_SinkNodeReset); |
| |
| leavecode = IssueSinkNodeReset(&(iDatapathList[i]), (OsclAny*) context, cmdid); |
| |
| if (cmdid != -1 && leavecode == 0) |
| { |
| ++iNumPendingDatapathCmd; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDecNodeReset() Reset on sink node leaved, asserting")); |
| FreeEngineContext(context); |
| OSCL_ASSERT(false); |
| } |
| } |
| } |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeReset() Out")); |
| } |
| |
| void PVPlayerEngine::HandleDatapathPrepare(PVPlayerEngineContext& aDatapathContext, PVMFStatus aDatapathStatus, PVMFCmdResp* aCmdResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleDatapathPrepare() for %s Tick=%d", |
| aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathPrepare() In %s", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr())); |
| |
| // Decrement the counter for pending datapath cmds |
| --iNumPendingDatapathCmd; |
| |
| if (aDatapathStatus != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathPrepare() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| // Cancel any pending node/datapath commands |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleDatapathPrepare() In %s Failed, Add EH command", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr())); |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aCmdResp) |
| { |
| if (aCmdResp->GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aCmdResp->GetEventExtensionInterface())); |
| } |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathFatal, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = aDatapathStatus; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| } |
| return; |
| } |
| |
| if (iNumPendingDatapathCmd == 0) |
| { |
| // Reposition and/or start the source node |
| PVMFStatus cmdstatus = DoSourceNodeQueryDataSourcePosition(aDatapathContext.iCmdId, aDatapathContext.iCmdContext); |
| if (cmdstatus != PVMFSuccess) |
| { |
| // Setting position not supported so start the source node |
| cmdstatus = DoSourceNodeStart(aDatapathContext.iCmdId, aDatapathContext.iCmdContext); |
| } |
| |
| if (cmdstatus != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathPrepare() Report command as failed, Add EH command")); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathPrepare() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| } |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathPrepare() Out")); |
| } |
| |
| |
| void PVPlayerEngine::HandleDatapathStart(PVPlayerEngineContext& aDatapathContext, PVMFStatus aDatapathStatus, PVMFCmdResp* aCmdResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleDatapathStart() for %s Tick=%d", |
| aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathStart() In %s", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr())); |
| |
| // Decrement the counter for pending datapath cmds |
| --iNumPendingDatapathCmd; |
| |
| if (aDatapathStatus != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathStart() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| // Cancel any pending node/datapath commands |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleDatapathStart() In %s Failed, Add EH command", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr())); |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aCmdResp) |
| { |
| if (aCmdResp->GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aCmdResp->GetEventExtensionInterface())); |
| } |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathFatal, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = aDatapathStatus; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE, NULL, NULL, NULL, false); |
| } |
| return; |
| } |
| |
| if (iNumPendingDatapathCmd == 0) |
| { |
| // This should never be happen if Skip on sink node has not completed (i.e. iNumPendingSkipCompleteEvent |
| // is greater than zero). If this happens with iNumPendingSkipCompleteEvent > 0 then just assert. |
| // Set the clock to the specified begin time just before Start of playback Clock |
| iPlaybackClock.Stop(); |
| bool overflow = 0; |
| iPlaybackClock.SetStartTime32(iSkipMediaDataTS, PVMF_MEDIA_CLOCK_MSEC, overflow); |
| |
| if (!(iWatchDogTimer->IsBusy())) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleDatapathStart() Setting WatchDogTimer for %d ms, TargetNPT=%d ActualNPT=%d, if interval zero set to default 1 second", |
| iWatchDogTimerInterval, iTargetNPT, iActualNPT)); |
| iWatchDogTimer->setTimerDuration(iWatchDogTimerInterval); |
| iWatchDogTimer->Start(); |
| } |
| // Set the actual playback position to the requested time since actual media data TS was adjusted |
| // This is important since the difference between the two is used to calculate the NPT to media data offset |
| // This is not required here as the ActualPlaybackPosition is already adjusted before calling Skip on Sink Node. |
| // iActualNPT=iCurrentBeginPosition.iPosValue.millisec_value; |
| |
| // Save the start NPT and TS |
| iStartNPT = iActualNPT; |
| iStartMediaDataTS = iSkipMediaDataTS; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleDatapathStart() TargetNPT %d, StartNPT %d StartTS %d", |
| iTargetNPT, iStartNPT, iStartMediaDataTS)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleDatapathStart() TargetNPT %d, StartNPT %d StartTS %d", |
| iTargetNPT, iStartNPT, iStartMediaDataTS)); |
| |
| SetEngineState(PVP_ENGINE_STATE_PREPARED); |
| |
| // send the actual playback position from where playback will resume after reposition. |
| PVPPlaybackPosition actualPlaybackPosition; |
| actualPlaybackPosition.iPosValue.millisec_value = iStartNPT; |
| actualPlaybackPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| PVMFBasicErrorInfoMessage* infomsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoPlaybackFromBeginTime, puuid, NULL)); |
| SendInformationalEvent(PVMFInfoActualPlaybackPosition, OSCL_STATIC_CAST(PVInterface*, infomsg), (OsclAny*)&actualPlaybackPosition); |
| infomsg->removeRef(); |
| |
| EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, PVMFSuccess); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathStart() Out")); |
| } |
| |
| |
| void PVPlayerEngine::HandleDatapathPause(PVPlayerEngineContext& aDatapathContext, PVMFStatus aDatapathStatus, PVMFCmdResp* aCmdResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleDatapathPause() for %s Tick=%d", |
| aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathPause() In %s", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr())); |
| |
| // Decrement the counter for pending datapath cmds |
| --iNumPendingDatapathCmd; |
| |
| if (aDatapathStatus != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathPause() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| // Cancel any pending node/datapath commands |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleDatapathPause() In %s Failed, Add EH command", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr())); |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aCmdResp) |
| { |
| if (aCmdResp->GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aCmdResp->GetEventExtensionInterface())); |
| } |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathFatal, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = aDatapathStatus; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PAUSE, NULL, NULL, NULL, false); |
| } |
| return; |
| } |
| |
| if (iNumPendingDatapathCmd == 0) |
| { |
| // Continue on by pauseing the source node |
| PVMFStatus cmdstatus = DoSourceNodePause(aDatapathContext.iCmdId, aDatapathContext.iCmdContext); |
| |
| if (cmdstatus != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathPause() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathPause() Report command as failed, Add EH command")); |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_PAUSE, NULL, NULL, NULL, false); |
| } |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathPause() Out")); |
| } |
| |
| |
| void PVPlayerEngine::HandleDatapathResume(PVPlayerEngineContext& aDatapathContext, PVMFStatus aDatapathStatus, PVMFCmdResp* aCmdResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleDatapathResume() for %s Tick=%d", |
| aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathResume() In %s", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr())); |
| |
| // Decrement the counter for pending datapath cmds |
| --iNumPendingDatapathCmd; |
| |
| if (aDatapathStatus != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathResume() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleDatapathResume() In %s Failed, Add EH command", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr())); |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aCmdResp) |
| { |
| if (aCmdResp->GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aCmdResp->GetEventExtensionInterface())); |
| } |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathFatal, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = aDatapathStatus; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_STOP, NULL, NULL, NULL, false); |
| } |
| return; |
| } |
| |
| if (iNumPendingDatapathCmd == 0) |
| { |
| if (iChangePlaybackPositionWhenResuming || iChangePlaybackDirectionWhenResuming) |
| { |
| // This should never be happen if Skip on sink node has not completed (i.e. iNumPendingSkipCompleteEvent |
| // is greater than zero). If this happens with iNumPendingSkipCompleteEvent > 0 then just assert. |
| // Set the clock to the specified begin time just before Start of playback Clock |
| iPlaybackClock.Stop(); |
| bool overflow = 0; |
| iPlaybackClock.SetStartTime32(iSkipMediaDataTS, PVMF_MEDIA_CLOCK_MSEC, overflow); |
| |
| if (iNumPVMFInfoStartOfDataPending == 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleDatapathResume() Skipping WatchDogTimer - Starting PlayBackClock")); |
| StartPlaybackClock(); |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleDatapathResume() Setting WatchDogTimer for %d ms, TargetNPT=%d ActualNPT=%d", |
| iWatchDogTimerInterval, iTargetNPT, iActualNPT)); |
| |
| // There can be a case in which WatchDogTimerInterval is zero and iNumPVMFInfoStartOfDataPending is greater than zero. |
| // In this case it is possible InfoStartofData is not sent by Sink Nodes for some time and player hangs. To avoid the player hang |
| // set the watchdog timer Interval to the default value of 1 second. |
| iWatchDogTimer->setTimerDuration(iWatchDogTimerInterval); |
| iWatchDogTimer->Start(); |
| } |
| |
| // Set the actual playback position to the requested time since actual media data TS was adjusted |
| // This is important since the difference between the two is used to calculate the NPT to media data offset |
| // This is not required here as the ActualPlaybackPosition is already adjusted before calling Skip on Sink Node. |
| // iActualNPT=iCurrentBeginPosition.iPosValue.millisec_value; |
| |
| //clear the pending direction change NPT. |
| iChangeDirectionNPT.iIndeterminate = true; |
| // Save the start NPT and TS |
| iStartNPT = iActualNPT; |
| iStartMediaDataTS = iSkipMediaDataTS; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleDatapathResume() TargetNPT %d, ActualNPT %d StartTS %d", |
| iTargetNPT, iStartNPT, iStartMediaDataTS)); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleDatapathResume() TargetNPT %d, ActualNPT %d StartTS %d", |
| iTargetNPT, iStartNPT, iStartMediaDataTS)); |
| |
| // send the actual playback position from where playback will resume after reposition. |
| PVPPlaybackPosition actualPlaybackPosition; |
| actualPlaybackPosition.iPosValue.millisec_value = iStartNPT; |
| actualPlaybackPosition.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| PVMFBasicErrorInfoMessage* infomsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoPlaybackFromBeginTime, puuid, NULL)); |
| SendInformationalEvent(PVMFInfoActualPlaybackPosition, OSCL_STATIC_CAST(PVInterface*, infomsg), (OsclAny*)&actualPlaybackPosition); |
| infomsg->removeRef(); |
| } |
| else |
| { |
| // Resume the playback clock - only if we have come out of any previous auto pause, if any |
| if (iPlaybackClock.GetState() == PVMFMediaClock::PAUSED) |
| { |
| StartPlaybackClock(); |
| |
| // Notify all sink nodes that have sync control IF that clock has started |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath && iDatapathList[i].iSinkNodeSyncCtrlIF) |
| { |
| iDatapathList[i].iSinkNodeSyncCtrlIF->ClockStarted(); |
| } |
| } |
| } |
| |
| // Restart the watchdog timer which was cancelled in Pause command. |
| // this should only be done when engine is waiting for StartofData info event |
| // after reposition. |
| if (iNumPVMFInfoStartOfDataPending > 0) |
| { |
| if (iWatchDogTimerInterval > 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleDatapathResume Setting WatchDogTimer for %d ms, iNumPVMFInfoStartOfDataPending=%d", |
| iWatchDogTimerInterval, iNumPVMFInfoStartOfDataPending)); |
| iWatchDogTimer->setTimerDuration(iWatchDogTimerInterval); |
| iWatchDogTimer->Start(); |
| } |
| } |
| |
| // Restart the end time check if enabled |
| if (iEndTimeCheckEnabled) |
| { |
| // Determine the check cycle based on interval setting in milliseconds |
| // and timer frequency of 100 millisec |
| int32 checkcycle = iEndTimeCheckInterval / 100; |
| if (checkcycle == 0) |
| { |
| ++checkcycle; |
| } |
| iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_ENDTIMECHECK); |
| iPollingCheckTimer->Request(PVPLAYERENGINE_TIMERID_ENDTIMECHECK, 0, checkcycle, this, true); |
| } |
| } |
| |
| SetEngineState(PVP_ENGINE_STATE_STARTED); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathResume() Report command as completed")); |
| EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, PVMFSuccess); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathResume() Out")); |
| } |
| |
| |
| void PVPlayerEngine::HandleDatapathStop(PVPlayerEngineContext& aDatapathContext, PVMFStatus aDatapathStatus, PVMFCmdResp* aCmdResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleDatapathStop() for %s Tick=%d", |
| aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathStop() In %s", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr())); |
| |
| // Decrement the counter for pending datapath cmds |
| --iNumPendingDatapathCmd; |
| |
| if (aDatapathStatus != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathStop() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleDatapathStop() In %s Failed, Add EH command", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr())); |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aCmdResp) |
| { |
| if (aCmdResp->GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aCmdResp->GetEventExtensionInterface())); |
| } |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathFatal, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = aDatapathStatus; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_STOP, NULL, NULL, NULL, false); |
| } |
| return; |
| } |
| |
| if (iNumPendingDatapathCmd == 0) |
| { |
| // Continue on by stopping the source node |
| PVMFStatus cmdstatus = DoSourceNodeStop(aDatapathContext.iCmdId, aDatapathContext.iCmdContext); |
| |
| if (cmdstatus != PVMFSuccess) |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathStop() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathStop() Report command as failed, Add EH command")); |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| iCommandCompleteStatusInErrorHandling = cmdstatus; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_STOP, NULL, NULL, NULL, false); |
| } |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathStop() Out")); |
| } |
| |
| |
| void PVPlayerEngine::HandleDatapathTeardown(PVPlayerEngineContext& aDatapathContext, PVMFStatus aDatapathStatus, PVMFCmdResp* aCmdResp) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleDatapathTeardown() for %s Tick=%d", |
| aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathTeardown() In %s", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr())); |
| |
| PVMFStatus cmdstatus; |
| |
| switch (aDatapathStatus) |
| { |
| case PVMFSuccess: |
| // Reset this datapath next |
| cmdstatus = DoDatapathReset(*(aDatapathContext.iEngineDatapath), aDatapathContext.iCmdId, aDatapathContext.iCmdContext); |
| break; |
| |
| default: |
| { |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathTeardown() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleDatapathTeardown() In %s Failed, Add EH command", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr())); |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aCmdResp) |
| { |
| if (aCmdResp->GetEventExtensionInterface()) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aCmdResp->GetEventExtensionInterface())); |
| } |
| } |
| |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathFatal, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = aDatapathStatus; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_STOP, NULL, NULL, NULL, false); |
| } |
| return; |
| } |
| } |
| |
| if (cmdstatus != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDatapathTeardown() Reset failed, asserting")); |
| OSCL_ASSERT(false); |
| EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, cmdstatus); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleVideoDatapathTeardown() Out")); |
| } |
| |
| |
| void PVPlayerEngine::HandleDatapathReset(PVPlayerEngineContext& aDatapathContext, PVMFStatus aDatapathStatus, PVMFCmdResp* aCmdResp) |
| { |
| OSCL_UNUSED_ARG(aCmdResp); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF, iPerfLogger, PVLOGMSG_INFO, |
| (0, "PVPlayerEngine::HandleDatapathReset() for %s Tick=%d", |
| aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr(), OsclTickCount::TickCount())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathReset() In %s", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr())); |
| |
| // Decrement the counter for pending datapath cmds |
| --iNumPendingDatapathCmd; |
| |
| if (aDatapathStatus != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleDatapathReset() In %s Reset failed, assert", aDatapathContext.iEngineDatapath->iTrackInfo->getTrackMimeType().get_cstr())); |
| OSCL_ASSERT(false); |
| return; |
| } |
| else |
| { |
| // Reset for this datapath is complete |
| //a sync call in engine - no async cmds issued here |
| DoEngineDatapathTeardown(*(aDatapathContext.iEngineDatapath)); |
| } |
| |
| //this means datapath reset and teardown is complete for all datapaths |
| if (iNumPendingDatapathCmd == 0) |
| { |
| if (iState == PVP_ENGINE_STATE_RESETTING) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleDatapathReset() Reset on SourceNode and Datapath completed")); |
| // Reset on source node and datapath is complete, now need to remove the data sinks and sources |
| // so schedule engine AO - we cannnot delete datapaths in callback, hence the reschedule |
| SetEngineState(PVP_ENGINE_STATE_IDLE); |
| RunIfNotReady(); |
| } |
| else if (iState == PVP_ENGINE_STATE_STOPPING) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathReset() Stop Completed")); |
| // stop has completed |
| SetEngineState(PVP_ENGINE_STATE_INITIALIZED); |
| EngineCommandCompleted(aDatapathContext.iCmdId, aDatapathContext.iCmdContext, PVMFSuccess); |
| } |
| else |
| { |
| //engine cannot be in any other state |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleDatapathReset() Wrong Engine state for Reset to complete, asserting")); |
| OSCL_ASSERT(false); |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDatapathReset() Out")); |
| } |
| |
| void PVPlayerEngine::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_ERR, (0, "PVPlayerEngine::HandleSourceNodeErrorEvent() In")); |
| |
| if (iState == PVP_ENGINE_STATE_RESETTING) |
| { |
| //this means error handling, reset or cancelall is still in progress |
| //no need to look for error event |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeErrorEvent() Return engine in resetting state no need to process the error event")); |
| return; |
| } |
| |
| for (uint32 i = 0; i < iCurrentContextList.size(); ++i) |
| { |
| if (iCurrentContextList[i]->iNode) |
| { |
| if (iCurrentContextList[i]->iNode == iSourceNode) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeErrorEvent() Cmd Pending on Source node, so src node should not send error events - ignoring err event")); |
| return; |
| } |
| } |
| } |
| |
| PVMFEventType event = aEvent.GetEventType(); |
| |
| switch (event) |
| { |
| case PVMFErrCorrupt: |
| case PVMFErrOverflow: |
| case PVMFErrResource: |
| case PVMFErrProcessing: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeErrorEvent() Sending PVPlayerErrSourceMediaData for error event %d, Add EH command if not present", event)); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeErrorEvent() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aEvent.GetEventExtensionInterface() != NULL) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aEvent.GetEventExtensionInterface())); |
| } |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceMediaData, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = event; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_GENERAL, NULL, NULL, NULL, false); |
| if (iCurrentCmd.empty()) |
| { |
| // this error was received when no cmd was being processed so send the error event from here |
| SendErrorEvent(iCommandCompleteStatusInErrorHandling, |
| OSCL_STATIC_CAST(PVInterface*, iCommandCompleteErrMsgInErrorHandling), |
| aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize()); |
| iCommandCompleteErrMsgInErrorHandling->removeRef(); |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| } |
| } |
| } |
| break; |
| |
| case PVMFErrUnderflow: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeErrorEvent() Sending PVPlayerErrSourceMediaDataUnavailable for error event %d, Add EH command if not present", event)); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeErrorEvent() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aEvent.GetEventExtensionInterface() != NULL) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aEvent.GetEventExtensionInterface())); |
| } |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceMediaDataUnavailable, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = event; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_GENERAL, NULL, NULL, NULL, false); |
| if (iCurrentCmd.empty()) |
| { |
| // this error was received when no cmd was being processed so send the error event from here |
| SendErrorEvent(iCommandCompleteStatusInErrorHandling, |
| OSCL_STATIC_CAST(PVInterface*, iCommandCompleteErrMsgInErrorHandling), |
| aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize()); |
| iCommandCompleteErrMsgInErrorHandling->removeRef(); |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| } |
| } |
| } |
| break; |
| |
| case PVMFErrNoResources: |
| case PVMFErrResourceConfiguration: |
| case PVMFErrTimeout: |
| case PVMFErrNoMemory: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeErrorEvent() Sending PVPlayerErrSourceFatal for error event %d, Add EH command if not present", event)); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSourceNodeErrorEvent() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aEvent.GetEventExtensionInterface() != NULL) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aEvent.GetEventExtensionInterface())); |
| } |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSourceFatal, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = event; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_GENERAL, NULL, NULL, NULL, false); |
| if (iCurrentCmd.empty()) |
| { |
| // this error was received when no cmd was being processed so send the error event from here |
| SendErrorEvent(iCommandCompleteStatusInErrorHandling, |
| OSCL_STATIC_CAST(PVInterface*, iCommandCompleteErrMsgInErrorHandling), |
| aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize()); |
| iCommandCompleteErrMsgInErrorHandling->removeRef(); |
| iCommandCompleteErrMsgInErrorHandling = 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_ERR, (0, "PVPlayerEngine::HandleDecNodeErrorEvent() In")); |
| |
| OSCL_UNUSED_ARG(aDatapathIndex); |
| |
| if (iState == PVP_ENGINE_STATE_RESETTING) |
| { |
| //this means error handling, reset or cancelall is still in progress |
| //no need to look for error event |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleDecNodeErrorEvent() Return engine in resetting state no need to process the error event")); |
| return; |
| } |
| |
| PVMFEventType event = aEvent.GetEventType(); |
| |
| switch (event) |
| { |
| case PVMFErrCorrupt: |
| case PVMFErrOverflow: |
| case PVMFErrUnderflow: |
| case PVMFErrProcessing: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleDecNodeErrorEvent() Sending PVPlayerErrDatapathMediaData for error event %d, Add EH command if not present", event)); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDecNodeErrorEvent() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aEvent.GetEventExtensionInterface() != NULL) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aEvent.GetEventExtensionInterface())); |
| } |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathMediaData, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = event; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_GENERAL, NULL, NULL, NULL, false); |
| if (iCurrentCmd.empty()) |
| { |
| // this error was received when no cmd was being processed so send the error event from here |
| SendErrorEvent(iCommandCompleteStatusInErrorHandling, |
| OSCL_STATIC_CAST(PVInterface*, iCommandCompleteErrMsgInErrorHandling), |
| aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize()); |
| iCommandCompleteErrMsgInErrorHandling->removeRef(); |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| } |
| } |
| } |
| break; |
| |
| case PVMFErrTimeout: |
| case PVMFErrNoResources: |
| case PVMFErrResourceConfiguration: |
| case PVMFErrResource: |
| case PVMFErrNoMemory: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleDecNodeErrorEvent() Sending PVPlayerErrDatapathFatal for error event %d, Add EH command if not present", event)); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleDecNodeErrorEvent() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aEvent.GetEventExtensionInterface() != NULL) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aEvent.GetEventExtensionInterface())); |
| } |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrDatapathFatal, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = event; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_GENERAL, NULL, NULL, NULL, false); |
| if (iCurrentCmd.empty()) |
| { |
| // this error was received when no cmd was being processed so send the error event from here |
| SendErrorEvent(iCommandCompleteStatusInErrorHandling, |
| OSCL_STATIC_CAST(PVInterface*, iCommandCompleteErrMsgInErrorHandling), |
| aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize()); |
| iCommandCompleteErrMsgInErrorHandling->removeRef(); |
| iCommandCompleteErrMsgInErrorHandling = 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_ERR, (0, "PVPlayerEngine::HandleSinkNodeErrorEvent() In")); |
| |
| OSCL_UNUSED_ARG(aDatapathIndex); |
| |
| if (iState == PVP_ENGINE_STATE_RESETTING) |
| { |
| //this means error handling, reset or cancelall is still in progress |
| //no need to look for error event |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSinkNodeErrorEvent() Return engine in resetting state no need to process the error event")); |
| return; |
| } |
| |
| PVMFEventType event = aEvent.GetEventType(); |
| |
| switch (event) |
| { |
| case PVMFErrCorrupt: |
| case PVMFErrOverflow: |
| case PVMFErrUnderflow: |
| case PVMFErrProcessing: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSinkNodeErrorEvent() Sending PVPlayerErrDatapathMediaData for error event %d, Add EH command if not present", event)); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeErrorEvent() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aEvent.GetEventExtensionInterface() != NULL) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aEvent.GetEventExtensionInterface())); |
| } |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSinkMediaData, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = event; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_GENERAL, NULL, NULL, NULL, false); |
| if (iCurrentCmd.empty()) |
| { |
| // this error was received when no cmd was being processed so send the error event from here |
| SendErrorEvent(iCommandCompleteStatusInErrorHandling, |
| OSCL_STATIC_CAST(PVInterface*, iCommandCompleteErrMsgInErrorHandling), |
| aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize()); |
| iCommandCompleteErrMsgInErrorHandling->removeRef(); |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| } |
| } |
| } |
| break; |
| |
| case PVMFErrTimeout: |
| case PVMFErrNoResources: |
| case PVMFErrResourceConfiguration: |
| case PVMFErrResource: |
| case PVMFErrNoMemory: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSinkNodeErrorEvent() Sending PVPlayerErrSinkFatal for error event %d, Add EH command if not present", event)); |
| bool ehPending = CheckForPendingErrorHandlingCmd(); |
| if (ehPending) |
| { |
| // there should be no error handling queued. |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::HandleSinkNodeErrorEvent() Already EH pending, should never happen")); |
| return; |
| } |
| else |
| { |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aEvent.GetEventExtensionInterface() != NULL) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aEvent.GetEventExtensionInterface())); |
| } |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| iCommandCompleteErrMsgInErrorHandling = OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerErrSinkFatal, puuid, nextmsg)); |
| iCommandCompleteStatusInErrorHandling = event; |
| AddCommandToQueue(PVP_ENGINE_COMMAND_ERROR_HANDLING_GENERAL, NULL, NULL, NULL, false); |
| if (iCurrentCmd.empty()) |
| { |
| // this error was received when no cmd was being processed so send the error event from here |
| SendErrorEvent(iCommandCompleteStatusInErrorHandling, |
| OSCL_STATIC_CAST(PVInterface*, iCommandCompleteErrMsgInErrorHandling), |
| aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize()); |
| iCommandCompleteErrMsgInErrorHandling->removeRef(); |
| iCommandCompleteErrMsgInErrorHandling = 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")); |
| } |
| |
| //Return val: true means found/deleted cmd(s). |
| bool PVPlayerEngine::removeCmdFromQ(Oscl_Vector<PVPlayerEngineCommand, OsclMemAllocator> &aVec, const PVPlayerEngineCommandType aCmdType, bool aRemove) |
| { |
| if (aVec.size() == 0) |
| { |
| return false; |
| } |
| // OSCL priority queue doesn't allow index access so will need to |
| // go through each pending cmd one-by-one, save commands that are not auto-resume |
| // and put the commands back into the pending queue. |
| // Vector to hold the pending cmds temporarily |
| bool ret = false; |
| Oscl_Vector<PVPlayerEngineCommand, OsclMemAllocator> tmpvec; |
| tmpvec.reserve(aVec.size()); |
| tmpvec.clear(); |
| // Go through each pending command |
| |
| for (int i = aVec.size() - 1; i >= 0; i--) |
| { |
| if (aVec[i].GetCmdType() == aCmdType) |
| { |
| ret = true; |
| if (!aRemove) |
| { |
| return ret; |
| } |
| continue; |
| } |
| tmpvec.push_back(aVec[i]); |
| } |
| aVec.clear(); |
| // Put the pending commands back in the priqueue |
| while (tmpvec.empty() == false) |
| { |
| aVec.push_front(tmpvec[0]); |
| tmpvec.erase(tmpvec.begin()); |
| } |
| return ret; |
| } |
| |
| //Return val: true means found/deleted cmd(s). |
| bool PVPlayerEngine::removeCmdFromQ(OsclPriorityQueue<PVPlayerEngineCommand, OsclMemAllocator, Oscl_Vector<PVPlayerEngineCommand, OsclMemAllocator>, PVPlayerEngineCommandCompareLess> &aVec, const PVPlayerEngineCommandType aCmdType, bool aRemove) |
| { |
| // OSCL priority queue doesn't allow index access so will need to |
| // go through each pending cmd one-by-one, save commands that are not auto-resume |
| // and put the commands back into the pending queue. |
| // Vector to hold the pending cmds temporarily |
| bool ret = false; |
| Oscl_Vector<PVPlayerEngineCommand, OsclMemAllocator> tmpvec; |
| tmpvec.reserve(aVec.size()); |
| tmpvec.clear(); |
| // Go through each pending command |
| while (aVec.empty() == false) |
| { |
| if (aVec.top().GetCmdType() == aCmdType) |
| { |
| ret = true; |
| if (!aRemove) |
| { |
| return ret; |
| } |
| aVec.pop(); |
| continue; |
| } |
| tmpvec.push_back(aVec.top()); |
| aVec.pop(); |
| } |
| // Put the pending commands back in the priqueue |
| while (tmpvec.empty() == false) |
| { |
| aVec.push(tmpvec[0]); |
| tmpvec.erase(tmpvec.begin()); |
| } |
| return ret; |
| } |
| |
| void PVPlayerEngine::HandleSourceNodeInfoEvent(const PVMFAsyncEvent& aEvent) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() In")); |
| |
| if (iState == PVP_ENGINE_STATE_RESETTING) |
| { |
| //this means error handling, reset or cancelall is still in progress |
| //no need to look for info event |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Return engine in resetting state no need to process the info event %d", aEvent.GetEventType())); |
| return; |
| } |
| |
| PVMFEventType event = aEvent.GetEventType(); |
| |
| switch (event) |
| { |
| case PVMFInfoBufferingStart: |
| case PVMFInfoBufferingComplete: |
| case PVMFInfoOverflow: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Sending buffering event %d", event)); |
| SendInformationalEvent(event, NULL, aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize()); |
| } |
| break; |
| |
| case PVMFInfoBufferingStatus: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Sending buffering status event %d", event)); |
| SendInformationalEvent(event, NULL, aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize()); |
| } |
| break; |
| |
| case PVMFInfoUnderflow: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Received PVMFInfoUnderflow")); |
| // remove pending auto-resume if there is any |
| if (removeCmdFromQ(iPendingCmds, PVP_ENGINE_COMMAND_RESUME_DUE_TO_BUFFER_DATAREADY, true)) |
| { |
| //cancelled the pending auto-resume |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() PVMFInfoUnderflow got cancelled")); |
| break; |
| } |
| |
| // if no auto-pause in the queue and no auto-pause in progress, add one |
| if ((! removeCmdFromQ(iCurrentCmd, PVP_ENGINE_COMMAND_PAUSE_DUE_TO_BUFFER_UNDERFLOW, false)) |
| && (! removeCmdFromQ(iPendingCmds, PVP_ENGINE_COMMAND_PAUSE_DUE_TO_BUFFER_UNDERFLOW, false))) |
| { |
| AddCommandToQueue(PVP_ENGINE_COMMAND_PAUSE_DUE_TO_BUFFER_UNDERFLOW, NULL, NULL, NULL, false); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Received source underflow event, issue auto-pause command")); |
| } |
| } |
| break; |
| |
| case PVMFInfoDataReady: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Received PVMFInfoDataReady")); |
| // remove pending auto-pause if there is any |
| if (removeCmdFromQ(iPendingCmds, PVP_ENGINE_COMMAND_PAUSE_DUE_TO_BUFFER_UNDERFLOW, true)) |
| { |
| //cancelled the pending auto-pause |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() PVMFInfoDataReady got cancelled")); |
| break; |
| } |
| |
| // if no resume in the queue and no resume in progress, add one |
| if ((! removeCmdFromQ(iCurrentCmd, PVP_ENGINE_COMMAND_RESUME_DUE_TO_BUFFER_DATAREADY, false)) |
| && (! removeCmdFromQ(iPendingCmds, PVP_ENGINE_COMMAND_RESUME_DUE_TO_BUFFER_DATAREADY, false))) |
| { |
| AddCommandToQueue(PVP_ENGINE_COMMAND_RESUME_DUE_TO_BUFFER_DATAREADY, NULL, NULL, NULL, false); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Received source data ready event, issue auto-resume command")); |
| } |
| } |
| break; |
| |
| case PVMFInfoContentLength: |
| case PVMFInfoContentType: |
| case PVMFInfoContentTruncated: |
| case PVMFInfoRemoteSourceNotification: |
| case PVMFInfoPlayListClipTransition: |
| case PVMFInfoPlayListSwitch: |
| { |
| PVInterface* intf = NULL; |
| PVMFBasicErrorInfoMessage* infomsg = NULL; |
| PVMFErrorInfoMessageInterface* nextmsg = NULL; |
| if (aEvent.GetEventExtensionInterface() != NULL) |
| { |
| nextmsg = GetErrorInfoMessageInterface(*(aEvent.GetEventExtensionInterface())); |
| PVUuid puuid = PVPlayerErrorInfoEventTypesUUID; |
| infomsg = |
| OSCL_NEW(PVMFBasicErrorInfoMessage, (PVPlayerInfoSourceMediaData, |
| puuid, |
| nextmsg)); |
| intf = OSCL_STATIC_CAST(PVInterface*, infomsg); |
| } |
| SendInformationalEvent(event, intf, aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize()); |
| if (infomsg != NULL) |
| { |
| infomsg->removeRef(); |
| } |
| infomsg = NULL; |
| } |
| break; |
| |
| case PVMFInfoTrackDisable: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Sending bad track disabled event %d", event)); |
| SendInformationalEvent(event, NULL, aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize()); |
| } |
| break; |
| |
| case PVMFInfoUnexpectedData: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Sending unexpected data event %d", event)); |
| SendInformationalEvent(event, NULL, aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize()); |
| } |
| break; |
| |
| case PVMFInfoSessionDisconnect: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Sending session disconnect %d", event)); |
| SendInformationalEvent(event, NULL, aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize()); |
| } |
| break; |
| case PVMFInfoMetadataAvailable: |
| { |
| PVUuid infomsguuid = PVMFMetadataInfoMessageInterfaceUUID; |
| PVMFMetadataInfoMessageInterface* eventMsg = NULL; |
| PVInterface* infoExtInterface = aEvent.GetEventExtensionInterface(); |
| if (infoExtInterface && |
| infoExtInterface->queryInterface(infomsguuid, (PVInterface*&)eventMsg)) |
| { |
| PVUuid eventuuid; |
| int32 infoCode; |
| eventMsg->GetCodeUUID(infoCode, eventuuid); |
| if (eventuuid == infomsguuid) |
| { |
| Oscl_Vector<PvmiKvp, OsclMemAllocator> kvpVector = eventMsg->GetMetadataVector(); |
| SendInformationalEvent(aEvent.GetEventType(), infoExtInterface, aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize()); |
| } |
| } |
| } |
| break; |
| case PVMFInfoDurationAvailable: |
| { |
| PVUuid infomsguuid = PVMFDurationInfoMessageInterfaceUUID; |
| PVMFDurationInfoMessageInterface* eventMsg = NULL; |
| PVInterface* infoExtInterface = aEvent.GetEventExtensionInterface(); |
| PVInterface* temp = NULL; |
| if (infoExtInterface && |
| infoExtInterface->queryInterface(infomsguuid, temp)) |
| { |
| PVUuid eventuuid; |
| int32 infoCode; |
| eventMsg = OSCL_STATIC_CAST(PVMFDurationInfoMessageInterface*, temp); |
| eventMsg->GetCodeUUID(infoCode, eventuuid); |
| if (eventuuid == infomsguuid) |
| { |
| 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 PVMFInfoPoorlyInterleavedContent: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Sending Poorly Interleaved Content Info %d", event)); |
| SendInformationalEvent(event, NULL, aEvent.GetEventData(), aEvent.GetLocalBuffer(), aEvent.GetLocalBufferSize()); |
| } |
| break; |
| case PVMFInfoSourceOverflow: |
| { |
| PVPPlaybackPosition aBeginPos; |
| aBeginPos.iIndeterminate = false; |
| aBeginPos.iPosUnit = PVPPBPOSUNIT_MILLISEC; |
| aBeginPos.iPosValue.millisec_value = 0; |
| PVPPlaybackPosition aEndPos; |
| aEndPos.iIndeterminate = true; |
| iOverflowFlag = true; |
| SetPlaybackRange(aBeginPos, aEndPos, false); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Received source overflow event, issue auto-reposition command")); |
| } |
| break; |
| case PVMFInfoEndOfData: |
| default: |
| // Do nothing but log it |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Do nothing for this event %d", event)); |
| break; |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSourceNodeInfoEvent() Out")); |
| } |
| |
| |
| void PVPlayerEngine::HandleDecNodeInfoEvent(const PVMFAsyncEvent& aEvent, int32 aDatapathIndex) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeInfoEvent() In")); |
| |
| if (iState == PVP_ENGINE_STATE_RESETTING) |
| { |
| //this means error handling, reset or cancelall is still in progress |
| //no need to look for info event |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleDecNodeInfoEvent() Return engine in resetting state no need to process the info event %d", aEvent.GetEventType())); |
| return; |
| } |
| |
| OSCL_UNUSED_ARG(aDatapathIndex); |
| |
| PVMFEventType event = aEvent.GetEventType(); |
| |
| switch (event) |
| { |
| case PVMFInfoProcessingFailure: |
| |
| SendInformationalEvent(PVMFInfoProcessingFailure); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeInfoEvent() Report ProcessingFailure event %d", event)); |
| break; |
| |
| case PVMFInfoOverflow: |
| case PVMFInfoEndOfData: |
| default: |
| // Do nothing but log it |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeInfoEvent() Do nothing for this event %d", event)); |
| break; |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleDecNodeInfoEvent() Out")); |
| } |
| |
| |
| void PVPlayerEngine::HandleSinkNodeInfoEvent(const PVMFAsyncEvent& aEvent, int32 aDatapathIndex) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() In")); |
| |
| if (iState == PVP_ENGINE_STATE_RESETTING) |
| { |
| //this means error handling, reset or cancelall is still in progress |
| //no need to look for info event |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() Return engine in resetting state no need to process the info event %d", aEvent.GetEventType())); |
| return; |
| } |
| |
| PVMFEventType event = aEvent.GetEventType(); |
| |
| switch (event) |
| { |
| case PVMFInfoStartOfData: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() PVMFInfoStartOfData event received for %s", |
| iDatapathList[aDatapathIndex].iTrackInfo->getTrackMimeType().get_cstr())); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() PVMFInfoStartOfData event received for %s, iNumPendingSkipCompleteEvent=%d iNumPVMFInfoStartOfDataPending=%d", |
| iDatapathList[aDatapathIndex].iTrackInfo->getTrackMimeType().get_cstr(), |
| iNumPendingSkipCompleteEvent, iNumPVMFInfoStartOfDataPending)); |
| |
| uint32 *data = (uint32*) aEvent.GetEventData(); |
| uint32 streamID = *data; |
| |
| if (streamID != iStreamID) |
| { |
| // received StartOfData for previous streamId, ignoring these events |
| break; |
| } |
| |
| if (iNumPVMFInfoStartOfDataPending > 0) |
| { |
| --iNumPVMFInfoStartOfDataPending; |
| } |
| |
| if ((iNumPendingSkipCompleteEvent == 0) && (iNumPVMFInfoStartOfDataPending == 0)) |
| { |
| if (iWatchDogTimer->IsBusy()) |
| { |
| iWatchDogTimer->Cancel(); |
| } |
| //check engine internal state here prior to starting the clock |
| //this is to make sure that we do not start the clock in case engine is still |
| //auto-paused (think usecase: auto-pause, setplaybackrange, auto-resume) |
| if (iState == PVP_ENGINE_STATE_STARTED) |
| { |
| // start the clock only if engine is in started state |
| StartPlaybackClock(); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() - PlayClock Started")); |
| } |
| } |
| //else it could mean duplicate or old PVMFInfoStartOfData, ignore both |
| } |
| break; |
| case PVMFInfoEndOfData: |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() PVMFInfoEndOfData event received for %s", |
| iDatapathList[aDatapathIndex].iTrackInfo->getTrackMimeType().get_cstr())); |
| |
| uint32 *data = (uint32*) aEvent.GetEventData(); |
| uint32 streamID = *data; |
| |
| if (streamID != iStreamID) |
| { |
| // received EndOfData for previous streamId, ignoring these events |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::HandleSinkNodeInfoEvent() PVMFInfoEndOfData event received for %s with StreamID=%d, Engine StreamID=%d", |
| iDatapathList[aDatapathIndex].iTrackInfo->getTrackMimeType().get_cstr(), |
| streamID, iStreamID)); |
| break; |
| } |
| |
| if (iDatapathList[aDatapathIndex].iDatapath && iDatapathList[aDatapathIndex].iEndOfDataReceived == false) |
| { |
| iDatapathList[aDatapathIndex].iEndOfDataReceived = true; |
| // If all datapath received EOS, initiate a pause-due-to-EOS |
| if (AllDatapathReceivedEndOfData() == true) |
| { |
| 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].iDatapath && |
| 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) |
| { |
| // send DataReady event only if it is not sent earlier and if EOS is not reported. |
| // It is possible that for Streaming repositioning to end use-cases engine receives |
| // EOS before prepare completes, in that case suppress DataReady event. |
| if (!iDataReadySent && !iPlaybackPausedDueToEndOfClip) |
| { |
| iDataReadySent = true; |
| SendInformationalEvent(PVMFInfoDataReady); |
| } |
| } |
| else if (aStatus == PVMFErrCancelled) |
| { |
| // Do nothing since the auto-resume was cancelled |
| } |
| else |
| { |
| SendErrorEvent(aStatus, aExtInterface); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::SendSourceDataReadyInfoEvent() Out")); |
| } |
| |
| |
| PVMFErrorInfoMessageInterface* PVPlayerEngine::GetErrorInfoMessageInterface(PVInterface& aInterface) |
| { |
| PVMFErrorInfoMessageInterface* extiface = NULL; |
| PVInterface* temp = NULL; |
| if (aInterface.queryInterface(PVMFErrorInfoMessageInterfaceUUID, temp)) |
| { |
| extiface = OSCL_STATIC_CAST(PVMFErrorInfoMessageInterface*, temp); |
| return extiface; |
| } |
| else |
| { |
| return NULL; |
| } |
| } |
| |
| |
| void PVPlayerEngine::StartPlaybackStatusTimer(void) |
| { |
| // Check if playback position reporting is enabled |
| if (!iPBPosEnable || iPlayStatusTimerEnabled) |
| return; |
| // To get regular play status events |
| iPlayStatusTimerEnabled = true; |
| |
| iClockNotificationsInf->SetCallbackDeltaTime(iPBPosStatusInterval, |
| iPlayStatusCallbackTimerMarginWindow, (PVMFMediaClockNotificationsObs*)this, false, NULL, |
| iPlayStatusCallbackTimerID); |
| } |
| |
| |
| void PVPlayerEngine::StopPlaybackStatusTimer(void) |
| { |
| |
| // Stop the playback position status timer |
| iPlayStatusTimerEnabled = false; |
| if (iClockNotificationsInf && iPlayStatusCallbackTimerID) |
| { |
| iClockNotificationsInf->CancelCallback(iPlayStatusCallbackTimerID, false); |
| iPlayStatusCallbackTimerID = 0; |
| } |
| } |
| |
| bool PVPlayerEngine::CheckForSourceRollOver() |
| { |
| uint32 alternates = iDataSource->GetNumAlternateSourceFormatTypes(); |
| if ((alternates > 0) && (iAlternateSrcFormatIndex < alternates)) |
| { |
| return true; |
| } |
| return false; |
| } |
| |
| PVMFStatus PVPlayerEngine::SetupDataSourceForUnknownURLAccess() |
| { |
| if (iDataSource == NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::SetupDataSourceForUnknownURLAccess() - No Data Source")); |
| return PVMFErrInvalidState; |
| } |
| else |
| { |
| /* |
| * In case of unknown url, here is the sequence that engine would attempt: |
| * 1) First Alternate source format would be PVMF_DATA_SOURCE_RTSP_URL, |
| * implying that we would attempt a RTSP streaming session |
| * |
| * 2) Primary source format would be set to PVMF_DATA_SOURCE_HTTP_URL, |
| * implying that we would attempt a progressive download first. |
| * |
| * 3) Second Alternate source format would be PVMF_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_MIME_DATA_SOURCE_RTSP_URL; ; |
| if (iDataSource->SetAlternateSourceFormatType(PVMF_MIME_DATA_SOURCE_HTTP_URL) != true) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::SetupDataSourceForUnknownURLAccess() - SetAlternateSourceFormatType Failed")); |
| return PVMFFailure; |
| } |
| if (iDataSource->SetAlternateSourceFormatType(PVMF_MIME_DATA_SOURCE_REAL_HTTP_CLOAKING_URL) != true) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::SetupDataSourceForUnknownURLAccess() - SetAlternateSourceFormatType Failed")); |
| return PVMFFailure; |
| } |
| if (iDataSource->SetAlternateSourceFormatType(PVMF_MIME_DATA_SOURCE_MS_HTTP_STREAMING_URL) != true) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::SetupDataSourceForUnknownURLAccess() - SetAlternateSourceFormatType Failed")); |
| return PVMFFailure; |
| } |
| return PVMFSuccess; |
| } |
| } |
| |
| /* scan thru aKvpValue, create a new PvmiKvp object and push |
| * than onto iPvmiKvpCapNConfig. |
| * return PVMFSuccess unless allocation error |
| */ |
| PVMFStatus PVPlayerEngine:: VerifyAndSaveKVPValues(PvmiKvp *aKvpValue) |
| { |
| |
| PvmiKvp* KvpCapNConfig = (PvmiKvp *)OSCL_MALLOC(sizeof(PvmiKvp)); |
| if (! KvpCapNConfig) return PVMFErrNoMemory; |
| oscl_memcpy(KvpCapNConfig, aKvpValue, sizeof(PvmiKvp)); |
| |
| |
| KvpCapNConfig->key = (char*)OSCL_MALLOC(oscl_strlen(aKvpValue->key) + 1); |
| if (! KvpCapNConfig->key) return PVMFErrNoMemory; |
| oscl_strncpy(KvpCapNConfig->key, aKvpValue->key, oscl_strlen(aKvpValue->key) + 1); |
| |
| |
| // all the values have copied automatically so just need to allocate memory of pointer type. |
| |
| if (oscl_strstr(aKvpValue->key, _STRLIT_CHAR("valtype=wchar*")) != NULL) |
| { |
| KvpCapNConfig->value.pWChar_value = (oscl_wchar*)OSCL_MALLOC((oscl_strlen(aKvpValue->value.pWChar_value) + 1) * sizeof(oscl_wchar)); |
| if (! KvpCapNConfig->value.pWChar_value) return PVMFErrNoMemory; |
| oscl_strncpy(KvpCapNConfig->value.pWChar_value, aKvpValue->value.pWChar_value, oscl_strlen(aKvpValue->value.pWChar_value) + 1); |
| |
| } |
| else if (oscl_strstr(aKvpValue->key, _STRLIT_CHAR("valtype=char*")) != NULL) |
| { |
| KvpCapNConfig->value.pChar_value = (char*)OSCL_MALLOC(oscl_strlen(aKvpValue->value.pChar_value) + 1); |
| if (! KvpCapNConfig->value.pChar_value) return PVMFErrNoMemory; |
| oscl_strncpy(KvpCapNConfig->value.pChar_value, aKvpValue->value.pChar_value, oscl_strlen(aKvpValue->value.pChar_value) + 1); |
| |
| } |
| else if (oscl_strstr(aKvpValue->key, _STRLIT_CHAR("valtype=uint8*")) != NULL) |
| { |
| KvpCapNConfig->value.pUint8_value = (uint8*)OSCL_MALLOC(oscl_strlen((char *)aKvpValue->value.pUint8_value) + 1); |
| if (! KvpCapNConfig->value.pUint8_value) return PVMFErrNoMemory; |
| oscl_memcpy(KvpCapNConfig->value.pUint8_value, aKvpValue->value.pUint8_value, oscl_strlen((char *)aKvpValue->value.pUint8_value) + 1); |
| |
| } |
| else if (oscl_strstr(aKvpValue->key, _STRLIT_CHAR("valtype=int32*")) != NULL) |
| { |
| KvpCapNConfig->value.pInt32_value = (int32*)OSCL_MALLOC(sizeof(int32)); |
| if (! KvpCapNConfig->value.pInt32_value) return PVMFErrNoMemory; |
| oscl_memcpy(KvpCapNConfig->value.pInt32_value, aKvpValue->value.pInt32_value, sizeof(int32)); |
| // @TODO: Future support will be based on length , currently support only one element |
| } |
| else if (oscl_strstr(aKvpValue->key, _STRLIT_CHAR("valtype=uint32*")) != NULL) |
| { |
| KvpCapNConfig->value.pUint32_value = (uint32*)OSCL_MALLOC(sizeof(uint32)); |
| if (! KvpCapNConfig->value.pUint32_value) return PVMFErrNoMemory; |
| oscl_memcpy(KvpCapNConfig->value.pUint32_value, aKvpValue->value.pUint32_value, sizeof(uint32)); |
| // @TODO: Future support will be based on length, currently support only one element |
| } |
| else if (oscl_strstr(aKvpValue->key, _STRLIT_CHAR("valtype=int64*")) != NULL) |
| { |
| KvpCapNConfig->value.pInt64_value = (int64*)OSCL_MALLOC(sizeof(int64)); |
| if (! KvpCapNConfig->value.pInt64_value) return PVMFErrNoMemory; |
| oscl_memcpy(KvpCapNConfig->value.pInt64_value, aKvpValue->value.pInt64_value, sizeof(int64)); |
| // @TODO: Future support will be based on length, currently support only one element |
| } |
| else if (oscl_strstr(aKvpValue->key, _STRLIT_CHAR("valtype=uint64*")) != NULL) |
| { |
| KvpCapNConfig->value.pUint64_value = (uint64*)OSCL_MALLOC(sizeof(uint64)); |
| if (! KvpCapNConfig->value.pUint64_value) return PVMFErrNoMemory; |
| oscl_memcpy(KvpCapNConfig->value.pUint64_value, aKvpValue->value.pUint64_value, sizeof(uint64)); |
| // @TODO: Future support will be based on length, currently support only one element |
| } |
| else if (oscl_strstr(aKvpValue->key, _STRLIT_CHAR("valtype=float*")) != NULL) |
| { |
| KvpCapNConfig->value.pFloat_value = (float*)OSCL_MALLOC(sizeof(float)); |
| if (! KvpCapNConfig->value.pFloat_value) return PVMFErrNoMemory; |
| oscl_memcpy(KvpCapNConfig->value.pFloat_value, aKvpValue->value.pFloat_value, sizeof(float)); |
| // @TODO: Future support will be based on length, currently support only one element |
| } |
| else if (oscl_strstr(aKvpValue->key, _STRLIT_CHAR("valtype=double*")) != NULL) |
| { |
| KvpCapNConfig->value.pDouble_value = (double*)OSCL_MALLOC(sizeof(double)); |
| if (! KvpCapNConfig->value.pDouble_value) return PVMFErrNoMemory; |
| oscl_memcpy(KvpCapNConfig->value.pDouble_value, aKvpValue->value.pDouble_value, sizeof(double)); |
| // @TODO: Future support will be based on length, currently support only one element |
| } |
| else if (oscl_strstr(aKvpValue->key, _STRLIT_CHAR("valtype=range_int32")) != NULL) |
| { |
| KvpCapNConfig->value.key_specific_value = (void*)OSCL_MALLOC(sizeof(range_int32)); |
| if (! KvpCapNConfig->value.key_specific_value) return PVMFErrNoMemory; |
| oscl_memcpy(KvpCapNConfig->value.key_specific_value, aKvpValue->value.key_specific_value, sizeof(range_int32)); |
| // @TODO: Future support will be based on length, currently support only one element |
| } |
| else if (oscl_strstr(aKvpValue->key, _STRLIT_CHAR("valtype=range_uint32")) != NULL) |
| { |
| KvpCapNConfig->value.key_specific_value = (void*)OSCL_MALLOC(sizeof(range_uint32)); |
| if (! KvpCapNConfig->value.key_specific_value) return PVMFErrNoMemory; |
| oscl_memcpy(KvpCapNConfig->value.key_specific_value, aKvpValue->value.key_specific_value, sizeof(range_uint32)); |
| // @TODO: Future support will be based on length, currently support only one element |
| } |
| |
| iPvmiKvpCapNConfig.push_back(KvpCapNConfig); |
| return PVMFSuccess; |
| } |
| |
| |
| void PVPlayerEngine::SetRollOverKVPValues() |
| { |
| PvmiKvp *SaveKvp; |
| PvmiKvp *ErrorKVP; |
| |
| for (uint i = 0; i < iPvmiKvpCapNConfig.size(); i++) |
| { |
| SaveKvp = iPvmiKvpCapNConfig[i]; |
| setParametersSync(NULL, SaveKvp, 1 , ErrorKVP); |
| |
| if (ErrorKVP != NULL) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::SetRollOverKVPValues() Configuring cap-config failed")); |
| } |
| } |
| |
| } |
| |
| void PVPlayerEngine::DeleteKVPValues() |
| { |
| uint i = 0; |
| while (i < iPvmiKvpCapNConfig.size()) |
| { |
| PvmiKvp **Setkvp = iPvmiKvpCapNConfig.begin(); |
| |
| if (oscl_strstr((*Setkvp)->key, _STRLIT_CHAR("valtype=wchar*")) != NULL) |
| { |
| OSCL_FREE((*Setkvp)->value.pWChar_value); |
| (*Setkvp)->value.pWChar_value = NULL; |
| |
| } |
| else if (oscl_strstr((*Setkvp)->key, _STRLIT_CHAR("valtype=char*")) != NULL) |
| { |
| OSCL_FREE((*Setkvp)->value.pChar_value); |
| (*Setkvp)->value.pChar_value = NULL; |
| } |
| else if (oscl_strstr((*Setkvp)->key, _STRLIT_CHAR("valtype=uint8*")) != NULL) |
| { |
| OSCL_FREE((*Setkvp)->value.pUint8_value); |
| (*Setkvp)->value.pUint8_value = NULL; |
| } |
| |
| else if (oscl_strstr((*Setkvp)->key, _STRLIT_CHAR("valtype=int32*")) != NULL) |
| { |
| OSCL_FREE((*Setkvp)->value.pInt32_value); |
| (*Setkvp)->value.pInt32_value = NULL; |
| |
| } |
| else if (oscl_strstr((*Setkvp)->key, _STRLIT_CHAR("valtype=uint32*")) != NULL) |
| { |
| OSCL_FREE((*Setkvp)->value.pUint32_value); |
| (*Setkvp)->value.pUint32_value = NULL; |
| |
| } |
| else if (oscl_strstr((*Setkvp)->key, _STRLIT_CHAR("valtype=int64*")) != NULL) |
| { |
| OSCL_FREE((*Setkvp)->value.pInt64_value); |
| (*Setkvp)->value.pInt64_value = NULL; |
| |
| } |
| else if (oscl_strstr((*Setkvp)->key, _STRLIT_CHAR("valtype=uint64*")) != NULL) |
| { |
| OSCL_FREE((*Setkvp)->value.pUint64_value); |
| (*Setkvp)->value.pUint64_value = NULL; |
| } |
| else if (oscl_strstr((*Setkvp)->key, _STRLIT_CHAR("valtype=float*")) != NULL) |
| { |
| OSCL_FREE((*Setkvp)->value.pFloat_value); |
| (*Setkvp)->value.pFloat_value = NULL; |
| } |
| else if (oscl_strstr((*Setkvp)->key, _STRLIT_CHAR("valtype=double*")) != NULL) |
| { |
| OSCL_FREE((*Setkvp)->value.pDouble_value); |
| (*Setkvp)->value.pDouble_value = NULL; |
| } |
| else if ((oscl_strstr((*Setkvp)->key, _STRLIT_CHAR("valtype=range_int32")) != NULL) || |
| (oscl_strstr((*Setkvp)->key, _STRLIT_CHAR("valtype=range_uint32")) != NULL)) |
| { |
| OSCL_FREE((*Setkvp)->value.key_specific_value); |
| (*Setkvp)->value.key_specific_value = NULL; |
| } |
| |
| OSCL_FREE((*Setkvp)->key); |
| (*Setkvp)->key = NULL; |
| |
| OSCL_FREE(*Setkvp); |
| *Setkvp = NULL; |
| |
| iPvmiKvpCapNConfig.erase(iPvmiKvpCapNConfig.begin()); |
| } |
| |
| } |
| |
| |
| void PVPlayerEngine::PVPlayerWatchdogTimerEvent() |
| { |
| //check engine internal state here prior to starting the clock |
| //this is to make sure that we do not start the clock in case engine is still |
| //auto-paused (think usecase: auto-pause, setplaybackrange, auto-resume) |
| if (iState == PVP_ENGINE_STATE_STARTED) |
| { |
| // start the clock only if engine is in started state |
| StartPlaybackClock(); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::PVPlayerWatchdogTimerEvent() WatchDog timer expired")); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO, (0, "PVPlayerEngine::PVPlayerWatchdogTimerEvent() WatchDog timer expired")); |
| } |
| } |
| |
| void PVPlayerEngine::StartPlaybackClock() |
| { |
| if (iWatchDogTimer->IsBusy()) |
| { |
| iWatchDogTimer->Cancel(); |
| } |
| |
| if (iPlaybackClock.GetState() == PVMFMediaClock::RUNNING) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "PVPlayerEngine::StartPlaybackClock() clock already started")); |
| return; |
| } |
| |
| iPlaybackClock.Start(); |
| // Notify all sink nodes that have sync control IF that clock has started |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iDatapath && iDatapathList[i].iSinkNodeSyncCtrlIF) |
| { |
| iDatapathList[i].iSinkNodeSyncCtrlIF->ClockStarted(); |
| } |
| } |
| |
| // To get regular play status events |
| StartPlaybackStatusTimer(); |
| |
| // Restart the end time check if enabled |
| if (iEndTimeCheckEnabled) |
| { |
| // Determine the check cycle based on interval setting in milliseconds |
| // and timer frequency of 100 millisec |
| int32 checkcycle = iEndTimeCheckInterval / 100; |
| if (checkcycle == 0) |
| { |
| ++checkcycle; |
| } |
| iPollingCheckTimer->Cancel(PVPLAYERENGINE_TIMERID_ENDTIMECHECK); |
| iPollingCheckTimer->Request(PVPLAYERENGINE_TIMERID_ENDTIMECHECK, 0, checkcycle, this, true); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::StartPlaybackClock() StartNPT %d StartTS %d", iStartNPT, iStartMediaDataTS)); |
| } |
| |
| PVMFStatus PVPlayerEngine::GetCompleteList(PVMFMediaPresentationInfo& aList) |
| { |
| if (iSourceNodeTrackSelIF) |
| { |
| PVPlayerState state = GetPVPlayerState(); |
| if ((state == PVP_STATE_INITIALIZED) || |
| (state == PVP_STATE_PREPARED) || |
| (state == PVP_STATE_STARTED) || |
| (state == PVP_STATE_PAUSED)) |
| { |
| aList.Reset(); |
| PVMFStatus retval = PVMFFailure; |
| int32 leavecode = 0; |
| OSCL_TRY(leavecode, retval = iSourceNodeTrackSelIF->GetMediaPresentationInfo(aList)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::GetCompleteList() GetMediaPresentationInfo on iSourceNodeTrackSelIF did a leave!")); |
| return PVMFFailure); |
| if (retval != PVMFSuccess) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::GetCompleteList() GetMediaPresentationInfo() call on source node failed")); |
| } |
| return retval; |
| } |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::GetCompleteList() iSourceNodeTrackSelIF Invalid")); |
| return PVMFFailure; |
| } |
| |
| PVMFStatus PVPlayerEngine::ReleaseCompleteList(PVMFMediaPresentationInfo& aList) |
| { |
| aList.Reset(); |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVPlayerEngine::GetPlayableList(PVMFMediaPresentationInfo& aList) |
| { |
| PVPlayerState state = GetPVPlayerState(); |
| if ((state == PVP_STATE_PREPARED) || |
| (state == PVP_STATE_STARTED) || |
| (state == PVP_STATE_PAUSED)) |
| { |
| aList = iPlayableList; |
| if (aList.getNumTracks() == 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::GetPlayableList() No tracks")); |
| return PVMFFailure; |
| } |
| return PVMFSuccess; |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::GetPlayableList() Invalid Engine State")); |
| return PVMFErrInvalidState; |
| } |
| |
| PVMFStatus PVPlayerEngine::ReleasePlayableList(PVMFMediaPresentationInfo& aList) |
| { |
| aList.Reset(); |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVPlayerEngine::GetSelectedList(PVMFMediaPresentationInfo& aList) |
| { |
| PVPlayerState state = GetPVPlayerState(); |
| if ((state == PVP_STATE_PREPARED) || |
| (state == PVP_STATE_STARTED) || |
| (state == PVP_STATE_PAUSED)) |
| { |
| aList.Reset(); |
| aList.setPresentationType(iPlayableList.getPresentationType()); |
| aList.setSeekableFlag(iPlayableList.IsSeekable()); |
| aList.SetDurationAvailable(iPlayableList.IsDurationAvailable()); |
| aList.setDurationValue(iPlayableList.getDurationValue()); |
| aList.setDurationTimeScale(iPlayableList.getDurationTimeScale()); |
| for (uint32 i = 0; i < iDatapathList.size(); ++i) |
| { |
| if (iDatapathList[i].iTrackInfo != NULL) |
| { |
| aList.addTrackInfo(*(iDatapathList[i].iTrackInfo)); |
| } |
| } |
| if (aList.getNumTracks() == 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::GetSelectedList() No tracks")); |
| return PVMFFailure; |
| } |
| return PVMFSuccess; |
| } |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::GetSelectedList() Invalid Engine State")); |
| return PVMFErrInvalidState; |
| } |
| |
| PVMFStatus PVPlayerEngine::ReleaseSelectedList(PVMFMediaPresentationInfo& aList) |
| { |
| aList.Reset(); |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVPlayerEngine::RegisterHelperObject(PVMFTrackSelectionHelper* aObject) |
| { |
| if (aObject != NULL) |
| { |
| if (iTrackSelectionHelper != NULL) |
| { |
| return PVMFErrAlreadyExists; |
| } |
| } |
| iTrackSelectionHelper = aObject; |
| return PVMFSuccess; |
| } |
| |
| void PVPlayerEngine::ResetReposVariables(bool aResetAll) |
| { |
| if (aResetAll) |
| { |
| iStreamID = 0; |
| } |
| if (iWatchDogTimer != NULL) |
| { |
| if (iWatchDogTimer->IsBusy()) |
| { |
| iWatchDogTimer->Cancel(); |
| } |
| } |
| iNumPendingSkipCompleteEvent = 0; |
| iNumPVMFInfoStartOfDataPending = 0; |
| iTargetNPT = 0; |
| iActualNPT = 0; |
| iActualMediaDataTS = 0; |
| iSkipMediaDataTS = 0; |
| } |
| |
| PVMFStatus PVPlayerEngine::DoErrorHandling() |
| { |
| //pls note that we come into this method twice, in case of error handling |
| //first time, we come here to start the error handling seq (cancelall if any, followed by reset) |
| //second time, we come here when all resets are complete to cleanup and send command completes |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoErrorHandling() In")); |
| // Stop the playback clock |
| iPlaybackClock.Stop(); |
| |
| // 1st check if anything needs to be cancelled on Source Node or Datapaths |
| if (!iCurrentContextList.empty()) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::DoErrorHandling() Some Command is being processed, cancel it")); |
| for (uint32 i = 0; i < iCurrentContextList.size(); ++i) |
| { |
| if (iCurrentContextList[i]->iNode) |
| { |
| if (iCurrentContextList[i]->iNode == iSourceNode) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoErrorHandling() Cmd Pending on Source node, should never happend, asserting")); |
| OSCL_ASSERT(false); |
| } |
| } |
| } |
| |
| // error handling code set engine state to resetting |
| SetEngineState(PVP_ENGINE_STATE_RESETTING); |
| iRollOverState = RollOverStateIdle; //reset roll over state to Idle, as engine is resetting itself |
| // Since there is a pending node or datapath, cancel it |
| PVMFStatus status = DoCancelPendingNodeDatapathCommand(); |
| if (status == PVMFPending) |
| { |
| // There are some commands which need to be cancelled so wait for cancel complete |
| // once cancels complete, we would start the reset sequence from either |
| // NodeCommandComplete, HandlePlayerDataPathEvent, RecognizeComplete |
| return PVMFPending; |
| } |
| // if there is nothing to cancel move forward to reset. |
| } |
| |
| // move on to resetting Source Nodes and Datapaths |
| if (iSourceNode) |
| { |
| int32 leavecode = 0; |
| // call reset on source node if not in created state |
| if (iSourceNode->GetState() != EPVMFNodeCreated) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::DoErrorHandling() Issue reset on Source Node")); |
| // error handling code set engine state to resetting |
| SetEngineState(PVP_ENGINE_STATE_RESETTING); |
| iRollOverState = RollOverStateIdle; //reset roll over state to Idle, as engine is resetting itself |
| |
| PVPlayerEngineContext* context = AllocateEngineContext(NULL, iSourceNode, NULL, -1, NULL, -1); |
| |
| PVMFCommandId cmdid = -1; |
| leavecode = 0; |
| OSCL_TRY(leavecode, cmdid = iSourceNode->Reset(iSourceNodeSessionId, (OsclAny*)context)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::DoErrorHandling() Reset on iSourceNode did a leave!")); |
| FreeEngineContext(context); |
| OSCL_ASSERT(false); |
| return PVMFFailure); |
| |
| return PVMFPending; |
| } |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::DoErrorHandling() Source node is deleted or in created state, so start removing sinks")); |
| |
| // Now delete the datapath. |
| DoRemoveAllSinks(); |
| |
| // finally do the source node cleanup |
| if (iDataSource) |
| { |
| RemoveDataSourceSync(*iDataSource); |
| } |
| |
| SetEngineState(PVP_ENGINE_STATE_IDLE); |
| |
| // Send the command completion if there is any command in Current command |
| if (!iCurrentCmd.empty()) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, |
| (0, "PVPlayerEngine::DoErrorHandling() Complete the engine command being processed")); |
| if (iCommandCompleteErrMsgInErrorHandling) |
| { |
| EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), |
| iCurrentCmd[0].GetContext(), |
| iCommandCompleteStatusInErrorHandling, |
| OSCL_STATIC_CAST(PVInterface*, iCommandCompleteErrMsgInErrorHandling)); |
| iCommandCompleteErrMsgInErrorHandling->removeRef(); |
| iCommandCompleteErrMsgInErrorHandling = NULL; |
| } |
| else |
| { |
| EngineCommandCompleted(iCurrentCmd[0].GetCmdId(), |
| iCurrentCmd[0].GetContext(), |
| iCommandCompleteStatusInErrorHandling); |
| } |
| } |
| |
| // just send the error handling complete event |
| SendInformationalEvent(PVMFInfoErrorHandlingComplete, NULL); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVPlayerEngine::DoErrorHandling() Out")); |
| |
| return PVMFSuccess; |
| } |
| |
| bool PVPlayerEngine::CheckForPendingErrorHandlingCmd() |
| { |
| //if an error handling cmd had been queued previously |
| //it must be in top, since error handling cmds have the |
| //highest priority and pending cmds queue is a priority |
| //queue |
| bool retval = false; |
| if (!iPendingCmds.empty()) |
| { |
| switch (iPendingCmds.top().GetCmdType()) |
| { |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_ADD_DATA_SOURCE: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_INIT: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_PREPARE: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_PAUSE: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_RESUME: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_SET_PLAYBACK_RANGE: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_SET_PLAYBACK_RATE: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_STOP: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_CANCEL_ALL_COMMANDS: |
| case PVP_ENGINE_COMMAND_ERROR_HANDLING_GENERAL: |
| retval = true; |
| break; |
| |
| default: |
| break; |
| } |
| } |
| return retval; |
| } |
| |
| PVMFStatus PVPlayerEngine::IssueNodeCancelCommand(PVPlayerEngineContext* aCurrentListContext, PVMFSessionId aSessionId, OsclAny* aNumberCancelCmdPending) |
| { |
| PVMFStatus leavecode = 0; |
| OSCL_TRY(leavecode, aCurrentListContext->iNode->CancelAllCommands(aSessionId, aNumberCancelCmdPending)); |
| OSCL_FIRST_CATCH_ANY(leavecode,;); |
| return leavecode; |
| } |
| |
| PVMFStatus PVPlayerEngine::IssueDatapathCancelCommand(PVPlayerEngineContext* aCurrentListContext, OsclAny* aNumberCancelCmdPending) |
| { |
| PVMFStatus leavecode = 0; |
| OSCL_TRY(leavecode, aCurrentListContext->iDatapath->CancelCommand(aNumberCancelCmdPending)); |
| OSCL_FIRST_CATCH_ANY(leavecode,;); |
| return leavecode; |
| } |
| |
| PVMFStatus PVPlayerEngine::IssueRecognizerRegistryCancel(OsclAny* aNumberCancelCmdPending) |
| { |
| PVMFStatus leavecode = 0; |
| OSCL_TRY(leavecode, iPlayerRecognizerRegistry.CancelQuery(aNumberCancelCmdPending)); |
| OSCL_FIRST_CATCH_ANY(leavecode,;); |
| return leavecode; |
| } |
| |
| PVMFStatus PVPlayerEngine::IssueSinkNodeInit(PVPlayerEngineDatapath* aDatapath, OsclAny* aCmdContext, PVMFCommandId &aCmdId) |
| { |
| PVMFStatus leavecode = 0; |
| OSCL_TRY(leavecode, aCmdId = aDatapath->iSinkNode->Init(aDatapath->iSinkNodeSessionId, aCmdContext)); |
| OSCL_FIRST_CATCH_ANY(leavecode,;); |
| return leavecode; |
| } |
| |
| PVMFStatus PVPlayerEngine::IssueSinkNodeReset(PVPlayerEngineDatapath* aDatapath, OsclAny* aCmdContext, PVMFCommandId &aCmdId) |
| { |
| PVMFStatus leavecode = 0; |
| OSCL_TRY(leavecode, aCmdId = aDatapath->iSinkNode->Reset(aDatapath->iSinkNodeSessionId, aCmdContext)); |
| OSCL_FIRST_CATCH_ANY(leavecode,;); |
| return leavecode; |
| } |
| |
| PVMFStatus PVPlayerEngine::IssueSinkSkipMediaData(PVPlayerEngineDatapath* aDatapath, bool aSFR, OsclAny* aCmdContext) |
| { |
| PVMFStatus leavecode = 0; |
| OSCL_TRY(leavecode, aDatapath->iSinkNodeSyncCtrlIF->SkipMediaData(aDatapath->iSinkNodeSessionId, iSkipMediaDataTS, iStreamID, aSFR, aCmdContext)); |
| OSCL_FIRST_CATCH_ANY(leavecode,;); |
| return leavecode; |
| } |
| |
| PVMFStatus PVPlayerEngine::IssueSourceSetDataSourcePosition(bool aIsPosUnitPlayList, OsclAny* aCmdContext) |
| { |
| PVMFStatus leavecode = 0; |
| if (aIsPosUnitPlayList) |
| { |
| OSCL_TRY(leavecode, iSourceNodePBCtrlIF->SetDataSourcePosition(iSourceNodeSessionId, |
| iDataSourcePosParams, |
| aCmdContext)); |
| |
| } |
| else |
| { |
| OSCL_TRY(leavecode, iSourceNodePBCtrlIF->SetDataSourcePosition(iSourceNodeSessionId, |
| iTargetNPT, iActualNPT, iActualMediaDataTS, iSeekToSyncPoint, iStreamID, aCmdContext)); |
| } |
| OSCL_FIRST_CATCH_ANY(leavecode,;); |
| return leavecode; |
| } |
| |
| PVMFStatus PVPlayerEngine::IssueDecNodeInit(PVMFNodeInterface* aNode, PVMFSessionId aDecNodeSessionId, OsclAny* aCmdContext, PVMFCommandId &aCmdId) |
| { |
| PVMFStatus leavecode = 0; |
| OSCL_TRY(leavecode, aCmdId = aNode->Init(aDecNodeSessionId, aCmdContext)); |
| OSCL_FIRST_CATCH_ANY(leavecode,;); |
| return leavecode; |
| } |
| |
| PVMFStatus PVPlayerEngine::IssueDecNodeReset(PVMFNodeInterface* aNode, PVMFSessionId aDecNodeSessionId, OsclAny* aCmdContext, PVMFCommandId &aCmdId) |
| { |
| PVMFStatus leavecode = 0; |
| OSCL_TRY(leavecode, aCmdId = aNode->Reset(aDecNodeSessionId, aCmdContext)); |
| OSCL_FIRST_CATCH_ANY(leavecode,;); |
| return leavecode; |
| } |
| |
| PVMFStatus PVPlayerEngine::IssueQueryInterface(PVMFNodeInterface* aNode, PVMFSessionId aSessionId, const PVUuid aUuid, PVInterface*& aInterfacePtr, OsclAny* aCmdContext, PVMFCommandId& aCmdId) |
| { |
| PVMFStatus leavecode = 0; |
| OSCL_TRY(leavecode, aCmdId = aNode->QueryInterface(aSessionId, aUuid, aInterfacePtr, aCmdContext)); |
| OSCL_FIRST_CATCH_ANY(leavecode,;); |
| return leavecode; |
| } |
| |
| OSCL_EXPORT_REF void |
| PVPlayerInterface::GetSDKInfo |
| ( |
| PVSDKInfo& aSdkInfo |
| ) |
| { |
| aSdkInfo.iLabel = PVPLAYER_ENGINE_SDKINFO_LABEL; |
| aSdkInfo.iDate = PVPLAYER_ENGINE_SDKINFO_DATE; |
| } |
| |
| // END FILE |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |