RTCManager.cs 18 KB

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