前面三篇blog分别介绍国网B接口注册、资源上报和资源信息获取,今天过一下国网B接口调阅实时视频相关的接口描述和消息示例,做过GB28181设备接入的都知道,国网B接口调阅实时视频流程和GB28181的基本一致的,区别在于SDP的一些参数描述,有些差别,举个例子,调阅实时视频,GB28181的SDP里面“s=Play”,国网B接口SDP取值定义“s=-”,如果严格按照规范来,估计好多系统都没法正常接入。

接口描述

国网B接口调阅实时视频,相关规范写的比较粗略:

调阅实时视频包括信令接口和媒体流接口,采用标准的SIP INVITE+SDP流程,媒体传输使用RTP/RTCP。

SDP 中 RTP Payload 的取值应遵守下面接口参数中的定义:

a) SDP 中的媒体信息,应仅有一个 m 行,用于描述视频格式。

b) 视频数据用 RTP 打包传输时,应考虑每个传输分组不大于 MTU,可采用的技术包括编码器层支持(如 ITU-T H.264 的 multi-slice 技术),或采用 RTP 层的分片机制(如 IETF RFC 3984 定义的 FU-A 技术)。

前端设备收到平台的INVITE请求后根据SDP描述进行媒体协商,协商通过后打开前端系统摄像机设备将获得的媒体流通过媒体通道发送到平台。

会话建立成功后,前端系统在某些特殊情况下可以主动结束当前呼叫。

平台应支持视频流的分发,以降低对前端系统的操作频繁性和节省网络带宽。

调阅实时视频的接口流程

主要功能流程如下:

a) F1:用户发送 INVITE 消息,携带 SDP 内容通过平台转发到前端设备。

b) F2:按照 SIP 要求,如前端系统在 0.5s 内未能处理该请求,则先发送 1xx 临时响应通过平台转发到用户。

c) F3:前端系统接受了调阅请求的操作,则发送携带 SDP 的 200 OK 响应通过平台转发到用户。

d) F4:用户发送 ACK 通过平台转发到前端设备。

e) 视频流从前端系统传输经平台转发到用户。

f) F5:用户结束会话,发送 BYE 消息到通过平台转发到前端系统。

g)F6:前端系统发送确认,将媒体通道拆线。

接口参数的重要SIP头字段和SIP响应码不再赘述,这里我们主要看看SDP的参数定义:

RTP动态Payload定义如下:

可以看到H.264的对应的Payload是100。

消息示例

调阅实时视频请求

INVITE sip:前端设备地址编码@前端系统所属平台域名或IP地址 SIP/2.0
From: <sip:用户地址编码@用户所属平台域名或IP地址>;tag=3101300
To: <sip:前端设备地址编码@前端系统所属平台域名或IP地址>
Contact: <sip:用户地址编码@用户所属平台域名或IP地址>
Call-ID: c47k42
Via: SIP/2.0/UDP 用户所属平台IP地址;branch=z9hG4bK
CSeq: 1 INVITE
Content-type: application/SDP
Content-Length: 消息体的长度
v=0
o=- 0 0 IN IP4 用户会话IP地址描述
s=-
c=IN IP4 用户媒体IP地址描述
m=video 13578 RTP/AVP 100
a=rtpmap:100 H264/90000
a=fmtp:100 CIF=1;4CIF=1;F=1;K=1
a=sendrecv

调阅实时视频请求响应

SIP/2.0 200 OK
From: <sip:用户地址编码@用户所属平台域名或IP地址>;tag=3101300
To: <sip:前端设备地址编码@前端系统所属平台域名或IP地址>;tag=20b0660
Contact: <sip:用户地址编码@前端系统所属平台域名或IP地址>
Call-ID: c47k42
Via: SIP/2.0/UDP 用户所属平台IP地址;branch=z9hG4bK
CSeq: 1 INVITE
Content-type: application/SDP
Content-Length: 消息体的长度
v=0
o=- 0 0 IN IP4 前端设备会话IP地址描述
s=-
c=IN IP4 前端设备媒体IP地址描述
m=video 1034 RTP/AVP 100
a=rtpmap:100 H264/90000
a=fmtp:100 CIF=1
a=fmtp:100 profile-level-id=420028;sprop-parameter-sets=Z0IAKO-kBQHsg,aM44gA==
a=sendrecv

国网B接口和GB28181的invite区别

我们再来看看,和GB28181的invite有什么不同之处:

GB/T28181-2016规范中,明确提到:实时视音频点播的SIP消息应通过本域或其他域的SIP服务器进行路由、转发,目标设备的实时视音频流宜通过本域内的媒体服务器进行转发。实时视音频点播采用SIP协议(IETFRFC3261)中的Invite方法实现会话连接,采用 RTP/RTCP协议(IETFRFC3550)实现媒体传输。

实时视音频点播的信令流程分为客户端主动发起和第三方呼叫控制两种方式,联网系统可选择其中一种或两种结合的实现方式。第三方呼叫控制的第三方控制者宜采用背靠背用户代理实现,有关第三方呼叫控制见IETFRFC3725。

实时视音频点播宜支持附录 M 规定的媒体流保活机制。

再看看GB28181客户端主动发起的实时视音频点播流程:

具体流程不再赘述,看看​​大牛直播SDK​​针对GB28181 invite的处理吧:

收到Invite后,除了正常信令交互回复外,初始化Sender():

@Overridepublic void ntsOnInvitePlay(String deviceId, SessionDescription session_des) {handler_.postDelayed(new Runnable() {@Overridepublic void run() {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());// 可以先给信令服务器发送临时振铃响应//sip_stack_android.respondPlayInvite(180, device_id_);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);}

Ack后,开始初始化Pusher,发送数据到国标平台侧:

@Overridepublic void ntsOnAckPlay(String deviceId) {handler_.postDelayed(new Runnable() {@Overridepublic void run() {Log.i(TAG,"ntsOnACKPlay, device_id:" +device_id_);if (!isRTSPPublisherRunning && !isPushingRtmp && !isRecording) {InitAndSetConfig();}libPublisher.SetGB28181RTPSender(publisherHandle, gb28181_rtp_sender_handle_, gb28181_rtp_payload_type_, gb28181_rtp_encoding_name_);int startRet = libPublisher.StartGB28181MediaStream(publisherHandle);if (startRet != 0) {if (!isRTSPPublisherRunning && !isPushingRtmp  && !isRecording) {if (publisherHandle != 0) {libPublisher.SmartPublisherClose(publisherHandle);publisherHandle = 0;}}destoryRTPSender();Log.e(TAG, "Failed to start GB28181 service..");return;}if (!isRTSPPublisherRunning && !isPushingRtmp && !isRecording) {CheckInitAudioRecorder();}startLayerPostThread();isGB28181StreamRunning = true;}private String device_id_;public Runnable set(String device_id) {this.device_id_ = device_id;return this;}}.set(deviceId),0);}

以上是国网B接口调阅实时视频(INVITE)接口描述和消息示例,然后就GB28181的invite做了简单的对比,感兴趣的开发者,可以仔细研读两份规范,看看还有哪些不一致的地方。

国网B接口调阅实时视频(INVITE)接口描述和消息示例相关推荐

  1. 国网B接口调阅实时视频规范解读和代码示例分析

    接口描述 国网B接口调阅实时视频,相关规范写的比较粗略: 调阅实时视频包括信令接口和媒体流接口,采用标准的SIP INVITE+SDP流程,媒体传输使用RTP/RTCP. SDP 中 RTP Payl ...

  2. RTSP/RTMP/GB28181协议视频监控平台搭建之国网B接口协议介绍

    我们知道TSINGSEE青犀视频全线产品对应了不同的视频协议,比如EasyNVR就是支持RTSP协议的视频平台,EasyDSS是支持RTMP协议的视频平台,EasyGBS是支持GB28181协议的视频 ...

  3. android实现国网B接口的前端设备app

    国网B接口是国家电网视频监控系统的内部接入协议,即提供视频监控系统与属于该平台的前端系统之间的接口.如下图:: 视跃科技基于国家电网B接口协议研发了前端设备软件RealGridDevice,不仅仅可以 ...

  4. 电网视频监控系统国网B接口中注册的接口流程GB281181国标流媒体服务平台

    国网B接口电网B接口 1.电网视频监控系统 2.电网B接口 协议(部分) 2.1.注册的接口流程 3.搭建GB28181视频直播平台 4.电网B接口设备如何接入 1.电网视频监控系统 电网视频监控系统 ...

  5. 解决布控球布控球接入国网南瑞B接口视频平台方法

    ​电力安全生产现场作业终端布控球.电力安全生产现场作业终端单兵等设备在国电平台使用,布控球可接入电网安全接入平台及电网统一视频监控平台 电力图像视频安全接入模块 产品简介 电力图像视频安全接入模块是一 ...

  6. 关于网易云音乐爬虫的api接口?

    抓包能力有限,分析了一下网易云音乐的一些api接口,但是关于它很多post请求都是加了密,没有弄太明白.之前在知乎看到过一个豆瓣工程师写的教程,但是被投诉删掉了,请问有网友fork了的吗?因为我觉得他 ...

  7. 新网域名查询和注册API接口类 源码

    最近公司要做一个基于新网的API,在自己的系统中实现实时查询域名注册情况,并且要能实时注册,注册费用自动从我们的代理帐户中扣除,下面是我写的核心实现类代码:     public class XinN ...

  8. python爬虫api接口,网易云音乐python爬虫api接口

    抓包能力有限,分析了一下网易云音乐的一些api接口,但是关于它很多post请求都是加了密,没有弄太明白.之前在知乎看到过一个豆瓣工程师写的教程,但是被投诉删掉了,请问有网友fork了的吗?因为我觉得他 ...

  9. 护网必备技能:Spring Boot 接口数据加解密 功能实现

    护网必备技能:Spring Boot 接口数据加解密 功能实现 文章目录 护网必备技能:Spring Boot 接口数据加解密 功能实现 1. 尽量少改动,不影响之前的业务逻辑: 2. 考虑到时间紧迫 ...

  10. php如何做7天后自动售货店,PHP自动售货发卡网源码集成多种支付接口

    PHP自动售货发卡网源码 集成多种支付接口 支付接口已集成 支付宝当面付 支付宝PC支付 支付宝手机支付 payjs微信扫码. Paysapi(支付宝/微信). 码支付(QQ/支付宝/微信) 微信企业 ...

最新文章

  1. 02.v-cli快速搭建
  2. Redis为什么使用单进程单线程方式也这么快
  3. Plyr – 简单,灵活的 HTML5 媒体播放器
  4. vue路由的钩子函数有哪些?都做了哪些事情?
  5. javascript基础 之 void
  6. Win2003 R2 with SP2的MSDN版所有版本http下载,已收集全
  7. to load JavaHL Library解决方法
  8. 《Lua程序设计》第1章 开始 学习笔记
  9. oj系统 的c语言答案,宁波大学OJ系统前105道C语言题目及答案精讲
  10. 利用C#编写一个附和闭合导线平差程序
  11. Java文件上传之断点续传解决方案
  12. a html w3c,HTML a 标签 | w3cschool菜鸟教程
  13. Netty原理与基础
  14. 【概率论与数理统计(研究生课程)】知识点总结6(抽样分布)
  15. 英语音标中KK音标、IPA音标、DJ音标各是什么意思
  16. 同步锁Synchronized和ReentrantLock区别
  17. 玩一个猜数字的小游戏吧
  18. Json对象和string之间的转换
  19. Ubuntu开发环境_TLP电源管理模块、禁用笔记本触摸板
  20. 什么是智能卡与IC卡

热门文章

  1. 二进制编辑和进程监控工具
  2. 2020华为软件精英挑战赛热身赛总结篇
  3. 50道经典计算机网络面试题梳理
  4. Java web简单注册和登陆项目案例
  5. 曹鹏php mysql视频教程_曹鹏 PHP+MYSQL 视频教程(flash)
  6. AD库转allegro步骤
  7. 知网下载pdf论文的最简单方法
  8. Java反射机制是否会影响性能
  9. Easypoi导出excel
  10. 人工智能艺术:一场用算法固定创意的马拉松