RtcMultiPusherV2.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Runtime.InteropServices;
  8. using System.Threading;
  9. using Vinno.FIS.TRTCClient.Common.Enum;
  10. using Vinno.FIS.TRTCClient.Common.Log;
  11. using Vinno.FIS.TRTCClient.Common.Pipe;
  12. using Vinno.vCloud.FIS.CrossPlatform.Common;
  13. using Vinno.vCloud.FIS.CrossPlatform.Common.Enum;
  14. using Vinno.vCloud.FIS.CrossPlatform.Common.Helper;
  15. using Vinno.vCloud.FIS.CrossPlatform.Common.LiveVideo;
  16. using Vinno.vCloud.FIS.CrossPlatform.Common.LiveVideo.Interface;
  17. namespace Vinno.vCloud.FIS.CrossPlatform.Windows.LiveVideo.RTC
  18. {
  19. public class RtcMultiPusherV2 : PusherBase, ILiveVideoPusherV2
  20. {
  21. private readonly ConcurrentDictionary<EnumLiveChannelCategory, TRTCClientV2> _pushers;
  22. private readonly ConcurrentDictionary<EnumLiveChannelCategory, EnumLiveStates> _liveStatus;
  23. public event EventHandler<ChannelStateEventArgsV2> ChannelStateChanged;
  24. public RtcMultiPusherV2()
  25. {
  26. _pushers = new ConcurrentDictionary<EnumLiveChannelCategory, TRTCClientV2>();
  27. _liveStatus = new ConcurrentDictionary<EnumLiveChannelCategory, EnumLiveStates>();
  28. }
  29. public bool StartPusher(IExtendedData pushParams, IEnumerable<CPVideoDeviceOutputInfo> deviceInfos)
  30. {
  31. var rtcParams = pushParams as RtcExtendedData;
  32. if (rtcParams == null || rtcParams.AppId == 0)
  33. {
  34. CrossPlatformHelper.Instance.LogWriter?.WriteLineError("RTC Multi Extended Data Is Null!");
  35. return false;
  36. }
  37. var userInfos = rtcParams.UserInfos;
  38. for (int i = 0; i < userInfos.Count(); i++)
  39. {
  40. var deviceInfo = deviceInfos.FirstOrDefault(c => c.Category == userInfos[i].Category);
  41. if (deviceInfo != null)
  42. {
  43. var device = (CPVideoDeviceOutputInfo)deviceInfo.Clone();
  44. bool isMute = true;
  45. string micId = "";
  46. if (i == 0)
  47. {
  48. isMute = rtcParams.IsMute;
  49. micId = rtcParams.MicDeviceId;
  50. }
  51. var pusher = new TRTCClientV2(device, userInfos[i].Width, userInfos[i].Height, rtcParams.AppId, userInfos[i].UserId, rtcParams.RoomId, userInfos[i].UserSign, userInfos[i].VideoFps, userInfos[i].VideoBitrate, userInfos[i].MinVideoBitrate, isMute, micId);
  52. if (_pushers.TryAdd(userInfos[i].Category, pusher))
  53. {
  54. pusher.ImageFrameReceived += OnImageFrameReceived;
  55. pusher.FirstFrameReceived += OnFirstFrameReceived;
  56. pusher.Start();
  57. if (LiveVideoStatusChecker.Instance.IsRealTimeCapturing && userInfos[i].Category == EnumLiveChannelCategory.Main)//只有RTCMultiPusherV2需要开启预览,才能拿到图,其余只要开启Capturer就可以拿到图,
  58. {
  59. pusher.StartPreview();
  60. }
  61. }
  62. else
  63. {
  64. pusher.Dispose();
  65. }
  66. }
  67. else
  68. {
  69. CrossPlatformHelper.Instance.LogWriter?.WriteLineError($"Rtc Multi PusherV2 Can not find {deviceInfo.Category} User Info!");
  70. }
  71. }
  72. return true;
  73. }
  74. public bool StopPusher()
  75. {
  76. foreach (var pusher in _pushers.Values)
  77. {
  78. pusher.ImageFrameReceived -= OnImageFrameReceived;
  79. pusher.FirstFrameReceived -= OnFirstFrameReceived;
  80. pusher.Stop();
  81. }
  82. _pushers.Clear();
  83. _liveStatus.Clear();
  84. return true;
  85. }
  86. public void SetMute(bool isMute)
  87. {
  88. if (_pushers.Count > 0)
  89. {
  90. _pushers[0].SetMute(isMute);
  91. }
  92. }
  93. public void SwitchMic(string micId)
  94. {
  95. if (_pushers.Count > 0)
  96. {
  97. _pushers[0].SwitchMic(micId);
  98. }
  99. }
  100. public override void StartPreview(EnumLiveChannelCategory category)
  101. {
  102. if (_pushers.TryGetValue(category, out var client))
  103. {
  104. client.StartPreview();
  105. }
  106. base.StartPreview(category);
  107. }
  108. public override void StopPreview()
  109. {
  110. foreach (var item in _pushers.Values)
  111. {
  112. if (item.Category == EnumLiveChannelCategory.Main && LiveVideoStatusChecker.Instance.IsRealTimeCapturing)
  113. {
  114. continue;
  115. }
  116. item.StopPreview();
  117. }
  118. base.StopPreview();
  119. }
  120. private void OnImageFrameReceived(object sender, ImageFrameData e)
  121. {
  122. var category = (EnumLiveChannelCategory)sender;
  123. if (category == EnumLiveChannelCategory.Main)
  124. {
  125. RainbowImageDetector.Instance.AddImage(e);
  126. LiveVideoStatusChecker.Instance.AddImage(e);
  127. }
  128. CopyPreviewData(category, e);
  129. }
  130. private void OnFirstFrameReceived(object sender, EnumLiveChannelCategory e)
  131. {
  132. if (!_liveStatus.TryGetValue(e, out var states))
  133. {
  134. if (_liveStatus.TryAdd(e, EnumLiveStates.TerminalIsPushing))
  135. {
  136. ChannelStateChanged?.Invoke(this, new ChannelStateEventArgsV2(e, EnumDeviceLiveState.Pushing));
  137. }
  138. }
  139. }
  140. public bool StartSpeedTest(uint appId, string userId, string userSign)
  141. {
  142. TRTCPusher pusher = null;
  143. try
  144. {
  145. pusher = new TRTCPusher();
  146. return pusher.StartSpeedTest(appId, userId, userSign);
  147. }
  148. catch (Exception ex)
  149. {
  150. CrossPlatformHelper.Instance.LogWriter?.WriteLineError($"Rtc Single PusherV2 StartSpeedTest Error:{ex}");
  151. return false;
  152. }
  153. finally
  154. {
  155. if (pusher != null)
  156. {
  157. pusher.StopSpeedTest();
  158. pusher = null;
  159. }
  160. }
  161. }
  162. public override void DoDispose()
  163. {
  164. StopPusher();
  165. _pushers.Clear();
  166. base.DoDispose();
  167. }
  168. private class TRTCClientV2 : IDisposable
  169. {
  170. public event EventHandler<ImageFrameData> ImageFrameReceived;
  171. public event EventHandler<EnumLiveChannelCategory> FirstFrameReceived;
  172. private TRTCRoomInfo _roomInfo;
  173. private int _processId;
  174. private ImageFrameData _imageFrameData;
  175. private EnumLiveChannelCategory _category;
  176. private ProcessKeepHelper _processKeeper;
  177. private PipeClient _messageClient;
  178. private PipeServer _messageServer;
  179. private PipeServer _videoPipeServer;
  180. private PipeClient _videoPipeClient;
  181. private bool _isPreviewing;
  182. private TerminalImageSenderV2 _terminalSender;
  183. private bool _isConnectedWithClient;
  184. private readonly object _previewLocker = new object();
  185. private int _terminalWidth;
  186. private int _terminalHeight;
  187. private readonly ManualResetEvent _handlingImageEvent = new ManualResetEvent(true);
  188. public EnumLiveChannelCategory Category => _category;
  189. public TRTCClientV2(CPVideoDeviceOutputInfo deviceInfo, int outputWidth, int outputHeight, int appid, string userId, int roomId, string userSign, int fps, int bitrate, int minBitrate, bool isMute, string micId)
  190. {
  191. _category = deviceInfo.Category;
  192. _imageFrameData = new ImageFrameData(0, 0);
  193. _roomInfo = new TRTCRoomInfo();
  194. _roomInfo.AppId = (uint)appid;
  195. _roomInfo.UserSig = userSign;
  196. _roomInfo.UserId = userId;
  197. _roomInfo.RoomId = (uint)roomId;
  198. _roomInfo.OutputWidth = outputWidth;
  199. _roomInfo.OutputHeight = outputHeight;
  200. _roomInfo.DeviceWidth = deviceInfo.OutputWidth;
  201. _roomInfo.DeviceHeight = deviceInfo.OutputHeight;
  202. _roomInfo.VideoFps = (uint)fps;
  203. _roomInfo.VideoBitrate = (uint)bitrate;
  204. _roomInfo.MinVideoBitrate = (uint)minBitrate;
  205. _roomInfo.DeviceId = deviceInfo.VideoDeviceId;
  206. _roomInfo.IsSonopost = CommonParameter.Instance.IsSonopost;
  207. _roomInfo.MicDeviceId = micId;
  208. _roomInfo.IsMute = isMute;
  209. _roomInfo.IsOldServerMode = false;
  210. if (_category == EnumLiveChannelCategory.Main && !_roomInfo.IsSonopost)
  211. {
  212. _roomInfo.IsUSMachineImage = true;
  213. }
  214. _roomInfo.IsForLive = true;
  215. switch (_category)
  216. {
  217. case EnumLiveChannelCategory.Main:
  218. _roomInfo.Category = EnumLiveChannelCategory.Main;
  219. _roomInfo.IsFillMode = false;
  220. break;
  221. case EnumLiveChannelCategory.Auxiliary1:
  222. _roomInfo.Category = EnumLiveChannelCategory.Auxiliary1;
  223. _roomInfo.IsFillMode = true;
  224. break;
  225. case EnumLiveChannelCategory.Auxiliary2:
  226. _roomInfo.Category = EnumLiveChannelCategory.Auxiliary2;
  227. _roomInfo.IsFillMode = true;
  228. break;
  229. case EnumLiveChannelCategory.Auxiliary3:
  230. _roomInfo.Category = EnumLiveChannelCategory.Auxiliary3;
  231. _roomInfo.IsFillMode = true;
  232. break;
  233. }
  234. }
  235. public void Start()
  236. {
  237. var trtcClientApp = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Vinno.FIS.TRTCClient.exe");
  238. var logPath = FISWin.FISLogPath;
  239. if (logPath.EndsWith("\\"))
  240. {
  241. logPath = logPath.Substring(0, logPath.Length - 1);
  242. }
  243. var argument = $"pid=\"{Process.GetCurrentProcess().Id}\" lpt=\"{logPath}\" {_roomInfo}";
  244. _processId = ProcessHelper.StartProcess(trtcClientApp, argument);
  245. if (_processId == 0)
  246. {
  247. CrossPlatformHelper.Instance.LogWriter?.WriteLineError($"RtcMultiPusherV2 Start Process Error,UserId:{_roomInfo.UserId}");
  248. return;
  249. }
  250. CrossPlatformHelper.Instance.LogWriter?.WriteLineInfo($"RtcMultiPusherV2 TRTCClient Start,RoomId:{_roomInfo.RoomId},ProcessId:{_processId}");
  251. StartMessagePipe();
  252. StartVideoPipeServer();
  253. if (_category == EnumLiveChannelCategory.Main && !_roomInfo.IsSonopost)
  254. {
  255. StartVideoPipeClient();
  256. StartTerminalSender();
  257. }
  258. _processKeeper = new ProcessKeepHelper(_processId);
  259. _processKeeper.StartKeepProcess(() =>
  260. {
  261. StopMessagePipe();
  262. StopVideoPipeServer();
  263. StopVideoPipeClient();
  264. StopTerminalSender();
  265. var processId = ProcessHelper.StartProcess(trtcClientApp, argument);
  266. _processId = processId;
  267. StartMessagePipe();
  268. StartVideoPipeServer();
  269. if (_category == EnumLiveChannelCategory.Main && !_roomInfo.IsSonopost)
  270. {
  271. StartVideoPipeClient();
  272. StartTerminalSender();
  273. }
  274. return processId;
  275. });
  276. }
  277. private void StartTerminalSender()
  278. {
  279. if (_category == EnumLiveChannelCategory.Main && !_roomInfo.IsSonopost)
  280. {
  281. if (_roomInfo.OutputWidth <= 640 && _roomInfo.OutputHeight <= 480)
  282. {
  283. _terminalWidth = 640;
  284. _terminalHeight = 480;
  285. _terminalSender = new Terminal640X480SenderV2(_roomInfo.VideoDeviceId, _roomInfo.OutputWidth, _roomInfo.OutputHeight);
  286. }
  287. else if (_roomInfo.OutputWidth <= 960 && _roomInfo.OutputHeight <= 544)
  288. {
  289. _terminalWidth = 960;
  290. _terminalHeight = 544;
  291. _terminalSender = new Terminal960X540SenderV2(_roomInfo.VideoDeviceId, _roomInfo.OutputWidth, _roomInfo.OutputHeight);
  292. }
  293. else if (_roomInfo.OutputWidth <= 960 && _roomInfo.OutputHeight <= 720)
  294. {
  295. _terminalWidth = 960;
  296. _terminalHeight = 720;
  297. _terminalSender = new Terminal960X720SenderV2(_roomInfo.VideoDeviceId, _roomInfo.OutputWidth, _roomInfo.OutputHeight);
  298. }
  299. else if (_roomInfo.OutputWidth <= 1280 && _roomInfo.OutputHeight <= 720)
  300. {
  301. _terminalWidth = 1280;
  302. _terminalHeight = 720;
  303. _terminalSender = new Terminal1280X720SenderV2(_roomInfo.VideoDeviceId, _roomInfo.OutputWidth, _roomInfo.OutputHeight);
  304. }
  305. else
  306. {
  307. _terminalWidth = 1920;
  308. _terminalHeight = 1080;
  309. _terminalSender = new Terminal1920X1080SenderV2(_roomInfo.VideoDeviceId, _roomInfo.OutputWidth, _roomInfo.OutputHeight);
  310. }
  311. _terminalSender.VideoFrameDataReceived += OnVideoFrameDataReceived;
  312. _terminalSender.Start();
  313. }
  314. }
  315. private void StartVideoPipeClient()
  316. {
  317. _videoPipeClient = new PipeClient($"{_processId}_TerminalImage");
  318. _videoPipeClient.LogMsgThrow += OnLogMsgThrow;
  319. CrossPlatformHelper.Instance.LogWriter?.WriteLineInfo($"RtcMultiPusherV2 Create Local Video Pipe Client :{_videoPipeClient.PipeName}");
  320. _videoPipeClient.Start();
  321. }
  322. private void OnLogMsgThrow(object sender, LogEventArgs e)
  323. {
  324. if (e == null)
  325. {
  326. return;
  327. }
  328. switch (e.LogType)
  329. {
  330. case DeviceLogCategory.Error:
  331. CrossPlatformHelper.Instance.LogWriter?.WriteLineError(e.Msg);
  332. break;
  333. case DeviceLogCategory.Warn:
  334. CrossPlatformHelper.Instance.LogWriter?.WriteLineWarn(e.Msg);
  335. break;
  336. case DeviceLogCategory.Verb:
  337. CrossPlatformHelper.Instance.LogWriter?.WriteLineVerbose(e.Msg);
  338. break;
  339. case DeviceLogCategory.Info:
  340. default:
  341. CrossPlatformHelper.Instance.LogWriter?.WriteLineInfo(e.Msg);
  342. break;
  343. }
  344. }
  345. private void StartVideoPipeServer()
  346. {
  347. _videoPipeServer = new PipeServer($"{_processId}_LocalVideo");
  348. _videoPipeServer.DataReceived += OnVideoDataReceived;
  349. _videoPipeServer.LogMsgThrow += OnLogMsgThrow;
  350. CrossPlatformHelper.Instance.LogWriter?.WriteLineInfo($"RtcMultiPusherV2Create Local Video Pipe Server :{_videoPipeServer.PipeName}");
  351. _videoPipeServer.StartAndReceive();
  352. }
  353. public void Stop()
  354. {
  355. CrossPlatformHelper.Instance.LogWriter?.WriteLineInfo($"RtcMultiPusherV2 TRTCClient Stop");
  356. _processKeeper?.StopKeepProcess();
  357. SendExitMessage();
  358. StopPreview();
  359. StopVideoPipeServer();
  360. StopVideoPipeClient();
  361. StopMessagePipe();
  362. StopTerminalSender();
  363. var success = ProcessHelper.FinishProcess(_processId);
  364. if (!success)
  365. {
  366. CrossPlatformHelper.Instance.LogWriter?.WriteLineError($"RtcMultiPusherV2 Finish Process Error,UserId:{_roomInfo.UserId}");
  367. }
  368. }
  369. private void StopTerminalSender()
  370. {
  371. if (_terminalSender != null)
  372. {
  373. _terminalSender.VideoFrameDataReceived -= OnVideoFrameDataReceived;
  374. _terminalSender.Stop();
  375. _terminalSender = null;
  376. };
  377. }
  378. private void OnVideoFrameDataReceived(object sender, CPVideoFrameData e)
  379. {
  380. if (e == null)
  381. {
  382. return;
  383. }
  384. _videoPipeClient?.SendBytes(e.Data);
  385. }
  386. private void SendExitMessage()
  387. {
  388. CrossPlatformHelper.Instance.LogWriter?.WriteLineInfo($"RtcMultiPusherV2 MessageClient Send Exit");
  389. var pipeMessageData = new PipeMessageData(PipeMessage.Exit, new byte[0]);
  390. _messageClient?.SendBytes(pipeMessageData.ToBytes());
  391. Thread.Sleep(50);
  392. }
  393. public void StartMessagePipe()
  394. {
  395. _messageClient = new PipeClient($"{_processId}_FIS2TRTCClientMessage");
  396. _messageClient.LogMsgThrow += OnLogMsgThrow;
  397. _messageClient.Start();
  398. _messageServer = new PipeServer($"{_processId}_TRTCClient2FISMessage");
  399. _messageServer.DataReceived += OnMessageDataReceived;
  400. _messageServer.LogMsgThrow += OnLogMsgThrow;
  401. _messageServer.StartAndReceive();
  402. }
  403. private void OnMessageDataReceived(object sender, byte[] e)
  404. {
  405. if (e == null)
  406. {
  407. return;
  408. }
  409. var pipeMessageData = PipeMessageData.FromBytes(e);
  410. CrossPlatformHelper.Instance.LogWriter?.WriteLineInfo($"RtcMultiPusherV2 Message Pipe Server Receive PipeMessage{pipeMessageData?.PipeMessage}");
  411. if (pipeMessageData.PipeMessage == PipeMessage.ImageSizeChanged)
  412. {
  413. var pipeImageSizeData = PipeImageSizeData.FromBytes(pipeMessageData.MessageData);
  414. if (_imageFrameData.Width != pipeImageSizeData.Width || _imageFrameData.Height != pipeImageSizeData.Height)
  415. {
  416. _imageFrameData.Resize(pipeImageSizeData.Width, pipeImageSizeData.Height);
  417. }
  418. }
  419. else if (pipeMessageData.PipeMessage == PipeMessage.BootUp)
  420. {
  421. lock (_previewLocker)
  422. {
  423. _isConnectedWithClient = true;
  424. if (_roomInfo.IsUSMachineImage && _roomInfo.IsForLive)
  425. {
  426. CrossPlatformHelper.Instance.LogWriter?.WriteLineInfo($"RtcMultiPusherV2 MessageClient Send ImageSizeChanged,Width:{_terminalWidth},Height:{_terminalHeight}");
  427. var pipeImageSizeData = new PipeMessageData(PipeMessage.ImageSizeChanged, new PipeImageSizeData(_terminalWidth, _terminalHeight).ToBytes());
  428. _messageClient?.SendBytes(pipeImageSizeData.ToBytes());
  429. }
  430. if (_isPreviewing)
  431. {
  432. CrossPlatformHelper.Instance.LogWriter?.WriteLineInfo($"RtcMultiPusherV2 MessageClient Send StartPreview");
  433. var startPreviewMessage = new PipeMessageData(PipeMessage.StartPreview, new byte[0]);
  434. _messageClient?.SendBytes(startPreviewMessage.ToBytes());
  435. }
  436. else
  437. {
  438. CrossPlatformHelper.Instance.LogWriter?.WriteLineInfo($"RtcMultiPusherV2 MessageClient Send StopPreview");
  439. var stopPreviewMessage = new PipeMessageData(PipeMessage.StopPreview, new byte[0]);
  440. _messageClient?.SendBytes(stopPreviewMessage.ToBytes());
  441. }
  442. }
  443. }
  444. else if (pipeMessageData.PipeMessage == PipeMessage.FirstFrameReceived)
  445. {
  446. FirstFrameReceived?.Invoke(this, _category);
  447. }
  448. }
  449. private void StopVideoPipeServer()
  450. {
  451. if (_videoPipeServer != null)
  452. {
  453. CrossPlatformHelper.Instance.LogWriter?.WriteLineInfo($"RtcMultiPusherV2 Close Pipe Server Video{_videoPipeServer.PipeName}");
  454. _videoPipeServer.DataReceived -= OnVideoDataReceived;
  455. _videoPipeServer.Dispose();
  456. _videoPipeServer.LogMsgThrow -= OnLogMsgThrow;
  457. _videoPipeServer = null;
  458. }
  459. }
  460. private void StopVideoPipeClient()
  461. {
  462. if (_videoPipeClient != null)
  463. {
  464. CrossPlatformHelper.Instance.LogWriter?.WriteLineInfo($"RtcMultiPusherV2 Close Pipe Client Video{_videoPipeClient.PipeName}");
  465. _videoPipeClient.Dispose();
  466. _videoPipeClient.LogMsgThrow -= OnLogMsgThrow;
  467. _videoPipeClient = null;
  468. }
  469. }
  470. private void OnVideoDataReceived(object sender, byte[] e)
  471. {
  472. if (e == null)
  473. {
  474. CrossPlatformHelper.Instance.LogWriter?.WriteLineError($"RtcMultiPusherV2 TRTCClient {_roomInfo.RoomId} {_roomInfo.UserId} received video image is empty");
  475. return;
  476. }
  477. try
  478. {
  479. _handlingImageEvent.Reset();
  480. if (_imageFrameData.Size != e.Length)
  481. {
  482. return;
  483. }
  484. if (_isPreviewing)
  485. {
  486. Marshal.Copy(e, 0, _imageFrameData.Data, e.Length);
  487. ImageFrameReceived?.Invoke(_category, _imageFrameData);
  488. }
  489. }
  490. catch (Exception ex)
  491. {
  492. CrossPlatformHelper.Instance.LogWriter?.WriteLineError($"RtcMultiPusherV2 OnVideoDataReceived error: {ex}");
  493. }
  494. finally
  495. {
  496. _handlingImageEvent.Set();
  497. }
  498. }
  499. public void StopMessagePipe()
  500. {
  501. if (_messageClient != null)
  502. {
  503. _messageClient.Dispose();
  504. _messageClient.LogMsgThrow -= OnLogMsgThrow;
  505. _messageClient = null;
  506. }
  507. if (_messageServer != null)
  508. {
  509. _messageServer.DataReceived -= OnMessageDataReceived;
  510. _messageServer.Dispose();
  511. _messageServer.LogMsgThrow -= OnLogMsgThrow;
  512. _messageServer = null;
  513. }
  514. }
  515. public void StartPreview()
  516. {
  517. lock (_previewLocker)
  518. {
  519. if (_isPreviewing)
  520. return;
  521. _isPreviewing = true;
  522. if (_isConnectedWithClient)
  523. {
  524. CrossPlatformHelper.Instance.LogWriter?.WriteLineInfo($"RtcMultiPusherV2 MessageClient Send StartPreview");
  525. var startPreviewMessage = new PipeMessageData(PipeMessage.StartPreview, new byte[0]);
  526. _messageClient?.SendBytes(startPreviewMessage.ToBytes());
  527. }
  528. }
  529. }
  530. public void SetMute(bool isMute)
  531. {
  532. if (_isConnectedWithClient)
  533. {
  534. CrossPlatformHelper.Instance.LogWriter?.WriteLineInfo($"RtcMultiPusherV2 MessageClient Send SetMute {isMute}");
  535. var isMuteMessage = new PipeBoolMessage(isMute);
  536. var muteMessage = new PipeMessageData(PipeMessage.Mute, isMuteMessage.ToBytes());
  537. _messageClient?.SendBytes(muteMessage.ToBytes());
  538. }
  539. }
  540. public void SwitchMic(string micId)
  541. {
  542. if (_isConnectedWithClient)
  543. {
  544. CrossPlatformHelper.Instance.LogWriter?.WriteLineInfo($"RtcMultiPusherV2 MessageClient Send SwitchMic {micId}");
  545. var micIdMessage = new PipeUserIdMessage(micId);
  546. var message = new PipeMessageData(PipeMessage.SwitchMic, micIdMessage.ToBytes());
  547. _messageClient?.SendBytes(message.ToBytes());
  548. }
  549. }
  550. public void StopPreview()
  551. {
  552. lock (_previewLocker)
  553. {
  554. if (!_isPreviewing)
  555. {
  556. return;
  557. }
  558. _isPreviewing = false;
  559. if (_isConnectedWithClient)
  560. {
  561. CrossPlatformHelper.Instance.LogWriter?.WriteLineInfo($"RtcMultiPusherV2 MessageClient Send StopPreview");
  562. var stopPreviewMessage = new PipeMessageData(PipeMessage.StopPreview, new byte[0]);
  563. _messageClient?.SendBytes(stopPreviewMessage.ToBytes());
  564. }
  565. }
  566. }
  567. public void Dispose()
  568. {
  569. Stop();
  570. _handlingImageEvent.WaitOne();
  571. _imageFrameData?.Dispose();
  572. }
  573. }
  574. }
  575. }