blob: 8286f7b2cf642ca5f1fa2e564316819048ddd6b4 [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_RTSP_UNICAST_H
#include "pvmf_sm_fsp_rtsp_unicast.h"
#endif
#ifndef OSCL_EXCLUSIVE_PTR_H_INCLUDED
#include "oscl_exclusive_ptr.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
#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 PVRTSP_ENGINE_NODE_EXTENSION_INTERFACE_H_INCLUDED
#include "pvrtspenginenodeextensioninterface.h"
#endif
#ifndef PVMF_MEDIA_PRESENTATION_INFO_H_INCLUDED
#include "pvmf_media_presentation_info.h"
#endif
#ifndef PVMF_SM_FSP_BASE_METADATA_H_INCLUDED
#include "pvmf_sm_fsp_base_metadata.h"
#endif
#ifndef SDP_PARSER_H
#include "sdp_parser.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 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 PVMF_SM_RTSP_UNICAST_CAPANDCONFIG_H
#include "pvmf_sm_rtsp_unicast_capandconfig.h"
#endif
#ifndef SDP_MEDIA_PARSER_REGISTRY_POPULATOR
#include "sdp_mediaparser_registry_populator.h"
#endif
/**
///////////////////////////////////////////////////////////////////////////////
// Node Constructor & Destructor
///////////////////////////////////////////////////////////////////////////////
*/
PVMFSMRTSPUnicastNode * PVMFSMRTSPUnicastNode::New(int32 aPriority)
{
PVMFSMRTSPUnicastNode * rtspUnicastNode = OSCL_NEW(PVMFSMRTSPUnicastNode, (aPriority));
if (rtspUnicastNode)
{
rtspUnicastNode->Construct();
}
return rtspUnicastNode;
}
PVMFSMRTSPUnicastNode::PVMFSMRTSPUnicastNode(int32 aPriority): PVMFSMFSPBaseNode(aPriority)
{
iJitterBufferDurationInMilliSeconds = DEFAULT_JITTER_BUFFER_DURATION_IN_MS;
oAutoReposition = false;
iPauseDenied = false;
ResetNodeParams(false);
}
PVMFSMRTSPUnicastNode::~PVMFSMRTSPUnicastNode()
{
CleanUp();
}
void PVMFSMRTSPUnicastNode::Construct()
{
PVMFSMFSPBaseNode::Construct();
int32 err;
OSCL_TRY(err,
iLogger = PVLogger::GetLoggerObject("PVMFSMRTSPUnicastNode");
iAvailableMetadataKeys.reserve(PVMFSTREAMINGMGRNODE_NUM_METADATAKEYS);
iAvailableMetadataKeys.clear();
// create the payload parser registry
PopulatePayloadParserRegistry();
CreateChildNodes();
QueryChildNodesExtentionInterface();
// 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)
{
CleanUp();
OSCL_LEAVE(err);
}
}
void PVMFSMRTSPUnicastNode::CreateChildNodes()
{
/*
* Create Socket Node
*/
OsclExclusivePtr<PVMFNodeInterface> socketNodeAutoPtr;
PVMFNodeInterface* iSocketNode;
iSocketNode = OSCL_NEW(PVMFSocketNode, (OsclActiveObject::EPriorityNominal));
socketNodeAutoPtr.set(iSocketNode);
PVMFSMFSPChildNodeContainer sSocketNodeContainer;
PVMFNodeSessionInfo socketNodeSession(this,
this,
OSCL_REINTERPRET_CAST(OsclAny*,
iSocketNode),
this,
OSCL_REINTERPRET_CAST(OsclAny*,
iSocketNode));
sSocketNodeContainer.iNode = iSocketNode;
sSocketNodeContainer.iSessionId =
iSocketNode->Connect(socketNodeSession);
sSocketNodeContainer.iNodeTag =
PVMF_SM_FSP_SOCKET_NODE;
sSocketNodeContainer.commandStartOffset =
PVMF_SM_FSP_SOCKET_NODE_COMMAND_START;
/* Push back the known UUID in case there are no queries */
PVUuid uuid(PVMF_SOCKET_NODE_EXTENSION_INTERFACE_UUID);
sSocketNodeContainer.iExtensionUuids.push_back(uuid);
iFSPChildNodeContainerVec.push_back(sSocketNodeContainer);
/*
* Create Session Controller Node
*/
OsclExclusivePtr<PVMFNodeInterface> sessionControllerAutoPtr;
//PVMFNodeInterface* iSessionControllerNode = OSCL_NEW(PVRTSPEngineNode, (OsclActiveObject::EPriorityNominal));
PVMFNodeInterface* iSessionControllerNode = PVMFRrtspEngineNodeFactory::CreatePVMFRtspEngineNode(OsclActiveObject::EPriorityNominal);
sessionControllerAutoPtr.set(iSessionControllerNode);
PVMFSMFSPChildNodeContainer sSessionControllerNodeContainer;
PVMFNodeSessionInfo sessionControllerSession(this,
this,
OSCL_REINTERPRET_CAST(OsclAny*,
iSessionControllerNode),
this,
OSCL_REINTERPRET_CAST(OsclAny*,
iSessionControllerNode));
sSessionControllerNodeContainer.iNode = iSessionControllerNode;
sSessionControllerNodeContainer.iSessionId =
iSessionControllerNode->Connect(sessionControllerSession);
sSessionControllerNodeContainer.iNodeTag =
PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE;
sSessionControllerNodeContainer.commandStartOffset =
PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_COMMAND_START;
/* Push back the known UUID in case there are no queries */
sSessionControllerNodeContainer.iExtensionUuids.push_back(KPVRTSPEngineNodeExtensionUuid);
iFSPChildNodeContainerVec.push_back(sSessionControllerNodeContainer);
/*
* Create jitter buffer node
*/
OsclExclusivePtr<PVMFNodeInterface> jitterBufferNodeAutoPtr;
PVMFNodeInterface* iJitterBufferNode;
iJitterBufferNode = OSCL_NEW(PVMFJitterBufferNode, (OsclActiveObject::EPriorityNominal));
jitterBufferNodeAutoPtr.set(iJitterBufferNode);
PVMFSMFSPChildNodeContainer sJitterBufferNodeContainer;
PVMFNodeSessionInfo jitterBufferSession(this,
this,
OSCL_REINTERPRET_CAST(OsclAny*,
iJitterBufferNode),
this,
OSCL_REINTERPRET_CAST(OsclAny*,
iJitterBufferNode));
sJitterBufferNodeContainer.iNode = iJitterBufferNode;
sJitterBufferNodeContainer.iSessionId =
iJitterBufferNode->Connect(jitterBufferSession);
sJitterBufferNodeContainer.iNodeTag =
PVMF_SM_FSP_JITTER_BUFFER_NODE;
sJitterBufferNodeContainer.commandStartOffset =
PVMF_SM_FSP_JITTER_BUFFER_CONTROLLER_COMMAND_START;
/* Push back the known UUID in case there are no queries */
sJitterBufferNodeContainer.iExtensionUuids.push_back(PVMF_JITTERBUFFERNODE_EXTENSIONINTERFACE_UUID);
iFSPChildNodeContainerVec.push_back(sJitterBufferNodeContainer);
/*
* Create media layer node
*/
OsclExclusivePtr<PVMFNodeInterface> mediaLayerNodeAutoPtr;
PVMFNodeInterface* iMediaLayerNode;
iMediaLayerNode = OSCL_NEW(PVMFMediaLayerNode, (OsclActiveObject::EPriorityNominal));
mediaLayerNodeAutoPtr.set(iMediaLayerNode);
PVMFSMFSPChildNodeContainer sMediaLayerNodeContainer;
PVMFNodeSessionInfo mediaLayerSession(this,
this,
OSCL_REINTERPRET_CAST(OsclAny*,
iMediaLayerNode),
this,
OSCL_REINTERPRET_CAST(OsclAny*,
iMediaLayerNode));
sMediaLayerNodeContainer.iNode = iMediaLayerNode;
sMediaLayerNodeContainer.iSessionId =
iMediaLayerNode->Connect(mediaLayerSession);
sMediaLayerNodeContainer.iNodeTag =
PVMF_SM_FSP_MEDIA_LAYER_NODE;
sMediaLayerNodeContainer.commandStartOffset =
PVMF_SM_FSP_MEDIA_LAYER_COMMAND_START;
/* Push back the known UUID in case there are no queries */
sMediaLayerNodeContainer.iExtensionUuids.push_back(PVMF_MEDIALAYERNODE_EXTENSIONINTERFACE_UUID);
iFSPChildNodeContainerVec.push_back(sMediaLayerNodeContainer);
sessionControllerAutoPtr.release();
socketNodeAutoPtr.release();
jitterBufferNodeAutoPtr.release();
mediaLayerNodeAutoPtr.release();
}
void PVMFSMRTSPUnicastNode::DestroyChildNodes()
{
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();
}
if (iFSPChildNodeContainerVec[i].iNodeTag == PVMF_SM_FSP_SOCKET_NODE)
{
OSCL_DELETE(OSCL_STATIC_CAST(PVMFSocketNode*, iFSPChildNodeContainerVec[i].iNode));
}
else if (iFSPChildNodeContainerVec[i].iNodeTag == PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE)
{
PVMFRrtspEngineNodeFactory::DeletePVMFRtspEngineNode(iFSPChildNodeContainerVec[i].iNode);
}
else if (iFSPChildNodeContainerVec[i].iNodeTag == PVMF_SM_FSP_JITTER_BUFFER_NODE)
{
OSCL_DELETE(OSCL_STATIC_CAST(PVMFJitterBufferNode*, iFSPChildNodeContainerVec[i].iNode));
}
else if (iFSPChildNodeContainerVec[i].iNodeTag == PVMF_SM_FSP_MEDIA_LAYER_NODE)
{
OSCL_DELETE(OSCL_STATIC_CAST(PVMFMediaLayerNode*, iFSPChildNodeContainerVec[i].iNode));
}
iFSPChildNodeContainerVec[i].iNode = NULL;
}
iFSPChildNodeContainerVec.clear();
}
void PVMFSMRTSPUnicastNode::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 PVMFSMRTSPUnicastNode::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();
}
void PVMFSMRTSPUnicastNode::QueryChildNodesExtentionInterface()
{
PVMFSMFSPChildNodeContainerVector::iterator it;
for (it = iFSPChildNodeContainerVec.begin(); it != iFSPChildNodeContainerVec.end(); it++)
{
//we dont use dynamic cast for cross cast.. because some compilers may not support it, and to avoid
//run time overheads.... So, we need to explicitly downcast the pvmfnodeinterface ptr to its
//concrete implementation and then, upcast it into required PVInterface class
PVInterface * interfacePtr = NULL;
switch (it->iNodeTag)
{
case PVMF_SM_FSP_SOCKET_NODE:
{
PVMFSocketNode * tmpPtr = OSCL_STATIC_CAST(PVMFSocketNode *, it->iNode);
interfacePtr = OSCL_STATIC_CAST(PVInterface*, tmpPtr);
}
break;
case PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE:
{
PVRTSPEngineNode * tmpPtr = OSCL_STATIC_CAST(PVRTSPEngineNode *, it->iNode);
interfacePtr = OSCL_STATIC_CAST(PVInterface*, tmpPtr);
}
break;
case PVMF_SM_FSP_JITTER_BUFFER_NODE:
{
PVMFJitterBufferNode * tmpPtr = OSCL_STATIC_CAST(PVMFJitterBufferNode *, it->iNode);
interfacePtr = OSCL_STATIC_CAST(PVInterface*, tmpPtr);
}
break;
case PVMF_SM_FSP_MEDIA_LAYER_NODE:
{
PVMFMediaLayerNode * tmpPtr = OSCL_STATIC_CAST(PVMFMediaLayerNode *, it->iNode);
interfacePtr = OSCL_STATIC_CAST(PVInterface*, tmpPtr);
}
break;
}
PVInterface* extensionIntfPtr = NULL;
bool retval = interfacePtr->queryInterface(it->iExtensionUuids.front(), extensionIntfPtr);
if (retval && extensionIntfPtr)
{
it->iExtensions.push_back(extensionIntfPtr);
}
}
}
/**
* Called by the command handler AO to process a command from
* the input queue.
* Return true if a command was processed, false if the command
* processor is busy and can't process another command now.
*/
bool PVMFSMRTSPUnicastNode::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(PVMF_SMFSP_NODE_QUERYUUID != aCmd.iCmd);
OSCL_ASSERT(PVMF_SMFSP_NODE_SET_DATASOURCE_RATE != aCmd.iCmd);
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:
if (iPauseDenied)
{
CommandComplete(iInputCommands, aCmd, PVMFErrNotSupported);
}
else
{
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:
OSCL_ASSERT(iPlayListRepositioning != true);
if (!oAutoReposition)
{
DoSetDataSourcePosition(aCmd);
}
else
{
DoSetDataSourcePositionOverflow(aCmd);
}
break;
case PVMF_SMFSP_NODE_QUERY_DATASOURCE_POSITION:
DoQueryDataSourcePosition(aCmd);
break;
case PVMF_SMFSP_NODE_SET_DATASOURCE_RATE:
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;
/* internal commands specific to rtsp unicast streaming*/
/* unknown commands */
default:
/* unknown command type */
CommandComplete(iInputCommands, aCmd, PVMFErrNotSupported);
break;
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
//Node command servicing functions queued in input command Q by base class
///////////////////////////////////////////////////////////////////////////////
void PVMFSMRTSPUnicastNode::DoQueryInterface(PVMFSMFSPBaseNodeCommand& aCmd)
{
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::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
{
*ptr = NULL;
}
if (*ptr)
{
PVMF_SM_RTSP_LOG_COMMAND_SEQ((0, "PVMFSMRTSPUnicastNode::QueryInterface() - CmdComplete - PVMFSuccess"));
CommandComplete(iInputCommands, aCmd, PVMFSuccess);
}
else
{
PVMF_SM_RTSP_LOG_COMMAND_SEQ((0, "PVMFSMRTSPUnicastNode::QueryInterface() - CmdFailed - PVMFErrNotSupported"));
CommandComplete(iInputCommands, aCmd, PVMFErrNotSupported);
}
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::DoQueryInterface - Out"));
return;
}
void PVMFSMRTSPUnicastNode::DoInit(PVMFSMFSPBaseNodeCommand& aCmd)
{
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::DoInit - In"));
switch (iInterfaceState)
{
case EPVMFNodeIdle:
{
/*
* At first Init, PVMFErrLicesneRequest is replied from Janus.
* Then iCPMInitPending is set into true.
* If second Init is called, just to check license authentication is required.
*/
if (iCPMInitPending)
{
MoveCmdToCurrentQueue(aCmd);
if (iSessionSourceInfo->iDRMProtected == true && iCPM)
{
RequestUsage();
return;
}
else
{
CommandComplete(iCurrentCommand,
iCurrentCommand.front(),
PVMFFailure,
NULL, NULL, NULL);
return;
}
}
else
{
/* An asynchronous method that prepare's the node for init */
PVMFStatus status = DoPreInit(aCmd);
if (status == PVMFSuccess)
{
/*
* Init for streaming manager cannot be completed unless Init
* 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_INIT_CMD_OFFSET;
internalCmd->parentCmd = aCmd.iCmd;
OsclAny *cmdContextData =
OSCL_REINTERPRET_CAST(OsclAny*, internalCmd);
PVMFNodeInterface* iNode = it->iNode;
iNode->Init(it->iSessionId, cmdContextData);
it->iNodeCmdState = PVMFSMFSP_NODE_CMD_PENDING;
}
else
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode:DoInit:RequestNewInternalCmd - Failed"));
CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
return;
}
}
MoveCmdToCurrentQueue(aCmd);
}
else if (status == PVMFPending)
{
MoveCmdToCurrentQueue(aCmd);
}
else
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode:DoInit: DoPreInit() - Failed"));
PVUuid eventuuid = PVMFStreamingManagerNodeEventTypeUUID;
int32 errcode = PVMFStreamingManagerNodeErrorParseSDPFailed;
CommandComplete(iInputCommands, aCmd, PVMFFailure, NULL, &eventuuid, &errcode);
return;
}
}
}
break;
default:
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::DoInit Failed - Invalid State"));
CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
}
break;
}
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::DoInit - Out"));
}
/**
* Call by DoInit as a prep step
*/
PVMFStatus PVMFSMRTSPUnicastNode::DoPreInit(PVMFSMFSPBaseNodeCommand& aCmd)
{
OSCL_UNUSED_ARG(aCmd);
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::DoPreInit - In"));
PVMFStatus status = PVMFSuccess;
if (iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_SDP_FILE)
{
status = ProcessSDP();
if (status != PVMFSuccess)
{
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::DoPreInit - Out, status=%d", status));
return status;
}
// ClipEndURL found - let UI know about this
if (iSdpInfo->getSessionInfo()->getEndOfClipAction() == LAUNCH_URL)
{
PVUuid eventuuid = PVMFStreamingManagerNodeEventTypeUUID;
int32 infocode = PVMFStreamingManagerNodeInfoLaunchURL;
ReportInfoEvent(PVMFInfoRemoteSourceNotification, (OsclAny*)(iSdpInfo->getSessionInfo()->getLaunchURL()), &eventuuid, &infocode);
}
PVMFSMFSPChildNodeContainer* iSessionControllerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
if (iSessionControllerNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return PVMFFailure;
}
PVRTSPEngineNodeExtensionInterface* rtspExtIntf =
(PVRTSPEngineNodeExtensionInterface*)
(iSessionControllerNodeContainer->iExtensions[0]);
/*
* This vector is intentionally left uninitialized.
* Streaming manager does not have any track selection info
* at this stage. "SetSDPInfo" would be called again before
* prepare complete to set up all the selected tracks. This
* call is needed here to indicate to Session Controller node
* that it is NOT a RTSP URL based session
*/
Oscl_Vector<StreamInfo, OsclMemAllocator> aSelectedStream;
status = rtspExtIntf->SetSDPInfo(iSdpInfo,
aSelectedStream);
if (status != PVMFSuccess)
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:DoPreInit - SetSDPInfo Failed"));
}
}
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::DoPreInit - Out"));
return status;
}
PVMFStatus PVMFSMRTSPUnicastNode::ProcessSDP()
{
PVMFStatus status;
OsclRefCounterMemFrag iSDPText;
if (iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_RTSP_URL)
{
PVMFSMFSPChildNodeContainer* iSessionControllerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
if (iSessionControllerNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return PVMFFailure;
}
PVRTSPEngineNodeExtensionInterface* rtspExtIntf =
(PVRTSPEngineNodeExtensionInterface*)
(iSessionControllerNodeContainer->iExtensions[0]);
status = rtspExtIntf->GetSDP(iSDPText);
if (status != PVMFSuccess)
{
return status;
}
}
else if (iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_SDP_FILE)
{
/* Parse SDP file contents into a buffer */
Oscl_FileServer fileServ;
Oscl_File osclFile;
fileServ.Connect();
PVMFSourceContextData* atempData = (PVMFSourceContextData*)iSessionSourceInfo->_sourceData;
if (atempData && atempData->CommonData() && atempData->CommonData()->iFileHandle)
{
OsclFileHandle* tempHandle = atempData ->CommonData()->iFileHandle;
osclFile.SetFileHandle(tempHandle);
}
if (osclFile.Open(iSessionSourceInfo->_sessionURL.get_cstr(),
Oscl_File::MODE_READ,
fileServ) != 0)
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:ProcessSDP - Unable to open SDP file"));
return PVMFFailure;
}
/* Get File Size */
osclFile.Seek(0, Oscl_File::SEEKEND);
int32 fileSize = osclFile.Tell();
osclFile.Seek(0, Oscl_File::SEEKSET);
if (fileSize <= 0)
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:ProcessSDP - Corrupt SDP file"));
return PVMFFailure;
}
OsclMemAllocDestructDealloc<uint8> my_alloc;
OsclRefCounter* my_refcnt;
uint aligned_refcnt_size =
oscl_mem_aligned_size(sizeof(OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >));
/*
* To acct for null char, as SDP buffer is treated akin to a string by the
* SDP parser lib.
*/
uint allocsize = oscl_mem_aligned_size(aligned_refcnt_size + fileSize + 2);
uint8* my_ptr = GetMemoryChunk(my_alloc, allocsize);
if (!my_ptr)
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:ProcessSDP - Unable to process SDP file"));
return PVMFFailure;
}
my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >(my_ptr));
my_ptr += aligned_refcnt_size;
OsclMemoryFragment memfrag;
memfrag.len = fileSize;
memfrag.ptr = my_ptr;
OsclRefCounterMemFrag tmpRefcntMemFrag(memfrag, my_refcnt, memfrag.len);
iSDPText = tmpRefcntMemFrag;
osclFile.Read(memfrag.ptr, 1, fileSize);
osclFile.Close();
fileServ.Close();
}
PVMFSMSharedPtrAlloc<SDPInfo> sdpAlloc;
SDPInfo* sdpInfo = sdpAlloc.allocate();
SDP_Parser *sdpParser;
SDPMediaParserRegistry* sdpParserReg = SDPMediaParserRegistryPopulater::PopulateRegistry();
sdpParser = OSCL_NEW(SDP_Parser, (sdpParserReg));
int32 sdpRetVal =
sdpParser->parseSDP((const char*)(iSDPText.getMemFragPtr()),
iSDPText.getMemFragSize(),
sdpInfo);
// save the SDP file name - the packet source node will need this
sdpInfo->setSDPFilename(iSessionSourceInfo->_sessionURL);
OSCL_DELETE(sdpParser);
SDPMediaParserRegistryPopulater::CleanupRegistry(sdpParserReg);
OsclRefCounterSA< PVMFSMSharedPtrAlloc<SDPInfo> > *refcnt =
new OsclRefCounterSA< PVMFSMSharedPtrAlloc<SDPInfo> >(sdpInfo);
OsclSharedPtr<SDPInfo> sharedSDPInfo(sdpInfo, refcnt);
if (sdpRetVal != SDP_SUCCESS)
{
return PVMFFailure;
}
iSdpInfo = sharedSDPInfo;
return PVMFSuccess;
}
//Compute Jitter buffer mem pool size
uint32 PVMFSMRTSPUnicastNode::GetJitterBufferMemPoolSize(PVMFJitterBufferNodePortTag aJBNodePortTag, PVMFRTSPTrackInfo& 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); //eq. 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); //eq. to SNODE_UDP_MULTI_MAX_BYTES_PER_RECV + MAX_UDP_PACKET_SIZE used in socket node
}
}
break;
default:
sizeInBytes = 0;
}
return sizeInBytes;
}
/**
* Called as a pre step for prepare
*/
PVMFStatus PVMFSMRTSPUnicastNode::DoGraphConstruct()
{
/*
* Session source info must have been set
*/
if (iSessionSourceInfo->_sessionType == PVMF_MIME_FORMAT_UNKNOWN)
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::GraphConstruct - Invalid Session Type %s", iSessionSourceInfo->_sessionType.getMIMEStrPtr()));
return PVMFFailure;
}
if (!PopulateTrackInfoVec())
{
return PVMFFailure;
}
if (ConstructGraphFor3GPPUDPStreaming())
{
if (iTotalNumRequestPortsComplete == iNumRequestPortsPending)
return PVMFSuccess;
else
return PVMFPending;
}
else
return PVMFFailure;
}
bool PVMFSMRTSPUnicastNode::PopulateTrackInfoVec()
{
if (iSelectedMediaPresetationInfo.getNumTracks() == 0)
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode: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())
{
PVMFRTSPTrackInfo trackInfo;
trackInfo.iTransportType += _STRLIT_CHAR("RTP");
trackInfo.trackID = mInfo->getMediaInfoID();
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_RTSP_LOGERROR((0, "StreamingManagerNode:PopulateTrackInfoVec - Selected Track List Empty"));
return false;
}
return true;
}
bool PVMFSMRTSPUnicastNode::ConstructGraphFor3GPPUDPStreaming()
{
uint32 numPortsRequested = 0;
/*
* Reserve UDP socket pairs
*/
if (!ReserveSockets())
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:ConstructGraphFor3GPPUDPStreaming - ReserveSockets() Failed"));
return false;
}
/*
* Request data UDP ports
*/
if (!RequestNetworkNodePorts(PVMF_SOCKET_NODE_PORT_TYPE_SOURCE,
numPortsRequested))
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:ConstructGraphFor3GPPUDPStreaming - RequestNetworkNodePorts(PVMF_SOCKET_NODE_PORT_TYPE_SOURCE) Failed"));
return false;
}
iNumRequestPortsPending += numPortsRequested;
/*
* Request feedback (RTCP) UDP ports
*/
if (!RequestNetworkNodePorts(PVMF_SOCKET_NODE_PORT_TYPE_SINK,
numPortsRequested))
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:ConstructGraphFor3GPPUDPStreaming - RequestNetworkNodePorts(PVMF_SOCKET_NODE_PORT_TYPE_SINK) Failed"));
return false;
}
iNumRequestPortsPending += numPortsRequested;
if (!RequestJitterBufferPorts(PVMF_JITTER_BUFFER_PORT_TYPE_INPUT,
numPortsRequested))
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:ConstructGraphFor3GPPUDPStreaming - RequestJitterBufferPorts(PVMF_JITTER_BUFFER_PORT_TYPE_INPUT) Failed"));
return false;
}
iNumRequestPortsPending += numPortsRequested;
if (!RequestJitterBufferPorts(PVMF_JITTER_BUFFER_PORT_TYPE_OUTPUT,
numPortsRequested))
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:ConstructGraphFor3GPPUDPStreaming - RequestJitterBufferPorts(PVMF_JITTER_BUFFER_PORT_TYPE_OUTPUT) Failed"));
return false;
}
iNumRequestPortsPending += numPortsRequested;
if (!RequestJitterBufferPorts(PVMF_JITTER_BUFFER_PORT_TYPE_FEEDBACK,
numPortsRequested))
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:ConstructGraphFor3GPPUDPStreaming - RequestJitterBufferPorts(PVMF_JITTER_BUFFER_PORT_TYPE_FEEDBACK) Failed"));
return false;
}
iNumRequestPortsPending += numPortsRequested;
if (!RequestMediaLayerPorts(PVMF_MEDIALAYER_PORT_TYPE_INPUT,
numPortsRequested))
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:ConstructGraphFor3GPPUDPStreaming - RequestMediaLayerPorts(PVMF_MEDIALAYER_PORT_TYPE_INPUT) Failed"));
return false;
}
iNumRequestPortsPending += numPortsRequested;
if (!RequestMediaLayerPorts(PVMF_MEDIALAYER_PORT_TYPE_OUTPUT,
numPortsRequested))
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:ConstructGraphFor3GPPUDPStreaming - RequestMediaLayerPorts(PVMF_MEDIALAYER_PORT_TYPE_OUTPUT) Failed"));
return false;
}
iNumRequestPortsPending += numPortsRequested;
return true;
}
bool PVMFSMRTSPUnicastNode::ReserveSockets()
{
uint32 sockid = 0;
char portConfigBuf[64];
oscl_memset((OsclAny*)portConfigBuf, 0, 64);
oscl_snprintf(portConfigBuf, 64, "%d", sockid);
OSCL_StackString<128> portConfig("UDP");
portConfig += _STRLIT_CHAR("/remote_address=0.0.0.0");
portConfig += _STRLIT_CHAR(";client_port=");
portConfig += portConfigBuf;
PVMFSMFSPChildNodeContainer* iSocketNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_SOCKET_NODE);
if (iSocketNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return false;
}
PVMFSocketNodeExtensionInterface* snExtIntf =
(PVMFSocketNodeExtensionInterface*)
(iSocketNodeContainer->iExtensions[0]);
PVMFRTSPTrackInfoVector::iterator it;
uint32 startPortNum = 0;
{
TimeValue current_time;
current_time.set_to_current_time();
uint32 my_seed = current_time.get_sec();
OsclRand random_num;
random_num.Seed(my_seed);
int32 first = random_num.Rand();
uint32 myport = (first & 0x1FFF) + 0x2000; //start from 8192
startPortNum = (myport >> 1) << 1; //start from even
}
for (it = iTrackInfoVec.begin();
it != iTrackInfoVec.end();
it++)
{
OSCL_StackString<128> portConfigWithMime;
portConfigWithMime += portConfig;
portConfigWithMime += _STRLIT_CHAR(";mime=");
portConfigWithMime += it->iMimeType;
PVMFStatus status = snExtIntf->AllocateConsecutivePorts(&portConfigWithMime,
it->iRTPSocketID,
it->iRTCPSocketID, startPortNum);
if (status != PVMFSuccess)
{
return false;
}
}
return true;
}
bool PVMFSMRTSPUnicastNode::RequestNetworkNodePorts(int32 portTag,
uint32& numPortsRequested)
{
numPortsRequested = 0;
PVMFSMFSPChildNodeContainer* nodeContainer =
getChildNodeContainer(PVMF_SM_FSP_SOCKET_NODE);
if (nodeContainer == NULL)
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode:RequestNetworkNodePorts - getChildNodeContainer Failed"));
return false;
}
for (uint32 i = 0; i < iTrackInfoVec.size(); i++)
{
PVMFRTSPTrackInfo 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 = portTag;
OsclAny *cmdContextData = OSCL_REINTERPRET_CAST(OsclAny*, internalCmd);
PVMFNodeInterface* iNode = nodeContainer->iNode;
uint32 sockid = 0;
bool oRTCP = false;
if (portTag == PVMF_SOCKET_NODE_PORT_TYPE_SOURCE)
{
sockid = trackInfo.iRTPSocketID;
}
else if (portTag == PVMF_SOCKET_NODE_PORT_TYPE_SINK)
{
sockid = trackInfo.iRTCPSocketID;
oRTCP = true;
}
char portConfigBuf[64];
oscl_memset((OsclAny*)portConfigBuf, 0, 64);
oscl_snprintf(portConfigBuf, 64, "%d", sockid);
OSCL_StackString<128> portConfig("UDP");
portConfig += _STRLIT_CHAR("/remote_address=0.0.0.0");
portConfig += _STRLIT_CHAR(";client_port=");
portConfig += portConfigBuf;
portConfig += _STRLIT_CHAR(";mime=");
portConfig += trackInfo.iMimeType.get_cstr();
if (oRTCP == true)
{
portConfig += _STRLIT_CHAR("/rtcp");
}
else
{
portConfig += _STRLIT_CHAR("/rtp");
}
iNode->RequestPort(nodeContainer->iSessionId,
internalCmd->portContext.portTag,
&portConfig,
cmdContextData);
numPortsRequested++;
nodeContainer->iNumRequestPortsPending++;
nodeContainer->iNodeCmdState = PVMFSMFSP_NODE_CMD_PENDING;
}
else
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:RequestNetworkNodePorts - RequestNewInternalCmd Failed"));
return false;
}
}
return true;
}
bool PVMFSMRTSPUnicastNode::RequestJitterBufferPorts(int32 portType,
uint32 &numPortsRequested)
{
PVMFSMFSPChildNodeContainer* nodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (nodeContainer == NULL)
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode: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++)
{
PVMFRTSPTrackInfo 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_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode:RequestJitterBufferPorts - RequestNewInternalCmd Failed"));
return false;
}
portTagStart += 3;
}
return true;
}
return false;
}
bool PVMFSMRTSPUnicastNode::RequestMediaLayerPorts(int32 portType,
uint32& numPortsRequested)
{
PVMFSMFSPChildNodeContainer* nodeContainer =
getChildNodeContainer(PVMF_SM_FSP_MEDIA_LAYER_NODE);
if (nodeContainer == NULL)
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode: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++)
{
PVMFRTSPTrackInfo 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_RTSP_LOGERROR((0, "StreamingManagerNode:RequestMediaLayerPorts - RequestNewInternalCmd Failed"));
return false;
}
portTagStart += 2;
}
return true;
}
//error
return false;
}
void PVMFSMRTSPUnicastNode::DoPrepare(PVMFSMFSPBaseNodeCommand& aCmd)
{
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::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_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode: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_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode:DoPrepare:RequestNewInternalCmd - Failed"));
CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
return;
}
}
MoveCmdToCurrentQueue(aCmd);
}
else
{
/* Graph construction not complete, so cant prep */
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode:DoPrepare Failed - Incomplete Graph"));
CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
}
}
break;
default:
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode:DoPrepare Failed - Invalid State"));
CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
break;
}
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::DoPrepare - Out"));
}
bool PVMFSMRTSPUnicastNode::GraphConnect()
{
if (iGraphConnectComplete == false)
{
/*
* Go over the track list and connect:
* network_node_port -> jitter_buffer_node_input_port;
* jitter_buffer_node_output_port -> media_layer_input_port
*/
PVMFStatus status;
for (uint32 i = 0; i < iTrackInfoVec.size(); i++)
{
PVMFRTSPTrackInfo trackInfo = iTrackInfoVec[i];
if ((trackInfo.iNetworkNodePort == NULL) ||
(trackInfo.iNetworkNodeRTCPPort == NULL) ||
(trackInfo.iJitterBufferInputPort == NULL) ||
(trackInfo.iJitterBufferOutputPort == NULL) ||
(trackInfo.iJitterBufferRTCPPort == NULL) ||
(trackInfo.iMediaLayerInputPort == NULL) ||
(trackInfo.iMediaLayerOutputPort == NULL))
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:GraphConnectFor3GPPUDPStreaming - Invalid Ports"));
return false;
}
PVMF_SM_RTSP_LOGINFO((0, "PVMFSM:GraphConnect - Track MimeType %s", trackInfo.iMimeType.get_cstr()));
/* connect network_node_port <-> jitter_buffer_node_input_port */
status = ConnectPortPairs(trackInfo.iJitterBufferInputPort,
trackInfo.iNetworkNodePort);
PVMF_SM_RTSP_LOGINFO((0, "PVMFSM:GraphConnectFor3GPPUDPStreaming - Connected Network - JB Input"));
PVMF_SM_RTSP_LOGINFO((0, "PVMFSM:GraphConnectFor3GPPUDPStreaming - NetworkPort=0x%x - JBInputPort=0x%x", trackInfo.iNetworkNodePort, trackInfo.iJitterBufferInputPort));
if (status != PVMFSuccess)
{
return false;
}
/*
* connect jitter_buffer_node_output_port <->
* media_layer_input_port
*/
status = ConnectPortPairs(trackInfo.iJitterBufferOutputPort,
trackInfo.iMediaLayerInputPort);
PVMF_SM_RTSP_LOGINFO((0, "PVMFSM:GraphConnectFor3GPPUDPStreaming - JB Output - ML Input"));
PVMF_SM_RTSP_LOGINFO((0, "PVMFSM:GraphConnectFor3GPPUDPStreaming - JB Output=0x%x - ML Input=0x%x", trackInfo.iJitterBufferOutputPort, trackInfo.iMediaLayerInputPort));
if (status != PVMFSuccess)
{
return false;
}
/*
* connect network_rtcp_port <-> jitter_buffer_rtcp_port
*/
status = ConnectPortPairs(trackInfo.iJitterBufferRTCPPort,
trackInfo.iNetworkNodeRTCPPort);
PVMF_SM_RTSP_LOGINFO((0, "PVMFSM:GraphConnectFor3GPPUDPStreaming - NetworkRTCPPort - JBRTCPPort"));
PVMF_SM_RTSP_LOGINFO((0, "PVMFSM:GraphConnectFor3GPPUDPStreaming - NetworkRTCPPort=0x%x - JBRTCPPort=0x%x", trackInfo.iNetworkNodeRTCPPort, trackInfo.iJitterBufferRTCPPort));
if (status != PVMFSuccess)
{
return false;
}
}
iGraphConnectComplete = true;
}
return true;
}
PVMFStatus PVMFSMRTSPUnicastNode::ConnectPortPairs(PVMFPortInterface* aPort1,
PVMFPortInterface* aPort2)
{
PVMFStatus status;
status = aPort1->Connect(aPort2);
if (status != PVMFSuccess)
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:ConnectPortPairs - Connect Failed"));
return status;
}
return status;
}
void PVMFSMRTSPUnicastNode::DoRequestPort(PVMFSMFSPBaseNodeCommand& aCmd)
{
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::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
*/
PVMFRTSPTrackInfo* trackInfo = FindTrackInfo(tag);
PVUuid eventuuid = PVMFStreamingManagerNodeEventTypeUUID;
int32 errcode = PVMFStreamingManagerNodeErrorInvalidRequestPortTag;
if (trackInfo == NULL)
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::DoRequestPort: FindTrackInfo failed"));
CommandComplete(iInputCommands, aCmd, PVMFErrArgument, NULL, &eventuuid, &errcode);
return;
}
if (trackInfo->iMediaLayerOutputPort == NULL)
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::DoRequestPort: iMediaLayerOutputPort NULL"));
CommandComplete(iInputCommands, aCmd, PVMFFailure, NULL, &eventuuid, &errcode);
return;
}
PVMF_SM_RTSP_LOG_COMMAND_SEQ((0, "PVMFSMRTSPUnicastNode::DoRequestPort() - CmdComplete - PVMFSuccess"));
/*
* Return the port pointer to the caller.
*/
CommandComplete(iInputCommands,
aCmd,
PVMFSuccess,
(OsclAny*)(trackInfo->iMediaLayerOutputPort));
PVMF_SM_RTSP_LOGINFO((0, "PVMFSMRTSPUnicastNode::DoRequestPort Success"));
}
else
{
PVMF_SM_RTSP_LOG_COMMAND_SEQ((0, "PVMFSMRTSPUnicastNode::RequestPort() - CmdFailed - PVMFErrInvalidState"));
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::DoRequestPort Failed - InvalidState"));
CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
}
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::DoRequestPort - Out"));
}
void PVMFSMRTSPUnicastNode::DoReleasePort(PVMFSMFSPBaseNodeCommand& aCmd)
{
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::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.
*/
PVMFRTSPTrackInfoVector::iterator it;
PVMFRTSPTrackInfo* 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_RTSP_LOG_COMMAND_SEQ((0, "PVMFSMRTSPUnicastNode::ReleasePort() - CmdFailed - PVMFErrArgument"));
/* invalid port */
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::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_RTSP_LOGINFO((0, "PVMFSMRTSPUnicastNode::DoReleasePort Success"));
CommandComplete(iInputCommands, aCmd, PVMFSuccess);
}
else
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::DoReleasePort Failed"));
CommandComplete(iInputCommands, aCmd, PVMFErrPortProcessing);
}
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::DoReleasePort - Out"));
}
void PVMFSMRTSPUnicastNode::DoStart(PVMFSMFSPBaseNodeCommand& aCmd)
{
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::DoStart - In"));
switch (iInterfaceState)
{
case EPVMFNodePrepared:
{
/*
* Connect the graph if not already connected. Usually the graph is
* disconnected as part of Stop. In case we are doing a start after
* stop, we would need to connect the graph again.
*/
if (GraphConnect() == false)
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode:CompleteStart - GraphConnect Failed"));
SetState(EPVMFNodeError);
PVUuid eventuuid = PVMFStreamingManagerNodeEventTypeUUID;
int32 errcode = PVMFStreamingManagerNodeGraphConnectFailed;
CommandComplete(iInputCommands, aCmd, PVMFFailure, NULL, &eventuuid, &errcode);
return;
}
bool isSessionDurationExpired = false;
PVMFSMFSPChildNodeContainer* jitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (jitterBufferNodeContainer)
{
PVMFJitterBufferExtensionInterface* jbExtIntf =
OSCL_STATIC_CAST(PVMFJitterBufferExtensionInterface*, jitterBufferNodeContainer->iExtensions.front());
if (jbExtIntf)
jbExtIntf->HasSessionDurationExpired(isSessionDurationExpired);
}
PVMFSMFSPChildNodeContainer *sessionControllerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
if (sessionControllerNodeContainer)
{
PVRTSPEngineNodeExtensionInterface* rtspExtIntf =
OSCL_STATIC_CAST(PVRTSPEngineNodeExtensionInterface*, sessionControllerNodeContainer->iExtensions.front());
if (rtspExtIntf)
rtspExtIntf->UpdateSessionCompletionStatus(isSessionDurationExpired);
}
/*
* Start for streaming manager cannot be completed unless
* Start 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_START_CMD_OFFSET;
internalCmd->parentCmd = aCmd.iCmd;
OsclAny *cmdContextData = OSCL_REINTERPRET_CAST(OsclAny*, internalCmd);
PVMFNodeInterface* iNode = it->iNode;
iNode->Start(it->iSessionId, cmdContextData);
it->iNodeCmdState = PVMFSMFSP_NODE_CMD_PENDING;
}
else
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode:DoStart:RequestNewInternalCmd - Failed"));
CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
return;
}
}
MoveCmdToCurrentQueue(aCmd);
}
break;
/*
* GraphConnect() not needed if starting from a paused state
*/
case EPVMFNodePaused:
{
bool isSessionDurationExpired = false;
PVMFSMFSPChildNodeContainer* jitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (jitterBufferNodeContainer)
{
PVMFJitterBufferExtensionInterface* jbExtIntf =
OSCL_STATIC_CAST(PVMFJitterBufferExtensionInterface*, jitterBufferNodeContainer->iExtensions.front());
if (jbExtIntf)
jbExtIntf->HasSessionDurationExpired(isSessionDurationExpired);
}
PVMFSMFSPChildNodeContainer *sessionControllerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
if (sessionControllerNodeContainer)
{
PVRTSPEngineNodeExtensionInterface* rtspExtIntf =
OSCL_STATIC_CAST(PVRTSPEngineNodeExtensionInterface*, sessionControllerNodeContainer->iExtensions.front());
if (rtspExtIntf)
rtspExtIntf->UpdateSessionCompletionStatus(isSessionDurationExpired);
}
/*
* Start for streaming manager cannot be completed unless
* Start for all the children nodes are complete
*/
PVMFSMFSPChildNodeContainerVector::iterator it;
for (it = iFSPChildNodeContainerVec.begin(); it != iFSPChildNodeContainerVec.end(); it++)
{
if (it->iAutoPaused == false)
{
PVMFSMFSPCommandContext* internalCmd = RequestNewInternalCmd();
if (internalCmd != NULL)
{
internalCmd->cmd =
it->commandStartOffset +
PVMF_SM_FSP_NODE_INTERNAL_START_CMD_OFFSET;
internalCmd->parentCmd = aCmd.iCmd;
OsclAny *cmdContextData = OSCL_REINTERPRET_CAST(OsclAny*, internalCmd);
PVMFNodeInterface* iNode = it->iNode;
iNode->Start(it->iSessionId, cmdContextData);
it->iNodeCmdState = PVMFSMFSP_NODE_CMD_PENDING;
}
else
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode:DoStart:RequestNewInternalCmd - Failed"));
CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
return;
}
}
}
MoveCmdToCurrentQueue(aCmd);
}
break;
case EPVMFNodeStarted:
//Ignore start if already started
CommandComplete(iInputCommands, aCmd, PVMFSuccess);
break;
default:
CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
break;
}
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::DoStart - Out"));
}
void PVMFSMRTSPUnicastNode::DoStop(PVMFSMFSPBaseNodeCommand& aCmd)
{
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::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_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode:DoStop:RequestNewInternalCmd - Failed"));
CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
return;
}
}
MoveCmdToCurrentQueue(aCmd);
}
break;
default:
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::DoStop Failure - Invalid State"));
CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
break;
}
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::DoStop - Out"));
}
void PVMFSMRTSPUnicastNode::DoPause(PVMFSMFSPBaseNodeCommand& aCmd)
{
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::DoPause - In"));
switch (iInterfaceState)
{
case EPVMFNodeStarted:
{
bool isSessionDurationExpired = false;
PVMFSMFSPChildNodeContainer* jitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (jitterBufferNodeContainer)
{
PVMFJitterBufferExtensionInterface* jbExtIntf =
OSCL_STATIC_CAST(PVMFJitterBufferExtensionInterface*, jitterBufferNodeContainer->iExtensions.front());
if (jbExtIntf)
jbExtIntf->HasSessionDurationExpired(isSessionDurationExpired);
}
PVMFSMFSPChildNodeContainer *sessionControllerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
if (sessionControllerNodeContainer)
{
PVRTSPEngineNodeExtensionInterface* rtspExtIntf =
OSCL_STATIC_CAST(PVRTSPEngineNodeExtensionInterface*, sessionControllerNodeContainer->iExtensions.front());
if (rtspExtIntf)
rtspExtIntf->UpdateSessionCompletionStatus(isSessionDurationExpired);
}
PVMFSMFSPChildNodeContainerVector::iterator it;
for (it = iFSPChildNodeContainerVec.begin(); it != iFSPChildNodeContainerVec.end(); it++)
{
/*
* Pause only if not already paused - could happen that
* some of the nodes could be paused due to flow control
*/
if ((it->iNode->GetState()) != EPVMFNodePaused)
{
PVMFSMFSPCommandContext* internalCmd = RequestNewInternalCmd();
if (internalCmd != NULL)
{
internalCmd->cmd =
it->commandStartOffset +
PVMF_SM_FSP_NODE_INTERNAL_PAUSE_CMD_OFFSET;
internalCmd->parentCmd = aCmd.iCmd;
OsclAny *cmdContextData = OSCL_REINTERPRET_CAST(OsclAny*, internalCmd);
PVMFNodeInterface* iNode = it->iNode;
iNode->Pause(it->iSessionId, cmdContextData);
it->iNodeCmdState = PVMFSMFSP_NODE_CMD_PENDING;
}
else
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode:DoPause:RequestNewInternalCmd - Failed"));
CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
return;
}
}
}
MoveCmdToCurrentQueue(aCmd);
}
break;
default:
CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
break;
}
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::DoPause - Out"));
return;
}
PVMFRTSPTrackInfo* PVMFSMRTSPUnicastNode::FindTrackInfo(uint32 atrackID)
{
PVMFRTSPTrackInfoVector::iterator it;
for (it = iTrackInfoVec.begin();
it != iTrackInfoVec.end();
it++)
{
if (it->trackID == atrackID)
{
return (it);
}
}
return NULL;
}
///////////////////////////////////////////////////////////////////////////////
//Implemenation of pure virtuals from PvmiCapabilityAndConfig interface
///////////////////////////////////////////////////////////////////////////////
void PVMFSMRTSPUnicastNode::setObserver(PvmiConfigAndCapabilityCmdObserver* aObserver)
{
ciObserver = aObserver;
}
PVMFStatus PVMFSMRTSPUnicastNode::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, "PVMFSMRTSPUnicastNode::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, "PVMFSMRTSPUnicastNode::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, "PVMFSMRTSPUnicastNode::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, "PVMFSMRTSPUnicastNode::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, "PVMFSMRTSPUnicastNode::getParametersSync() Unsupported key"));
return PVMFErrNoMemory;
}
#if 0
// Return the requested info
oscl_free(aParameters);
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFSMRTSPUnicastNode::getParametersSync() Memory allocation for key string failed"));
return PVMFErrNoMemory;
#endif
PVMFStatus retval = GetConfigParameter(aParameters, aNumParamElements, i, reqattr);
if (retval != PVMFSuccess)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFSMRTSPUnicastNode::getParametersSync() "
"Retrieving streaming manager parameter failed"));
return retval;
}
}
else
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFSMRTSPUnicastNode::getParametersSync() Unsupported key"));
return PVMFErrArgument;
}
return PVMFSuccess;
}
PVMFStatus PVMFSMRTSPUnicastNode::GetConfigParameter(PvmiKvp*& aParameters,
int& aNumParamElements,
int32 aIndex, PvmiKvpAttr reqattr)
{
PVMF_SM_RTSP_LOGINFO((0, "PVMFSMRTSPUnicastNode::GetConfigParameter() In"));
aNumParamElements = 0;
// Allocate memory for the KVP
aParameters = (PvmiKvp*)oscl_malloc(sizeof(PvmiKvp));
if (aParameters == NULL)
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::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_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::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];
if (!jbExtIntf)
return PVMFFailure;
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_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::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_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_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::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_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];
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_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::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];
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_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::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);
uint32 inactivityDuration = 0;
if (jbExtIntf)
{
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_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::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_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::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_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_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastPlusPVRNode::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;
}
PVMFStatus PVMFSMRTSPUnicastNode::releaseParameters(PvmiMIOSession aSession,
PvmiKvp* aParameters,
int num_elements)
{
OSCL_UNUSED_ARG(aSession);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFSMRTSPUnicastNode::releaseParameters() In"));
if (aParameters == NULL || num_elements < 1)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFSMRTSPUnicastNode::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, "PVMFSMRTSPUnicastNode::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, "PVMFSMRTSPUnicastNode::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, "PVMFSMRTSPUnicastNode::releaseParameters() Out"));
return PVMFSuccess;
}
void PVMFSMRTSPUnicastNode::createContext(PvmiMIOSession aSession,
PvmiCapabilityContext& aContext)
{
OSCL_UNUSED_ARG(aSession);
OSCL_UNUSED_ARG(aContext);
// not supported
OSCL_LEAVE(PVMFErrNotSupported);
}
void PVMFSMRTSPUnicastNode::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);
}
void PVMFSMRTSPUnicastNode::DeleteContext(PvmiMIOSession aSession,
PvmiCapabilityContext& aContext)
{
OSCL_UNUSED_ARG(aSession);
OSCL_UNUSED_ARG(aContext);
// not supported
OSCL_LEAVE(PVMFErrNotSupported);
}
void PVMFSMRTSPUnicastNode::setParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters,
int num_elements, PvmiKvp* &aRet_kvp)
{
OSCL_UNUSED_ARG(aSession);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFSMRTSPUnicastNode::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, "PVMFSMRTSPUnicastNode::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, "PVMFSMRTSPUnicastNode::setParametersSync() Unsupported key"));
return;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
(0, "PVMFSMRTSPUnicastNode::setParametersSync() key str %s", compstr));
// 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, "PVMFSMRTSPUnicastNode::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, "PVMFSMRTSPUnicastNode::setParametersSync() Unsupported key"));
return;
}
}
else
{
// Unknown key string
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFSMRTSPUnicastNode::setParametersSync() Unsupported key"));
return;
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFSMRTSPUnicastNode::setParametersSync() Out"));
}
uint32 PVMFSMRTSPUnicastNode::getCapabilityMetric(PvmiMIOSession aSession)
{
OSCL_UNUSED_ARG(aSession);
return 0;
}
PVMFStatus PVMFSMRTSPUnicastNode::verifyParametersSync(PvmiMIOSession aSession,
PvmiKvp* aParameters,
int num_elements)
{
OSCL_UNUSED_ARG(aSession);
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFSMRTSPUnicastNode::verifyParametersSync() In"));
if (aParameters == NULL || num_elements < 1)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
(0, "PVMFSMRTSPUnicastNode::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, "PVPlayerEngine::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, "PVPlayerEngine::DoCapConfigVerifyParameters() Verifying parameter %d failed", paramind));
return retval;
}
}
else
{
// Unknown key string
return PVMFErrArgument;
}
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVPlayerEngine::DoCapConfigVerifyParameters() Out"));
return PVMFSuccess;
}
PVMFStatus PVMFSMRTSPUnicastNode::VerifyAndSetConfigParameter(int index, PvmiKvp& aParameter, bool set)
{
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::VerifyAndSetConfigParameter() In index[%d]", index));
// Determine the valtype
PvmiKvpValueType keyvaltype = GetValTypeFromKeyString(aParameter.key);
if (keyvaltype == PVMI_KVPVALTYPE_UNKNOWN)
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::VerifyAndSetConfigParameter() "
"Valtype in key string unknown"));
return PVMFErrArgument;
}
// Verify the valtype
if (keyvaltype != StreamingManagerConfig_BaseKeys[index].iValueType)
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::VerifyAndSetConfigParameter() "
"Valtype does not match for key"));
return PVMFErrArgument;
}
switch (index)
{
case BASEKEY_DELAY:
{
uint32 rebuffThreshold = 0;
PVMFSMFSPChildNodeContainer* iJitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
OSCL_ASSERT(iJitterBufferNodeContainer);
if (!iJitterBufferNodeContainer)
return PVMFFailure;
PVMFJitterBufferExtensionInterface* jbExtIntf = NULL;
if (iJitterBufferNodeContainer)
jbExtIntf = (PVMFJitterBufferExtensionInterface*)iJitterBufferNodeContainer->iExtensions[0];
if (jbExtIntf)
jbExtIntf->getJitterBufferRebufferingThresholdInMilliSeconds(rebuffThreshold);
if (!jbExtIntf)
return PVMFFailure;
// Validate
if ((aParameter.value.uint32_value < MIN_JITTER_BUFFER_DURATION_IN_MS) ||
(aParameter.value.uint32_value > MAX_JITTER_BUFFER_DURATION_IN_MS) ||
(aParameter.value.uint32_value < rebuffThreshold))
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::VerifyAndSetConfigParameter() "
"Trying to set delay to 0"));
return PVMFErrArgument;
}
if (set)
{
// save value locally
setJitterBufferDurationInMilliSeconds(aParameter.value.uint32_value);
// pass the value on to the jitter buffer node
jbExtIntf->setJitterBufferDurationInMilliSeconds(aParameter.value.uint32_value);
}
}
break;
case BASEKEY_REBUFFERING_THRESHOLD:
{
uint32 jbDuration = 0;
PVMFSMFSPChildNodeContainer* iJitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
OSCL_ASSERT(iJitterBufferNodeContainer);
if (!iJitterBufferNodeContainer)
return PVMFFailure;
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)iJitterBufferNodeContainer->iExtensions[0];
jbExtIntf->getJitterBufferDurationInMilliSeconds(jbDuration);
// Validate
if (aParameter.value.uint32_value >= jbDuration)
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::VerifyAndSetConfigParameter() "
"Trying to set rebuffering threshold greater than equal to jitter buffer duration"));
return PVMFErrArgument;
}
if (set)
{
// pass the value on to the jitter buffer node
jbExtIntf->setJitterBufferRebufferingThresholdInMilliSeconds(aParameter.value.uint32_value);
}
}
break;
case BASEKEY_JITTERBUFFER_NUMRESIZE:
{
if (set)
{
// retrieve and update
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);
jbExtIntf->SetSharedBufferResizeParams(aParameter.value.uint32_value, resizeSize);
}
}
break;
case BASEKEY_JITTERBUFFER_RESIZESIZE:
{
if (set)
{
// retrieve and update
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);
jbExtIntf->SetSharedBufferResizeParams(numResize, aParameter.value.uint32_value);
}
}
break;
case BASEKEY_JITTERBUFFER_MAX_INACTIVITY_DURATION:
{
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;
//validate input value...
if (aParameter.value.uint32_value > DEFAULT_MAX_INACTIVITY_DURATION_IN_MS)
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::VerifyAndSetConfigParameter() "
"Trying to set max inactivity duration greater than allowed inactivity duration"));
return PVMFErrArgument;
}
if (set)
{
//update the maximum alloyed delay for the incoming msg at input port of JB node
jbExtIntf->setMaxInactivityDurationForMediaInMs(aParameter.value.uint32_value);
}
}
break;
case BASEKEY_SESSION_CONTROLLER_USER_AGENT:
{
if (set)
{
// user agent update
PVMFSMFSPChildNodeContainer* iSessionControllerNodeContainer = NULL;
iSessionControllerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
OSCL_wHeapString<OsclMemAllocator> userAgent;
OSCL_wHeapString<OsclMemAllocator> dummy;
if (iSessionControllerNodeContainer != NULL)
{
PVRTSPEngineNodeExtensionInterface* rtspExtIntf =
(PVRTSPEngineNodeExtensionInterface*)
(iSessionControllerNodeContainer->iExtensions[0]);
userAgent = aParameter.value.pWChar_value;
rtspExtIntf->SetClientParameters(userAgent, dummy, dummy);
}
// save user-agent kvp for cpm
if (iCPM)
{
PVMFStatus status = iCPMKvpStore.addKVPString(aParameter.key, userAgent);
if (status != PVMFSuccess) return status;
}
}
}
break;
case BASEKEY_SESSION_CONTROLLER_KEEP_ALIVE_DURING_PLAY:
{
if (set)
{
// keep-alive during play update
/* As of now just RTSP node supports an external config of keep-alive during play */
PVMFSMFSPChildNodeContainer* iSessionControllerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
if (iSessionControllerNodeContainer != NULL)
{
PVRTSPEngineNodeExtensionInterface* rtspExtIntf =
(PVRTSPEngineNodeExtensionInterface*)
(iSessionControllerNodeContainer->iExtensions[0]);
rtspExtIntf->SetKeepAliveMethod_keep_alive_in_play(aParameter.value.bool_value);
}
}
}
break;
case BASEKEY_SESSION_CONTROLLER_RTSP_TIMEOUT:
{
if (set)
{
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::VerifyAndSetConfigParameter() BASEKEY_SESSION_CONTROLLER_RTSP_TIMEOUT "));
// RTSP response waiting time out
PVMFSMFSPChildNodeContainer* iSessionControllerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
if (iSessionControllerNodeContainer != NULL)
{
PVRTSPEngineNodeExtensionInterface* rtspExtIntf =
(PVRTSPEngineNodeExtensionInterface*)
(iSessionControllerNodeContainer->iExtensions[0]);
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::VerifyAndSetConfigParameter() BASEKEY_SESSION_CONTROLLER_RTSP_TIMEOUT rtspExtIntf%x", rtspExtIntf));
rtspExtIntf->SetRTSPTimeOut(aParameter.value.uint32_value);
}
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::VerifyAndSetConfigParameter() BASEKEY_SESSION_CONTROLLER_RTSP_TIMEOUT Done"));
}
}
break;
case BASEKEY_DISABLE_FIREWALL_PACKETS:
{
if (set)
{
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->DisableFireWallPackets();
}
}
break;
default:
return PVMFErrNotSupported;
}
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "PVMFSMRTSPUnicastNode::VerifyAndSetPlayerParameter() Out"));
return PVMFSuccess;
}
///////////////////////////////////////////////////////////////////////////////
// Implemenation of PVMFDataSourceInitializationExtensionInterface interface
///////////////////////////////////////////////////////////////////////////////
PVMFStatus PVMFSMRTSPUnicastNode::SetSourceInitializationData(OSCL_wString& aSourceURL, PVMFFormatType& aSourceFormat, OsclAny* aSourceData)
{
//To set proxy server info with the session controller node
if (aSourceData != NULL)
{
PVInterface* pvInterface = OSCL_STATIC_CAST(PVInterface*, aSourceData);
PVInterface* sourceDataContext = NULL;
PVUuid sourceContextUuid(PVMF_SOURCE_CONTEXT_DATA_UUID);
if (pvInterface->queryInterface(sourceContextUuid, sourceDataContext))
{
if (sourceDataContext)
{
PVInterface* streamingDataContext = NULL;
PVUuid streamingContextUuid(PVMF_SOURCE_CONTEXT_DATA_STREAMING_UUID);
if (sourceDataContext->queryInterface(streamingContextUuid, streamingDataContext))
{
if (streamingDataContext)
{
PVMFSourceContextDataStreaming* sContext =
OSCL_STATIC_CAST(PVMFSourceContextDataStreaming*, streamingDataContext);
if (sContext->iProxyName.get_size() > 0)
{
PVMFSMFSPChildNodeContainer* iSessionControllerNodeContainer = NULL;
iSessionControllerNodeContainer = getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
if (iSessionControllerNodeContainer)
{
PVRTSPEngineNodeExtensionInterface* rtspExtIntf =
(PVRTSPEngineNodeExtensionInterface*)(iSessionControllerNodeContainer->iExtensions[0]);
if (rtspExtIntf)
{ //the proxyname doesn't need to be unicode
OsclMemAllocator alloc;
char *buf = (char*)alloc.allocate(sContext->iProxyName.get_size() + 1);
if (!buf)
return PVMFErrNoMemory;
uint32 size = oscl_UnicodeToUTF8(sContext->iProxyName.get_cstr(), sContext->iProxyName.get_size(), buf, sContext->iProxyName.get_size() + 1);
if (size == 0)
{
alloc.deallocate(buf);
return PVMFErrNoMemory;
}
OSCL_FastString myProxyName(buf, size);
rtspExtIntf->SetRtspProxy(myProxyName, sContext->iProxyPort);
alloc.deallocate(buf);
}
}
}
}
}
}
}
}
//to check if we should use CPM plugin?
if (aSourceData)
{
PVInterface* pvInterface =
OSCL_STATIC_CAST(PVInterface*, aSourceData);
PVInterface* streamingDataSrc = NULL;
PVUuid streamingDataSrcUuid(PVMF_STREAMING_DATASOURCE_UUID);
if (pvInterface->queryInterface(streamingDataSrcUuid, streamingDataSrc))
{
PVMFStreamingDataSource* opaqueData =
OSCL_STATIC_CAST(PVMFStreamingDataSource*, streamingDataSrc);
iPreviewMode = opaqueData->iPreviewMode;
iUseCPMPluginRegistry = opaqueData->iUseCPMPluginRegistry;
iCPMSourceData.iPreviewMode = iPreviewMode;
iCPMSourceData.iIntent = opaqueData->iIntent;
}
else
{
PVInterface* sourceDataContext = NULL;
PVInterface* commonDataContext = NULL;
PVUuid sourceContextUuid(PVMF_SOURCE_CONTEXT_DATA_UUID);
PVUuid commonContextUuid(PVMF_SOURCE_CONTEXT_DATA_COMMON_UUID);
if (pvInterface->queryInterface(sourceContextUuid, sourceDataContext))
{
if (sourceDataContext->queryInterface(commonContextUuid, commonDataContext))
{
PVMFSourceContextDataCommon* cContext =
OSCL_STATIC_CAST(PVMFSourceContextDataCommon*, commonDataContext);
iPreviewMode = cContext->iPreviewMode;
iUseCPMPluginRegistry = cContext->iUseCPMPluginRegistry;
PVMFSourceContextData* sContext =
OSCL_STATIC_CAST(PVMFSourceContextData*, sourceDataContext);
iSourceContextData = *sContext;
iSourceContextDataValid = true;
}
}
}
}
/*
* If a CPM flag is provided in the source data, then
* create a CPM object here...
*/
if (iUseCPMPluginRegistry)
{
//cleanup any prior instance
if (iCPM)
{
iCPM->ThreadLogoff();
PVMFCPMFactory::DestroyContentPolicyManager(iCPM);
iCPM = NULL;
}
iCPM = PVMFCPMFactory::CreateContentPolicyManager(*this);
iCPM->ThreadLogon();
}
//to set the sessionsource info and configure session controller node [RTSP client], with the session type
if ((aSourceFormat == PVMF_MIME_DATA_SOURCE_RTSP_URL))
{
PVMFSMFSPChildNodeContainer* iSessionControllerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
if (iSessionControllerNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return PVMFFailure;
}
PVRTSPEngineNodeExtensionInterface* rtspExtIntf =
(PVRTSPEngineNodeExtensionInterface*)
(iSessionControllerNodeContainer->iExtensions[0]);
iSessionSourceInfo->_sessionType = aSourceFormat;
iSessionSourceInfo->_sessionURL = aSourceURL;
rtspExtIntf->SetStreamingType(PVRTSP_3GPP_UDP);
return (rtspExtIntf->SetSessionURL(iSessionSourceInfo->_sessionURL));
}
else if (aSourceFormat == PVMF_MIME_DATA_SOURCE_SDP_FILE)
{
PVMFSMFSPChildNodeContainer* iSessionControllerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
if (iSessionControllerNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return PVMFFailure;
}
PVRTSPEngineNodeExtensionInterface* rtspExtIntf =
(PVRTSPEngineNodeExtensionInterface*)
(iSessionControllerNodeContainer->iExtensions[0]);
// right now, PVMF_MIME_DATA_SOURCE_SDP_FILE => non-interleaved RTSP
rtspExtIntf->SetStreamingType(PVRTSP_3GPP_UDP);
iSessionSourceInfo->_sessionType = aSourceFormat;
iSessionSourceInfo->_sessionURL = aSourceURL;
iSessionSourceInfo->_sourceData = aSourceData;
return PVMFSuccess;
}
else
return PVMFErrNotSupported;
}
PVMFStatus PVMFSMRTSPUnicastNode::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;
}
PVMFStatus PVMFSMRTSPUnicastNode::SetEstimatedServerClock(PVMFMediaClock* aClientClock)
{
OSCL_UNUSED_ARG(aClientClock);
return PVMFErrNotSupported;
}
///////////////////////////////////////////////////////////////////////////////
//Implementation of PVMFTrackSelectionExtensionInterface
///////////////////////////////////////////////////////////////////////////////
PVMFStatus PVMFSMRTSPUnicastNode::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 iAltType = PVMF_TRACK_ALTERNATE_TYPE_UNDEFINED;
if (sdpAltGroupType == SDP_ALT_GROUP_LANGUAGE)
{
iAltType = PVMF_TRACK_ALTERNATE_TYPE_LANGUAGE;
}
else if (sdpAltGroupType == SDP_ALT_GROUP_BANDWIDTH)
{
iAltType = 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 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];
// 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 PVMFFailure;
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 (iAltType != PVMF_TRACK_ALTERNATE_TYPE_UNDEFINED)
{
/* Expose alternate track ids */
trackInfo.setTrackAlternates(iAltType);
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;
}
PVMFStatus PVMFSMRTSPUnicastNode::SelectTracks(PVMFMediaPresentationInfo& aInfo)
{
SDPInfo* sdpInfo = iSdpInfo.GetRep();
if (sdpInfo == NULL)
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode: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_RTSP_LOGERROR((0, "StreamingManagerNode: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;
}
///////////////////////////////////////////////////////////////////////////////
//Implementation of PVMFMetadataExtensionInterface
///////////////////////////////////////////////////////////////////////////////
uint32 PVMFSMRTSPUnicastNode::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 PVMFSMRTSPUnicastNode::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 PVMFSMRTSPUnicastNode::DoGetMetadataKeys(PVMFSMFSPBaseNodeCommand& aCmd)
{
return DoGetMetadataKeysBase(aCmd);
}
PVMFStatus PVMFSMRTSPUnicastNode::GetRTSPPluginSpecificValues(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)
{
PVMFStatus retval = PVMFCreateKVPUtils::CreateKVPForBoolValue(KeyVal,
PVMFSTREAMINGMGRNODE_PAUSE_DENIED_KEY,
iPauseDenied);
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;
}
PVMFStatus PVMFSMRTSPUnicastNode::DoGetMetadataValues(PVMFSMFSPBaseNodeCommand& aCmd)
{
iNoOfValuesIteratedForValueVect = 0;
iNoOfValuesPushedInValueVect = 0;
PVMFStatus retval = GetRTSPPluginSpecificValues(aCmd);
if (PVMFSuccess != retval)
return retval;
return DoGetMetadataValuesBase(aCmd);
}
PVMFStatus PVMFSMRTSPUnicastNode::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 PVMFSMRTSPUnicastNode::ReleaseNodeMetadataValues(Oscl_Vector<PvmiKvp, OsclMemAllocator>& aValueList,
uint32 aStartingValueIndex,
uint32 aEndValueIndex)
{
//no allocation for any value in kvp took in derived class so just calling base class release functions
return ReleaseNodeMetadataValuesBase(aValueList, aStartingValueIndex, aEndValueIndex);
}
void PVMFSMRTSPUnicastNode::DoSetDataSourcePosition(PVMFSMFSPBaseNodeCommand& aCmd)
{
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMFSPBaseNodeCommand::DoSetDataSourcePosition - In"));
iActualRepositionStartNPTInMSPtr = NULL;
iActualMediaDataTSPtr = NULL;
iPVMFDataSourcePositionParamsPtr = NULL;
iJumpToIFrame = false;
uint32 streamID = 0;
aCmd.PVMFSMFSPBaseNodeCommand::Parse(iRepositionRequestedStartNPTInMS,
iActualRepositionStartNPTInMSPtr,
iActualMediaDataTSPtr,
iJumpToIFrame,
streamID);
PVMF_SM_RTSP_LOG_COMMAND_REPOS((0, "PVMFSMFSPBaseNodeCommand::DoSetDataSourcePosition - TargetNPT = %d", iRepositionRequestedStartNPTInMS));
PVMFSMFSPChildNodeContainer* iJitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (iJitterBufferNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return;
}
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)
(iJitterBufferNodeContainer->iExtensions[0]);
*iActualRepositionStartNPTInMSPtr = 0;
*iActualMediaDataTSPtr = 0;
if ((iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_RTSP_URL) ||
(iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_SDP_FILE))
{
if (iInterfaceState == EPVMFNodePrepared)
{
iStreamID = streamID;
jbExtIntf->SendBOSMessage(iStreamID);
bool oRandAccessDenied = true;
sessionDescription* sessionInfo =
iSdpInfo->getSessionInfo();
oRandAccessDenied = sessionInfo->getRandomAccessDenied();
if ((oRandAccessDenied == true) ||
(iSessionStopTimeAvailable == false) ||
(((int32)iRepositionRequestedStartNPTInMS < (int32)iSessionStartTime) ||
((int32)iRepositionRequestedStartNPTInMS >= (int32)iSessionStopTime)))
{
if (iRepositionRequestedStartNPTInMS == 0)
{
/* Implies that we are repositioning to zero, which is not a invalid request
* so dont send PVMFErrNotSupported
*/
}
else
{
/*
* Implies an open ended session or invalid request time
* - no pause or reposition
*/
CommandComplete(iInputCommands, aCmd, PVMFErrNotSupported);
return;
}
}
/*
* SetDataSource from a prepared state could mean two things:
* - In Play-Stop-Play usecase engine does a SetDataSourcePosition
* to get the start media TS to set its playback clock
* - Engine is trying to do a play with a non-zero start offset
*/
if (iRepositionRequestedStartNPTInMS < iSessionStopTime && iRepositionRequestedStartNPTInMS != iSessionStartTime)
{
// we need to use part of the logic of repositioning to start
// streaming from a non-zero offset. Enabled only for 3gpp streaming
iRepositioning = true;
/* Start the nodes */
PVMFStatus status = DoRepositioningStart3GPPStreaming();
if (PVMFSuccess != status)
{
CommandComplete(iInputCommands, aCmd, status);
return;
}
MoveCmdToCurrentQueue(aCmd);
return;
}
GetActualMediaTSAfterSeek();
PVMF_SM_RTSP_LOG_COMMAND_SEQ((0, "PVMFSMRTSPUnicastNode::SetDataSourcePosition() - CmdComplete"));
CommandComplete(iInputCommands, aCmd, PVMFSuccess);
}
else if ((iInterfaceState == EPVMFNodeStarted) || (iInterfaceState == EPVMFNodePaused))
{
bool oRandAccessDenied = true;
sessionDescription* sessionInfo =
iSdpInfo->getSessionInfo();
oRandAccessDenied = sessionInfo->getRandomAccessDenied();
if (!CanPerformRepositioning(oRandAccessDenied))
{
CommandComplete(iInputCommands, aCmd, PVMFErrNotSupported);
return;
}
iStreamID = streamID;
jbExtIntf->SendBOSMessage(iStreamID);
iRepositioning = true;
/* Put the jitter buffer into a state of transition */
PVMFSMFSPChildNodeContainer* iJitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (iJitterBufferNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return;
}
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)
(iJitterBufferNodeContainer->iExtensions[0]);
jbExtIntf->PrepareForRepositioning();
/* If node is running, pause first */
if (iInterfaceState == EPVMFNodeStarted)
{
if (!DoRepositioningPause3GPPStreaming())
{
CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
}
}
/* If already paused do not pause */
else if (iInterfaceState == EPVMFNodePaused)
{
PVMFStatus status = DoRepositioningStart3GPPStreaming();
if (PVMFSuccess != status)
{
CommandComplete(iInputCommands, aCmd, status);
}
}
MoveCmdToCurrentQueue(aCmd);
}
else
{
CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
return;
}
}
else
{
PVMF_SM_RTSP_LOG_COMMAND_SEQ((0, "PVMFSMRTSPUnicastNode::SetDataSourcePosition() - Cmd Failed - PVMFErrArgument"));
CommandComplete(iInputCommands, aCmd, PVMFErrArgument);
return;
}
return;
}
void PVMFSMRTSPUnicastNode::DoQueryDataSourcePosition(PVMFSMFSPBaseNodeCommand& aCmd)
{
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::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_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::DoQueryDataSourcePosition - Out"));
return;
}
PVMFStatus PVMFSMRTSPUnicastNode::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;
}
///////////////////////////////////////////////////////////////////////////////
//Implementation of the virtual function declared in PVMFNodeCmdStatusObserver
///////////////////////////////////////////////////////////////////////////////
void PVMFSMRTSPUnicastNode::NodeCommandCompleted(const PVMFCmdResp& aResponse)
{
PVMF_SM_RTSP_LOGINFO((0, "PVMFSMRTSPUnicastNode::NodeCommandCompleted"));
bool performErrHandling = false;
HandleChildNodeCommandCompletion(aResponse, performErrHandling);
PVMF_SM_RTSP_LOGINFO((0, "PVMFSMRTSPUnicastNode::NodeCommandCompleted - performErrHandling[%d]", performErrHandling));
if (performErrHandling == true)
{
HandleError(aResponse);
}
return;
}
/**
retval: true - perform error handling based on response (if needed)
retval: false - do not perform error handling.Concrete implemenbtation of the FSP will take care of error handling
*/
void PVMFSMRTSPUnicastNode::HandleChildNodeCommandCompletion(const PVMFCmdResp& aResponse, bool& aPerformErrHandling)
{
aPerformErrHandling = true;
PVMFSMFSPCommandContext *cmdContextData =
OSCL_REINTERPRET_CAST(PVMFSMFSPCommandContext*, aResponse.GetContext());
PVMF_SM_RTSP_LOGINFO((0, "PVMFSMRTSPUnicastNode:HandleChildNodeCommandCompletion: %d", cmdContextData->cmd));
if ((cmdContextData->cmd >=
PVMF_SM_FSP_SOCKET_NODE_COMMAND_START) &&
(cmdContextData->cmd <
PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_COMMAND_START))
{
HandleSocketNodeCommandCompleted(aResponse, aPerformErrHandling);
}
else if ((cmdContextData->cmd >=
PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_COMMAND_START) &&
(cmdContextData->cmd <
PVMF_SM_FSP_JITTER_BUFFER_CONTROLLER_COMMAND_START))
{
HandleRTSPSessionControllerCommandCompleted(aResponse, aPerformErrHandling);
}
else if ((cmdContextData->cmd >=
PVMF_SM_FSP_JITTER_BUFFER_CONTROLLER_COMMAND_START) &&
(cmdContextData->cmd <
PVMF_SM_FSP_MEDIA_LAYER_COMMAND_START))
{
HandleJitterBufferCommandCompleted(aResponse, aPerformErrHandling);
}
else if ((cmdContextData->cmd >=
PVMF_SM_FSP_MEDIA_LAYER_COMMAND_START) &&
(cmdContextData->cmd <
PVMF_SM_FSP_HTTP_SESSION_CONTROLLER_COMMAND_START))
{
HandleMediaLayerCommandCompleted(aResponse, aPerformErrHandling);
}
else
{
OSCL_ASSERT(false);
}
}
void PVMFSMRTSPUnicastNode::HandleSocketNodeCommandCompleted(const PVMFCmdResp& aResponse, bool& aPerformErrHandling)
{
aPerformErrHandling = false;
PVMFSMFSPChildNodeContainer* iSocketNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_SOCKET_NODE);
if (iSocketNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return;
}
PVMFSMFSPCommandContext *cmdContextData =
OSCL_REINTERPRET_CAST(PVMFSMFSPCommandContext*, aResponse.GetContext());
cmdContextData->oFree = true;
PVMF_SM_RTSP_LOGINFO((0, "PVMFSMRTSPUnicastNode::HandleSocketNodeCommandCompleted In - cmd [%d] iSocketNodeContainer->iNodeCmdState [%d] iInterfaceState[%d]", cmdContextData->cmd, iSocketNodeContainer->iNodeCmdState, iInterfaceState));
//RTSPUNICAST plugin uses sync version of QueryInterface to get xtension interface of its various child nodes
//Also RTSPUNICAST plugin doesn t call QueryUUID on child node.
//So, command completion of async version of QueryUUID and QueryInterface from child node not expected.
OSCL_ASSERT(cmdContextData->cmd != PVMF_SM_FSP_SOCKET_NODE_QUERY_UUID);
OSCL_ASSERT(cmdContextData->cmd != PVMF_SM_FSP_SOCKET_NODE_QUERY_INTERFACE);
if (iSocketNodeContainer->iNodeCmdState == PVMFSMFSP_NODE_CMD_PENDING)
{
if (cmdContextData->cmd == PVMF_SM_FSP_SOCKET_NODE_REQUEST_PORT)
{
//This is last of the request ports
OSCL_ASSERT(iSocketNodeContainer->iNumRequestPortsPending > 0);
if (--iSocketNodeContainer->iNumRequestPortsPending == 0)
{
iSocketNodeContainer->iNodeCmdState = PVMFSMFSP_NODE_CMD_IDLE;
}
}
else
{
iSocketNodeContainer->iNodeCmdState = PVMFSMFSP_NODE_CMD_IDLE;
}
}
else if (iSocketNodeContainer->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))
{
iSocketNodeContainer->iNodeCmdState = PVMFSMFSP_NODE_CMD_IDLE;
}
else
{
PVMF_SM_RTSP_LOGINFO((0, "PVMFSMRTSPUnicastNode::HandleSocketNodeCommandCompleted 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 (iSocketNodeContainer->iNodeCmdState == PVMFSMFSP_NODE_CMD_IDLE)
{
PVMF_SM_RTSP_LOGINFO((0, "PVMFSMRTSPUnicastNode::HandleSocketNodeCommandCompleted Nodecontainer state IDLE 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_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::HandleSocketNodeCommandCompleted - Command failed - context=0x%x, status=0x%x", aResponse.GetContext(), aResponse.GetCmdStatus()));
if (IsBusy())
{
Cancel();
RunIfNotReady();
}
return;
}
switch (cmdContextData->cmd)
{
case PVMF_SM_FSP_SOCKET_NODE_INIT:
{
CompleteInit();
}
break;
case PVMF_SM_FSP_SOCKET_NODE_PREPARE:
{
CompletePrepare();
}
break;
case PVMF_SM_FSP_SOCKET_NODE_START:
{
CompleteStart();
}
break;
case PVMF_SM_FSP_SOCKET_NODE_STOP:
{
CompleteStop();
}
break;
case PVMF_SM_FSP_SOCKET_NODE_FLUSH:
{
CompleteFlush();
}
break;
case PVMF_SM_FSP_SOCKET_NODE_PAUSE:
{
CompletePause();
}
break;
case PVMF_SM_FSP_SOCKET_NODE_RESET:
{
CompleteReset();
}
break;
case PVMF_SM_FSP_SOCKET_NODE_REQUEST_PORT:
{
PVMFPortInterface* port =
(PVMFPortInterface*)aResponse.GetEventData();
/*
* Save the port in TrackInfo
*/
PVMFRTSPTrackInfo* trackInfo =
FindTrackInfo(cmdContextData->portContext.trackID);
OSCL_ASSERT(trackInfo);
if (!trackInfo)
return;
if (cmdContextData->portContext.portTag ==
PVMF_SOCKET_NODE_PORT_TYPE_SOURCE)
{
if (trackInfo)
trackInfo->iNetworkNodePort = port;
iSocketNodeContainer->iOutputPorts.push_back(port);
}
else if (cmdContextData->portContext.portTag ==
PVMF_SOCKET_NODE_PORT_TYPE_SINK)
{
if (trackInfo)
trackInfo->iNetworkNodeRTCPPort = port;
iSocketNodeContainer->iInputPorts.push_back(port);
}
CompleteGraphConstruct();
}
break;
case PVMF_SM_FSP_SOCKET_NODE_CANCEL_ALL_COMMANDS:
{
CompleteChildNodesCmdCancellation();
}
break;
default:
break;
}
return;
}
void PVMFSMRTSPUnicastNode::HandleRTSPSessionControllerCommandCompleted(const PVMFCmdResp& aResponse,
bool& aPerformErrHandling)
{
aPerformErrHandling = false;
PVMFSMFSPChildNodeContainer* iSessionControllerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
if (iSessionControllerNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return;
}
PVMFSMFSPCommandContext *cmdContextData =
OSCL_REINTERPRET_CAST(PVMFSMFSPCommandContext*, aResponse.GetContext());
cmdContextData->oFree = true;
PVMF_SM_RTSP_LOGINFO((0, "PVMFSMRTSPUnicastNode::HandleRTSPSessionControllerCommandCompleted In - cmd [%d] iSessionControllerNodeContainer->iNodeCmdState [%d] iInterfaceState[%d]", cmdContextData->cmd, iSessionControllerNodeContainer->iNodeCmdState, iInterfaceState));
//RTSPPLUSUNICAST plugin uses sync version of QueryInterface to get xtension interface of its various child nodes
//Also RTSPPLUSUNICAST plugin doesn t call QueryUUID on child node.
//So, command completion of async version of QueryUUID and QueryInterface from child node not expected.
OSCL_ASSERT(cmdContextData->cmd != PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_QUERY_UUID);
OSCL_ASSERT(cmdContextData->cmd != PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_QUERY_INTERFACE);
if (iSessionControllerNodeContainer->iNodeCmdState == PVMFSMFSP_NODE_CMD_PENDING)
{
if (cmdContextData->cmd == PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_REQUEST_PORT)
{
//This is last of the request ports
OSCL_ASSERT(iSessionControllerNodeContainer->iNumRequestPortsPending > 0);
if (--iSessionControllerNodeContainer->iNumRequestPortsPending == 0)
{
iSessionControllerNodeContainer->iNodeCmdState = PVMFSMFSP_NODE_CMD_IDLE;
}
}
else
{
iSessionControllerNodeContainer->iNodeCmdState = PVMFSMFSP_NODE_CMD_IDLE;
}
}
else if (iSessionControllerNodeContainer->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))
{
iSessionControllerNodeContainer->iNodeCmdState = PVMFSMFSP_NODE_CMD_IDLE;
}
else
{
PVMF_SM_RTSP_LOGINFO((0, "PVMFSMRTSPUnicastNode::HandleRTSPSessionControllerCommandCompleted 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 (iSessionControllerNodeContainer->iNodeCmdState == PVMFSMFSP_NODE_CMD_IDLE)
{
PVMF_SM_RTSP_LOGINFO((0, "PVMFSMRTSPUnicastNode::HandleRTSPSessionControllerCommandCompleted 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;
}
if ((cmdContextData->cmd == PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_PAUSE) ||
(cmdContextData->cmd == PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_STOP))
{
/*
* Check if it is a pause/stop failure - suppress pause/stop failures if they
* happen after a session is complete
*/
PVMFSMFSPChildNodeContainer* iJitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (iJitterBufferNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return;
}
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)
(iJitterBufferNodeContainer->iExtensions[0]);
bool oSessionExpired = false;
jbExtIntf->HasSessionDurationExpired(oSessionExpired);
if (oSessionExpired == true)
{
aPerformErrHandling = false;
}
}
/* if a failure has been overridden just fall thru */
if (aPerformErrHandling == true)
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::HandleRTSPSessionControllerCommandCompleted - Command failed - context=0x%x, status=0x%x", aResponse.GetContext(), aResponse.GetCmdStatus()));
if (IsBusy())
{
Cancel();
RunIfNotReady();
}
return;
}
}
switch (cmdContextData->cmd)
{
case PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_INIT:
CompleteInit();
break;
case PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_PREPARE:
{
/* Complete set up of feedback channels */
CompleteFeedBackPortsSetup();
/*
* Send start complete params to child nodes
* viz. SSRC etc
*/
SendSessionControlPrepareCompleteParams();
CompletePrepare();
}
break;
case PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_START:
{
/*
* Send start complete params to child nodes
* viz. actual play range, rtp info params etc
*/
SendSessionControlStartCompleteParams();
/* We should resume output of JB has it been paused */
for (uint32 i = 0; i < iFSPChildNodeContainerVec.size(); i++)
{
if (iFSPChildNodeContainerVec[i].iNodeTag == PVMF_SM_FSP_JITTER_BUFFER_NODE &&
iFSPChildNodeContainerVec[i].iNodeCmdState == PVMFSMFSP_NODE_CMD_IDLE)
{
PVMFSMFSPChildNodeContainer* iJitterBufferNodeContainer = getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (iJitterBufferNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return;
}
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)(iJitterBufferNodeContainer->iExtensions[0]);
jbExtIntf->StartOutputPorts();
}
}
CompleteStart();
}
break;
case PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_STOP:
{
CompleteStop();
}
break;
case PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_FLUSH:
CompleteFlush();
break;
case PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_PAUSE:
{
CompletePause();
}
break;
case PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_RESET:
CompleteReset();
break;
case PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_REQUEST_PORT:
{
/*
* Save the port in TrackInfo
*/
PVMFRTSPTrackInfo* trackInfo =
FindTrackInfo(cmdContextData->portContext.trackID);
OSCL_ASSERT(trackInfo);
PVMFPortInterface* port =
(PVMFPortInterface*)aResponse.GetEventData();
if (cmdContextData->portContext.portTag ==
PVMF_RTSP_NODE_PORT_TYPE_OUTPUT)
{
if (trackInfo)
trackInfo->iSessionControllerOutputPort = port;
iSessionControllerNodeContainer->iOutputPorts.push_back(port);
}
else if (cmdContextData->portContext.portTag ==
PVMF_RTSP_NODE_PORT_TYPE_INPUT)
{
iSessionControllerNodeContainer->iInputPorts.push_back(port);
}
else if (cmdContextData->portContext.portTag ==
PVMF_RTSP_NODE_PORT_TYPE_INPUT_OUTPUT)
{
if (trackInfo)
trackInfo->iSessionControllerFeedbackPort = port;
iSessionControllerNodeContainer->iFeedBackPorts.push_back(port);
}
CompleteGraphConstruct();
}
break;
case PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_CANCEL_ALL_COMMANDS:
{
CompleteChildNodesCmdCancellation();
}
break;
default:
break;
}
return;
}
void PVMFSMRTSPUnicastNode::HandleJitterBufferCommandCompleted(const PVMFCmdResp& aResponse, bool& aPerformErrHandling)
{
aPerformErrHandling = false;
PVMFSMFSPChildNodeContainer* iJitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (iJitterBufferNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return;
}
PVMFSMFSPCommandContext *cmdContextData =
OSCL_REINTERPRET_CAST(PVMFSMFSPCommandContext*, aResponse.GetContext());
cmdContextData->oFree = true;
PVMF_SM_RTSP_LOGINFO((0, "PVMFSMRTSPUnicastNode::HandleJitterBufferCommandCompleted In - cmd [%d] iJitterBufferNodeContainer->iNodeCmdState [%d] iInterfaceState[%d]", cmdContextData->cmd, iJitterBufferNodeContainer->iNodeCmdState, iInterfaceState));
OSCL_ASSERT(cmdContextData->cmd != PVMF_SM_FSP_JITTER_BUFFER_QUERY_UUID);
OSCL_ASSERT(cmdContextData->cmd != PVMF_SM_FSP_JITTER_BUFFER_QUERY_INTERFACE);
if (iJitterBufferNodeContainer->iNodeCmdState == PVMFSMFSP_NODE_CMD_PENDING)
{
if (cmdContextData->cmd == PVMF_SM_FSP_JITTER_BUFFER_REQUEST_PORT)
{
//This is last of the request ports
OSCL_ASSERT(iJitterBufferNodeContainer->iNumRequestPortsPending > 0);
if (--iJitterBufferNodeContainer->iNumRequestPortsPending == 0)
{
iJitterBufferNodeContainer->iNodeCmdState = PVMFSMFSP_NODE_CMD_IDLE;
}
}
else
{
iJitterBufferNodeContainer->iNodeCmdState = PVMFSMFSP_NODE_CMD_IDLE;
}
}
else if (iJitterBufferNodeContainer->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))
{
iJitterBufferNodeContainer->iNodeCmdState = PVMFSMFSP_NODE_CMD_IDLE;
}
else
{
PVMF_SM_RTSP_LOGINFO((0, "PVMFSMRTSPUnicastNode::HandleJitterBufferCommandCompleted 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 (iJitterBufferNodeContainer->iNodeCmdState == PVMFSMFSP_NODE_CMD_IDLE)
{
PVMF_SM_RTSP_LOGINFO((0, "PVMFSMRTSPUnicastNode::HandleJitterBufferCommandCompleted cmd 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_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::HandleJitterBufferCommandCompleted - Command failed - context=0x%x, status=0x%x", aResponse.GetContext(), aResponse.GetCmdStatus()));
if (IsBusy())
{
Cancel();
RunIfNotReady();
}
return;
}
switch (cmdContextData->cmd)
{
case PVMF_SM_FSP_JITTER_BUFFER_INIT:
{
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)
(iJitterBufferNodeContainer->iExtensions[0]);
if (jbExtIntf == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return;
}
bool disableFireWallPackets = true;
if ((iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_RTSP_URL) ||
(iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_SDP_FILE))
{
//do not disable fw pkts run time
//apps can still disable it compile time or using KVP
//for UDP sessions ofcourse
disableFireWallPackets = false;
}
CompleteInit();
}
break;
case PVMF_SM_FSP_JITTER_BUFFER_PREPARE:
CompletePrepare();
break;
case PVMF_SM_FSP_JITTER_BUFFER_START:
{
/* If start has been cancelled wait for cancel success */
if (aResponse.GetCmdStatus() != PVMFErrCancelled)
{
/* We need to pause output of JB before RTSP response is received */
for (uint32 i = 0; i < iFSPChildNodeContainerVec.size(); i++)
{
if (iFSPChildNodeContainerVec[i].iNodeTag == PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE &&
iFSPChildNodeContainerVec[i].iNodeCmdState == PVMFSMFSP_NODE_CMD_PENDING)
{
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)(iJitterBufferNodeContainer->iExtensions[0]);
jbExtIntf->StopOutputPorts();
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::HandleJitterBufferCommandCompleted - StopOutputPorts()"));
}
}
CompleteStart();
}
}
break;
case PVMF_SM_FSP_JITTER_BUFFER_STOP:
{
CompleteStop();
}
break;
case PVMF_SM_FSP_JITTER_BUFFER_FLUSH:
CompleteFlush();
break;
case PVMF_SM_FSP_JITTER_BUFFER_PAUSE:
CompletePause();
break;
case PVMF_SM_FSP_JITTER_BUFFER_RESET:
CompleteReset();
break;
case PVMF_SM_FSP_JITTER_BUFFER_REQUEST_PORT:
{
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)
(iJitterBufferNodeContainer->iExtensions[0]);
if (jbExtIntf == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return;
}
/*
* Save the port in TrackInfo
*/
PVMFRTSPTrackInfo* trackInfo =
FindTrackInfo(cmdContextData->portContext.trackID);
OSCL_ASSERT(trackInfo);
PVMFPortInterface* port =
(PVMFPortInterface*)aResponse.GetEventData();
uint32 bitrate = 0;
if (cmdContextData->portContext.portTag ==
PVMF_JITTER_BUFFER_PORT_TYPE_INPUT)
{
if (trackInfo)
{
bitrate = trackInfo->bitRate;
trackInfo->iJitterBufferInputPort = port;
}
iJitterBufferNodeContainer->iInputPorts.push_back(port);
}
else if (cmdContextData->portContext.portTag ==
PVMF_JITTER_BUFFER_PORT_TYPE_OUTPUT)
{
if (trackInfo)
trackInfo->iJitterBufferOutputPort = port;
iJitterBufferNodeContainer->iOutputPorts.push_back(port);
}
else if (cmdContextData->portContext.portTag ==
PVMF_JITTER_BUFFER_PORT_TYPE_FEEDBACK)
{
iJitterBufferNodeContainer->iFeedBackPorts.push_back(port);
if (trackInfo)
{
trackInfo->iJitterBufferRTCPPort = port;
if (trackInfo->iRTCPBwSpecified)
{
jbExtIntf->setPortRTCPParams(port, iTrackInfoVec.size(), trackInfo->iRR, trackInfo->iRS);
}
}
}
jbExtIntf->setPortParams(port,
trackInfo->trackTimeScale,
bitrate,
trackInfo->iTrackConfig,
trackInfo->iRateAdaptation,
trackInfo->iRateAdaptationFeedBackFrequency);
CompleteGraphConstruct();
}
break;
case PVMF_SM_FSP_JITTER_BUFFER_CANCEL_ALL_COMMANDS:
{
CompleteChildNodesCmdCancellation();
}
break;
default:
break;
}
return;
}
void PVMFSMRTSPUnicastNode::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_RTSP_LOGINFO((0, "PVMFSMRTSPUnicastNode::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_RTSP_LOGINFO((0, "PVMFSMRTSPUnicastNode::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_RTSP_LOGINFO((0, "PVMFSMRTSPUnicastNode::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_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::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
*/
PVMFRTSPTrackInfo* trackInfo =
FindTrackInfo(cmdContextData->portContext.trackID);
PVMFPortInterface* port =
(PVMFPortInterface*)aResponse.GetEventData();
OSCL_ASSERT(trackInfo && port);
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;
const 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;
}
void PVMFSMRTSPUnicastNode::CompleteInit()
{
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::CompleteInit - In"));
if (CheckChildrenNodesInit())
{
if (!iCurrentCommand.empty() && iCancelCommand.empty())
{
PVMFSMFSPBaseNodeCommand& aCmd = iCurrentCommand.front();
if (aCmd.iCmd == PVMF_SMFSP_NODE_INIT)
{
PVMFStatus status = PVMFSuccess;
if ((iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_RTSP_URL))
{
status = ProcessSDP();
}
if (status == PVMFSuccess)
{
status = InitMetaData();
if (status == PVMFSuccess)
{
if (iSessionSourceInfo->iDRMProtected == true)
{
PopulateDRMInfo();
//This clip is protected clip
if (iCPM)
{
/*
* Go thru CPM commands before parsing the file in case
* of a new source file.
* - Init CPM
* - Open Session
* - Register Content
* - Get Content Type
* - Approve Usage
* In case the source file has already been parsed skip to
* - Approve Usage
*/
InitCPM();
return;
}
else
{
PVMF_SM_RTSP_LOG_COMMAND_SEQ((0, "PVMFSMRTSPUnicastNode::Init() - CmdComplete - PVMFErrArgument"));
CommandComplete(iCurrentCommand,
iCurrentCommand.front(),
PVMFErrArgument,
NULL, NULL, NULL);
return;
}
}
}
else
{
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::CompleteInit - InitMetaData fail"));
}
PVMF_SM_RTSP_LOG_COMMAND_SEQ((0, "PVMFSMRTSPUnicastNode::Init() - CmdComplete - PVMFSuccess"));
//Init is completed at unprotected clip
SetState(EPVMFNodeInitialized);
PVMF_SM_RTSP_LOGINFO((0, "PVMFSMRTSPUnicastNode::CompleteInit Success"));
CommandComplete(iCurrentCommand, aCmd, PVMFSuccess);
}
else
{
PVMF_SM_RTSP_LOG_COMMAND_SEQ((0, "PVMFSMRTSPUnicastNode::Init() - Cmd Failed - PVMFStreamingManagerNodeErrorParseSDPFailed"));
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::CompleteInit Failure"));
PVUuid eventuuid = PVMFStreamingManagerNodeEventTypeUUID;
int32 errcode = PVMFStreamingManagerNodeErrorParseSDPFailed;
CommandComplete(iCurrentCommand, aCmd, status, NULL, &eventuuid, &errcode);
}
}
}
}
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFPVMFSMRTSPUnicastNode::CompleteInit - Out"));
return;
}
bool PVMFSMRTSPUnicastNode::CheckChildrenNodesInit()
{
for (uint32 i = 0; i < iFSPChildNodeContainerVec.size(); i++)
{
if (iFSPChildNodeContainerVec[i].iNodeCmdState != PVMFSMFSP_NODE_CMD_IDLE)
{
return false;
}
}
return true;
}
PVMFStatus PVMFSMRTSPUnicastNode::InitMetaData()
{
// Clear out the existing key list
iAvailableMetadataKeys.clear();
iCPMMetadataKeys.clear();
// Get the SDP info
SDPInfo* sdpInfo = iSdpInfo.GetRep();
if (sdpInfo == NULL)
{
return PVMFErrInvalidState;
}
// Get Asset Info
sessionDescription* sessionInfo = sdpInfo->getSessionInfo();
if (sessionInfo != NULL)
{
iMetaDataInfo->iRandomAccessDenied = sessionInfo->getRandomAccessDenied();
AssetInfoType assetInfo = sessionInfo->getAssetInfo();
iMetaDataInfo->iTitlePresent = assetInfo.oTitlePresent;
iMetaDataInfo->iDescriptionPresent = assetInfo.oDescriptionPresent;
iMetaDataInfo->iCopyRightPresent = assetInfo.oCopyRightPresent;
iMetaDataInfo->iPerformerPresent = assetInfo.oPerformerPresent;
iMetaDataInfo->iAuthorPresent = assetInfo.oAuthorPresent;
iMetaDataInfo->iGenrePresent = assetInfo.oGenrePresent;
iMetaDataInfo->iRatingPresent = assetInfo.oRatingPresent;
iMetaDataInfo->iClassificationPresent = assetInfo.oClassificationPresent;
iMetaDataInfo->iKeyWordsPresent = assetInfo.oKeyWordsPresent;
iMetaDataInfo->iLocationPresent = assetInfo.oLocationPresent;
iMetaDataInfo->iAlbumPresent = assetInfo.oAlbumPresent;
if (iMetaDataInfo->iTitlePresent)
{
iMetaDataInfo->iTitle = assetInfo.Box[AssetInfoType::TITLE];
}
if (iMetaDataInfo->iDescriptionPresent)
{
iMetaDataInfo->iDescription = assetInfo.Box[AssetInfoType::DESCRIPTION];
}
if (iMetaDataInfo->iCopyRightPresent)
{
iMetaDataInfo->iCopyright = assetInfo.Box[AssetInfoType::COPYRIGHT];
}
if (iMetaDataInfo->iPerformerPresent)
{
iMetaDataInfo->iPerformer = assetInfo.Box[AssetInfoType::PERFORMER];
}
if (iMetaDataInfo->iAuthorPresent)
{
iMetaDataInfo->iAuthor = assetInfo.Box[AssetInfoType::AUTHOR];
}
if (iMetaDataInfo->iRatingPresent)
{
iMetaDataInfo->iRating = assetInfo.Box[AssetInfoType::RATING];
}
if (iMetaDataInfo->iClassificationPresent)
{
iMetaDataInfo->iClassification = assetInfo.Box[AssetInfoType::CLASSIFICATION];
}
if (iMetaDataInfo->iKeyWordsPresent)
{
iMetaDataInfo->iNumKeyWords = assetInfo.iNumKeyWords;
for (uint32 i = 0; i < iMetaDataInfo->iNumKeyWords; i++)
{
iMetaDataInfo->iKeyWords[i] = assetInfo.KeyWords[i];
}
}
if (iMetaDataInfo->iLocationPresent)
{
iMetaDataInfo->iLocationStruct = assetInfo.iLocationStruct;
}
if (iMetaDataInfo->iAlbumPresent)
{
iMetaDataInfo->iAlbum = assetInfo.Box[AssetInfoType::ALBUM];
}
if (assetInfo.iRecordingYear)
{
iMetaDataInfo->iYear = assetInfo.iRecordingYear;
}
RtspRangeType *sessionRange = OSCL_CONST_CAST(RtspRangeType*, (sessionInfo->getRange()));
if (sessionRange->end_is_set == true)
{
iMetaDataInfo->iSessionDurationAvailable = true;
int32 sessionStartTime = 0, sessionStopTime = 0;
sessionRange->convertToMilliSec(sessionStartTime, sessionStopTime);
uint32 duration = 0;
if (sessionStopTime > sessionStartTime && sessionStartTime >= 0)
{
duration = (uint32)(sessionStopTime - sessionStartTime);
}
Oscl_Int64_Utils::set_uint64(iMetaDataInfo->iSessionDuration, 0, duration);
iMetaDataInfo->iSessionDurationTimeScale = 1000;
}
iPauseDenied = iMetaDataInfo->iSessionDurationAvailable ? false : true;
}
iMetaDataInfo->iNumTracks = sdpInfo->getNumMediaObjects();
for (uint32 i = 0; i < iMetaDataInfo->iNumTracks; i++)
{
Oscl_Vector<mediaInfo*, SDPParserAlloc> mediaInfoVec = sdpInfo->getMediaInfo(i);
for (uint32 j = 0; j < mediaInfoVec.size(); ++j)
{
mediaInfo* mInfo = mediaInfoVec[j];
if (mInfo != NULL)
{
PVMFSMTrackMetaDataInfo trackMetaDataInfo;
trackMetaDataInfo.iTrackID = mInfo->getMediaInfoID();
const char* mimeType = mInfo->getMIMEType();
OSCL_StackString<32> realAudio(_STRLIT_CHAR("realaudio"));
OSCL_StackString<32> realVideo(_STRLIT_CHAR("realvideo"));
OSCL_StackString<32> h263(_STRLIT_CHAR("H263"));
if (oscl_strstr(mimeType, realAudio.get_cstr()) != NULL)
{
trackMetaDataInfo.iMimeType = PVMF_MIME_REAL_AUDIO;
}
else if (oscl_strstr(mimeType, realVideo.get_cstr()) != NULL)
{
trackMetaDataInfo.iMimeType = PVMF_MIME_REAL_VIDEO;
}
else
{
trackMetaDataInfo.iMimeType += mimeType;
}
Oscl_Vector<PayloadSpecificInfoTypeBase*, SDPParserAlloc> payloadVector;
payloadVector = mInfo->getPayloadSpecificInfoVector();
if (payloadVector.size() != 0)
{
/*
* There can be multiple payloads per media segment.
* We only support one for now, so
* use just the first payload
*/
PayloadSpecificInfoTypeBase* payloadInfo = payloadVector[0];
if (oscl_strstr(mimeType, h263.get_cstr()) != NULL)
{
H263PayloadSpecificInfoType* h263PayloadInfo =
OSCL_STATIC_CAST(H263PayloadSpecificInfoType*, payloadInfo);
trackMetaDataInfo.iTrackWidth = h263PayloadInfo->getFrameWidth();
trackMetaDataInfo.iTrackHeight = h263PayloadInfo->getFrameHeight();
}
int32 configSize = payloadInfo->configSize;
OsclAny* config = payloadInfo->configHeader.GetRep();
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 PVMFErrResource;
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);
trackMetaDataInfo.iCodecSpecificInfo = tmpRefcntMemFrag;
}
}
trackMetaDataInfo.iTrackBitRate = (uint32)(mInfo->getBitrate());
RtspRangeType *mediaRange = mInfo->getRtspRange();
if (mediaRange->end_is_set == true)
{
int32 mediaStartTime = 0, mediaStopTime = 0;
mediaRange->convertToMilliSec(mediaStartTime, mediaStopTime);
uint32 trackduration = 0;
if (mediaStopTime > mediaStartTime && mediaStartTime >= 0)
{
trackduration = (uint32)(mediaStopTime - mediaStartTime);
}
uint64 trackduration64 = 0;
Oscl_Int64_Utils::set_uint64(trackduration64, 0, trackduration);
trackMetaDataInfo.iTrackDuration = trackduration64;
trackMetaDataInfo.iTrackDurationTimeScale = 1000;
trackMetaDataInfo.iTrackDurationAvailable = true;
}
else
{
trackMetaDataInfo.iTrackDurationAvailable = false;
}
iMetaDataInfo->iTrackMetaDataInfoVec.push_back(trackMetaDataInfo);
}
}
}
PVMFStatus status = PopulateAvailableMetadataKeys();
if (PVMFSuccess != status)
{
return status;
}
iMetaDataInfo->iMetadataAvailable = true;
return PVMFSuccess;
}
PVMFStatus PVMFSMRTSPUnicastNode::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 PVMFSMRTSPUnicastNode::CompletePrepare()
{
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::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_RTSP_LOG_COMMAND_SEQ((0, "PVMFSMRTSPUnicastNode::Prepare() - CmdComplete - PVMFSuccess"));
CommandComplete(iCurrentCommand, aCmd, PVMFSuccess);
}
}
}
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFPVMFSMRTSPUnicastNode::CompletePrepare - Out"));
return;
}
bool PVMFSMRTSPUnicastNode::CheckChildrenNodesPrepare()
{
for (uint32 i = 0; i < iFSPChildNodeContainerVec.size(); i++)
{
if (iFSPChildNodeContainerVec[i].iNodeCmdState != PVMFSMFSP_NODE_CMD_IDLE)
{
return false;
}
}
return true;
}
void PVMFSMRTSPUnicastNode::CompleteStart()
{
int32 localMode = 0;
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::CompleteStart - 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_RTSP_LOG_COMMAND_SEQ((0, "PVMFSMRTSPUnicastNode::SetDataSourcePosition() - CmdComplete - PMVFSuccess"));
iRepositioning = false;
iPlayListRepositioning = false;
if ((localMode == 0) || (localMode == -1))
{
GetActualMediaTSAfterSeek();
}
iPVMFDataSourcePositionParamsPtr = NULL;
}
if ((localMode == 0) || (localMode == -1))
{
SetState(EPVMFNodeStarted);
if (IsAdded())
{
/* wakeup the AO */
RunIfNotReady();
}
PVMF_SM_RTSP_LOG_COMMAND_SEQ((0, "PVMFSMRTSPUnicastNode::Start() - CmdComplete - PMVFSuccess"));
}
CommandComplete(iCurrentCommand, aCmd, PVMFSuccess);
}
}
}
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::CompleteStart - Out"));
return;
}
bool PVMFSMRTSPUnicastNode::CheckChildrenNodesStart()
{
for (uint32 i = 0; i < iFSPChildNodeContainerVec.size(); i++)
{
if (iFSPChildNodeContainerVec[i].iNodeCmdState == PVMFSMFSP_NODE_CMD_PENDING)
{
return false;
}
}
return true;
}
void PVMFSMRTSPUnicastNode::GetActualMediaTSAfterSeek()
{
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;
}
iActualMediaDataTS = jbExtIntf->getActualMediaDataTSAfterSeek();
if (iActualMediaDataTSPtr != NULL)
{
*iActualMediaDataTSPtr = iActualMediaDataTS;
PVMF_SM_RTSP_LOG_COMMAND_REPOS((0, "PVMFPVMFSMRTSPUnicastNode::GetActualMediaTSAfterSeek - TargetNPT = %d, ActualNPT=%d, ActualMediaDataTS=%d",
iRepositionRequestedStartNPTInMS, *iActualRepositionStartNPTInMSPtr, *iActualMediaDataTSPtr));
}
}
void PVMFSMRTSPUnicastNode::CompleteStop()
{
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::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_RTSP_LOG_COMMAND_SEQ((0, "PVMFSMRTSPUnicastNode::Stop() - CmdComplete - PVMFSuccess"));
CommandComplete(iCurrentCommand, aCmd, PVMFSuccess);
}
}
}
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::CompleteStop - Out"));
return;
}
void PVMFSMRTSPUnicastNode::ResetStopCompleteParams()
{
iPlaylistPlayInProgress = false;
iRepositionRequestedStartNPTInMS = 0;
}
void PVMFSMRTSPUnicastNode::CompletePause()
{
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFPVMFSMRTSPUnicastNode::CompletePause - In"));
if (CheckChildrenNodesPause())
{
SetState(EPVMFNodePaused);
if (iRepositioning)
{
OSCL_ASSERT((iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_RTSP_URL) ||
(iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_SDP_FILE));
/*
* Pause request generated by a reposition command
* complete. Issue a start.
*/
if (iPVMFDataSourcePositionParamsPtr == NULL)
{
DoRepositioningStart3GPPStreaming();
}
}
else
{
if (!iCurrentCommand.empty() && iCancelCommand.empty())
{
PVMFSMFSPBaseNodeCommand& aCmd = iCurrentCommand.front();
PVMF_SM_RTSP_LOG_COMMAND_SEQ((0, "PVMFPVMFSMRTSPUnicastNode::Pause() - CmdComplete - PVMFSuccess"));
CommandComplete(iCurrentCommand, aCmd, PVMFSuccess);
}
}
}
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFPVMFSMRTSPUnicastNode::CompletePause - Out"));
return;
}
bool PVMFSMRTSPUnicastNode::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;
}
/*
* Called by the call back routine whenever a "RequestPort" call
* completes successfully.
*/
void PVMFSMRTSPUnicastNode::CompleteGraphConstruct()
{
iTotalNumRequestPortsComplete++;
/*
* Once all port requests are complete, connect the graph
*/
if (iTotalNumRequestPortsComplete == iNumRequestPortsPending)
{
PVMFSMFSPBaseNodeCommand& aCmd = iCurrentCommand.front();
if (!SendSessionSourceInfoToSessionController())
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode:CompleteGraphConstruct - SendSessionSourceInfoToSessionController Failed"));
InternalCommandComplete(iCurrentCommand, aCmd, PVMFFailure);
}
else
{
iGraphConstructComplete = true;
PVMFSMFSPChildNodeContainer* socketNodeContainer = getChildNodeContainer(PVMF_SM_FSP_SOCKET_NODE);
PVMFSMFSPChildNodeContainer* jitterBufferNodeContainer = getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if ((socketNodeContainer == NULL) || (jitterBufferNodeContainer == NULL))
{
OSCL_ASSERT(false);
return;
}
PVMFJitterBufferExtensionInterface* jbExtIntf = OSCL_STATIC_CAST(PVMFJitterBufferExtensionInterface*, jitterBufferNodeContainer->iExtensions[0]);
PVMFSocketNodeExtensionInterface* socketExtnIntf = OSCL_STATIC_CAST(PVMFSocketNodeExtensionInterface*, socketNodeContainer->iExtensions[0]);
OSCL_ASSERT(jbExtIntf && socketExtnIntf);
if (!jbExtIntf || !socketExtnIntf)
return;
//For RTSP based streamings, we want the mempools to get resized
//For input port, get the value from Jitter Buffer Node
uint32 resizeSizeInputPort = 0;
uint32 numResizeInputPort = 0;
jbExtIntf->GetSharedBufferResizeParams(numResizeInputPort, resizeSizeInputPort);
//For feedback port we use the const initialized to a configurable macro
const uint32 resizeSizeFeedbackPort = DEFAULT_MAX_SOCKETMEMPOOL_RESIZELEN_FEEDBACK_PORT;
const uint32 numResizeFeedbackPort = 1;
//For every track
//Decide the size of the shared buffer to be allocated at socket node for receiving
//RTP packets [Input port]
//Receiving the response of RTCP reports send by JB [Feedback Port]
for (uint32 i = 0; i < iTrackInfoVec.size(); i++)
{
PVMFRTSPTrackInfo trackInfo = iTrackInfoVec[i];
uint32 bufferSzForRTPPackets = GetJitterBufferMemPoolSize(PVMF_JITTER_BUFFER_PORT_TYPE_INPUT, iTrackInfoVec[i]);
uint32 bufferSzForRTCPResponse = GetJitterBufferMemPoolSize(PVMF_JITTER_BUFFER_PORT_TYPE_FEEDBACK, iTrackInfoVec[i]);
//Set with the socket node
OsclMemPoolResizableAllocator* socketAlloc = socketExtnIntf->CreateSharedBuffer(trackInfo.iNetworkNodePort, bufferSzForRTPPackets, DEFAULT_NUM_MEDIA_MSGS_IN_JITTER_BUFFER, resizeSizeInputPort, numResizeInputPort);
jbExtIntf->SetJitterBufferChunkAllocator(socketAlloc, trackInfo.iJitterBufferInputPort);
const uint32 numMemChunksForRTCPMemPool = bufferSzForRTCPResponse / MAX_SOCKET_BUFFER_SIZE;
socketExtnIntf->CreateSharedBuffer(trackInfo.iNetworkNodeRTCPPort, bufferSzForRTCPResponse, numMemChunksForRTCPMemPool, resizeSizeFeedbackPort, numResizeFeedbackPort);
}
InternalCommandComplete(iCurrentCommand, aCmd, PVMFSuccess);
}
}
}
/*
* Called when all port requests are complete, in order to send the
* UDP port information to RTSP
*/
bool PVMFSMRTSPUnicastNode::SendSessionSourceInfoToSessionController()
{
if (((iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_RTSP_URL) ||
(iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_SDP_FILE)))
{
PVMFSMFSPChildNodeContainer* iSocketNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_SOCKET_NODE);
if (iSocketNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return false;
}
PVMFSocketNode* socketNode =
(PVMFSocketNode*)(iSocketNodeContainer->iNode);
PVMFSMFSPChildNodeContainer* iSessionControllerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
if (iSessionControllerNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return false;
}
PVRTSPEngineNodeExtensionInterface* rtspExtIntf =
(PVRTSPEngineNodeExtensionInterface*)
(iSessionControllerNodeContainer->iExtensions[0]);
Oscl_Vector<StreamInfo, OsclMemAllocator> aSelectedStream;
for (uint32 i = 0; i < iTrackInfoVec.size(); i++)
{
PVMFRTSPTrackInfo trackInfo = iTrackInfoVec[i];
OsclNetworkAddress localAdd;
OsclNetworkAddress remoteAdd;
StreamInfo sInfo;
sInfo.iSDPStreamId = trackInfo.trackID;
if (trackInfo.iNetworkNodePort == NULL)
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode:SendSessionSourceInfoToSessionController - Invalid Port"));
return false;
}
socketNode->GetPortConfig(*trackInfo.iNetworkNodePort,
localAdd,
remoteAdd);
sInfo.iCliRTPPort = localAdd.port;
socketNode->GetPortConfig(*trackInfo.iNetworkNodeRTCPPort,
localAdd,
remoteAdd);
sInfo.iCliRTCPPort = localAdd.port;
/* Set Rate Adaptation parameters */
sInfo.b3gppAdaptationIsSet = false;
if (trackInfo.iRateAdaptation)
{
sInfo.b3gppAdaptationIsSet = true;
/* Compute buffer size based on bitrate and jitter duration*/
uint32 sizeInBytes = MIN_RTP_SOCKET_MEM_POOL_SIZE_IN_BYTES;
if (((int32)iJitterBufferDurationInMilliSeconds > 0) &&
((int32)trackInfo.bitRate > 0))
{
uint32 byteRate = trackInfo.bitRate / 8;
uint32 overhead = (byteRate * PVMF_JITTER_BUFFER_NODE_MEM_POOL_OVERHEAD) / 100;
uint32 durationInSec = iJitterBufferDurationInMilliSeconds / 1000;
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;
}
sInfo.iBufSize = sizeInBytes;
sInfo.iTargetTime = iJitterBufferDurationInMilliSeconds;
}
aSelectedStream.push_back(sInfo);
}
if (rtspExtIntf->SetSDPInfo(iSdpInfo,
aSelectedStream) != PVMFSuccess)
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode:SendSessionSourceInfoToSessionController - SetSDPInfo Failed"));
return false;
}
/* Set play range from SDP */
sessionDescription* sessionInfo = iSdpInfo->getSessionInfo();
RtspRangeType *rtspRange = OSCL_CONST_CAST(RtspRangeType*, (sessionInfo->getRange()));
rtspRange->convertToMilliSec((int32&)iSessionStartTime, (int32&)iSessionStopTime);
if (rtspRange->end_is_set == false)
{
iSessionStopTime = 0xFFFFFFFF;
iSessionStopTimeAvailable = false;
}
if ((rtspRange->format != RtspRangeType::INVALID_RANGE) &&
(rtspRange->start_is_set != false))
{
if (rtspExtIntf->SetRequestPlayRange(*rtspRange) != PVMFSuccess)
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode:SendRequestPlayRangeToSessionController - SetRequestPlayRange Failed"));
return false;
}
}
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
//Implemenation of pure virtuals from PVMFSMFSPBaseNode
///////////////////////////////////////////////////////////////////////////////
bool PVMFSMRTSPUnicastNode::IsFSPInternalCmd(PVMFCommandId aId)
{
OSCL_UNUSED_ARG(aId);
return false;
}
void PVMFSMRTSPUnicastNode::addRef()
{
}
void PVMFSMRTSPUnicastNode::removeRef()
{
}
void PVMFSMRTSPUnicastNode::setJitterBufferDurationInMilliSeconds(uint32 duration)
{
iJitterBufferDurationInMilliSeconds = duration;
}
PVMFStatus PVMFSMRTSPUnicastNode::DoRepositioningStart3GPPStreaming()
{
PVMFStatus status = SetRTSPPlaybackRange();
if (PVMFSuccess != status)
{
return status;
}
bool isSessionDurationExpired = false;
PVMFSMFSPChildNodeContainer* jitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (jitterBufferNodeContainer)
{
PVMFJitterBufferExtensionInterface* jbExtIntf =
OSCL_STATIC_CAST(PVMFJitterBufferExtensionInterface*, jitterBufferNodeContainer->iExtensions.front());
if (jbExtIntf)
jbExtIntf->HasSessionDurationExpired(isSessionDurationExpired);
}
PVMFSMFSPChildNodeContainer *sessionControllerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
if (sessionControllerNodeContainer)
{
PVRTSPEngineNodeExtensionInterface* rtspExtIntf =
OSCL_STATIC_CAST(PVRTSPEngineNodeExtensionInterface*, sessionControllerNodeContainer->iExtensions.front());
if (rtspExtIntf)
rtspExtIntf->UpdateSessionCompletionStatus(isSessionDurationExpired);
}
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_START_CMD_OFFSET;
internalCmd->parentCmd = PVMF_SMFSP_NODE_SET_DATASOURCE_POSITION;
OsclAny *cmdContextData = OSCL_REINTERPRET_CAST(OsclAny*, internalCmd);
PVMFNodeInterface* iNode = it->iNode;
iNode->Start(it->iSessionId, cmdContextData);
it->iNodeCmdState = PVMFSMFSP_NODE_CMD_PENDING;
}
else
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode:DoRepositioningStart:RequestNewInternalCmd - Failed"));
status = PVMFErrNoMemory;
}
}
return status;
}
PVMFStatus PVMFSMRTSPUnicastNode::SetRTSPPlaybackRange()
{
PVMFStatus status = PVMFSuccess;
/* Set Requested Play Range */
PVMFSMFSPChildNodeContainer* iSessionControllerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
if (iSessionControllerNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return false;
}
PVRTSPEngineNodeExtensionInterface* rtspExtIntf =
(PVRTSPEngineNodeExtensionInterface*)
(iSessionControllerNodeContainer->iExtensions[0]);
RtspRangeType rtspRange;
rtspRange.format = RtspRangeType::NPT_RANGE;
rtspRange.start_is_set = true;
rtspRange.npt_start.npt_format = NptTimeFormat::NPT_SEC;
rtspRange.npt_start.npt_sec.sec = iRepositionRequestedStartNPTInMS / 1000;
rtspRange.npt_start.npt_sec.milli_sec =
(iRepositionRequestedStartNPTInMS - ((iRepositionRequestedStartNPTInMS / 1000) * 1000));
rtspRange.end_is_set = true;
rtspRange.npt_end.npt_format = NptTimeFormat::NPT_SEC;
rtspRange.npt_end.npt_sec.sec = iSessionStopTime / 1000;
rtspRange.npt_end.npt_sec.milli_sec =
(iSessionStopTime - ((iSessionStopTime / 1000) * 1000));
status = rtspExtIntf->SetRequestPlayRange(rtspRange);
if (PVMFSuccess != status)
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:SetRTSPPlaybackRange() - SetRequestPlayRange Failed"));
}
return status;
}
bool PVMFSMRTSPUnicastNode::DoRepositioningPause3GPPStreaming()
{
PVMFSMFSPChildNodeContainerVector::iterator it;
bool isSessionDurationExpired = false;
PVMFSMFSPChildNodeContainer* jitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (jitterBufferNodeContainer)
{
PVMFJitterBufferExtensionInterface* jbExtIntf =
OSCL_STATIC_CAST(PVMFJitterBufferExtensionInterface*, jitterBufferNodeContainer->iExtensions.front());
if (jbExtIntf)
jbExtIntf->HasSessionDurationExpired(isSessionDurationExpired);
}
PVMFSMFSPChildNodeContainer *sessionControllerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
if (sessionControllerNodeContainer)
{
PVRTSPEngineNodeExtensionInterface* rtspExtIntf =
OSCL_STATIC_CAST(PVRTSPEngineNodeExtensionInterface*, sessionControllerNodeContainer->iExtensions.front());
if (rtspExtIntf)
rtspExtIntf->UpdateSessionCompletionStatus(isSessionDurationExpired);
}
for (it = iFSPChildNodeContainerVec.begin(); it != iFSPChildNodeContainerVec.end(); it++)
{
int32 nodeTag = it->iNodeTag;
//if pv playlist rp, don't pause
if ((nodeTag == PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE) ||
(nodeTag == PVMF_SM_FSP_MEDIA_LAYER_NODE) ||
(nodeTag == PVMF_SM_FSP_JITTER_BUFFER_NODE) ||
(nodeTag == PVMF_SM_FSP_SOCKET_NODE))
{
PVMFSMFSPCommandContext* internalCmd = RequestNewInternalCmd();
if (internalCmd != NULL)
{
internalCmd->cmd =
it->commandStartOffset +
PVMF_SM_FSP_NODE_INTERNAL_PAUSE_CMD_OFFSET;
internalCmd->parentCmd = PVMF_SMFSP_NODE_SET_DATASOURCE_POSITION;
OsclAny *cmdContextData = OSCL_REINTERPRET_CAST(OsclAny*, internalCmd);
PVMFNodeInterface* iNode = it->iNode;
iNode->Pause(it->iSessionId, cmdContextData);
it->iNodeCmdState = PVMFSMFSP_NODE_CMD_PENDING;
}
else
{
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode:DoRepositioningPause:RequestNewInternalCmd - Failed"));
return false;
}
}
}
return true;
}
bool PVMFSMRTSPUnicastNode::CompleteFeedBackPortsSetup()
{
PVMFSMFSPChildNodeContainer* iSocketNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_SOCKET_NODE);
if (iSocketNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return false;
}
PVMFSocketNode* socketNode =
(PVMFSocketNode*)(iSocketNodeContainer->iNode);
PVMFSMFSPChildNodeContainer* iSessionControllerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
if (iSessionControllerNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return false;
}
PVRTSPEngineNodeExtensionInterface* rtspExtIntf =
(PVRTSPEngineNodeExtensionInterface*)
(iSessionControllerNodeContainer->iExtensions[0]);
Oscl_Vector<StreamInfo, OsclMemAllocator> aSelectedStream;
if (rtspExtIntf->GetStreamInfo(aSelectedStream) != PVMFSuccess)
{
OSCL_LEAVE(OsclErrGeneral);
}
for (uint32 i = 0; i < aSelectedStream.size(); i++)
{
StreamInfo streamInfo = aSelectedStream[i];
PVMFRTSPTrackInfo* trackInfo = FindTrackInfo(streamInfo.iSDPStreamId);
if (trackInfo == NULL)
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:CompleteFeedBackPortsSetup - FindTrackInfo Failed"));
return false;
}
if (trackInfo->iNetworkNodeRTCPPort == NULL)
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:CompleteFeedBackPortsSetup - Invalid RTCP Port"));
return false;
}
OsclNetworkAddress localAddRTCP;
OsclNetworkAddress remoteAddRTCP;
localAddRTCP.port = streamInfo.iCliRTCPPort;
remoteAddRTCP.port = streamInfo.iSerRTCPPort;
remoteAddRTCP.ipAddr = streamInfo.iSerIpAddr;
socketNode->SetPortConfig(*(trackInfo->iNetworkNodeRTCPPort),
localAddRTCP,
remoteAddRTCP);
if (trackInfo->iNetworkNodePort == NULL)
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:CompleteFeedBackPortsSetup - Invalid RTP Port"));
return false;
}
OsclNetworkAddress localAddRTP;
OsclNetworkAddress remoteAddRTP;
localAddRTP.port = streamInfo.iCliRTPPort;
remoteAddRTP.port = streamInfo.iSerRTPPort;
remoteAddRTP.ipAddr = streamInfo.iSerIpAddr;
socketNode->SetPortConfig(*(trackInfo->iNetworkNodePort),
localAddRTP,
remoteAddRTP);
}
return true;
}
bool
PVMFSMRTSPUnicastNode::SendSessionControlPrepareCompleteParams()
{
if ((iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_RTSP_URL) ||
(iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_SDP_FILE))
{
PVMFSMFSPChildNodeContainer* iSessionControllerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
if (iSessionControllerNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return false;
}
PVRTSPEngineNodeExtensionInterface* rtspExtIntf =
(PVRTSPEngineNodeExtensionInterface*)
(iSessionControllerNodeContainer->iExtensions[0]);
PVMFSMFSPChildNodeContainer* iJitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (iJitterBufferNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return false;
}
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)
(iJitterBufferNodeContainer->iExtensions[0]);
Oscl_Vector<StreamInfo, OsclMemAllocator> aSelectedStream;
if (rtspExtIntf->GetStreamInfo(aSelectedStream) != PVMFSuccess)
{
OSCL_LEAVE(OsclErrGeneral);
}
for (uint32 i = 0; i < aSelectedStream.size(); i++)
{
StreamInfo streamInfo = aSelectedStream[i];
PVMFRTSPTrackInfo* trackInfo = FindTrackInfo(streamInfo.iSDPStreamId);
if (trackInfo == NULL)
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:SendSessionControlPrepareCompleteParams - FindTrackInfo Failed"));
return false;
}
if (trackInfo->iJitterBufferInputPort == NULL)
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:SendSessionControlPrepareCompleteParams - Invalid Port"));
return false;
}
if (streamInfo.ssrcIsSet)
{
jbExtIntf->setPortSSRC(trackInfo->iJitterBufferInputPort,
streamInfo.iSSRC);
}
}
/* Set server info */
PVRTSPEngineNodeServerInfo rtspServerInfo;
PVMFJitterBufferFireWallPacketInfo fireWallPktInfo;
rtspExtIntf->GetServerInfo(rtspServerInfo);
if (rtspServerInfo.iIsPVServer)
{
fireWallPktInfo.iFormat = PVMF_JB_FW_PKT_FORMAT_PV;
}
fireWallPktInfo.iServerRoundTripDelayInMS = rtspServerInfo.iRoundTripDelayInMS;
if (0 == fireWallPktInfo.iServerRoundTripDelayInMS)
{
fireWallPktInfo.iServerRoundTripDelayInMS = PVMF_JITTER_BUFFER_NODE_FIREWALL_PKT_DEFAULT_SERVER_RESPONSE_TIMEOUT_IN_MS;
}
fireWallPktInfo.iNumAttempts = PVMF_JITTER_BUFFER_NODE_DEFAULT_FIREWALL_PKT_ATTEMPTS;
jbExtIntf->setServerInfo(fireWallPktInfo);
}
return true;
}
bool PVMFSMRTSPUnicastNode::SendSessionControlStartCompleteParams()
{
PVMFSMFSPChildNodeContainer* iJitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (iJitterBufferNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return false;
}
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)
(iJitterBufferNodeContainer->iExtensions[0]);
PVMFSMFSPChildNodeContainer* iMediaLayerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_MEDIA_LAYER_NODE);
if (iMediaLayerNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return false;
}
PVMFMediaLayerNodeExtensionInterface* mlExtIntf =
(PVMFMediaLayerNodeExtensionInterface*)
(iMediaLayerNodeContainer->iExtensions[0]);
bool end_is_set = true;
int32 startTime = 0;
int32 stopTime = 0;
if ((iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_RTSP_URL) ||
(iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_SDP_FILE))
{
PVMFSMFSPChildNodeContainer* iSessionControllerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
if (iSessionControllerNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return false;
}
PVRTSPEngineNodeExtensionInterface* rtspExtIntf =
(PVRTSPEngineNodeExtensionInterface*)
(iSessionControllerNodeContainer->iExtensions[0]);
/* Get Actual Play Range */
RtspRangeType rangeType;
if (rtspExtIntf->GetActualPlayRange(rangeType) != PVMFSuccess)
{
return false;
}
rangeType.convertToMilliSec(startTime, stopTime);
/* Use from SDP if not set */
end_is_set = rangeType.end_is_set;
if (end_is_set == false)
{
stopTime = iSessionStopTime;
}
if (iRepositioning)
{
iActualRepositionStartNPTInMS = startTime;
if (iActualRepositionStartNPTInMSPtr != NULL)
{
*iActualRepositionStartNPTInMSPtr = startTime;
}
}
Oscl_Vector<StreamInfo, OsclMemAllocator> aSelectedStream;
if (rtspExtIntf->GetStreamInfo(aSelectedStream) != PVMFSuccess)
{
OSCL_LEAVE(OsclErrGeneral);
}
for (uint32 i = 0; i < aSelectedStream.size(); i++)
{
StreamInfo streamInfo = aSelectedStream[i];
PVMFRTSPTrackInfo* trackInfo = FindTrackInfo(streamInfo.iSDPStreamId);
if (trackInfo == NULL)
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:SendStartCompleteSessionControlParams - FindTrackInfo Failed"));
return false;
}
if (trackInfo->iJitterBufferInputPort == NULL)
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:SendStartCompleteSessionControlParams - Invalid Port"));
return false;
}
if (streamInfo.seqIsSet != true)
{
streamInfo.seqIsSet = false;
streamInfo.seq = 0;
}
if (streamInfo.rtptimeIsSet != true)
{
streamInfo.rtptimeIsSet = false;
streamInfo.rtptime = 0;
}
jbExtIntf->setPortRTPParams(trackInfo->iJitterBufferInputPort,
streamInfo.seqIsSet,
streamInfo.seq,
streamInfo.rtptimeIsSet,
streamInfo.rtptime,
rangeType.start_is_set,
startTime,
iRepositioning);
}
}
/* Send actual stop time to Jitter Buffer */
if (jbExtIntf->setPlayRange(startTime,
stopTime,
iRepositioning,
end_is_set) != true)
{
return false;
}
if (mlExtIntf->setPlayRange(startTime, stopTime, iRepositioning) != true)
{
return false;
}
return true;
}
void PVMFSMRTSPUnicastNode::HandleNodeInformationalEvent(const PVMFAsyncEvent& aEvent)
{
if (SupressInfoEvent())
{
PVMF_SM_RTSP_LOGINFO((0, "PVMFSMRTSPUnicastNode:HandleNodeInformationalEvent Supress info event %u", aEvent.GetEventType()));
return;
}
PVMFAsyncEvent event = OSCL_CONST_CAST(PVMFAsyncEvent, aEvent);
PVMFEventType infoEvent = aEvent.GetEventType();
if (infoEvent == PVMFInfoEndOfData)
{
/* Notify jitter buffer */
PVMFSMFSPChildNodeContainer* iJitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (iJitterBufferNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return;
}
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)
(iJitterBufferNodeContainer->iExtensions[0]);
jbExtIntf->NotifyOutOfBandEOS();
}
else if (infoEvent == PVMFInfoPlayListClipTransition)
{
if (iPlaylistPlayInProgress)
{
iPlaylistPlayInProgress = false;
PVMFSMFSPChildNodeContainer* iSessionControllerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_RTSP_SESSION_CONTROLLER_NODE);
if (iSessionControllerNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return;
}
PVMFSMFSPChildNodeContainer* iJitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (iJitterBufferNodeContainer == NULL)
{
OSCL_LEAVE(OsclErrBadHandle);
return;
}
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)
(iJitterBufferNodeContainer->iExtensions[0]);
PVMFRTSPClientEngineNodePlaylistInfoType *myType = (PVMFRTSPClientEngineNodePlaylistInfoType*)(aEvent.GetEventData());
if (myType == NULL)
{//hang?
PVMF_SM_RTSP_LOGERROR((0, "PVMFSMRTSPUnicastNode::HandleNodeInformationalEvent - PVMFInfoPlayListClipTransition No event data - context=0x%x, event data=0x%x", aEvent.GetContext(), aEvent.GetEventData()));
if (IsBusy())
{
Cancel();
RunIfNotReady();
}
return;
}
NptTimeFormat npt_start;
npt_start.npt_format = NptTimeFormat::NPT_SEC;
npt_start.npt_sec.sec = myType->iPlaylistNPTSec;
npt_start.npt_sec.milli_sec = myType->iPlaylistNPTMillsec;
jbExtIntf->PurgeElementsWithNPTLessThan(npt_start);
iSessionControllerNodeContainer->iNodeCmdState = PVMFSMFSP_NODE_CMD_IDLE;
CompleteStart();
}
PVMFNodeInterface::ReportInfoEvent(event);
}
else if (infoEvent == PVMFInfoSourceOverflow)
{
/* Make note of the overflow */
oAutoReposition = true;
PVMFNodeInterface::ReportInfoEvent(event);
}
else
{
/* Just pass the info event up */
PVMFNodeInterface::ReportInfoEvent(event);
}
}
bool PVMFSMRTSPUnicastNode::CanPerformRepositioning(bool aRandAccessDenied)
{
if ((aRandAccessDenied == true) ||
(iSessionStopTimeAvailable == false) ||
(((int32)iRepositionRequestedStartNPTInMS < (int32)iSessionStartTime) ||
((int32)iRepositionRequestedStartNPTInMS > (int32)iSessionStopTime)))
{
/*
* Implies an open ended session or invalid request time
* - no pause or reposition
*/
return false;
}
return true;
}
bool
PVMFSMRTSPUnicastNode::CheckChildrenNodesStop()
{
{
for (uint32 i = 0; i < iFSPChildNodeContainerVec.size(); i++)
{
if (iFSPChildNodeContainerVec[i].iNodeCmdState != PVMFSMFSP_NODE_CMD_IDLE)
{
return false;
}
}
}
return true;
}
void PVMFSMRTSPUnicastNode::CleanUp()
{
DestroyChildNodes();
DestroyPayloadParserRegistry();
ResetNodeParams();
iLogger = NULL;
}
void PVMFSMRTSPUnicastNode::PopulateDRMInfo()
{
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::PopulateDRMInfo() In"));
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFSMRTSPUnicastNode::PopulateDRMInfo() - CPM not supported yet"));
}
void PVMFSMRTSPUnicastNode::ResetNodeParams(bool aReleaseMemmory)
{
iTrackInfoVec.clear();
iSdpInfo.Unbind();
PVMFSMFSPBaseNode::ResetNodeParams(aReleaseMemmory);
}
void PVMFSMRTSPUnicastNode::GetMaxMediaTS()
{
PVMFSMFSPChildNodeContainer* iJitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (iJitterBufferNodeContainer == NULL) OSCL_LEAVE(OsclErrBadHandle);
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)
(iJitterBufferNodeContainer->iExtensions[0]);
PVMFSMFSPChildNodeContainer* iMediaLayerNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_MEDIA_LAYER_NODE);
if (iMediaLayerNodeContainer == NULL) OSCL_LEAVE(OsclErrBadHandle);
PVMFMediaLayerNodeExtensionInterface* mlExtIntf =
(PVMFMediaLayerNodeExtensionInterface*)
(iMediaLayerNodeContainer->iExtensions[0]);
if (mlExtIntf == NULL) OSCL_LEAVE(OsclErrBadHandle);
PVMFPortInterface* mlInPort = iMediaLayerNodeContainer->iInputPorts[0];
if ((iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_RTSP_URL) ||
(iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_SDP_FILE))
{
iActualMediaDataTS = jbExtIntf->getMaxMediaDataTS();
if (iActualMediaDataTSPtr != NULL)
{
*iActualMediaDataTSPtr = iActualMediaDataTS;
PVMF_SM_RTSP_LOG_COMMAND_REPOS((0, "PVMFStreamingManagerNode::GetActualMediaTSAfterSeek - TargetNPT = %d, ActualNPT=%d, ActualMediaDataTS=%d",
iRepositionRequestedStartNPTInMS, *iActualRepositionStartNPTInMSPtr, *iActualMediaDataTSPtr));
}
if (iPVMFDataSourcePositionParamsPtr != NULL)
{
iPVMFDataSourcePositionParamsPtr->iActualMediaDataTS = iActualMediaDataTS;
PVMF_SM_RTSP_LOG_COMMAND_REPOS((0, "PVMFStreamingManagerNode::GetActualMediaTSAfterSeek - ActualMediaDataTS=%d",
iPVMFDataSourcePositionParamsPtr->iActualMediaDataTS));
}
}
else if (iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_MS_HTTP_STREAMING_URL)
{
iActualRepositionStartNPTInMS = jbExtIntf->getActualMediaDataTSAfterSeek();
*iActualRepositionStartNPTInMSPtr = iActualRepositionStartNPTInMS;
iActualMediaDataTS = mlExtIntf->getMaxOutPortTimestamp(mlInPort);
*iActualMediaDataTSPtr = iActualMediaDataTS;
PVMF_SM_RTSP_LOG_COMMAND_REPOS((0, "PVMFStreamingManagerNode::GetActualMediaTSAfterSeek - TargetNPT = %d, ActualNPT=%d, ActualMediaDataTS=%d",
iRepositionRequestedStartNPTInMS, *iActualRepositionStartNPTInMSPtr, *iActualMediaDataTSPtr));
}
}
void PVMFSMRTSPUnicastNode::DoSetDataSourcePositionOverflow(PVMFSMFSPBaseNodeCommand& aCmd)
{
PVMF_SM_RTSP_LOGSTACKTRACE((0, "PVMFStreamingManagerNode::DoSetDataSourcePositionOverflow - In"));
iActualRepositionStartNPTInMSPtr = NULL;
iActualMediaDataTSPtr = NULL;
iPVMFDataSourcePositionParamsPtr = NULL;
iJumpToIFrame = false;
PVMFTimestamp aTargetNPT;
bool aSeekToSyncPoint;
aCmd.PVMFSMFSPBaseNodeCommand::Parse(aTargetNPT,
iActualRepositionStartNPTInMSPtr,
iActualMediaDataTSPtr,
aSeekToSyncPoint,
iStreamID);
PVMFSMFSPChildNodeContainer* iJitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (iJitterBufferNodeContainer == NULL) OSCL_LEAVE(OsclErrBadHandle);
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)
(iJitterBufferNodeContainer->iExtensions[0]);
jbExtIntf->SendBOSMessage(iStreamID);
oAutoReposition = false;
if (iInterfaceState == EPVMFNodeStarted)
{
bool oRandAccessDenied = false;
if ((iSessionSourceInfo->_sessionType != PVMF_MIME_DATA_SOURCE_RTSP_URL) &&
(iSessionSourceInfo->_sessionType != PVMF_MIME_DATA_SOURCE_SDP_FILE))
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:DoSetDataSourcePositionOverflow - Invalid Session Type"));
oRandAccessDenied = true;
}
if (oRandAccessDenied == true)
{
/*
* Implies an open ended session or invalid request time
* - no pause or reposition
*/
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:DoSetDataSourcePositionOverflow - Invalid Args"));
CommandComplete(iInputCommands, aCmd, PVMFFailure);
return;
}
/* Put the jitter buffer into a state of transition - only if the playlist switch mode is 0*/
PVMFSMFSPChildNodeContainer* iJitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (iJitterBufferNodeContainer == NULL) OSCL_LEAVE(OsclErrBadHandle);
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)
(iJitterBufferNodeContainer->iExtensions[0]);
jbExtIntf->PrepareForRepositioning();
if ((iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_RTSP_URL) ||
(iSessionSourceInfo->_sessionType == PVMF_MIME_DATA_SOURCE_SDP_FILE))
{
// Purge JB at this point
GetMaxMediaTS();
*iActualMediaDataTSPtr = iActualMediaDataTS;
PVMFSMFSPChildNodeContainer* iJitterBufferNodeContainer =
getChildNodeContainer(PVMF_SM_FSP_JITTER_BUFFER_NODE);
if (iJitterBufferNodeContainer == NULL) OSCL_LEAVE(OsclErrBadHandle);
PVMFJitterBufferExtensionInterface* jbExtIntf =
(PVMFJitterBufferExtensionInterface*)
(iJitterBufferNodeContainer->iExtensions[0]);
// Convert iActualMediaDataTS to NPT time format
NptTimeFormat npt_start;
npt_start.npt_format = NptTimeFormat::NPT_SEC;
npt_start.npt_sec.sec = iActualMediaDataTS / 1000;
npt_start.npt_sec.milli_sec = iActualMediaDataTS - 1000 * (iActualMediaDataTS / 1000);
jbExtIntf->PurgeElementsWithNPTLessThan(npt_start);
CommandComplete(iInputCommands, aCmd, PVMFSuccess);
}
else
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:DoSetDataSourcePositionOverflow - Invalid Session Type"));
CommandComplete(iInputCommands, aCmd, PVMFFailure);
}
}
else
{
PVMF_SM_RTSP_LOGERROR((0, "StreamingManagerNode:DoSetDataSourcePositionOverflow - Invalid State"));
CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
}
return;
}