blob: fdb1baa2d340f42ba1e2932e7797bceca6873ec9 [file] [log] [blame]
/* ------------------------------------------------------------------
* 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.
* -------------------------------------------------------------------
*/
#ifndef PVMF_SM_FSP_PVR_BASE_IMPL_H
#include "pvmf_sm_fsp_pvr_base_impl.h"
#endif
#ifndef PVMF_JITTER_BUFFER_NODE_H_INCLUDED
#include "pvmf_jitter_buffer_node.h"
#endif
#ifndef PVMF_MEDIALAYER_NODE_H_INCLUDED
#include "pvmf_medialayer_node.h"
#endif
#ifndef OSCL_SNPRINTF_H_INCLUDED
#include "oscl_snprintf.h"
#endif
#ifndef AMR_PAYLOAD_PARSER_FACTORY_H_INCLUDED
#include "amr_payload_parser_factory.h"
#endif
#ifndef H263_PAYLOAD_PARSER_FACTORY_H_INCLUDED
#include "h263_payload_parser_factory.h"
#endif
#ifndef H264_PAYLOAD_PARSER_FACTORY_H_INCLUDED
#include "h264_payload_parser_factory.h"
#endif
#ifndef ASF_PAYLOAD_PARSER_FACTORY_H_INCLUDED
#include "asf_payload_parser_factory.h"
#endif
#ifndef M4V_AUDIO_PAYLOAD_PARSER_FACTORY_H_INCLUDED
#include "m4v_audio_payload_parser_factory.h"
#endif
#ifndef M4V_PAYLOAD_PARSER_FACTORY_H_INCLUDED
#include "m4v_payload_parser_factory.h"
#endif
#ifndef PAYLOAD_PARSER_REGISTRY_H_INCLUDED
#include "payload_parser_registry.h"
#endif
#ifndef RFC3640_PAYLOAD_PARSER_FACTORY_H_INCLUDED
#include "rfc3640_payload_parser_factory.h"
#endif
#ifndef OSCL_MIME_STRING_UTILS_H
#include "pv_mime_string_utils.h"
#endif
#ifndef PVMI_KVP_UTIL_H_INCLUDED
#include "pvmi_kvp_util.h"
#endif
#ifndef PVMI_DRM_KVP_H_INCLUDED
#include "pvmi_drm_kvp.h"
#endif
#ifndef PVRTSP_CLIENT_ENGINE_NODE_H
#include "pvrtsp_client_engine_node.h"
#endif
#ifndef SDP_PARSER_H
#include "sdp_parser.h"
#endif
#ifndef PVMF_PVR_NODE_H_INCLUDED
#include "pvmf_pvr_node.h"
#endif
#ifndef PVMF_SOCKET_NODE_H_INCLUDED
#include "pvmf_socket_node.h"
#endif
#ifndef PVMF_RTSP_ENGINE_NODE_FACTORY_H_INCLUDED
#include "pvrtsp_client_engine_factory.h"
#endif
PVMFSMFSPPVRBase::PVMFSMFSPPVRBase(int32 aPriority) : PVMFSMFSPBaseNode(aPriority)
{
}
void PVMFSMFSPPVRBase::BypassError()
{
int32 localMode = 0;
if (iPVMFDataSourcePositionParamsPtr != NULL)
{
localMode = iPVMFDataSourcePositionParamsPtr->iMode;
}
PVMF_SM_FSP_PVR_BASE_LOGSTACKTRACE((0, "PVMFSMFSPPVRBase::BypassError() - In"));
if (CheckChildrenNodesStart())
{
if (!iCurrentCommand.empty() && iCancelCommand.empty())
{
PVMFSMFSPBaseNodeCommand aCmd = iCurrentCommand.front();
if ((aCmd.iCmd == PVMF_SMFSP_NODE_START) ||
(aCmd.iCmd == PVMF_SMFSP_NODE_SET_DATASOURCE_POSITION))
{
if (iRepositioning)
{
PVMF_SM_FSP_PVR_BASE_LOGCMDSEQ((0, "PVMFSMFSPPVRBase::BypassError() - InRepos"));
iRepositioning = false;
iPlayListRepositioning = false;
iPVMFDataSourcePositionParamsPtr = NULL;
PVMFSMFSPChildNodeContainer* jitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
OSCL_ASSERT(jitterBufferNodeContainer);
if (!jitterBufferNodeContainer)
return;
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)
(jitterBufferNodeContainer->iExtensions[0]);
OSCL_ASSERT(jbExtIntf);
if (!jbExtIntf)
return;
/* Set jitter buffer state to ready */
jbExtIntf->UpdateJitterBufferState();
}
if ((localMode == 0) || (localMode == -1))
{
SetState(EPVMFNodeStarted);
if (IsAdded())
{
/* wakeup the AO */
RunIfNotReady();
}
PVMF_SM_FSP_PVR_BASE_LOGCMDSEQ((0, "PVMFSMFSPPVRBase::BypassError() - InLocalMode"));
RunIfNotReady();
}
CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess, NULL, NULL, NULL);
}
}
}
PVMF_SM_FSP_PVR_BASE_LOGSTACKTRACE((0, "PVMFSMFSPPVRBase::BypassError() - Out"));
return;
}
bool PVMFSMFSPPVRBase::CheckChildrenNodesInit()
{
for (uint32 i = 0; i < iFSPChildNodeContainerVec.size(); i++)
{
if (iFSPChildNodeContainerVec[i].iNodeCmdState != PVMFSMFSP_NODE_CMD_IDLE)
{
return false;
}
}
return true;
}
bool PVMFSMFSPPVRBase::CheckChildrenNodesPause()
{
for (uint32 i = 0; i < iFSPChildNodeContainerVec.size(); i++)
{
if (iFSPChildNodeContainerVec[i].iNodeCmdState != PVMFSMFSP_NODE_CMD_IDLE
&& iFSPChildNodeContainerVec[i].iNodeCmdState != PVMFSMFSP_NODE_CMD_CANCEL_PENDING)
{
return false;
}
}
return true;
}
bool PVMFSMFSPPVRBase::CheckChildrenNodesPrepare()
{
for (uint32 i = 0; i < iFSPChildNodeContainerVec.size(); i++)
{
if (iFSPChildNodeContainerVec[i].iNodeCmdState != PVMFSMFSP_NODE_CMD_IDLE)
{
return false;
}
}
return true;
}
bool PVMFSMFSPPVRBase::CheckChildrenNodesStart()
{
for (uint32 i = 0; i < iFSPChildNodeContainerVec.size(); i++)
{
if (iFSPChildNodeContainerVec[i].iNodeCmdState == PVMFSMFSP_NODE_CMD_PENDING)
{
return false;
}
}
return true;
}
bool PVMFSMFSPPVRBase::CheckChildrenNodesStop()
{
for (uint32 i = 0; i < iFSPChildNodeContainerVec.size(); i++)
{
if (iFSPChildNodeContainerVec[i].iNodeCmdState != PVMFSMFSP_NODE_CMD_IDLE)
{
return false;
}
}
return true;
}
void PVMFSMFSPPVRBase::CleanUp()
{
ReleaseChildNodesExtentionInterface();
DestroyChildNodes();
DestroyPayloadParserRegistry();
ResetNodeParams();
iLogger = NULL;
}
void PVMFSMFSPPVRBase::ResetNodeParams(bool aReleaseMemory)
{
iPVREnabled = false;
if (aReleaseMemory)
{
if (iPVRExtInterface)
iPVRExtInterface->removeRef();
//PVR interface is pointing to interface available in nodeconatiner for PVR. So, dont relase it, just make it null, it will be released in func ReleaseChildNodesExtentionInterface
iPVRQueryInterface = NULL;
if (iPVRControl)
{
; //todo release the pvr control???
}
}
iPVRExtInterface = NULL;
iPVRQueryInterface = NULL;
iPVRControl = NULL;
iTrackInfoVec.clear();
PVMFSMFSPBaseNode::ResetNodeParams(aReleaseMemory);
}
void PVMFSMFSPPVRBase::CompletePrepare()
{
PVMF_SM_FSP_PVR_BASE_LOGSTACKTRACE((0, "PVMFSMFSPPVRBase::CompletePrepare() - In"));
if ((CheckChildrenNodesPrepare()) && (iGraphConstructComplete))
{
if (!iCurrentCommand.empty() && iCancelCommand.empty())
{
PVMFSMFSPBaseNodeCommand& aCmd = iCurrentCommand.front();
if (aCmd.iCmd == PVMF_SMFSP_NODE_PREPARE)
{
SetState(EPVMFNodePrepared);
PVMF_SM_FSP_PVR_BASE_LOGCMDSEQ((0, "PVMFSMFSPPVRBase::Prepare() - CmdComplete - PVMFSuccess"));
CommandComplete(iCurrentCommand, aCmd, PVMFSuccess);
}
}
}
PVMF_SM_FSP_PVR_BASE_LOGSTACKTRACE((0, "PVMFSMFSPPVRBase::CompletePrepare() - Out"));
return;
}
void PVMFSMFSPPVRBase::CompleteStop()
{
PVMF_SM_FSP_PVR_BASE_LOGSTACKTRACE((0, "PVMFSMFSPPVRBase::CompleteStop() - In"));
if (CheckChildrenNodesStop())
{
if (!iCurrentCommand.empty() && iCancelCommand.empty())
{
PVMFSMFSPBaseNodeCommand& aCmd = iCurrentCommand.front();
if (aCmd.iCmd == PVMF_SMFSP_NODE_STOP)
{
/* transition to Prepared state */
ResetStopCompleteParams();
SetState(EPVMFNodePrepared);
PVMF_SM_FSP_PVR_BASE_LOGCMDSEQ((0, "PVMFSMFSPPVRBase::Stop() - CmdComplete - PVMFSuccess"));
CommandComplete(iCurrentCommand, aCmd, PVMFSuccess);
}
}
}
PVMF_SM_FSP_PVR_BASE_LOGSTACKTRACE((0, "PVMFSMFSPPVRBase::CompleteStop() - Out"));
return;
}
PVMFStatus PVMFSMFSPPVRBase::ComputeSkipTimeStamp(PVMFTimestamp aTargetNPT,
PVMFTimestamp aActualNPT,
PVMFTimestamp aActualMediaDataTS,
PVMFTimestamp& aSkipTimeStamp,
PVMFTimestamp& aStartNPT)
{
//for RTSP streaming we always start playback from aActualNPT
//by defintion aActualMediaDataTS is the timestamp that corresponds
//to aActualNPT
OSCL_UNUSED_ARG(aTargetNPT);
OSCL_UNUSED_ARG(aSkipTimeStamp);
OSCL_UNUSED_ARG(aStartNPT);
aSkipTimeStamp = aActualMediaDataTS;
aStartNPT = aActualNPT;
return PVMFSuccess;
}
PVMFStatus PVMFSMFSPPVRBase::ConnectPortPairs(PVMFPortInterface* aPort1,
PVMFPortInterface* aPort2)
{
PVMFStatus status;
status = aPort1->Connect(aPort2);
if (status != PVMFSuccess)
{
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "StreamingManagerNode:ConnectPortPairs - Connect Failed"));
return status;
}
return status;
}
void PVMFSMFSPPVRBase::Construct()
{
PVMFSMFSPBaseNode::Construct();
int32 err;
OSCL_TRY(err,
iLogger = PVLogger::GetLoggerObject("PVMFSMPVRFilePlaybackNode");
iAvailableMetadataKeys.reserve(PVMFSTREAMINGMGRNODE_NUM_METADATAKEYS);
iAvailableMetadataKeys.clear();
CreateChildNodes();
QueryChildNodesExtentionInterface();
// create the payload parser registry
PopulatePayloadParserRegistry();
// pass the payload parser registry on to the media layer node
PVMFSMFSPChildNodeContainer* iMediaLayerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_MEDIA_LAYER_NODE);
OSCL_ASSERT(iMediaLayerNodeContainer);
PVMFMediaLayerNodeExtensionInterface* mlExtIntf = NULL;
if (iMediaLayerNodeContainer)
mlExtIntf = (PVMFMediaLayerNodeExtensionInterface*)(iMediaLayerNodeContainer->iExtensions[0]);
if (mlExtIntf)
mlExtIntf->setPayloadParserRegistry(PayloadParserRegistry::GetPayloadParserRegistry());
);
if (err != OsclErrNone)
{
PVMFSMFSPBaseNode::CleanUp();
OSCL_LEAVE(err);
}
}
void PVMFSMFSPPVRBase::PopulatePayloadParserRegistry()
{
PayloadParserRegistry* registry =
PayloadParserRegistry::GetPayloadParserRegistry();
OSCL_ASSERT(registry == NULL);
PayloadParserRegistry::Init();
registry = PayloadParserRegistry::GetPayloadParserRegistry();
StrPtrLen aac_latm("audio/MP4A-LATM");
StrPtrLen amr("audio/AMR");
StrPtrLen amrwb("audio/AMR-WB");
StrPtrLen h263_old("video/H263-1998");
StrPtrLen h263("video/H263-2000");
StrPtrLen m4v("video/MP4V-ES");
StrPtrLen h264("video/H264");
StrPtrLen mp4a(PVMF_MIME_MPEG4_AUDIO);
StrPtrLen rfc3640("audio/mpeg4-generic");
IPayloadParserFactory* m4vP = OSCL_NEW(M4VPayloadParserFactory, ());
IPayloadParserFactory* aacP = OSCL_NEW(M4VAudioPayloadParserFactory, ());
IPayloadParserFactory* amrP = OSCL_NEW(AmrPayloadParserFactory, ());
IPayloadParserFactory* h263P = OSCL_NEW(H263PayloadParserFactory, ());
IPayloadParserFactory* h264P = OSCL_NEW(H264PayloadParserFactory, ());
IPayloadParserFactory* amrwbP = OSCL_NEW(AmrPayloadParserFactory, ());
IPayloadParserFactory* rfc3640P = OSCL_NEW(RFC3640PayloadParserFactory, ());
registry->addPayloadParserFactoryToRegistry(m4v, m4vP);
registry->addPayloadParserFactoryToRegistry(h264, h264P);
registry->addPayloadParserFactoryToRegistry(aac_latm, aacP);
registry->addPayloadParserFactoryToRegistry(mp4a, aacP);
registry->addPayloadParserFactoryToRegistry(amr, amrP);
registry->addPayloadParserFactoryToRegistry(amrwb, amrwbP);
registry->addPayloadParserFactoryToRegistry(h263_old, h263P);
registry->addPayloadParserFactoryToRegistry(h263, h263P);
registry->addPayloadParserFactoryToRegistry(rfc3640, rfc3640P);
}
void PVMFSMFSPPVRBase::createContext(PvmiMIOSession aSession,
PvmiCapabilityContext& aContext)
{
OSCL_UNUSED_ARG(aSession);
OSCL_UNUSED_ARG(aContext);
// not supported
OSCL_LEAVE(PVMFErrNotSupported);
}
void PVMFSMFSPPVRBase::DeleteContext(PvmiMIOSession aSession,
PvmiCapabilityContext& aContext)
{
OSCL_UNUSED_ARG(aSession);
OSCL_UNUSED_ARG(aContext);
// not supported
OSCL_LEAVE(PVMFErrNotSupported);
}
void PVMFSMFSPPVRBase::DestroyPayloadParserRegistry()
{
StrPtrLen aac_latm("audio/MP4A-LATM");
StrPtrLen amr("audio/AMR");
StrPtrLen amrwb("audio/AMR-WB");
StrPtrLen h263("video/H263-2000");
StrPtrLen m4v("video/MP4V-ES");
StrPtrLen h264("video/H264");
StrPtrLen rfc3640("audio/mpeg4-generic");
PayloadParserRegistry* registry =
PayloadParserRegistry::GetPayloadParserRegistry();
if (registry == NULL) return;
OsclMemoryFragment memFrag;
memFrag.ptr = (OsclAny*)(m4v.c_str());
memFrag.len = (uint32)m4v.size();
OSCL_DELETE(registry->lookupPayloadParserFactory(memFrag));
memFrag.ptr = (OsclAny*)(h264.c_str());
memFrag.len = (uint32)h264.size();
OSCL_DELETE(registry->lookupPayloadParserFactory(memFrag));
memFrag.ptr = (OsclAny*)(aac_latm.c_str());
memFrag.len = (uint32)aac_latm.size();
OSCL_DELETE(registry->lookupPayloadParserFactory(memFrag));
memFrag.ptr = (OsclAny*)(amr.c_str());
memFrag.len = (uint32)amr.size();
OSCL_DELETE(registry->lookupPayloadParserFactory(memFrag));
memFrag.ptr = (OsclAny*)(amrwb.c_str());
memFrag.len = (uint32)amrwb.size();
OSCL_DELETE(registry->lookupPayloadParserFactory(memFrag));
memFrag.ptr = (OsclAny*)(h263.c_str());
memFrag.len = (uint32)h263.size();
OSCL_DELETE(registry->lookupPayloadParserFactory(memFrag));
memFrag.ptr = (OsclAny*)(rfc3640.c_str());
memFrag.len = (uint32)rfc3640.size();
OSCL_DELETE(registry->lookupPayloadParserFactory(memFrag));
PayloadParserRegistry::Cleanup();
}
PVMFCommandId PVMFSMFSPPVRBase::DoGetMetadataKeys(PVMFSMFSPBaseNodeCommand& aCmd)
{
return DoGetMetadataKeysBase(aCmd);
}
PVMFCommandId PVMFSMFSPPVRBase::DoGetMetadataValues(PVMFSMFSPBaseNodeCommand& aCmd)
{
iNoOfValuesIteratedForValueVect = 0;
iNoOfValuesPushedInValueVect = 0;
PVMFStatus retval = GetPVRPluginSpecificValues(aCmd);
if (PVMFSuccess != retval)
return retval;
return DoGetMetadataValuesBase(aCmd);
}
void PVMFSMFSPPVRBase::DoPrepare(PVMFSMFSPBaseNodeCommand& aCmd)
{
PVMF_SM_FSP_PVR_BASE_LOGSTACKTRACE((0, "PVMFSMFSPPVRBase::DoPrepare - In"));
switch (iInterfaceState)
{
case EPVMFNodeInitialized:
{
if (iGraphConstructComplete)
{
/*
* Connect the graph here. This is needed since we would send firewall packets
* as part of Prepare.
*/
if (GraphConnect() == false)
{
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase:DoPrepare - GraphConnect Failed"));
SetState(EPVMFNodeError);
PVUuid eventuuid = PVMFStreamingManagerNodeEventTypeUUID;
int32 errcode = PVMFStreamingManagerNodeGraphConnectFailed;
CommandComplete(iInputCommands, aCmd, PVMFFailure, NULL, &eventuuid, &errcode);
return;
}
/*
* Prepare for streaming manager cannot be completed unless Prepare
* for all the children nodes are complete
*/
PVMFSMFSPChildNodeContainerVector::iterator it;
for (it = iFSPChildNodeContainerVec.begin(); it != iFSPChildNodeContainerVec.end(); it++)
{
PVMFSMFSPCommandContext* internalCmd = RequestNewInternalCmd();
if (internalCmd != NULL)
{
internalCmd->cmd =
it->commandStartOffset +
PVMF_SM_FSP_NODE_INTERNAL_PREPARE_CMD_OFFSET;
internalCmd->parentCmd = aCmd.iCmd;
OsclAny *cmdContextData =
OSCL_REINTERPRET_CAST(OsclAny*, internalCmd);
PVMFNodeInterface* iNode = it->iNode;
iNode->Prepare(it->iSessionId, cmdContextData);
it->iNodeCmdState = PVMFSMFSP_NODE_CMD_PENDING;
}
else
{
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase:DoPrepare:RequestNewInternalCmd - Failed"));
CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
return;
}
}
MoveCmdToCurrentQueue(aCmd);
}
else
{
/* Graph construction not complete, so cant prep */
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase:DoPrepare Failed - Incomplete Graph"));
CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
}
}
break;
default:
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase:DoPrepare Failed - Invalid State"));
CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
break;
}
PVMF_SM_FSP_PVR_BASE_LOGSTACKTRACE((0, "PVMFSMFSPPVRBase::DoPrepare - Out"));
}
void PVMFSMFSPPVRBase::DoQueryDataSourcePosition(PVMFSMFSPBaseNodeCommand& aCmd)
{
PVMF_SM_FSP_PVR_BASE_LOGSTACKTRACE((0, "PVMFSMFSPPVRBase::DoQueryDataSourcePosition - In"));
PVMFTimestamp repositionrequestedstartnptinms = 0;
PVMFTimestamp* actualrepositionstartnptinmsptr = NULL;
bool seektosyncpoint = false;
aCmd.PVMFSMFSPBaseNodeCommand::Parse(repositionrequestedstartnptinms,
actualrepositionstartnptinmsptr,
seektosyncpoint);
if (actualrepositionstartnptinmsptr == NULL)
{
CommandComplete(iInputCommands, aCmd, PVMFErrArgument);
return;
}
*actualrepositionstartnptinmsptr = 0;
// This query is not supported for streaming sessions
CommandComplete(iInputCommands, aCmd, PVMFErrNotSupported);
PVMF_SM_FSP_PVR_BASE_LOGSTACKTRACE((0, "PVMFSMFSPPVRBase::DoQueryDataSourcePosition - Out"));
return;
}
void PVMFSMFSPPVRBase::DoReleasePort(PVMFSMFSPBaseNodeCommand& aCmd)
{
PVMF_SM_FSP_PVR_BASE_LOGSTACKTRACE((0, "PVMFSMFSPPVRBase::DoReleasePort - In"));
/*
* Since the streaming manager does not have ports of its own,
* a release port command typically translates to disconnecting
* the underlying media layer port.
*/
PVMFPortInterface* port;
aCmd.PVMFSMFSPBaseNodeCommandBase::Parse((PVMFPortInterface*&)port);
/*
* Find TrackInfo that corresponds to the Media Layer Output port
* on which the current relase is being called.
*/
PVMFPVRBaseTrackInfoVector::iterator it;
PVMFPVRBaseTrackInfo* trackInfo = NULL;
for (it = iTrackInfoVec.begin();
it != iTrackInfoVec.end();
it++)
{
if (it->iMediaLayerOutputPort == port)
{
trackInfo = it;
break;
}
}
PVUuid eventuuid = PVMFStreamingManagerNodeEventTypeUUID;
if (trackInfo == NULL)
{
PVMF_SM_FSP_PVR_BASE_LOGCMDSEQ((0, "PVMFSMFSPPVRBase::ReleasePort() - CmdFailed - PVMFErrArgument"));
/* invalid port */
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMPVRFilePlaybackNode::DoReleasePort Failed - Invalid Port"));
int32 errcode = PVMFStreamingManagerNodeErrorInvalidPort;
CommandComplete(iInputCommands, aCmd, PVMFErrArgument, NULL, &eventuuid, &errcode);
return;
}
PVMFStatus status = it->iMediaLayerOutputPort->Disconnect();
if (status != PVMFSuccess)
{
PVMF_SM_FSP_PVR_BASE_LOGINFO((0, "PVMFSMFSPPVRBase::DoReleasePort Success"));
CommandComplete(iInputCommands, aCmd, PVMFSuccess);
}
else
{
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase::DoReleasePort Failed"));
CommandComplete(iInputCommands, aCmd, PVMFErrPortProcessing);
}
PVMF_SM_FSP_PVR_BASE_LOGSTACKTRACE((0, "PVMFSMFSPPVRBase::DoReleasePort - Out"));
}
PVMFPVRBaseTrackInfo* PVMFSMFSPPVRBase::FindTrackInfo(uint32 atrackID)
{
PVMFPVRBaseTrackInfoVector::iterator it;
for (it = iTrackInfoVec.begin();
it != iTrackInfoVec.end();
it++)
{
if (it->trackID == atrackID)
{
return (it);
}
}
return NULL;
}
void PVMFSMFSPPVRBase::DoRequestPort(PVMFSMFSPBaseNodeCommand& aCmd)
{
PVMF_SM_FSP_PVR_BASE_LOGSTACKTRACE((0, "PVMFSMFSPPVRBase::DoRequestPort - In"));
/*
* This node supports port request only after the graph
* has been fully constructed
*/
if (iGraphConstructComplete)
{
/*
* retrieve port tag
*/
OSCL_String* mimetype;
int32 tag;
aCmd.PVMFSMFSPBaseNodeCommandBase::Parse(tag, mimetype);
/*
* Do not Allocate a new port. RTSP unicast node treats the output
* port from the media layer as its own output port. Find the media
* layer output port corresponding to the input mimetype and hand the
* same out
*/
PVMFPVRBaseTrackInfo* trackInfo = FindTrackInfo(tag);
PVUuid eventuuid = PVMFStreamingManagerNodeEventTypeUUID;
int32 errcode = PVMFStreamingManagerNodeErrorInvalidRequestPortTag;
if (trackInfo == NULL)
{
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase::DoRequestPort: FindTrackInfo failed"));
CommandComplete(iInputCommands, aCmd, PVMFErrArgument, NULL, &eventuuid, &errcode);
return;
}
if (trackInfo->iMediaLayerOutputPort == NULL)
{
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase::DoRequestPort: iMediaLayerOutputPort NULL"));
CommandComplete(iInputCommands, aCmd, PVMFFailure, NULL, &eventuuid, &errcode);
return;
}
PVMF_SM_FSP_PVR_BASE_LOGCMDSEQ((0, "PVMFSMFSPPVRBase::DoRequestPort() - CmdComplete - PVMFSuccess"));
/*
* Return the port pointer to the caller.
*/
CommandComplete(iInputCommands,
aCmd,
PVMFSuccess,
(OsclAny*)(trackInfo->iMediaLayerOutputPort));
PVMF_SM_FSP_PVR_BASE_LOGINFO((0, "PVMFSMFSPPVRBase::DoRequestPort Success"));
}
else
{
PVMF_SM_FSP_PVR_BASE_LOGCMDSEQ((0, "PVMFSMFSPPVRBase::RequestPort() - CmdFailed - PVMFErrInvalidState"));
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase::DoRequestPort Failed - InvalidState"));
CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
}
PVMF_SM_FSP_PVR_BASE_LOGSTACKTRACE((0, "PVMFSMFSPPVRBase::DoRequestPort - Out"));
}
void PVMFSMFSPPVRBase::DoStop(PVMFSMFSPBaseNodeCommand& aCmd)
{
PVMF_SM_FSP_PVR_BASE_LOGSTACKTRACE((0, "PVMFSMFSPPVRBase::DoStop - In"));
iStreamID = 0;
switch (iInterfaceState)
{
case EPVMFNodeStarted:
case EPVMFNodePaused:
{
/*
* Stop for streaming manager cannot be completed unless
* Stop for all the children nodes are complete
*/
PVMFSMFSPChildNodeContainerVector::iterator it;
for (it = iFSPChildNodeContainerVec.begin(); it != iFSPChildNodeContainerVec.end(); it++)
{
PVMFSMFSPCommandContext* internalCmd = RequestNewInternalCmd();
if (internalCmd != NULL)
{
internalCmd->cmd =
it->commandStartOffset +
PVMF_SM_FSP_NODE_INTERNAL_STOP_CMD_OFFSET;
internalCmd->parentCmd = aCmd.iCmd;
OsclAny *cmdContextData = OSCL_REINTERPRET_CAST(OsclAny*, internalCmd);
PVMFNodeInterface* iNode = it->iNode;
iNode->Stop(it->iSessionId, cmdContextData);
it->iNodeCmdState = PVMFSMFSP_NODE_CMD_PENDING;
}
else
{
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase:DoStop:RequestNewInternalCmd - Failed"));
CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
return;
}
}
MoveCmdToCurrentQueue(aCmd);
}
break;
default:
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase::DoStop Failure - Invalid State"));
CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
break;
}
PVMF_SM_FSP_PVR_BASE_LOGSTACKTRACE((0, "PVMFSMFSPPVRBase::DoStop - Out"));
}
void PVMFSMFSPPVRBase::GetAcutalMediaTSAfterSeek()
{
PVMFSMFSPChildNodeContainer* iJitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (iJitterBufferNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return;
}
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)
(iJitterBufferNodeContainer->iExtensions[0]);
PVMFSMFSPChildNodeContainer* iMediaLayerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_MEDIA_LAYER_NODE);
if (iMediaLayerNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return;
}
PVMFMediaLayerNodeExtensionInterface* mlExtIntf =
(PVMFMediaLayerNodeExtensionInterface*)
(iMediaLayerNodeContainer->iExtensions[0]);
if (mlExtIntf == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return;
}
if ((iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_RTSP_URL) ||
(iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_SDP_FILE))
{
iActualMediaDataTS = jbExtIntf->getActualMediaDataTSAfterSeek();
if (iActualMediaDataTSPtr != NULL)
{
*iActualMediaDataTSPtr = iActualMediaDataTS;
PVMF_SM_FSP_PVR_BASE_LOGCOMMANDREPOS((0, "PVMFSMFSPPVRBase::GetAcutalMediaTSAfterSeek - TargetNPT = %d, ActualNPT=%d, ActualMediaDataTS=%d",
iRepositionRequestedStartNPTInMS, *iActualRepositionStartNPTInMSPtr, *iActualMediaDataTSPtr));
}
if (iPVMFDataSourcePositionParamsPtr != NULL)
{
iPVMFDataSourcePositionParamsPtr->iActualMediaDataTS = iActualMediaDataTS;
PVMF_SM_FSP_PVR_BASE_LOGCOMMANDREPOS((0, "PVMFSMFSPPVRBase::GetAcutalMediaTSAfterSeek - ActualMediaDataTS=%d",
iPVMFDataSourcePositionParamsPtr->iActualMediaDataTS));
}
}
}
uint32 PVMFSMFSPPVRBase::getCapabilityMetric(PvmiMIOSession aSession)
{
OSCL_UNUSED_ARG(aSession);
return 0;
}
PVMFStatus PVMFSMFSPPVRBase::GetMediaPresentationInfo(PVMFMediaPresentationInfo& aInfo)
{
SDPInfo* sdpInfo = iSdpInfo.GetRep();
/* Get SDP Session Info */
sessionDescription* sessionInfo = sdpInfo->getSessionInfo();
RtspRangeType *sessionRange = OSCL_CONST_CAST(RtspRangeType*, (sessionInfo->getRange()));
int32 sessionStartTime = 0, sessionStopTime = 0;
sessionRange->convertToMilliSec(sessionStartTime, sessionStopTime);
int32 duration_msec = (sessionStopTime - sessionStartTime);
uint64 duration64;
Oscl_Int64_Utils::set_uint64(duration64, 0, (uint32)duration_msec);
if (sessionRange->end_is_set == true)
{
aInfo.setDurationValue(duration64);
aInfo.setDurationTimeScale(1000);
}
else
{
aInfo.SetDurationAvailable(false);
}
aInfo.setSeekableFlag((!(sessionInfo->getRandomAccessDenied())));
int32 numTracks = sdpInfo->getNumMediaObjects();
SDPAltGroupType sdpAltGroupType = sessionInfo->getSDPAltGroupType();
PVMF_TRACK_INFO_TRACK_ALTERNATE_TYPE altType = PVMF_TRACK_ALTERNATE_TYPE_UNDEFINED;
if (sdpAltGroupType == SDP_ALT_GROUP_LANGUAGE)
{
altType = PVMF_TRACK_ALTERNATE_TYPE_LANGUAGE;
}
else if (sdpAltGroupType == SDP_ALT_GROUP_BANDWIDTH)
{
altType = PVMF_TRACK_ALTERNATE_TYPE_BANDWIDTH;
}
for (int32 i = 0; i < numTracks; i++)
{
/*
* Get the vector of mediaInfo as there can
* alternates for each track
*/
Oscl_Vector<mediaInfo*, SDPParserAlloc> mediaInfoVec =
sdpInfo->getMediaInfo(i);
uint32 minfoVecLen = mediaInfoVec.size();
for (uint32 j = 0; j < minfoVecLen; j++)
{
mediaInfo* mInfo = mediaInfoVec[j];
if (mInfo == NULL)
{
return PVMFFailure;
}
RtspRangeType *mediaRange = mInfo->getRtspRange();
int32 mediaStartTime = 0, mediaStopTime = 0;
mediaRange->convertToMilliSec(mediaStartTime, mediaStopTime);
int32 mediaDuration_ms = mediaStopTime - mediaStartTime;
uint64 mediaDuration64;
Oscl_Int64_Utils::set_uint64(mediaDuration64, 0, (uint32)mediaDuration_ms);
PVMFTrackInfo trackInfo;
Oscl_Vector<PayloadSpecificInfoTypeBase*, SDPParserAlloc> payloadVector;
payloadVector = mInfo->getPayloadSpecificInfoVector();
if (payloadVector.size() == 0)
{
return PVMFFailure;
}
/*
* There can be multiple payloads per media segment.
* We only support one for now, so
* use just the first payload
*/
PayloadSpecificInfoTypeBase* payloadInfo = payloadVector[0];
// set config for later
int32 configSize = payloadInfo->configSize;
OsclAny* config = payloadInfo->configHeader.GetRep();
OSCL_StackString<256> mimeString;
const char* mimeType = mInfo->getMIMEType();
mimeString += mimeType;
trackInfo.setTrackMimeType(mimeString);
uint32 trackID = mInfo->getMediaInfoID();
trackInfo.setTrackID(trackID);
trackInfo.setPortTag(trackID);
trackInfo.setTrackBitRate(mInfo->getBitrate());
if (mediaRange->end_is_set == true)
{
trackInfo.setTrackDurationValue(mediaDuration64);
}
else
{
trackInfo.SetDurationAvailable(false);
}
if ((configSize > 0) && (config != NULL))
{
OsclMemAllocDestructDealloc<uint8> my_alloc;
OsclRefCounter* my_refcnt;
uint aligned_refcnt_size =
oscl_mem_aligned_size(sizeof(OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >));
uint8* my_ptr = GetMemoryChunk(my_alloc, aligned_refcnt_size + configSize);
if (!my_ptr)
return false;
my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >(my_ptr));
my_ptr += aligned_refcnt_size;
OsclMemoryFragment memfrag;
memfrag.len = (uint32)configSize;
memfrag.ptr = my_ptr;
oscl_memcpy((void*)(memfrag.ptr), (const void*)config, memfrag.len);
OsclRefCounterMemFrag tmpRefcntMemFrag(memfrag, my_refcnt, memfrag.len);
trackInfo.setTrackConfigInfo(tmpRefcntMemFrag);
}
int32 dependsOnTrackID = mInfo->getDependsOnTrackID();
if (dependsOnTrackID != -1)
{
trackInfo.setDependsOn();
mediaInfo* baseMediaInfo = sdpInfo->getMediaInfoBasedOnDependsOnID(dependsOnTrackID);
if (baseMediaInfo == NULL)
{
return PVMFFailure;
}
trackInfo.addDependsOnTrackID(baseMediaInfo->getMediaInfoID());
}
if (altType != PVMF_TRACK_ALTERNATE_TYPE_UNDEFINED)
{
/* Expose alternate track ids */
trackInfo.setTrackAlternates(altType);
for (uint32 k = 0; k < minfoVecLen; k++)
{
mediaInfo* mInfo = mediaInfoVec[k];
if (mInfo == NULL)
{
return PVMFFailure;
}
uint32 altID = mInfo->getMediaInfoID();
if (altID != trackID)
{
trackInfo.addAlternateTrackID((int32)altID);
}
}
}
aInfo.addTrackInfo(trackInfo);
}
}
iCompleteMediaPresetationInfo = aInfo;
return PVMFSuccess;
}
uint32 PVMFSMFSPPVRBase::GetNumMetadataKeys(char* aQueryKeyString)
{
//Metadata is avaialable in three forms
//1. Metadata common to streaming of all type of payloads and FF specific metadata
//2. Streaming specific metadata
//3. CPM metadata
//First two types are avaiable in iAvailableMetaDatakeys vector
//Third type can be had from metadataextension interface
//base class considers count of all of these
return PVMFSMFSPBaseNode::GetNumMetadataKeysBase(aQueryKeyString);
}
uint32 PVMFSMFSPPVRBase::GetNumMetadataValues(PVMFMetadataList& aKeyList)
{
//Metadata is avaialable in three forms
//1. Metadata common to streaming of all type of payloads and FF specific metadata
//2. Streaming specific metadata
//3. CPM metadata
//First two types are avaiable in iAvailableMetaDatakeys vector
//Third type can be had from metadataextension interface
//Base class considers count of all of these
return PVMFSMFSPBaseNode::GetNumMetadataValuesBase(aKeyList);
}
PVMFStatus PVMFSMFSPPVRBase::getParametersSync(PvmiMIOSession aSession, PvmiKeyType aIdentifier,
PvmiKvp*& aParameters, int& aNumParamElements,
PvmiCapabilityContext aContext)
{
OSCL_UNUSED_ARG(aSession);
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, "PVMFSMFSPPVRBase::getParametersSync() Invalid key string"));
return PVMFErrArgument;
}
// Retrieve the second component from the key string
pv_mime_string_extract_type(1, aIdentifier, compstr);
// Check if it is key string for streaming manager
if (pv_mime_strcmp(compstr, _STRLIT_CHAR("net")) < 0)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFSMFSPPVRBase::getParametersSync() Unsupported key"));
return PVMFFailure;
}
if (compcount == 2)
{
// Since key is "x-pvmf/net" return all
// nodes available at this level. Ignore attribute
// since capability is only allowed
// Allocate memory for the KVP list
aParameters = (PvmiKvp*)oscl_malloc(StreamingManagerConfig_NumBaseKeys * sizeof(PvmiKvp));
if (aParameters == NULL)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFSMFSPPVRBase::getParametersSync() Memory allocation for KVP failed"));
return PVMFErrNoMemory;
}
oscl_memset(aParameters, 0, StreamingManagerConfig_NumBaseKeys*sizeof(PvmiKvp));
// Allocate memory for the key strings in each KVP
PvmiKeyType memblock = (PvmiKeyType)oscl_malloc(StreamingManagerConfig_NumBaseKeys * SMCONFIG_KEYSTRING_SIZE * sizeof(char));
if (memblock == NULL)
{
oscl_free(aParameters);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFSMFSPPVRBase::getParametersSync() Memory allocation for key string failed"));
return PVMFErrNoMemory;
}
oscl_strset(memblock, 0, StreamingManagerConfig_NumBaseKeys*SMCONFIG_KEYSTRING_SIZE*sizeof(char));
// Assign the key string buffer to each KVP
uint32 j;
for (j = 0; j < StreamingManagerConfig_NumBaseKeys; ++j)
{
aParameters[j].key = memblock + (j * SMCONFIG_KEYSTRING_SIZE);
}
// Copy the requested info
for (j = 0; j < StreamingManagerConfig_NumBaseKeys; ++j)
{
oscl_strncat(aParameters[j].key, _STRLIT_CHAR("x-pvmf/net/"), 17);
oscl_strncat(aParameters[j].key, StreamingManagerConfig_BaseKeys[j].iString, oscl_strlen(StreamingManagerConfig_BaseKeys[j].iString));
oscl_strncat(aParameters[j].key, _STRLIT_CHAR(";type="), 6);
switch (StreamingManagerConfig_BaseKeys[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 (StreamingManagerConfig_BaseKeys[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[SMCONFIG_KEYSTRING_SIZE-1] = 0;
}
aNumParamElements = StreamingManagerConfig_NumBaseKeys;
}
else if (compcount == 3)
{
pv_mime_string_extract_type(2, aIdentifier, compstr);
// Determine what is requested
PvmiKvpAttr reqattr = GetAttrTypeFromKeyString(aIdentifier);
if (reqattr == PVMI_KVPATTR_UNKNOWN)
{
reqattr = PVMI_KVPATTR_CUR;
}
uint i;
for (i = 0; i < StreamingManagerConfig_NumBaseKeys; i++)
{
if (pv_mime_strcmp(compstr, (char*)(StreamingManagerConfig_BaseKeys[i].iString)) >= 0)
{
break;
}
}
if (i == StreamingManagerConfig_NumBaseKeys)
{
// no match found
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFSMFSPPVRBase:getParametersSync() Unsupported key"));
return PVMFErrArgument;
}
PVMFStatus retval = GetConfigParameter(aParameters, aNumParamElements, i, reqattr);
if (retval != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFSMFSPPVRBase::getParametersSync() "
"Retrieving streaming manager parameter failed"));
return retval;
}
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFSMFSPPVRBase::getParametersSync() Unsupported key"));
return PVMFErrArgument;
}
return PVMFSuccess;
}
void PVMFSMFSPPVRBase::HandleMediaLayerCommandCompleted(const PVMFCmdResp& aResponse, bool& aPerformErrHandling)
{
aPerformErrHandling = false;
PVMFSMFSPChildNodeContainer* iMediaLayerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_MEDIA_LAYER_NODE);
if (iMediaLayerNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return;
}
PVMFSMFSPCommandContext *cmdContextData =
OSCL_REINTERPRET_CAST(PVMFSMFSPCommandContext*, aResponse.GetContext());
cmdContextData->oFree = true;
PVMF_SM_FSP_PVR_BASE_LOGINFO((0, "PVMFSMFSPPVRBase::HandleMediaLayerCommandCompleted In - cmd [%d] iMediaLayerNodeContainer->iNodeCmdState [%d] iInterfaceState[%d]", cmdContextData->cmd, iMediaLayerNodeContainer->iNodeCmdState, iInterfaceState));
OSCL_ASSERT(cmdContextData->cmd != PVMF_SM_FSP_MEDIA_LAYER_QUERY_UUID);
OSCL_ASSERT(cmdContextData->cmd != PVMF_SM_FSP_MEDIA_LAYER_QUERY_INTERFACE);
if (iMediaLayerNodeContainer->iNodeCmdState == PVMFSMFSP_NODE_CMD_PENDING)
{
if (cmdContextData->cmd == PVMF_SM_FSP_MEDIA_LAYER_REQUEST_PORT)
{
//This is last of the request ports
OSCL_ASSERT(iMediaLayerNodeContainer->iNumRequestPortsPending > 0);
if (--iMediaLayerNodeContainer->iNumRequestPortsPending == 0)
{
iMediaLayerNodeContainer->iNodeCmdState = PVMFSMFSP_NODE_CMD_IDLE;
}
}
else
{
iMediaLayerNodeContainer->iNodeCmdState = PVMFSMFSP_NODE_CMD_IDLE;
}
}
else if (iMediaLayerNodeContainer->iNodeCmdState == PVMFSMFSP_NODE_CMD_CANCEL_PENDING)
{
if ((cmdContextData->parentCmd == PVMF_SMFSP_NODE_CANCELALLCOMMANDS) || (cmdContextData->parentCmd == PVMF_SMFSP_NODE_CANCELCOMMAND) || (cmdContextData->parentCmd == PVMF_SMFSP_NODE_CANCEL_DUE_TO_ERROR))
{
iMediaLayerNodeContainer->iNodeCmdState = PVMFSMFSP_NODE_CMD_IDLE;
}
else
{
PVMF_SM_FSP_PVR_BASE_LOGINFO((0, "PVMFSMFSPPVRBase::HandleMediaLayerCommandCompleted cmd completion for cmd other than cancel during cancellation"));
//if cancel is pending and if the parent cmd is not cancel then this is
//is most likely the cmd that is being cancelled.
//we ignore cmd completes from child nodes if cancel is pending
//we simply wait on cancel complete and cancel the pending cmd
return;
}
}
else if (iMediaLayerNodeContainer->iNodeCmdState == PVMFSMFSP_NODE_CMD_IDLE)
{
PVMF_SM_FSP_PVR_BASE_LOGINFO((0, "PVMFSMFSPPVRBase::HandleMediaLayerCommandCompleted container in IDLE state already"));
/*
* This is to handle a usecase where a node reports cmd complete for cancelall first
* and then reports cmd complete on the cmd that was meant to be cancelled.
* There are two possible scenarios that could arise based on this:
* i) SM node has reported cmd complete on both canceall and the cmd meant to be cancelled
* to engine by the time cmd complete on the cmd that was meant to be cancelled arrives
* from the child node. In this case iNodeCmdState would be PVMFSMFSP_NODE_CMD_NO_PENDING.
* ii) SM node is still waiting on some other child nodes to complete cancelall.
* In this case iNodeCmdState would be PVMFSMFSP_NODE_CMD_IDLE.
* In either case iNodeCmdState cannot be PVMFSMFSP_NODE_CMD_PENDING or PVMFSMFSP_NODE_CMD_IDLE
* (recall that we call ResetNodeContainerCmdState prior to issuing cancelall)
* Or this is the case of node reporting cmd complete multiple times for a cmd, which
* also can be ignored
*/
return;
}
if (EPVMFNodeError == iInterfaceState)//If interface is in err state, let the err handler do processing
{
aPerformErrHandling = true;
return;
}
if (aResponse.GetCmdStatus() != PVMFSuccess)
{
if (aResponse.GetCmdStatus() != PVMFErrCancelled)
{
aPerformErrHandling = true;
}
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase::HandleMediaLayerCommandCompleted - Command failed - context=0x%x, status=0x%x", aResponse.GetContext(), aResponse.GetCmdStatus()));
if (IsBusy())
{
Cancel();
RunIfNotReady();
}
return;
}
switch (cmdContextData->cmd)
{
case PVMF_SM_FSP_MEDIA_LAYER_INIT:
CompleteInit();
break;
case PVMF_SM_FSP_MEDIA_LAYER_PREPARE:
CompletePrepare();
break;
case PVMF_SM_FSP_MEDIA_LAYER_START:
{
CompleteStart();
}
break;
case PVMF_SM_FSP_MEDIA_LAYER_STOP:
{
CompleteStop();
}
break;
case PVMF_SM_FSP_MEDIA_LAYER_FLUSH:
CompleteFlush();
break;
case PVMF_SM_FSP_MEDIA_LAYER_PAUSE:
CompletePause();
break;
case PVMF_SM_FSP_MEDIA_LAYER_RESET:
CompleteReset();
break;
case PVMF_SM_FSP_MEDIA_LAYER_REQUEST_PORT:
{
PVMFMediaLayerNodeExtensionInterface* mlExtIntf =
(PVMFMediaLayerNodeExtensionInterface*)
(iMediaLayerNodeContainer->iExtensions[0]);
if (mlExtIntf == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return;
}
/*
* Save the port in TrackInfo
*/
PVMFPVRBaseTrackInfo* trackInfo =
FindTrackInfo(cmdContextData->portContext.trackID);
PVMFPortInterface* port =
(PVMFPortInterface*)aResponse.GetEventData();
OSCL_ASSERT(trackInfo && port);
if (!trackInfo || !port)
return;
if (cmdContextData->portContext.portTag ==
PVMF_MEDIALAYER_PORT_TYPE_INPUT)
{
if (trackInfo)
trackInfo->iMediaLayerInputPort = port;
iMediaLayerNodeContainer->iInputPorts.push_back(port);
}
else if (cmdContextData->portContext.portTag ==
PVMF_MEDIALAYER_PORT_TYPE_OUTPUT)
{
if (trackInfo)
trackInfo->iMediaLayerOutputPort = port;
iMediaLayerNodeContainer->iOutputPorts.push_back(port);
uint32 preroll32 = 0;
bool live = false;
mlExtIntf->setOutPortStreamParams(port,
cmdContextData->portContext.trackID,
preroll32,
live);
}
mediaInfo* mInfo = NULL;
SDPInfo* sdpInfo = iSdpInfo.GetRep();
if (sdpInfo == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return;
}
if (trackInfo)
{
mInfo = sdpInfo->getMediaInfoBasedOnID(trackInfo->trackID);
mlExtIntf->setPortMediaParams(port, trackInfo->iTrackConfig, mInfo);
}
CompleteGraphConstruct();
}
break;
case PVMF_SM_FSP_MEDIA_LAYER_CANCEL_ALL_COMMANDS:
{
CompleteChildNodesCmdCancellation();
}
break;
default:
break;
}
return;
}
bool PVMFSMFSPPVRBase::IsFSPInternalCmd(PVMFCommandId aId)
{
OSCL_UNUSED_ARG(aId);
return false;
}
void PVMFSMFSPPVRBase::NodeCommandCompleted(const PVMFCmdResp& aResponse)
{
PVMF_SM_FSP_PVR_BASE_LOGINFO((0, "PVMFSMFSPPVRBase::NodeCommandCompleted"));
bool performErrHandling = false;
HandleChildNodeCommandCompletion(aResponse, performErrHandling);
PVMF_SM_FSP_PVR_BASE_LOGINFO((0, "PVMFSMFSPPVRBase::NodeCommandCompleted - performErrHandling[%d]", performErrHandling));
if (performErrHandling == true)
{
HandleError(aResponse);
}
return;
}
PVMFStatus PVMFSMFSPPVRBase::PopulateAvailableMetadataKeys()
{
int32 leavecode = OsclErrNone;
OSCL_TRY(leavecode,
PVMFSMFSPBaseNode::PopulateAvailableMetadataKeys();
//Add feature specific streaming metadata keys
// Create the parameter string for the index range
if (iMetaDataInfo->iNumTracks > 0)
{
char indexparam[18];
oscl_snprintf(indexparam, 18, ";index=0...%d", (iMetaDataInfo->iNumTracks - 1));
indexparam[17] = NULL_TERM_CHAR;
iAvailableMetadataKeys.push_front(PVMFSTREAMINGMGRNODE_TRACKINFO_BITRATE_KEY);
iAvailableMetadataKeys[0] += indexparam;
}
iAvailableMetadataKeys.push_back(PVMFSTREAMINGMGRNODE_PAUSE_DENIED_KEY);
);
if (leavecode != OsclErrNone)
return leavecode;
else
return PVMFSuccess;
}
void PVMFSMFSPPVRBase::PopulateDRMInfo()
{
PVMF_SM_FSP_PVR_BASE_LOGSTACKTRACE((0, "PVMFSMFSPPVRBase::PopulateDRMInfo() In"));
PVMF_SM_FSP_PVR_BASE_LOGSTACKTRACE((0, "PVMFSMFSPPVRBase::PopulateDRMInfo() - CPM not supported yet"));
}
bool PVMFSMFSPPVRBase::PopulateTrackInfoVec()
{
if (iSelectedMediaPresetationInfo.getNumTracks() == 0)
{
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase:PopulateTrackInfoVec - Selected Track List Empty"));
return false;
}
/*
* Get selected tracks
*/
int32 numTracks = iSdpInfo->getNumMediaObjects();
if (numTracks > 0)
{
for (int32 i = 0; i < numTracks; i++)
{
/*
* Get the vector of mediaInfo as there can
* alternates for each track
*/
Oscl_Vector<mediaInfo*, SDPParserAlloc> mediaInfoVec =
iSdpInfo->getMediaInfo(i);
uint32 minfoVecLen = mediaInfoVec.size();
for (uint32 j = 0; j < minfoVecLen; j++)
{
mediaInfo* mInfo = mediaInfoVec[j];
if (mInfo == NULL)
{
return false;
}
if (mInfo->getSelect())
{
PVMFPVRBaseTrackInfo trackInfo;
trackInfo.trackID = mInfo->getMediaInfoID();
trackInfo.iTransportType += _STRLIT_CHAR("RTP");
Oscl_Vector<PayloadSpecificInfoTypeBase*, SDPParserAlloc> payloadVector;
payloadVector = mInfo->getPayloadSpecificInfoVector();
if (payloadVector.size() == 0)
{
return false;
}
/*
* There can be multiple payloads per media segment.
* We only support one for now, so
* use just the first payload
*/
PayloadSpecificInfoTypeBase* payloadInfo = payloadVector[0];
trackInfo.trackTimeScale = payloadInfo->sampleRate;
// set config for later
int32 configSize = payloadInfo->configSize;
OsclAny* config = payloadInfo->configHeader.GetRep();
const char* mimeType = mInfo->getMIMEType();
trackInfo.iMimeType += mimeType;
trackInfo.portTag = mInfo->getMediaInfoID();
trackInfo.bitRate = mInfo->getBitrate();
if (mInfo->getReportFrequency() > 0)
{
trackInfo.iRateAdaptation = true;
trackInfo.iRateAdaptationFeedBackFrequency =
mInfo->getReportFrequency();
}
if ((mInfo->getRTCPReceiverBitRate() >= 0) &&
(mInfo->getRTCPSenderBitRate() >= 0))
{
trackInfo.iRR = mInfo->getRTCPReceiverBitRate();
trackInfo.iRS = mInfo->getRTCPSenderBitRate();
trackInfo.iRTCPBwSpecified = true;
}
if ((configSize > 0) && (config != NULL))
{
OsclMemAllocDestructDealloc<uint8> my_alloc;
OsclRefCounter* my_refcnt;
uint aligned_refcnt_size =
oscl_mem_aligned_size(sizeof(OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >));
uint8* my_ptr = GetMemoryChunk(my_alloc, aligned_refcnt_size + configSize);
if (!my_ptr)
return false;
my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >(my_ptr));
my_ptr += aligned_refcnt_size;
OsclMemoryFragment memfrag;
memfrag.len = (uint32)configSize;
memfrag.ptr = my_ptr;
oscl_memcpy((void*)(memfrag.ptr), (const void*)config, memfrag.len);
OsclRefCounterMemFrag tmpRefcntMemFrag(memfrag, my_refcnt, memfrag.len);
trackInfo.iTrackConfig = tmpRefcntMemFrag;
}
iTrackInfoVec.push_back(trackInfo);
}
}
}
}
else
{
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase:PopulateTrackInfoVec - Selected Track List Empty"));
return false;
}
return true;
}
bool PVMFSMFSPPVRBase::ProcessCommand(PVMFSMFSPBaseNodeCommand& aCmd)
{
if (EPVMFNodeError == iInterfaceState)
{
if (iCurrErrHandlingCommand.size() > 0)
{
return false;
}
switch (aCmd.iCmd)
{
case PVMF_SMFSP_NODE_CANCEL_DUE_TO_ERROR:
DoCancelAllPendingCommands(aCmd);
break;
case PVMF_SMFSP_NODE_RESET_DUE_TO_ERROR:
DoResetDueToErr(aCmd);
break;
}
return true;
}
/*
* normally this node will not start processing one command
* until the prior one is finished. However, a hi priority
* command such as Cancel must be able to interrupt a command
* in progress.
*/
if ((iCurrentCommand.size() > 0 && !aCmd.hipri()
&& aCmd.iCmd != PVMF_SMFSP_NODE_CANCEL_GET_LICENSE)
|| iCancelCommand.size() > 0)
return false;
OSCL_ASSERT(aCmd.iCmd != PVMF_SMFSP_NODE_QUERYUUID);
OSCL_ASSERT(aCmd.iCmd != PVMF_SMFSP_NODE_SET_DATASOURCE_RATE);
switch (aCmd.iCmd)
{
/* node interface commands */
case PVMF_SMFSP_NODE_QUERYINTERFACE:
DoQueryInterface(aCmd);
break;
case PVMF_SMFSP_NODE_INIT:
DoInit(aCmd);
break;
case PVMF_SMFSP_NODE_PREPARE:
DoPrepare(aCmd);
break;
case PVMF_SMFSP_NODE_REQUESTPORT:
DoRequestPort(aCmd);
break;
case PVMF_SMFSP_NODE_RELEASEPORT:
DoReleasePort(aCmd);
break;
case PVMF_SMFSP_NODE_START:
DoStart(aCmd);
break;
case PVMF_SMFSP_NODE_STOP:
DoStop(aCmd);
break;
case PVMF_SMFSP_NODE_FLUSH:
DoFlush(aCmd);
break;
case PVMF_SMFSP_NODE_PAUSE:
DoPause(aCmd);
break;
case PVMF_SMFSP_NODE_RESET:
DoReset(aCmd);
break;
case PVMF_SMFSP_NODE_CANCELALLCOMMANDS:
DoCancelAllCommands(aCmd);
break;
case PVMF_SMFSP_NODE_CANCELCOMMAND:
DoCancelCommand(aCmd);
break;
/* add extention interface commands */
case PVMF_SMFSP_NODE_SET_DATASOURCE_POSITION:
if (iPlayListRepositioning == true)
{
DoSetDataSourcePositionPlayList(aCmd);
}
else
{
DoSetDataSourcePosition(aCmd);
}
break;
case PVMF_SMFSP_NODE_QUERY_DATASOURCE_POSITION:
DoQueryDataSourcePosition(aCmd);
break;
case PVMF_SMFSP_NODE_GETNODEMETADATAKEYS:
{
PVMFStatus status = DoGetMetadataKeys(aCmd);
if (status != PVMFPending)
{
CommandComplete(iInputCommands, aCmd, status);
}
else
{
MoveCmdToCurrentQueue(aCmd);
}
}
break;
case PVMF_SMFSP_NODE_GETNODEMETADATAVALUES:
{
PVMFStatus status = DoGetMetadataValues(aCmd);
if (status != PVMFPending)
{
CommandComplete(iInputCommands, aCmd, status);
}
else
{
MoveCmdToCurrentQueue(aCmd);
}
}
break;
case PVMF_SMFSP_NODE_GET_LICENSE_W:
{
PVMFStatus status = DoGetLicense(aCmd, true);
if (status == PVMFPending)
{
MoveCmdToCurrentQueue(aCmd);
}
else
{
CommandComplete(iInputCommands, aCmd, status);
}
}
break;
case PVMF_SMFSP_NODE_GET_LICENSE:
{
PVMFStatus status = DoGetLicense(aCmd);
if (status == PVMFPending)
{
MoveCmdToCurrentQueue(aCmd);
}
else
{
CommandComplete(iInputCommands, aCmd, status);
}
}
break;
case PVMF_SMFSP_NODE_CANCEL_GET_LICENSE:
DoCancelGetLicense(aCmd);
break;
case PVMF_SMFSP_NODE_CAPCONFIG_SETPARAMS:
{
PvmiMIOSession session;
PvmiKvp* aParameters;
int num_elements;
PvmiKvp** ppRet_kvp;
aCmd.Parse(session, aParameters, num_elements, ppRet_kvp);
setParametersSync(NULL, aParameters, num_elements, *ppRet_kvp);
ciObserver->SignalEvent(aCmd.iId);
}
break;
/* internal commands common to all types of streaming*/
case PVMF_SMFSP_NODE_CONSTRUCT_SESSION: //to construct the graph
{
PVMFStatus status = DoGraphConstruct();
if (status != PVMFPending)
{
InternalCommandComplete(iInputCommands, aCmd, status);
}
else
{
MoveCmdToCurrentQueue(aCmd);
}
}
break;
/* unknown commands */
default:
/* unknown command type */
CommandComplete(iInputCommands, aCmd, PVMFErrNotSupported);
break;
}
return true;
}
void PVMFSMFSPPVRBase::ReleaseChildNodesExtentionInterface()
{
uint32 i, j;
for (i = 0; i < iFSPChildNodeContainerVec.size(); i++)
{
for (j = 0; j < iFSPChildNodeContainerVec[i].iExtensions.size(); j++)
{
PVInterface* extIntf = iFSPChildNodeContainerVec[i].iExtensions[j];
extIntf->removeRef();
extIntf = NULL;
}
iFSPChildNodeContainerVec[i].iExtensions.clear();
}
}
PVMFStatus PVMFSMFSPPVRBase::ReleaseNodeMetadataKeys(PVMFMetadataList& aKeyList,
uint32 aStartingKeyIndex,
uint32 aEndKeyIndex)
{
//no allocation for any keys took in derived class so just calling base class release functions
return ReleaseNodeMetadataKeysBase(aKeyList, aStartingKeyIndex, aEndKeyIndex);
}
PVMFStatus PVMFSMFSPPVRBase::ReleaseNodeMetadataValues(Oscl_Vector<PvmiKvp, OsclMemAllocator>& aValueList,
uint32 aStartingValueIndex,
uint32 aEndValueIndex)
{
return ReleaseNodeMetadataValuesBase(aValueList, aStartingValueIndex, aEndValueIndex);
}
PVMFStatus PVMFSMFSPPVRBase::releaseParameters(PvmiMIOSession aSession,
PvmiKvp* aParameters,
int num_elements)
{
OSCL_UNUSED_ARG(aSession);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFSMFSPPVRBase::releaseParameters() In"));
if (aParameters == NULL || num_elements < 1)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFSMFSPPVRBase::releaseParameters() 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, "PVMFSMFSPPVRBase::releaseParameters() 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
if (pv_mime_strcmp(compstr, _STRLIT_CHAR("net")) >= 0)
{
// Go through each KVP and release memory for value if allocated from heap
for (int32 i = 0; i < num_elements; ++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, "PVMFSMFSPPVRBase::releaseParameters() 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_WCHARPTR && aParameters[i].value.pWChar_value != NULL)
{
oscl_free(aParameters[i].value.pWChar_value);
aParameters[i].value.pWChar_value = NULL;
}
else 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);
}
}
}
oscl_free(aParameters[0].key);
// Free memory for the parameter list
oscl_free(aParameters);
aParameters = NULL;
}
else
{
// Unknown key string
return PVMFErrArgument;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFSMFSPPVRBase::releaseParameters() Out"));
return PVMFSuccess;
}
bool PVMFSMFSPPVRBase::RequestJitterBufferPorts(int32 portType,
uint32 &numPortsRequested)
{
PVMFSMFSPChildNodeContainer* nodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (nodeContainer == NULL)
{
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase:RequestJitterBufferPorts - getChildNodeContainer Failed"));
return false;
}
numPortsRequested = 0;
/*
* Request port - all jitter buffer input ports
* are even numbered and output and rtcp ports are odd numbered
*/
int32 portTagStart = portType;
if ((iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_RTSP_URL)
|| (iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_SDP_FILE)
)
{
for (uint32 i = 0; i < iTrackInfoVec.size(); i++)
{
PVMFPVRBaseTrackInfo trackInfo = iTrackInfoVec[i];
PVMFSMFSPCommandContext* internalCmd = RequestNewInternalCmd();
if (internalCmd != NULL)
{
internalCmd->cmd =
nodeContainer->commandStartOffset +
PVMF_SM_FSP_NODE_INTERNAL_REQUEST_PORT_OFFSET;
internalCmd->parentCmd = PVMF_SMFSP_NODE_CONSTRUCT_SESSION;
internalCmd->portContext.trackID = trackInfo.trackID;
internalCmd->portContext.portTag = portType;
OsclAny *cmdContextData = OSCL_REINTERPRET_CAST(OsclAny*, internalCmd);
PVMFNodeInterface* iNode = nodeContainer->iNode;
OSCL_StackString<32> portConfig = trackInfo.iTransportType;
portConfig += _STRLIT_CHAR("/");
portConfig += trackInfo.iMimeType;
iNode->RequestPort(nodeContainer->iSessionId,
portTagStart,
&(portConfig),
cmdContextData);
numPortsRequested++;
nodeContainer->iNumRequestPortsPending++;
nodeContainer->iNodeCmdState = PVMFSMFSP_NODE_CMD_PENDING;
}
else
{
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase:RequestJitterBufferPorts - RequestNewInternalCmd Failed"));
return false;
}
portTagStart += 3;
}
return true;
}
return false;
}
bool PVMFSMFSPPVRBase::RequestMediaLayerPorts(int32 portType,
uint32& numPortsRequested)
{
PVMFSMFSPChildNodeContainer* nodeContainer =
getChildNodeContainer(PVMF_SM_FSP_MEDIA_LAYER_NODE);
if (nodeContainer == NULL)
{
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase:RequestMediaLayerPorts - getChildNodeContainer Failed"));
return false;
}
numPortsRequested = 0;
/*
* Request port - all media layer input ports
* are even numbered and output are odd numbered
*/
int32 portTagStart = portType;
if ((iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_RTSP_URL)
|| (iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_SDP_FILE)
)
{
for (uint32 i = 0; i < iTrackInfoVec.size(); i++)
{
PVMFPVRBaseTrackInfo trackInfo = iTrackInfoVec[i];
PVMFSMFSPCommandContext* internalCmd = RequestNewInternalCmd();
if (internalCmd != NULL)
{
internalCmd->cmd =
nodeContainer->commandStartOffset +
PVMF_SM_FSP_NODE_INTERNAL_REQUEST_PORT_OFFSET;
internalCmd->parentCmd = PVMF_SMFSP_NODE_CONSTRUCT_SESSION;
internalCmd->portContext.trackID = trackInfo.trackID;
internalCmd->portContext.portTag = portType;
OsclAny *cmdContextData =
OSCL_REINTERPRET_CAST(OsclAny*, internalCmd);
PVMFNodeInterface* iNode = nodeContainer->iNode;
iNode->RequestPort(nodeContainer->iSessionId,
portTagStart,
&(trackInfo.iMimeType),
cmdContextData);
numPortsRequested++;
nodeContainer->iNumRequestPortsPending++;
nodeContainer->iNodeCmdState = PVMFSMFSP_NODE_CMD_PENDING;
}
else
{
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase:RequestMediaLayerPorts - RequestNewInternalCmd Failed"));
return false;
}
portTagStart += 2;
}
return true;
}
//error
return false;
}
void PVMFSMFSPPVRBase::ResetStopCompleteParams()
{
iPlaylistPlayInProgress = false;
iRepositionRequestedStartNPTInMS = 0;
}
PVMFStatus PVMFSMFSPPVRBase::SelectTracks(PVMFMediaPresentationInfo& aInfo)
{
SDPInfo* sdpInfo = iSdpInfo.GetRep();
if (sdpInfo == NULL)
{
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase:SelectTracks - SDP Not Available"));
return PVMFErrArgument;
}
int32 numTracks = aInfo.getNumTracks();
for (int32 i = 0; i < numTracks; i++)
{
PVMFTrackInfo* trackInfo = aInfo.getTrackInfo(i);
uint32 trackID = trackInfo->getTrackID();
mediaInfo* mInfo =
sdpInfo->getMediaInfoBasedOnID(trackID);
if (mInfo == NULL)
{
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase:SelectTracks - Invalid SDP TrackID"));
return PVMFErrArgument;
}
mInfo->setSelect();
/* Set selected field in meta info */
Oscl_Vector<PVMFSMTrackMetaDataInfo, OsclMemAllocator>::iterator it;
for (it = iMetaDataInfo->iTrackMetaDataInfoVec.begin(); it != iMetaDataInfo->iTrackMetaDataInfoVec.end(); it++)
{
if (it->iTrackID == trackID)
{
it->iTrackSelected = true;
}
}
}
iSelectedMediaPresetationInfo = aInfo;
return PVMFSuccess;
}
PVMFStatus PVMFSMFSPPVRBase::SetClientPlayBackClock(PVMFMediaClock* aClientClock)
{
PVMFSMFSPChildNodeContainer* iJitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (iJitterBufferNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return PVMFFailure;
}
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)
(iJitterBufferNodeContainer->iExtensions[0]);
jbExtIntf->setClientPlayBackClock(aClientClock);
PVMFSMFSPChildNodeContainer* iMediaLayerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_MEDIA_LAYER_NODE);
if (iMediaLayerNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return PVMFFailure;
}
PVMFMediaLayerNodeExtensionInterface* mlExtIntf =
(PVMFMediaLayerNodeExtensionInterface*)
(iMediaLayerNodeContainer->iExtensions[0]);
mlExtIntf->setClientPlayBackClock(aClientClock);
return PVMFSuccess;
}
void PVMFSMFSPPVRBase::setContextParameters(PvmiMIOSession aSession,
PvmiCapabilityContext& aContext,
PvmiKvp* aParameters,
int num_parameter_elements)
{
OSCL_UNUSED_ARG(aSession);
OSCL_UNUSED_ARG(aContext);
OSCL_UNUSED_ARG(aParameters);
OSCL_UNUSED_ARG(num_parameter_elements);
// not supported
OSCL_LEAVE(PVMFErrNotSupported);
}
PVMFStatus PVMFSMFSPPVRBase::SetEstimatedServerClock(PVMFMediaClock* aClientClock)
{
OSCL_UNUSED_ARG(aClientClock);
return PVMFErrNotSupported;
}
void PVMFSMFSPPVRBase::setJitterBufferDurationInMilliSeconds(uint32 duration)
{
iJitterBufferDurationInMilliSeconds = duration;
}
void PVMFSMFSPPVRBase::setObserver(PvmiConfigAndCapabilityCmdObserver* aObserver)
{
ciObserver = aObserver;
}
void PVMFSMFSPPVRBase::setParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters,
int num_elements, PvmiKvp* &aRet_kvp)
{
OSCL_UNUSED_ARG(aSession);
if (aParameters == NULL || num_elements < 1)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFSMFSPPVRBase::setParametersSync() KVP list is NULL or number of elements is 0"));
return;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFSMFSPPVRBase::setParametersSync() In"));
// Go through each parameter
for (int paramind = 0; paramind < num_elements; ++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
aRet_kvp = &aParameters[paramind];
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFSMFSPPVRBase::setParametersSync() Unsupported key"));
return;
}
// 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 the streaming manager
if (pv_mime_strcmp(compstr, _STRLIT_CHAR("net")) >= 0)
{
if (compcount == 3)
{
pv_mime_string_extract_type(2, aParameters[paramind].key, compstr);
uint i;
for (i = 0; i < StreamingManagerConfig_NumBaseKeys; i++)
{
if (pv_mime_strcmp(compstr, (char*)(StreamingManagerConfig_BaseKeys[i].iString)) >= 0)
{
break;
}
}
if (StreamingManagerConfig_NumBaseKeys == i)
{
// invalid third component
aRet_kvp = &aParameters[paramind];
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFSMFSPPVRBase::setParametersSync() Unsupported key"));
return;
}
// Verify and set the passed-in setting
PVMFStatus retval = VerifyAndSetConfigParameter(i, aParameters[paramind], true);
if (retval != PVMFSuccess)
{
aRet_kvp = &aParameters[paramind];
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFSMFSPPVRBase::setParametersSync() Setting "
"parameter %d failed", paramind));
return;
}
}
else
{
// Do not support more than 3 components right now
aRet_kvp = &aParameters[paramind];
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFSMFSPPVRBase::setParametersSync() Unsupported key"));
return;
}
}
else
{
// Unknown key string
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFSMFSPPVRBase::setParametersSync() Unsupported key"));
return;
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFSMFSPPVRBase::setParametersSync() Out"));
}
PVMFStatus PVMFSMFSPPVRBase::verifyParametersSync(PvmiMIOSession aSession,
PvmiKvp* aParameters,
int num_elements)
{
OSCL_UNUSED_ARG(aSession);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFSMFSPPVRBase::verifyParametersSync() In"));
if (aParameters == NULL || num_elements < 1)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFSMFSPPVRBase::verifyParametersSync() Passed in parameter invalid"));
return PVMFErrArgument;
}
// Go through each parameter and verify
for (int32 paramind = 0; paramind < num_elements; ++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, "PVMFSMFSPPVRBase::verifyParametersSync() 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 this node
if ((pv_mime_strcmp(compstr, _STRLIT_CHAR("net")) >= 0) && (compcount == 3))
{
pv_mime_string_extract_type(2, aParameters[paramind].key, compstr);
uint i;
for (i = 0; i < StreamingManagerConfig_NumBaseKeys; i++)
{
if (pv_mime_strcmp(compstr, (char*)(StreamingManagerConfig_BaseKeys[i].iString)) >= 0)
{
break;
}
}
if (StreamingManagerConfig_NumBaseKeys == i)
{
return PVMFErrArgument;
}
// Verify the passed-in player setting
PVMFStatus retval = VerifyAndSetConfigParameter(i, aParameters[paramind], false);
if (retval != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFSMFSPPVRBase::DoCapConfigVerifyParameters() Verifying parameter %d failed", paramind));
return retval;
}
}
else
{
// Unknown key string
return PVMFErrArgument;
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFSMFSPPVRBase::DoCapConfigVerifyParameters() Out"));
return PVMFSuccess;
}
bool PVMFSMFSPPVRBase::SkipThisNodeResume(int32 aNodeTag)
{
if (iPVREnabled)
{
if ((aNodeTag == PVMF_SM_FSP_SOCKET_NODE)
|| (aNodeTag == PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE))
{
// SocketNode and Rtsp Engine were not paused
return true;
}
}
return false;
}
bool PVMFSMFSPPVRBase::SkipThisNodePause(int32 aNodeTag)
{
if (iPVREnabled)
{
if ((aNodeTag == PVMF_SM_FSP_SOCKET_NODE)
|| (aNodeTag == PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE))
{
// SocketNode and Rtsp Engine were not paused
return true;
}
}
return false;
}
void PVMFSMFSPPVRBase::SetPVRTrackParams(uint32 aMediaTrackId, const PvmfMimeString* aMimeType,
uint32 aTimescale, uint32 aBitrate)
{
// If PVR is enabled, pass the track information to the extension interface
if (iPVREnabled)
{
OSCL_ASSERT(iPVRExtInterface != NULL);
iPVRExtInterface->setTrackParams(aMediaTrackId, aMimeType, aTimescale,
aBitrate);
}
}
void PVMFSMFSPPVRBase::SetPVRTrackRTPParams(const PvmfMimeString* aMimeType,
bool aSeqNumBasePresent, uint32 aSeqNumBase, bool aRTPTimeBasePresent,
uint32 aRTPTimeBase, uint32 aNPTInMS)
{
if (iPVREnabled)
{
OSCL_ASSERT(iPVRExtInterface != NULL);
iPVRExtInterface->setTrackRTPParams(aMimeType,
aSeqNumBasePresent,
aSeqNumBase,
aRTPTimeBasePresent,
aRTPTimeBase,
aNPTInMS);
}
}
void PVMFSMFSPPVRBase::SetPVRSdpText(OsclRefCounterMemFrag& aSDPText)
{
if (iPVREnabled)
{
// For PVR, make sure we pass the sdp text
OSCL_ASSERT(iPVRExtInterface != NULL);
iPVRExtInterface->SetSdpText(aSDPText);
}
}
//Compute Jitter buffer mem pool size
uint32 PVMFSMFSPPVRBase::GetJitterBufferMemPoolSize(PVMFJitterBufferNodePortTag aJBNodePortTag, PVMFPVRBaseTrackInfo& aRTSPTrackInfo)
{
uint32 sizeInBytes = 0;
uint32 byteRate = (aRTSPTrackInfo.bitRate) / 8;
uint32 overhead = (byteRate * PVMF_JITTER_BUFFER_NODE_MEM_POOL_OVERHEAD) / 100;
uint32 jitterBufferDuration;
PVMFSMFSPChildNodeContainer* jitterBufferNodeContainer = getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (jitterBufferNodeContainer == NULL)
{
OSCL_ASSERT(false);
return false;
}
PVMFJitterBufferExtensionInterface* jbExtIntf = OSCL_STATIC_CAST(PVMFJitterBufferExtensionInterface*, jitterBufferNodeContainer->iExtensions[0]);
if (jbExtIntf == NULL)
{
OSCL_ASSERT(false);
return sizeInBytes;
}
jbExtIntf->getJitterBufferDurationInMilliSeconds(jitterBufferDuration);
uint32 durationInSec = jitterBufferDuration / 1000;
switch (aJBNodePortTag)
{
case PVMF_JITTER_BUFFER_PORT_TYPE_INPUT:
{
if (durationInSec > 0)
{
sizeInBytes = ((byteRate + overhead) * durationInSec);
if (sizeInBytes < MIN_RTP_SOCKET_MEM_POOL_SIZE_IN_BYTES)
{
sizeInBytes = MIN_RTP_SOCKET_MEM_POOL_SIZE_IN_BYTES;
}
sizeInBytes += (2 * MAX_SOCKET_BUFFER_SIZE); //MAX_SOCKET_BUFFER_SIZE equals to SNODE_UDP_MULTI_MAX_BYTES_PER_RECV + MAX_UDP_PACKET_SIZE used in socket node
}
}
break;
case PVMF_JITTER_BUFFER_PORT_TYPE_FEEDBACK:
{
if (durationInSec > 0)
{
sizeInBytes = MIN_RTP_SOCKET_MEM_POOL_SIZE_IN_BYTES;
sizeInBytes += (2 * MAX_SOCKET_BUFFER_SIZE); //MAX_SOCKET_BUFFER_SIZE equals to SNODE_UDP_MULTI_MAX_BYTES_PER_RECV + MAX_UDP_PACKET_SIZE used in socket node
}
}
break;
default:
sizeInBytes = 0;
}
return sizeInBytes;
}
bool PVMFSMFSPPVRBase::SetPVRPlaybackRange()
{
// Send the repositioning point to PVR Extension Interface
OSCL_ASSERT(iPVRExtInterface != NULL);
if (iPVRExtInterface->SetDataSourcePosition(iRepositionRequestedStartNPTInMS) != PVMFSuccess)
{
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "StreamingManagerNode:DoRepositioningStart - SetRequestPlayRange Failed for PVR"));
return false;
}
return true;
}
PVMFStatus PVMFSMFSPPVRBase::GetConfigParameter(PvmiKvp*& aParameters,
int& aNumParamElements,
int32 aIndex, PvmiKvpAttr reqattr)
{
PVMF_SM_FSP_PVR_BASE_LOGINFO((0, "PVMFSMFSPPVRBase::GetConfigParameter() In"));
aNumParamElements = 0;
// Allocate memory for the KVP
aParameters = (PvmiKvp*)oscl_malloc(sizeof(PvmiKvp));
if (aParameters == NULL)
{
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase::GetConfigParameter() 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(SMCONFIG_KEYSTRING_SIZE * sizeof(char));
if (memblock == NULL)
{
oscl_free(aParameters);
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase::GetConfigParameter() Memory allocation for key string failed"));
return PVMFErrNoMemory;
}
oscl_strset(memblock, 0, SMCONFIG_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/net/"), 17);
oscl_strncat(aParameters[0].key, StreamingManagerConfig_BaseKeys[aIndex].iString,
oscl_strlen(StreamingManagerConfig_BaseKeys[aIndex].iString));
oscl_strncat(aParameters[0].key, _STRLIT_CHAR(";type=value;valtype="), 20);
switch (StreamingManagerConfig_BaseKeys[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_WCHARPTR:
oscl_strncat(aParameters[0].key,
_STRLIT_CHAR(PVMI_KVPVALTYPE_WCHARPTR_STRING),
oscl_strlen(PVMI_KVPVALTYPE_WCHARPTR_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[SMCONFIG_KEYSTRING_SIZE-1] = 0;
// Copy the requested info
switch (aIndex)
{
case BASEKEY_DELAY:
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
PVMFSMFSPChildNodeContainer* iJitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
OSCL_ASSERT(iJitterBufferNodeContainer);
if (!iJitterBufferNodeContainer)
return PVMFFailure;
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)iJitterBufferNodeContainer->iExtensions[0];
OSCL_ASSERT(jbExtIntf);
if (!jbExtIntf)
return PVMFFailure;
if (jbExtIntf)
jbExtIntf->getJitterBufferDurationInMilliSeconds(aParameters[0].value.uint32_value);
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
aParameters[0].value.uint32_value = DEFAULT_JITTER_BUFFER_DURATION_IN_MS;
}
else
{
// Return capability
range_uint32* rui32 = (range_uint32*)oscl_malloc(sizeof(range_uint32));
if (rui32 == NULL)
{
oscl_free(aParameters[0].key);
oscl_free(aParameters);
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase::GetConfigParameter() "
"Memory allocation for range uint32 failed"));
return PVMFErrNoMemory;
}
rui32->min = MIN_JITTER_BUFFER_DURATION_IN_MS;
rui32->max = MAX_JITTER_BUFFER_DURATION_IN_MS;
aParameters[0].value.key_specific_value = (void*)rui32;
}
break;
case BASEKEY_JITTERBUFFER_NUMRESIZE:
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
uint32 numResize, resizeSize;
PVMFSMFSPChildNodeContainer* iJitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
OSCL_ASSERT(iJitterBufferNodeContainer);
if (!iJitterBufferNodeContainer)
return PVMFFailure;
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)iJitterBufferNodeContainer->iExtensions[0];
OSCL_ASSERT(jbExtIntf);
if (!jbExtIntf)
return PVMFFailure;
jbExtIntf->GetSharedBufferResizeParams(numResize, resizeSize);
aParameters[0].value.uint32_value = numResize;
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
aParameters[0].value.uint32_value = DEFAULT_MAX_NUM_SOCKETMEMPOOL_RESIZES;
}
else
{
// Return capability
range_uint32* rui32 = (range_uint32*)oscl_malloc(sizeof(range_uint32));
if (rui32 == NULL)
{
oscl_free(aParameters[0].key);
oscl_free(aParameters);
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase::GetConfigParameter() "
"Memory allocation for range uint32 failed"));
return PVMFErrNoMemory;
}
rui32->min = MIN_NUM_SOCKETMEMPOOL_RESIZES;
rui32->max = MAX_NUM_SOCKETMEMPOOL_RESIZES;
aParameters[0].value.key_specific_value = (void*)rui32;
}
break;
case BASEKEY_JITTERBUFFER_RESIZESIZE:
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
uint32 numResize, resizeSize;
PVMFSMFSPChildNodeContainer* iJitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
OSCL_ASSERT(iJitterBufferNodeContainer);
if (!iJitterBufferNodeContainer)
return PVMFFailure;
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)iJitterBufferNodeContainer->iExtensions[0];
OSCL_ASSERT(jbExtIntf);
if (!jbExtIntf)
return PVMFFailure;
jbExtIntf->GetSharedBufferResizeParams(numResize, resizeSize);
aParameters[0].value.uint32_value = resizeSize;
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
aParameters[0].value.uint32_value = DEFAULT_MAX_SOCKETMEMPOOL_RESIZELEN_INPUT_PORT;
}
else
{
// Return capability
range_uint32* rui32 = (range_uint32*)oscl_malloc(sizeof(range_uint32));
if (rui32 == NULL)
{
oscl_free(aParameters[0].key);
oscl_free(aParameters);
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase::GetConfigParameter() "
"Memory allocation for range uint32 failed"));
return PVMFErrNoMemory;
}
rui32->min = MIN_SOCKETMEMPOOL_RESIZELEN_INPUT_PORT;
rui32->max = MAX_SOCKETMEMPOOL_RESIZELEN_INPUT_PORT;
aParameters[0].value.key_specific_value = (void*)rui32;
}
break;
case BASEKEY_JITTERBUFFER_MAX_INACTIVITY_DURATION:
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
PVMFSMFSPChildNodeContainer* iJitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
OSCL_ASSERT(iJitterBufferNodeContainer);
if (!iJitterBufferNodeContainer)
return PVMFFailure;
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)iJitterBufferNodeContainer->iExtensions[0];
OSCL_ASSERT(jbExtIntf);
if (!jbExtIntf)
return PVMFFailure;
uint32 inactivityDuration = 0;
jbExtIntf->getMaxInactivityDurationForMediaInMs(inactivityDuration);
aParameters[0].value.uint32_value = inactivityDuration;
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
aParameters[0].value.uint32_value = DEFAULT_MAX_INACTIVITY_DURATION_IN_MS;
}
else
{
// Return capability
range_uint32* rui32 = (range_uint32*)oscl_malloc(sizeof(range_uint32));
if (rui32 == NULL)
{
oscl_free(aParameters[0].key);
oscl_free(aParameters);
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase::GetConfigParameter() "
"Memory allocation for range uint32 failed"));
return PVMFErrNoMemory;
}
rui32->min = 0;
rui32->max = DEFAULT_MAX_INACTIVITY_DURATION_IN_MS;
aParameters[0].value.key_specific_value = (void*)rui32;
}
break;
case BASEKEY_SESSION_CONTROLLER_USER_AGENT:
if ((reqattr == PVMI_KVPATTR_CUR) || (reqattr == PVMI_KVPATTR_DEF))
{
aParameters[0].value.pWChar_value = NULL;
/* As of now just RTSP node supports an external config of user agent */
PVMFSMFSPChildNodeContainer* iSessionControllerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
if (iSessionControllerNodeContainer != NULL)
{
PVRTSPEngineNodeExtensionInterface* rtspExtIntf =
(PVRTSPEngineNodeExtensionInterface*)
(iSessionControllerNodeContainer->iExtensions[0]);
OSCL_wHeapString<OsclMemAllocator> userAgent;
if (rtspExtIntf->GetUserAgent(userAgent) == PVMFSuccess)
{
// Return current value
oscl_wchar* ptr = (oscl_wchar*)oscl_malloc(sizeof(oscl_wchar) * (userAgent.get_size()));
if (ptr)
{
oscl_memcpy(ptr, userAgent.get_cstr(), userAgent.get_size());
aParameters[0].value.pWChar_value = ptr;
}
else
{
oscl_free(aParameters[0].key);
oscl_free(aParameters);
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase::GetConfigParameter() "
"Memory allocation for user agent failed"));
return PVMFErrNoMemory;
}
}
}
}
else
{
// Return capability - no concept of capability for user agent
// do nothing
}
break;
case BASEKEY_SESSION_CONTROLLER_KEEP_ALIVE_INTERVAL:
case BASEKEY_SESSION_CONTROLLER_KEEP_ALIVE_DURING_PLAY:
if ((reqattr == PVMI_KVPATTR_CUR) || (reqattr == PVMI_KVPATTR_DEF))
{
if (aIndex == BASEKEY_SESSION_CONTROLLER_KEEP_ALIVE_INTERVAL)
{
aParameters[0].value.uint32_value = PVRTSPENGINENODE_DEFAULT_KEEP_ALIVE_INTERVAL;
}
else
{
aParameters[0].value.bool_value = false;
}
/* As of now just RTSP node supports an external config of user agent */
PVMFSMFSPChildNodeContainer* iSessionControllerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
if (iSessionControllerNodeContainer != NULL)
{
PVRTSPEngineNodeExtensionInterface* rtspExtIntf =
(PVRTSPEngineNodeExtensionInterface*)
(iSessionControllerNodeContainer->iExtensions[0]);
uint32 timeout;
bool okeepalivemethod;
bool okeepaliveinplay;
rtspExtIntf->GetKeepAliveMethod((int32&)timeout, okeepalivemethod, okeepaliveinplay);
if (aIndex == BASEKEY_SESSION_CONTROLLER_KEEP_ALIVE_INTERVAL)
{
aParameters[0].value.uint32_value = timeout;
}
else
{
aParameters[0].value.bool_value = okeepaliveinplay;
}
}
}
else
{
// Return capability - no concept of capability for keep alive interval
// do nothing
}
break;
case BASEKEY_REBUFFERING_THRESHOLD:
{
if (reqattr == PVMI_KVPATTR_CUR)
{
// Return current value
PVMFSMFSPChildNodeContainer* iJitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
OSCL_ASSERT(iJitterBufferNodeContainer);
if (!iJitterBufferNodeContainer)
return PVMFFailure;
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)iJitterBufferNodeContainer->iExtensions[0];
OSCL_ASSERT(jbExtIntf);
if (!jbExtIntf)
return PVMFFailure;
jbExtIntf->getJitterBufferRebufferingThresholdInMilliSeconds(aParameters[0].value.uint32_value);
}
else if (reqattr == PVMI_KVPATTR_DEF)
{
// Return default
aParameters[0].value.uint32_value = DEFAULT_JITTER_BUFFER_UNDERFLOW_THRESHOLD_IN_MS;
}
else
{
// Return capability
range_uint32* rui32 = (range_uint32*)oscl_malloc(sizeof(range_uint32));
if (rui32 == NULL)
{
oscl_free(aParameters[0].key);
oscl_free(aParameters);
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase::GetConfigParameter() "
"Memory allocation for range uint32 failed"));
return PVMFErrNoMemory;
}
rui32->min = DEFAULT_JITTER_BUFFER_UNDERFLOW_THRESHOLD_IN_MS;
rui32->max = DEFAULT_JITTER_BUFFER_UNDERFLOW_THRESHOLD_IN_MS;
aParameters[0].value.key_specific_value = (void*)rui32;
}
}
break;
case BASEKEY_SESSION_CONTROLLER_RTSP_TIMEOUT:
{
if ((reqattr == PVMI_KVPATTR_CUR) || (reqattr == PVMI_KVPATTR_DEF))
{
/* As of now just RTSP node supports an external config of RTSP time out */
PVMFSMFSPChildNodeContainer* iSessionControllerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
if (iSessionControllerNodeContainer != NULL)
{
PVRTSPEngineNodeExtensionInterface* rtspExtIntf =
(PVRTSPEngineNodeExtensionInterface*)
(iSessionControllerNodeContainer->iExtensions[0]);
int32 timeout;
rtspExtIntf->GetRTSPTimeOut(timeout);
aParameters[0].value.uint32_value = OSCL_STATIC_CAST(uint32, timeout);
}
}
else
{
// Return capability
range_uint32* rui32 = (range_uint32*)oscl_malloc(sizeof(range_uint32));
if (rui32 == NULL)
{
oscl_free(aParameters[0].key);
oscl_free(aParameters);
PVMF_SM_FSP_PVR_BASE_LOGERR((0, "PVMFSMFSPPVRBase::GetConfigParameter() "
"Memory allocation for range uint32 failed"));
return PVMFErrNoMemory;
}
rui32->min = MIN_RTSP_SERVER_INACTIVITY_TIMEOUT_IN_SEC;
rui32->max = MAX_RTSP_SERVER_INACTIVITY_TIMEOUT_IN_SEC;
aParameters[0].value.key_specific_value = (void*)rui32;
}
}
break;
case BASEKEY_DISABLE_FIREWALL_PACKETS:
{
if ((reqattr == PVMI_KVPATTR_CUR) || (reqattr == PVMI_KVPATTR_DEF))
{
aParameters[0].value.bool_value = false;
}
}
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;
}
void PVMFSMFSPPVRBase::DoQueryInterface(PVMFSMFSPBaseNodeCommand& aCmd)
{
PVMF_SM_FSP_PVR_BASE_LOGSTACKTRACE((0, "PVMFSMFSPPVRBase::DoQueryInterface - In"));
PVUuid* uuid;
PVInterface** ptr;
aCmd.PVMFSMFSPBaseNodeCommandBase::Parse(uuid, ptr);
*ptr = NULL;
if (*uuid == PVMF_TRACK_SELECTION_INTERFACE_UUID)
{
PVMFTrackSelectionExtensionInterface* interimPtr =
OSCL_STATIC_CAST(PVMFTrackSelectionExtensionInterface*, this);
*ptr = OSCL_STATIC_CAST(PVInterface*, interimPtr);
}
else if (*uuid == PVMF_DATA_SOURCE_INIT_INTERFACE_UUID)
{
PVMFDataSourceInitializationExtensionInterface* interimPtr =
OSCL_STATIC_CAST(PVMFDataSourceInitializationExtensionInterface*, this);
*ptr = OSCL_STATIC_CAST(PVInterface*, interimPtr);
}
else if (*uuid == PvmfDataSourcePlaybackControlUuid)
{
PvmfDataSourcePlaybackControlInterface* interimPtr =
OSCL_STATIC_CAST(PvmfDataSourcePlaybackControlInterface*, this);
*ptr = OSCL_STATIC_CAST(PVInterface*, interimPtr);
}
else if (*uuid == KPVMFMetadataExtensionUuid)
{
PVMFMetadataExtensionInterface* interimPtr =
OSCL_STATIC_CAST(PVMFMetadataExtensionInterface*, this);
*ptr = OSCL_STATIC_CAST(PVInterface*, interimPtr);
}
else if (*uuid == PVMI_CAPABILITY_AND_CONFIG_PVUUID)
{
PvmiCapabilityAndConfig* interimPtr =
OSCL_STATIC_CAST(PvmiCapabilityAndConfig*, this);
*ptr = OSCL_STATIC_CAST(PVInterface*, interimPtr);
}
else if (*uuid == PVMFCPMPluginLicenseInterfaceUuid)
{
PVMFCPMPluginLicenseInterface* interimPtr =
OSCL_STATIC_CAST(PVMFCPMPluginLicenseInterface*, this);
*ptr = OSCL_STATIC_CAST(PVInterface*, interimPtr);
}
else if (*uuid == PVMF_DATA_SOURCE_PACKETSOURCE_INTERFACE_UUID)
{
PVMFDataSourcePacketSourceInterface* interimPtr =
OSCL_STATIC_CAST(PVMFDataSourcePacketSourceInterface*, this);
*ptr = OSCL_STATIC_CAST(PVInterface*, interimPtr);
}
else
{
*ptr = NULL;
}
if (*ptr)
{
PVMF_SM_FSP_PVR_BASE_LOGCMDSEQ((0, "PVMFSMFSPPVRBase::QueryInterface() - CmdComplete - PVMFSuccess"));
CommandComplete(iInputCommands, aCmd, PVMFSuccess);
}
else
{
PVMF_SM_FSP_PVR_BASE_LOGCMDSEQ((0, "PVMFSMFSPPVRBase::QueryInterface() - CmdFailed - PVMFErrNotSupported"));
CommandComplete(iInputCommands, aCmd, PVMFErrNotSupported);
}
PVMF_SM_FSP_PVR_BASE_LOGSTACKTRACE((0, "PVMFSMFSPPVRBase::DoQueryInterface - Out"));
return;
}
PVMFStatus PVMFSMFSPPVRBase::GetPVRPluginSpecificValues(PVMFSMFSPBaseNodeCommand& aCmd)
{
PVMFMetadataList* keylistptr = NULL;
Oscl_Vector<PvmiKvp, OsclMemAllocator>* valuelistptr = NULL;
uint32 starting_index;
int32 max_entries;
aCmd.PVMFSMFSPBaseNodeCommand::Parse(keylistptr, valuelistptr, starting_index, max_entries);
// Check the parameters
if (keylistptr == NULL || valuelistptr == NULL)
{
return PVMFErrArgument;
}
uint32 numkeys = keylistptr->size();
if (numkeys <= 0 || max_entries == 0)
{
// Don't do anything
return PVMFErrArgument;
}
uint32 numvalentries = 0;
int32 numentriesadded = 0;
for (uint32 lcv = 0; lcv < numkeys; lcv++)
{
PvmiKvp KeyVal;
KeyVal.key = NULL;
KeyVal.value.pWChar_value = NULL;
KeyVal.value.pChar_value = NULL;
if (oscl_strstr((*keylistptr)[lcv].get_cstr(), PVMFSTREAMINGMGRNODE_PAUSE_DENIED_KEY) != NULL)
{
// Increment the counter for the number of values found so far
++numvalentries;
// Create a value entry if past the starting index
if (numvalentries > starting_index)
{
// check if duration is available first
bool keyValue = iMetaDataInfo->iSessionDurationAvailable ? false : true;
if (keyValue == true)
keyValue = !iPVREnabled;
PVMFStatus retval = PVMFCreateKVPUtils::CreateKVPForBoolValue(KeyVal,
PVMFSTREAMINGMGRNODE_PAUSE_DENIED_KEY,
keyValue);
if (retval != PVMFSuccess && retval != PVMFErrArgument)
{
break;
}
}
}
/* Check if the max number of value entries were added */
if (max_entries > 0 && numentriesadded >= max_entries)
{
iPVMFStreamingManagerNodeMetadataValueCount = (*valuelistptr).size();
return PVMFSuccess;
}
// Add the KVP to the list if the key string was created
if (KeyVal.key != NULL)
{
if (PVMFSuccess != PushKVPToMetadataValueList(valuelistptr, KeyVal))
{
switch (GetValTypeFromKeyString(KeyVal.key))
{
case PVMI_KVPVALTYPE_CHARPTR:
if (KeyVal.value.pChar_value != NULL)
{
OSCL_ARRAY_DELETE(KeyVal.value.pChar_value);
KeyVal.value.pChar_value = NULL;
}
break;
default:
// Add more case statements if other value types are returned
break;
}
OSCL_ARRAY_DELETE(KeyVal.key);
KeyVal.key = NULL;
}
else
{
// Increment the counter for number of value entries added to the list
++numentriesadded;
}
// Check if the max number of value entries were added
if (max_entries > 0 && numentriesadded >= max_entries)
{
// Maximum number of values added so break out of the loop
break;
}
}
}
iNoOfValuesIteratedForValueVect = numvalentries;
iNoOfValuesPushedInValueVect = numentriesadded;
iPVMFStreamingManagerNodeMetadataValueCount = (*valuelistptr).size();
return PVMFSuccess;
}