======================================================== This file outlines the files involved in receiving and moving RTP data from the physical network up to the client renderers. ======================================================== [Raw Network I/O Subsystem] --------------------------- 1. common/netio/conn.cpp common/netio/pub/thrdconn.h Data is received from the underlying network.. conn has a static mConnectionList, which stores a list of all open connections in helix player. conn::new_socket() creates a connection for the correct platform, (which is actually a ThreadedConn if we support threads.), and adds it to its global list. ThreadedConn inherits from conn, and implements various methods.. including readfrom(), which will provide a packet from the local buffer -- m_ReadUDPBuffers -- if there is one to be passed up. also has void set_callback(HXAsyncNetCallback* pCallback); and its own member: CHXSimpleList m_ReadUDPBuffers; [Client Core Network Services] ------------------------------ 2. client/netwksvc/hxnetapi.cpp HXNetworkServices::CreateUDPSocket() actually returns a new HXUDPSocket(m_pContext, this); UDP Data is read from the network and stored in the read buffer: conn* m_pData; (class member) STDMETHODIMP HXUDPSocket::Bind(UINT32 ulLocalAddr, UINT16 nPort) -- initialises the underlying conn object from the raq io subsystem m_pData = conn::new_socket(HX_UDP_SOCKET); ... theErr = m_pData->init(ulLocalAddr, nPort); it also initializes the: IHXUDPResponse* pUDPResponse to whatever gets passed in in Init(); HXUDPSocket::DoRead() gets data from the lower level into a temp buffer, after constructing a packet from the data that includes its source address and port. theErr = m_pData->readfrom(pBuffer, ulAddress, ulPort); ... m_ReadBuffers.AddTail((void*)pPacket); Then, if a read is pending, we grab the last thing to arrive (ie. oldest) and return it asynchronously to the response object for this UDPSocket. UDP_PACKET* pPacket = (UDP_PACKET*)m_ReadBuffers.RemoveHead(); ... m_pUDPResponse->ReadDone(HXR_OK, pBuffer, ulAddress, ulPort); HXUDPSocket::Read(UINT16 nBytes) actually calls DoRead() a number of times... (sort of 'pumps' data up the stack i guess?). [Protocol Subsystem] -------------------- 3. protocol/rtsp/rtspclnt.cpp 'The Protocol subsystem, such as for the RTSP protocol, pass read buffers from the Client Core Network Services to the Protocol Transport Subsystem' RTSPClientProtocol::sendSetupRequestMessageExt() -- seems to do this in response to a sdp description (or other) from a server for a particular stream: RTSPTransport* pTrans = new RTPUDPTransport(m_bSetupRecord); ... IHXUDPSocket* pUDPSocket = (IHXUDPSocket*)(*m_pUDPSocketStreamMap)[streamNumber]; pUDPSocket->GetLocalPort(nUDPPort); IHXUDPSocket* pRTCPSocket = (IHXUDPSocket*)(*m_pRTCPSocketStreamMap)[streamNumber]; UINT16 nRTCPPort; pRTCPSocket->GetLocalPort(nRTCPPort); (nb: CHXMapLongToObj* m_pUDPSocketStreamMap; // map streamID->socket) ... ((RTPUDPTransport*)pTrans)->init( m_pContext, pUDPSocket, (IHXRTSPTransportResponse*) this)) ... RTCPUDPTransport* pRTCPTran = new RTCPUDPTransport(m_bSetupRecord); pRTCPTran->init(m_pContext, pRTCPSocket, (RTPUDPTransport*)pTrans, (IHXRTSPTransportResponse*) this, streamNumber); ((RTPUDPTransport*)pTrans)->setRTCPTransport(pRTCPTran); pRequest->addTransportInfo(pTrans, (RTCPBaseTransport*)pRTCPTran, streamNumber, nUDPPort); Sockets for udp are setup in RTSPClientProtocol::InitSockets() -- (udpSocket1 and 2..) also creates two UDPResponseHelpers and adds them to m_UDPResponseHelperList. then inits the two sockets it created with the UDPResponseHelper objects, and then binds the sockets to the local address and two consecutive addresses (even followed by odd). then adds the sockets to the maps for the streams in the RTSPClientProtocol ... the 'helpers' call ReadDoneWithToPort(), which provides the same info as ReadDone(), but appends the local port that the packets were delivered on! ReadDoneWithToPort():: nb: bold.. verrifies the addr received from! .. would have to have been hacked for our first approach ... pTrans->handlePacket(pBuffer); but recall.. RTSPTransport* pTrans = new RTPUDPTransport(m_bSetupRecord); when we call handlePacket(pBuffer) we loose some of the information we've accumulated.. i think (port numbers are available, the remote addr etc.. has been verified, so we dont care, arrival time not stored.. presumably added in next level........ [Protocol Transport Subsystem] ------------------------------ 4. protocol/transport/rtp/rtptran.cpp (RTPUDPTransport inherits from RTPBaseTransport, which inherits from RTSPTransport) RTPBaseTransport::_handlePacket unpacks the rtp, verrifies the verion number...... then: RTSPStreamData* pStreamData = m_pStreamHandler->getStreamData(m_streamNumber); where getStreamData does the following on the m_pStreamHandler defined in RTSPTransport m_pStreamDataMap->Lookup(streamNumber, (void*&)pStreamData) an RTSPTransport has a RTSPStreamHandler* m_pStreamHandler;. and it initializes it when we try to call addStreamInfo(RTSPStreamInfo* pStreamInfo, UINT32 ulBufferDepth) if it doesnt allready exist which in turn calls initStreamData() on an RTSPStreamHandler which setsup buffers for seperate stream numbers using the data from the pStreamInfo update RTCP statistics may need to temporarily buffer the data received in m_StartInfoWaitQueue before putting it where it belongs... in which case its locally 'resent' back to _handlePacket then does something funkey converting timestamps to helixs native rma timestamp type... but preserves the rtp one too.. and eventually produces a CHXPacket, which we store using..... storePacket() -- implemented by RTSPTransport, which produces a ClientPacket* of our data, which gets appended to the pTransportBuffer for the particular stream number (getTransportBuffer(uStreamNumber)). (pTransportBuffer is a RTSPTransportBuffer). [Client Core Player] -------------------- 5. client/core/hxplay.cpp HXPlayer::EventReady(hxsource, pevent) is called by an underlying HXSource member of the player, which itself is called via its HXSource::EventReady() method. Depending on the event status it is immediately dispatched to the renderer plugin, or queued. HXPlayer::ProcessCurrentEvents() passes queued up packets from its underlying sources to the packets associated renderer plugin via SendPacket(). The HXPLayer has a (HXEventList) m_EventList which is the buffer into which packets are stored. notes:: ./client/core/buffmgr.cpp: m_pParent->EventReady(pEvent); ./client/core/rtspprotocol.cpp: mOwner->EventReady(pEvent); (nb: when RTSPProtocol::HandlePacket() is called by ?SOMETHING? it creates a CHXEvent for the packet and notifies the RTSPProtocols.mOwner via mOwner.EventReady(). mOwner is a HXNetSource, and HXSource implements the EventReady() handler. The HXNetSource then passes the event onto its owner via HXSource::EventReady(){ m_pPlayer.EventReady(this, pEvent)}.) A HXSource gets a player associated with it in HXSource::Init() "The Client Core Player deques up to 50 packets every time the SourceInfo::ProcessIdle function is called" ... note: in ProcessIdle() it calls pSource->GetEvent(stream_num, pEvent) which calls HXNetSource->GetEvent() which calls HXNetSource->GetEventFromProtocol() and finally sends the packets up to the player via SendPacket() (or directly into the players queue, and increases pRendInfo->m_ulNumberOfPacketsQueued. [Datatype Renderer] ------------------- Packet arrives in the renderer as expected.