GB28181媒体保活机制探究与实现

2023-02-16 12:40:53 浏览数 (1)

规范解读

GB28181-2016和GB28181-2022关于媒体保活机制这块,并无调整,平台、设备媒体流保活机制规定如下:

a)链路建立后,码流经过的各级平台应具备媒体流丢失监测能力,若监测到媒体流丢失,应释放该条媒体链路,并通过会话内Bye消息通知上下级平台;

b)上下级平台之间、平台与设备之间、平台与客户端之间应通过注册,状态信息报送等进行状态监测,若监测到媒体流接收方或媒体流发送方故障或离线,应主动释放媒体链路,停止媒体流的发送;

c)通过Subject标识进行已发送流的清理判断。上级平台向下级平台、平台向设备发送呼叫请求时,应携带Subject头域,Subject头域的“媒体流发送者ID:发送方媒体流序列号”用于对媒体源标识,此标识与请求的码流具有对应关系。下级平台,设备在接收到呼叫请求后,应判断是否在发送以此媒体源标识的码流,若已经在发送,则应释放现有媒体流发送链路并按照请求建立新的媒体流发送链路。

技术实现

本文以大牛直播SDK的Android平台GB28181设备接入模块为例,启动GB28181即注册到国标平台侧,并按照周期发送信条信令:

和心跳相关的参数设置如下:

代码语言:javascript复制
private int gb28181_reg_expired_           = 3600; // 注册有效期时间最小3600秒
private int gb28181_heartbeat_interval_    = 20; // 心跳间隔GB28181默认是60, 目前调整到20秒
private int gb28181_heartbeat_count_       = 3; // 心跳间隔3次失败,表示和服务器断开了

InitGB28181Agent()的时候,设置下去:

代码语言:javascript复制
// GB28181配置
gb28181_agent_.config(gb28181_reg_expired_, gb28181_heartbeat_interval_, gb28181_heartbeat_count_);

心跳异常处理如下:

代码语言:javascript复制
//Author: daniusdk.com
@Override
public void ntsOnHeartBeatException(int exceptionCount,  String lastExceptionInfo) {
    Log.e(TAG, "ntsOnHeartBeatException heart beat timeout count reached, count:"   exceptionCount 
            ", exception info:"   (lastExceptionInfo!=null?lastExceptionInfo:""));

    // 停止信令, 然后重启
    handler_.postDelayed(new Runnable() {
        @Override
        public void run() {
            Log.i(TAG, "gb28281_heart_beart_timeout");

            stopAudioPlayer();
            destoryRTPReceiver();

            if (gb_broadcast_source_id_ != null && gb_broadcast_target_id_ != null && gb28181_agent_ != null)
                gb28181_agent_.byeAudioBroadcast(gb_broadcast_source_id_, gb_broadcast_target_id_);

            gb_broadcast_source_id_ = null;
            gb_broadcast_target_id_ = null;
            btnGB28181AudioBroadcast.setText("GB28181语音广播");
            btnGB28181AudioBroadcast.setEnabled(false);

            stopGB28181Stream();
            destoryRTPSender();

            if (gb28181_agent_ != null) {
                gb28181_agent_.terminateAllPlays(true);

                Log.i(TAG, "gb28281_heart_beart_timeout sip stop");
                gb28181_agent_.stop();

                String local_ip_addr = IPAddrUtils.getIpAddress(context_);
                if (local_ip_addr != null && !local_ip_addr.isEmpty() ) {
                    Log.i(TAG, "gb28281_heart_beart_timeout get local ip addr: "   local_ip_addr);
                    gb28181_agent_.setLocalAddress(local_ip_addr);
                }

                Log.i(TAG, "gb28281_heart_beart_timeout sip start");
                gb28181_agent_.start();
            }
        }

    },0);
}

总结

GB28181媒体保活机制,相对比较清晰,不会有大的规范解读误区,感兴趣的开发者,可以参考实现。

0 人点赞