最近碰到一个非常棘手的问题,NVR通过ONVIF协议接入IPC进行录像,在录像时,会发现其中有个别IPC会出现录像断断续续的情况。这种情况很难复现,但是这种情况一旦出现,整个过程会一直持续很长时间,一般是直到重启RTSP Server。

通过苦逼型的大规模测试发现: 
1、IPC与NVR之间是通过RTP over TCP的方式传输数据(这个测试结果很简单就可以知道); 
2、开启1个客户端(通过RTP over TCP传输数据),打开rtsp流后,使用任务管理器强制结束。紧接着马上再开1个客户端,打开rtsp流,稍等一会儿(1分钟左右),后面开启的这个流居然自动断开了。这是一个必现的bug。(这里测试时,客户端可使用VLC,不过VLC默认情况下是使用RTP over UDP的方式传输数据。要使用 over TCP方式接收数据,需要通过以下设置: “工具”->“首选项”,打开首选项对话框后,“显示设置”处点击“全部”单选按钮,在左侧树形菜单依次展开:“输入/编解码器”->“去复用器”->“RTP/RTSP”,选中“使用RTP over RTSP(TCP)”);

通过调试发现: 
1、RTSPServer::createNew()的参数里面有个reclamationTestSeconds参数,该参数默认值为65; 
2、RTSPServer::createNewClientSession创建一个RTSPClientSession实例时,RTSPClientSession构造函数会调用noteLiveness,noteLiveness会设置一个延时任务,该任务的延时时间即为1中的reclamationTestSeconds(其值为秒,需要转换为微秒,回调为livenessTimeoutTask)。noteLiveness除了在构造的时候调用,在RTSP SERVER接收到一个RR数据包后,也会调用(RR其实也用作了一种心跳包了);
3、RTSPServer::incomingConnectionHandler()函数在异常结束上一个客户端后,再打开一个客户端打开rtsp流时,函数中accept返回的socket的值和上一个客户端的socket句柄值是相同的(概率在50%以上,如果这里返回的socket句柄不同,这个bug就不会复现了);

通过以上3条,如果你读过live555的代码,应该知道是怎么回事了。上面2中设置的延时任务的回调函数livenessTimeoutTask,只干了一件事件,就是delete掉RTSPServer::createNewClientSession创建的实例。查看RTSPClientSession的析构函数,发现其居然把RTPInterface::fTCPStreams链表中对应的节点给删掉了。而RTP和RTCP包是通过RTSPServer::sendPacket发送到各个客户端的,在发送的时候,就是直接对RTPInterface::fTCPStreams保存的地址(即socket句柄)进行发送。如果RTPInterface::fTCPStreams中的socket清除了,客户端自然不会再接收到数据,出现断线已经是必然了。至此,断线的原因终于明了:即异常结束掉一个客户端,在65秒内(默认值为65),再开启一个客户端打开流,第二次打开的这条流会在65秒内必然断开,如果客户端有断线自动重连的功能,那么,断断续续的情况就出现了。

通过测试还发现,通过RTP over UDP的方式接收数据时,异常结束客户端,RTSP Server居然会接收到一条TEARDOWN消息,而在TEARDOWN消息的处理过程中,会清理掉client session和RTSP链接,即使用RTP OVER UDP的方式传输数据时,异常结束客户端,并不会出现上述bug,这个让我困惑不少,如果哪位知道,请告诉我原因。

其实解决这个问题,只需要注释掉livenessTimeoutTask中的delete语句就行了,不过这不是最终解决方案,因为会造成内存泄漏,最好的方式是使用SESSION ID和目标地址进行关联,在调用StreamState::endPlaying删除目的地址时,如果SESSION ID不对应,不从链表中清除掉对应的节点就行了。

转自:http://m.blog.csdn.net/blog/zxwangyun/40541023

(转)live555 RTSP Server RTP over TCP BUG的更多相关文章

  1. 【视频开发】RTSP SERVER(基于live555)详细设计

    /* *本文基于LIVE555的嵌入式的RTSP流媒体服务器一个设计文档,个中细节现剖于此,有需者可参考指正,同时也方便后期自己查阅.(本版本是基于2011年的live555) 作者:llf_17@q ...

  2. Live555研究之三 RTSP Server处理请求

    RTSP Server会不断用select查询是否有socket连接,如果有则在(*handler->handlerProc)(handler->clientData, resultCon ...

  3. 一个RTSP/RTP over TCP 的丢包引起的问题

    背景知识:可以查看https://www.cnblogs.com/lidabo/p/4483497.html RTSP/RTP over TCP TCP承载RTSP/RTP   When you us ...

  4. RTSP - RTP over TCP

    RTP over RTSP(TCP)(一)   RTP over RTSP包混合发送的解决办法   RTSP - RTP over TCP     To use TCP communication, ...

  5. 使用live555 在linux下搭建 rtsp server

    系统环境 Debian 7 x64  / centos 7 x64  都可以 首先去下载源码 http://www.live555.com/liveMedia/public/live555-lates ...

  6. RTSP HTTP RTP RTCP

    RTSP简介 RTSP(Real Time Streaming Protocol)是由Real Network和Netscape共同提出的如何有效地在IP网络上传输流媒体数据的应用层协议.RTSP对流 ...

  7. Managed Media Aggregation using Rtsp and Rtp

    his article was written almost 2 years ago, it's content may not reflect the latest state of the cod ...

  8. live555 RTSP推送到Darwin出现404错误的解决

    我们将Darwin部署到公网,接收live555 RTSP/RTP推送的时候,经常会出现在SETUP步骤Darwin返回404错误,经过查找原因,主要是Darwin对live555推送的sdp信息中的 ...

  9. 让EasyDarwin只支持RTP over TCP传输

    我们经常需要EasyDarwin服务器支持公网流媒体传输,但很多时候,播放器默认都是通过RTP over UDP的形式在RTSP SETUP中请求,往往都以在内网接收不到UDP数据失败结束,那么我们如 ...

随机推荐

  1. 在vue-cli搭建的项目中在后台mock接口中支持req.body和req.cookies

    在<vue-cli搭建的项目中增加后台mock接口>中实现了后台mock,但是前端post的t数据都要在mock的后台接口中使用req的接收数据事件获取http协议body中的数据. re ...

  2. linux命令(46):批量更改文件后缀,文件名

    linux shell 1.要将所有 jpeg的后缀名图片文件修改为 jpg文件. rename .jpeg .jpg *.jpeg

  3. python(39):argparse的用法,从外部传入指定参数

    直接上例子: # /usr/bin/env python # coding=utf8 import os import argparse import logging import sys FORMA ...

  4. 连接web端,mysql,返回乱码解决

    参考:http://yushan.iteye.com/blog/265019

  5. Quo JS多种触摸手势轻量级JavaScript库

    http://www.uedsc.com/quo-js.html http://quojs.tapquo.com/

  6. form的验证包括手机号邮箱等等

    $(function(){    var checkedByVerifyCode = false;    var checkMobieCode = false;    var checkedMobil ...

  7. Lintcode: Subarray Sum 解题报告

    Subarray Sum 原题链接:http://lintcode.com/zh-cn/problem/subarray-sum/# Given an integer array, find a su ...

  8. 【神经网络】LSTM 网络

      Long Short Term 网络—— 一般就叫做 LSTM ——是一种 RNN 特殊的类型,可以学习长期依赖信息.LSTM 由Hochreiter & Schmidhuber (199 ...

  9. 实现基于最近邻内插和双线性内插的图像缩放C++实现

    平时我们写图像处理的代码时,如果需要缩放图片,我们都是直接调用图像库的resize函数来完成图像的缩放.作为一个机器视觉或者图像处理算法的工作者,图像缩放代码的实现应该是必须掌握的.在众多图像缩放算法 ...

  10. 使用 libvirt创建和管理KVM虚拟机

      1. libvirt介绍    Libvirt是一个软件集合,便于使用者管理虚拟机和其他虚拟化功能,比如存储和网络接口管理等等.Libvirt概括起来包括一个API库.一个 daemon(libv ...