(转)基于live555的流媒体代理转发服务器
对于并发量并不大而且对性能要求不是很高的流媒体传输模块,live555还是很好的选择,下面说一下我所实现的流媒体代理服务器(目前只能实现对H264单视频的转发)
代理转发主要分为对RTSP的转发与对RTP的转发(没有实现对rtcp的转发),尽量做到不破坏原有程序框架,所以还是要将整个代理过程融合于ServerMediaSubsession、Source、Sink的循环中,按照流程,RTSP OPTIONS不是必需进行转发,直接转到DESCRIBE的转发过程。
DECRIBE转发:在看过很多大型的流媒体服务器协议以后,会发现有一个相同点:前端设备在注册到流媒体服务器以后会将其自身的无论是实时资源还是录像资源都上报到流媒体服务器中集中管理,那么此处同理,在流媒体服务器上线(主动注册与保活)后改为主动向前端请求资源,到此处也就是发送DESCRIBE请求,我实现的代理服务器中,专门定义了一个类,继承自RTSPClient,向前端设备发送DESCRIBE请求,成功接收到携带SDP信息的反馈以后,根据SDP信息生成MediaSession,再执行其中每一个MediaSubsession的initiate(),这样获取由前端发送来数据的Source就已经准备就绪,同时,在每一个MediaSubsession建立以后,在对应流的ServerMediaSession中加入ServerMediaSubsession(此处ServerMediaSubsession继承自OnDemandServerMediaSubsession),这样就做到了一个ServerMediaSubsession对应一个MediaSubsession(这里一定要区分ServerMediaSubsession与MediaSubsession),两路会话的连接,下面就是客户端发起了DESCRIBE请求,转到RTSPServer::RTSPClientSession::handleCmd_DESCRIBE(),再转到ServerMediaSession::generateSDPDescription(),因为是转发,而且不能让客户端知道是转发,所以sdp信息在m字段前面的参数都是基于代理服务器本身,从m开始便是真正的媒体信息,原有的live555结构中,获取每一个track的sdpLine是由virtual char const* OnDemandServerMediaSubsession::sdpLines();得到,于是,我们可以重写此virtual函数,返回什么呢,返回的就是我们刚才传入的MediaSubsession的savedSDPLines()返回值。这样,SDP信息就可以在不破坏原有live555循环的基础上构造出来,并实现转发了。
SETUP转发:同DESCRIBE一样,原有框架已经形成,在收到SETUP请求以后,找RTSPServer::RTSPClientSession::handleCmd_SETUP(),再找到virtual void OnDemandServerMediaSubsession::getStreamParameters(),在原有live555循环中,此函数作用为建立本地接收端口,建立createNewSource与createNewSink,将数据传输循环中的各个部件都准备妥当,一旦收到Play命令就开始循环工作,那么同样重写此virtual函数,在重写中实现向前端发送SETUP请求,等待响应成功,再执行本地的SETUP,向前端发送SETUP实现可以同样由刚才传入的"RTSPClient继承"与MediaSubsession来实现发送命令,等待返回,再继续执行OnDemandServerMediaSubsession::getStreamParameters()实现本地的SETUP,如此一来,本地与远程的SETUP都已完成。
PLAY转发:同样,按照流程,重写OnDemandServerMediaSubsession::startStream()函数,发送Play请求到远程,等待返回,再执行本地的startStream(),本地与远程的Play都已完成。
上面已经将RTSP的转发实现,而且基本是在live555原有基础上进行,没有破坏原有框架结构,下面进行rtp的转发。
rtp的转发实现的重点是在建立source到sink的循环,重写OnDemandServerMediaSubsession::createNewStreamSource,与OnDemandServerMediaSubsession::createNewRTPSink,理想中的转发是能够实现收到rtp包不进行任何重组,直接发送即可,但我所实现的只能是由MediaSubsession中的readSource获取完整的一帧后,再交给rtpSink进行重新切片组装,具体到实现上,我实现了一个集成自H264VideoStreamFramer的类,并将MediaSubsession->readSource作为inputSource传入,重写doGetNextFrame(),从inputSource中获取完整一帧,copy到fTo,再交由createNewRTPSink()返回的H264VideoRTPSink进行重新组装并发送,后来考虑到此种做法,有利有弊,与不重新组装,直接发送,各有考虑。
如此,便实现了RTSP与RTP的转发功能,多有不妥,后续会持续改进,还望能够在留言中多多指正!
2012.3.23
有朋友问到rtcp的转发问题,这里阐述下我的理解:
转发RTCP实际的意义并不是很大,一个方面是rtcp控制的可能是两条不通的数据链路,对拥堵的控制总是在较小的链路基础上,牺牲太大;第二是作为服务器考虑,服务器通过双重身份将数据取来再发出去,控制协调应当完全自主掌控,如果后期在服务器中加入缓存机制实现抖动控制和拥堵控制,可以通过对进线与出线的rtcp控制达到控制作用,而且效果较好!
转自:http://www.easydarwin.org/article/Streaming/1.html
(转)基于live555的流媒体代理转发服务器的更多相关文章
- Node.js做的代理转发服务器
可以代理苹果ID服务器 const http = require('http'); const https = require('https'); const client = require('ht ...
- Nginx实现ssl一级、二级域名证书部署并用https访问代理转发服务器
1. 规划 域名 解析IP Nginx代理 htpps://www.devcult.com 47.88.10.155 htpps://auto.devcult.com 47.88.10.155 ...
- 基于live555的一个简单RTSP服务器
1,编译live555源码目录下的 BasicUsageEnvironment.groupsock.liveMedia.UsageEnvironment四个工程生成相应的库文件: 目录结构如下: 2, ...
- 用live555做流媒体转发服务器?
当我们看到这里,说明大家都有这样的一个想法:那就是如何用live555实现一个直播代理转发的流媒体服务器? 我们先不着急去讨论用live555实现流媒体转发的技术方法123,先从live555的整个架 ...
- 基于go手动写个转发代理服务
由于公司经常需要异地办公,在调试的时候需要用到内网环境,因此手动写了个代理转发服务器給兄弟们用:socks5proxy. 选型上,语言上就选择了Go,简单清晰,转发协议选择了socks5. SOCKS ...
- 嵌入式流媒体音视频服务器EasyIPCamera中live555发送性能优化点
EasyIPCamera流媒体服务器 今年EasyDarwin团队在给国内某最大的金融安防公司做技术咨询的时候,开发了一款适用于嵌入式IPCamera.NVR的RTSP流媒体服务器:EasyIPCam ...
- 基于Qt实现的TCP端口数据转发服务器
对于Qt,比较喜欢qt的sdk框架,我也是用于做一些工作中用到的工具软件,基于qt的sdk做起来也比较快: 一.概述 今天要说的这个tcp端口转发服务器,主要是用于将监听端口的数据转发到另外一个服务器 ...
- 基于Java Mina 通信框架的JT/T809转发服务器设计
Apache MINA 是 Apache 组织的一个开源项目,为开发高性能和高可用性的网络应用程序提供了非常便利的框架. 也是Java开发者的一个福利(.NET目前还没有类似封装的这么好的基础sock ...
- 基于 Red5 的流媒体服务器的搭建和应用
http://www.ibm.com/developerworks/cn/opensource/os-cn-Red5/ Red5 是一个采用 Java 开发的开源免费 Flash 流媒体服务器.Red ...
随机推荐
- unity3d 通过添加rigidBody来指明物体是动态的,以避免cache开销
unity3d 通过添加rigidBody来指明物体是动态的,以避免cache开销. 如果不添加rigidBody,则unity会认为它是静态的,会对物理计算进行cache,但如果此物体实际上tran ...
- Android开发9——Activity的启动模式
在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作.在Android中Activity的启动模式决定了Activity的启动运行方式. 一. ...
- php 多进程解决代码常驻内存的问题php 多进程解决代码常驻内存的问题
PHP不适合做常驻的SHELl进程,因为它没有专门的gc例程,也没有有效的内存管理途径. 如果用PHP做常驻SHELL,会经常被内存耗尽导致abort而unhappy. 而且,如果输入数据非法,而脚本 ...
- 使用jQuery的ajax同步请求吃过的亏
jQuery是一个非经常常使用的js库.甚至我们开发不论什么一个项目都首先把jquery导入进行.jQuery太过强大,使用起来非常方便.可是在使用的过程中也遇到过非常多坑.我在这里分享一下.避免大家 ...
- putty的复制和粘贴
putty在终端中的复制--->只要用左键选中即是复制了,千万不要按右键. 在windows下的复制后,在终端粘贴---> 只要右键即可.
- Disable Oracle Automatic Jobs
By default, Oracle will run some maintance jobs every night. If you don't want to run those jobs, yo ...
- .NET执行SQL插入时间的问题
错误描述: 一个项目,源码是BOSS给的,部署到网上了,运行没有问题,可是在本地运行,就会有问题,问题在于往一些表插入记录的时候,本地不管怎么样都插入不了,而网上就可以插入,都是相同的一份代码 解决: ...
- 执行 update操作的时候有报错 ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> show full processlist; #查看问题的线程!!!! 找到异常进程的ID 然后kill 掉: mysql> kill xxxxxxx; #xxxxxx是ID ...
- 黑客编程教程(十三)多线程DOS程序
DOS基本原理相信大家都已经很熟悉了,DOS工具大家也用的很熟悉.在群里 经常有人说什么时候去DOS什么东西. 现在我们就自己编写一个DOS工具. #include <winsock2.h> ...
- 李洪强iOS开发之-sql数据库的使用
一,创建工程 二: 导入头文件 三:导入 四: 数据库增删改查 //因为是结构体类型,所以用assign //1.创建数据库(保存路径) @property(nonatomic,assign)sqli ...