Android平台如何实现外部RTSP|RTMP流注入轻量级RTSP服务模块(内网RTSP网关)

简介: 今天分享的是外部RTSP或RTMP流,拉取后注入到本地轻量级RTSP服务模块,供内网小并发场景下使用,这里我们叫做内网RTSP网关模块。

技术背景

今天分享的是外部RTSP或RTMP流,拉取后注入到本地轻量级RTSP服务模块,供内网小并发场景下使用,这里我们叫做内网RTSP网关模块。


内网RTSP网关模块,系内置轻量级RTSP服务模块扩展,完成外部RTSP/RTMP数据拉取并注入到轻量级RTSP服务模块工作,多个内网客户端直接访问内网轻量级RTSP服务获取公网数据,无需部署单独的服务器,支持RTSP/RTMP H.265数据接入。


内置轻量级RTSP服务模块和内置RTSP网关模块共同点:


内置轻量级RTSP服务模块和内置RTSP网关模块,核心痛点是避免用户或者开发者单独部署RTSP或者RTMP服务,数据汇聚到内置RTSP服务,对外提供可供拉流的RTSP URL,适用于内网环境下,对并发要求不高的场景,支持H.264/H.265,支持RTSP鉴权、单播、组播模式,考虑到单个服务承载能力,我们支持同时创建多个RTSP服务,并支持获取当前RTSP服务会话连接数。


内置轻量级RTSP服务模块和内置RTSP网关模块不同点:数据来源不同


1. 内置轻量级RTSP服务模块,数据源来自摄像头、屏幕、麦克风等编码前数据,或者本地编码后的对接数据;


2. 内置RTSP网关模块,实际上是RTSP/RTMP拉流模块+内置轻量级RTSP服务模块组合出来的。数据源来自RTSP或RTMP网络流,拉流模块完成编码后的音视频数据回调,然后,汇聚到内置轻量级RTSP服务模块。

技术设计

本文以大牛直播SDK的转发demo基础设计为例,增加了内网RTSP网关模块,由于我们有非常稳定完善的RTSP、RTMP直播播放模块,内网RTSP网关模块,无非就是拉取到RTSP或RTMP流,把编码后的H.264/H.265数据回调上来,然后注入到轻量级RTSP服务模块即可,如下图所示:

d177424975d742b9abeef822dac0deb4.jpg

先开始拉流,获取到拉流的RTSP或RTMP数据,实现如下:

        //Author: daniusdk.com
            btnPullStream.setOnClickListener(new Button.OnClickListener() {
      // @Override
      public void onClick(View v) {
        if (isPulling)
        {
          if(isPushing || isRecording || isRTSPPublisherRunning)
          {
            Log.e(TAG, "please make sure pusher/recorder/rtsp server stopped first..");
            return;
          }
          StopPull();
          btnPullStream.setText("开始拉流");
          btnPushStream.setEnabled(false);
        }
        else {
          Log.i(TAG, "onClick StartPull Stream..");
          boolean is_pull_suc = StartPull();
          if(!is_pull_suc)
          {
            Log.e(TAG, "call StartPull() failed!");
            return;
          }
          btnPullStream.setText("停止拉流");
          btnPushStream.setEnabled(true);
        }
      }
    });


启动RTSP服务:

  //启动/停止RTSP服务
  class ButtonRtspServiceListener implements OnClickListener {
    public void onClick(View v) {
      if (isRTSPServiceRunning) {
        stopRtspService();
        btnRtspService.setText("启动RTSP服务");
        btnRtspPublisher.setEnabled(false);
        isRTSPServiceRunning = false;
        return;
      }
      if(!OpenPushHandle())
      {
        return;
      }
      Log.i(TAG, "onClick start rtsp service..");
      rtsp_handle_ = libPublisher.OpenRtspServer(0);
      if (rtsp_handle_ == 0) {
        Log.e(TAG, "创建rtsp server实例失败! 请检查SDK有效性");
      } else {
        int port = 8554;
        if (libPublisher.SetRtspServerPort(rtsp_handle_, port) != 0) {
          libPublisher.CloseRtspServer(rtsp_handle_);
          rtsp_handle_ = 0;
          Log.e(TAG, "创建rtsp server端口失败! 请检查端口是否重复或者端口不在范围内!");
        }
        //String user_name = "admin";
        //String password = "12345";
        //libPublisher.SetRtspServerUserNamePassword(rtsp_handle_, user_name, password);
        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;
      }
    }
  }


发布RTSP流:

  //发布/停止RTSP流
  class ButtonRtspPublisherListener implements OnClickListener {
    public void onClick(View v) {
      if (isRTSPPublisherRunning) {
        stopRtspPublisher();
        btnRtspPublisher.setText("发布RTSP流");
        btnGetRtspSessionNumbers.setEnabled(false);
        btnRtspService.setEnabled(true);
      }
      else
      {
        Log.i(TAG, "onClick start rtsp publisher..");
        boolean startRet = StartRtspStream();
        if (!startRet) {
          Log.e(TAG, "Failed to call StartRtspStream().");
          return;
        }
        btnRtspPublisher.setText("停止RTSP流");
        btnGetRtspSessionNumbers.setEnabled(true);
        btnRtspService.setEnabled(false);
      }
    }
  };


如果需要获取到RTSP会话链接数:

  //当前RTSP会话数弹出框
  private void PopRtspSessionNumberDialog(int session_numbers) {
    final EditText inputUrlTxt = new EditText(this);
    inputUrlTxt.setFocusable(true);
    inputUrlTxt.setEnabled(false);
    String session_numbers_tag = "RTSP服务当前客户会话数: " + session_numbers;
    inputUrlTxt.setText(session_numbers_tag);
    AlertDialog.Builder builderUrl = new AlertDialog.Builder(this);
    builderUrl
        .setTitle("内置RTSP服务")
        .setView(inputUrlTxt).setNegativeButton("确定", null);
    builderUrl.show();
  }


如果需要预览:

    btnStartStopPlayback.setOnClickListener(new Button.OnClickListener() {
      // @Override
      public void onClick(View v) {
        if (isPlaying) {
          Log.i(TAG, "Stop playback stream++");
          StopPlay();
          btnStartStopPlayback.setText("开始播放 ");
          Log.i(TAG, "Stop playback stream--");
        } else {
          Log.i(TAG, "Start playback stream++");
          boolean startRet = StartPlay();
          if (!startRet) {
            Log.e(TAG, "Failed to call StartPlay().");
            return;
          }
          btnStartStopPlayback.setText("停止播放 ");
          Log.i(TAG, "Start playback stream--");
        }
      }
    });
  }


技术总结

内网RTSP网关,在小并发的环境下,不需要单独部署RTSP或RTMP服务,配合我们RTSP播放器,延迟毫秒级,优势非常明显,感兴趣的开发者可参考,如果需要测试,可测试看看,不止Android平台,Windows也有类似的实现。

相关文章
|
6天前
|
Android开发
Android 11 添加Service服务SELinux问题
Android 11 添加Service服务SELinux问题
16 1
|
1月前
|
运维 网络协议 安全
长连接网关技术专题(十):百度基于Go的千万级统一长连接服务架构实践
本文将介绍百度基于golang实现的统一长连接服务,从统一长连接功能实现和性能优化等角度,描述了其在设计、开发和维护过程中面临的问题和挑战,并重点介绍了解决相关问题和挑战的方案和实践经验。
84 1
|
2月前
|
Android开发
安卓SO层开发 -- 编译指定平台的SO文件
安卓SO层开发 -- 编译指定平台的SO文件
33 0
|
2月前
|
缓存 安全 API
【亿级数据专题】「高并发架构」盘点本年度探索对外服务的百万请求量的API网关设计实现
公司对外开放的OpenAPI-Server服务,作为核心内部系统与外部系统之间的重要通讯枢纽,每天处理数百万次的API调用、亿级别的消息推送以及TB/PB级别的数据同步。经过多年流量的持续增长,该服务体系依然稳固可靠,展现出强大的负载能力。
57 9
【亿级数据专题】「高并发架构」盘点本年度探索对外服务的百万请求量的API网关设计实现
|
1月前
|
SpringCloudAlibaba Java 网络架构
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(七)Spring Cloud Gateway服务网关
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(七)Spring Cloud Gateway服务网关
105 0
|
1月前
|
运维 监控 Java
应用研发平台EMAS产品常见问题之安卓构建版本失败如何解决
应用研发平台EMAS(Enterprise Mobile Application Service)是阿里云提供的一个全栈移动应用开发平台,集成了应用开发、测试、部署、监控和运营服务;本合集旨在总结EMAS产品在应用开发和运维过程中的常见问题及解决方案,助力开发者和企业高效解决技术难题,加速移动应用的上线和稳定运行。
|
1月前
|
运维 监控 Android开发
应用研发平台EMAS常见问题之安卓push的离线转通知目前无法收到如何解决
应用研发平台EMAS(Enterprise Mobile Application Service)是阿里云提供的一个全栈移动应用开发平台,集成了应用开发、测试、部署、监控和运营服务;本合集旨在总结EMAS产品在应用开发和运维过程中的常见问题及解决方案,助力开发者和企业高效解决技术难题,加速移动应用的上线和稳定运行。
25 1
|
3月前
|
监控 Java API
springcloud5-服务网关zuul及gateway
springcloud5-服务网关zuul及gateway
119 1
springcloud5-服务网关zuul及gateway
|
3月前
|
编解码 测试技术 开发工具
如何实现Android视音频数据对接到GB28181平台(SmartGBD)
如何实现Android视音频数据对接到GB28181平台(SmartGBD)
|
3月前
|
开发工具 Android开发
Android平台RTMP推送|轻量级RTSP服务|GB28181设备接入模块之实时快照保存JPG还是PNG?
Android平台RTMP推送|轻量级RTSP服务|GB28181设备接入模块之实时快照保存JPG还是PNG?