Partage de technologie

Comment le casque VR lit-il le flux RTSP|RTMP 8K avec une faible latence ?

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

formation technique

Lorsque nous créions des lecteurs RTSP et RTMP pour la plate-forme Unity, certaines entreprises ont mis en avant de telles exigences techniques, dans l'espoir de lire des flux en direct panoramiques 8K RTSP|RTMP et des données 8K sur le casque, ce qui a proposé de nouvelles idées pour le casque et le lecteur. En fonction des exigences, nous discuterons de la manière dont les visiocasques VR lisent les données de streaming RTSP|RTMP 8K sous plusieurs aspects :

1. Assistance aux joueurs

  1. compatibilité : Premièrement, le lecteur RTSP|RTMP doit prendre en charge le streaming vidéo en résolution 8K. Cela signifie que le lecteur doit être capable de décoder la vidéo 8K et de la lire sur un périphérique d'affichage prenant en charge la résolution 8K. Inutile de dire que nous le prenons déjà en charge.
  2. capacité de décodage : Le lecteur doit disposer de puissantes capacités de décodage pour gérer la grande quantité de données contenues dans le flux vidéo 8K. Cela nécessite généralement que le joueur utilise des algorithmes de décodage efficaces et utilise pleinement les fonctions d'accélération matérielle (telles que l'accélération GPU), ce qui nécessite que le casque prenne en charge le décodage dur 8K.

2. Exigences du réseau

  1. bande passante : Le streaming vidéo 8K nécessite une bande passante réseau extrêmement élevée pour prendre en charge la transmission en temps réel. Assurez-vous que la bande passante du réseau est suffisamment grande pour éviter des problèmes tels que le retard, le retard ou la mise en mémoire tampon pendant la lecture. S'il s'agit d'un environnement intranet, ne vous inquiétez pas des problèmes de bande passante.
  2. la stabilité : La stabilité de la connexion réseau est également très importante. Une connexion réseau instable peut entraîner une interruption du streaming vidéo ou une dégradation de la qualité.

3. Exigences matérielles

  1. Processeur et mémoire: Les casques VR diffusent des flux vidéo 8K, ce qui impose des exigences très élevées en matière de performances des casques VR. Par exemple, quest3 est un bon choix.

4. Étapes de lecture

  1. Sélectionnez le lecteur RTSP: Notre approche consiste à utiliser le lecteur RTSP|RTMP natif du Daniu Live SDK en mode de décodage dur pour rappeler les données YUV ou RGB décodées à l'unité. Il est à noter qu'en raison du flux RTSP|RTMP 8K, la quantité de données. Les données très volumineuses, notamment décodées, doivent être réduites le moins possible si les conditions le permettent.

Réalisation technique

Cet article prend comme exemple le module de lecture RTSP|RTMP de la plateforme Android Unity3D du SDK Daniu Live :

Commencer à jouer:

  1. /*
  2. * SmartPlayerAndroidMono.cs
  3. * Author: daniusdk.com
  4. * QQ:89030985
  5. */
  6. public void Play()
  7. {
  8. if (is_running)
  9. {
  10. Debug.Log("已经在播放。。");
  11. return;
  12. }
  13. //获取输入框的url
  14. string url = input_url_.text.Trim();
  15. if (!url.StartsWith("rtmp://") && !url.StartsWith("rtsp://"))
  16. {
  17. videoUrl = "rtsp://admin:[email protected]:554/h264/ch1/main/av_stream";
  18. }
  19. else
  20. {
  21. videoUrl = url;
  22. }
  23. OpenPlayer();
  24. if ( player_handle_ == 0 )
  25. return;
  26. NT_U3D_Set_Game_Object(player_handle_, game_object_);
  27. /* ++ 播放前参数配置可加在此处 ++ */
  28. int is_using_tcp = 0; //TCP/UDP模式设置
  29. NT_U3D_SetRTSPTcpMode(player_handle_, is_using_tcp);
  30. int is_report = 0;
  31. int report_interval = 1;
  32. NT_U3D_SetReportDownloadSpeed(player_handle_, is_report, report_interval); //下载速度回调
  33. NT_U3D_SetBuffer(player_handle_, play_buffer_time_); //设置buffer time
  34. NT_U3D_SetPlayerLowLatencyMode(player_handle_, is_low_latency_ ? 1 : 0); //设置是否启用低延迟模式
  35. NT_U3D_SetMute(player_handle_, is_mute_ ? 1 : 0); //是否启动播放的时候静音
  36. NT_U3D_SetAudioVolume(player_handle_, cur_audio_volume_); //设置播放音量
  37. NT_U3D_SetVideoDecoderMode(player_handle_, is_hw_decode_ ? 1 : 0); //设置H.264软硬解模式
  38. NT_U3D_SetVideoHevcDecoderMode(player_handle_, is_hw_decode_ ? 1 : 0); //设置H.265软硬解模式
  39. int is_output = 1;
  40. int disable_use_image_planes = 0;
  41. bool is_supports_texture_format = SystemInfo.SupportsTextureFormat(TextureFormat.RG16);
  42. Debug.Log("is_supports_texture_format: " + is_supports_texture_format);
  43. int is_supported_multiple_format = is_supports_texture_format? 1:0;
  44. int max_images = 3;
  45. int buffer_pool_max_size = 0;
  46. NT_U3D_SetImageReaderOutput(player_handle_, is_output, disable_use_image_planes, is_supported_multiple_format, max_images, buffer_pool_max_size); //硬解码image reader
  47. int is_fast_startup = 1;
  48. NT_U3D_SetFastStartup(player_handle_, is_fast_startup); //设置快速启动模式
  49. int rtsp_timeout = 10;
  50. NT_U3D_SetRTSPTimeout(player_handle_, rtsp_timeout); //设置RTSP超时时间
  51. int is_auto_switch_tcp_udp = 1;
  52. NT_U3D_SetRTSPAutoSwitchTcpUdp(player_handle_, is_auto_switch_tcp_udp); //设置TCP/UDP模式自动切换
  53. int is_audiotrack = 1;
  54. NT_U3D_SetAudioOutputType(player_handle_, is_audiotrack); //设置音频输出模式: if 0: 自动选择; if with 1: audiotrack模式
  55. NT_U3D_SetUrl(player_handle_, videoUrl);
  56. /* -- 播放前参数配置可加在此处 -- */
  57. int flag = NT_U3D_StartPlay(player_handle_);
  58. if (flag == DANIULIVE_RETURN_OK)
  59. {
  60. is_need_get_frame_ = true;
  61. Debug.Log("播放成功");
  62. }
  63. else
  64. {
  65. is_need_get_frame_ = false;
  66. Debug.LogError("播放失败");
  67. }
  68. is_running = true;
  69. }

L'implémentation OpenPlayer() correspondante est la suivante :

  1. private void OpenPlayer()
  2. {
  3. if ( java_obj_cur_activity_ == null )
  4. {
  5. Debug.LogError("getApplicationContext is null");
  6. return;
  7. }
  8. player_handle_ = NT_U3D_Open();
  9. if (player_handle_ != 0)
  10. Debug.Log("open success");
  11. else
  12. Debug.LogError("open fail");
  13. }

Fermer le joueur :

  1. private void ClosePlayer()
  2. {
  3. is_need_get_frame_ = false;
  4. is_need_init_texture_ = false;
  5. int flag = NT_U3D_StopPlay(player_handle_);
  6. if (flag == DANIULIVE_RETURN_OK)
  7. {
  8. Debug.Log("停止成功");
  9. }
  10. else
  11. {
  12. Debug.LogError("停止失败");
  13. }
  14. flag = NT_U3D_Close(player_handle_);
  15. if (flag == DANIULIVE_RETURN_OK)
  16. {
  17. Debug.Log("关闭成功");
  18. }
  19. else
  20. {
  21. Debug.LogError("关闭失败");
  22. }
  23. player_handle_ = 0;
  24. NT_U3D_UnInit();
  25. is_running = false;
  26. video_format_ = VideoFrame.FORMAT_UNKNOWN;
  27. video_width_ = 0;
  28. video_height_ = 0;
  29. }

Mettre à jour les données d'actualisation :

  1. private void Update()
  2. {
  3. if (!is_need_get_frame_)
  4. return;
  5. if (player_handle_ == 0)
  6. return;
  7. AndroidJavaObject u3d_video_frame_obj = NT_U3D_GetVideoFrame(player_handle_);
  8. if (u3d_video_frame_obj == null)
  9. {
  10. return;
  11. }
  12. VideoFrame converted_video_frame = ConvertToVideoFrame(u3d_video_frame_obj);
  13. if (converted_video_frame == null)
  14. {
  15. u3d_video_frame_obj.Call("release");
  16. u3d_video_frame_obj = null;
  17. return;
  18. }
  19. if (!is_need_init_texture_)
  20. {
  21. if (converted_video_frame.format_ != video_format_)
  22. {
  23. is_need_init_texture_ = true;
  24. }
  25. else if (converted_video_frame.width_ != video_width_
  26. || converted_video_frame.height_ != video_height_
  27. || converted_video_frame.stride0_ != y_row_bytes_
  28. || converted_video_frame.stride1_ != u_row_bytes_
  29. || converted_video_frame.stride2_ != v_row_bytes_)
  30. {
  31. is_need_init_texture_ = true;
  32. }
  33. }
  34. if (is_need_init_texture_)
  35. {
  36. if (InitYUVTexture(converted_video_frame))
  37. {
  38. is_need_init_texture_ = false;
  39. }
  40. }
  41. UpdateYUVTexture(converted_video_frame);
  42. converted_video_frame.java_frame_obj_ = null;
  43. converted_video_frame = null;
  44. u3d_video_frame_obj.Call("release");
  45. u3d_video_frame_obj = null;
  46. }

Résumer

Si un casque VR doit lire des flux RTSP ou RTSP 8K, il a des exigences très élevées en matière de matériel et de réseau, il peut donc rencontrer certains défis dans les applications pratiques. Grâce à des tests réels, le casque quest3, combiné à notre lecteur RTSP|RTMP, peut atteindre un retard de la milliseconde dans la lecture des données vidéo 8K dans Unity pour répondre à des scénarios d'utilisation avec des exigences en temps réel très élevées, telles que le contrôle de la balance. Les développeurs intéressés peuvent en discuter. avec moi individuellement.