SceneSelectUI.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Globalization;
  5. using System.Linq;
  6. using UnityEngine;
  7. using UnityEngine.SceneManagement;
  8. using UnityEngine.UI;
  9. using Gyroscope = UnityEngine.InputSystem.Gyroscope;
  10. #if URS_USE_AR_FOUNDATION
  11. using UnityEngine.XR.ARFoundation;
  12. #endif
  13. namespace Unity.RenderStreaming.Samples
  14. {
  15. internal enum SignalingType
  16. {
  17. WebSocket,
  18. Http,
  19. Furioos
  20. }
  21. internal class RenderStreamingSettings
  22. {
  23. public const int DefaultStreamWidth = 1280;
  24. public const int DefaultStreamHeight = 720;
  25. private bool useDefaultSettings = false;
  26. private SignalingType signalingType = SignalingType.WebSocket;
  27. private string signalingAddress = "localhost";
  28. private int signalingInterval = 5000;
  29. private bool signalingSecured = false;
  30. private Vector2Int streamSize = new Vector2Int(DefaultStreamWidth, DefaultStreamHeight);
  31. private VideoCodecInfo receiverVideoCodec = null;
  32. private VideoCodecInfo senderVideoCodec = null;
  33. public bool UseDefaultSettings
  34. {
  35. get { return useDefaultSettings; }
  36. set { useDefaultSettings = value; }
  37. }
  38. public SignalingType SignalingType
  39. {
  40. get { return signalingType; }
  41. set { signalingType = value; }
  42. }
  43. public string SignalingAddress
  44. {
  45. get { return signalingAddress; }
  46. set { signalingAddress = value; }
  47. }
  48. public bool SignalingSecured
  49. {
  50. get { return signalingSecured; }
  51. set { signalingSecured = value; }
  52. }
  53. public int SignalingInterval
  54. {
  55. get { return signalingInterval; }
  56. set { signalingInterval = value; }
  57. }
  58. public SignalingSettings SignalingSettings
  59. {
  60. get
  61. {
  62. switch (signalingType)
  63. {
  64. case SignalingType.Furioos:
  65. {
  66. var schema = signalingSecured ? "https" : "http";
  67. return new FurioosSignalingSettings
  68. (
  69. url: $"{schema}://{signalingAddress}"
  70. );
  71. }
  72. case SignalingType.WebSocket:
  73. {
  74. var schema = signalingSecured ? "wss" : "ws";
  75. return new WebSocketSignalingSettings
  76. (
  77. url: $"{schema}://{signalingAddress}"
  78. );
  79. }
  80. case SignalingType.Http:
  81. {
  82. var schema = signalingSecured ? "https" : "http";
  83. return new HttpSignalingSettings
  84. (
  85. url: $"{schema}://{signalingAddress}",
  86. interval: signalingInterval
  87. );
  88. }
  89. }
  90. throw new InvalidOperationException();
  91. }
  92. }
  93. public Vector2Int StreamSize
  94. {
  95. get { return streamSize; }
  96. set { streamSize = value; }
  97. }
  98. public VideoCodecInfo ReceiverVideoCodec
  99. {
  100. get { return receiverVideoCodec; }
  101. set { receiverVideoCodec = value; }
  102. }
  103. public VideoCodecInfo SenderVideoCodec
  104. {
  105. get { return senderVideoCodec; }
  106. set { senderVideoCodec = value; }
  107. }
  108. }
  109. internal class SceneSelectUI : MonoBehaviour
  110. {
  111. [SerializeField] private Toggle toggleUseDefaultSettings;
  112. [SerializeField] private Dropdown dropdownSignalingType;
  113. [SerializeField] private InputField inputFieldSignalingAddress;
  114. [SerializeField] private Toggle toggleSignalingSecured;
  115. [SerializeField] private InputField inputFieldSignalingInterval;
  116. [SerializeField] private Dropdown streamSizeSelector;
  117. [SerializeField] private InputField textureWidthInput;
  118. [SerializeField] private InputField textureHeightInput;
  119. [SerializeField] private Dropdown receiverVideoCodecSelector;
  120. [SerializeField] private Dropdown senderVideoCodecSelector;
  121. [SerializeField] private Button buttonBidirectional;
  122. [SerializeField] private Button buttonBroadcast;
  123. [SerializeField] private Button buttonGyro;
  124. [SerializeField] private Button buttonRenderPipeline;
  125. [SerializeField] private Button buttonReceiver;
  126. [SerializeField] private Button buttonWebBrowserInput;
  127. [SerializeField] private Button buttonAR;
  128. [SerializeField] private Button buttonMultiplay;
  129. [SerializeField]
  130. private List<Vector2Int> streamSizeList = new List<Vector2Int>
  131. {
  132. new Vector2Int(640, 360),
  133. new Vector2Int(1280, 720),
  134. new Vector2Int(1920, 1080),
  135. new Vector2Int(2560, 1440),
  136. new Vector2Int(3840, 2160),
  137. new Vector2Int(360, 640),
  138. new Vector2Int(720, 1280),
  139. new Vector2Int(1080, 1920),
  140. new Vector2Int(1440, 2560),
  141. new Vector2Int(2160, 3840),
  142. };
  143. private RenderStreamingSettings settings;
  144. static string CodecTitle(VideoCodecInfo codec)
  145. {
  146. switch (codec)
  147. {
  148. case H264CodecInfo h264Codec:
  149. return $"{h264Codec.mimeType} {h264Codec.profile} {h264Codec.level.ToString().Insert(1, ".")} {h264Codec.codecImplementation}";
  150. case VP9CodecInfo V9Codec:
  151. return $"{V9Codec.mimeType} {V9Codec.profile} {V9Codec.codecImplementation}";
  152. case AV1CodecInfo av1Codec:
  153. return $"{av1Codec.mimeType} {av1Codec.profile} {av1Codec.codecImplementation}";
  154. default:
  155. return $"{codec.mimeType} {codec.codecImplementation}";
  156. }
  157. throw new ArgumentException();
  158. }
  159. void Start()
  160. {
  161. SampleManager.Instance.Initialize();
  162. settings = SampleManager.Instance.Settings;
  163. toggleUseDefaultSettings.isOn = settings.UseDefaultSettings;
  164. dropdownSignalingType.value = (int)settings.SignalingType;
  165. inputFieldSignalingAddress.text = settings.SignalingAddress;
  166. toggleSignalingSecured.isOn = settings.SignalingSecured;
  167. inputFieldSignalingInterval.text =
  168. settings.SignalingInterval.ToString(CultureInfo.InvariantCulture);
  169. toggleUseDefaultSettings.onValueChanged.AddListener(OnChangeUseDefaultSettings);
  170. dropdownSignalingType.onValueChanged.AddListener(OnChangeSignalingType);
  171. inputFieldSignalingAddress.onValueChanged.AddListener(OnChangeSignalingAddress);
  172. toggleSignalingSecured.onValueChanged.AddListener(OnChangeSignalingSecured);
  173. inputFieldSignalingInterval.onValueChanged.AddListener(OnChangeSignalingInterval);
  174. SetInteractableSignalingUI(!settings.UseDefaultSettings);
  175. var optionList = streamSizeList.Select(size => new Dropdown.OptionData($" {size.x} x {size.y} ")).ToList();
  176. optionList.Add(new Dropdown.OptionData(" Custom "));
  177. streamSizeSelector.options = optionList;
  178. var existInList = streamSizeList.Contains(settings.StreamSize);
  179. if (existInList)
  180. {
  181. streamSizeSelector.value = streamSizeList.IndexOf(settings.StreamSize);
  182. }
  183. else
  184. {
  185. streamSizeSelector.value = optionList.Count - 1;
  186. textureWidthInput.text = settings.StreamSize.x.ToString();
  187. textureHeightInput.text = settings.StreamSize.y.ToString();
  188. textureWidthInput.interactable = true;
  189. textureHeightInput.interactable = true;
  190. }
  191. streamSizeSelector.onValueChanged.AddListener(OnChangeStreamSizeSelect);
  192. textureWidthInput.onValueChanged.AddListener(OnChangeTextureWidthInput);
  193. textureHeightInput.onValueChanged.AddListener(OnChangeTextureHeightInput);
  194. var receiverVideoCodecList = VideoStreamReceiver.GetAvailableCodecs()
  195. .Select(codec => new Dropdown.OptionData(CodecTitle(codec))).ToList();
  196. receiverVideoCodecSelector.options.AddRange(receiverVideoCodecList);
  197. var senderVideoCodecList = VideoStreamSender.GetAvailableCodecs()
  198. .Select(codec => new Dropdown.OptionData(CodecTitle(codec))).ToList();
  199. senderVideoCodecSelector.options.AddRange(senderVideoCodecList);
  200. receiverVideoCodecSelector.value = Array.FindIndex(VideoStreamReceiver.GetAvailableCodecs().ToArray(), codec => codec.Equals(settings.ReceiverVideoCodec)) + 1;
  201. senderVideoCodecSelector.value = Array.FindIndex(VideoStreamSender.GetAvailableCodecs().ToArray(), codec => codec.Equals(settings.SenderVideoCodec)) + 1;
  202. receiverVideoCodecSelector.onValueChanged.AddListener(OnChangeReceiverVideoCodecSelect);
  203. senderVideoCodecSelector.onValueChanged.AddListener(OnChangeSenderVideoCodecSelect);
  204. buttonBidirectional.onClick.AddListener(OnPressedBidirectional);
  205. buttonBroadcast.onClick.AddListener(OnPressedBroadcast);
  206. buttonGyro.onClick.AddListener(OnPressedGyro);
  207. buttonRenderPipeline.onClick.AddListener(OnPressedRenderPipeline);
  208. buttonReceiver.onClick.AddListener(OnPressedReceiver);
  209. buttonWebBrowserInput.onClick.AddListener(OnPressedWebBrowserInput);
  210. buttonAR.onClick.AddListener(OnPressedAR);
  211. buttonMultiplay.onClick.AddListener(OnPressedMultiplay);
  212. #if UNITY_EDITOR
  213. buttonGyro.interactable = false;
  214. #else
  215. // Gyro input is not supported on this device.
  216. if (Gyroscope.current == null)
  217. {
  218. buttonGyro.interactable = false;
  219. }
  220. #endif
  221. #if !URS_USE_URP_RUNTIME && !URS_USE_HDRP_RUNTIME
  222. buttonRenderPipeline.interactable = false;
  223. #endif
  224. #if URS_USE_AR_FOUNDATION
  225. StartCoroutine(CheckARAvailability(available => { buttonAR.interactable = available; }));
  226. #else
  227. buttonAR.interactable = false;
  228. #endif
  229. }
  230. #if URS_USE_AR_FOUNDATION
  231. IEnumerator CheckARAvailability(Action<bool> callback)
  232. {
  233. if ((ARSession.state == ARSessionState.None) ||
  234. (ARSession.state == ARSessionState.CheckingAvailability))
  235. {
  236. yield return ARSession.CheckAvailability();
  237. }
  238. callback?.Invoke(ARSession.state == ARSessionState.Ready);
  239. }
  240. #endif
  241. private void OnChangeSignalingType(int value)
  242. {
  243. settings.SignalingType =
  244. (SignalingType)Enum.GetValues(typeof(SignalingType)).GetValue(value);
  245. }
  246. private void OnChangeSignalingAddress(string value)
  247. {
  248. settings.SignalingAddress = value;
  249. }
  250. private void OnChangeSignalingSecured(bool value)
  251. {
  252. settings.SignalingSecured = value;
  253. }
  254. private void OnChangeUseDefaultSettings(bool value)
  255. {
  256. settings.UseDefaultSettings = value;
  257. SetInteractableSignalingUI(!value);
  258. }
  259. private void SetInteractableSignalingUI(bool interactable)
  260. {
  261. dropdownSignalingType.interactable = interactable;
  262. inputFieldSignalingAddress.interactable = interactable;
  263. toggleSignalingSecured.interactable = interactable;
  264. inputFieldSignalingInterval.interactable = interactable;
  265. }
  266. private void OnChangeSignalingInterval(string value)
  267. {
  268. if (int.TryParse(value, out int _value))
  269. {
  270. settings.SignalingInterval = _value;
  271. }
  272. else
  273. {
  274. settings.SignalingInterval = 5000;
  275. }
  276. }
  277. private void OnChangeStreamSizeSelect(int index)
  278. {
  279. var isCustom = index >= streamSizeList.Count;
  280. textureWidthInput.interactable = isCustom;
  281. textureHeightInput.interactable = isCustom;
  282. if (isCustom)
  283. {
  284. return;
  285. }
  286. settings.StreamSize = streamSizeList[index];
  287. }
  288. private void OnChangeTextureWidthInput(string input)
  289. {
  290. var height = settings.StreamSize.y;
  291. if (string.IsNullOrEmpty(input))
  292. {
  293. settings.StreamSize = new Vector2Int(RenderStreamingSettings.DefaultStreamWidth, height);
  294. return;
  295. }
  296. if (int.TryParse(input, out var width))
  297. {
  298. settings.StreamSize = new Vector2Int(width, height);
  299. }
  300. }
  301. private void OnChangeTextureHeightInput(string input)
  302. {
  303. var width = settings.StreamSize.x;
  304. if (string.IsNullOrEmpty(input))
  305. {
  306. settings.StreamSize = new Vector2Int(width, RenderStreamingSettings.DefaultStreamHeight);
  307. return;
  308. }
  309. if (int.TryParse(input, out var height))
  310. {
  311. settings.StreamSize = new Vector2Int(width, height);
  312. }
  313. }
  314. private void OnChangeSenderVideoCodecSelect(int index)
  315. {
  316. if (index == 0)
  317. settings.SenderVideoCodec = null;
  318. else
  319. settings.SenderVideoCodec = VideoStreamSender.GetAvailableCodecs().ElementAt(index - 1);
  320. }
  321. private void OnChangeReceiverVideoCodecSelect(int index)
  322. {
  323. if (index == 0)
  324. settings.ReceiverVideoCodec = null;
  325. else
  326. settings.ReceiverVideoCodec = VideoStreamReceiver.GetAvailableCodecs().ElementAt(index - 1);
  327. }
  328. private void OnPressedBidirectional()
  329. {
  330. SceneManager.LoadScene("Bidirectional", LoadSceneMode.Single);
  331. }
  332. private void OnPressedBroadcast()
  333. {
  334. SceneManager.LoadScene("Broadcast", LoadSceneMode.Single);
  335. }
  336. private void OnPressedGyro()
  337. {
  338. SceneManager.LoadScene("Gyro", LoadSceneMode.Single);
  339. }
  340. private void OnPressedRenderPipeline()
  341. {
  342. #if URS_USE_URP_RUNTIME
  343. SceneManager.LoadScene("URP", LoadSceneMode.Single);
  344. #elif URS_USE_HDRP_RUNTIME
  345. SceneManager.LoadScene("HDRP", LoadSceneMode.Single);
  346. #else
  347. throw new InvalidOperationException("HDRP or URP package is not found in this project.");
  348. #endif
  349. }
  350. private void OnPressedReceiver()
  351. {
  352. SceneManager.LoadScene("Receiver", LoadSceneMode.Single);
  353. }
  354. private void OnPressedWebBrowserInput()
  355. {
  356. SceneManager.LoadScene("WebBrowserInput", LoadSceneMode.Single);
  357. }
  358. private void OnPressedAR()
  359. {
  360. SceneManager.LoadScene("ARFoundation", LoadSceneMode.Single);
  361. }
  362. private void OnPressedMultiplay()
  363. {
  364. SceneManager.LoadScene("Multiplay", LoadSceneMode.Single);
  365. }
  366. }
  367. }