live555学习ing

参考网上文章调试了一个例子,实现从摄像头IPC通过rtsp获取码流转发到EasyDarwin服务器功能
参考文章:https://blog.youkuaiyun.com/xiejiashu/article/details/34434669

使用testRTSPClient例子编译了一个rtspclient,从EasyDarwin服务器获取码流功能

记录下相关信息:

使用的live555版本是2015年的,因为最新的版本去掉了DarwinInjector.cpp,不支持对Darwin的支持,后面有必要在考虑整合到最新版本的live555中

下载了文章中的代码,把转发IPC的代码合并到自己的工程中,由于live555版本的区别,编译不过,用比较工具查看代码,然后把ProxyServerMediaSubsession类的声明从ProxyServerMediaSession.cpp移到了ProxyServerMediaSession.hh中,同时增加了两个函数,编译通过,增加的函数是:

  char const* mediumName() const { return fClientMediaSubsession.mediumName(); }
  unsigned char rtpPayloadFormat() const { return fClientMediaSubsession.rtpPayloadFormat(); }

修改缓冲大小:

main函数中需添加
OutPacketBuffer::maxSize = 800000;

创建live555基本环境,所有live555程序必须的:

scheduler = BasicTaskScheduler::createNew();
env = BasicUsageEnvironment::createNew(*scheduler);

用ProxyServerMediaSession类实现连接IPC码流功能

sms = ProxyServerMediaSession::createNew(*env, NULL, src);

此调用会创建跟IPC的rtps连接
类的继承关系:

ProxyServerMediaSession->ServerMediaSession->Medium

ProxyServerMediaSession的构造函数会调用defaultCreateNewProxyRTSPClientFunc创建ProxyRTSPClient,ProxyRTSPClient类继承关系:

ProxyRTSPClient->RTSPClient -> Mediu
ProxyServerMediaSubsession -> OnDemandServerMediaSubsession -> ServerMediaSubsession - >Medium

创建ProxyRTSPClient的时候实际调用到的是构造函数,之后调用ProxyRTSPClient::sendDESCRIBE,最终调用到RTSPClient::sendDescribeCommand,发送DESCRIBE命令。

DESCRIBE发送成功后调用,用sdp信息调顺序:

 ProxyRTSPClient::continueAfterDESCRIBE
 ProxyServerMediaSession::continueAfterDESCRIBE 
 MediaSession::createNew创建  MediaSession对象
 MediaSession::initializeWithSDP用sdp初始化MediaSession对象
 createNewMediaSubsession(),创建MediaSubsession对象,可能创建多个,如:有音频和视频,会创建两个,根据SDP信息初始化MediaSubsession对象相关信息,添加到MediaSession对象的链表fSubsessionsHead中
 ProxyServerMediaSubsession,根据MediaSubsession创建ProxyServerMediaSubsession对象,添加到ServerMediaSession的链表中

创建source:
用ProxyServerMediaSubsession对象调用ProxyServerMediaSubsession::createNewStreamSource分别创建音视频source,是FramedSource类型对象

RTSPClient::sendSetupCommand发送SETUP命令
ProxyRTSPClient::continueAfterSETUP,SETUP发送成功后调用这个函数
RTSPClient::sendPlayCommand,发送PLAY命令,连接音视频流

创建sink:
创建两个Groupsock对象,分别用来转发视频,音频流

用ProxyServerMediaSubsession对象调用ProxyServerMediaSubsession::createNewRTPSink创建视频、音频sink,是RTPSink类型:
H264VideoRTPSink::createNew,区分视频类型创建H264sink

创建DarwinInjector对象,并将sink添加到DarwinInjector对象中

DarwinInjector::createNew,创建DarwinInjector对象
DarwinInjector::addStream,添加sink
DarwinInjector::setDestination,建立与服务推流连接

sink对象调用MediaSink::startPlaying开始转发

MediaSink::startPlaying
H264or5VideoRTPSink::continuePlaying
MultiFramedRTPSink::continuePlaying
H264or5Fragmenter::doGetNextFrame()
H264or5Fragmenter::afterGettingFrame1
H264or5Fragmenter::afterGettingFrame

continuePlaying和doGetNextFrame循环调用

Boolean DarwinInjector::setDestination函数修改,解决没有RTCP时候不能发送音频问题:

  if (ss->rtcpInstance() != NULL) {
ss->rtcpInstance()->setStreamSocket(fRTSPClient->socketNum(),
				    streamChannelId++);
  }
  else
  {
	  streamChannelId++;    //add 解决无rtcp的时候音频问题
  }

RTPSink数据发送调用过程:

MultiFramedRTPSink::continuePlaying
MultiFramedRTPSink::buildAndSendPacket
MultiFramedRTPSink::packFrame
MultiFramedRTPSink::afterGettingFrame

MultiFramedRTPSink::sendNext
MultiFramedRTPSink::buildAndSendPacket
MultiFramedRTPSink::packFrame
MultiFramedRTPSink::afterGettingFrame
MultiFramedRTPSink::afterGettingFrame1
MultiFramedRTPSink::sendPacketIfNecessary
RTPInterface::sendPacket

高码率视频数据传输的优化点

对高清高码率的视频画面,每一帧的视频数据就会比较大,这个数值往往会超出live555内部默认的内存处理大小,因为对于live555的优化,主要就是集中在内存缓冲大小的扩大,以及避免内存数据拷贝。以下为根据实际开发和测试所总结出来的有效的优化点:
1.扩展帧解析buffer大小,即BANK_SIZE,默认值为150k,根据传输的H264数据帧大小,至少设置为300k。否则超出大小,可能会被Live555抛弃。
2.增加OutPacketBuffer::maxSize大小,同样为了容纳超大帧数据,否则可能会导致数据丢失。
3.在RTPInterface中,增加socket发送缓冲区大小,即increaseSendBufferTo函数的参数值
4.对MultiFramedRTPSink::sendPacketIfNecessary中,可以直接调用sendNext尝试组建RTP报文发送数据包,这样修改的优点是已读取的数据会被尽快发送出去,不过也多占用一些线程时间。
5.对于应用程序将数据从自己的线程传递给Live555的时候,应该尽量减少内存拷贝,最好是通过内存池的形式,以避免拷贝内存阻塞Live555事件循环

经过以上修改,以及应用程序内部代码的优化,在实际应用中,已经实现了10Mbps高码率的1080p以上高分辨率高清视频的流畅直播。


3. 看不到直播视频,如何排查?

我们可以先配置easydarwin.xml文件中的

true

字段为true,然后重新启动EasyDarwin,请求EasyDarwin,如果一点报文都没有打印,那就是你访问的地址错了!如果报文有打印,那就可以具体看看返回的错误码是多少了,错误码对照表:

响应码报文描述定义
200Success OK成功创建
201Success Created成功创建
202Success Accepted 已接受用于处理,但处理尚未完成
204Success No Content 已接收请求,但不存在要回送的信息
206Success Partial Content 已接收请求,但要回送的信息不完整
301Redirect Permanent Moved 请求的数据具有新的位置且更改是永久的。
302Redirect Temp Moved 请求的数据临时具有不同 URI
303Redirect See Other 可在另一 URI 下找到对请求的响应
305Use Proxy 必须通过位置字段中提供的代理来访问请求的资源
400Client Bad Request 请求中有语法问题,或不能满足请求
401Client Unauthorized 未授权客户端访问数据
402Payment Required 需要付款,表示计费系统已有效
403Client Forbidden 禁止, 即使有授权也不需要访问
404Not Found 服务器找不到给定的资源
405Method Not Allowed 请求的方法不支持
407Proxy Authentication Required 代理认证请求,客户机首先必须使用代理认证自身
408Request Timeout 请求超时
409Conflict 请求冲突
412Precondition Failed 前提条件失败
415Unsupported Media Type 服务器拒绝服务请求,因为不支持请求实体的格式
500Server Internal Error 内部错误,因为意外情况,服务器不能完成请求
501Server Not Implemented 未执行,服务器不支持请求
502Server Bad Gateway 错误网关,服务器接收到来自上游服务器的无效响应
503Server Unavailable 由于临时过载或无法获得服务护,服务器无法处理请求
505RTSP Version Not Supported 不支持的RTSP版本
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值