GB28181信令交互流程及Android端设备对接探讨

GB28181规范必要性

好多开发者在做比如执法记录仪、智能安全帽、智能监控等设备端视频回传技术方案选型的时候,不清楚到底是用RTSP、RTMP还是GB28181,对GB28181相对比较陌生,我们就GB28181规范的必要性,做个探讨:

  1. 实现设备互联互通
    • 不同厂商设备兼容:在视频监控领域,市场上存在众多的设备厂商,各厂商生产的监控设备在通信协议、数据格式等方面可能存在差异。GB28181 规范为这些不同厂商的设备提供了统一的通信标准,使得它们能够相互识别、连接和通信。例如,一个使用 A 厂商摄像头的监控系统,可以与使用 B 厂商存储设备和 C 厂商监控平台的系统实现无缝对接,大大提高了设备的兼容性和互操作性。
    • 跨系统集成便利:除了不同厂商的设备之间需要互联,在一些大型的监控项目中,还可能涉及到多个不同的监控子系统,如城市安防监控系统、交通监控系统、企业内部监控系统等。GB28181 规范使得这些不同的监控系统能够基于统一的标准进行集成,实现信息的共享和协同工作,避免了因系统之间不兼容而导致的信息孤岛问题。
  2. 保障信息传输安全
    • 数据加密与认证:GB28181 规范对设备之间的通信过程提出了安全要求,包括对数据的加密传输、设备的身份认证等。通过加密技术,可以防止监控视频数据在传输过程中被窃取或篡改,确保信息的保密性和完整性。身份认证机制则可以保证只有合法的设备能够接入系统,防止非法设备的入侵和恶意攻击,提高了系统的安全性。
    • 访问控制与权限管理:该规范还规定了不同用户对监控系统的访问权限和操作权限,例如,管理员可以对设备进行配置和管理,普通用户只能查看实时视频或回放录像等。这样可以有效地防止未经授权的访问和操作,保护监控系统的安全和隐私。
  3. 提高系统管理效率
    • 设备集中管理:对于拥有大量监控设备的系统,如城市级的安防监控网络,设备的管理是一个巨大的挑战。GB28181 规范支持设备的集中管理,监控中心可以通过统一的管理平台对分布在不同地点的设备进行远程配置、监控、升级等操作,大大提高了设备管理的效率,降低了管理成本。
    • 故障诊断与排查:当监控系统出现故障时,GB28181 规范规定了设备应提供的故障信息和报警机制,使得管理员能够快速准确地定位故障设备和故障原因,及时进行修复,减少系统的故障时间,提高系统的可靠性和稳定性。
  4. 便于行业标准化发展
    • 规范市场秩序:在没有统一标准之前,视频监控市场较为混乱,各厂商各自为政,产品质量和性能参差不齐。GB28181 规范的制定为行业提供了统一的技术标准和规范,促使厂商按照标准进行产品研发和生产,提高了产品的质量和性能,规范了市场秩序,有利于行业的健康发展。
    • 推动技术创新:标准的制定为技术创新提供了一个明确的方向和框架,厂商可以在符合标准的前提下,不断探索和创新新的技术和应用,推动视频监控技术的不断发展。例如,在 GB28181 规范的基础上,一些厂商研发出了具有智能分析功能的监控设备,能够实现人脸识别、行为分析等高级功能,提高了监控系统的智能化水平。
  5. 满足公共安全需求
    • 应急指挥与协同作战:在公共安全领域,如公安、消防、应急管理等部门,需要快速获取准确的监控信息,以便进行应急指挥和协同作战。GB28181 规范确保了不同部门之间的监控系统能够实现互联互通,在紧急情况下,各部门可以快速共享监控视频和信息,提高应急响应的速度和效率,为保障公共安全提供有力支持。
    • 证据收集与追溯:监控视频作为一种重要的证据来源,在案件侦破、事故调查等方面具有重要作用。GB28181 规范保证了监控视频数据的规范性和可靠性,使得监控视频能够作为有效的证据被使用,为司法机关和相关部门的工作提供了便利。

GB28181信令交互流程

GB28181 规范中的信令交互流程主要包括注册、保活、设备信息查询、实时视频预览等环节,具体如下:

注册流程

  1. 下级设备发起注册请求:下级监控设备(如摄像头、编码器等)向上级监控平台(或中心管理服务器)发送REGISTER请求消息。该消息中包含设备的基本信息,如设备 ID、IP 地址、端口号、设备类型等,以及请求的过期时间(expires字段)等信息。
  2. 上级平台要求认证(可选):上级平台收到注册请求后,如果开启了认证功能,会回复401 Unauthorized响应,要求下级设备在后续的注册请求中携带认证信息。401响应中包含了认证所需的参数,如认证域(realm)、随机数(nonce)等。
  3. 下级设备再次发起注册请求(带认证信息):下级设备根据上级平台的要求,在第二次发送的REGISTER请求中添加认证信息,通常是使用摘要认证方式,计算出响应值(response)并添加到请求中。认证信息包括用户名、密码、随机数、请求方法、请求 URI 等信息的摘要值。
  4. 上级平台验证并回复:上级平台收到第二次注册请求后,验证认证信息的正确性。如果验证通过,则回复200 OK响应,表示注册成功,同时在响应中可以包含注册的有效期(expires字段)等信息。上级平台会将下级设备的信息记录下来,以便后续的管理和控制。

保活流程

  1. 下级设备发送保活请求:注册成功后,下级设备需要定期向上级平台发送保活请求,以维持连接的有效性。保活请求通常使用MESSAGE方法,并在消息体中携带保活命令(cmdtype="keepalive")和设备状态等信息。
  2. 上级平台回复:上级平台收到保活请求后,回复200 OK响应,表示确认收到保活信息。

设备信息查询流程

  1. 设备端发送查询请求:上级平台或其他有权限的设备可以向下级设备发送设备信息查询请求,请求消息中包含查询的命令类型和要查询的设备 ID(如果是查询单个设备信息)等信息。
  2. 下级设备回复查询结果:下级设备收到查询请求后,根据请求中的命令类型和设备 ID,查找相应的设备信息,并将查询结果返回给上级平台。查询结果通常以 XML 格式的消息体进行封装,包含设备的基本信息、状态信息、通道信息等。

实时视频预览流程

GB28181 规范中的实时视频预览流程主要包括以下步骤:

  1. 发起预览请求34:
    • 上级平台(客户端)动作:上级监控平台或有权限的客户端想要预览下级设备的实时视频时,会向下级设备发送INVITE请求。请求中包含媒体流的描述信息,如视频编码格式、分辨率、帧率等,以及接收视频流的地址和端口号等信息。在消息头域中通常会携带subject字段,表明点播的视频源 ID、发送方媒体流序列号、媒体流接收者 ID、接收端媒体流序列号等参数。例如,SDP消息体中s字段为 “play” 代表实时点播。
  2. 请求的路由与转发
    • SIP 服务器处理:SIP 服务器收到上级平台的INVITE请求后,开始进行信令的路由和转发工作。它会根据请求中的目标设备信息,将请求转发到相应的下级设备所在的网络域或直接转发到下级设备。
  3. 建立媒体连接(下级设备到媒体服务器)
    • SIP 服务器到媒体服务器:SIP 服务器首先向媒体服务器发送INVITE请求,此请求不携带SDP消息体,目的是通知媒体服务器准备接收媒体流。
    • 媒体服务器响应:媒体服务器收到 SIP 服务器的INVITE请求后,回复200 OK响应,携带SDP消息体。消息体中描述了媒体服务器接收媒体流的 IP、端口、媒体格式等内容,以便下级设备能够将媒体流正确地发送到媒体服务器。
  4. 建立媒体连接(媒体服务器到下级设备)
    • SIP 服务器到下级设备:SIP 服务器收到媒体服务器返回的200 OK响应后,将该响应消息体中的相关信息添加到新的INVITE请求中,并发送给下级设备(媒体流发送者)。这个请求中的s字段同样为 “play” 代表实时点播,并且增加y字段描述同步源(SSRC)值,f字段描述媒体参数等,告知下级设备向媒体服务器发送媒体流的具体要求。
    • 下级设备响应:下级设备收到 SIP 服务器的INVITE请求后,回复200 OK响应,携带SDP消息体,消息体中描述了下级设备发送媒体流的 IP、端口、媒体格式、SSRC 字段等内容,表示下级设备准备好发送媒体流。
  5. 会话建立确认
    • 上级平台到媒体服务器:SIP 服务器收到下级设备返回的200 OK响应后,向上级平台回复确认消息,告知上级平台媒体流的传输路径已经建立。上级平台收到确认消息后,开始准备接收媒体流。
    • SIP 服务器到下级设备:SIP 服务器向媒体服务器发送ACK请求,请求中携带下级设备回复的200 OK响应消息体,完成与媒体服务器的INVITE会话建立过程。同时,SIP 服务器也向下级设备发送ACK请求,请求中不携带消息体,完成与下级设备的INVITE会话建立过程。至此,三方的媒体会话连接建立完成,媒体流可以开始传输。
  6. 媒体流传输
    • 下级设备推送:下级设备根据会话建立时确定的参数,将实时视频流通过 RTP(Real-time Transport Protocol)协议推送到媒体服务器指定的接收端口。RTP 协议用于实时传输音视频数据,保证数据的实时性和顺序性。
    • 媒体服务器转发:媒体服务器接收到下级设备推送的媒体流后,根据上级平台的请求,将媒体流转发到上级平台指定的接收地址和端口。上级平台接收并解码媒体流,就可以实现实时视频预览。
  7. 结束预览
    • 上级平台发起:当预览结束时,上级平台向上级 SIP 服务器发送BYE请求,通知 SIP 服务器停止视频传输。
    • SIP 服务器响应:SIP 服务器收到BYE请求后回复200 OK响应,会话断开。然后,SIP 服务器分别向媒体服务器和下级设备发送BYE请求,通知它们结束媒体流的传输。
    • 媒体服务器和下级设备响应:媒体服务器和下级设备收到BYE请求后,分别回复200 OK响应,会话断开,整个实时视频预览流程结束。

GB28181对接

本文以大牛直播SDK的Android平台GB28181设备接入模块为例,介绍下,如何实现和对接GB28181设备端。

Android终端除支持常规的音视频数据接入外,还可以支持移动设备位置(MobilePosition)订阅和通知、图像抓拍、语音广播和语音对讲、历史视音频下载和回放,支持对接数据类型如下:

  1. 编码前数据(目前支持的有YV12/NV21/NV12/I420/RGB24/RGBA32/RGB565等数据类型),其中,Android平台前后摄像头数据,或者屏幕数据,或者Unity拿到的数据,均属编码前数据;
  2. 编码后数据(如无人机等264/HEVC数据,或者本地解析的MP4音视频数据);
  3. 拉取RTSP或RTMP流并接入至GB28181平台(比如其他IPC的RTSP流,可通过Android平台GB28181接入到国标平台)。

功能设计

  •  [视频格式]H.264/H.265(Android H.265硬编码);
  •  [音频格式]G.711 A律、AAC;
  •  [音量调节]Android平台采集端支持实时音量调节;
  •  [H.264硬编码]支持H.264特定机型硬编码;
  •  [H.265硬编码]支持H.265特定机型硬编码;
  •  [软硬编码参数配置]支持gop间隔、帧率、bit-rate设置;
  •  [软编码参数配置]支持软编码profile、软编码速度、可变码率设置;
  •  支持横屏、竖屏推流;
  •  Android平台支持后台service推送屏幕(推送屏幕需要5.0+版本);
  • 支持纯视频、音视频PS打包传输;
  • 支持RTP OVER UDP和RTP OVER TCP被动模式(TCP媒体流传输客户端);
  • 支持信令通道网络传输协议TCP/UDP设置;
  • 支持注册、注销,支持注册刷新及注册有效期设置;
  • 支持设备目录查询应答;
  • 支持心跳机制,支持心跳间隔、心跳检测次数设置;
  • 支持移动设备位置(MobilePosition)订阅和通知;
  •  适用国家标准:GB/T 28181—2016;
  • 支持语音广播;
  • 支持语音对讲;
  • 支持图像抓拍;
  • 支持历史视音频文件检索;
  • 支持历史视音频文件下载;
  • 支持历史视音频文件回放;
  • 支持云台控制和预置位查询;
  •  [实时水印]支持动态文字水印、png水印;
  •  [镜像]Android平台支持前置摄像头实时镜像功能;
  •  [实时静音]支持实时静音/取消静音;
  •  [实时快照]支持实时快照;
  •  [降噪]支持环境音、手机干扰等引起的噪音降噪处理、自动增益、VAD检测;
  •  [外部编码前视频数据对接]支持YUV数据对接;
  •  [外部编码前音频数据对接]支持PCM对接;
  •  [外部编码后视频数据对接]支持外部H.264数据对接;
  •  [外部编码后音频数据对接]外部AAC数据对接;
  •  [扩展录像功能]支持和录像SDK组合使用,录像相关功能。

集成示例

以Android平台Camera2对接为例,信令部分需要实现如下标红接口:

/*
 * MainActivity.java
 * Author: daniusdk.com
 * WeChat: xinsheng120
 */
public class MainActivity extends Activity implements ViewTreeObserver.OnGlobalLayoutListener, Camera2Listener,
        GBSIPAgentListener, GBSIPAgentPlayListener, GBSIPAgentAudioBroadcastListener,
        GBSIPAgentDeviceControlListener, GBSIPAgentQueryCommandListener, 
        GBSIPAgentTalkListener, 
        GBSIPAgentQueryRecordInfoListener{
}

媒体数据处理接口,可参照SmartPublisherJniV2.java,如需语音广播或语音对讲,可参照SmartPlayerJniV2.java。

信令处理

GBSIPAgentListener主要系GB28181注册、心跳、DevicePosition等,如注册成功、注册超时、注册网络传输层错误、心跳异常、设备位置请求处理:

public interface GBSIPAgentListener
{
    /*注册成功
    * @param dateString: 服务器日期,用来校准设备端时间,用户自行决定是否校准设备时间
    */
    void ntsRegisterOK(String dateString);

    /*
    *注册超时
    */
    void ntsRegisterTimeout();

    /*
    *注册网络传输层异常
    */
    void ntsRegisterTransportError(String errorInfo);

    /*
    *心跳达到异常次数
    */
    void ntsOnHeartBeatException(int exceptionCount, String lastExceptionInfo);

    /*
     * 设备位置请求, 这个主要用在移动设备位置订阅上
     * @param interval 请求间隔, 单位是毫秒
     */
    void ntsOnDevicePositionRequest(String deviceId, int interval);
}

GBSIPAgentPlayListener主要系GB28181的Invite、Ack、Bye等处理:

public interface GBSIPAgentPlayListener {

    /*
     *收到s=Play的实时视音频点播
     */
    void ntsOnInvitePlay(String deviceId, SessionDescription sessionDescription);

    /*
     *发送play invite response 异常
     */
    void ntsOnPlayInviteResponseException(String deviceId, int statusCode, String errorInfo);

    /*
     * 收到CANCEL play INVITE请求
     */
    void ntsOnCancelPlay(String deviceId);

    /*
     * 收到Ack
     */
    void ntsOnAckPlay(String deviceId);

    /*
     * 收到Bye
     */
    void ntsOnByePlay(String deviceId);

    /*
     * 不是在收到BYE Message情况下, 终止Play
     */
    void ntsOnTerminatePlay(String deviceId);

    /*
     * Play会话对应的对话终止, 一般不会出发这个回调,目前只有在响应了200K, 但在64*T1时间后还没收到ACK,才可能会出发
    收到这个, 请做相关清理处理
    */
    void ntsOnPlayDialogTerminated(String deviceId);
}

GBSIPAgentAudioBroadcastListener主要系GB28181语音广播处理相关,如有语音广播相关需求,可参照demo实例实现:

public interface GBSIPAgentAudioBroadcastListener {

    /*
     *收到语音广播通知
     */
    void ntsOnNotifyBroadcastCommand(String fromUserName, String fromUserNameAtDomain, String sn, String sourceID, String targetID);

    /*
     *需要准备接受语音广播的SDP内容
     */
    void ntsOnAudioBroadcast(String commandFromUserName, String commandFromUserNameAtDomain, String sourceID, String targetID);

    /*
     *音频广播, 发送Invite请求异常
     */
    void ntsOnInviteAudioBroadcastException(String sourceID, String targetID, String errorInfo);

    /*
     *音频广播, 等待Invite响应超时
     */
    void ntsOnInviteAudioBroadcastTimeout(String sourceID, String targetID);

    /*
     *音频广播, 收到Invite消息最终响应
     */
    void ntsOnInviteAudioBroadcastResponse(String sourceID, String targetID, int statusCode, SessionDescription sessionDescription);

    /*
     * 音频广播, 收到BYE Message
     */
    void ntsOnByeAudioBroadcast(String sourceID, String targetID);


    /*
     * 不是在收到BYE Message情况下, 终止音频广播
     */
    void ntsOnTerminateAudioBroadcast(String sourceID, String targetID);
}

GBSIPAgentDeviceControlListener主要系GB28181设备控制相关,比如远程启动、云台控制:

public interface GBSIPAgentDeviceControlListener {

    /*
     * 收到远程启动控制命令
     */
    void ntsOnDeviceControlTeleBootCommand(String deviceId, String teleBootValue);

    /*
    * 云台控制
     */
    void ntsOnDeviceControlPTZCmd(String deviceId, String typeValue);
}

GBSIPAgentQueryCommandListener主要系GB28181查询命令,如预置位查询:

public interface GBSIPAgentQueryCommandListener {

    /*
     * 设备预置位查询
     */
    void ntsOnDevicePresetQueryCommand(String fromUserName, String fromUserNameAtDomain, String sn, String deviceId);
}

GBSIPAgentTalkListener主要系GB28181语音对讲相关处理:

public interface GBSIPAgentTalkListener {
    /*
     *收到s=Talk 语音对讲
     */
    void ntsOnInviteTalk(String deviceId, SessionDescription sessionDescription);

    /*
     *发送talk invite response 异常
     */
    void ntsOnTalkInviteResponseException(String deviceId, int statusCode, String errorInfo);

    /*
     * 收到CANCEL Talk INVITE请求
     */
    void ntsOnCancelTalk(String deviceId);

    /*
     * 收到Ack
     */
    void ntsOnAckTalk(String deviceId);

    /*
     * 收到Bye
     */
    void ntsOnByeTalk(String deviceId);

    /*
     * 不是在收到BYE Message情况下, 终止Talk
     */
    void ntsOnTerminateTalk(String deviceId);

    /*
     * Talk会话对应的对话终止, 一般不会出发这个回调,目前只有在响应了200K, 但在64*T1时间后还没收到ACK,才可能会出发
    收到这个, 请做相关清理处理
    */
    void ntsOnTalkDialogTerminated(String deviceId);
}

GBSIPAgentPlaybackListener系历史视音频回放相关:

public interface GBSIPAgentPlaybackListener {
    void ntsOnInvitePlayback(long var1, String var3, SessionDescription var4);

    void ntsOnPlaybackInviteResponseException(long var1, String var3, int var4, String var5);

    void ntsOnCancelPlayback(long var1, String var3);

    void ntsOnAckPlayback(long var1, String var3);

    void ntsOnPlaybackMANSRTSPPlayCommand(long var1, String var3);

    void ntsOnPlaybackMANSRTSPPauseCommand(long var1, String var3);

    void ntsOnPlaybackMANSRTSPScaleCommand(long var1, String var3, double var4);

    void ntsOnPlaybackMANSRTSPSeekCommand(long var1, String var3, double var4);

    void ntsOnPlaybackMANSRTSPTeardownCommand(long var1, String var3);

    void ntsOnByePlayback(long var1, String var3);

    void ntsOnTerminatePlayback(long var1, String var3);

    void ntsOnPlaybackDialogTerminated(long var1, String var3);
}

GBSIPAgentDownloadListen系历史视音频下载相关:

public interface GBSIPAgentDownloadListener {
    void ntsOnInviteDownload(long var1, String var3, SessionDescription var4);

    void ntsOnDownloadInviteResponseException(long var1, String var3, int var4, String var5);

    void ntsOnCancelDownload(long var1, String var3);

    void ntsOnAckDownload(long var1, String var3);

    void ntsOnDownloadMANSRTSPScaleCommand(long var1, String var3, double var4);

    void ntsOnByeDownload(long var1, String var3);

    void ntsOnTerminateDownload(long var1, String var3);

    void ntsOnDownloadDialogTerminated(long var1, String var3);
}
媒体数据处理
RTP数据发送

RTP Sender(SmartPublisherJniV2.java)相关接口设计:

/*
 * SmartPublisherJniV2.java
 * Author: https://daniusdk.com
 * WeChat:xinsheng120
 */
/*
 * 创建RTP Sender实例
 *
 * @param reserve:保留参数传0
 *
 * @return RTP Sender 句柄,0表示失败
 */
public native long CreateRTPSender(int reserve);

/**
 *设置 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);

/**
 *设置 RTP Sender IP地址类型
 *
 * @param rtp_sender_handle, CreateRTPSender返回值
 * @param ip_address_type, 0:IPV4, 1:IPV6, 默认是IPV4, 当前仅支持IPV4
 *
 * @return {0} if successful
 */
public native int SetRTPSenderIPAddressType(long rtp_sender_handle, int ip_address_type);

/**
 *设置 RTP Sender RTP Socket本地端口
 *
 * @param rtp_sender_handle, CreateRTPSender返回值
 * @param port, 必须是偶数,设置0的话SDK会自动分配, 默认值是0
 *
 * @return {0} if successful
 */
public native int SetRTPSenderLocalPort(long rtp_sender_handle, int port);

/**
 *设置 RTP Sender SSRC
 *
 * @param rtp_sender_handle, CreateRTPSender返回值
 * @param ssrc, 如果设置的话,这个字符串要能转换成uint32类型, 否则设置失败
 *
 * @return {0} if successful
 */
public native int SetRTPSenderSSRC(long rtp_sender_handle, String ssrc);

/**
 *设置 RTP Sender RTP socket 发送Buffer大小
 *
 * @param rtp_sender_handle, CreateRTPSender返回值
 * @param buffer_size, 必须大于0, 默认是512*1024, 当前仅对UDP socket有效, 根据视频码率考虑设置合适的值
 *
 * @return {0} if successful
 */
public native int SetRTPSenderSocketSendBuffer(long rtp_sender_handle, int buffer_size);

/**
 *设置 RTP Sender RTP时间戳时钟频率
 *
 * @param rtp_sender_handle, CreateRTPSender返回值
 * @param clock_rate, 必须大于0, 对于GB28181 PS规定是90kHz, 也就是90000
 *
 * @return {0} if successful
 */
public native int SetRTPSenderClockRate(long rtp_sender_handle, int clock_rate);

/**
 *设置 RTP Sender 目的IP地址, 注意当前用在GB2818推送上,只设置一个地址,将来扩展如果用在其他地方,可能要设置多个目的地址,到时候接口可能会调整
 *
 * @param rtp_sender_handle, CreateRTPSender返回值
 * @param address, IP地址
 * @param port, 端口
 *
 * @return {0} if successful
 */
public native int SetRTPSenderDestination(long rtp_sender_handle, String address, int port);

/**
 * 设置是否开启 RTP Receiver
 * @param rtp_sender_handle, CreateRTPSender返回值
 * @param is_enable, 0表示不收RTP包, 1表示收RTP包, SDK默认值为0.
 * @return
 */
public native int EnableRTPSenderReceive(long rtp_sender_handle, int is_enable);

/**
 *设置RTP Receiver SSRC
 *
 * @param rtp_sender_handle, CreateRTPSender返回值
 * @param ssrc, 如果设置的话,这个字符串要能转换成uint32类型, 否则设置失败
 *
 * @return {0} if successful
 */
public native int SetRTPSenderReceiveSSRC(long rtp_sender_handle, String ssrc);

/**
 *设置RTP Receiver Payload 相关信息
 *
 * @param rtp_sender_handle, CreateRTPSender返回值
 *
 * @param payload_type, 请参考 RFC 3551
 *
 * @param encoding_name, 编码名, 请参考 RFC 3551, 如果payload_type不是动态的, 可能传null就好
 *
 * @param media_type, 媒体类型, 请参考 RFC 3551, 1 是视频, 2是音频
 *
 * @param clock_rate, 请参考 RFC 3551
 *
 * @return {0} if successful
 */
public native int SetRTPSenderReceivePayloadType(long rtp_sender_handle, int payload_type, String encoding_name, int media_type, int clock_rate);

/**
 *设置RTP Receiver PS的pts和dts clock frequency
 *
 * @param rtp_sender_handle, CreateRTPSender返回值
 *
 * @param ps_clock_frequency, 默认是90000, 一些特殊场景需要设置
 *
 * @return {0} if successful
 */
public native int SetRTPSenderReceivePSClockFrequency(long rtp_sender_handle, int ps_clock_frequency);

/**
 *设置 RTP Receiver 音频采样率
 *
 * @param rtp_sender_handle, CreateRTPSender返回值
 * @param sampling_rate, 音频采样率
 *
 * @return {0} if successful
 */
public native int SetRTPSenderReceiveAudioSamplingRate(long rtp_sender_handle, int sampling_rate);

/**
 *设置 RTP Receiver 音频通道数
 *
 * @param rtp_sender_handle, CreateRTPSender返回值
 * @param channels, 音频通道数
 *
 * @return {0} if successful
 */
public native int SetRTPSenderReceiveAudioChannels(long rtp_sender_handle, int channels);

/**
 *初始化RTP Sender, 初始化之前先调用上面的接口配置相关参数
 *
 * @param rtp_sender_handle, CreateRTPSender返回值
 *
 * @return {0} if successful
 */
public native int InitRTPSender(long rtp_sender_handle);

/**
 *获取RTP Sender RTP Socket本地端口
 *
 * @param rtp_sender_handle, CreateRTPSender返回值
 *
 * @return 失败返回0, 成功的话返回响应的端口, 请在InitRTPSender返回成功之后调用
 */
public native int GetRTPSenderLocalPort(long rtp_sender_handle);

/**
 * UnInit RTP Sender
 *
 * @param rtp_sender_handle, CreateRTPSender返回值
 *
 * @return {0} if successful
 */
public native int UnInitRTPSender(long rtp_sender_handle);

/**
 * 释放RTP Sender, 释放之后rtp_sender_handle就无效了,请不要再使用
 *
 * @param rtp_sender_handle, CreateRTPSender返回值
 *
 * @return {0} if successful
 */
public native int DestoryRTPSender(long rtp_sender_handle);
RTP数据接收

对应RTP Receiver(SmartPlayerJniV2.java)相关接口设计,如无语音广播或语音对讲相关技术需求,这部分可忽略:

/*
 * SmartPlayerJniV2.java
 * Author: https://daniusdk.com
 * WeChat: xinsheng120
 */
/*
 * 创建RTP Receiver
 *
 * @param reserve:保留参数传0
 *
 * @return RTP Receiver 句柄,0表示失败
 */
public native long CreateRTPReceiver(int reserve);


/**
 *设置 RTP Receiver传输协议
 *
 * @param rtp_receiver_handle, CreateRTPReceiver
 * @param transport_protocol, 0:UDP, 1:TCP, 默认是UDP
 *
 * @return {0} if successful
 */
public native int SetRTPReceiverTransportProtocol(long rtp_receiver_handle, int transport_protocol);


/**
 *设置 RTP Receiver IP地址类型
 *
 * @param rtp_receiver_handle, CreateRTPReceiver
 * @param ip_address_type, 0:IPV4, 1:IPV6, 默认是IPV4
 *
 * @return {0} if successful
 */
public native int SetRTPReceiverIPAddressType(long rtp_receiver_handle, int ip_address_type);


/**
 *设置 RTP Receiver RTP Socket本地端口
 *
 * @param rtp_receiver_handle, CreateRTPReceiver
 * @param port, 必须是偶数,设置0的话SDK会自动分配, 默认值是0
 *
 * @return {0} if successful
 */
public native int SetRTPReceiverLocalPort(long rtp_receiver_handle, int port);


/**
 *设置 RTP Receiver SSRC
 *
 * @param rtp_receiver_handle, CreateRTPReceiver
 * @param ssrc, 如果设置的话,这个字符串要能转换成uint32类型, 否则设置失败
 *
 * @return {0} if successful
 */
public native int SetRTPReceiverSSRC(long rtp_receiver_handle, String ssrc);


/**
 *创建 RTP Receiver 会话
 *
 * @param rtp_receiver_handle, CreateRTPReceiver
 * @param reserve, 保留值,目前传0
 *
 * @return {0} if successful
 */
public native int CreateRTPReceiverSession(long rtp_receiver_handle, int reserve);


/**
 *获取 RTP Receiver RTP Socket本地端口
 *
 * @param rtp_receiver_handle, CreateRTPReceiver
 *
 * @return 失败返回0, 成功的话返回响应的端口, 请在CreateRTPReceiverSession返回成功之后调用
 */
public native int GetRTPReceiverLocalPort(long rtp_receiver_handle);


/**
 *设置 RTP Receiver Payload 相关信息
 *
 * @param rtp_receiver_handle, CreateRTPReceiver
 *
 * @param payload_type, 请参考 RFC 3551
 *
 * @param encoding_name, 编码名, 请参考 RFC 3551, 如果payload_type不是动态的, 可能传null就好
 *
 * @param media_type, 媒体类型, 请参考 RFC 3551, 1 是视频, 2是音频
 *
 * @param clock_rate, 请参考 RFC 3551
 *
 * @return {0} if successful
 */
public native int SetRTPReceiverPayloadType(long rtp_receiver_handle, int payload_type, String encoding_name, int media_type, int clock_rate);


/**
 *设置 RTP Receiver 音频采样率
 *
 * @param rtp_receiver_handle, CreateRTPReceiver
 * @param sampling_rate, 音频采样率
 *
 * @return {0} if successful
 */
public native int SetRTPReceiverAudioSamplingRate(long rtp_receiver_handle, int sampling_rate);

/**
 *设置 RTP Receiver 音频通道数
 *
 * @param rtp_receiver_handle, CreateRTPReceiver
 * @param channels, 音频通道数
 *
 * @return {0} if successful
 */
public native int SetRTPReceiverAudioChannels(long rtp_receiver_handle, int channels);


/**
 *设置 RTP Receiver 远端地址
 *
 * @param rtp_receiver_handle, CreateRTPReceiver
 * @param address, IP地址
 * @param port, 端口
 *
 * @return {0} if successful
 */
public native int SetRTPReceiverRemoteAddress(long rtp_receiver_handle, String address, int port);

/**
 *初始化 RTP Receiver
 *
 * @param rtp_receiver_handle, CreateRTPReceiver
 *
 * @return {0} if successful
 */
public native int InitRTPReceiver(long rtp_receiver_handle);

/**
 *UnInit RTP Receiver
 *
 * @param rtp_receiver_handle, CreateRTPReceiver
 *
 * @return {0} if successful
 */
public native int UnInitRTPReceiver(long rtp_receiver_handle);


/**
 *Destory RTP Receiver Session
 *
 * @param rtp_receiver_handle, CreateRTPReceiver
 *
 * @return {0} if successful
 */
public native int DestoryRTPReceiverSession(long rtp_receiver_handle);


/**
 *Destory RTP Receiver
 *
 * @param rtp_receiver_handle, CreateRTPReceiver
 *
 * @return {0} if successful
 */
public native int DestoryRTPReceiver(long rtp_receiver_handle);

PostAudioPacket(SmartPlayerJniV2.java),投递音频包给外部Live source,目前仅于语音对讲使用:

/*
 * SmartPlayerJniV2.java
 * Author: https://daniusdk.com
 */
/**
 * 投递音频包给外部Live source, 注意ByteBuffer对象必须是DirectBuffer
 *
 * @param handle: return value from SmartPlayerOpen()
 *
 * @return {0} if successful
 */
public native int PostAudioPacket(long handle, int codec_id,
                          java.nio.ByteBuffer packet, int offset, int size, long pts, boolean is_pts_discontinuity,
                          java.nio.ByteBuffer extra_data, int extra_data_offset, int extra_data_size, int sample_rate, int channels);
GB28181接口调用

对应GB28181相关接口调用相关设计如下:

/*
 * SmartPublisherJniV2.java
 * Author: https://daniusdk.com
 * WeChat: xinsheng120
 */
/**
 * 设置GB28181 RTP Sender
 *
 * @param rtp_sender_handle, CreateRTPSender返回值
 * @param rtp_payload_type, 对于GB28181 PS, 协议定义是96, 具体以SDP为准,  RFC 3551有定义
 * @param encoding_name, 编码名, 请参考 RFC 3551, 当前仅支持: "PS", 其他值返回失败
 * @return {0} if successful
 */
public native int SetGB28181RTPSender(long handle, long rtp_sender_handle, int rtp_payload_type, String encoding_name);

/**
 * 设置GB28181 RTP 收到的音频包回调
 * @param handle
 * @param audio_packet_callback
 * @return
 */
public native int SetGB28181ReceiveAudioPacketCallback(long handle, NTAudioPacketCallback audio_packet_callback);

/**
 * 启动 GB28181 媒体流
 *
 * @return {0} if successful
 */
public native int StartGB28181MediaStream(long handle);

/**
 * 停止 GB28181 媒体流
 *
 * @return {0} if successful
 */
public native int StopGB28181MediaStream(long handle);

GB28181未来发展趋势

GB28181规范目前已经迎来了2022版,随着规范行业影响力和应用范围越来越大,相信还会有类似2026、2030等迭代版本出来,我们预测的GB28181发展趋势可能会是以下几个方面,感兴趣的也可以跟我单独探讨:

  1. 技术标准持续优化
    • 编码格式升级:随着视频技术的不断发展,未来 GB28181 在编码格式方面会不断优化和扩展。目前已经增加了对 H.265 等高效编码格式的支持,后续可能会进一步提升对新一代编码标准的兼容性和适应性,以提高视频传输的效率和质量,降低带宽占用。例如,在一些对画质和带宽要求较高的场景中,更先进的编码格式能够更好地满足需求。
    • 传输协议改进:在传输协议上,会不断增强其稳定性和可靠性。可能会对现有协议的一些细节进行优化,减少传输延迟、丢包等问题,提高信令交互的效率。同时,也会适应网络技术的发展,更好地支持 5G、IPv6 等新的网络环境,以满足大规模、高并发的视频传输需求。
    • 安全性增强:视频监控涉及到公共安全和个人隐私等重要信息,因此安全性将是未来发展的重点。GB28181 会不断加强对数据加密、身份认证、访问控制等安全机制的要求和规范,以应对日益复杂的网络安全威胁。例如,采用更先进的加密算法,加强对设备和用户的身份认证管理,确保视频数据的安全传输和存储。
  2. 与其他标准和技术的融合
    • 与物联网融合:物联网技术的发展使得各种设备之间的互联互通变得更加紧密。GB28181 会与物联网技术进一步融合,实现视频监控系统与其他智能设备的联动,如与传感器、门禁系统、消防系统等进行信息交互和协同工作。例如,当传感器检测到异常情况时,能够自动触发视频监控系统进行录像和报警,提高安全防范的智能化水平。
    • 与人工智能结合:人工智能技术在视频分析领域的应用越来越广泛。未来,GB28181 会与人工智能技术深度结合,实现对视频内容的智能分析和处理,如人脸识别、行为分析、车牌识别等。这将大大提高视频监控的效率和价值,为公共安全、交通管理、企业管理等领域提供更强大的技术支持。
    • 与云计算结合:云计算技术为视频监控系统的存储和计算提供了强大的支持。GB28181 会与云计算技术进一步结合,实现视频数据的云存储和云处理,降低用户的硬件投资和维护成本。同时,通过云计算平台的资源共享和弹性扩展能力,能够更好地满足不同用户的需求。
  3. 应用场景不断拓展
    • 智慧城市建设:在智慧城市建设中,视频监控是重要的组成部分。GB28181 将在智慧城市的各个领域得到广泛应用,如城市交通管理、公共安全防控、城市环境监测等。通过与其他城市管理系统的集成,实现信息的共享和协同工作,为城市的智能化管理提供有力支持。
    • 智能安防领域:除了公共安全领域,GB28181 在智能安防领域的应用也会不断拓展。例如,在企业安防、社区安防、家庭安防等场景中,基于 GB28181 的视频监控系统能够实现多设备的互联互通和集中管理,提高安防系统的可靠性和智能化水平。
    • 跨行业应用:GB28181 的应用范围将不仅仅局限于安防领域,还会向其他行业拓展。例如,在教育、医疗、金融等行业,视频监控系统也有着广泛的需求。GB28181 可以为这些行业的视频监控系统提供标准化的解决方案,促进不同行业之间的视频资源整合和共享。
  4. 产业生态不断完善
    • 设备兼容性提高:随着 GB28181 的不断推广和应用,设备厂商会更加注重产品的兼容性,生产出更多符合 GB28181 标准的设备。这将使得不同厂商的设备之间能够更好地实现互联互通,减少系统集成的难度和成本,促进视频监控产业的健康发展。
    • 产业协同合作加强:GB28181 的发展需要产业链上各个环节的协同合作,包括设备厂商、软件开发商、系统集成商、运营商等。未来,这些企业之间的合作会更加紧密,共同推动 GB28181 技术的不断创新和应用,形成更加完善的产业生态。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【北京迅为】《STM32MP157开发板嵌入式开发指南》- 第十八章 Linux编写第一个自己的命令

iTOP-STM32MP157开发板采用ST推出的双核cortex-A7单核cortex-M4异构处理器,既可用Linux、又可以用于STM32单片机开发。开发板采用核心板底板结构,主频650M、1G内存、8G存储,核心板采用工业级板对板连接器,高可靠,牢固耐…

企业安全策略制定

如今,网络安全是所有组织的必需品,而不是奢侈品。现代企业面临着针对其数据、网络和系统的复杂且不断演变的威胁。 即使一个漏洞也可能导致严重违规、财务损失和声誉受损。正如堡垒依靠多层防御共同作用一样,公司的安全措施必须作为一个整体…

【学习笔记】手写 Tomcat 六

目录 一、线程池 1. 构建线程池的类 2. 创建任务 3. 执行任务 测试 二、URL编码 解决方案 测试 三、如何接收客户端发送的全部信息 解决方案 测试 四、作业 1. 了解工厂模式 2. 了解反射技术 一、线程池 昨天使用了数据库连接池,我们了解了连接池的优…

渗透测试--文件上传常用绕过方式

文件上传常用绕过方式 1.前端代码,限制只允许上传图片。修改png为php即可绕过前端校验。 2.后端校验Content-Type 校验文件格式 前端修改,抓取上传数据包,并且修改 Content-Type 3.服务端检测(目录路径检测) 对目…

医院体检管理系统小程序的设计

管理员账户功能包括:系统首页,个人中心,用户管理,体检分类管理,体检套餐管理,体检预约管理,体检报告管理,系统管理 微信端账号功能包括:系统首页,体检套餐&a…

四、Drf认证组件

四、Drf认证组件 4.1 快速使用 from django.shortcuts import render,HttpResponse from rest_framework.response import Response from rest_framework.views import APIView from rest_framework.authentication import BaseAuthentication from rest_framework.exception…

数据结构:将复杂的现实问题简化为计算机可以理解和处理的形式

整句话的总体意义是,**数据结构是用于将现实世界中的实体和关系抽象为数学模型,并在计算机中表示和实现的关键工具**。它不仅包括如何存储数据,还包括对这些数据的操作,能够有效支持计算机程序的运行。通过这一过程,数…

利用PDLP扩展线性规划求解能力

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

Java项目实战II基于Java+Spring Boot+MySQL的甘肃非物质文化网站设计与实现(源码+数据库+文档)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者 一、前言 甘肃省作为中国历史文化名省,拥有丰富的非物质文化遗产资源,涵盖表演艺术、手…

TypeScript 封装 Axios 1.7.7

随着Axios版本的不同,类型也在改变,以后怎么写类型? 1. 封装Axios 将Axios封装成一个类,同时重新封装request方法 重新封装request有几个好处: 所有的请求将从我们定义的requet请求中发送,这样以后更换…

Golang | Leetcode Golang题解之第441题排列硬币

题目: 题解: func arrangeCoins(n int) int {return sort.Search(n, func(k int) bool { k; return k*(k1) > 2*n }) }

【Unity服务】如何使用Unity Version Control

Unity上的线上服务有很多,我们接触到的第一个一般就是Version Control,用于对项目资源的版本管理。 本文介绍如何为项目添加Version Control,并如何使用,以及如何将项目与Version Control断开链接。 其实如果仅仅是对项目资源进…

09_OpenCV彩色图片直方图

import cv2 import numpy as np import matplotlib.pyplot as plt %matplotlib inlineimg cv2.imread(computer.jpeg, 1) img cv2.cvtColor(img, cv2.COLOR_BGR2RGB) plt.imshow(img) plt.show()plot绘制直方图 plt.hist(img.ravel(), 256) #ravel() 二维降一维 256灰度级…

学习记录:js算法(五十):二叉树的右视图

文章目录 二叉树的右视图我的思路网上思路 总结 二叉树的右视图 给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。 图一: 示例 1:如图一 输入: [1,2,3,null,5,null,4] …

C++面向对象基础

目录 一.函数 1.内联函数 2.函数重载 3.哑元函数 二.类和对象 2.1 类的定义 2.2 创建对象 三. 封装(重点) 四. 构造函数 constructor(重点) 4.1 基础使用 4.2 构造初始化列表 4.3 构造函数的调用方式(掌握…

解决方法:PDF文件打开之后不能打印?

打开PDF文件之后,发现文件不能打印?这是什么原因?首先我们需要先查看一下自己的打印机是否能够正常运行,如果打印机是正常的,我们再查看一下,文件中的打印功能按钮是否是灰色的状态。 如果PDF中的大多数功…

秋招内推--招联金融2025

【投递方式】 直接扫下方二维码,或点击内推官网https://wecruit.hotjob.cn/SU61025e262f9d247b98e0a2c2/mc/position/campus,使用内推码 igcefb 投递) 【招聘岗位】 后台开发 前端开发 数据开发 数据运营 算法开发 技术运维 软件测试 产品策…

数据结构-LRU缓存(C语言实现)

遇到困难,不必慌张,正是成长的时候,耐心一点! 目录 前言一、题目介绍二、实现过程2.1 实现原理2.2 实现思路2.2.1 双向链表2.2.2 散列表 2.3 代码实现2.3.1 结构定义2.3.2 双向链表操作实现2.3.3 实现散列表的操作2.3.4 内存释放代…

SigmaStudio控件Cross Mixer\Signal Merger算法效果分析

衰减与叠加混音算法验证分析一 CH2:输入源为-20dB正弦波1khz CH1叠加混音:参考混音算法https://blog.csdn.net/weixin_48408892/article/details/129878036?spm1001.2014.3001.5502 Ch0衰减混音:外部多个输入源做混音时,建议参考该算法控件&…

在VMware虚拟机上部署polardb

免密登录到我们的虚拟机之后,要在虚拟机上部署polardb数据库,首先第一步要先克隆源码: 为了进SSH协议进行传输源码需要先进行下面的步骤: 将宿主机上的私钥文件复制到虚拟机上 scp "C:\Users\waitw\.ssh\id_rsa" ann…