Home | History | Annotate | Download | only in src
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 #ifndef PVMF_SOCKET_PORT_H_INCLUDED
     19 #include "pvmf_socket_port.h"
     20 #endif
     21 
     22 #ifndef OSCL_MIME_STRING_UTILS_H
     23 #include "pv_mime_string_utils.h"
     24 #endif
     25 
     26 #include "pvmf_socket_node_tunables.h"
     27 
     28 
     29 PVMFSocketPort::PVMFSocketPort(int32 aTag, PVMFNodeInterface* aNode)
     30         : PvmfPortBaseImpl(aTag, aNode)
     31 {
     32     Construct();
     33 }
     34 
     35 ////////////////////////////////////////////////////////////////////////////
     36 PVMFSocketPort::PVMFSocketPort(int32 aTag, PVMFNodeInterface* aNode
     37                                , uint32 aInCapacity
     38                                , uint32 aInReserve
     39                                , uint32 aInThreshold
     40                                , uint32 aOutCapacity
     41                                , uint32 aOutReserve
     42                                , uint32 aOutThreshold)
     43         : PvmfPortBaseImpl(aTag, aNode, aInCapacity, aInReserve, aInThreshold, aOutCapacity, aOutReserve, aOutThreshold)
     44 {
     45     iPortTag = (PVMFSocketNodePortTag)aTag;
     46     Construct();
     47 }
     48 
     49 ////////////////////////////////////////////////////////////////////////////
     50 void PVMFSocketPort::Construct()
     51 {
     52     iConfig = NULL;
     53     iLogger = PVLogger::GetLoggerObject("PVMFSocketPort");
     54     oscl_memset(&iStats, 0, sizeof(PvmfPortBaseImplStats));
     55     iNumFramesConsumed = 0;
     56     PvmiCapabilityAndConfigPortFormatImpl::Construct(
     57         PVMF_SOCKET_PORT_SPECIFIC_ALLOCATOR
     58         , PVMF_SOCKET_PORT_SPECIFIC_ALLOCATOR_VALTYPE);
     59 }
     60 
     61 ////////////////////////////////////////////////////////////////////////////
     62 PVMFSocketPort::~PVMFSocketPort()
     63 {
     64     Disconnect();
     65 }
     66 
     67 ////////////////////////////////////////////////////////////////////////////
     68 bool PVMFSocketPort::IsFormatSupported(PVMFFormatType aFmt)
     69 {
     70     bool formatSupported = false;
     71     if ((aFmt == PVMF_MIME_INET_UDP) || (aFmt == PVMF_MIME_INET_TCP))
     72     {
     73         formatSupported = true;
     74     }
     75     return formatSupported;
     76 }
     77 
     78 ////////////////////////////////////////////////////////////////////////////
     79 void PVMFSocketPort::FormatUpdated()
     80 {
     81     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO
     82                     , (0, "PVMFSocketPort::FormatUpdated %s", iFormat.getMIMEStrPtr()));
     83 }
     84 
     85 void PVMFSocketPort::setParametersSync(PvmiMIOSession aSession,
     86                                        PvmiKvp* aParameters,
     87                                        int num_elements,
     88                                        PvmiKvp * & aRet_kvp)
     89 {
     90     OSCL_UNUSED_ARG(aSession);
     91     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFSocketPort::getParametersSync: aSession=0x%x, aParameters=0x%x, num_elements=%d, aRet_kvp=0x%x",
     92                     aSession, aParameters, num_elements, aRet_kvp));
     93 
     94     if (!aParameters || (num_elements != 1) ||
     95             (pv_mime_strcmp(aParameters->key, PVMF_SOCKET_PORT_SPECIFIC_ALLOCATOR_VALTYPE) != 0))
     96     {
     97         aRet_kvp = aParameters;
     98         OSCL_LEAVE(OsclErrArgument);
     99     }
    100     if (aParameters->value.key_specific_value == NULL)
    101     {
    102         aRet_kvp = aParameters;
    103         OSCL_LEAVE(OsclErrArgument);
    104     }
    105 }
    106 
    107 PVMFStatus PVMFSocketPort::getParametersSync(PvmiMIOSession aSession,
    108         PvmiKeyType aIdentifier,
    109         PvmiKvp*& aParameters,
    110         int& num_parameter_elements,
    111         PvmiCapabilityContext aContext)
    112 {
    113     OSCL_UNUSED_ARG(aSession);
    114     OSCL_UNUSED_ARG(aContext);
    115     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",
    116                     aSession, aIdentifier, aParameters, num_parameter_elements, aContext));
    117 
    118     if (pv_mime_strcmp(aIdentifier, PVMI_PORT_CONFIG_INPLACE_DATA_PROCESSING_KEY) != 0)
    119     {
    120         PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFSocketPort::getParametersSync: Error - Unsupported PvmiKeyType"));
    121         return PVMFErrNotSupported;
    122     }
    123 
    124     num_parameter_elements = 0;
    125     if (!pvmiGetPortInPlaceDataProcessingInfoSync(PVMI_PORT_CONFIG_INPLACE_DATA_PROCESSING_VALUE, aParameters))
    126     {
    127         return PVMFFailure;
    128     }
    129     num_parameter_elements = 1;
    130     return PVMFSuccess;
    131 }
    132 
    133 PVMFStatus PVMFSocketPort::releaseParameters(PvmiMIOSession aSession,
    134         PvmiKvp* aParameters,
    135         int num_elements)
    136 {
    137     OSCL_UNUSED_ARG(aSession);
    138     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFSocketPort::releaseParameters: aSession=0x%x, aParameters=0x%x, num_elements=%d",
    139                     aSession, aParameters, num_elements));
    140 
    141     if ((num_elements != 1) ||
    142             (pv_mime_strcmp(aParameters->key, PVMI_PORT_CONFIG_INPLACE_DATA_PROCESSING_VALUE) != 0))
    143     {
    144         PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFSocketPort::releaseParameters: Error - Not a PvmiKvp created by this port"));
    145         return PVMFFailure;
    146     }
    147     OsclMemAllocator alloc;
    148     alloc.deallocate((OsclAny*)(aParameters));
    149     return PVMFSuccess;
    150 }
    151 
    152 bool
    153 PVMFSocketPort::pvmiGetPortInPlaceDataProcessingInfoSync(const char* aFormatValType,
    154         PvmiKvp*& aKvp)
    155 {
    156     /*
    157      * Create PvmiKvp for capability settings
    158      */
    159     aKvp = NULL;
    160     OsclMemAllocator alloc;
    161     uint32 strLen = oscl_strlen(aFormatValType) + 1;
    162     uint8* ptr = (uint8*)alloc.allocate(sizeof(PvmiKvp) + strLen);
    163     if (!ptr)
    164     {
    165         PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFSocketPort::pvmiGetPortInPlaceDataProcessingInfoSync: Error - No memory. Cannot allocate PvmiKvp"));
    166         return false;
    167     }
    168     aKvp = new(ptr) PvmiKvp;
    169     ptr += sizeof(PvmiKvp);
    170     aKvp->key = (PvmiKeyType)ptr;
    171     oscl_strncpy(aKvp->key, aFormatValType, strLen);
    172     aKvp->length = aKvp->capacity = strLen;
    173 
    174 #if SNODE_ENABLE_UDP_MULTI_PACKET
    175     if (iTag == PVMF_SOCKET_NODE_PORT_TYPE_SOURCE)
    176         aKvp->value.bool_value = false;//for the multiple UDP recv feature
    177     else
    178 #endif
    179         aKvp->value.bool_value = true;
    180 
    181     return true;
    182 }
    183 
    184 ////////////////////////////////////////////////////////////////////////////
    185 PVMFStatus PVMFSocketPort::PeekIncomingMsg(PVMFSharedMediaMsgPtr& aMsg)
    186 {
    187     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    188                     (0, "0x%x PVMFSocketPort::PeekIncomingMsg", this));
    189 
    190     if (iIncomingQueue.iQ.empty())
    191     {
    192         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
    193                         (0, "0x%x PVMFSocketPort::PeekIncomingMsg: Error - Incoming queue is empty", this));
    194         return PVMFFailure;
    195     }
    196 
    197     // Save message to output parameter and erase it from queue
    198     aMsg = iIncomingQueue.iQ.front();
    199 
    200     return PVMFSuccess;
    201 }
    202 
    203 ////////////////////////////////////////////////////////////////////////////
    204 PVMFStatus PVMFSocketPort::QueueOutgoingMsg(PVMFSharedMediaMsgPtr aMsg)
    205 //In this node, we skip the outgoing queue and go directly to the connected port's
    206 //incoming queue.
    207 {
    208     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFSocketPort::QueueOutgoingMsg"));
    209 
    210     //If port is not connected, don't accept data on the
    211     //outgoing queue.
    212     if (!iConnectedPort)
    213     {
    214         PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFSocketPort::QueueOutgoingMsg: Error - Port not connected"));
    215         return PVMFFailure;
    216     }
    217 
    218     PvmfPortBaseImpl* cpPort = OSCL_STATIC_CAST(PvmfPortBaseImpl*, iConnectedPort);
    219 
    220     // Connected Port incoming Queue is in busy / flushing state.  Do not accept more outgoing messages
    221     // until the queue is not busy, i.e. queue size drops below specified threshold or FlushComplete
    222     // is called.
    223     if (cpPort->iIncomingQueue.iBusy)
    224     {
    225         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"));
    226         return (PvmfPortBaseImpl::QueueOutgoingMsg(aMsg));
    227     }
    228 
    229     // Add message to outgoing queue and notify the node of the activity
    230     // There is no need to trap the push_back, since it cannot leave in this usage
    231     // Reason being that we do a reserve in the constructor and we do not let the
    232     // port queues grow indefinitely (we either a connected port busy or outgoing Q busy
    233     // before we reach the reserved limit
    234     PVMFStatus status = cpPort->Receive(aMsg);
    235 
    236     if (status != PVMFSuccess)
    237     {
    238         return PVMFFailure;
    239     }
    240 
    241     // Outgoing queue size is at capacity and goes into busy state. The owner node is
    242     // notified of this transition into busy state.
    243     if (cpPort->isIncomingFull())
    244     {
    245         PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFSocketPort::QueueOutgoingMsg: Connected Port incoming queue is full. Goes into busy state"));
    246         cpPort->iIncomingQueue.iBusy = true;
    247         PvmfPortBaseImpl::PortActivity(PVMF_PORT_ACTIVITY_CONNECTED_PORT_BUSY);
    248     }
    249 
    250     return PVMFSuccess;
    251 }
    252 
    253 bool PVMFSocketPort::IsOutgoingQueueBusy()
    254 //In this node, we skip the outgoing queue and go directly to the connected port's
    255 //incoming queue.
    256 {
    257     if (iConnectedPort != NULL)
    258     {
    259         PvmfPortBaseImpl* cpPort = OSCL_STATIC_CAST(PvmfPortBaseImpl*, iConnectedPort);
    260         return (cpPort->iIncomingQueue.iBusy);
    261     }
    262     return (PvmfPortBaseImpl::IsOutgoingQueueBusy());;
    263 }
    264 
    265