GB28181平台如何接入无人机实现智能巡检?

2023-11-08

大家都知道,无人机巡检系统,有效解决了传统巡查工作空间和时间局限问题,降低人力工作成本,有效替代人工巡检工作模式。智能巡检系统通过人工智能技术和机械智能技术完美结合,在工业等场景下,应用非常广泛。本文旨在讲如何实现无人机(如大疆无人机)数据到GB28181平台(如海康、大华、宇视等国标平台)。

本文以Android平台接入大疆无人机为例,首先,无人机可以通过厂商提供的接口,回调编码后的H.264/H.265数据,需要注意的是,由于GB/T28181-2016,官方规范,仅对H.264做过描述,考虑到系统通用性和尽可能的规避转码带来的性能或使用体验问题,一般建议H.264编码。

无人机的数据会上来后,可以通过编码后的数据接口,投递到JNI层,把视音频数据封装成PS包,让把PS包以负载的方式封装成RTP包,完成媒体数据的上传即可。

本文以转发的模块为例说明,无图无真相:

具体实现:APP启动后,我们先点击启动GB28181按钮,完成到国标平台的注册,并通过心跳机制,保持和国标平台端的通信。

当国标平台端,需要查看无人机的实时画面时,可以发送Invite,请求无人机画面,Android平台GB28181接入模块,这时启动拉取无人机回调数据,并完成数据投递,和H.264到PS到RTP的打包上传即可。

/*
* MainActivity.java
* GitHub: https://github.com/daniulive/SmarterStreaming
*/
class ButtonGB28181AgentListener implements OnClickListener {
  public void onClick(View v) {
    stopGB28181Stream();
    destoryRTPSender();

    if (null == gb28181_agent_ ) {
      if( !initGB28181Agent() )
        return;
    }

    if (gb28181_agent_.isRunning()) {
      gb28181_agent_.terminateAllPlays(true);// 目前测试下来,发送BYE之后,有些服务器会立即发送INVITE,是否发送BYE根据实际情况看
      gb28181_agent_.stop();
      btnGB28181Agent.setText("启动GB28181");
    }
    else {
      if ( gb28181_agent_.start() ) {
        btnGB28181Agent.setText("停止GB28181");
      }
    }
  }
}

//停止GB28181 媒体流
private void stopGB28181Stream() {
  if(!isGB28181StreamRunning)
    return;

  if (libPublisher != null) {
    libPublisher.StopGB28181MediaStream(publisherHandle);
  }

  if (!isRecording && !isRTSPPublisherRunning && !isPushing) {
    if (publisherHandle != 0) {
      if (libPublisher != null) {
        libPublisher.SmartPublisherClose(publisherHandle);
        publisherHandle = 0;
      }
    }
  }

  isGB28181StreamRunning = false;
}

开放的video数据投递接口如下:

/**
 * 设置编码后视频数据(H.264)
 *
 * @param codec_id, H.264对应 1
 *
 * @param data 编码后的video数据
 *
 * @param size data length
 *
 * @param is_key_frame 是否I帧, if with key frame, please set 1, otherwise, set 0.
 *
 * @param timestamp video timestamp
 *
 * @param pts Presentation Time Stamp, 显示时间戳
 *
 * @return {0} if successful
 */
public native int SmartPublisherPostVideoEncodedData(long handle, int codec_id, ByteBuffer data, int size, int is_key_frame, long timestamp, long pts);

如果还有audio的话,audio数据接口如下:

/**
 * 设置音频数据(AAC/PCMA/PCMU/SPEEX)
 *
 * @param codec_id:
 *
 *  NT_MEDIA_CODEC_ID_AUDIO_BASE = 0x10000,
 * NT_MEDIA_CODEC_ID_PCMA = NT_MEDIA_CODEC_ID_AUDIO_BASE,
 * NT_MEDIA_CODEC_ID_PCMU,
 * NT_MEDIA_CODEC_ID_AAC,
 * NT_MEDIA_CODEC_ID_SPEEX,
 * NT_MEDIA_CODEC_ID_SPEEX_NB,
 * NT_MEDIA_CODEC_ID_SPEEX_WB,
 * NT_MEDIA_CODEC_ID_SPEEX_UWB,
 *
 * @param data audio数据
 *
 * @param size data length
 *
 * @param is_key_frame 是否I帧, if with key frame, please set 1, otherwise, set 0, audio忽略
 *
 * @param timestamp video timestamp
 *
 * @param parameter_info 用于AAC special config信息填充
 *
 * @param parameter_info_size parameter info size
 *
 * @return {0} if successful
 */
public native int SmartPublisherPostAudioEncodedData(long handle, int codec_id, ByteBuffer data, int size, int is_key_frame, long timestamp,ByteBuffer parameter_info, int parameter_info_size);

其他信令交互流程前面提到很多次了,本文不再赘述,这里主要看看Invite和Ack的处理:

先看Invite处理:

@Override
  public void ntsOnInvitePlay(String deviceId, PlaySessionDescription session_des) {
    handler_.postDelayed(new Runnable() {
      @Override
      public void run() {
        MediaSessionDescription video_des = session_des_.getVideoDescription();
        SDPRtpMapAttribute ps_rtpmap_attr = video_des.getPSRtpMapAttribute();

        Log.i(TAG,"ntsInviteReceived, 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, "ntsInviteReceived 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); // 设置到2M
        libPublisher.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_);
        gb28181_agent_.respondPlayInviteOK(device_id_,local_ip_addr, local_port);

        gb28181_rtp_sender_handle_ = rtp_sender_handle;
      }

      private String device_id_;
      private PlaySessionDescription session_des_;

      public Runnable set(String device_id, PlaySessionDescription session_des) {
        this.device_id_ = device_id;
        this.session_des_ = session_des;
        return this;
      }
    }.set(deviceId, session_des),0);
  }

  @Override
  public void ntsOnCancelPlay(String deviceId) {
    // 这里取消Play会话
    handler_.postDelayed(new Runnable() {
      @Override
      public void run() {
        Log.i(TAG, "ntsOnCancelPlay, deviceId=" + device_id_);

        destoryRTPSender();
      }

      private String device_id_;

      public Runnable set(String device_id) {
        this.device_id_ = device_id;
        return this;
      }

    }.set(deviceId),0);
  }

Ack后调用StartGB28181MediaStream(),开始发送大疆无人机编码后的数据到国标平台端。

@Override
public void ntsOnAckPlay(String deviceId) {
  handler_.postDelayed(new Runnable() {
    @Override
    public void run() {
      Log.i(TAG,"ntsOnACKPlay, device_id:" +device_id_);

      if (!isRecording && !isRTSPPublisherRunning && !isPushing) {
        OpenPushHandle();
      }

      libPublisher.SetGB28181RTPSender(publisherHandle, gb28181_rtp_sender_handle_, gb28181_rtp_payload_type_, gb28181_rtp_encoding_name_);
      int startRet = libPublisher.StartGB28181MediaStream(publisherHandle);
      if (startRet != 0) {

        if (!isRecording && !isRTSPPublisherRunning && !isPushing) {
          if (publisherHandle != 0) {
            libPublisher.SmartPublisherClose(publisherHandle);
            publisherHandle = 0;
          }
        }

        destoryRTPSender();

        Log.e(TAG, "Failed to start GB28181 service..");
        return;
      }

      isGB28181StreamRunning = true;
    }

    private String device_id_;

    public Runnable set(String device_id) {
      this.device_id_ = device_id;
      return this;
    }

  }.set(deviceId),0);
}

需要注意的是,可以在国标平台端发起Invite请求,到Ack完成后,才开始调用大疆无人机的接口回调H.264数据,有些型号的无人机,也可以回调编码前的yuv/nv12等格式数据,这种我们也可以处理,自己编码即可。

由于无人机的特殊性,携带经纬度信息,也可以通过GB28181位置订阅(MobilePosition)实现无人机实时位置的更新。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GB28181平台如何接入无人机实现智能巡检? 的相关文章

  • Android平台RTMP推送或GB28181设备接入端如何实现采集audio音量放大?

    我们在做Android平台RTMP推送和GB28181设备对接的时候 遇到这样的问题 有的设备 麦克风采集出来的audio 音量过高或过低 特别是有些设备 采集到的麦克风声音过低 导致播放端听不清前端采集的audio 这时候 就需要针对采集
  • Android GB28181接入端实时位置订阅和上报之-如何获取当前经纬度

    我们在做Android平台GB28181的时候 其中实时位置 MobilePosition 订阅和上报这块 涉及到实时经纬度的获取 特别是执法记录 车载系统的那个等场景 几乎就是标配 今天主要是分享一段实时获取位置的代码 CameraPub
  • Android GB28181设备接入端语音广播和语音对讲技术实现探究

    上篇文章提到Android端GB28181接入端的语音广播和语音对讲的实现 从spec角度大概介绍了下流程和简单的接口设计 好多开发者私信我 希望展开说一下 其实这块难度不大 只是广播和对讲涉及到双向实现 如果之前没有相关的积累 从头实现麻
  • Android平台GB28181历史视音频文件检索规范探讨及技术实现

    技术背景 我们在做Android平台GB28181设备接入侧模块的时候 特别是执法记录仪或类似场景 系统除了对常规的录像有要求 还需要能和GB28181平台侧交互 比如实现设备侧视音频文件检索 下载或回放 本文假定记录仪或相关设备已经完成录
  • Android平台GB28181设备接入技术探讨

    GB T28181技术背景 在此之前 我们先对协议规范做个简单了解 GB28181协议是一种用于视频监控系统互联互通的国际标准 它定义了视频监控系统中的设备间如何进行通信 交换数据和协调控制 以下是GB28181协议的一些主要内容 设备互联
  • GB28181-2022注册注销基本要求、注册重定向解读和技术实现

    规范解读 GB28181 2022注册 注销基本要求相对GB28181 2016版本 做了一定的调整 新调整的部分如下 更改了注册和注销基本要求 见 9 1 1 2016 年版的 9 1 1 1 增加对NAT模式网络传输要求 宜增加TCP传
  • Android平台如何高效率实现GB28181对接?

    技术背景 GB28181协议是一种用于设备状态信息报送的协议 可以在不同设备之间进行通信和数据传输 在安卓系统上实现GB T 28181非常必要 GB28181协议实现分两部分 一部分是信令 另外一部分就是媒体数据的编码 信令主要包括SIP
  • Android平台GB28181设备接入端如何实现本地录像?

    实现Android平台GB28181设备接入的时候 有个功能点不可避免 那就是本地录像 实际上 在实现GB28181设备接入模块之前 我们前些年做RTMP推送和轻量级RTSP服务的时候 早已经实现了本地录像功能 本地录像功能 我们实现的主要
  • Android平台GB28181设备接入模块分辨率发生变化怎么办?

    技术背景 我们在做Android平台gb28181设备接入模块的时候 遇到这样的情况 比如横竖屏分辨率不锁定 采集摄像头的时候 可以实现 横屏状态采集横屏 竖屏状态采集竖屏 简单来说 横屏状态比如采集的1280 720的 竖屏状态 采集的数
  • Android平台GB28181设备接入端如何实时更新经纬度实现国标平台侧电子地图位置标注

    技术背景 我们在做GB28181设备接入端的时候 其中有个功能 不难但非常重要 那就是GB28181实时位置的订阅 mobileposition subscribe 和上报 notify 特别是执法记录仪 智能安全帽 车载终端等场景下 现场
  • GB/T28181设备接入端如何应用到数字城管场景?

    什么是数字城管 数字城管 又称 数字化城市管理 或 智慧城管 是一种采用信息化手段和移动通信技术来处理 分析和管理整个城市的所有城管部件和城管事件信息 促进城市管理现代化的信息化措施 数字城管通过建立城市管理信息化平台 实现城市管理信息的采
  • GB28181媒体保活机制探究与实现

    规范解读 GB28181 2016和GB28181 2022关于媒体保活机制这块 并无调整 平台 设备媒体流保活机制规定如下 a 链路建立后 码流经过的各级平台应具备媒体流丢失监测能力 若监测到媒体流丢失 应释放该条媒体链路 并通过会话内B
  • GB28181平台如何接入无人机实现智能巡检?

    大家都知道 无人机巡检系统 有效解决了传统巡查工作空间和时间局限问题 降低人力工作成本 有效替代人工巡检工作模式 智能巡检系统通过人工智能技术和机械智能技术完美结合 在工业等场景下 应用非常广泛 本文旨在讲如何实现无人机 如大疆无人机 数据
  • Andorid平台GB28181设备接入端如何生成黑帧并推送至国标平台

    我们在做Android平台GB28181设备接入模块的时候 遇到这样的需求 做移动对讲的时候 是不需要视频数据的 但是国标平台侧 没有视频的话 大多平台又无法播纯音频打包的数据 网页端大多基于http flv或webrtc实现 基于此 我们
  • GB/T28181-2022针对H.265、AAC的说明和技术实现

    GB T28181 2022规范说明 GB T28181 2022相对来GB T28181 2016针对H 265 AAC的更新如下 更改了 联网系统通信协议结构图 媒体流通道增加了 H 265 G 722 1 AAC 见 4 3 1 20
  • GB/T28181-2022图像抓拍规范解读及技术实现

    规范解读 GB28181 2022相对2016 增加了设备软件升级 图像抓拍信令流程和协议接口 我们先回顾下规范说明 图像抓拍基本要求 源设备向目标设备发送图像抓拍配置命令 携带传输路径 会话ID等信息 目标设备完成图像传输后 发送图像抓拍
  • GB28181设备接入侧如何支持H.265?

    技术背景 一直以来 GB28181 2022之前的规范版本让人诟病的一点 没有明确针对H 265的说明 特别是监控摄像机 H 265已然成为标配 GB T28181 2022规范 终于针对H 265做了明确的说明 让我们来一起解读下规范 基
  • [技术分享]Android平台实时音视频录像模块设计之道

    实现背景 录像有什么难的 无非就是数据过来 编码保存mp4而已 这可能是好多开发者在做录像模块的时候的思考输出 是的 确实不难 但是做好 或者和其他模块有非常好的逻辑配合 确实不容易 好多开发者希望聊聊录像模块 实际上录像这块 需求层面的东
  • Android平台GB28181设备接入侧(编码前

    在之前 我有写过Android平台GB28181设备接入模块的好多blog 包括参数设置 功能支持与扩展等 以数据接入为例 支持的数据类型涉及编码前 编码后或直接流数据 RTSP或RTMP流 可用于如智能监控 智慧零售 智慧教育 远程办公
  • GB28181状态信息报送解读及Android端国标设备接入技术实现

    今天主要聊聊GB T28181状态信息报送这块 先回顾下协议规范相关细节 然后再针对代码实现 做个简单的说明 状态消息报送基本要求 当源设备 包括网关 SIP设备 SIP客户端或联网系统 发现工作异常时 应立即向本 SIP监控域 的SIP服

随机推荐

  • 直接修改html文本页面没变化,DOM问题:点击按钮的时候,修改input元素的value属性值,为什么在HTML结构上没有变化?...

    代码 无标题文档 span background lime window nl ad function 获取input span var oTxt document getElementsByTagName input 0 var oBtn
  • 什么是元宇宙:我们在哪里,我们要去哪里

    自Facebook于 2021 年 10 月 28 日更名为 Meta 以来 启发新名称的模糊概念一直是讨论的热门话题 虽然元宇宙似乎是 Meta 野心的产物 但事实并非如此 一些人会争辩说 马克扎克伯格在Connect 2021会议主题演
  • 基于 FFmpeg 的跨平台视频播放器简明教程(六):使用 SDL 播放音频和视频

    系列文章目录 基于 FFmpeg 的跨平台视频播放器简明教程 一 FFMPEG Conan 环境集成 基于 FFmpeg 的跨平台视频播放器简明教程 二 基础知识和解封装 demux 基于 FFmpeg 的跨平台视频播放器简明教程 三 视频
  • qt透明度设置

    QPaintEvent QPainter painter this painter setRenderHint QPainter Antialiasing painter setBrush m color painter setPen Qt
  • MySQL的优化

    目录 一 概念 二 查看SQL执行频率 三 定位低效率执行SQL 定位低效率执行SQL 慢查询日志 操作 定位低效率执行SQL show processlist 四 explain分析执行计划 字段说明 explain中的id explai
  • STM32+LittleVgl(LVGL)文件系统使用

    目录 一 硬件及软件准备 二 前言 三 显示效果 四 移植文件到工程目录下 五 将文件添加进工程中 六 使能文件 七 修改 lv port fs c 文件 八 修改main c 九 将图片资源拷贝到外部存储器中 一 硬件及软件准备 完整工程
  • 【迪文屏】踩坑指南——汉字显示乱码、背景图不显示问题的解决方法

    迪文屏支持的字库文件有HZK DZK Bin格式 迪文屏文字乱码请按下图中步骤一个个排查 迪文屏更改背景显示不出来可能是未生成icl文件或者icl文件位置未设置对 所以系统找不到 生成的icl图标库文件后 记得在CFG配置文件更改ILC位置
  • 数据库之DML的基本操作

    DML 数据操作语言 对表记录的操作 增 删 改 1 插入数据 insert into 表名 列名1 列名2 values 列值1 列值2 在表名后给出要插入的列名 其他没有指定的列插入NILL 在values后给出列值 值的顺序和个数必须
  • HTTPS工作原理原理及常见状态码

    HTTPS工作原理原理 简介 HTTPS是常用的web协议 用来交互网页数据 由于HTTP是不加密的 在公网上明文传输 缺少保密性 所以出现了安全加密的HTTP协议 HTTPS协议 HTTPS协议是在SSL协议基础上的HTTP协议 SSL协
  • JVM系列(八) JVM 垃圾收集算法

    前面我们了解了很多JVM配置垃圾回收的方式 但是具体垃圾是如何被回收的 或者说垃圾回收算法有哪些 今天我们文章主要讲解一下垃圾回收算法 1 分代收集理论 我们都知道 很早的JVM会把堆分为几个区域 新生代 老年代 永久代等区域 为什么要这么
  • JSP详细讲解

    JSP详细讲解 前言 一 JSP 介绍 二 JSP 运行原理 1 JSP 技术特点 2 JSP 与 Servlet 区别 三 JSP 的使用 1 JSP 的三种原始标签 2 JSP 原始标签的使用 3 JSP 的指令标签 4 JSP 指令标
  • 王爽汇编语言课程设计1

    一 实验要求 在屏幕输出实验七中的数据 二 设计思路 1 将实验七的程序编写成一个子过程finishing 在主程序中调用 可以获得实验七种指定格式的table段数据 设置es bx指向table段中第一行 2 创建一个数据缓存区buffe
  • 双电源切换电路的几种方案

    一 使用两个二极管 VBUS和VBAT单独供电的情况很好理解 由于二极管的单向性 不会发生电流的倒灌 当VBUS和VBAT都有电时 VBUS为5V VBAT为3 7V 此时D17处于反向截至状态 只有VBUS输出但VOUT 优点是方案简单
  • nuxt项目中引用less/scss全局变量

    nuxt项目中有些样式需要经常使用 并且未来有可能会改 比如主题色 theme color 所以希望在一个地方定义后 后面直接引用变量即可 但是正常使用时 less的变量是不能跨文件使用的 下面使用 nuxtjs style resourc
  • 国外IP地址汇总

    ip route 1 0 0 0 255 255 255 0 10 201 130 13 ip route 1 1 1 0 255 255 255 0 10 201 130 13 ip route 1 2 3 0 255 255 255 0
  • SylixOS下移植C++程序——命名粉碎

    1 概念 1 1 命名粉碎 命名粉碎 name mangling 又称命名修饰 name mangling是一种在编译器和链接器之间用于通信的符号协议 其目的在于按照程序中的语言规范 使符号具备足够的语义信息以保证链接过程准确无误的进行 编
  • props传递对象_解决vue组件props传值对象获取不到的问题

    先说问题 父组件利用props向子组件传值 浏览器 console 有这个值 但是获取不到内部的属性 困了我3个小时 真的 personal console 以下为原代码 1 home vue 父组件 personal是被传的参数 pers
  • 可视化卡片笔记写作?我试了最近才开放的 Heptabase

    2021 年 12 月末 我在微信里面读了 Alan 詹雨安 Heptabase 开发者 的文章 立即对更名不久的 Heptabase 来了兴趣 靠着海玮的邀请 我加入了 Heptabase 的 Discord 做了自我介绍 当然 也加入了
  • js常用hook

    一 Hook 技术原理 Hook是一种钩子技术 在系统没有调用函数之前 钩子程序就先得到控制权 这时候钩子函数既可以加工处理该函数的执行行为 也可以强制结束消息的传递 简单来说就是修改原有的js代码就是hook JS 是一种弱类型语言 同一
  • GB28181平台如何接入无人机实现智能巡检?

    大家都知道 无人机巡检系统 有效解决了传统巡查工作空间和时间局限问题 降低人力工作成本 有效替代人工巡检工作模式 智能巡检系统通过人工智能技术和机械智能技术完美结合 在工业等场景下 应用非常广泛 本文旨在讲如何实现无人机 如大疆无人机 数据