IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 如何在Android端实现轻量级RTSP服务(类似于IPC) -> 正文阅读

[移动开发]如何在Android端实现轻量级RTSP服务(类似于IPC)

为什么要设计轻量级RTSP服务

首先声明一点,本blog提到的轻量级RTSP服务,类似于网络摄像头(IPC),而非传统意义的接受外部推流的RTSP服务器。

轻量级RTSP服务解决的核心痛点:避免用户单独部署RTSP或者RTMP服务,实现本地的音视频数据(如摄像头|屏幕、麦克风),编码后,汇聚到内置RTSP服务,对外提供可供拉流的RTSP URL,轻量级RTSP服务,适用于内网环境下,对并发要求不高的场景,视频编码支持H.264/H.265,音频对外输出AAC,支持RTSP鉴权、单播、组播模式,考虑到单个服务承载能力,支持同时创建多个RTSP服务,并支持获取当前RTSP服务会话连接数。

如何设计轻量级RTSP服务接口

轻量级RTSP服务接口,通过服务和发布RTSP结合的方式,可在Android端快速实现类似于IPC功能,详细接口也可参看大牛直播SDK提供的官方DEMO模块(地址)。

1.?InitRtspServer()

顾名思义,初始化RTSP服务,和UnInitRTSPServer()接口配套使用,不管启动几个RTSP服务,Init和UnInit接口仅需调一次即可。

	/*
	 * Init rtsp server(和UnInitRtspServer配对使用,即便是启动多个RTSP服务,也只需调用一次InitRtspServer,请确保在OpenRtspServer之前调用)
	 *
	 * @param ctx: get by this.getApplicationContext()
	 *
	 * @return {0} if successful
	 */
	public native int InitRtspServer(Object ctx);

2.UnInitRtspServer()

如InitRtspServer()所述,不再赘述,接口设计如下:

	/*
	 * UnInit rtsp server(和InitRtspServer配对使用,即便是启动多个RTSP服务,也只需调用一次UnInitRtspServer)
	 *
	 * @return {0} if successful
	 */
	public native int UnInitRtspServer();

3. OpenRtspServer()

创建个RTSP Server实例,返回实例句柄。

	/*
	 * 创建一个rtsp server
	 *
   	 * @param reserve:保留参数传0
	 *
	 * @return rtsp server 句柄
	 */
	public native long OpenRtspServer(int reserve);

4. SetRtspServerPort()

设置RTSP服务的监听端口,一般来说,可以设置如554、1554等。

	/*
	 * 设置rtsp server 监听端口, 在StartRtspServer之前必须要设置端口
	 *
   	 * @param rtsp_server_handle: rtsp server 句柄
	 *
   	 * @param port: 端口号,可以设置为554,或者是1024到65535之间,其他值返回失败
	 *
	 * @return {0} if successful
	 */
	public native int SetRtspServerPort(long rtsp_server_handle, int port);

5.?SetRtspServerUserNamePassword()

接口目的是为了设置rtsp server 鉴权用户名和密码, 这个可以不设置,只有需要鉴权的再设置。

	/*
	 * 设置rtsp server 鉴权用户名和密码, 这个可以不设置,只有需要鉴权的再设置
	 *
   	 * @param rtsp_server_handle: rtsp server 句柄
	 *
   	 * @param user_name: 用户名(必须是英文)
	 * 
   	 * @param password:密码(必须是英文)
	 *
	 * @return {0} if successful
	 */
	public native int SetRtspServerUserNamePassword(long rtsp_server_handle, String user_name, String password);

6.?SetRtspServerMulticast()

设置rtsp server 组播, 如果server设置成组播就不能单播,组播和单播只能选一个, 一般来说单播网络设备支持的好,wifi组播很多路由器不支持。一般不建议设置组播。

	/*
	 * 设置rtsp server 组播, 如果server设置成组播就不能单播,组播和单播只能选一个, 一般来说单播网络设备支持的好,wifi组播很多路由器不支持
	 *
	 * @param rtsp_server_handle: rtsp server 句柄
	 *
	 * @param is_multicast: 是否组播, 1为组播, 0为单播, 其他值接口返回错误, 默认是单播
	 *
	 * @return {0} if successful
	 */
	public native int SetRtspServerMulticast(long rtsp_server_handle, int is_multicast);

7.?SetRtspServerMulticastAddress()

设置rtsp server 组播组播地址。

	/*
	 * 设置rtsp server 组播组播地址
	 *
	 * @param rtsp_server_handle: rtsp server 句柄
	 *
	 * @param multicast_address: 组播地址
	 *
	 * 如果设置的不是组播地址, 将返回错误
	 * 组播地址范围说明: [224.0.0.0, 224.0.0.255] 为组播预留地址, 不能设置. 可设置范围为[224.0.1.0, 239.255.255.255], 其中SSM地址范围为[232.0.0.0, 232.255.255.255]
	 *
	 *  @return {0} if successful
	 */
	public native int SetRtspServerMulticastAddress(long rtsp_server_handle, String multicast_address);

8.?GetRtspServerClientSessionNumbers()

获取rtsp server当前的客户会话数, 这个接口必须在StartRtspServer之后再调用。

	/*
	 * 获取rtsp server当前的客户会话数, 这个接口必须在StartRtspServer之后再调用
	 *
   	 * @param rtsp_server_handle: rtsp server 句柄
	 *
	 * @return {当前rtsp server会话数}
	 */
	public native int GetRtspServerClientSessionNumbers(long rtsp_server_handle);

9.?StartRtspServer()

启动RTSP服务。

	/*
	 * 启动rtsp server
	 *
   	 * @param rtsp_server_handle: rtsp server 句柄
	 *
   	 * @param reserve: 保留参数传0
	 *
	 * @return {0} if successful
	 */
	public native int StartRtspServer(long rtsp_server_handle, int reserve);

10. StopRtspServer()

停止RTSP服务。

	/*
	 * 停止rtsp server
	 *
   	 * @param rtsp_server_handle: rtsp server 句柄
	 *
	 * @return {0} if successful
	 */
	public native int StopRtspServer(long rtsp_server_handle);

如何调用接口

1. 先调InitRtspServer()接口

       libPublisher = new SmartPublisherJniV2();

        libPublisher.InitRtspServer(myContext);      //和UnInitRtspServer配对使用,即便是启动多个RTSP服务,也只需调用一次InitRtspServer,请确保在OpenRtspServer之前调用

2. 启动、停止RTSP服务

    //启动/停止RTSP服务
    class ButtonRtspServiceListener implements OnClickListener {
        public void onClick(View v) {
            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实例失败! 请检查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);

                //一般来说单播网络设备支持的好,wifi组播很多路由器不支持,默认单播模式;如需使用组播模式,确保设备支持后,打开注释代码测试即可
                /*
                boolean is_enable_multicast = true;

                if(is_enable_multicast)
                {
                    int is_multicast = 1;

                    libPublisher.SetRtspServerMulticast(rtsp_handle_, is_multicast);

                    boolean is_enable_ssm_multicast = true;

                    String multicast_address = "";

                    if(is_enable_ssm_multicast)
                    {
                        multicast_address = MakeSSMMulticastAddress();
                    }
                    else
                    {
                        multicast_address = MakeMulticastAddress();
                    }

                    Log.i(TAG, "is_enable_ssm_multicast:" + is_enable_ssm_multicast + " multiAddr: " + multicast_address);

                    libPublisher.SetRtspServerMulticastAddress(rtsp_handle_, multicast_address);
                }
                */

                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;
            }
        }
    }

3. 发布、停止RTSP流

    //发布/停止RTSP流
    class ButtonRtspPublisherListener implements OnClickListener {
        public void onClick(View v) {
            if (isRTSPPublisherRunning) {
                stopRtspPublisher();

                if (!isPushingRtmp && !isRecording && !isPushingRtsp) {
                    ConfigControlEnable(true);
                }

                btnRtspPublisher.setText("发布RTSP流");
                btnGetRtspSessionNumbers.setEnabled(false);
                btnRtspService.setEnabled(true);
                isRTSPPublisherRunning = false;

                return;
            }

            Log.i(TAG, "onClick start rtsp publisher..");

            if (!isPushingRtmp && !isRecording && !isPushingRtsp) {
                InitAndSetConfig();
            }

            if (publisherHandle == 0) {
                Log.e(TAG, "Start rtsp publisher, publisherHandle is null..");
                return;
            }

            String rtsp_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 && !isRecording && !isPushingRtsp) {
                if (pushType == 0 || pushType == 1) {
                    CheckInitAudioRecorder();    //enable pure video publisher..
                }

                ConfigControlEnable(false);
            }

            btnRtspPublisher.setText("停止RTSP流");
            btnGetRtspSessionNumbers.setEnabled(true);
            btnRtspService.setEnabled(false);
            isRTSPPublisherRunning = true;
        }
    }

    ;

4. 获取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();
    }

    //获取RTSP会话数
    class ButtonGetRtspSessionNumbersListener implements OnClickListener {
        public void onClick(View v) {
            if (libPublisher != null && rtsp_handle_ != 0) {
                int session_numbers = libPublisher.GetRtspServerClientSessionNumbers(rtsp_handle_);

                Log.i(TAG, "GetRtspSessionNumbers: " + session_numbers);

                PopRtspSessionNumberDialog(session_numbers);
            }
        }
    };

5. UnInitRtspServer()

			
			libPublisher.UnInitRtspServer();      //如已启用内置服务功能(InitRtspServer),调用UnInitRtspServer, 注意,即便是启动多个RTSP服务,也只需调用UnInitRtspServer一次
 

6. 生成组播地址

    private String MakeMulticastAddress()
    {
        // 239.0.1.0 ~ 239.255.255.255
        long begin = 0xEF000100;
        long end = 0xEFFFFFFF;

        long count = end - begin;

        Random random = new Random();
        long addr_host = begin + (random.nextInt((int)count));

        return DigitToIpAddr(addr_host);
    }

    private String MakeSSMMulticastAddress()
    {
        // 232.0.1.0 ~ 232.255.255.255

        long begin = 0xE8000100;
        long end = 0xE8FFFFFF;

        long count = end - begin;

        Random random = new Random();
        long addr_host = begin + (random.nextInt((int)count));

        return DigitToIpAddr(addr_host);
    }

    private String DigitToIpAddr(long ip) {
        return ((ip >> 24) & 0xFF) + "."
                + ((ip >> 16) & 0xFF) + "."
                + ((ip >> 8) & 0xFF) + "."
                + (ip & 0xFF);
    }

总结

为满足内网无纸化/电子教室等内网超低延迟需求,避免让用户配置单独的服务器,我们在推送端发布了轻量级RTSP服务SDK,简单来说,之前推送端SDK支持的功能,内置轻量级RTSP服务SDK后,功能继续支持。

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

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-11-19 17:44:27  更:2021-11-19 17:44:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:31:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码