Android平台下VR头显如何低延迟播放4K以上超高分辨率RTSP|RTMP流

06-23 1495阅读

技术背景

VR头显需要更高的分辨率以提供更清晰的视觉体验、满足沉浸感的要求、适应透镜放大效应以及适应更广泛的可视角度,超高分辨率的优势如下:

  1. 提供更清晰的视觉体验:VR头显的分辨率直接决定了用户所看到的图像的清晰度。更高的分辨率意味着更多的像素数,可以呈现更细腻、更逼真的图像,从而提升用户的视觉体验,更高的分辨率可以进一步减少图像中的颗粒感和纱窗效应,让用户感受到更加真实的虚拟世界。
  2. 满足沉浸感的要求:VR头显的主要目的是为用户提供沉浸式的体验,使用户感觉自己完全置身于虚拟环境中。为了达到这种效果,头显需要能够呈现足够清晰、细腻的图像,以便用户能够清晰地看到虚拟环境中的各种细节。更高的分辨率可以确保用户在头部移动或转动时,依然能够保持画面的清晰度和稳定性,从而增强沉浸感。
  3. 适应透镜放大效应:VR头显通过透镜将小屏幕放大至用户眼前,以模拟大屏幕的效果。然而,这种放大效应会导致图像的像素密度降低,使得图像看起来相对模糊。因此,为了保持放大后的图像依然清晰,VR头显需要更高的分辨率来弥补透镜放大带来的像素密度降低问题。
  4. 适应更广泛的可视角度:一些VR头显设计倾向于在画质可以接受的情况下,尽量增大可视角度,以便用户能够更自然地观察虚拟环境。然而,这也会导致图像在边缘区域出现拉伸和变形。为了保持这些区域依然清晰可辨,VR头显需要更高的分辨率来确保整个画面的清晰度和稳定性。

技术实现

实际上,大牛直播SDK在2018年就发布了Unity的RTSP|RTMP的播放模块,平台陆续覆盖了Windows、Android、iOS和Linux,Unity下播放RTSP|RTMP流,原理很简单,底层原生模块,把RTSP|RTMP流拉过来,做解析解码回调YUV或RGB数据到上层,Unity环境下,做绘制即可。说来容易,难点在于,如果需要更好的解码效率、资源占用和低延迟,需要确保每个环节都做到极致,总体延迟可以达到200-400ms。

Android平台下VR头显如何低延迟播放4K以上超高分辨率RTSP|RTMP流

目前我们实现的功能如下:

  •  [支持播放协议]高稳定、超低延迟(毫秒级延迟,行业内几无效果接近的播放端)、业内首屈一指的RTMP、RTSP直播播放SDK;
  •  [多实例播放]支持多实例播放;
  •  [事件回调]支持网络状态、buffer状态等回调;
  •  [视频格式]支持RTMP扩展H.265,H.264;
  •  [音频格式]支持AAC/PCMA/PCMU/Speex;
  •  [H.264/H.265软解码]支持H.264/H.265软解;
  •  [H.264硬解码]Android/iOS支持H.264特定机型硬解;
  •  [H.265硬解]Android/iOS支持H.265特定机型硬解;
  •  [RTSP模式设置]支持RTSP TCP/UDP模式设置;
  •  [RTSP TCP/UDP自动切换]支持RTSP TCP、UDP模式自动切换;
  •  [RTSP超时设置]支持RTSP超时时间设置,单位:秒;
  •  [RTSP 401认证处理]支持上报RTSP 401事件,如URL携带鉴权信息,会自动处理;
  •  [缓冲时间设置]支持buffer time设置;
  •  [首屏秒开]支持首屏秒开模式;
  •  [低延迟模式]支持超低延迟模式设置;
  •  [复杂网络处理]支持断网重连等各种网络环境自动适配;
  •  [快速切换URL]支持播放过程中,快速切换其他URL,内容切换更快;
  •  [实时静音]支持播放过程中,实时静音/取消静音;
  •  [实时快照]支持播放过程中截取当前播放画面;
  •  [渲染角度]支持0°,90°,180°和270°四个视频画面渲染角度设置;
  •  [渲染镜像]支持水平反转、垂直反转模式设置;
  •  [实时下载速度更新]支持当前下载速度实时回调(支持设置回调时间间隔);
  •  [音视频自适应]支持播放过程中,音视频信息改变后自适应播放;
  •  [扩展录像功能]完美支持和录像模块组合使用。

    废话不多说,上代码,先说开始播放:

    /*
     * SmartPlayerAndroidMono.cs
     * Author: daniusdk.com
     * Created on 2018/05/10.
     */
    public void Play()
    {
    	if (is_running)
    	{
    		Debug.Log("已经在播放。。");   
    		return;
    	}
    	//获取输入框的url
    	string url = input_url_.text.Trim();
    	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 time
    	NT_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 reader
    	int 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");
    	else
    		Debug.LogError("open fail");
    }

    ClosePlayer实现如下:

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

    总结

    VR头显下播放超高分辨率的RTSP或RTMP,实现低延迟的播放,意义很大,比如平衡操控场景下,可以远程操控挖掘机等危险设备,提高工作效率、改善工作环境、降低安全风险、节约人力成本。在虚拟仿真、无人机操控等场景下也意义重大,感兴趣的开发者,可以单独跟我交流。

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]