live555作为RTSP流媒体服务器时Server端多track而客户端仅请求一个track,当客户端关闭时没有关闭流的问题解决方案

当我们使用live555作为流媒体服务器时,某个通道对应的所有客户端断开后, 不能正常回调关闭。
某一通道同时支持视频和音频输出, 即video和audio两个track
VLC和EasyPlayer播放库来中的RTSPClient则都会请求(所以不存在问题);
而某些客户端则只请求了一个track, 比如video;

此时再关闭,会有两种情况:
在VLC或自有播放库来断开连接时,都会正常回调关闭;
在仅请求了video的客户端断开连接时, 一定不会回调关闭;

分析问题:

在RTSPClient断开时,一定会调用RTSPServer::stopTCPStreamingOnSocket, 当流为RTP Over TCP时, 则会调用deleteStreamByTrack;
在deleteStreamByTrack函数中, 是一个for循环,检测fStreamStates的subsession, 因为sdp中存在video和audio, fNumStreamStates的值为2, 而客户端只请求了video,所以在以下的代码中,判断不成立:

  Boolean noSubsessionsRemain = True;
  for (unsigned i = 0; i < fNumStreamStates; ++i) {
    if (fStreamStates[i].subsession != NULL) {
      noSubsessionsRemain = False;		//因为存在video和audio, 所以此处条件会成立
      break;
    }
  }

因为noSubsessionsRemain为False, 所以下面的代码不会被执行;

if (noSubsessionsRemain) delete this;

顺便说一下, delete this是删除RTSPClientSession, 在ClientSession的析构函数中,会减少引用计数,如果计数为0, 则删除fOurServerMediaSession;

解决问题:

在RTSPClientConnection中增加一个计数变量, 用于记录客户端请求的track个数, 然后在deleteStreamByTrack中递减,如果为0, 则使上面的noSubsessionsRemain为True;
修改如下:

	//在RTSPClientConnection的声明中,增加以下两个变量
	int	clientRequestTrackNum;		//for rtp over tcp
	char fClientSessionIdStr[16];	//for rtp over udp
	
	void RTSPServer::RTSPClientSession
	::handleCmd_SETUP(UsageEnvironment *pEnv, RTSPServer::RTSPClientConnection* ourClientConnection,
			  char const* urlPreSuffix, char const* urlSuffix, char const* fullRequestStr) {
			  
			  ......
			  
			  
	    if (streamingMode == RTP_TCP) {
	      // Note that we'll be streaming over the RTSP TCP connection:
	      fStreamStates[trackNum].tcpSocketNum = ourClientConnection->fClientOutputSocket;
	      fOurRTSPServer.noteTCPStreamingOnSocket(fStreamStates[trackNum].tcpSocketNum, this, trackNum);

				//此处增加计数
		  	ourClientConnection->clientRequestTrackNum ++;
	    }		
	    
	    ......
	}		

修改deleteStreamByTrack的声明和实现:

	void deleteStreamByTrack(UsageEnvironment *pEnv, unsigned trackNum, Boolean lockFlag, int *clientTrackNum);

	void RTSPServer::RTSPClientSession::deleteStreamByTrack(UsageEnvironment *pEnv, unsigned trackNum, Boolean lockFlag, int *clientTrackNum) {

		lockClientFlag = lockFlag;

	  if (trackNum >= fNumStreamStates) return; // sanity check; shouldn't happen
	  if (fStreamStates[trackNum].subsession != NULL) {
	    fStreamStates[trackNum].subsession->deleteStream(fOurSessionId, fStreamStates[trackNum].streamToken);
	    fStreamStates[trackNum].subsession = NULL;
	  }
	  
	  // Optimization: If all subsessions have now been deleted, then we can delete ourself now:
	  Boolean noSubsessionsRemain = True;
	  for (unsigned i = 0; i < fNumStreamStates; ++i) {
	    if (fStreamStates[i].subsession != NULL) {
	      noSubsessionsRemain = False;
	      break;
	    }
	  }

	  if (NULL!=clientTrackNum)
	  {
		  if (*clientTrackNum > 0)		*clientTrackNum -= 1;
		  if (*clientTrackNum == 0)		noSubsessionsRemain = True;
	  }

	  if (noSubsessionsRemain) delete this;
	}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值