IPC 代理 总结


想要做一个IPC 代理 需要了解 整个IPC 的服务 以及通信接口,目前IPC 通信 包括流数据传输、流数据控制、 IPC 摄像头控制;

数据传输 指媒体流,流数据控制 指调控流的meta 如码率、通道等,IPC 摄像头控制 可以控制摄像头的转向。

目前IPC 对接 客户端 可以使用onvif 和 国标GB 协议;

onvif

  1. NVR 客户端 需要 联通 IPC ,有两种模式,一种是主动发现 一种是手动配置 IP 和 端口,主动发现 使用udp 广播报文,IPC 设备 收到广播报文告诉NVR 自己的地址 XAddrs,(一个IPC 可以告诉),以及 device 获取接口url http://ip/onvif/device_service;
  2. NVR 客户端 获取到设备接口后,获取设备能力 ,需要知道该IPC 设备支持哪些能力 属性等 ,onvif 基于 http 使用 soap、wsdl 等描述语言, post 请求 http://ip/onvif/device_service GetCapbilities; IPC 会把 流媒体服务器media 的地址 响应回来 http://ip/onvif/media 。
  3. GetProfiles, 获取流的token 和 多路流的哪一路,一路代表一个流地址;
  4. GetStreamUri 携带token 获取流媒体播放地址,token 101 第一路流等;
  5. 使用流地址开始 拉流,可以使用ONVIF Device Test Tool 进行调试 ;
  6. 摄像头控制 url

ONVIF代理对接

如果我们需要对原始流处理后再播放,接入一个代理,可以使用nginx (透传)+ 页面改写 改写流地址,但是要注意 content-length 头和 chunk 头处理,参考 image_filter 模块。可以使用ONVIF Device Test Tool 进行调试 或者通过抓包对比IPC 直连方式调试。

对于event 的代理需要做双向代理,NVR 中可以配置 对某些 事件的 报警 event,NVR 需要告诉IPC 要针对哪些 事件进行上报,IPC 告诉客户端 过来拉,客户端向IPC 拉取;需要做更多测试;

ONVIF总结

  1. NVR 的广播模式 需要与IPC 在同一局域网,若使用手动配置IP,IPC 需要外网地址。相比较, SIP 协议更适合外网系统,onvif 适合局域网。
  2. onvif 有时返回500 是由于服务 对某些消息 不支持,与代理报文的准确性无关;

国标 SIP

在国标体系中,主要有 sip 服务器 、流媒体服务器、IPC、全球眼 管理和播放客户端 角色,sip 服务器 在整个体系中扮演管理角色,在一个庞大的IPC 分布式端网络,相关部门需要快速了解整个IPC 的 用途、地点等,因此有特殊的编号,类似onvif 里面的 P G S 等概念。采用主动注册体系更方便 分布式IPC 的接入和管理,同时能够利用NAT 机制 和 内部网络通信。SIP 服务器除了注册管理外,还要进行协调 流媒体服务器和 IPC 之前的事务时序,

由于IPC 内网,流媒体服务器公用外网,因此需要IPC 主动推送到流媒体服务器。全球眼从流媒体服务器获取拉流地址播放。通信采用SIP 和sdp 方式;

  1. IPC 向 SIP 服务器进行注册,通过抓包 使用 wireshark 搜索 sip 可以对比国标协议,REGISTER 请求;
  2. 全球眼客户端点击播放时 会产生INVITE 请求,在sdp 中描述play 信息 告知 IPC 客户端 流媒体服务器地址,RTP SSRC 等,以及协商封包格式等
  3. 客户端推流
  4. 保活、控制 等等…
    v=0
    o=34020000001320000002 0 0 IN IP4 192.168.1.31
    s=XLIPCAM
    c=IN IP4 192.168.1.31
    t=0 0
    m=video 6090 RTP/AVP 96
    a=rtpmap:96 MP2P/90000

SIP 代理对接

如果我们需要对原始流处理后再播放,接入一个代理. 对接原有sip 服务器, 实现点主要在于如何对接原有SIP服务器 和 IPC,SIP代理可以有两种模式,一种是SIP 级联,一种是控制网关,SIP 级联相当于代理部分又是一套SIP 系统,需要实现SIP 服务器的角色等;而控制网关则需要实现一个IPC 客户端功能,但是拉流来源来自真实的IPC 内容。操作IPC 指令同样需要能够理解并下达真实IPC。

我们采用 ffmpeg 从IPC 拉流并压缩,将压缩后的内容通过本地TCP 套接字传递给代理,代理将相应的视频内容进行ps封包 rtp 封包怼到流媒体服务器。

ffmpeg -f rtsp -rtsp_transport tcp -i "rtsp://admin:admin123@192.168.1.64:554/Streaming/Channels/101?transportmode=unicast&profile=Profile_101" -vcodec libx264 -preset faster -tune zerolatency -threads 1 -rc-lookahead 0 -maxrate 900k -minrate 900k -b:v 900k -g 50 -sc_threshold 0 -an -f h264 unix:///home/ffmpeg.sock


ffmpeg -f rtsp -rtsp_transport tcp -i "rtsp://admin:admin123@192.168.1.64:554/Streaming/Channels/101?transportmode=unicast&profile=Profile_101" -vcodec libx264 -profile baseline -vf scale=1920:1080 -preset fast -tune zerolatency -maxrate 800k -minrate 600k -b:v 700k -bufsize 700k -keyint_min 50 -g 50 -sc_threshold 0 -an -f rtp rtp://192.168.11.253:5160?localrtpport=5061

问题总结

解决问题方法:找代码,相关函数 github搜索;QQ 群;对比IPC 抓包;软件的调试器;

RTP SDP 文件打开后再推流 VLC 无法播放sdp VLC 调试信息

黑屏===》帧ps 封包,没有使用h264 的原始数据raw data 无法解包

VLC 打开sdp 开始绿花屏====》 可能I 帧 丢失 要等I 帧下次刷新

VLC 打开sdp 等待===》等待I 帧到来打开

帧率设置不对===》 花屏

时间 模糊 windows udp 丢包

多线程I 帧 无法解包花屏 (本地播放因为本地有多个CPU播放正常, 远程服务器不一定使用多线程解压,并行压缩分为同一个帧内并行和帧间并行 ,此时ffmpeg 需使用一个线程压缩)

全球眼无法播放,有 音频封包 但是没有真实音频数据, 音频去掉相关bit,但是没有去掉结构体, bit 长度有计算结构体 0

绿屏 设置了使用h264 解码ps封包

花屏 丢帧 帧率 缓冲区

丢帧 ffmpeg 推流帧率缩小一半 从40 到 20

无法播放 SPLIT_IDR 以4 位 分隔,真实 输入源 可能 3位 4位 分隔 混合

ffmpeg 从内存中读取数据(或将数据输出到内存)

FFMPEG基于内存的转码实例——输入输出视频均在内存