RTCManager.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. using Agora.Rtc;
  2. using Agora.Util;
  3. using SC.XR.Unity;
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using UnityEngine;
  7. using UnityEngine.Rendering;
  8. using UnityEngine.UI;
  9. public class RTCManager : SingletonMono<RTCManager>
  10. {
  11. public Camera ca;
  12. public RawImage img;
  13. Texture2D screenShot;
  14. byte[] bts;
  15. /// <summary>
  16. /// 自身UID
  17. /// </summary>
  18. public uint uid;
  19. /// <summary>
  20. /// 当前频道号
  21. /// </summary>
  22. public string channelName;
  23. [SerializeField]
  24. private string _appID = "";
  25. [SerializeField]
  26. private string _token = "";
  27. internal IRtcEngine RtcEngine = null;
  28. public delegate void OnInitDelegate();
  29. public delegate void OnJoinChannelDelegate();
  30. public delegate void OnLeaveChannelDelegate();
  31. public delegate void OnShowViewRawImageDelegate(string uid, RawImage rawImage);
  32. public delegate void OnShowViewMeshRendererDelegate(string uid, MeshRenderer mesh);
  33. public delegate void OnShowOneViewRawImageDelegate(RawImage rawImage);
  34. public delegate void OnMuteLocalAudioStreamDelegate(bool isAudio);
  35. public delegate void OnMuteLocalVideoStreamDelegate(bool isVideo);
  36. public delegate void OnMuteRemoteAudioStreamDelegate(string uid, bool isAudio);
  37. public delegate void OnMuteRemoteVideoStreamDelegate(string uid, bool isVideo);
  38. public delegate void OnRemoteAudioStateChangedDelegate(string uid,REMOTE_AUDIO_STATE_RTC state, REMOTE_AUIDO_STATE_REASON_RTC reason);
  39. public delegate void OnRemoteVideoStateChangedDelegate(string uid,REMOTE_VIDEO_STATE_RTC state, REMOTE_VIDEO_STATE_REASON_RTC reason);
  40. public delegate void OnUserJoinedDelegate(string uid);
  41. public delegate void OnUserOfflineDelegate(string uid);
  42. public delegate void OnSetUidDelegate(string uid);
  43. public delegate void OnSetChannelNameDelegate(string channelName);
  44. public delegate void OnAddPeeridUidDelegate(string peerid, string uid);
  45. public delegate void OnRemAtPeeridUidDelegate(string peerid);
  46. public OnInitDelegate OnInit;
  47. public OnJoinChannelDelegate OnJoinChannel;
  48. public OnLeaveChannelDelegate OnLeaveChannel;
  49. public OnShowViewRawImageDelegate OnShowViewRawImage;
  50. public OnShowViewMeshRendererDelegate OnShowViewMeshRenderer;
  51. public OnShowOneViewRawImageDelegate OnShowOneViewRawImage;
  52. public OnMuteLocalAudioStreamDelegate OnMuteLocalAudioStream;
  53. public OnMuteLocalVideoStreamDelegate OnMuteLocalVideoStream;
  54. public OnMuteRemoteAudioStreamDelegate OnMuteRemoteAudioStream;
  55. public OnMuteRemoteVideoStreamDelegate OnMuteRemoteVideoStream;
  56. public OnRemoteAudioStateChangedDelegate OnRemoteAudioStateChanged;
  57. public OnRemoteVideoStateChangedDelegate OnRemoteVideoStateChanged;
  58. public OnUserJoinedDelegate OnUserJoined;
  59. public OnUserOfflineDelegate OnUserOffline;
  60. public OnSetUidDelegate OnSetUid;
  61. public OnSetChannelNameDelegate OnSetChannelName;
  62. public OnAddPeeridUidDelegate OnAddPeeridUid;
  63. public OnRemAtPeeridUidDelegate OnRemAtPeeridUid;
  64. private void Update()
  65. {
  66. PermissionHelper.RequestMicrophontPermission();
  67. PermissionHelper.RequestCameraPermission();
  68. }
  69. /// <summary>
  70. /// 初始化
  71. /// </summary>
  72. public void Init()
  73. {
  74. // OnInit();
  75. InitEngine();
  76. }
  77. private void InitEngine()
  78. {
  79. _appID = "59a3e20fd9674f53a3422ff48b16db75";
  80. RtcEngine = Agora.Rtc.RtcEngine.CreateAgoraRtcEngine();
  81. RTCManagerHandler handler = new RTCManagerHandler(this);
  82. RtcEngineContext context = new RtcEngineContext(_appID, 0,
  83. CHANNEL_PROFILE_TYPE.CHANNEL_PROFILE_COMMUNICATION,
  84. AUDIO_SCENARIO_TYPE.AUDIO_SCENARIO_DEFAULT);
  85. // RtcEngine.SetCameraDeviceOrientation(VIDEO_SOURCE_TYPE.VIDEO_SOURCE_CAMERA, VIDEO_ORIENTATION.VIDEO_ORIENTATION_90);
  86. RtcEngine.Initialize(context);
  87. RtcEngine.InitEventHandler(handler);
  88. }
  89. public void SetUid(string uid)
  90. {
  91. // OnSetUid(uid);
  92. // UID = uid;
  93. this.uid = StringToUint(uid);
  94. }
  95. public void SetChannelName(string channelName)
  96. {
  97. // OnSetChannelName(channelName);
  98. this.channelName = channelName;
  99. }
  100. /// <summary>
  101. /// 进入房间
  102. /// </summary>
  103. public void JoinChannel()
  104. {
  105. // OnJoinChannel();
  106. RtcEngine.EnableAudio();
  107. RtcEngine.EnableVideo();
  108. // RtcEngine.DisableAudio();
  109. // RtcEngine.DisableVideo();
  110. VideoEncoderConfiguration config = new VideoEncoderConfiguration();
  111. config.dimensions = new VideoDimensions(1280, 720);
  112. config.frameRate = 15;
  113. config.bitrate = 0;
  114. // config.orientationMode = ORIENTATION_MODE.ORIENTATION_MODE_ADAPTIVE;
  115. RtcEngine.SetVideoEncoderConfiguration(config);
  116. RtcEngine.SetChannelProfile(CHANNEL_PROFILE_TYPE.CHANNEL_PROFILE_COMMUNICATION);
  117. RtcEngine.SetClientRole(CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER);
  118. // _channelName = roomid;
  119. RtcEngine.SetExternalVideoSource(true, true, EXTERNAL_VIDEO_SOURCE_TYPE.VIDEO_FRAME, new SenderOptions());
  120. if (DeviceType.type == "DreamGlass")
  121. RtcEngine.SetAudioProfile(0, AUDIO_SCENARIO_TYPE.AUDIO_SCENARIO_GAME_STREAMING);
  122. // RtcEngine.SetLocalVideoMirrorMode(VIDEO_MIRROR_MODE_TYPE.VIDEO_MIRROR_MODE_ENABLED);
  123. RtcEngine.JoinChannel(_token, channelName, "", uid);
  124. Debug.Log("uid " + uid);
  125. //RtcEngine.MuteLocalVideoStream(false);
  126. //RtcEngine.MuteLocalAudioStream(false);
  127. //RtcEngine.MuteAllRemoteAudioStreams(true);
  128. //RtcEngine.MuteAllRemoteVideoStreams(true);
  129. //isRoom = true;
  130. //MuteLocalAudioStream(CustomInfo.isSendAudio);
  131. //MuteLocalVideoStream(CustomInfo.isSendVideo);
  132. // isSendVideo = CustomInfo.isSendVideo;
  133. StartCoroutine(RenderTexturesScreenCapture());
  134. }
  135. IEnumerator RenderTexturesScreenCapture()
  136. {
  137. Debug.Log("RenderTexturesScreenCapture发送图片1");
  138. yield return new WaitForEndOfFrame();
  139. if (screenShot == null)
  140. {
  141. screenShot = new Texture2D(1280, 720, TextureFormat.RGBA32, false);
  142. StartCoroutine(GetRenederFPS());
  143. }
  144. while (true)
  145. {
  146. // if (isSendVideo)
  147. // continue;
  148. // img.texture = RemoteRtc.Instance.cam.activeTexture;
  149. // RenderTexture.active = ca.activeTexture;
  150. // screenShot.ReadPixels(new Rect(0, 0, ca.activeTexture.width, ca.activeTexture.height), 0, 0);
  151. // screenShot.Apply();
  152. //Camera.main.targetTexture = null;
  153. // RenderTexture.active = null;
  154. yield return new WaitForSeconds(0.05f);
  155. if (bts != null)
  156. {
  157. // screenShot = HorizontalFlipTexture(screenShot2);
  158. var timetick = System.DateTime.Now.Ticks / 10000;
  159. ExternalVideoFrame externalVideoFrame = new ExternalVideoFrame();
  160. externalVideoFrame.type = VIDEO_BUFFER_TYPE.VIDEO_BUFFER_RAW_DATA;
  161. externalVideoFrame.format = VIDEO_PIXEL_FORMAT.VIDEO_PIXEL_RGBA;
  162. externalVideoFrame.buffer = bts;// screenShot.GetRawTextureData();
  163. externalVideoFrame.stride = (int)screenShot.width;
  164. externalVideoFrame.height = (int)screenShot.height;
  165. externalVideoFrame.rotation = 180;
  166. externalVideoFrame.cropLeft = 1;
  167. externalVideoFrame.cropRight = 1;
  168. externalVideoFrame.timestamp = timetick;
  169. RtcEngine.PushVideoFrame(externalVideoFrame);
  170. }
  171. }
  172. }
  173. IEnumerator GetRenederFPS()
  174. {
  175. while (true)
  176. {
  177. var req = AsyncGPUReadback.Request(RemoteRtc.Instance.cam2.activeTexture);
  178. yield return new WaitUntil(() => req.done);
  179. if (!req.hasError)
  180. {
  181. if (bts == null)
  182. {
  183. bts = new byte[req.layerDataSize];
  184. }
  185. req.GetData<byte>().CopyTo(bts);
  186. // screenShot.LoadRawTextureData(bts);
  187. // screenShot.Apply();
  188. // tex.SetPixels32(req.GetData<Color32>().ToArray());
  189. // img.texture = screenShot;
  190. }
  191. else
  192. {
  193. Debug.LogError("Error AsyncGPUReadbackRequest.hasError");
  194. }
  195. }
  196. }
  197. /// <summary>
  198. /// 退出房间
  199. /// </summary>
  200. public void LeaveChannel()
  201. {
  202. //OnLeaveChannel();
  203. int msg = RtcEngine.LeaveChannel();
  204. switch (msg)
  205. {
  206. case 0:
  207. Debug.Log( "成功退出频道: " + channelName);
  208. break;
  209. default:
  210. Debug.Log("退出频道失败: " + msg);
  211. break;
  212. }
  213. }
  214. /// <summary>
  215. /// 显示用户画面
  216. /// </summary>
  217. /// <param name="uid"> 用户的UID</param>
  218. /// <param name="rawImage"> 需要显示的RawImage</param>
  219. public void ShowViewRawImage( string peerId, RawImage rawImage)
  220. {
  221. //OnShowViewRawImage(uid, rawImage);
  222. MakeVideoView(StringToUint(peerId), rawImage, this.channelName);
  223. }
  224. /// <summary>
  225. /// 显示用户画面
  226. /// </summary>
  227. /// <param name="uid"> 用户的UID</param>
  228. /// <param name="mesh"> 需要显示的Mesh</param>
  229. public void ShowViewMeshRenderer(string uid, MeshRenderer mesh)
  230. {
  231. OnShowViewMeshRenderer(uid, mesh);
  232. }
  233. /// <summary>
  234. /// 开关自身音频
  235. /// </summary>
  236. /// <param name="isAudio"></param>
  237. public void MuteLocalAudioStream(bool isAudio)
  238. {
  239. //OnMuteLocalAudioStream(isAudio);
  240. int msg = RtcEngine.MuteLocalAudioStream(!isAudio);
  241. // int msg = RtcEngine.EnableLocalAudio(isAudio);
  242. switch (msg)
  243. {
  244. case 0:
  245. Debug.Log(isAudio ? "打开本地音频成功" : "关闭本地音频成功 ");
  246. break;
  247. default:
  248. Debug.LogError("开关本地音频失败: " + msg);
  249. break;
  250. }
  251. }
  252. /// <summary>
  253. /// 开关自身视频
  254. /// </summary>
  255. /// <param name="isVideo"></param>
  256. public void MuteLocalVideoStream(bool isVideo)
  257. {
  258. // OnMuteLocalVideoStream(isVideo);
  259. int msg = RtcEngine.MuteLocalVideoStream(!isVideo);
  260. switch (msg)
  261. {
  262. case 0:
  263. Debug.Log(isVideo ? "打开本地视频成功 " : "关闭本地视频成功 ");
  264. break;
  265. default:
  266. Debug.LogError("开关本地视频失败: " + msg);
  267. break;
  268. }
  269. }
  270. /// <summary>
  271. /// 订阅/取订 用户音频
  272. /// </summary>
  273. /// <param name="uid"></param>
  274. /// <param name="isAudio"></param>
  275. public void MuteRemoteAudioStream(string peerid, bool isAudio)
  276. {
  277. // OnMuteRemoteAudioStream(uid, isAudio);
  278. //
  279. int msg = RtcEngine.MuteRemoteAudioStream(StringToUint(peerid), !isAudio);
  280. switch (msg)
  281. {
  282. case 0:
  283. Debug.Log(isAudio ? "订阅远端音频成功" : "取订远端音频成功 ");
  284. break;
  285. default:
  286. Debug.LogError("远端音频失败: " + msg);
  287. break;
  288. }
  289. }
  290. /// <summary>
  291. /// 订阅/取订 用户视频
  292. /// </summary>
  293. /// <param name="uid"></param>
  294. /// <param name="isVideo"></param>
  295. public void MuteRemoteVideoStream(string peerid, bool isVideo)
  296. {
  297. // OnMuteRemoteVideoStream(uid, isVideo);
  298. int msg = RtcEngine.MuteRemoteVideoStream(StringToUint(peerid), !isVideo);
  299. switch (msg)
  300. {
  301. case 0:
  302. Debug.Log(isVideo ? "订阅远端视频成功" : "取订远端视频成功 ");
  303. break;
  304. default:
  305. Debug.LogError("远端视频失败: " + msg);
  306. break;
  307. }
  308. }
  309. /// <summary>
  310. /// 用户音频状态发生变化的回调
  311. /// </summary>
  312. /// <param name="uid"></param>
  313. /// <param name="state"> 音频状态 </param>
  314. public void RemoteAudioStateChanged(string uid ,REMOTE_AUDIO_STATE state, REMOTE_AUDIO_STATE_REASON reason)
  315. {
  316. OnRemoteAudioStateChanged(uid, (REMOTE_AUDIO_STATE_RTC)state, (REMOTE_AUIDO_STATE_REASON_RTC)reason);
  317. }
  318. /// <summary>
  319. /// 用户视频状态发生变化的回调
  320. /// </summary>
  321. /// <param name="uid"></param>
  322. /// <param name="state"> 视频状态 </param>
  323. public void RemoteVideoStateChanged(string uid ,REMOTE_VIDEO_STATE state , REMOTE_VIDEO_STATE_REASON reason)
  324. {
  325. OnRemoteVideoStateChanged(uid, (REMOTE_VIDEO_STATE_RTC)state, (REMOTE_VIDEO_STATE_REASON_RTC)reason);
  326. }
  327. /// <summary>
  328. /// 有用户进入频道的回调
  329. /// </summary>
  330. /// <param name="uid"></param>
  331. public void UserJoined(string uid)
  332. {
  333. OnUserJoined(uid);
  334. }
  335. /// <summary>
  336. /// 有用户退出频道的回调
  337. /// </summary>
  338. /// <param name="uid"></param>
  339. public void UserOffline(string uid)
  340. {
  341. OnUserOffline(uid);
  342. }
  343. private uint StringToUint(string value)
  344. {
  345. //byte[] bytes = Encoding.ASCII.GetBytes(value);
  346. return (uint)int.Parse(value);
  347. // return BitConverter.ToUInt32(bytes);
  348. }
  349. internal static void MakeVideoView(uint uid, RawImage rawImage, string channelId = "")
  350. {
  351. Debug.Log("MakeVideoView " + uid);
  352. //var go = GameObject.Find(uid.ToString());
  353. //if (!ReferenceEquals(go, null))
  354. //{
  355. // return; // reuse
  356. //}
  357. // create a GameObject and assign to this new user
  358. var videoSurface = MakeImageSurface(rawImage);
  359. // var videoSurface = MakePlaneSurface(uid.ToString());
  360. if (ReferenceEquals(videoSurface, null)) return;
  361. // configure videoSurface
  362. if (uid == 0)
  363. {
  364. // videoSurface.SetForUser(uid, channelId);
  365. }
  366. else
  367. {
  368. videoSurface.SetForUser(uid, channelId, VIDEO_SOURCE_TYPE.VIDEO_SOURCE_REMOTE);
  369. }
  370. //videoSurface.OnTextureSizeModify += (int width, int height) =>
  371. //{
  372. // float scale = (float)height / (float)width;
  373. // videoSurface.transform.localScale = new Vector3(-5, 5 * scale, 1);
  374. // Debug.Log("OnTextureSizeModify: " + width + " " + height);
  375. //};
  376. videoSurface.SetEnable(true);
  377. // AgoraVideoAudioManager.Instance.EnableLocalVideo(false);
  378. }
  379. private static VideoSurface MakeImageSurface(RawImage rawImage)
  380. {
  381. // make the object draggable
  382. if (rawImage.gameObject.GetComponent<UIElementDrag>() != null)
  383. Destroy(rawImage.gameObject.GetComponent<UIElementDrag>());
  384. rawImage.gameObject.AddComponent<UIElementDrag>();
  385. // configure videoSurface
  386. if (rawImage.gameObject.GetComponent<VideoSurface>() != null)
  387. Destroy(rawImage.gameObject.GetComponent<VideoSurface>());
  388. var videoSurface = rawImage.gameObject.AddComponent<VideoSurface>();
  389. return videoSurface;
  390. }
  391. internal static void OnUserJoined_Agora(uint uid)
  392. {
  393. // _videoSample.Log.UpdateLog(string.Format("OnUserJoined uid: ${0} elapsed: ${1}", uid, elapsed));
  394. // Debug.Log(string.Format("OnUserJoined uid: ${0} elapsed: ${1}", uid, elapsed))
  395. RTCManager.Instance.UserJoined(uid.ToString());
  396. }
  397. internal static void OnRemoteVideoStateChanged_Agora(uint uid, REMOTE_VIDEO_STATE state, REMOTE_VIDEO_STATE_REASON
  398. reason)
  399. {
  400. RTCManager.Instance.RemoteVideoStateChanged(uid.ToString(), state, reason);
  401. }
  402. internal static void OnRemoteAudioStateChanged_Agora(uint uid, REMOTE_AUDIO_STATE state, REMOTE_AUDIO_STATE_REASON reason)
  403. {
  404. RTCManager.Instance.RemoteAudioStateChanged(uid.ToString(), state, reason);
  405. }
  406. }
  407. public class RTCManagerHandler : IRtcEngineEventHandler
  408. {
  409. private readonly RTCManager _videoSample;
  410. internal RTCManagerHandler(RTCManager videoSample)
  411. {
  412. _videoSample = videoSample;
  413. }
  414. public override void OnError(int err, string msg)
  415. {
  416. }
  417. public override void OnJoinChannelSuccess(RtcConnection connection, int elapsed)
  418. {
  419. int build = 0;
  420. Debug.Log("Agora: OnJoinChannelSuccess ");
  421. //// _videoSample.Log.UpdateLog(string.Format("sdk version: ${0}",
  422. // // _videoSample.RtcEngine.GetVersion(ref build)));
  423. // //_videoSample.Log.UpdateLog(string.Format("sdk build: ${0}",
  424. // // build));
  425. // //_videoSample.Log.UpdateLog(
  426. // string.Format("OnJoinChannelSuccess channelName: {0}, uid: {1}, elapsed: {2}",
  427. // connection.channelId, connection.localUid, elapsed));
  428. // // _videoSample.ClickSelf();
  429. // // AgoraVideoAudioManager.MakeVideoView(0);
  430. }
  431. public override void OnLeaveChannel(RtcConnection connection, RtcStats stats)
  432. {
  433. // _videoSample.Log.UpdateLog("OnLeaveChannel");
  434. //RTCManager.DestroyVideoView(0);
  435. }
  436. public override void OnClientRoleChanged(RtcConnection connection, CLIENT_ROLE_TYPE oldRole, CLIENT_ROLE_TYPE newRole)
  437. {
  438. //_videoSample.Log.UpdateLog("OnClientRoleChanged");
  439. }
  440. public override void OnUserJoined(RtcConnection connection, uint uid, int elapsed)
  441. {
  442. Debug.Log(string.Format("OnUserJoined uid: ${0} elapsed: ${1}", uid, elapsed));
  443. // _videoSample.Log.UpdateLog(string.Format("OnUserJoined uid: ${0} elapsed: ${1}", uid, elapsed));
  444. RTCManager.OnUserJoined_Agora(uid);
  445. // AgoraVideoAudioManager.MakeVideoView(uid, _videoSample.GetChannelName());
  446. }
  447. public override void OnUserOffline(RtcConnection connection, uint uid, USER_OFFLINE_REASON_TYPE reason)
  448. {
  449. // _videoSample.Log.UpdateLog(string.Format("OnUserOffLine uid: ${0}, reason: ${1}", uid,
  450. // (int)reason));
  451. // AgoraVideoAudioManager.DestroyVideoView(uid);
  452. }
  453. public override void OnRemoteVideoStateChanged(RtcConnection connection, uint remoteUid, REMOTE_VIDEO_STATE state, REMOTE_VIDEO_STATE_REASON reason, int elapsed)
  454. {
  455. RTCManager.OnRemoteVideoStateChanged_Agora(remoteUid, state, reason);
  456. }
  457. public override void OnRemoteAudioStateChanged(RtcConnection connection, uint remoteUid, REMOTE_AUDIO_STATE state, REMOTE_AUDIO_STATE_REASON reason, int elapsed)
  458. {
  459. RTCManager.OnRemoteAudioStateChanged_Agora(remoteUid, state, reason);
  460. }
  461. }