GB28181基于TCP协议的视音频媒体传输探究及实现

我们先看看官方规范针对TCP协议的视音频传输描述:

实时视频点播、历史视频回放与下载的 TCP媒体传输应支持基于RTP封装的视音频PS流,封装格式参照IETFRFC4571。

流媒体服务器宜同时支持作为TCP媒体流传输服务端和客户端。默认情况下,前端设备向流媒体服务器发送媒体流时前端设备应作为TCP媒体流传输客户端,流媒体服务器作为 TCP媒体流传输服务端;同级或跨级流媒体服务器间基于 TCP协议传输视频流时,媒体流的接收方宜作为TCP媒体流传输服务端。

媒体流的发送方和接收方可扩展SDP参数进行TCP媒体流传输服务端和客户端的协商,协商机制参考附录 F及IETFRFC4571的定义。

这里我们看个INVITE信令交互示例:

INVITE sip:34020000001320000001@3402000000 SIP/2.0
Via: SIP/2.0/TCP 192.168.0.105:15060;rport;branch=z9hG4bK630055772
From: <sip:34020000002000000001@3402000000>;tag=562055772
To: <sip:34020000001320000001@3402000000>
Call-ID: 589055668
CSeq: 183 INVITE
Content-Type: APPLICATION/SDP
Contact: <sip:34020000002000000001@192.168.0.105:15060>
Max-Forwards: 70
User-Agent: LiveGB28181
Subject: 34020000001320000001:0200000001,34020000002000000001:0
Content-Length: 222v=0
o=34020000001320000001 0 0 IN IP4 192.168.0.105
s=Play
c=IN IP4 192.168.0.105
t=0 0
m=video 30076 RTP/AVP 96 97 98
a=recvonly
a=rtpmap:96 PS/90000
a=rtpmap:97 MPEG4/90000
a=rtpmap:98 H264/90000
y=0200000001

判断媒体流走TCP还是UDP,主要看这里:

m=video 30076 RTP/AVP 96 97 98

传输方式采用“RTP/AVP”标识传输层协议为 RTP over UDP,采用“TCP/RTP/AVP”标识传输层协议为 RTP over TCP,需要注意的是,我们实际对接的时候,部分厂商SDP非常随意,有的甚至直接标记个tcp,这让我们对接的时候,很困惑。

技术实现:

 

本文以大牛直播SDK的Android平台GB28181设备接入端为例,启动GB28181,完成注册、catalog等交互后,Invite上来后,设置媒体流通过TCP还是UDP发送出去:

@Override
public void ntsOnInvitePlay(String deviceId, SessionDescription session_des) {handler_.postDelayed(new Runnable() {@Overridepublic void run() {// 先振铃响应下gb28181_agent_.respondPlayInvite(180, device_id_);MediaSessionDescription video_des = null;SDPRtpMapAttribute ps_rtpmap_attr = null;// 28181 视频使用PS打包Vector<MediaSessionDescription> video_des_list = session_des_.getVideoPSDescriptions();if (video_des_list != null && !video_des_list.isEmpty()) {for(MediaSessionDescription m : video_des_list) {if (m != null && m.isValidAddressType() && m.isHasAddress() ) {video_des = m;ps_rtpmap_attr = video_des.getPSRtpMapAttribute();break;}}}if (null == video_des) {gb28181_agent_.respondPlayInvite(488, device_id_);Log.i(TAG, "ntsOnInvitePlay get video description is null, response 488, device_id:" + device_id_);return;}if (null == ps_rtpmap_attr) {gb28181_agent_.respondPlayInvite(488, device_id_);Log.i(TAG, "ntsOnInvitePlay get ps rtp map attribute is null, response 488, device_id:" + device_id_);return;}Log.i(TAG,"ntsOnInvitePlay, device_id:" +device_id_+", is_tcp:" + video_des.isRTPOverTCP()+ " rtp_port:" + video_des.getPort() + " ssrc:" + video_des.getSSRC()+ " address_type:" + video_des.getAddressType() + " address:" + video_des.getAddress());long rtp_sender_handle = libPublisher.CreateRTPSender(0);if ( rtp_sender_handle == 0 ) {gb28181_agent_.respondPlayInvite(488, device_id_);Log.i(TAG, "ntsOnInvitePlay CreateRTPSender failed, response 488, device_id:" + device_id_);return;}gb28181_rtp_payload_type_  = ps_rtpmap_attr.getPayloadType();gb28181_rtp_encoding_name_ =  ps_rtpmap_attr.getEncodingName();libPublisher.SetRTPSenderTransportProtocol(rtp_sender_handle, video_des.isRTPOverUDP()?0:1);libPublisher.SetRTPSenderIPAddressType(rtp_sender_handle, video_des.isIPv4()?0:1);libPublisher.SetRTPSenderLocalPort(rtp_sender_handle, 0);libPublisher.SetRTPSenderSSRC(rtp_sender_handle, video_des.getSSRC());libPublisher.SetRTPSenderSocketSendBuffer(rtp_sender_handle, 2*1024*1024); // 设置到2MlibPublisher.SetRTPSenderClockRate(rtp_sender_handle, ps_rtpmap_attr.getClockRate());libPublisher.SetRTPSenderDestination(rtp_sender_handle, video_des.getAddress(), video_des.getPort());if ( libPublisher.InitRTPSender(rtp_sender_handle) != 0 ) {gb28181_agent_.respondPlayInvite(488, device_id_);libPublisher.DestoryRTPSender(rtp_sender_handle);return;}int local_port = libPublisher.GetRTPSenderLocalPort(rtp_sender_handle);if (local_port == 0) {gb28181_agent_.respondPlayInvite(488, device_id_);libPublisher.DestoryRTPSender(rtp_sender_handle);return;}Log.i(TAG,"get local_port:" + local_port);String local_ip_addr = IPAddrUtils.getIpAddress(context_);MediaSessionDescription local_video_des = new MediaSessionDescription(video_des.getType());local_video_des.addFormat(String.valueOf(ps_rtpmap_attr.getPayloadType()));local_video_des.addRtpMapAttribute(ps_rtpmap_attr);local_video_des.setAddressType(video_des.getAddressType());local_video_des.setAddress(local_ip_addr);local_video_des.setPort(local_port);local_video_des.setTransportProtocol(video_des.getTransportProtocol());local_video_des.setSSRC(video_des.getSSRC());if (!gb28181_agent_.respondPlayInviteOK(device_id_,local_video_des) ) {libPublisher.DestoryRTPSender(rtp_sender_handle);Log.e(TAG, "ntsOnInvitePlay call respondPlayInviteOK failed.");return;}gb28181_rtp_sender_handle_ = rtp_sender_handle;}private String device_id_;private SessionDescription session_des_;public Runnable set(String device_id, SessionDescription session_des) {this.device_id_ = device_id;this.session_des_ = session_des;return this;}}.set(deviceId, session_des),0);
}

接口设计如下:

/***设置 RTP Sender传输协议** @param rtp_sender_handle, CreateRTPSender返回值* @param transport_protocol, 0:UDP, 1:TCP, 默认是UDP** @return {0} if successful*/public native int SetRTPSenderTransportProtocol(long rtp_sender_handle, int transport_protocol);

以上是GB28181基于TCP协议的视音频媒体传输探究及实现,感兴趣的开发者,可以查看相关协议规范,根据需求实现自己的业务逻辑即可。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/552935.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android平台GB28181接入端如何对接UVC摄像头?

我们在对接Android平台GB28181接入的时候&#xff0c;有公司提出这样的需求&#xff0c;除了采集执法记录仪摄像头自带的数据外&#xff0c;还想通过执法记录仪采集外接UVC摄像头。 实际上&#xff0c;这块对我们来说有点炒冷饭了&#xff0c;不算新的诉求。​大牛直播SDK​在2…

Android平台实现系统内录(捕获播放的音频)并推送RTMP服务技术方案探究

几年来&#xff0c;我们在做无纸化同屏或在线教育相关场景的时候&#xff0c;总是被一件事情困扰&#xff1a;如何实现Android平台的系统内录&#xff0c;并推送到其他播放端&#xff0c;常用的场景比如做无纸化会议或教育的时候&#xff0c;主讲人或老师需要放一个视频&#x…

Android平台GB28181设备接入端PTZ对接详解

PTZCmd实现背景 上一篇blog“Android平台GB28181设备接入模块之球机/云台控制探究”谈到&#xff0c;Android平台做国标GB28181设备接入端的时候&#xff0c;PTZ控制要不要处理&#xff1f;如果处理&#xff0c;难度大不大&#xff1f; 首先说要不要处理&#xff1a;如果只是…

Android平台GB28181设备接入模块摄像头采集方向不对怎么办?

背景 我们在做Android平台GB28181设备接入模块的时候&#xff0c;有开发者提到这样的诉求&#xff1a;他们的智能头盔、执法记录仪等设备&#xff0c;采集到的图像&#xff0c;是旋转了90、180甚至270的&#xff0c;设备本身无法针对图像做翻转或者旋转操作&#xff0c;问我们…

Android平台GB28181设备接入模块分辨率发生变化怎么办?

技术背景 我们在做Android平台gb28181设备接入模块的时候&#xff0c;遇到这样的情况&#xff0c;比如横竖屏分辨率不锁定&#xff0c;采集摄像头的时候&#xff0c;可以实现&#xff0c;横屏状态采集横屏&#xff0c;竖屏状态采集竖屏&#xff0c;简单来说&#xff0c;横屏状…

RTSP、RTMP播放器拉到的视频图像角度不对怎么办?

我们在做RTSP、RTMP播放器的时候&#xff0c;遇到这样的诉求&#xff1a;特别是RTSP&#xff0c;有些摄像头安装可能倒置或者旋转了90亦或270&#xff0c;拉取到图像&#xff0c;势必需要对视频图像做一定的处理&#xff0c;确保显示正常。 为此&#xff0c;我们提供了以下接口…

Android平台GB28181设备接入端如何调节实时音量?

我们在对接Android平台GB28181设备接入端的时候&#xff0c;有开发者提出这样的疑惑&#xff0c;如何调整设备接入端的实时音量&#xff1f; 实际上&#xff0c;这块我们前几年在做RTMP直播推送模块的时候&#xff0c;已经发布了相关的接口&#xff0c;这里再回顾下&#xff1…

【技术分享】如何实现功能完备性能优异的RTMP、RTSP播放器?

技术背景 这几年&#xff0c;我们对接了太多有RTSP或RTMP直播播放器诉求的开发者&#xff0c;他们当中除了寻求完整的解决方案的&#xff0c;还有些是技术探讨&#xff0c;希望能借鉴我们播放端的开发思路或功能特性&#xff0c;完善自己的产品。 忙里偷闲&#xff0c;今天我…

我正在参加2022年度博客之星评选,大家帮我点个五星好评

大家好&#xff0c;我是音视频牛哥&#xff0c;致力于跨平台的实时RTMP推流、转发、RTMP/RTSP直播播放、GB28181设备接入。 有幸参加2022年度博客之星评选&#xff0c;欢迎大家帮点五星好评。如果我的博客能给开发者带来哪怕一丝启发&#xff0c;对博主来说&#xff0c;也甚感…

rtmp/rtsp/hls公网真正可用的测试地址

相信大家在调试播放器的时候&#xff0c;都有这样的困惑&#xff0c;很难找到合适的公有测试源&#xff0c;以下是大牛直播SDK&#xff08;GitHub地址&#xff09;整理的真正可用的直播地址源。 其中&#xff0c;rtmp和rtsp的url&#xff0c;用我们播放器验证通过。 1. rtmp:…

公网可用的RTMP、RTSP测试地址(更新于2021年3月)

好多博客提到的公网可测试的RTSP和RTMP URL大多都不用了&#xff0c;以下是大牛直播SDK(Github)于2021年3月亲测可用的几个URL&#xff0c;有其他可用的URL&#xff0c;也欢迎大家在评论区回复。 RTMP流地址 湖南卫视&#xff1a;rtmp://58.200.131.2:1935/livetv/hunantv (7…

Unity环境下RTMP推流+RTMP播放低延迟解决方案

在本文之前&#xff0c;我们发布了Unity环境下的RTMP推流&#xff08;Windows平台Android平台&#xff09;和RTMP|RTSP拉流&#xff08;Windows平台Android平台iOS平台&#xff09;低延迟的解决方案&#xff0c;今天做个整体汇总&#xff0c;权当抛砖引玉。 1. Unity环境下RTM…

麒麟操作系统|Linux下低延时RTMP|RTSP直播播放实现

背景 国产操作系统多为以Linux为基础二次开发的操作系统。2014年4月8日起&#xff0c;美国微软公司停止了对Windows XP SP3操作系统提供服务支持&#xff0c;这引起了社会和广大用户的广泛关注和对信息安全的担忧。而2020年对Windows7服务支持的终止再一次推动了国产系统的发展…

基于RTMP实现Linux|麒麟操作系统下屏幕|系统声音采集推送

背景 Windows操作系统自问世以来&#xff0c;以其简单易用的图形化界面操作受到大众追捧&#xff0c;为计算机的普及、科技的发展做出了不可磨灭的功绩&#xff0c;也慢慢的成为人们最依赖的操作系统。在中国&#xff0c;90&#xff05;以上的办公环境都是Windows&#xff0c;…

如何快速实现Android平台前端设备接入能力

技术背景 SIP(会话初始化协议)是在 IP网络上进行多媒体通信的应用层控制协议&#xff0c;以几种RFC的形式提供&#xff0c;其中最重要的是包含核心协议规范的RFC3261。该协议用于创建&#xff0c;修改和终止与一个或多个参与者的会话。通过会话&#xff0c;我们了解了一组进行…

长安渝北工厂机器人_长安工厂探秘!解密CS75 PLUS究竟是怎样造出来的

长安CS75 PLUS自打上市以来&#xff0c;销量真的是有目共睹&#xff0c;仅仅一个半月就有3万多的订单&#xff0c;这辆车真的很火很爆款。但我不仅要提出一些疑问了&#xff0c;CS75 PLUS卖这么好&#xff0c;制造工艺怎么样呢&#xff1f;它又是怎么造出来的呢&#xff1f;带着…

threadlocal存连接对象的目的_终于懂了ThreadLocal,不再害怕面试官问了

ThreadLocal解析synchronized和ThreadLocal的区别&#xff1a;synchronized:以时间换空间&#xff0c;只提供一份变量&#xff0c;让不同的线程排队访问&#xff0c;失去了并发性&#xff0c;降低了程序效率&#xff0c;着重对各线程之间访问资源的同步性ThreadLocal:以空间换时…

主板后置音频接口图解_颜值出众、用料靠谱——华擎(ASRock)Z490 Extreme4极限玩家主板 简析...

一、前言你们能想象嘛&#xff0c;那种主板已经到了&#xff0c;处理器却没抢到的感觉。刚开始看到Plus会员提前抢的时候&#xff0c;我心里面还有一些放心&#xff0c;但当时间刚过秒变无货的时候&#xff0c;一切又已回到当初&#xff0c;难受&#xff01;居然没有首发抢到10…

中查出所有姓张的学生为啥查不出来_只有笔试成绩没有面试成绩是什么原因 教师资格面试成绩怎么查...

[闽南网]对于很多同学来说&#xff0c;今晚是个不眠夜。就在几个小时前&#xff0c;教师资格证面试成绩查询入口开通了&#xff0c;相比之前发布的消息&#xff0c;成绩公布提前了很多。参加了这次教师资格证考试的同学&#xff0c;一得到消息就忙着查成绩&#xff0c;毕竟面试…

c++用模板实现稀疏多项式_用线性表实现一元多项式及相加运算

“ 本文主要讨论线性表在多项式计算中的应用&#xff0c;讨论内容涉及到一元n次多项式在计算机中的表示&#xff0c;及多项式相加运算。”01在数学上&#xff0c;一个一元n次多项式可以按照升幂写成Pn(x) p0 p1x p2x2 …… pnxn它由n1个系数唯一确定。因此&#xff0c;一个…