StreamingComponentTest.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. using System;
  2. using System.Linq;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using NUnit.Framework;
  6. using Unity.Collections;
  7. using UnityEngine;
  8. using Unity.WebRTC;
  9. using UnityEngine.TestTools;
  10. using UnityEngine.InputSystem;
  11. using UnityEngine.InputSystem.Users;
  12. namespace Unity.RenderStreaming.RuntimeTest
  13. {
  14. class VideoStreamSenderTest
  15. {
  16. [Test]
  17. public void GetAvailableCodec()
  18. {
  19. IEnumerable<VideoCodecInfo> codecs = VideoStreamSender.GetAvailableCodecs();
  20. Assert.That(codecs, Is.Not.Empty);
  21. Assert.That(codecs.Any(codec => codec.name == "VP8"));
  22. Assert.That(codecs.Any(codec => codec.name == "VP9"));
  23. Assert.That(codecs.Any(codec => codec.name == "AV1"));
  24. foreach(var codec in codecs)
  25. {
  26. Assert.That(codec.name, Is.Not.Empty);
  27. Assert.That(codec.mimeType, Is.Not.Empty);
  28. Assert.That(codec.codecImplementation, Is.Not.Empty);
  29. switch (codec)
  30. {
  31. case VP9CodecInfo vp9codec:
  32. Assert.That(vp9codec.name, Is.EqualTo("VP9"));
  33. Assert.That(vp9codec.profile, Is.Not.Zero);
  34. break;
  35. case H264CodecInfo h264codec:
  36. Assert.That(h264codec.name, Is.EqualTo("H264"));
  37. Assert.That(h264codec.level, Is.GreaterThan(0));
  38. Assert.That(h264codec.profile, Is.Not.Zero);
  39. break;
  40. default:
  41. break;
  42. }
  43. }
  44. }
  45. [Test]
  46. public void SelectCodecCapabilities()
  47. {
  48. var codecs = VideoStreamSender.GetAvailableCodecs();
  49. var caps = RTCRtpSender.GetCapabilities(TrackKind.Video).SelectCodecCapabilities(codecs);
  50. Assert.That(codecs.Count(), Is.EqualTo(caps.Count()));
  51. }
  52. [Test]
  53. public void SetEnabled()
  54. {
  55. var go = new GameObject();
  56. var sender = go.AddComponent<VideoStreamSender>();
  57. sender.enabled = false;
  58. sender.enabled = true;
  59. UnityEngine.Object.DestroyImmediate(go);
  60. }
  61. [UnityTest]
  62. public IEnumerator CreateTrack()
  63. {
  64. var go = new GameObject();
  65. var sender = go.AddComponent<VideoStreamSender>();
  66. MediaStreamTrack track = null;
  67. // With camera
  68. sender.source = VideoStreamSource.Camera;
  69. Assert.That(() => sender.CreateTrack(), Throws.Exception.TypeOf<ArgumentNullException>());
  70. var camera = go.AddComponent<Camera>();
  71. sender.sourceCamera = camera;
  72. sender.width = 640;
  73. sender.height = 480;
  74. var op = sender.CreateTrack();
  75. yield return op;
  76. track = op.Track;
  77. Assert.That(track, Is.Not.Null);
  78. var videoTrack = track as VideoStreamTrack;
  79. Assert.That(videoTrack.Texture.width, Is.EqualTo(sender.width));
  80. Assert.That(videoTrack.Texture.height, Is.EqualTo(sender.height));
  81. track.Dispose();
  82. track = null;
  83. // With screen
  84. sender.source = VideoStreamSource.Screen;
  85. op = sender.CreateTrack();
  86. yield return op;
  87. track = op.Track;
  88. Assert.That(track, Is.Not.Null);
  89. track.Dispose();
  90. track = null;
  91. // With Texture
  92. sender.source = VideoStreamSource.Texture;
  93. Assert.That(sender.sourceTexture, Is.Null);
  94. Assert.That(() => sender.CreateTrack(), Throws.Exception.TypeOf<ArgumentNullException>());
  95. var width = 640;
  96. var height = 480;
  97. var format = WebRTC.WebRTC.GetSupportedRenderTextureFormat(SystemInfo.graphicsDeviceType);
  98. var texture = new RenderTexture(width, height, 0, format);
  99. sender.sourceTexture = texture;
  100. Assert.That(sender.sourceTexture, Is.Not.Null);
  101. Assert.That(sender.width, Is.EqualTo(width));
  102. Assert.That(sender.height, Is.EqualTo(height));
  103. Assert.That(() => sender.width = 1280, Throws.Nothing);
  104. Assert.That(() => sender.height = 720, Throws.Nothing);
  105. op = sender.CreateTrack();
  106. yield return op;
  107. track = op.Track;
  108. Assert.That(track, Is.Not.Null);
  109. track.Dispose();
  110. // With WebCam
  111. /// todo:: standalone build is failed by IL2CPP error in Unity 2021.3.
  112. #if !(UNITY_IPHONE || UNITY_ANDROID || (UNITY_2021_3 && ENABLE_IL2CPP))
  113. if (WebCamTexture.devices.Length > 0 && Application.HasUserAuthorization(UserAuthorization.WebCam))
  114. {
  115. sender.source = VideoStreamSource.WebCamera;
  116. Assert.That(sender.sourceDeviceIndex, Is.EqualTo(0));
  117. sender.sourceDeviceIndex = -1;
  118. Assert.That(() => sender.CreateTrack(), Throws.Exception.TypeOf<ArgumentOutOfRangeException>());
  119. sender.sourceDeviceIndex = 0;
  120. op = sender.CreateTrack();
  121. yield return op;
  122. track = op.Track;
  123. Assert.That(track, Is.Not.Null);
  124. Assert.That(sender.sourceWebCamTexture, Is.Not.Null);
  125. track.Dispose();
  126. }
  127. #endif
  128. UnityEngine.Object.DestroyImmediate(go);
  129. }
  130. [Test]
  131. public void IsPlaying()
  132. {
  133. var go = new GameObject();
  134. var sender = go.AddComponent<VideoStreamSender>();
  135. Assert.That(sender.isPlaying, Is.False);
  136. UnityEngine.Object.DestroyImmediate(go);
  137. }
  138. [Test]
  139. public void SetBitrate()
  140. {
  141. var go = new GameObject();
  142. var sender = go.AddComponent<VideoStreamSender>();
  143. uint minBitrate = 1000;
  144. uint maxBitrate = 2000;
  145. sender.SetBitrate(minBitrate, maxBitrate);
  146. Assert.That(sender.minBitrate, Is.EqualTo(minBitrate));
  147. Assert.That(sender.maxBitrate, Is.EqualTo(maxBitrate));
  148. minBitrate = 3000;
  149. Assert.That(() => sender.SetBitrate(minBitrate, maxBitrate), Throws.Exception.TypeOf<ArgumentException>());
  150. UnityEngine.Object.DestroyImmediate(go);
  151. }
  152. [Test]
  153. public void SetFrameRate()
  154. {
  155. var go = new GameObject();
  156. var sender = go.AddComponent<VideoStreamSender>();
  157. float framerate = 24;
  158. sender.SetFrameRate(framerate);
  159. Assert.That(sender.frameRate, Is.EqualTo(framerate));
  160. framerate = 0;
  161. sender.SetFrameRate(framerate);
  162. Assert.That(sender.frameRate, Is.EqualTo(framerate));
  163. framerate = -1;
  164. Assert.That(() => sender.SetFrameRate(framerate), Throws.Exception.TypeOf<ArgumentOutOfRangeException>());
  165. UnityEngine.Object.DestroyImmediate(go);
  166. }
  167. [Test]
  168. public void SetScaleResolutionDown()
  169. {
  170. var go = new GameObject();
  171. var sender = go.AddComponent<VideoStreamSender>();
  172. float scaleFactor = 2;
  173. sender.SetScaleResolutionDown(scaleFactor);
  174. Assert.That(sender.scaleResolutionDown, Is.EqualTo(scaleFactor));
  175. scaleFactor = 1;
  176. sender.SetScaleResolutionDown(scaleFactor);
  177. Assert.That(sender.scaleResolutionDown, Is.EqualTo(scaleFactor));
  178. scaleFactor = -1;
  179. Assert.That(() => sender.SetScaleResolutionDown(scaleFactor), Throws.Exception.TypeOf<ArgumentOutOfRangeException>());
  180. scaleFactor = 0.5f;
  181. Assert.That(() => sender.SetScaleResolutionDown(scaleFactor), Throws.Exception.TypeOf<ArgumentOutOfRangeException>());
  182. UnityEngine.Object.DestroyImmediate(go);
  183. }
  184. [Test]
  185. public void SetCodec()
  186. {
  187. var go = new GameObject();
  188. var sender = go.AddComponent<VideoStreamSender>();
  189. Assert.That(sender.codec, Is.Null);
  190. var codecs = VideoStreamSender.GetAvailableCodecs();
  191. Assert.That(codecs, Is.Not.Empty);
  192. var codec = codecs.First();
  193. sender.SetCodec(codec);
  194. Assert.That(sender.codec, Is.EqualTo(codec));
  195. sender.SetCodec(null);
  196. Assert.That(sender.codec, Is.Null);
  197. }
  198. }
  199. class VideoStreamReceiverTest
  200. {
  201. [Test]
  202. public void GetAvailableCodec()
  203. {
  204. IEnumerable<VideoCodecInfo> codecs = VideoStreamReceiver.GetAvailableCodecs();
  205. Assert.That(codecs, Is.Not.Empty);
  206. Assert.That(codecs.Any(codec => codec.name == "VP8"));
  207. Assert.That(codecs.Any(codec => codec.name == "VP9"));
  208. Assert.That(codecs.Any(codec => codec.name == "AV1"));
  209. foreach (var codec in codecs)
  210. {
  211. Assert.That(codec.name, Is.Not.Empty);
  212. Assert.That(codec.mimeType, Is.Not.Empty);
  213. Assert.That(codec.codecImplementation, Is.Not.Empty);
  214. switch (codec)
  215. {
  216. case VP9CodecInfo vp9codec:
  217. Assert.That(vp9codec.name, Is.EqualTo("VP9"));
  218. Assert.That(vp9codec.profile, Is.Not.Zero);
  219. break;
  220. case H264CodecInfo h264codec:
  221. Assert.That(h264codec.name, Is.EqualTo("H264"));
  222. Assert.That(h264codec.level, Is.GreaterThan(0));
  223. Assert.That(h264codec.profile, Is.Not.Zero);
  224. break;
  225. }
  226. }
  227. }
  228. [Test]
  229. public void SelectCodecCapabilities()
  230. {
  231. var codecs = VideoStreamReceiver.GetAvailableCodecs();
  232. var caps = RTCRtpReceiver.GetCapabilities(TrackKind.Video).SelectCodecCapabilities(codecs);
  233. Assert.That(codecs.Count(), Is.EqualTo(caps.Count()));
  234. }
  235. [Test]
  236. public void SetCodec()
  237. {
  238. var go = new GameObject();
  239. var receiver = go.AddComponent<VideoStreamReceiver>();
  240. Assert.That(receiver.codec, Is.Null);
  241. var codecs = VideoStreamReceiver.GetAvailableCodecs();
  242. Assert.That(codecs, Is.Not.Empty);
  243. var codec = codecs.First();
  244. receiver.SetCodec(codec);
  245. Assert.That(receiver.codec, Is.EqualTo(codec));
  246. receiver.SetCodec(null);
  247. Assert.That(receiver.codec, Is.Null);
  248. }
  249. }
  250. class AudioStreamSenderTest
  251. {
  252. [Test]
  253. public void GetAvailableCodec()
  254. {
  255. IEnumerable<AudioCodecInfo> codecs = AudioStreamSender.GetAvailableCodecs();
  256. Assert.That(codecs, Is.Not.Empty);
  257. foreach(var codec in codecs)
  258. {
  259. Assert.That(codec.name, Is.Not.Empty);
  260. Assert.That(codec.mimeType, Is.Not.Empty);
  261. Assert.That(codec.channelCount, Is.GreaterThan(0));
  262. Assert.That(codec.sampleRate, Is.GreaterThan(0));
  263. }
  264. }
  265. [UnityTest]
  266. public IEnumerator CreateTrack()
  267. {
  268. var go = new GameObject();
  269. var sender = go.AddComponent<AudioStreamSender>();
  270. MediaStreamTrack track;
  271. // With AudioSource
  272. var go2 = new GameObject();
  273. sender = go2.AddComponent<AudioStreamSender>();
  274. sender.source = AudioStreamSource.AudioSource;
  275. Assert.That(() => sender.CreateTrack(), Throws.Exception.TypeOf<InvalidOperationException>());
  276. sender.audioSource = go2.AddComponent<AudioSource>();
  277. var op = sender.CreateTrack();
  278. yield return op;
  279. track = op.Track;
  280. Assert.That(track, Is.Not.Null);
  281. track.Dispose();
  282. // APIOnly
  283. var go3 = new GameObject();
  284. sender = go3.AddComponent<AudioStreamSender>();
  285. sender.source = AudioStreamSource.APIOnly;
  286. op = sender.CreateTrack();
  287. yield return op;
  288. track = op.Track;
  289. Assert.That(track, Is.Not.Null);
  290. track.Dispose();
  291. // With AudioListener
  292. // workaround(kazuki): Fix NullReferenceException in AudioStreamTrack.ProcessAudio.
  293. //sender.source = AudioStreamSource.AudioListener;
  294. //Assert.That(() => sender.CreateTrack(), Throws.Exception.TypeOf<InvalidOperationException>());
  295. //sender.audioListener = go.AddComponent<AudioListener>();
  296. //op = sender.CreateTrack();
  297. //yield return op;
  298. //track = op.Track;
  299. //Assert.That(track, Is.Not.Null);
  300. //track.Dispose();
  301. // With Microphone
  302. #if !(UNITY_IPHONE || UNITY_ANDROID)
  303. if (Microphone.devices.Length > 0 && Application.HasUserAuthorization(UserAuthorization.Microphone))
  304. {
  305. sender.source = AudioStreamSource.Microphone;
  306. op = sender.CreateTrack();
  307. yield return op;
  308. track = op.Track;
  309. Assert.That(track, Is.Not.Null);
  310. track.Dispose();
  311. track = null;
  312. }
  313. #endif
  314. UnityEngine.Object.DestroyImmediate(go);
  315. UnityEngine.Object.DestroyImmediate(go2);
  316. UnityEngine.Object.DestroyImmediate(go3);
  317. }
  318. // workaround(kazuki): Fix NullReferenceException in AudioStreamTrack.ProcessAudio. (WRS-231)
  319. [UnityTest]
  320. [UnityPlatform(exclude = new[] { RuntimePlatform.OSXEditor, RuntimePlatform.OSXPlayer, RuntimePlatform.LinuxEditor, RuntimePlatform.LinuxPlayer })]
  321. public IEnumerator ReplaceTrack()
  322. {
  323. var go = new GameObject();
  324. var sender = go.AddComponent<AudioStreamSender>();
  325. Assert.That(() => sender.ReplaceTrack(null), Throws.Exception.TypeOf<ArgumentNullException>());
  326. // With AudioListener
  327. sender.source = AudioStreamSource.AudioListener;
  328. var audioListener = go.AddComponent<AudioListener>();
  329. sender.audioListener = audioListener;
  330. var op = sender.CreateTrack();
  331. yield return op;
  332. var track = op.Track;
  333. Assert.That(track, Is.Not.Null);
  334. sender.ReplaceTrack(track);
  335. UnityEngine.Object.DestroyImmediate(go);
  336. }
  337. [Test]
  338. public void SelectCodecCapabilities()
  339. {
  340. var codecs = AudioStreamSender.GetAvailableCodecs();
  341. var caps = RTCRtpSender.GetCapabilities(TrackKind.Audio).SelectCodecCapabilities(codecs);
  342. Assert.That(codecs.Count(), Is.EqualTo(caps.Count()));
  343. }
  344. [Test]
  345. public void SetEnabled()
  346. {
  347. var go = new GameObject();
  348. var sender = go.AddComponent<AudioStreamSender>();
  349. sender.enabled = false;
  350. sender.enabled = true;
  351. UnityEngine.Object.DestroyImmediate(go);
  352. }
  353. [Test]
  354. public void IsPlaying()
  355. {
  356. var go = new GameObject();
  357. var sender = go.AddComponent<VideoStreamSender>();
  358. Assert.That(sender.isPlaying, Is.False);
  359. UnityEngine.Object.DestroyImmediate(go);
  360. }
  361. [Test]
  362. public void SetBitrate()
  363. {
  364. var go = new GameObject();
  365. var sender = go.AddComponent<AudioStreamSender>();
  366. uint minBitrate = 1000;
  367. uint maxBitrate = 2000;
  368. sender.SetBitrate(minBitrate, maxBitrate);
  369. Assert.That(sender.minBitrate, Is.EqualTo(minBitrate));
  370. Assert.That(sender.maxBitrate, Is.EqualTo(maxBitrate));
  371. minBitrate = 3000;
  372. Assert.That(() => sender.SetBitrate(minBitrate, maxBitrate), Throws.Exception.TypeOf<ArgumentException>());
  373. UnityEngine.Object.DestroyImmediate(go);
  374. }
  375. [Test]
  376. public void SetCodec()
  377. {
  378. var go = new GameObject();
  379. var sender = go.AddComponent<AudioStreamSender>();
  380. Assert.That(sender.codec, Is.Null);
  381. var codecs = AudioStreamSender.GetAvailableCodecs();
  382. Assert.That(codecs, Is.Not.Empty);
  383. var codec = codecs.First();
  384. sender.SetCodec(codec);
  385. Assert.That(sender.codec, Is.EqualTo(codec));
  386. sender.SetCodec(null);
  387. Assert.That(sender.codec, Is.Null);
  388. }
  389. [Test]
  390. public void SetData()
  391. {
  392. var go = new GameObject();
  393. var sender = go.AddComponent<AudioStreamSender>();
  394. NativeArray<float> nativeArray = new NativeArray<float>(256, Allocator.Temp);
  395. Assert.That(() => sender.SetData(ref nativeArray, 2), Throws.Exception.TypeOf<InvalidOperationException>());
  396. sender.source = AudioStreamSource.APIOnly;
  397. Assert.That(() => sender.SetData(ref nativeArray, 2), Throws.Nothing);
  398. nativeArray.Dispose();
  399. }
  400. }
  401. class AudioStreamReceiverTest
  402. {
  403. [Test]
  404. public void GetAvailableCodec()
  405. {
  406. IEnumerable<AudioCodecInfo> codecs = AudioStreamReceiver.GetAvailableCodecs();
  407. Assert.That(codecs, Is.Not.Empty);
  408. foreach (var codec in codecs)
  409. {
  410. Assert.That(codec.name, Is.Not.Empty);
  411. Assert.That(codec.mimeType, Is.Not.Empty);
  412. Assert.That(codec.channelCount, Is.GreaterThan(0));
  413. Assert.That(codec.sampleRate, Is.GreaterThan(0));
  414. }
  415. }
  416. [Test]
  417. public void SelectCodecCapabilities()
  418. {
  419. var codecs = AudioStreamReceiver.GetAvailableCodecs();
  420. var caps = RTCRtpReceiver.GetCapabilities(TrackKind.Audio).SelectCodecCapabilities(codecs);
  421. Assert.That(codecs.Count(), Is.EqualTo(caps.Count()));
  422. }
  423. [Test]
  424. public void SetCodec()
  425. {
  426. var go = new GameObject();
  427. var receiver = go.AddComponent<AudioStreamReceiver>();
  428. Assert.That(receiver.codec, Is.Null);
  429. var codecs = AudioStreamReceiver.GetAvailableCodecs();
  430. Assert.That(codecs, Is.Not.Empty);
  431. var codec = codecs.First();
  432. receiver.SetCodec(codec);
  433. Assert.That(receiver.codec, Is.EqualTo(codec));
  434. receiver.SetCodec(null);
  435. Assert.That(receiver.codec, Is.Null);
  436. }
  437. }
  438. class InputSenderTest
  439. {
  440. [Test]
  441. public void SetChannel()
  442. {
  443. var go = new GameObject();
  444. var sender = go.AddComponent<InputSender>();
  445. Assert.That(sender.Channel, Is.Null);
  446. Assert.That(() => sender.SetChannel(null), Throws.Exception.TypeOf<NullReferenceException>());
  447. sender.enabled = false;
  448. sender.enabled = true;
  449. sender.SetChannel(null, null);
  450. var connection = new RTCPeerConnection();
  451. var channel = connection.CreateDataChannel("test");
  452. sender.SetChannel(null, channel);
  453. UnityEngine.Object.DestroyImmediate(go);
  454. channel.Dispose();
  455. connection.Dispose();
  456. }
  457. }
  458. class InputReceiverTest
  459. {
  460. [Test]
  461. public void SetChannel()
  462. {
  463. var go = new GameObject();
  464. go.SetActive(false);
  465. var receiver = go.AddComponent<InputReceiver>();
  466. var asset = ScriptableObject.CreateInstance<InputActionAsset>();
  467. var mapName = "test";
  468. asset.AddActionMap(mapName);
  469. receiver.actions = asset;
  470. go.SetActive(true);
  471. Assert.That(receiver.Channel, Is.Null);
  472. Assert.That(() => receiver.SetChannel(null), Throws.Exception.TypeOf<NullReferenceException>());
  473. receiver.enabled = false;
  474. receiver.enabled = true;
  475. Assert.That(receiver.inputIsActive, Is.True);
  476. Assert.That(receiver.user.id, Is.Not.EqualTo(InputUser.InvalidId));
  477. Assert.That(receiver.devices, Is.Empty);
  478. Assert.That(receiver.defaultActionMap, Is.Null);
  479. Assert.That(receiver.currentActionMap, Is.Null);
  480. receiver.currentActionMap = new InputActionMap();
  481. Assert.That(receiver.actionEvents, Is.Not.Null);
  482. receiver.actionEvents = new PlayerInput.ActionEvent[]{};
  483. receiver.SwitchCurrentActionMap(mapName);
  484. var device = UnityEngine.InputSystem.InputSystem.devices.First();
  485. receiver.PerformPairingWithDevice(device);
  486. receiver.PerformPairingWithAllLocalDevices();
  487. receiver.UnpairDevices(device);
  488. receiver.SetChannel(null, null);
  489. UnityEngine.Object.DestroyImmediate(asset);
  490. UnityEngine.Object.DestroyImmediate(go);
  491. }
  492. [Test]
  493. public void InputUserId()
  494. {
  495. var go = new GameObject();
  496. go.SetActive(false);
  497. var receiver = go.AddComponent<InputReceiver>();
  498. // user.id is InputUser.InvalidId in default.
  499. Assert.That(receiver.actions, Is.Null);
  500. Assert.That(receiver.user.id, Is.EqualTo(InputUser.InvalidId));
  501. var asset = ScriptableObject.CreateInstance<InputActionAsset>();
  502. var mapName = "test";
  503. asset.AddActionMap(mapName);
  504. receiver.actions = asset;
  505. // user.id is not InputUser.InvalidId after set actions parameter.
  506. Assert.That(receiver.actions, Is.Not.Null);
  507. Assert.That(receiver.user.id, Is.EqualTo(InputUser.InvalidId));
  508. UnityEngine.Object.DestroyImmediate(go);
  509. }
  510. }
  511. }