📄 servermediasubsession.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 + -