⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 servermediasubsession.cpp

📁 rtsp协议的主要实现代码.对开发流媒体
💻 CPP
字号:
// ServerMediaSubsession.cpp: implementation of the ServerMediaSubsession class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ServerMediaSubsession.h"
#include "RTPSink.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

class StreamState {
public:
	//##ModelId=432A2DD3005E
	StreamState(Port const& serverRTPPort, Port const& serverRTCPPort,
		RTPSink* rtpSink,unsigned totalBW, char* CNAME,
		FramedSource* mediaSource);
	//##ModelId=432A2DD3005D
	virtual ~StreamState();
	
	//##ModelId=432A2DD3003F
	void startPlaying(Destinations* destinations);
	//##ModelId=432A2DD3003E
	void pause();
	//##ModelId=432A2DD30033
	void endPlaying(Destinations* destinations);
	//##ModelId=432A2DD30032
	void reclaim();
	
	//##ModelId=432A2DD30031
	unsigned& referenceCount() { return fReferenceCount; }
	
	//##ModelId=432A2DD30030
	Port const& serverRTPPort() const { return fServerRTPPort; }
	//##ModelId=432A2DD3002F
	Port const& serverRTCPPort() const { return fServerRTCPPort; }
	
	//##ModelId=432A2DD3002E
	RTPSink const* rtpSink() const { return fRTPSink; }
	
	//##ModelId=432A2DD30024
	FramedSource* mediaSource() const { return fMediaSource; }
	
private:
	//##ModelId=432A2DD30021
	Boolean fAreCurrentlyPlaying;
	//##ModelId=432A2DD30012
	unsigned fReferenceCount;
	
	Port fServerRTPPort, fServerRTCPPort;
	
	//##ModelId=432A2DD30007
	RTPSink* fRTPSink;
	
	//##ModelId=432A2DD203DF
	unsigned fTotalBW; char* fCNAME;
	
	//##ModelId=432A2DD203DA
	FramedSource* fMediaSource;
	
};

//************************ StreamState implement*************************
StreamState::StreamState(Port const& serverRTPPort, Port const& serverRTCPPort,
						 RTPSink* rtpSink,  unsigned totalBW, char* CNAME,
						 FramedSource* mediaSource)
						 : fAreCurrentlyPlaying(False), fReferenceCount(1),
						 fServerRTPPort(serverRTPPort), fServerRTCPPort(serverRTCPPort),
						 fRTPSink(rtpSink), fTotalBW(totalBW), fCNAME(CNAME),
						 fMediaSource(mediaSource){
	
}  

StreamState::~StreamState()
{
	reclaim();
}


void StreamState::reclaim() {
	// Delete allocated media objects
	
	delete fRTPSink; fRTPSink = NULL;

	delete fMediaSource; fMediaSource = NULL;
	
	fReferenceCount = 0;
}

void StreamState
::startPlaying(Destinations* dests) 
{
	if (dests == NULL) return;
	if (!fAreCurrentlyPlaying && fMediaSource != NULL) 
	{
		if (fRTPSink != NULL) 
		{
			fRTPSink->fRTPInterface->AddRtpDest(inet_ntoa(dests->addr), ntohs(dests->rtpPort.num()));
			fRTPSink->startPlaying(fMediaSource);
			fAreCurrentlyPlaying = True;
		}
	}
}

void StreamState::endPlaying(Destinations* dests) {
	// Tell the RTP and RTCP 'groupsocks' to stop using these destinations:
	if(fRTPSink)
	{
		fRTPSink->fRTPInterface->RemoveRtpDest(inet_ntoa(dests->addr), ntohs(dests->rtpPort.num()));
	}
}

//******************** ServerMediaSubsession implement****************
ServerMediaSubsession::ServerMediaSubsession(const char * SDPMediaTypeString,const char * FileName) :
	fSDPMediaTypeString(SDPMediaTypeString),fPortNumForSDP(0),fTrackNumber(0),fTrackId(NULL),fSDPLines(NULL)
{
	fFileName = strDup(FileName);
	memset(fCNAME,0,sizeof(fCNAME));
	gethostname(fCNAME, sizeof fCNAME);
}

ServerMediaSubsession::~ServerMediaSubsession()
{

}

void ServerMediaSubsession::getStreamParameters(unsigned clientSessionId,  
												netAddressBits clientAddress,  
												Port const& clientRTPPort,  
												Port const& clientRTCPPort,  
												int tcpSocketNum,  
												unsigned char rtpChannelId,  
												unsigned char rtcpChannelId,  
												netAddressBits& destinationAddress,
												u_int8_t& destinationTTL,  
												Boolean& isMulticast,  
												Port& serverRTPPort,  
												Port& serverRTCPPort,  
												void*& streamToken )
{
	if (destinationAddress == 0) destinationAddress = clientAddress;
	struct in_addr destinationAddr; destinationAddr.s_addr = destinationAddress;
	isMulticast = False;
	
	{
		// Normal case: Create a new media source:
		unsigned streamBitrate;
		streamBitrate = GetEstBitrate();
		//FramedSource* mediaSource
		//	= createNewStreamSource(clientSessionId, streamBitrate);
		
		// Create a new 'groupsock' for the RTP destination, and make sure that
		// its port number is even:
		struct in_addr dummyAddr; dummyAddr.s_addr = 0;
		portNumBits serverRTPPortNum = 0;
			
		// Create a sink for this stream:
		RTPSink* rtpSink;
		{
			// Normal case: We're streaming RTP (over UDP or TCP):
			unsigned char rtpPayloadType = 96 + trackNumber()-1; // if dynamic
			rtpSink = createNewRTPSink(rtpPayloadType, fMediaSource);
			fRTPSink = rtpSink;
			serverRTPPort = fRTPSink->GetServerPort();
			serverRTCPPort = fRTPSink->GetServerPort() + 1;
		}
		
		// Set up the state of the stream.  The stream will get started later:
		streamToken = new StreamState(serverRTPPort, serverRTCPPort, rtpSink,streamBitrate, fCNAME, fMediaSource);
	}
	
	// Record these destinations as being for this client session id:
	Destinations* destinations;
	if (tcpSocketNum < 0) { // UDP
		destinations = new Destinations(destinationAddr, clientRTPPort, clientRTCPPort);
	}
	fDestinationsHashTable.insert(pair<unsigned,Destinations *>(clientSessionId, destinations));
}

const char * ServerMediaSubsession::sdpLines()
{
	if(fSDPLines)
		return fSDPLines;
	unsigned estBitrate; // unused
    FramedSource* inputSource = createNewStreamSource(0, estBitrate);
    if (inputSource == NULL) return NULL; // file not found
	fMediaSource = inputSource;  //create media source

	char const* mediaType = fSDPMediaTypeString;
	unsigned char rtpPayloadType = fMediaSource->GetPayloadFormatCode();
	if(rtpPayloadType == 0)
	{
		rtpPayloadType = 96 + trackNumber() - 1;//if dynamic
	}
	struct in_addr serverAddrForSDP; serverAddrForSDP.s_addr = 0; //muti addr
	char* const ipAddressStr = strDup(our_inet_ntoa(serverAddrForSDP));
	char* rtpmapLine = strDup("");//rtpSink->rtpmapLine();
	char const* rangeLine = strDup("");//rangeSDPLine();
	char const* auxSDPLine = NULL;//getAuxSDPLine(rtpSink, inputSource);
	if (auxSDPLine == NULL) auxSDPLine = strDup("");

	char const* const sdpFmt =
		"m=%s %u RTP/AVP %d\r\n"
		"c=IN IP4 %s\r\n"
		"%s"
		"%s"
		"%s"
		"a=control:%s\r\n";
	unsigned sdpFmtSize = strlen(sdpFmt)
		+ strlen(mediaType) + 5 /* max short len */ + 3 /* max char len */
		+ strlen(ipAddressStr)
		+ strlen(rtpmapLine)
		+ strlen(rangeLine)
		+ strlen(auxSDPLine)
		+ strlen(trackId());
	char* sdpLines = new char[sdpFmtSize];
	sprintf(sdpLines, sdpFmt,
		mediaType, // m= <media>
		fPortNumForSDP, // m= <port>
		rtpPayloadType, // m= <fmt list>
		ipAddressStr, // c= address
		rtpmapLine, // a=rtpmap:... (if present)
		rangeLine, // a=range:... (if present)
		auxSDPLine, // optional extra SDP line
		trackId()); // a=control:<track-id>
	delete[] (char*)rangeLine; delete[] rtpmapLine; delete[] ipAddressStr;
	
	fSDPLines = strDup(sdpLines);
	delete[] sdpLines;

	return fSDPLines;
}

const char * ServerMediaSubsession::trackId()
{
	if (fTrackNumber == 0) return NULL; // not yet in a ServerMediaSession
	
	if (fTrackId == NULL) {
		char buf[100];
		sprintf(buf, "track%d", fTrackNumber);
		fTrackId = strDup(buf);
	}
	return fTrackId;
}

void ServerMediaSubsession::startStream(unsigned clientSessionId, 
										void* streamToken, unsigned short& rtpSeqNum,
										unsigned& rtpTimestamp)
{
	StreamState* streamState = (StreamState*)streamToken; 
	MAPDestinations::iterator it;
	it = fDestinationsHashTable.find(clientSessionId);
	if(it == fDestinationsHashTable.end())
		return ;
	Destinations* destinations
		= (Destinations*)it->second;

		streamState->startPlaying(destinations);
		if (streamState->rtpSink() != NULL) {
			rtpSeqNum = streamState->rtpSink()->currentSeqNo();
			rtpTimestamp = streamState->rtpSink()->currentTimestamp();
		}
}

void ServerMediaSubsession::testScaleFactor(float& scale) {
	// default implementation: Support scale = 1 only
	scale = 1;
}

void ServerMediaSubsession::deleteStream(unsigned clientSessionId,
												 void*& streamToken) {
	// Look up (and remove) the destinations for this client session:
	MAPDestinations::iterator it;
	Destinations* destinations = NULL;
	it = fDestinationsHashTable.find(clientSessionId);
	if(it != fDestinationsHashTable.end())
	{
		destinations = it->second;
		fDestinationsHashTable.erase(it);
	}

	// Stop streaming to these destinations:
	StreamState* streamState = (StreamState*)streamToken; 
	if (streamState != NULL) streamState->endPlaying(destinations);
	
	// Delete the "StreamState" structure if it's no longer being used:
	if (streamState != NULL) 
	{
		delete streamState;
		streamToken = NULL;
		delete fSDPLines; fSDPLines = NULL;
	}
	// Finally, delete the destinations themselves:
	delete destinations;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -