blob: 223ee6b98d5d74b43394b5808c4d1ab2bf69d106 [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_SOCKET_PORT_H_INCLUDED
#include "pvmf_socket_port.h"
#endif
#ifndef OSCL_MIME_STRING_UTILS_H
#include "pv_mime_string_utils.h"
#endif
#include "pvmf_socket_node_tunables.h"
PVMFSocketPort::PVMFSocketPort(int32 aTag, PVMFNodeInterface* aNode)
: PvmfPortBaseImpl(aTag, aNode)
{
Construct();
}
////////////////////////////////////////////////////////////////////////////
PVMFSocketPort::PVMFSocketPort(int32 aTag, PVMFNodeInterface* aNode
, uint32 aInCapacity
, uint32 aInReserve
, uint32 aInThreshold
, uint32 aOutCapacity
, uint32 aOutReserve
, uint32 aOutThreshold)
: PvmfPortBaseImpl(aTag, aNode, aInCapacity, aInReserve, aInThreshold, aOutCapacity, aOutReserve, aOutThreshold)
{
iPortTag = (PVMFSocketNodePortTag)aTag;
Construct();
}
////////////////////////////////////////////////////////////////////////////
void PVMFSocketPort::Construct()
{
iConfig = NULL;
iLogger = PVLogger::GetLoggerObject("PVMFSocketPort");
oscl_memset(&iStats, 0, sizeof(PvmfPortBaseImplStats));
iNumFramesConsumed = 0;
PvmiCapabilityAndConfigPortFormatImpl::Construct(
PVMF_SOCKET_PORT_SPECIFIC_ALLOCATOR
, PVMF_SOCKET_PORT_SPECIFIC_ALLOCATOR_VALTYPE);
}
////////////////////////////////////////////////////////////////////////////
PVMFSocketPort::~PVMFSocketPort()
{
Disconnect();
}
////////////////////////////////////////////////////////////////////////////
bool PVMFSocketPort::IsFormatSupported(PVMFFormatType aFmt)
{
bool formatSupported = false;
if ((aFmt == PVMF_MIME_INET_UDP) || (aFmt == PVMF_MIME_INET_TCP))
{
formatSupported = true;
}
return formatSupported;
}
////////////////////////////////////////////////////////////////////////////
void PVMFSocketPort::FormatUpdated()
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO
, (0, "PVMFSocketPort::FormatUpdated %s", iFormat.getMIMEStrPtr()));
}
void PVMFSocketPort::setParametersSync(PvmiMIOSession aSession,
PvmiKvp* aParameters,
int num_elements,
PvmiKvp * & aRet_kvp)
{
OSCL_UNUSED_ARG(aSession);
PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFSocketPort::getParametersSync: aSession=0x%x, aParameters=0x%x, num_elements=%d, aRet_kvp=0x%x",
aSession, aParameters, num_elements, aRet_kvp));
if (!aParameters || (num_elements != 1) ||
(pv_mime_strcmp(aParameters->key, PVMF_SOCKET_PORT_SPECIFIC_ALLOCATOR_VALTYPE) != 0))
{
aRet_kvp = aParameters;
OSCL_LEAVE(OsclErrArgument);
}
if (aParameters->value.key_specific_value == NULL)
{
aRet_kvp = aParameters;
OSCL_LEAVE(OsclErrArgument);
}
}
PVMFStatus PVMFSocketPort::getParametersSync(PvmiMIOSession aSession,
PvmiKeyType aIdentifier,
PvmiKvp*& aParameters,
int& num_parameter_elements,
PvmiCapabilityContext aContext)
{
OSCL_UNUSED_ARG(aSession);
OSCL_UNUSED_ARG(aContext);
PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFSocketPort::getParametersSync: aSession=0x%x, aIdentifier=%s, aParameters=0x%x, num_parameters_elements=%d, aContext=0x%x",
aSession, aIdentifier, aParameters, num_parameter_elements, aContext));
if (pv_mime_strcmp(aIdentifier, PVMI_PORT_CONFIG_INPLACE_DATA_PROCESSING_KEY) != 0)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFSocketPort::getParametersSync: Error - Unsupported PvmiKeyType"));
return PVMFErrNotSupported;
}
num_parameter_elements = 0;
if (!pvmiGetPortInPlaceDataProcessingInfoSync(PVMI_PORT_CONFIG_INPLACE_DATA_PROCESSING_VALUE, aParameters))
{
return PVMFFailure;
}
num_parameter_elements = 1;
return PVMFSuccess;
}
PVMFStatus PVMFSocketPort::releaseParameters(PvmiMIOSession aSession,
PvmiKvp* aParameters,
int num_elements)
{
OSCL_UNUSED_ARG(aSession);
PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFSocketPort::releaseParameters: aSession=0x%x, aParameters=0x%x, num_elements=%d",
aSession, aParameters, num_elements));
if ((num_elements != 1) ||
(pv_mime_strcmp(aParameters->key, PVMI_PORT_CONFIG_INPLACE_DATA_PROCESSING_VALUE) != 0))
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFSocketPort::releaseParameters: Error - Not a PvmiKvp created by this port"));
return PVMFFailure;
}
OsclMemAllocator alloc;
alloc.deallocate((OsclAny*)(aParameters));
return PVMFSuccess;
}
bool
PVMFSocketPort::pvmiGetPortInPlaceDataProcessingInfoSync(const char* aFormatValType,
PvmiKvp*& aKvp)
{
/*
* Create PvmiKvp for capability settings
*/
aKvp = NULL;
OsclMemAllocator alloc;
uint32 strLen = oscl_strlen(aFormatValType) + 1;
uint8* ptr = (uint8*)alloc.allocate(sizeof(PvmiKvp) + strLen);
if (!ptr)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFSocketPort::pvmiGetPortInPlaceDataProcessingInfoSync: Error - No memory. Cannot allocate PvmiKvp"));
return false;
}
aKvp = new(ptr) PvmiKvp;
ptr += sizeof(PvmiKvp);
aKvp->key = (PvmiKeyType)ptr;
oscl_strncpy(aKvp->key, aFormatValType, strLen);
aKvp->length = aKvp->capacity = strLen;
#if SNODE_ENABLE_UDP_MULTI_PACKET
if (iTag == PVMF_SOCKET_NODE_PORT_TYPE_SOURCE)
aKvp->value.bool_value = false;//for the multiple UDP recv feature
else
#endif
aKvp->value.bool_value = true;
return true;
}
////////////////////////////////////////////////////////////////////////////
PVMFStatus PVMFSocketPort::PeekIncomingMsg(PVMFSharedMediaMsgPtr& aMsg)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
(0, "0x%x PVMFSocketPort::PeekIncomingMsg", this));
if (iIncomingQueue.iQ.empty())
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
(0, "0x%x PVMFSocketPort::PeekIncomingMsg: Error - Incoming queue is empty", this));
return PVMFFailure;
}
// Save message to output parameter and erase it from queue
aMsg = iIncomingQueue.iQ.front();
return PVMFSuccess;
}
////////////////////////////////////////////////////////////////////////////
PVMFStatus PVMFSocketPort::QueueOutgoingMsg(PVMFSharedMediaMsgPtr aMsg)
//In this node, we skip the outgoing queue and go directly to the connected port's
//incoming queue.
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFSocketPort::QueueOutgoingMsg"));
//If port is not connected, don't accept data on the
//outgoing queue.
if (!iConnectedPort)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFSocketPort::QueueOutgoingMsg: Error - Port not connected"));
return PVMFFailure;
}
PvmfPortBaseImpl* cpPort = OSCL_STATIC_CAST(PvmfPortBaseImpl*, iConnectedPort);
// Connected Port incoming Queue is in busy / flushing state. Do not accept more outgoing messages
// until the queue is not busy, i.e. queue size drops below specified threshold or FlushComplete
// is called.
if (cpPort->iIncomingQueue.iBusy)
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFSocketPort::QueueOutgoingMsg: Connected Port Incoming queue in busy / flushing state - Attempting to Q in output port's outgoing msg q"));
return (PvmfPortBaseImpl::QueueOutgoingMsg(aMsg));
}
// Add message to outgoing queue and notify the node of the activity
// There is no need to trap the push_back, since it cannot leave in this usage
// Reason being that we do a reserve in the constructor and we do not let the
// port queues grow indefinitely (we either a connected port busy or outgoing Q busy
// before we reach the reserved limit
PVMFStatus status = cpPort->Receive(aMsg);
if (status != PVMFSuccess)
{
return PVMFFailure;
}
// Outgoing queue size is at capacity and goes into busy state. The owner node is
// notified of this transition into busy state.
if (cpPort->isIncomingFull())
{
PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFSocketPort::QueueOutgoingMsg: Connected Port incoming queue is full. Goes into busy state"));
cpPort->iIncomingQueue.iBusy = true;
PvmfPortBaseImpl::PortActivity(PVMF_PORT_ACTIVITY_CONNECTED_PORT_BUSY);
}
return PVMFSuccess;
}
bool PVMFSocketPort::IsOutgoingQueueBusy()
//In this node, we skip the outgoing queue and go directly to the connected port's
//incoming queue.
{
if (iConnectedPort != NULL)
{
PvmfPortBaseImpl* cpPort = OSCL_STATIC_CAST(PvmfPortBaseImpl*, iConnectedPort);
return (cpPort->iIncomingQueue.iBusy);
}
return (PvmfPortBaseImpl::IsOutgoingQueueBusy());;
}