Android平台GB28181设备接入侧如何同时对外输出RTSP流?

简介: Android平台GB28181设备接入侧如何同时对外输出RTSP流?

 技术背景

GB28181的应用场景非常广泛,如公共安全、交通管理、企业安全、教育、医疗等众多领域,细分场景可用于如执法记录仪、智能安全帽、智能监控、智慧零售、智慧教育、远程办公、明厨亮灶、智慧交通、智慧工地、雪亮工程、平安乡村、生产运输、车载终端等:

    1. 公共安全:通过GB28181协议,用户可以实时监控特定区域的视频画面,从而提高公共安全水平。
    2. 交通管理:GB28181可用于交通监控系统,帮助交通部门实时监控道路交通情况,提高交通管理效率。
    3. 企业安全:GB28181可以用于构建企业视频监控系统,保护企业资产,提高安全工作效率。
    4. 教育:通过GB28181协议,用户可以进行远程视频会议和教学,为学生提供更为灵活的学习方式。
    5. 医疗:GB28181可以用于医疗领域的视频监控,提高医疗安全和管理效率。

    技术实现

    本文以Android平台GB28181设备接入模块为例,谈谈具体实现,还有如何对外输出RTSP流。

    Android终端除支持常规的音视频数据接入外,还可以支持移动设备位置(MobilePosition)订阅和通知、语音广播和语音对讲、云台控制回调和预置位查询,支持对接数据类型如下:

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

      技术设计架构图:

      视沃科技(大牛直播SDK)GB28181设备接入SDK.png

      功能设计:

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

        Android平台GB28181设备接入模块,除了上述的功能点外,我们遇到的诉求有,如何同时对外输出RTSP,供如内网平台预览播放?

        这里就提到了轻量级RTSP服务,音视频数据源过来后,编码分别注入GB28181模块和轻量级RTSP服务模块,如果需要做到对外输出RTSP流,只需要启动RTSP服务,然后发布RTSP流即可,具体的操作如下:

        image.gif编辑

        启动、停止RTSP服务:

        //启动/停止RTSP服务classButtonRtspServiceListenerimplementsView.OnClickListener {
        publicvoidonClick(Viewv) {
        if (isRTSPServiceRunning) {
        stopRtspService();
        btnRtspService.setText("启动RTSP服务");
        btnRtspPublisher.setEnabled(false);
        isRTSPServiceRunning=false;
        return;
            }
        Log.i(TAG, "onClick start rtsp service..");
        rtsp_handle_=libPublisher.OpenRtspServer(0);
        if (rtsp_handle_==0) {
        Log.e(TAG, "创建rtsp server实例失败! 请联系 https://daniusdk.com 检查SDK有效性");
            } else {
        intport=8554;
        if (libPublisher.SetRtspServerPort(rtsp_handle_, port) !=0) {
        libPublisher.CloseRtspServer(rtsp_handle_);
        rtsp_handle_=0;
        Log.e(TAG, "创建rtsp server端口失败! 请检查端口是否重复或者端口不在范围内!");
              }
        if (libPublisher.StartRtspServer(rtsp_handle_, 0) ==0) {
        Log.i(TAG, "启动rtsp server 成功!");
              } else {
        libPublisher.CloseRtspServer(rtsp_handle_);
        rtsp_handle_=0;
        Log.e(TAG, "启动rtsp server失败! 请检查设置的端口是否被占用!");
              }
        btnRtspService.setText("停止RTSP服务");
        btnRtspPublisher.setEnabled(true);
        isRTSPServiceRunning=true;
            }
          }
        }

        image.gif

        发布、停止RTSP流:

        //发布/停止RTSP流classButtonRtspPublisherListenerimplementsView.OnClickListener {
        publicvoidonClick(Viewv) {
        if (isRTSPPublisherRunning) {
        stopRtspPublisher();
        btnRtspPublisher.setText("发布RTSP流");
        btnGetRtspSessionNumbers.setEnabled(false);
        btnRtspService.setEnabled(true);
        return;
            }
        Log.i(TAG, "onClick start rtsp publisher..");
        if (!isPushingRtmp&&!isGB28181StreamRunning&&!isRecording) {
        InitAndSetConfig();
            }
        if (publisherHandle==0) {
        Log.e(TAG, "Start rtsp publisher, publisherHandle is null..");
        return;
            }
        Stringrtsp_stream_name="stream1";
        libPublisher.SetRtspStreamName(publisherHandle, rtsp_stream_name);
        libPublisher.ClearRtspStreamServer(publisherHandle);
        libPublisher.AddRtspStreamServer(publisherHandle, rtsp_handle_, 0);
        if (libPublisher.StartRtspStream(publisherHandle, 0) !=0) {
        Log.e(TAG, "调用发布rtsp流接口失败!");
        return;
            }
        if (!isPushingRtmp&&!isGB28181StreamRunning&&!isRecording) {
        CheckInitAudioRecorder();    //enable pure video publisher..    }
        startLayerPostThread();
        btnRtspPublisher.setText("停止RTSP流");
        btnGetRtspSessionNumbers.setEnabled(true);
        btnRtspService.setEnabled(false);
        isRTSPPublisherRunning=true;
          }
        }

        image.gif

        获取RTSP链接数:

        //获取RTSP会话数classButtonGetRtspSessionNumbersListenerimplementsView.OnClickListener {
        publicvoidonClick(Viewv) {
        if (libPublisher!=null&&rtsp_handle_!=0) {
        intsession_numbers=libPublisher.GetRtspServerClientSessionNumbers(rtsp_handle_);
        Log.i(TAG, "GetRtspSessionNumbers: "+session_numbers);
        PopRtspSessionNumberDialog(session_numbers);
            }
          }
        }

        image.gif

        获取回调上来的RTSP URL,对应的事件ID为EVENT_DANIULIVE_ERC_PUBLISHER_RTSP_URL

        privatestaticclassEventHandlerPublisherV2implementsNTSmartEventCallbackV2 {
        @OverridepublicvoidonNTSmartEventCallbackV2(longhandle, intid, longparam1, longparam2, Stringparam3, Stringparam4, Objectparam5) {
        Log.i(TAG, "EventHandeV2: handle="+handle+" id:"+id);
        Stringpublisher_event="";
        switch (id) {
             .....
        caseNTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_RECORDER_START_NEW_FILE:
        publisher_event="开始一个新的录像文件 : "+param3;
        break;
        caseNTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_ONE_RECORDER_FILE_FINISHED:
        if (recorder_io_executor_!=null) {
        ExecutorServiceexecutor=recorder_io_executor_.get();
        if (executor!=null)
        executor.execute(newRecordFileFinishedHandler().set(handle, param3, param1));
                }
        publisher_event="已生成一个录像文件 : "+param3;
        break;
        caseNTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_SEND_DELAY:
        publisher_event="发送时延: "+param1+" 帧数:"+param2;
        break;
        caseNTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_CAPTURE_IMAGE:
        publisher_event="快照: "+param1+" 路径:"+param3;
        if (param1==0) {
        publisher_event=publisher_event+"截取快照成功..";
                } else {
        publisher_event=publisher_event+"截取快照失败..";
                }
        break;
        caseNTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_RTSP_URL:
        publisher_event="RTSP服务URL: "+param3;
        break;
            }
        Stringstr="当前回调状态:"+publisher_event;
        Log.i(TAG, str);
        if (handler_!=null) {
        android.os.Handlerhandler=handler_.get();
        if (handler!=null) {
        Messagemessage=newMessage();
        message.what=PUBLISHER_EVENT_MSG;
        message.obj=publisher_event;
        handler.sendMessage(message);
              }
            }
          }
        publicNTSmartEventCallbackV2set(android.os.Handlerhandler, ExecutorServicerecorder_io_executor) {
        this.handler_=newWeakReference<>(handler);
        this.recorder_io_executor_=newWeakReference<>(recorder_io_executor);
        returnthis;
          }
        privateWeakReference<android.os.Handler>handler_;
        privateWeakReference<ExecutorService>recorder_io_executor_;
        }

        image.gif

        总结

        GB28181设备接入模块同时输出RTSP流的话,需要注意的是,在一个实例里面完成,确保只编码一路音视频数据,然后分别打包注入两个模块,尽可能的降低设备性能消耗。

        相关文章
        |
        10月前
        |
        存储 Android开发
        如何查看Flutter应用在Android设备上已被撤销的权限?
        如何查看Flutter应用在Android设备上已被撤销的权限?
        469 64
        |
        10月前
        |
        存储 Android开发 数据安全/隐私保护
        如何在Android设备上撤销Flutter应用程序的所有权限?
        如何在Android设备上撤销Flutter应用程序的所有权限?
        629 64
        |
        10月前
        |
        缓存 Android开发 开发者
        Flutter环境配置完成后,如何在Android设备上运行Flutter应用程序?
        Flutter环境配置完成后,如何在Android设备上运行Flutter应用程序?
        1887 62
        |
        10月前
        |
        开发工具 Android开发 开发者
        在Android设备上运行Flutter应用程序时,如果遇到设备未授权的问题该如何解决?
        在Android设备上运行Flutter应用程序时,如果遇到设备未授权的问题该如何解决?
        685 61
        |
        7月前
        |
        监控 Android开发 数据安全/隐私保护
        批量发送短信的平台,安卓群发短信工具插件脚本,批量群发短信软件【autojs版】
        这个Auto.js脚本实现了完整的批量短信发送功能,包含联系人管理、短信内容编辑、发送状态监控等功能
        |
        11月前
        |
        监控 Shell Linux
        Android调试终极指南:ADB安装+多设备连接+ANR日志抓取全流程解析,覆盖环境变量配置/多设备调试/ANR日志分析全流程,附Win/Mac/Linux三平台解决方案
        ADB(Android Debug Bridge)是安卓开发中的重要工具,用于连接电脑与安卓设备,实现文件传输、应用管理、日志抓取等功能。本文介绍了 ADB 的基本概念、安装配置及常用命令。包括:1) 基本命令如 `adb version` 和 `adb devices`;2) 权限操作如 `adb root` 和 `adb shell`;3) APK 操作如安装、卸载应用;4) 文件传输如 `adb push` 和 `adb pull`;5) 日志记录如 `adb logcat`;6) 系统信息获取如屏幕截图和录屏。通过这些功能,用户可高效调试和管理安卓设备。
        |
        4月前
        |
        移动开发 前端开发 Android开发
        【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
        【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
        529 12
        【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
        |
        4月前
        |
        移动开发 JavaScript 应用服务中间件
        【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
        【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
        473 5
        【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
        |
        4月前
        |
        移动开发 Rust JavaScript
        【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
        【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
        894 4
        【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
        |
        5月前
        |
        开发工具 Android开发
        X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡
        X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡
        673 11
        X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡

        热门文章

        最新文章