(转)基于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 ...
随机推荐
- Django修改用户名密码的方法
1.python manage.py shell 2.from django.contrib.auth.models import User 3.user=User.objects.get(usern ...
- [k8s]prometheus+grafana监控node和mysql(普罗/grafana均vm安装)
https://github.com/prometheus/prometheus Architecture overview Prometheus Server Prometheus Server 负 ...
- 怎样设置linux中Tab键的宽度(可永久设置)
和我的上篇文章一样,能够设置当前用户的Tab键宽度.也能够设置全部用户的Tab键宽度 一.仅设置当前用户的Tab键宽度 输入命令:vim ~/.vimrc 然后:set tabstop=4 //我 ...
- 基于jquery的邮箱输入联想插件开发
js代码: /*create by code_bunny 20140701 973295131@qq.com https://github.com/OOP-Code-Bunny */ (functio ...
- jsoup解析网页出现转义符问题
https://www.oschina.net/question/996055_136438 *************************************** 我要解析这个网页 htt ...
- python 高阶函数 map lambda filter等
map 描述 map() 会根据提供的函数对指定序列做映射. 第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表. ...
- 获取Django中model字段名 字段的verbose_name
obj._meta.fields 为关键 obj为model类 推荐使用函数 from django.apps import apps def getmodelfield(appname,modeln ...
- win7语言设置为英语
控制面板,地区和语言 可以设置格式 键盘和语言 安装显示的语言 选择“可选更新包”,选择语言的语言
- 一款基于jquery的手风琴图片展示效果
今天要给大家分享一款基于jquery的手风琴图片展示效果.这款图片的展示效果鼠标经过前是灰色的,当鼠标经过时图片变大且变为彩色.效果图如下: 在线预览 源码下载 实现的代码. html代码: &l ...
- Springmvc mvc:exclude-mapping不拦截 无效
最近在使用ssm框架搭建一个后台,需要判断每个请求都判断是否登录,未登录跳转到登录页面, 使用发现 mvc:exclude-mapping 不拦截,发现,怎么都无效,依然是进行拦截.查了很多资料,总算 ...