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