Android平台Unity3D下如何同时播放多路RTMP|RTSP流?

技术背景

好多开发者,提到希望在Unity的Android头显终端,播放2路以上RTMP或RTSP流,在设备性能一般的情况下,对Unity下的RTMP|RTSP播放器提出了更高的要求。实际上,我们在前几年发布Unity下直播播放模块的时候,就已经支持了Android多实例播放RTMP|RTSP,随着大家对这块的技术诉求和性能要求越来越高,我们需要持续考虑如何低资源占用的播放多实例流。

实现思路

目前,我们是通过大牛直播SDK原生的RTMP|RTSP播放器,设置回调解码后的YUV或RGB数据,然后投递到Unity层,在Unity层做渲染。

对于每一路RTMP或RTSP流,可以分别创建个播放实例,并启动播放。可以创建一个管理类,用于统一管理多个播放器实例,方便对多路流的播放状态进行监控和控制。

当从原生播放器中获取到视频流的数据后,需要将数据回调到 Unity 中进行渲染。可以使用 Unity 的纹理(Texture)来存储视频帧数据,并将其应用到相应的材质(Material)上,然后将材质应用到 3D 模型或UI元素上,以实现视频的播放显示。对于多路视频流,需要为每一路视频流创建独立的纹理和材质,并分别进行渲染。

具体实现如下:

开始播放:

/** SmartPlayerAndroidMono.cs* Author: daniusdk.com* WeChat: xinsheng120*/public void Play(int sel)
{if (videoctrl[sel].is_running){Debug.Log("已经在播放.. sel: " + sel);   return;}videoctrl[sel].player_handle_ = OpenPlayer();if (videoctrl[sel].player_handle_ == 0){Debug.LogError("open fail sel: " + sel);return;}NT_U3D_Set_Game_Object(videoctrl[sel].player_handle_, game_object_);/* ++ 播放前参数配置可加在此处 ++ */int is_using_tcp = 0;        //TCP/UDP模式设置NT_U3D_SetRTSPTcpMode(videoctrl[sel].player_handle_, is_using_tcp);int is_report = 0;int report_interval = 1;NT_U3D_SetReportDownloadSpeed(videoctrl[sel].player_handle_, is_report, report_interval);  //下载速度回调int buffer_time = 0;NT_U3D_SetBuffer(videoctrl[sel].player_handle_, buffer_time);//设置buffer timeNT_U3D_SetPlayerLowLatencyMode(videoctrl[sel].player_handle_, 0);//设置是否启用低延迟模式NT_U3D_SetMute(videoctrl[sel].player_handle_, 0);//是否启动播放的时候静音int cur_audio_volume = 100;         //默认播放音量NT_U3D_SetAudioVolume(videoctrl[sel].player_handle_, cur_audio_volume);             //设置播放音量Boolean is_hw_decode = true;NT_U3D_SetVideoDecoderMode(videoctrl[sel].player_handle_, is_hw_decode ? 1 : 0);          //设置H.264软硬解模式NT_U3D_SetVideoHevcDecoderMode(videoctrl[sel].player_handle_, is_hw_decode ? 1 : 0);          //设置H.265软硬解模式NT_U3D_SetImageReaderOutput(videoctrl[sel].player_handle_, is_output, disable_use_image_planes, is_supported_multiple_format, max_images, buffer_pool_max_size);int is_fast_startup = 1;NT_U3D_SetFastStartup(videoctrl[sel].player_handle_, is_fast_startup);                     //设置快速启动模式int rtsp_timeout = 10;NT_U3D_SetRTSPTimeout(videoctrl[sel].player_handle_, rtsp_timeout);                        //设置RTSP超时时间int is_auto_switch_tcp_udp = 1;NT_U3D_SetRTSPAutoSwitchTcpUdp(videoctrl[sel].player_handle_, is_auto_switch_tcp_udp);    //设置TCP/UDP模式自动切换int is_audiotrack = 1;NT_U3D_SetAudioOutputType(videoctrl[sel].player_handle_, is_audiotrack);                   //设置音频输出模式: if 0: 自动选择; if with 1: audiotrack模式NT_U3D_SetUrl(videoctrl[sel].player_handle_, videoctrl[sel].videoUrl);/* -- 播放前参数配置可加在此处 -- */int flag = NT_U3D_StartPlay(videoctrl[sel].player_handle_);if (flag  == DANIULIVE_RETURN_OK){videoctrl[sel].is_need_get_frame_ = true;Debug.Log("播放成功 sel: " + sel);}else{videoctrl[sel].is_need_get_frame_ = false;Debug.LogError("播放失败 sel: " + sel);}videoctrl[sel].is_running = true;  
}

对应的OpenPlayer()实现如下:

private long OpenPlayer()
{if ( java_obj_cur_activity_ == null ){Debug.LogError("getApplicationContext is null");return 0;}long player_handle = 0;player_handle = NT_U3D_Open();if (player_handle != 0)Debug.Log("open success");elseDebug.LogError("open fail");return player_handle;
}

停止播放:

private void ClosePlayer(int sel)
{videoctrl[sel].is_need_get_frame_ = false;videoctrl[sel].is_need_init_texture_ = false;int flag = NT_U3D_StopPlay(videoctrl[sel].player_handle_);if (flag == DANIULIVE_RETURN_OK){Debug.Log("停止成功");}else{Debug.LogError("停止失败");}flag = NT_U3D_Close(videoctrl[sel].player_handle_);if (flag == DANIULIVE_RETURN_OK){Debug.Log("关闭成功");}else{Debug.LogError("关闭失败");}videoctrl[sel].player_handle_ = 0;videoctrl[sel].video_format_ = VideoFrame.FORMAT_UNKNOWN;videoctrl[sel].video_width_ = 0;videoctrl[sel].video_height_ = 0;videoctrl[sel].is_running = false;
}

UpdateYUVTexture()实现如下:

private void UpdateYUVTexture(VideoFrame video_frame,int sel)
{if (video_frame == null)return;if (video_frame.java_frame_obj_ == null)return;if (video_frame.plane0_ == IntPtr.Zero || video_frame.plane1_ == IntPtr.Zero)return;if (video_frame.format_ == VideoFrame.FORMAT_I420) {if (video_frame.plane2_ptr_ == IntPtr.Zero)return;}if (videoctrl[sel].yTexture_ != null){videoctrl[sel].yTexture_.LoadRawTextureData(video_frame.plane0_, video_frame.plane0_size_);videoctrl[sel].yTexture_.Apply();}if (videoctrl[sel].uTexture_ != null){videoctrl[sel].uTexture_.LoadRawTextureData(video_frame.plane1_, video_frame.plane1_size_);videoctrl[sel].uTexture_.Apply();}if (video_frame.format_ == VideoFrame.FORMAT_I420){if (videoctrl[sel].vTexture_ != null){videoctrl[sel].vTexture_.LoadRawTextureData(video_frame.plane2_, video_frame.plane2_size_);videoctrl[sel].vTexture_.Apply();}}
}

总结

直接在Unity中播放RTMP|RTSP流可能并不简单,因为Unity没有内置对RTMP|RTSP的直接支持。你需要根据你的具体需求(如是否需要实时交互、流的来源、你的技术栈等)来选择最合适的解决方案。对于大多数应用场景,使用插件或服务器端转码可能是最简单有效的方法,但不是效率最高的办法,特别是对延迟要求比较高的场景,可以考虑使用大牛直播SDK这种专业的Unity RTMP|RTSP播放模块,无论是延迟还是稳定性,均可达到业内顶级的水准。以上是Unity下多路播放RTMP|RTSP的技术探讨,感兴趣的开发者,可以单独跟我沟通讨论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/53423.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

9.20日学习记录及相关问题解答

部分一 今天看了一本古老的书。学到了一些有关计算机的远古的知识。弥补了一些之前没有意识到的空白点。 原来上个世纪就有AI这个东西了 现阶段的主流模式,在许多年前其实是将来要发展的对象。 B/S指的是客户机/服务器结构模式 C/S是在B/S基础上发展过来的。三层结…

网络安全-LD_PRELOAD,请求劫持

目录 一、环境 二、开始做题 三、总结原理 四、如何防护 一、环境 我们这里用蚁剑自带的靶场第一关来解释 docker制作一下即可 二、开始做题 首先环境内很明显给我们已经写好了webshell 同样我们也可以访问到 我们使用这个蚁剑把这个webshell连上 我们发现命令不能执行&am…

Dockerfile全面指南:从基础到进阶,掌握容器化构建的核心工具

目录 Dockerfile全面指南:从基础到进阶,掌握容器化构建的核心工具 引言 一、什么是 Dockerfile 二、Dockerfile 的基本结构 三、Dockerfile 的常见配置项 1、多阶段构建 (Multi-stage Builds) 2、缓存优化 3、合并 RUN 命令 四、Dockerfile 使用…

从数据仓库到数据中台再到数据飞轮:我了解的数据技术进化史

这里写目录标题 前言数据仓库:数据整合的起点数据中台:数据共享的桥梁数据飞轮:业务与数据的双向驱动结语 前言 在当今这个数据驱动的时代,企业发展离不开对数据的深度挖掘和高效利用。从最初的数据仓库,到后来的数据…

基于SpringBoot+Vue+MySQL的校园一卡通系统

系统展示 用户前台界面 管理员后台界面 系统背景 随着现代社会的快速发展,校园一卡通已成为大学生活中不可或缺的一部分。它不仅承载着校园消费的功能,还集成了学生身份证明、图书馆借阅、门禁系统等多种服务。然而,传统的一卡通管理系统往往…

OpenCL 学习(2)---- OpenCL Platform 和 Device

目录 OpenCL PlatformOpenCL Device参考代码 OpenCL Platform opencl 支持的 Platform 可以使用 clGetPlatformIDs 函数查询,函数原型如下: clGetPlatformIDs(cl_uint /* num_entries */,cl_platform_id * /* platforms */,cl_uint * …

鸿蒙OpenHarmony【轻量系统内核扩展组件(CPU占用率)】子系统开发

基本概念 CPU(中央处理器,Central Processing Unit)占用率分为系统CPU占用率和任务CPU占用率。 系统CPU占用率:是指周期时间内系统的CPU占用率,用于表示系统一段时间内的闲忙程度,也表示CPU的负载情况。系…

linux中vim编辑器的应用实例

前言 Linux有大量的配置文件,其中编辑一些配置文件,最常用的工具就是 Vim ,本文介绍一个实际应用的Vim编辑器开发文档的实例。 Vim是一个类似于Vi的著名的功能强大、高度可定制的文本编辑器,在Vi的基础上改进和增加了很多特性。…

告别枯燥:我开发了一个在电脑桌面上使用弹幕来背单词的软件

前言 在这个快节奏的时代,我们每天都在忙碌中度过,手机虽然方便,但往往难以找到一整块时间来专心背单词。然而,你是否意识到,每天坐在电脑前的时间远比使用手机的时间要长?现在我们来介绍一个新型的学习软…

基于大数据的电子产品需求数据分析系统的设计与实现(Python Vue Flask Mysql)

💗博主介绍💗:✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示:文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…

Springboot 文件上传下载相关问题

文章目录 关于Springboot 文件上传下载问题解决方案注意事项文件上传文件下载文件删除文件在线打开在写练习的时候,发现了一些小小的问题,已经在 上述代码中体现。① 代码路径碰到中文的时候,会有乱码,需要转换(内容中…

浏览器插件利器--allWebPluginV2.0.0.20-stable版发布

allWebPlugin简介 allWebPlugin中间件是一款为用户提供安全、可靠、便捷的浏览器插件服务的中间件产品,致力于将浏览器插件重新应用到所有浏览器。它将现有ActiveX控件直接嵌入浏览器,实现插件加载、界面显示、接口调用、事件回调等。支持Chrome、Firefo…

我的AI工具箱Tauri版-VideoIntroductionClipCut视频介绍混剪

本教程基于自研的AI工具箱Tauri版进行VideoIntroductionClipCut视频介绍混剪。 本项目为自研的AI工具箱Tauri版中的视频剪辑模块,专注于自动生成视频介绍片段。该模块名为 VideoIntroductionClipCut,用户可以通过该工具快速进行视频的混剪和介绍内容的生…

【网络】高级IO——epoll版本TCP服务器初阶

目录 前言 一,epoll的三个系统调用接口 1.1.epoll_create函数 1.1.1.epoll_create函数干了什么 1.2. epoll_ctl函数 1.2.1.epoll_ctl函数函数干了什么 1.3.epoll_wait函数 1.3.1.epoll_wait到底干了什么 1.4.epoll的工作过程中内核在干什么 二,…

nginx upstream转发连接错误情况研究

本次测试用到3台服务器: 192.168.10.115:转发服务器A 192.168.10.209:upstream下服务器1 192.168.10.210:upstream下服务器2 1台客户端:192.168.10.112 服务器A中nginx主要配置如下: log_format main…

linux下共享内存的3种使用方式

进程是资源封装的单位,内存就是进程所封装的资源的一种。一般情况下,进程间的内存是相互隔离的,也就是说一个进程不能访问另一个进程的内存。如果一个进程想要访问另一个进程的内存,那么必须要进过内核这个桥梁,这就是…

基于SpringBoot+Vue+MySQL的医院信息管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 在当今社会,随着医疗服务需求的不断增长和医疗信息化的快速发展,提升医院管理效率和服务质量成为了医疗行业的核心需求。传统的医院管理模式面临着效率低下、资源分配不均、患者就医体验差等问题。为了应…

Nginx 跨域 + 无法设置 Cookie 解决办法

今天来分享一下关于项目部署上线时怎么解决跨域问题!!! 首先感谢一下大佬的方法,才让这个困扰我很久的问题得以解决!!! 这也是我请教大佬才解决的问题,大佬和我说,这是他耗费两周才解决的问题,我这也是属于前人栽树后人乘凉了,嘿嘿嘿!!! 前端问题 前端没有携带 cookie 导致后端…

uni-app安装插件

1.通过插件市场安装https://ext.dcloud.net.cn 打开HBuilderX编辑器。 点击菜单栏中的“工具”->“插件安装”。 这里会看到已安装插件和安装新插件两个选项卡,点击安装新插件, 能看到一些核心插件,如果所需要的插件在核心插件里面有&…

1、vectorCast单元测试常用操作

一、自动创建测试工程 1、设置工作目录 进入软件主页面,点击file,选择set working directory,随便选择一个保存该项目的目录即可。 2、创建一个空工程 编译器选择vector自带的编译器,vectorCast MinGW C。 此时项目工程就创建好了 2.1、配置编译器节点 点击编译器节点…