📄 ondemandservermediasubsession.cpp
字号:
unsigned& rtpTimestamp) { StreamState* streamState = (StreamState*)streamToken; Destinations* destinations = (Destinations*)(fDestinationsHashTable->Lookup((char const*)clientSessionId)); if (streamState != NULL) { streamState->startPlaying(destinations); if (streamState->rtpSink() != NULL) { rtpSeqNum = streamState->rtpSink()->currentSeqNo(); rtpTimestamp = streamState->rtpSink()->currentTimestamp(); } }}void OnDemandServerMediaSubsession::pauseStream(unsigned /*clientSessionId*/, void* streamToken) { // Pausing isn't allowed if multiple clients are receiving data from // the same source: if (fReuseFirstSource) return; StreamState* streamState = (StreamState*)streamToken; if (streamState != NULL) streamState->pause();}void OnDemandServerMediaSubsession::seekStream(unsigned /*clientSessionId*/, void* streamToken, float seekNPT) { // Seeking isn't allowed if multiple clients are receiving data from // the same source: if (fReuseFirstSource) return; StreamState* streamState = (StreamState*)streamToken; if (streamState != NULL && streamState->mediaSource() != NULL) { seekStreamSource(streamState->mediaSource(), seekNPT); }}void OnDemandServerMediaSubsession::setStreamScale(unsigned /*clientSessionId*/, void* streamToken, float scale) { // Changing the scale factor isn't allowed if multiple clients are receiving data // from the same source: if (fReuseFirstSource) return; StreamState* streamState = (StreamState*)streamToken; if (streamState != NULL && streamState->mediaSource() != NULL) { setStreamSourceScale(streamState->mediaSource(), scale); }}void OnDemandServerMediaSubsession::deleteStream(unsigned clientSessionId, void*& streamToken) { // Look up (and remove) the destinations for this client session: Destinations* destinations = (Destinations*)(fDestinationsHashTable->Lookup((char const*)clientSessionId)); if (destinations != NULL) { fDestinationsHashTable->Remove((char const*)clientSessionId); } // 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 && streamState->referenceCount() > 0) { --streamState->referenceCount(); if (streamState->referenceCount() == 0) { delete streamState; if (fLastStreamToken == streamToken) fLastStreamToken = NULL; streamToken = NULL; } } // Finally, delete the destinations themselves: delete destinations;}char const* OnDemandServerMediaSubsession::getAuxSDPLine(RTPSink* rtpSink, FramedSource* /*inputSource*/) { // Default implementation: return rtpSink == NULL ? NULL : rtpSink->auxSDPLine();}void OnDemandServerMediaSubsession::seekStreamSource(FramedSource* /*inputSource*/, float /*seekNPT*/) { // Default implementation: Do nothing}void OnDemandServerMediaSubsession::setStreamSourceScale(FramedSource* /*inputSource*/, float /*scale*/) { // Default implementation: Do nothing}void OnDemandServerMediaSubsession::setSDPLinesFromRTPSink(RTPSink* rtpSink, FramedSource* inputSource) { if (rtpSink == NULL) return; char const* mediaType = rtpSink->sdpMediaType(); unsigned char rtpPayloadType = rtpSink->rtpPayloadType(); struct in_addr serverAddrForSDP; serverAddrForSDP.s_addr = fServerAddressForSDP; char* const ipAddressStr = strDup(our_inet_ntoa(serverAddrForSDP)); char* rtpmapLine = rtpSink->rtpmapLine(); char const* rangeLine = rangeSDPLine(); char const* auxSDPLine = getAuxSDPLine(rtpSink, inputSource); if (auxSDPLine == NULL) auxSDPLine = ""; 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;}////////// StreamState implementation //////////static void afterPlayingStreamState(void* clientData) { // When the input stream ends, keep it alive, in case the client wants to // subsequently re-play the stream starting from somewhere other than the end. // If, instead, you want to terminate the stream, enable the following code.#if 0 StreamState* streamState = (StreamState*)clientData; streamState->reclaim();#endif}StreamState::StreamState(Port const& serverRTPPort, Port const& serverRTCPPort, RTPSink* rtpSink, BasicUDPSink* udpSink, unsigned totalBW, char* CNAME, FramedSource* mediaSource, Groupsock* rtpGS, Groupsock* rtcpGS) : fAreCurrentlyPlaying(False), fReferenceCount(1), fServerRTPPort(serverRTPPort), fServerRTCPPort(serverRTCPPort), fRTPSink(rtpSink), fUDPSink(udpSink), fTotalBW(totalBW), fCNAME(CNAME), fRTCPInstance(NULL) /* created later */, fMediaSource(mediaSource), fRTPgs(rtpGS), fRTCPgs(rtcpGS) {} StreamState::~StreamState() { reclaim();}void StreamState::startPlaying(Destinations* dests) { if (dests == NULL) return; if (!fAreCurrentlyPlaying && fMediaSource != NULL) { if (fRTPSink != NULL) { fRTPSink->startPlaying(*fMediaSource, afterPlayingStreamState, this); fAreCurrentlyPlaying = True; } else if (fUDPSink != NULL) { fUDPSink->startPlaying(*fMediaSource, afterPlayingStreamState, this); fAreCurrentlyPlaying = True; } } if (fRTCPInstance == NULL && fRTPSink != NULL) { // Create (and start) a 'RTCP instance' for this RTP sink: fRTCPInstance = RTCPInstance::createNew(fRTPSink->envir(), fRTCPgs, fTotalBW, (unsigned char*)fCNAME, fRTPSink, NULL /* we're a server */); // Note: This starts RTCP running automatically } if (dests->isTCP) { // Change RTP and RTCP to use the TCP socket instead of UDP: if (fRTPSink != NULL) { fRTPSink->addStreamSocket(dests->tcpSocketNum, dests->rtpChannelId); } if (fRTCPInstance != NULL) { fRTCPInstance->addStreamSocket(dests->tcpSocketNum, dests->rtcpChannelId); } } else { // Tell the RTP and RTCP 'groupsocks' about this destination // (in case they don't already have it): if (fRTPgs != NULL) fRTPgs->addDestination(dests->addr, dests->rtpPort); if (fRTCPgs != NULL) fRTCPgs->addDestination(dests->addr, dests->rtcpPort); }}void StreamState::pause() { if (fRTPSink != NULL) fRTPSink->stopPlaying(); if (fUDPSink != NULL) fUDPSink->stopPlaying(); fAreCurrentlyPlaying = False;}void StreamState::endPlaying(Destinations* dests) { if (dests->isTCP) { if (fRTPSink != NULL) { fRTPSink->removeStreamSocket(dests->tcpSocketNum, dests->rtpChannelId); } if (fRTCPInstance != NULL) { fRTCPInstance->removeStreamSocket(dests->tcpSocketNum, dests->rtcpChannelId); } } else { // Tell the RTP and RTCP 'groupsocks' to stop using these destinations: if (fRTPgs != NULL) fRTPgs->removeDestination(dests->addr, dests->rtpPort); if (fRTCPgs != NULL) fRTCPgs->removeDestination(dests->addr, dests->rtcpPort); }}void StreamState::reclaim() { // Delete allocated media objects Medium::close(fRTCPInstance) /* will send a RTCP BYE */; fRTCPInstance = NULL; Medium::close(fRTPSink); fRTPSink = NULL; Medium::close(fUDPSink); fUDPSink = NULL; Medium::close(fMediaSource); fMediaSource = NULL; delete fRTPgs; fRTPgs = NULL; delete fRTCPgs; fRTCPgs = NULL; fReferenceCount = 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -