live555的rtsp代理ProxyServerMediaSession改进

live555的rtsp代理ProxyServerMediaSession改进

live555中的ProxyServerMediaSession是一个为后端的网络摄像头或其他设备做rtsp代理的类

实际应用中有几个地方需要注意

1 代理过程中,从第一次客户端连接,proxy就会开始从后端rtsp服务器拉数据,在所有客户端断开连接后,proxy发送rtsp的pause(而不是teardown)命令给后端rtsp服务器,从而继续从后端获取数据,一直占用带宽。

2 live555使用中,需要根据实际情况修改一些值,预防数据包被人为的网络切断(truncation)而发生花屏问题,

 例如默认值对中低码率的视频也许正常,遇到1080p的时候就出现问题。

  2.1  OutPacketBuffer::maxSize (过小时live555会在运行时有警告提示,帧数据丢失)

  2.2  接收和发送的socket 缓冲区大小,可以通过调用 increaseReceiveBufferTo和increaseSendBufferTo接口修改


这里说一下参考的解决方法:

1 解决无客户端连接时不从后端接收流媒体数据:

在ProxyRtspClient添加代码

 
TaskToken fProxyResetCommandTask; //所有客户端断开后执行

static void ProxyRTSPClient::proxyReset(void* clientData){
	((ProxyRTSPClient*)clientData)->handleProxyReset();
}

void ProxyRTSPClient::handleProxyReset(){
	continueAfterLivenessCommand(-1,False);
	envir().taskScheduler().unscheduleDelayedTask(fProxyResetCommandTask);
	fProxyResetCommandTask = NULL;
}

//在proxyRtspClient 构造函数中初始化fProxyResetCommandTask

fProxyResetCommandTask = NULL;

修改ProxyServerMediaSubsession::closeStreamSource(FramedSource* inputSource)函数

void ProxyServerMediaSubsession::closeStreamSource(FramedSource* inputSource) {
  if (verbosityLevel() > 0) {
    envir() << *this << "::closeStreamSource()\n";
  }
  // Because there's only one input source for this 'subsession' (regardless of how many downstream clients are proxying it),
  // we don't close the input source here.  (Instead, we wait until *this* object gets deleted.)
  // However, because (as evidenced by this function having been called) we no longer have any clients accessing the stream,
  // then we "PAUSE" the downstream proxied stream, until a new client arrives:
  if (fHaveSetupStream) {
    ProxyServerMediaSession* const sms = (ProxyServerMediaSession*)fParentSession;
    ProxyRTSPClient* const proxyRTSPClient = sms->fProxyRTSPClient;
    if (proxyRTSPClient->fLastCommandWasPLAY) { // so that we send only one "PAUSE"; not one for each subsession
      //proxyRTSPClient->sendPauseCommand(fClientMediaSubsession.parentSession(), NULL, proxyRTSPClient->auth());

	  proxyRTSPClient->sendTeardownCommand(fClientMediaSubsession.parentSession(), NULL, proxyRTSPClient->auth());

	  proxyRTSPClient->fProxyResetCommandTask = envir().taskScheduler().scheduleDelayedTask(0,ProxyRTSPClient::proxyReset,proxyRTSPClient);
	  proxyRTSPClient->fLastCommandWasPLAY = False;
    }	
	fHaveSetupStream = False;
  }
}

2 设置缓冲大小

2.1 OutPacketBuffer::maxSize 是个静态变量,程序开始便可以设置。(这个就不用多说了吧,大家水平都这么高了)

     比如OutPacketBuffer::maxSize = 2000000; 就行

2.2  接收时的socket 缓冲设置,修改ProxyServerMediaSubsession::createNewStreamSource函数,加上蓝色部分

FramedSource* ProxyServerMediaSubsession::createNewStreamSource(unsigned clientSessionId, unsigned& estBitrate) {
  ProxyServerMediaSession* const sms = (ProxyServerMediaSession*)fParentSession;

  if (verbosityLevel() > 0) {
    envir() << *this << "::createNewStreamSource(session id " << clientSessionId << ")\n";
  }

  // If we haven't yet created a data source from our 'media subsession' object, initiate() it to do so:
  if (fClientMediaSubsession.readSource() == NULL) {
    fClientMediaSubsession.receiveRawMP3ADUs(); // hack for MPA-ROBUST streams
    fClientMediaSubsession.receiveRawJPEGFrames(); // hack for proxying JPEG/RTP streams. (Don't do this if we're transcoding.)
    fClientMediaSubsession.initiate();
	<span style="color:#330099;">if(!strcmp(fClientMediaSubsession.mediumName(),"video"))
	increaseReceiveBufferTo(envir(),fClientMediaSubsession.rtpSource()->RTPgs()->socketNum(),2000000);</span>
    if (verbosityLevel() > 0) {

2.3修改发送的缓冲大小,在OnDemandServerMediaSubsession::getStreamParameters函数中大小即可修改

void OnDemandServerMediaSubsession
::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 (rtpGroupsock != NULL) {
	// Try to use a big send buffer for RTP -  at least 0.1 second of
	// specified bandwidth and at least 50 KB
	unsigned rtpBufSize = streamBitrate * 25 / 2; // 1 kbps * 0.1 s = 12.5 bytes
	<span style="color:#000099;">if (rtpBufSize < 50 * 1024) rtpBufSize = 2000 * 1024; //50 * 1024;</span>
	increaseSendBufferTo(envir(), rtpGroupsock->socketNum(), rtpBufSize);
      }

...
}


你可能感兴趣的:(live555的rtsp代理ProxyServerMediaSession改进)