当前位置: 首页 > news >正文

VR头显如何低延迟播放8K的RTSP|RTMP流

技术背景

我们在做Unity平台RTSP、RTMP播放器的时候,有公司提出来这样的技术需求,希望在头显播放全景的8K RTSP|RTMP直播流,8K的数据,对头显和播放器,都提出了新的要求,我们从几个方面,探讨下VR头显设备如何播放8K的RTSP|RTMP流数据:

一、播放器支持

  1. 兼容性:首先,RTSP|RTMP播放器需要支持8K分辨率的视频流。这意味着播放器必须能够解码8K视频,并在支持8K分辨率的显示设备上播放,这个不必多说,我们已经支持。
  2. 解码能力:播放器需要具备强大的解码能力,以处理8K视频流中的大量数据。这通常要求播放器使用高效的解码算法,并充分利用硬件加速功能(如GPU加速),这就需要头显支持8K的硬解码。

二、网络要求

  1. 带宽:8K视频流需要极高的网络带宽来支持实时传输。确保网络带宽足够大,以避免播放过程中出现卡顿、延迟或缓冲等问题,如果是内网环境下,基本不要纠结带宽问题。
  2. 稳定性:网络连接的稳定性也非常重要。不稳定的网络连接可能导致视频流中断或质量下降。

三、硬件要求

  1. 处理器与内存:VR头显播放8K的视频流,对VR头显的性能,提了很高的要求,比如说quest3,就是不错的选择。

四、播放步骤

  1. 选择RTSP播放器:我们的做法,是用大牛直播SDK的原生的RTSP|RTMP播放器,硬解码模式,回调解码后的YUV或RGB数据到unity,需要注意的是,由于8K的RTSP|RTMP流,数据量非常大,特别是解码后的数据,条件允许的情况下,需要尽可能少的减少拷贝。

技术实现

本文以大牛直播SDK的Android平台Unity3D RTSP|RTMP播放模块为例:

开始播放:

/** SmartPlayerAndroidMono.cs* Author: daniusdk.com* QQ:89030985*/
public void Play()
{if (is_running){Debug.Log("已经在播放。。");   return;}//获取输入框的urlstring url = input_url_.text.Trim();if (!url.StartsWith("rtmp://") && !url.StartsWith("rtsp://")){videoUrl = "rtsp://admin:daniulive12345@192.168.0.120:554/h264/ch1/main/av_stream";}else{videoUrl = url;}OpenPlayer();if ( player_handle_ == 0 )return;NT_U3D_Set_Game_Object(player_handle_, game_object_);/* ++ 播放前参数配置可加在此处 ++ */int is_using_tcp = 0;        //TCP/UDP模式设置NT_U3D_SetRTSPTcpMode(player_handle_, is_using_tcp);int is_report = 0;int report_interval = 1;NT_U3D_SetReportDownloadSpeed(player_handle_, is_report, report_interval);  //下载速度回调NT_U3D_SetBuffer(player_handle_, play_buffer_time_);                        //设置buffer timeNT_U3D_SetPlayerLowLatencyMode(player_handle_, is_low_latency_ ? 1 : 0);    //设置是否启用低延迟模式NT_U3D_SetMute(player_handle_, is_mute_ ? 1 : 0);                           //是否启动播放的时候静音NT_U3D_SetAudioVolume(player_handle_, cur_audio_volume_);                   //设置播放音量NT_U3D_SetVideoDecoderMode(player_handle_, is_hw_decode_ ? 1 : 0);          //设置H.264软硬解模式NT_U3D_SetVideoHevcDecoderMode(player_handle_, is_hw_decode_ ? 1 : 0);          //设置H.265软硬解模式int is_output = 1;int disable_use_image_planes = 0;bool is_supports_texture_format = SystemInfo.SupportsTextureFormat(TextureFormat.RG16);Debug.Log("is_supports_texture_format: " + is_supports_texture_format);int is_supported_multiple_format = is_supports_texture_format? 1:0;int max_images = 3;int buffer_pool_max_size = 0;NT_U3D_SetImageReaderOutput(player_handle_, is_output, disable_use_image_planes, is_supported_multiple_format, max_images, buffer_pool_max_size);  //硬解码image readerint is_fast_startup = 1;NT_U3D_SetFastStartup(player_handle_, is_fast_startup);                     //设置快速启动模式int rtsp_timeout = 10;NT_U3D_SetRTSPTimeout(player_handle_, rtsp_timeout);                        //设置RTSP超时时间int is_auto_switch_tcp_udp = 1;NT_U3D_SetRTSPAutoSwitchTcpUdp(player_handle_, is_auto_switch_tcp_udp);    //设置TCP/UDP模式自动切换int is_audiotrack = 1;NT_U3D_SetAudioOutputType(player_handle_, is_audiotrack);                   //设置音频输出模式: if 0: 自动选择; if with 1: audiotrack模式NT_U3D_SetUrl(player_handle_, videoUrl);/* -- 播放前参数配置可加在此处 -- */int flag = NT_U3D_StartPlay(player_handle_);if (flag  == DANIULIVE_RETURN_OK){is_need_get_frame_ = true;Debug.Log("播放成功");}else{is_need_get_frame_ = false;Debug.LogError("播放失败");}is_running = true;  
}

对应的OpenPlayer()实现如下:

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

关闭Player:

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

Update刷新数据:

private void Update()
{if (!is_need_get_frame_)return;if (player_handle_ == 0)return;AndroidJavaObject u3d_video_frame_obj = NT_U3D_GetVideoFrame(player_handle_);if (u3d_video_frame_obj == null){return;}VideoFrame converted_video_frame = ConvertToVideoFrame(u3d_video_frame_obj);if (converted_video_frame == null){u3d_video_frame_obj.Call("release");u3d_video_frame_obj = null;return;}if (!is_need_init_texture_){if (converted_video_frame.format_ != video_format_){is_need_init_texture_ = true;}else if (converted_video_frame.width_ != video_width_|| converted_video_frame.height_ != video_height_|| converted_video_frame.stride0_ != y_row_bytes_|| converted_video_frame.stride1_ != u_row_bytes_|| converted_video_frame.stride2_ != v_row_bytes_){is_need_init_texture_ = true;}}if (is_need_init_texture_){if (InitYUVTexture(converted_video_frame)){is_need_init_texture_ = false;}}UpdateYUVTexture(converted_video_frame);converted_video_frame.java_frame_obj_ = null;converted_video_frame = null;u3d_video_frame_obj.Call("release");u3d_video_frame_obj = null;
}

总结

VR头显如果需要播放8K的RTSP或RTSP流,对硬件和网络的要求非常高,因此在实际应用中可能会遇到一些挑战。通过实际测试,在quest3头显,配合我们的RTSP|RTMP播放器,在unity下,可以实现毫秒级延迟的8K视频数据播放,以满足平衡操控等对实时性要求非常高的使用场景,感兴趣的开发者,可以单独跟我探讨。

相关文章:

VR头显如何低延迟播放8K的RTSP|RTMP流

技术背景 我们在做Unity平台RTSP、RTMP播放器的时候,有公司提出来这样的技术需求,希望在头显播放全景的8K RTSP|RTMP直播流,8K的数据,对头显和播放器,都提出了新的要求,我们从几个方面,探讨下V…...

2、ASPX、.NAT(环境/框架)安全

ASPX、.NAT&#xff08;环境/框架&#xff09;安全 源自小迪安全b站公开课 1、搭建组合&#xff1a; WindowsIISaspxsqlserver .NAT基于windows C开发的框架/环境 对抗Java xx.dll <> xx.jar 关键源码封装在dll文件内。 2、.NAT配置调试-信息泄露 功能点&#xf…...

在家上网IP地址是固定的吗?

在数字化时代&#xff0c;互联网已成为我们日常生活中不可或缺的一部分。无论是工作、学习还是娱乐&#xff0c;我们都离不开网络的支持。然而&#xff0c;当我们在家中接入互联网时&#xff0c;可能会产生这样一个疑问&#xff1a;在家上网IP地址是固定的吗&#xff1f;下面一…...

交换机和路由器的工作流程

1、交换机工作流程&#xff1a; 将接口中的电流识别为二进制&#xff0c;并转换成数据帧&#xff0c;交换机会记录学习该数据帧的源MAC地址&#xff0c;并将其端口关联起来记录在MAC地址表中。然后查看MAC地址表来查找目标MAC地址&#xff0c;会有一下一些情况&#xff1a; MA…...

算法笔记——LCR

一.LCR 152. 验证二叉搜索树的后序遍历序列 题目描述&#xff1a; 给你一个二叉搜索树的后续遍历序列&#xff0c;让你判断该序列是否合法。 解题思路&#xff1a; 根据二叉搜索树的特性&#xff0c;二叉树搜索的每一个结点&#xff0c;大于左子树&#xff0c;小于右子树。…...

ChatGPT对话:如何制作静态网页?

【编者按】编者在很早以前制作过静态网页&#xff0c;之后长期没有使用&#xff0c;已完全不知道最新现状了。所以&#xff0c;从制作工具开始询问ChatGPT&#xff0c;回答非常全面&#xff0c;完全可以解决初学者的问题。 编者虽然长期不制作网页&#xff0c;但一直在编程&…...

k8s(二)

五、kubernetes架构(K8S的架构也是master和node模式&#xff09; 集群里至少需要有一个master节点&#xff0c;即就是主节点。node节点可以多个。 若是多个master节点&#xff0c;worker节点和master的apiserverr进行交互时&#xff0c;就需要通过LB(load banlance&#xff09;…...

ClickHouse表引擎概述

ClickHouse表引擎概述 表引擎的功能&#xff1a; 数据的存储方式 数据的存储位置 是否可以使用索引 是否可以使用分区 是否支持数据副本 并发数据访问 ClickHouse在建表时必须指定表引擎。 表引擎主要分为四大类&#xff1a;MergeTree系列、Log系列、与其他存储/处理系…...

jenkins系列-04-jenkins参数化构建

使用maven build之前&#xff0c;先checkout 指定分支或标签&#xff1a; 拖拽调整顺序&#xff1a;shell执行在前&#xff0c;构建在后&#xff1a; gitee新建标签tag:...

Flutter框架时间线梳理

Flutter是一个开源的UI工具包&#xff0c;它用于构建高质量的原生移动应用。Flutter的版本历史如下&#xff1a; Flutter 0.1.2&#xff1a; 2018年发布&#xff0c;这是第一个正式发布的版本&#xff0c;包含了基本的框架和工具。 Flutter 1.0.0&#xff1a; 2019年发布&…...

RAG 效果提升的最后一步—— 微调LLM

如果说&#xff0c;rerank能够让RAG的效果实现百尺竿头更进一步&#xff0c;那么LLM微调应该是RAG效果提升的最后一步。 把召回的数据&#xff0c;经过粗排&#xff0c;重排序后&#xff0c;送给模型&#xff0c;由模型最后总结答案。LLM的确已经是RAG的最后一步了。 这里还是会…...

C语言 | Leetcode C语言题解之第230题二叉搜索树中第K小的元素

题目&#xff1a; 题解&#xff1a; /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/int search_num(struct TreeNode* root, int k, int *result, int num) {if(num k 1){retu…...

YOWOv2(yowov2)动作识别+Fastreid身份识别 详细安装与实现

首先yowov2是一款简单且实时的时空动作检测方案&#xff0c;fastreid是行人重识别&#xff08;身份识别&#xff09; yowov2介绍链接直达fastreid链接直达为时空动作检测任务设计实时框架仍然是一个挑战。YOWOv2 提出了一种新颖的实时动作检测框架&#xff0c;利用三维骨干和二…...

【微服务】Spring Cloud中如何使用Eureka

摘要 Eureka作为Netflix开源的服务发现框架&#xff0c;在Spring Cloud体系中扮演着至关重要的角色。本文详细介绍了Eureka的基本概念、工作原理以及如何在Spring Cloud中集成和使用Eureka进行服务发现和管理。通过深入分析Eureka的注册与发现机制、区域感知和自我保护等高级特…...

【Neo4j】实战 (数据库技术丛书)学习笔记

Neo4j实战 (数据库技术丛书) 第1章演示了应用Neo4j作为图形数据库对改进性能和扩展性的可能性, 也讨论了对图形建模的数据如何正好适应于Neo4j数据模型,现在到了该动 手实践的时间了。第一章 概述 Neo4j将数据作为顶点和边存储(或者用Neo4j术语,节点和关系存 储)。用户被定…...

【Perl】Perl 语言入门

1. Perl语言介绍 Perl 是一种高级、解释型、动态编程语言&#xff0c;由Larry Wall在1987年发布。Perl 以其强大的文本处理能力而闻名&#xff0c;特别是在处理报告生成、文件转换、系统管理任务等方面。它吸收了C、Shell脚本语言、AWK、sed等语言的特性&#xff0c;并加入了大…...

godis源码分析——database存储核心1

前言 redis的核心是数据的快速存储&#xff0c;下面就来分析一下godis的底层存储是如何实现&#xff0c;先分析单机服务。 此文采用抓大放小原则&#xff0c;先大的流程方向&#xff0c;再抓细节。 流程图 源码分析 现在以客户端连接&#xff0c;并发起set key val命令为例…...

【UE5.1】Chaos物理系统基础——06 子弹破坏石块

前言 在前面我们已经完成了场系统的制作&#xff08;【UE5.1】Chaos物理系统基础——02 场系统的应用_ue5&#xff09;以及子弹的制作&#xff08;【UE5.1 角色练习】16-枪械射击——瞄准&#xff09;&#xff0c;现在我们准备实现的效果是&#xff0c;角色发射子弹来破坏石柱。…...

Django是干什么的?好用么?

Django是一个开源的Python Web框架&#xff0c;用于快速开发高质量的Web应用程序。它提供了许多功能和工具&#xff0c;以简化常见的Web开发任务&#xff0c;如路由、请求处理、数据库管理等。 Django的优点包括&#xff1a; 简单易用&#xff1a;Django提供了清晰的文档和丰…...

C语言实现数据结构B树

B树&#xff08;B-Tree&#xff09;是一种自平衡的树数据结构&#xff0c;它维护着数据的有序性&#xff0c;并允许搜索、顺序访问、插入、删除等操作都在对数时间内完成。B树广泛用于数据库和操作系统的文件系统中。 B树的基本特性 根节点&#xff1a;根节点至少有两个子节点…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

从面试角度回答Android中ContentProvider启动原理

Android中ContentProvider原理的面试角度解析&#xff0c;分为​​已启动​​和​​未启动​​两种场景&#xff1a; 一、ContentProvider已启动的情况 1. ​​核心流程​​ ​​触发条件​​&#xff1a;当其他组件&#xff08;如Activity、Service&#xff09;通过ContentR…...

macOS 终端智能代理检测

&#x1f9e0; 终端智能代理检测&#xff1a;自动判断是否需要设置代理访问 GitHub 在开发中&#xff0c;使用 GitHub 是非常常见的需求。但有时候我们会发现某些命令失败、插件无法更新&#xff0c;例如&#xff1a; fatal: unable to access https://github.com/ohmyzsh/oh…...

怎么开发一个网络协议模块(C语言框架)之(六) ——通用对象池总结(核心)

+---------------------------+ | operEntryTbl[] | ← 操作对象池 (对象数组) +---------------------------+ | 0 | 1 | 2 | ... | N-1 | +---------------------------+↓ 初始化时全部加入 +------------------------+ +-------------------------+ | …...

STM32标准库-ADC数模转换器

文章目录 一、ADC1.1简介1. 2逐次逼近型ADC1.3ADC框图1.4ADC基本结构1.4.1 信号 “上车点”&#xff1a;输入模块&#xff08;GPIO、温度、V_REFINT&#xff09;1.4.2 信号 “调度站”&#xff1a;多路开关1.4.3 信号 “加工厂”&#xff1a;ADC 转换器&#xff08;规则组 注入…...