设为首页 收藏本站
查看: 986|回复: 0

[经验分享] rtsp server(live555)详细设计

[复制链接]

尚未签到

发表于 2018-10-18 13:12:25 | 显示全部楼层 |阅读模式
  /*
  *本文基于LIVE555的嵌入式的RTSP流媒体服务器一个设计文档,个中细节现剖于此,有需者可参考指正,同时也方便后期自己查阅。(本版本是基于2011年的live555)
  作者:llf_17@qq.com
  */
  RTSP SERVER(基于live555)详细设计
  这个server的最终情况如下:
  性能:D1数据时:
  1.      8路全开udp
  PID USER     PR  NI  VIRT RES  SHR S %CPU %MEM    TIME+ COMMAND
  1175root      20   0 65712 23m 3112 R 29.0 34.5 285:13.05 dvrapp_SN6108
  2.      8路全开tcp
  PID USER     PR  NI  VIRT RES  SHR S %CPU %MEM    TIME+ COMMAND
  1175root      20   0 65612 23m 3112 R 31.0 34.4 289:03.86 dvrapp_SN6108
  文件:
  静态库大小:Live555.a  1,585KB
  文件个数:  150左右
  

  目录
  1.代码移植... 3
  1.1代码获取... 3
  1.2文件初步裁剪... 3
  1.3修改Makefile. 3
  1.4将live555生成的静态库链接到我司的可执行程序中... 3
  2.功能添加... 4
  2.1 数据的输入... 4
  2.2实时视频(H264)的输入和输出... 5
  2.3实时音频(G711.a)的输入和输出... 6
  2.4 H264视频离散nal单元输入的实现... 6
  2.5单播的实现... 7
  2.6多路连接的实现... 7
  2.7最大连接数的限制... 9
  2.8服务端主动断开连接的实现... 9
  2.9 sdp信息的添加修改... 10
  2.10重定向的实现... 10
  3. 代码裁剪... 11
  4. 效率优化... 12
  4.1Ring buffer双队列的修改... 12
  4.2内存拷贝的去除及socketwritev 的实现... 13
  5. 部分函数说明:... 16
  6. 部分实验结果... 17
  
1.代码移植
  将live555代码移植到我司嵌入式平台上。
1.1代码获取
  http://www.live555.com/liveMedia/public/
  本次移植使用的版本是2011.12.23.
1.2文件初步裁剪
  Live555为跨平台库,本移移植旨在arm linux上运行,所以需先裁剪掉其它无关文件。
  a.删除之前先生成用于linux的makefile.进入live文件夹,运行./genMakefiles linux.此时生成了用于linux的Makefile.
  b.删除冗余文件和文件夹。
  每个文件夹下只保留*.cpp,*.hh, *.c, *.h, Makefile.其余全部删除。
  删除文件夹:WindowsAudioInputDevice和mediaServer
1.3修改Makefile
  Makefile变量主要做以下修改:
  C_COMPILER =              arm-hismall-linux-gcc
  CPLUSPLUS_COMPILER =    arm-hismall-linux-g++
  LINK =                    arm-hismall-linux-g++-o
  LINK_OPTS =          -L.-lpthread
  C_FLAGS =              $(COMPILE_OPTS)     $(CFLAGSARM)
  CPLUSPLUS_FLAGS =    $(COMPILE_OPTS)$(CFLAGSARM)
1.4将live555生成的静态库链接到我司的可执行程序中
  如:dvrapp_sn6108
  裁剪到此时的Live555编译时会生成所有的库,不可能将所有库链进可执行程序中。我司只用到了视频:H264,音频 G711.a.其余不用。故只需将这几个有关库链接进即可。
  我司链接静态库到可执行程序的做法是,先成一个xx.a,然后在生成可执行程序时,链接所有.a文件。所以我们这里只需将需要的.o文件装进live555.a即可。
  具体做法:在live555文件夹下新建文件夹liveLib用于存放其它文件生成的.a. 此文件夹用于生成live555.a最终库。(将所有.a先打散成.o,再合成一个live555.a).每个文件夹下在生成.a时都拷贝一份.a到liveLib中。最后将生成的live555.a拷贝到master\LIB\ARM\SN6108中。可执行程序链接时在此文件夹下可找到live555.a。
2.功能添加
  Live555源码的功能要用到我司具体项目中还需做一定的修改,不是拿来就能用的。
  原本对于开源项目,尤其是c++项目,最好不要改动原有的类,所以修改应该是继承父类,在子类中修改。这样有利于代码的升级,和维护。但是由于考虑到c++的继承的层数以及虚函数的运行时绑定对性能的影响,以及编译出文件的大小,所以本修改中只对一部分类作了继承,另一些直接在原有类中添加新方法。
2.1 数据的输入
  数据从ringbuffer到server模块的传输,使用了通知机制,即当ringbuf有数据时,数据发出通道,告知某一通道有数据可用,则server在需要的时候会来这个通道来取数据。

  通知机制主要由以下函数实现。
  void signalNewFrameData(int mediaType, int chanel,int trans_mode,int buf_len)
  signalNewFrameData为一个全局函数,可被外部线程调用(注意,整个live555是一个单线程程序)。signalnewFrameData会调用virtual void triggerEvent(EventTriggerId eventTriggerId, void*clientData = NULL), 这个函数共两个参数,一个是触发的事件id,另一个是此id对应的事件处理函数所在的类实例指针,这里具体是各个输入的videoSource和audioSource类实例指针。
  数据的写入ringbuffer由以下函数实现:
  在write_unicast_data_live里(只用于单播),每当一个数据到来后,先判断是音频还是视频,然后再装入各自对应的ringbuffer,接着调用 signalnewFrameData通知相应的server. 通知时刻落在server刚好需要数据的时刻区间间的概率较小,大部分情况是(经实验证明了的):server正在处理其它数据; 或已经取完数据,正在等下次取数据时刻的到来(此时可能正停留在Eventloop 里的sigleStep的select中)。所以通知后都会把事件记入一个bitmask类型的变量fTriggersAwaitingHandling(最多可累计挂入32个待处理事件)中, 然后在select结束后,再处理每个TriggerNum所对应的事件(调用Source中的deliverFrame将数据向后传送)。处理完一个事件,则将fTriggersAwaitingHandling中对应的bitmask位清0,singleStep每一次循环中TriggerEvent只处理一个事件(如有未处理完事件,等下一循环再处理)。
2.2实时视频(H264)的输入和输出
  Live555提供的示例里面有直接读文件的类和使用方法,但没有实时输入的类及其实现。
  Live555中数据流基本路线是:
  SourceàFilter1àFilter2…àSink
  Filter可能有多个,也可能一个也没有。对于h264,filter有两个,对于音频g711.a,实现中则没有Filter.
  本设计具体实现视频实时输入方法如下:
  1.视频输入
  在live555中,输入为Source类,输出为 Sink类。中间处理环节类称为Filter.
  SNDeviceSource类继承于FramedSource,用于实时输入h264视频。该类的实现参考了DeviceSource。
  在SNDeviceSource::deliverFrame()中实现数据的输入。Memmove 将数据拷贝到fTo.(最后优化后已经改为传指针了,没有了内存拷贝).
  2 .Filter
  对于H264视频Source不是直接到Sink, 而是经过如下:
  SNDeviceSourceàH264VideoStreamDiscreteFrameràH264FUAFragmenteràH264VideoRTPSink
  中间两个类称为Filter,是对视频数据的进一步处理。
  H264VideoStreamDiscreteFramer继承于H264VideoStreamFramer, H264VideoStreamFramer主要是提取sps, pps。H264VideoStreamDiscreteFramer 主要是用于输入 离散的NAL单元,H264FUAFragmenter主要是对H264nal进行分片打包,根据rfc3984中FU-A规则进行分片打包。
  3 .视频输出
  H264VideoRTPSink为原有类, 实现了h264 rtp包的输出.
  视频的打包和发送操作都在H264VideoRTPSink的父类multiFramedRTPSink中.其打包发送的流程如下:
  sendNextàbuildandSendPacketàpackFrameàgetnextFrameà…àafterGettingFrameàsendPacketIfnessaryàscheduleDelayedTask àsendNextà。。。
  buildandSendPacket会将rtp包头打好(timestamps and sequence num先预留,等取到帧数据后再填充)。
  packFrame即将帧数据往rtp包头后面挂。所以其任务就是要取得帧数据,所以调用getnextFrame来从上一游来获取帧数据。对于h264来说,它的上一级由2.12可看出是H264FUAFragmenter, 这个类会将帧数据分好片(

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-623227-1-1.html 上篇帖子: srs(simple Rtmp Server )的一些说明 下篇帖子: 3、Nginx关于server块和location块的配置
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表