VR头显Unity下如何实现毫秒级延迟的RTMP或RTSP播放?

简介: VR头显Unity下如何实现毫秒级延迟的RTMP或RTSP播放?

技术背景

虚拟现实(VR)技术的互动性和沉浸感,为我们提供了一种全新的视觉体验,不过,如果需要实现真正的沉浸式体验,VR播放的延迟问题非常重要。

好多VR场景下,如果存在延迟,用户在移动头部时可能会感觉到画面反应不及时,导致影响视频的流畅度。在VR电影或VR直播中,延迟则可能导致画面和声音的实时同步出现问题,使用户产生晕眩感。

如何尽可能降低Unity环境下的直播播放延迟,是摆在我们面前的大问题,目前,硬件厂商也采用一些更加好的传输技术,例如5G网络等高速网络技术,以降低传输延迟。当然,还可以通过优化传输链路及数据处理流程等方法,提高传输速度和实时性。今天,我们主要介绍的是VR头显下,如何低延迟的实现RTMP或RTSP的播放。

技术实现

说了这么多,如何在VR头显端,尽可能的降低直播播放延迟呢?常用的方法,比如可以用专门的播放器中间件,实现数据的拉流解码会数据回调,在unity下,优化数据处理和渲染。

以大牛直播SDK为例,我们在做Unity下RTMP或RTSP直播播放的时候,大多场景对延迟和资源占有要求非常高,鉴于好多时候,特别是头显终端,性能可能不尽人意,需要播放的视频分辨率码率又高,如何高效率的实现低延迟的RTMP或RTSP播放,是Unity下比较棘手的问题,特别是毫秒级延迟。

以Android平台为例,原生模块拿到RTSP或RTSP流后,解码获取到原始的YUV或RGB数据,然后投递给Unity,Unity下如果需要更低的延迟,数据交互这块,尽可能的高效率,尽可能的减少数据的投递和拷贝。

开始播放:

privatevoidOnStartStopBtnClicked()
{
if (is_running)
  {
Close();
btn_start_stop_playback_.GetComponentInChildren<Text>().text="开始播放";
btn_decode_mode_.GetComponent<Button>().interactable=true;
btn_latency_mode_.GetComponent<Button>().interactable=true;
  }
else  {
Play();
btn_start_stop_playback_.GetComponentInChildren<Text>().text="停止播放";
btn_decode_mode_.GetComponent<Button>().interactable=false;
btn_latency_mode_.GetComponent<Button>().interactable=false;
  }
}

image.gif

对应Play()实现,这里主要是播放前参数设定,比如采用软解还是硬解码、buffer time是多少,是不是开启低延迟模式等:

//Author: daniusdk.compublicvoidPlay()
{
if (is_running)
  {
Debug.Log("已经在播放。。");   
return;
  }
OpenPlayer();
if ( player_handle_==0 )
return;
NT_U3D_Set_Game_Object(player_handle_, game_object_);
/* ++ 播放前参数配置可加在此处 ++ */intis_using_tcp=0;        //TCP/UDP模式设置NT_U3D_SetRTSPTcpMode(player_handle_, is_using_tcp);
intis_report=0;
intreport_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软硬解模式intis_fast_startup=1;
NT_U3D_SetFastStartup(player_handle_, is_fast_startup);                     //设置快速启动模式intrtsp_timeout=10;
NT_U3D_SetRTSPTimeout(player_handle_, rtsp_timeout);                        //设置RTSP超时时间intis_auto_switch_tcp_udp=1;
NT_U3D_SetRTSPAutoSwitchTcpUdp(player_handle_, is_auto_switch_tcp_udp);    //设置TCP/UDP模式自动切换intis_audiotrack=1;
NT_U3D_SetAudioOutputType(player_handle_, is_audiotrack);                   //设置音频输出模式: if 0: 自动选择; if with 1: audiotrack模式NT_U3D_SetUrl(player_handle_, videoUrl);
/* -- 播放前参数配置可加在此处 -- */intflag=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;  
}

image.gif

开始播放后,native模块,回调yuv/rgb数据,unity3d模块,做相应的绘制处理即可。

privatevoidUpdate()
{
if (!is_need_get_frame_)
return;
if (player_handle_==0)
return;
AndroidJavaObjectu3d_video_frame_obj=NT_U3D_GetVideoFrame(player_handle_);
if (u3d_video_frame_obj==null)
return;
VideoFrameconverted_video_frame=ConvertToVideoFrame(u3d_video_frame_obj);
if (converted_video_frame==null)
return;
if ( !is_need_init_texture_)
  {
if (converted_video_frame.width_!=video_width_||converted_video_frame.height_!=video_height_||converted_video_frame.y_stride_!=y_row_bytes_||converted_video_frame.u_stride_!=u_row_bytes_||converted_video_frame.v_stride_!=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=null;
}

image.gif

如果需要关闭RTMP或RTSP流,调用对应的ClosePlayer()就好:

privatevoidClosePlayer()
{
is_need_get_frame_=false;
is_need_init_texture_=false;
intflag=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_width_=0;
video_height_=0;
}

image.gif

以上以Android平台为例,大概介绍了Unity环境下的RTMP、RTSP直播播放,如果需要延迟和稳定性都靠谱,建议数据接收、解包解码回调yuv/rgb数据在原始native模块处理,然后把解码后的数据,高效率的投递到unity测,实现unity环境下的低延迟RTMP或RTSP,感兴趣的开发者可以酌情了解。

相关文章
|
29天前
|
编解码 vr&ar 图形学
|
29天前
|
编解码 vr&ar 图形学
Unity下如何实现低延迟的全景RTMP|RTSP流渲染
随着虚拟现实技术的发展,全景视频成为新的媒体形式。本文详细介绍了如何在Unity中实现低延迟的全景RTMP或RTSP流渲染,包括环境准备、引入依赖、初始化客户端、解码与渲染、优化低延迟等步骤,并提供了具体的代码示例。适用于远程教育、虚拟旅游等实时交互场景。
58 5
|
12天前
|
编解码 vr&ar 图形学
Unity下如何实现低延迟的全景RTMP|RTSP流渲染
随着虚拟现实技术的发展,全景视频逐渐成为新的媒体形式。本文详细介绍了如何在Unity中实现低延迟的全景RTMP或RTSP流渲染,包括环境准备、引入依赖、初始化客户端、解码与渲染、优化低延迟等步骤,并提供了具体的代码示例。适用于远程教育、虚拟旅游等实时交互场景。
20 2
|
14天前
|
编解码 vr&ar 图形学
超时空穿越!揭秘如何在VR头显端实现毫秒级低延迟的RTSP|RTMP播放,打造沉浸式直播新纪元!
本文详细介绍了如何在VR头显端实现低延迟的RTSP或RTMP播放。首先,确保开发环境已安装Unity编辑器及相关插件。接着,通过初始化客户端、解码视频数据并渲染到VR头显屏幕,实现流畅的视频播放。最后,提供了优化低延迟的方法,包括硬件加速、减少缓冲区大小和选择合适的编解码器。示例代码展示了具体实现步骤。
24 1
|
3月前
|
图形学 Android开发 iOS开发
穿越数字洪流,揭秘Unity3d中的视频魔法!Windows、Android和iOS如何征服RTSP与RTMP的终极指南!
【8月更文挑战第15天】在数字媒体的海洋中,实时视频流是连接世界的桥梁。对于那些渴望在Unity3d中搭建这座桥梁的开发者来说,本文将揭示如何在Windows、Android和iOS平台上征服RTSP与RTMP的秘密。我们将深入探讨这两种协议的特性,以及在不同平台上实现流畅播放的技巧。无论你是追求稳定性的RTSP拥趸,还是低延迟的RTMP忠实粉丝,这里都有你需要的答案。让我们一起穿越数字洪流,探索Unity3d中视频魔法的世界吧!
64 2
|
5月前
|
人工智能 编解码 5G
虚拟现实(VR)与增强现实(AR)的融合:开启全新交互时代
【6月更文挑战第17天】虚拟现实(VR)与增强现实(AR)融合成混合现实(MR),打造全新交互体验。MR结合VR的沉浸感和AR的现实增强,应用于教育、游戏、设计和营销,带来创新教学方式、沉浸式游戏体验和高效设计工具。尽管面临技术挑战,随着5G和AI的发展,MR有望引领未来交互的革命。
|
5月前
|
传感器 数据可视化 安全
【虚拟现实】二、主要的AR/VR硬件设备
【虚拟现实】二、主要的AR/VR硬件设备
96 3
|
2月前
|
5G 测试技术 语音技术
5G赋能沉浸式体验:VR/AR时代的网络基石
5G赋能沉浸式体验:VR/AR时代的网络基石
71 1
下一篇
无影云桌面