LiveVideoV2.cs 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943
  1. using JsonRpcLite.Rpc;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Runtime.InteropServices;
  6. using Vinno.FIS.TRTCClient.Common.Enum;
  7. using Vinno.IUS.Common.Log;
  8. using Vinno.vCloud.Common.FIS.Helper;
  9. using Vinno.vCloud.Common.FIS.Notification;
  10. using Vinno.vCloud.FIS.CrossPlatform.Common;
  11. using Vinno.vCloud.FIS.CrossPlatform.Common.Enum;
  12. using Vinno.vCloud.FIS.CrossPlatform.Common.LiveVideo;
  13. using WingInterfaceLibrary.Enum;
  14. using WingInterfaceLibrary.Enum.NotificationEnum;
  15. using WingInterfaceLibrary.Interface;
  16. using WingInterfaceLibrary.LiveConsultation;
  17. using WingInterfaceLibrary.Notifications;
  18. using WingInterfaceLibrary.Notifications.Consultation;
  19. using WingInterfaceLibrary.Notifications.Education;
  20. using WingInterfaceLibrary.Notifications.Live;
  21. namespace Vinno.vCloud.Common.FIS.LiveVideos
  22. {
  23. internal class LiveVideoV2 : ILiveVideoV2
  24. {
  25. private readonly string _token;
  26. private readonly JsonRpcClient _client;
  27. private readonly IDeviceService _deviceService;
  28. private readonly ILiveConsultationService _liveConsultationService;
  29. private readonly IEducationService _educationService;
  30. private readonly object _operateLocker = new object();
  31. private readonly object _locker = new object();
  32. private readonly string _uniqueId;
  33. private readonly ILiveVideoPusherManagerV2 _pusherManager;
  34. private readonly IPreviewManagerV2 _previewManager;
  35. private readonly RealTimeCaptureManager _realtimeCaptureManager;
  36. private readonly FISWebSocket _websocket;
  37. private readonly List<CPVideoDeviceOutputInfo> _currentVideoDeviceInfoList;
  38. private readonly List<VideoDeviceOutputInfoDTO> _currentOutputVideoInfoList;
  39. private readonly int _usScreenWidth;
  40. private readonly int _usScreenHeight;
  41. private bool _disposed;
  42. private bool _liveVideoEnabled;
  43. private bool _firstCommit;
  44. private string _oldPreviewCameraId;
  45. private RainbowImageDetectConfig _rainbowImageDetectConfig;
  46. private bool _isPaused;
  47. private bool _cameraLiveEnabled;
  48. private int _cameraPreviewWidth;
  49. private int _cameraPreviewHeight;
  50. private byte[] _previewBuffer;
  51. private string _cameraId;
  52. private string _micDeviceId;
  53. private bool _isMute;
  54. /// <summary>
  55. /// Raised when camera Preview Excute
  56. /// </summary>
  57. public event EventHandler<byte[]> PreviewCameraCaptured;
  58. /// <summary>
  59. /// Raised when Camera Preview Image Size Changed
  60. /// </summary>
  61. public event EventHandler<ImageSize> CameraPreviewImageSizeChanged;
  62. /// <summary>
  63. /// The event to notificate the US to show or hide the live video out put window
  64. /// </summary>
  65. public event EventHandler<LiveNotificationArgs> LiveNotification;
  66. /// <summary>
  67. /// Raised when capture image generated.(only for new server)
  68. /// </summary>
  69. public event EventHandler<string> CaptureImageGenerated;
  70. /// <summary>
  71. /// Raised when record video generated.(only for new server)
  72. /// </summary>
  73. public event EventHandler<string> RecordVideoGenerated;
  74. public LiveVideoV2(string token, string uniqueId, int usScreenWidth, int usScreenHeight, FISWebSocket websocket, JsonRpcClient client, string deviceModel, string deviceType, string softwareVersion)
  75. {
  76. _token = token;
  77. _uniqueId = uniqueId;
  78. _websocket = websocket;
  79. _websocket.NotificationReceived += OnNotificationReceived;
  80. _client = client;
  81. _deviceService = _client?.CreateProxy<IDeviceService>();
  82. _liveConsultationService = _client?.CreateProxy<ILiveConsultationService>();
  83. _educationService = _client?.CreateProxy<IEducationService>();
  84. _usScreenWidth = usScreenWidth;
  85. _usScreenHeight = usScreenHeight;
  86. _previewBuffer = new byte[0];
  87. _firstCommit = true;
  88. _currentOutputVideoInfoList = new List<VideoDeviceOutputInfoDTO>();
  89. _currentVideoDeviceInfoList = new List<CPVideoDeviceOutputInfo>();
  90. _pusherManager = new LiveVideoPusherManagerV2(_token, _liveConsultationService, _deviceService, _educationService, _uniqueId, deviceModel, deviceType, softwareVersion);
  91. _pusherManager.LiveVideoNotification += OnLiveVideoNotification;
  92. _previewManager = new PreviewManagerV2(_pusherManager, _uniqueId);
  93. _previewManager.PreviewImageReceived += OnPreviewImageReceived;
  94. RainbowImageDetector.Instance.IsPaused += OnIsPaused;
  95. if (CommonParameter.Instance.IsSonopost)
  96. {
  97. _realtimeCaptureManager = new RealTimeCaptureManager();
  98. _realtimeCaptureManager.CaptureImageGenerated += OnCaptureImageGenerated;
  99. _realtimeCaptureManager.RecordVideoGenerated += OnRecordVideoGenerated;
  100. }
  101. }
  102. public void ReUploadRestVid()
  103. {
  104. _realtimeCaptureManager?.ReUploadRestVid();
  105. }
  106. private void OnRecordVideoGenerated(object sender, string e)
  107. {
  108. RecordVideoGenerated?.Invoke(this, e);
  109. }
  110. private void OnCaptureImageGenerated(object sender, string e)
  111. {
  112. CaptureImageGenerated?.Invoke(this, e);
  113. }
  114. private void OnPreviewImageReceived(object sender, ImageFrameData data)
  115. {
  116. if (data == null)
  117. {
  118. return;
  119. }
  120. if (_cameraPreviewHeight != data.Height || _cameraPreviewWidth != data.Width)
  121. {
  122. _cameraPreviewHeight = data.Height;
  123. _cameraPreviewWidth = data.Width;
  124. Array.Resize(ref _previewBuffer, data.Size);
  125. CameraPreviewImageSizeChanged?.Invoke(this, new ImageSize(_cameraPreviewWidth, _cameraPreviewHeight));
  126. }
  127. Marshal.Copy(data.Data, _previewBuffer, 0, data.Size);
  128. PreviewCameraCaptured?.Invoke(this, _previewBuffer);
  129. }
  130. /// <summary>
  131. /// Speed live test network and auto select good network to server
  132. /// </summary>
  133. /// <returns></returns>
  134. public bool StartSpeedTest()
  135. {
  136. bool speedTest = false;
  137. if (_pusherManager != null)
  138. {
  139. speedTest = _pusherManager.StartSpeedTest();
  140. }
  141. return speedTest;
  142. }
  143. private void OnNotificationReceived(object sender, NotificationArgs e)
  144. {
  145. switch (e.NotificationType)
  146. {
  147. case NotificationTypeEnum.StartLiveToDeviceNotification:
  148. try
  149. {
  150. Logger.WriteLineInfo($"LiveVideoV2 StartLiveToDeviceNotification Receive");
  151. if (e.Params is StartLiveToDeviceNotification startLiveToDeviceNotification)
  152. {
  153. HandleStartLiveToDeviceNotification(startLiveToDeviceNotification);
  154. }
  155. }
  156. catch (Exception ex)
  157. {
  158. Logger.WriteLineError($"LiveVideoV2 Handle StartLiveToDeviceNotification Error:{ex}");
  159. }
  160. break;
  161. case NotificationTypeEnum.CloseLiveToDeviceNotification:
  162. try
  163. {
  164. Logger.WriteLineInfo($"LiveVideoV2 CloseLiveToDeviceNotification Receive");
  165. HandleCloseLiveToDeviceNotification();
  166. }
  167. catch (Exception ex)
  168. {
  169. Logger.WriteLineError($"LiveVideoV2 Handle CloseLiveToDeviceNotification Error:{ex}");
  170. }
  171. break;
  172. case NotificationTypeEnum.ModifyDeviceMergedVideoSizeNotification:
  173. try
  174. {
  175. Logger.WriteLineInfo($"LiveVideoV2 ModifyDeviceMergedVideoSizeNotification Receive");
  176. if (e.Params is ModifyDeviceMergedVideoSizeNotification modifyDeviceMergedVideoSizeNotification)
  177. {
  178. HandleModifyDeviceMergedVideoSizeNotification(modifyDeviceMergedVideoSizeNotification);
  179. }
  180. }
  181. catch (Exception ex)
  182. {
  183. Logger.WriteLineError($"LiveVideoV2 Handle ModifyDeviceMergedVideoSizeNotification Error:{ex}");
  184. }
  185. break;
  186. case NotificationTypeEnum.StartConsolutionHeartRateToDeviceNotification:
  187. try
  188. {
  189. Logger.WriteLineInfo($"LiveVideoV2 StartConsolutionHeartRateToDeviceNotification Receive");
  190. if (e.Params is StartConsolutionHeartRateToDeviceNotification startConsolutionHeartRateToDeviceNotification)
  191. {
  192. HandleStartConsolutionHeartRateToDeviceNotification(startConsolutionHeartRateToDeviceNotification);
  193. }
  194. }
  195. catch (Exception ex)
  196. {
  197. Logger.WriteLineError($"LiveVideoV2 Handle StartConsolutionHeartRateToDeviceNotification Error:{ex}");
  198. }
  199. break;
  200. case NotificationTypeEnum.CloseConsolutionHeartRateToDeviceNotification:
  201. try
  202. {
  203. Logger.WriteLineInfo($"LiveVideoV2 CloseConsolutionHeartRateToDeviceNotification Receive");
  204. if (e.Params is CloseConsolutionHeartRateToDeviceNotification closeConsolutionHeartRateToDeviceNotification)
  205. {
  206. HandleCloseConsolutionHeartRateToDeviceNotification(closeConsolutionHeartRateToDeviceNotification);
  207. }
  208. }
  209. catch (Exception ex)
  210. {
  211. Logger.WriteLineError($"LiveVideoV2 Handle CloseConsolutionHeartRateToDeviceNotification Error:{ex}");
  212. }
  213. break;
  214. case NotificationTypeEnum.StartEducationHeartRateToDeviceNotification:
  215. try
  216. {
  217. Logger.WriteLineInfo($"LiveVideoV2 StartEducationHeartRateToDeviceNotification Receive");
  218. if (e.Params is StartEducationHeartRateToDeviceNotification startEducationHeartRateToDeviceNotification)
  219. {
  220. HandleStartEducationHeartRateToDeviceNotification(startEducationHeartRateToDeviceNotification);
  221. }
  222. }
  223. catch (Exception ex)
  224. {
  225. Logger.WriteLineError($"LiveVideoV2 Handle StartEducationHeartRateToDeviceNotification Error:{ex}");
  226. }
  227. break;
  228. case NotificationTypeEnum.CloseCourseHeartRateToDeviceNotification:
  229. try
  230. {
  231. Logger.WriteLineInfo($"LiveVideoV2 CloseCourseHeartRateToDeviceNotification Receive");
  232. if (e.Params is CloseCourseHeartRateToDeviceNotification closeCourseHeartRateToDeviceNotification)
  233. {
  234. HandleCloseCourseHeartRateToDeviceNotification(closeCourseHeartRateToDeviceNotification);
  235. }
  236. }
  237. catch (Exception ex)
  238. {
  239. Logger.WriteLineError($"LiveVideoV2 Handle CloseCourseHeartRateToDeviceNotification Error:{ex}");
  240. }
  241. break;
  242. case NotificationTypeEnum.ChangeConsultationToDeviceNotification:
  243. try
  244. {
  245. Logger.WriteLineInfo($"LiveVideoV2 ChangeConsultationToDeviceNotification Receive");
  246. if (e.Params is ChangeConsultationToDeviceNotification changeConsultationToDeviceNotification)
  247. {
  248. HandleChangeConsultationToDeviceNotification(changeConsultationToDeviceNotification);
  249. }
  250. }
  251. catch (Exception ex)
  252. {
  253. Logger.WriteLineError($"LiveVideoV2 Handle ChangeConsultationToDeviceNotification Error:{ex}");
  254. }
  255. break;
  256. }
  257. }
  258. private void HandleCloseLiveToDeviceNotification()
  259. {
  260. lock (_operateLocker)
  261. {
  262. if (_isPaused)
  263. {
  264. Logger.WriteLineInfo($"Receive CloseLiveToDeviceNotification,but it is paused,so skipped it.");
  265. return;
  266. }
  267. _pusherManager.LiveStateChanged(new LiveEventArgs(false));
  268. }
  269. }
  270. private void HandleModifyDeviceMergedVideoSizeNotification(ModifyDeviceMergedVideoSizeNotification modifyDeviceMergedVideoSizeNotification)
  271. {
  272. lock (_operateLocker)
  273. {
  274. if (vCloudServerConfig.Instance.MergedChannel != modifyDeviceMergedVideoSizeNotification.MergedChannel)
  275. {
  276. vCloudServerConfig.Instance.MergedChannel = modifyDeviceMergedVideoSizeNotification.MergedChannel;
  277. _pusherManager.LiveStateChanged(new LiveEventArgs(false));
  278. }
  279. else
  280. {
  281. if (modifyDeviceMergedVideoSizeNotification.VideoDeviceInfos == null)
  282. {
  283. if (_currentOutputVideoInfoList.Count > 0)
  284. {
  285. _pusherManager.LiveStateChanged(new LiveEventArgs(false));
  286. }
  287. }
  288. else
  289. {
  290. if (modifyDeviceMergedVideoSizeNotification.VideoDeviceInfos.Count != _currentOutputVideoInfoList.Count)
  291. {
  292. _pusherManager.LiveStateChanged(new LiveEventArgs(false));
  293. }
  294. else
  295. {
  296. var deviceInfos = new List<VideoDeviceOutputInfoDTO>();
  297. foreach (var device in modifyDeviceMergedVideoSizeNotification.VideoDeviceInfos)
  298. {
  299. deviceInfos.Add(DTOConverter.ConvertVideoDeviceDTOToVideoDeviceOutputInfoDTO(device));
  300. }
  301. if (IsDifferent(deviceInfos))
  302. {
  303. _pusherManager.LiveStateChanged(new LiveEventArgs(false));
  304. }
  305. }
  306. }
  307. }
  308. }
  309. }
  310. private void HandleStartConsolutionHeartRateToDeviceNotification(StartConsolutionHeartRateToDeviceNotification startConsolutionHeartRateToDeviceNotification)
  311. {
  312. _pusherManager.StartHeartRateKeeper(startConsolutionHeartRateToDeviceNotification.LiveRoomCode, startConsolutionHeartRateToDeviceNotification.IntervalSeconds, EnumHeartRateType.LiveConsultation);
  313. }
  314. private void HandleStartEducationHeartRateToDeviceNotification(StartEducationHeartRateToDeviceNotification startEducationHeartRateToDeviceNotification)
  315. {
  316. _pusherManager.StartHeartRateKeeper(startEducationHeartRateToDeviceNotification.LiveRoomCode, startEducationHeartRateToDeviceNotification.IntervalSeconds, EnumHeartRateType.Education);
  317. }
  318. private void HandleCloseConsolutionHeartRateToDeviceNotification(CloseConsolutionHeartRateToDeviceNotification closeConsolutionHeartRateToDeviceNotification)
  319. {
  320. _pusherManager.StopHeartRateKeeper();
  321. }
  322. private void HandleCloseCourseHeartRateToDeviceNotification(CloseCourseHeartRateToDeviceNotification closeCourseHeartRateToDeviceNotification)
  323. {
  324. _pusherManager.StopHeartRateKeeper();
  325. }
  326. private void HandleChangeConsultationToDeviceNotification(ChangeConsultationToDeviceNotification changeConsultationToDeviceNotification)
  327. {
  328. _pusherManager.ChangeHeartRateCode(changeConsultationToDeviceNotification.ConsultationCode);
  329. }
  330. private void HandleStartLiveToDeviceNotification(StartLiveToDeviceNotification startLiveToDeviceNotification)
  331. {
  332. lock (_operateLocker)
  333. {
  334. if (_isPaused)
  335. {
  336. Logger.WriteLineInfo($"Receive StartLiveToDeviceNotification,but it is paused,so skipped it.");
  337. return;
  338. }
  339. if (startLiveToDeviceNotification.VideoDeviceOutputList?.Count == 0)
  340. {
  341. Logger.WriteLineError("LiveVideoV2 Receive StartLiveToDeviceNotification,But the VideoDeviceOutputInfo Count is 0");
  342. return;
  343. }
  344. _currentOutputVideoInfoList.Clear();
  345. foreach (var device in startLiveToDeviceNotification.VideoDeviceOutputList)
  346. {
  347. _currentOutputVideoInfoList.Add(DTOConverter.ConvertVideoDeviceOutputInfoToVideoDeviceOutputInfoDTO(device));
  348. }
  349. IExtendedData extendedData;
  350. switch (vCloudServerConfig.Instance.LiveProtocolType)
  351. {
  352. case TransactionStatusEnum.TRTC:
  353. extendedData = CreateExtentedData(EnumLiveProtocol.RTC, startLiveToDeviceNotification, _micDeviceId, _isMute);
  354. break;
  355. case TransactionStatusEnum.VRTC:
  356. Logger.WriteLineError("LiveVideoV2 Current doesn't support VRTC Mode");
  357. return;
  358. default:
  359. extendedData = CreateExtentedData(EnumLiveProtocol.Rtmp, startLiveToDeviceNotification, _micDeviceId, _isMute);
  360. break;
  361. }
  362. Logger.WriteLineInfo($"ExtendedData:{extendedData}");
  363. if (extendedData != null)
  364. {
  365. var pushMode = startLiveToDeviceNotification.MergedChannel ? EnumLiveDataMode.MergeLive : EnumLiveDataMode.OnlyLive;
  366. var liveProtocol = extendedData is RtcExtendedData ? EnumLiveProtocol.RTC : EnumLiveProtocol.Rtmp;
  367. var liveEventArgs = new LiveEventArgs(true, liveProtocol, pushMode, extendedData);
  368. _pusherManager.LiveStateChanged(liveEventArgs);
  369. }
  370. }
  371. }
  372. private void DoDispose()
  373. {
  374. if (!_disposed)
  375. {
  376. RainbowImageDetector.Instance.IsPaused -= OnIsPaused;
  377. RainbowImageDetector.Instance.StopDetect();
  378. _websocket.NotificationReceived -= OnNotificationReceived;
  379. _pusherManager.Dispose();
  380. _pusherManager.LiveVideoNotification -= OnLiveVideoNotification;//需放在Dispose之后,否则收不到Close的通知
  381. _previewManager.PreviewImageReceived -= OnPreviewImageReceived;
  382. _previewManager.Dispose();
  383. if (_realtimeCaptureManager != null)
  384. {
  385. _realtimeCaptureManager.CaptureImageGenerated -= OnCaptureImageGenerated;
  386. _realtimeCaptureManager.RecordVideoGenerated -= OnRecordVideoGenerated;
  387. _realtimeCaptureManager.StopRecordVideo(false);
  388. }
  389. _disposed = true;
  390. }
  391. }
  392. private void OnIsPaused(object sender, bool e)
  393. {
  394. lock (_operateLocker)
  395. {
  396. Logger.WriteLineInfo($"LiveVideoV2 Set IsPaused:{e}");
  397. if (e)
  398. {
  399. _isPaused = true;
  400. _pusherManager.SetIsPaused(e);
  401. _previewManager.SetIsPaused(e);
  402. }
  403. else
  404. {
  405. _pusherManager.SetIsPaused(e);
  406. _previewManager.SetIsPaused(e);
  407. _isPaused = false;
  408. }
  409. }
  410. }
  411. private void OnLiveVideoNotification(object sender, LiveNotificationArgs e)
  412. {
  413. LiveNotification?.Invoke(this, e);
  414. }
  415. /// <param name="enableCameraLive"></param>
  416. /// <param name="cameraId"></param>
  417. /// <param name="micId"></param>
  418. /// <param name="showPreviewImage"></param>
  419. /// <param name="enableLiveVideo"></param>
  420. /// <param name="isMute"></param>
  421. public void ChangeCameraSettings(bool enableCameraLive, string cameraId, string micId, bool showPreviewImage, bool enableLiveVideo, bool isMute)
  422. {
  423. lock (_locker)
  424. {
  425. var needNotifyServer = false;
  426. if (!enableCameraLive)
  427. {
  428. cameraId = null;
  429. showPreviewImage = false;
  430. }
  431. if (_firstCommit)
  432. {
  433. _firstCommit = false;
  434. needNotifyServer = true;
  435. }
  436. if (_cameraId != cameraId)
  437. {
  438. _cameraId = cameraId;
  439. needNotifyServer = true;
  440. }
  441. if (_liveVideoEnabled != enableLiveVideo)
  442. {
  443. _liveVideoEnabled = enableLiveVideo;
  444. needNotifyServer = true;
  445. }
  446. if (_cameraLiveEnabled != enableCameraLive)
  447. {
  448. _cameraLiveEnabled = enableCameraLive;
  449. needNotifyServer = true;
  450. }
  451. if (needNotifyServer)
  452. {
  453. var infos = GetVideoDeviceInfos(enableLiveVideo, enableCameraLive, cameraId);
  454. _currentVideoDeviceInfoList.Clear();
  455. foreach (var info in infos)
  456. {
  457. var item = info.Clone() as CPVideoDeviceOutputInfo;
  458. _currentVideoDeviceInfoList.Add(item);
  459. }
  460. _previewManager.UpdateCurrentVideoDeviceInfoList(infos);
  461. }
  462. if (_micDeviceId != micId)
  463. {
  464. _micDeviceId = micId;
  465. _pusherManager.SwitchMic(micId);
  466. }
  467. if (_isMute != isMute)
  468. {
  469. _isMute = isMute;
  470. _pusherManager.SetMute(isMute);
  471. }
  472. if (showPreviewImage && cameraId != null)
  473. {
  474. if (cameraId != _oldPreviewCameraId && _previewManager.IsPreviewing)
  475. {
  476. _previewManager.StopPreview(true);
  477. }
  478. _oldPreviewCameraId = cameraId;
  479. _previewManager.StartPreview(cameraId, 640, 480, 20, EnumLiveChannelCategory.Auxiliary1);
  480. }
  481. else
  482. {
  483. _previewManager.StopPreview(false);
  484. }
  485. }
  486. }
  487. public void ChangeCameraSettingsForSonopost(bool showPreviewImage, EnumLiveChannelCategory previewLiveChannel, IEnumerable<CPVideoDeviceInfo> infos, string micId, bool isMute, RainbowImageDetectConfig rainbowImageDetectConfig)
  488. {
  489. lock (_locker)
  490. {
  491. bool needNotifyServer = false;
  492. if (_firstCommit)
  493. {
  494. _firstCommit = false;
  495. needNotifyServer = true;
  496. }
  497. if (infos == null)
  498. {
  499. if (_currentVideoDeviceInfoList.Count != 0 || needNotifyServer)
  500. {
  501. _currentVideoDeviceInfoList.Clear();
  502. _previewManager.UpdateCurrentVideoDeviceInfoList(new List<CPVideoDeviceOutputInfo>());
  503. }
  504. }
  505. else
  506. {
  507. var newInfos = new List<CPVideoDeviceOutputInfo>();
  508. foreach (var info in infos)
  509. {
  510. string idForServer = null;
  511. switch (info.Category)
  512. {
  513. case EnumLiveChannelCategory.Main:
  514. idForServer = _uniqueId;
  515. break;
  516. case EnumLiveChannelCategory.Auxiliary1:
  517. idForServer = "Camera1";
  518. break;
  519. case EnumLiveChannelCategory.Auxiliary2:
  520. idForServer = "Camera2";
  521. break;
  522. case EnumLiveChannelCategory.Auxiliary3:
  523. idForServer = "Camera3";
  524. break;
  525. }
  526. var item = new CPVideoDeviceOutputInfo
  527. {
  528. VideoDeviceId = info.Id,
  529. IdForServer = idForServer,
  530. VideoDeviceSourceType = info.Category == EnumLiveChannelCategory.Main ? EnumVideoDeviceSourceType.Desktop : EnumVideoDeviceSourceType.Camera,
  531. Category = info.Category,
  532. OutputWidth = info.Width,
  533. OutputHeight = info.Height,
  534. };
  535. newInfos.Add(item);
  536. }
  537. if (newInfos.Count() != _currentVideoDeviceInfoList.Count() || needNotifyServer)
  538. {
  539. _currentVideoDeviceInfoList.Clear();
  540. foreach (var info in newInfos)
  541. {
  542. var item = info.Clone() as CPVideoDeviceOutputInfo;
  543. _currentVideoDeviceInfoList.Add(item);
  544. }
  545. _previewManager.UpdateCurrentVideoDeviceInfoList(newInfos.ToList());
  546. }
  547. else
  548. {
  549. if (IsDifferent(newInfos.ToList()) || needNotifyServer)
  550. {
  551. _currentVideoDeviceInfoList.Clear();
  552. foreach (var info in newInfos)
  553. {
  554. var item = info.Clone() as CPVideoDeviceOutputInfo;
  555. _currentVideoDeviceInfoList.Add(item);
  556. }
  557. _previewManager.UpdateCurrentVideoDeviceInfoList(newInfos.ToList());
  558. }
  559. }
  560. }
  561. if (_micDeviceId != micId)
  562. {
  563. _micDeviceId = micId;
  564. _pusherManager.SwitchMic(micId);
  565. }
  566. if (_isMute != isMute)
  567. {
  568. _isMute = isMute;
  569. _pusherManager.SetMute(isMute);
  570. }
  571. var device = infos.FirstOrDefault(x => x.Category == previewLiveChannel);
  572. if (showPreviewImage && device != null)
  573. {
  574. if (device.Id != _oldPreviewCameraId && _previewManager.IsPreviewing)
  575. {
  576. _previewManager.StopPreview(true);
  577. }
  578. _oldPreviewCameraId = device.Id;
  579. _previewManager.StartPreview(device.Id, device.Width, device.Height, device.FrameRate, device.Category);
  580. }
  581. else
  582. {
  583. _previewManager.StopPreview(false);
  584. }
  585. }
  586. var init = false;
  587. var updateEnable = false;
  588. var updateIntervalTime = false;
  589. if (_rainbowImageDetectConfig == null)
  590. {
  591. updateEnable = true;
  592. updateIntervalTime = true;
  593. init = true;
  594. _rainbowImageDetectConfig = rainbowImageDetectConfig;
  595. }
  596. else
  597. {
  598. if (_rainbowImageDetectConfig.IsDetectRainbowImage != rainbowImageDetectConfig.IsDetectRainbowImage)
  599. {
  600. _rainbowImageDetectConfig.IsDetectRainbowImage = rainbowImageDetectConfig.IsDetectRainbowImage;
  601. updateEnable = true;
  602. }
  603. if (_rainbowImageDetectConfig.BeforeDisableIntervalTime != rainbowImageDetectConfig.BeforeDisableIntervalTime)
  604. {
  605. _rainbowImageDetectConfig.BeforeDisableIntervalTime = rainbowImageDetectConfig.BeforeDisableIntervalTime;
  606. updateIntervalTime = true;
  607. }
  608. if (_rainbowImageDetectConfig.BeforeEnableIntervalTime != rainbowImageDetectConfig.BeforeEnableIntervalTime)
  609. {
  610. _rainbowImageDetectConfig.BeforeEnableIntervalTime = rainbowImageDetectConfig.BeforeEnableIntervalTime;
  611. updateIntervalTime = true;
  612. }
  613. if (_rainbowImageDetectConfig.AfterEnableIntervalTime != rainbowImageDetectConfig.AfterEnableIntervalTime)
  614. {
  615. _rainbowImageDetectConfig.AfterEnableIntervalTime = rainbowImageDetectConfig.AfterEnableIntervalTime;
  616. updateIntervalTime = true;
  617. }
  618. if (_rainbowImageDetectConfig.ScanIntervalTime != rainbowImageDetectConfig.ScanIntervalTime)
  619. {
  620. _rainbowImageDetectConfig.ScanIntervalTime = rainbowImageDetectConfig.ScanIntervalTime;
  621. updateIntervalTime = true;
  622. }
  623. }
  624. UpdateRainbowImageDetectConfig(updateEnable, init, updateIntervalTime);
  625. }
  626. private void UpdateRainbowImageDetectConfig(bool updateEnable, bool init, bool updateIntervalTime)
  627. {
  628. if (init)
  629. {
  630. CrossPlatformHelper.Instance.DriverHelper.InitializeCaptureCard(_rainbowImageDetectConfig.CaptureCardList);
  631. }
  632. if (updateIntervalTime)
  633. {
  634. RainbowImageDetector.Instance.SetIntervalTime(_rainbowImageDetectConfig.BeforeDisableIntervalTime, _rainbowImageDetectConfig.BeforeEnableIntervalTime, _rainbowImageDetectConfig.AfterEnableIntervalTime, _rainbowImageDetectConfig.ScanIntervalTime);
  635. }
  636. if (updateEnable)
  637. {
  638. if (_rainbowImageDetectConfig.IsDetectRainbowImage)
  639. {
  640. RainbowImageDetector.Instance.StartDetect();
  641. }
  642. else
  643. {
  644. RainbowImageDetector.Instance.StopDetect();
  645. }
  646. }
  647. }
  648. public void Dispose()
  649. {
  650. DoDispose();
  651. GC.SuppressFinalize(this);
  652. }
  653. private List<CPVideoDeviceOutputInfo> GetVideoDeviceInfos(bool liveVideoEnabled, bool cameraEnabled, string cameraId)
  654. {
  655. var videoInfoList = new List<CPVideoDeviceOutputInfo>();
  656. if (liveVideoEnabled)
  657. {
  658. videoInfoList.Add(new CPVideoDeviceOutputInfo
  659. {
  660. Category = EnumLiveChannelCategory.Main,
  661. VideoDeviceId = _uniqueId,
  662. IdForServer = _uniqueId,
  663. VideoDeviceSourceType = EnumVideoDeviceSourceType.Desktop,
  664. OutputHeight = _usScreenHeight,
  665. OutputWidth = _usScreenWidth,
  666. });
  667. if (cameraEnabled)
  668. {
  669. videoInfoList.Add(new CPVideoDeviceOutputInfo
  670. {
  671. Category = EnumLiveChannelCategory.Auxiliary1,
  672. IdForServer = "Camera1",
  673. VideoDeviceId = cameraId,
  674. VideoDeviceSourceType = EnumVideoDeviceSourceType.Camera,
  675. OutputHeight = 480,
  676. OutputWidth = 640,
  677. });
  678. }
  679. }
  680. return videoInfoList;
  681. }
  682. private IExtendedData CreateExtentedData(EnumLiveProtocol protocol, StartLiveToDeviceNotification notification, string micId, bool isMute)
  683. {
  684. if (protocol == EnumLiveProtocol.RTC)
  685. {
  686. var rtcExtentedData = new RtcExtendedData(null, micId, isMute);
  687. rtcExtentedData.AppId = notification.AppId;
  688. rtcExtentedData.RoomId = notification.RoomNo;
  689. if (notification.MergedChannel)
  690. {
  691. if (notification.MergedVideoOutputHeight == 720 && notification.MergedVideoOutputWidth == 1280)
  692. {
  693. rtcExtentedData.IsMergeChannel = notification.MergedChannel;
  694. rtcExtentedData.MergeType = EnumMergeType.Merge1280X720;
  695. }
  696. else
  697. {
  698. rtcExtentedData.IsMergeChannel = notification.MergedChannel;
  699. rtcExtentedData.MergeType = EnumMergeType.Merge1920X1080;
  700. }
  701. }
  702. else
  703. {
  704. rtcExtentedData.IsMergeChannel = notification.MergedChannel;
  705. rtcExtentedData.MergeType = EnumMergeType.None;
  706. }
  707. int cameraNo = 0;
  708. if (notification.VideoDeviceOutputList != null && notification.VideoDeviceOutputList.Count > 0)
  709. {
  710. for (int i = 0; i < notification.VideoDeviceOutputList.Count(); i++)
  711. {
  712. EnumLiveChannelCategory enumLiveChannelCategory;
  713. var userId = notification.VideoDeviceOutputList[i].VideoDeviceId;
  714. var userSign = notification.VideoDeviceOutputList[i].VideoDeviceSign;
  715. if (notification.VideoDeviceOutputList[i].VideoDeviceSourceType == VideoDeviceSourceTypeEnum.Desktop)
  716. {
  717. enumLiveChannelCategory = EnumLiveChannelCategory.Main;
  718. }
  719. else
  720. {
  721. switch (cameraNo)
  722. {
  723. case 0:
  724. enumLiveChannelCategory = EnumLiveChannelCategory.Auxiliary1;
  725. cameraNo++;
  726. break;
  727. case 1:
  728. enumLiveChannelCategory = EnumLiveChannelCategory.Auxiliary2;
  729. cameraNo++;
  730. break;
  731. case 2:
  732. enumLiveChannelCategory = EnumLiveChannelCategory.Auxiliary3;
  733. cameraNo++;
  734. break;
  735. default:
  736. continue;
  737. }
  738. }
  739. var width = notification.VideoDeviceOutputList[i].OutputWidth;
  740. var height = notification.VideoDeviceOutputList[i].OutputHeight;
  741. var fps = notification.VideoDeviceOutputList[i].VideoFps;
  742. var bitrate = notification.VideoDeviceOutputList[i].VideoBitrate;
  743. var minBitrate = notification.VideoDeviceOutputList[i].MinVideoBitrate;
  744. rtcExtentedData.UserInfos.Add(new RtcUserInfo(enumLiveChannelCategory, userId, userSign, width, height, fps, bitrate, minBitrate));
  745. }
  746. }
  747. return rtcExtentedData;
  748. }
  749. else if (protocol == EnumLiveProtocol.Rtmp)
  750. {
  751. var rtmpExtendedData = new RtmpExtendedData(null, micId, isMute);
  752. if (notification.MergedChannel)
  753. {
  754. if (notification.MergedVideoOutputHeight == 720 && notification.MergedVideoOutputWidth == 1280)
  755. {
  756. rtmpExtendedData.IsMergeChannel = notification.MergedChannel;
  757. rtmpExtendedData.MergeType = EnumMergeType.Merge1280X720;
  758. }
  759. else
  760. {
  761. rtmpExtendedData.IsMergeChannel = notification.MergedChannel;
  762. rtmpExtendedData.MergeType = EnumMergeType.Merge1920X1080;
  763. }
  764. }
  765. else
  766. {
  767. rtmpExtendedData.IsMergeChannel = notification.MergedChannel;
  768. rtmpExtendedData.MergeType = EnumMergeType.None;
  769. }
  770. int cameraNo = 0;
  771. if (notification.VideoDeviceOutputList != null && notification.VideoDeviceOutputList.Count > 0)
  772. {
  773. for (int i = 0; i < notification.VideoDeviceOutputList.Count(); i++)
  774. {
  775. EnumLiveChannelCategory enumLiveChannelCategory;
  776. if (notification.VideoDeviceOutputList[i].LiveData == null)
  777. {
  778. Logger.WriteLineError($"{notification.VideoDeviceOutputList[i].VideoDeviceId}'s RtmpPushUrl is null");
  779. }
  780. var pushUrl = notification.VideoDeviceOutputList[i].LiveData?.RtmpPushUrl;
  781. if (notification.VideoDeviceOutputList[i].VideoDeviceSourceType == VideoDeviceSourceTypeEnum.Desktop)
  782. {
  783. enumLiveChannelCategory = EnumLiveChannelCategory.Main;
  784. }
  785. else
  786. {
  787. switch (cameraNo)
  788. {
  789. case 0:
  790. enumLiveChannelCategory = EnumLiveChannelCategory.Auxiliary1;
  791. cameraNo++;
  792. break;
  793. case 1:
  794. enumLiveChannelCategory = EnumLiveChannelCategory.Auxiliary2;
  795. cameraNo++;
  796. break;
  797. case 2:
  798. enumLiveChannelCategory = EnumLiveChannelCategory.Auxiliary3;
  799. cameraNo++;
  800. break;
  801. default:
  802. continue;
  803. }
  804. }
  805. var width = notification.VideoDeviceOutputList[i].OutputWidth;
  806. var height = notification.VideoDeviceOutputList[i].OutputHeight; ;
  807. rtmpExtendedData.UserInfos.Add(new RtmpUserInfo(enumLiveChannelCategory, pushUrl, width, height));
  808. }
  809. }
  810. return rtmpExtendedData;
  811. }
  812. return null;
  813. }
  814. /// <summary>
  815. /// 获取品牌列表
  816. /// </summary>
  817. /// <returns></returns>
  818. public List<string> GetBrandList()
  819. {
  820. return _pusherManager?.GetBrandList();
  821. }
  822. /// <summary>
  823. /// 获取型号列表
  824. /// </summary>
  825. /// <param name="brand"></param>
  826. /// <param name="model"></param>
  827. /// <returns></returns>
  828. public List<string> GetModelList(string brand)
  829. {
  830. return _pusherManager?.GetModelList(brand);
  831. }
  832. /// <summary>
  833. /// 获取推荐分辨率
  834. /// </summary>
  835. /// <param name="brand"></param>
  836. /// <param name="model"></param>
  837. /// <returns></returns>
  838. public DeviceRecommandResolution GetRecommandResolution(string brand, string model)
  839. {
  840. return _pusherManager?.GetRecommandResolution(brand, model);
  841. }
  842. private bool IsDifferent(List<CPVideoDeviceOutputInfo> newVideoDeviceInfos)
  843. {
  844. for (int i = 0; i < newVideoDeviceInfos.Count(); i++)
  845. {
  846. if (newVideoDeviceInfos[i].ToString() != _currentVideoDeviceInfoList[i].ToString())
  847. {
  848. return true;
  849. }
  850. }
  851. return false;
  852. }
  853. private bool IsDifferent(List<VideoDeviceOutputInfoDTO> newVideoDeviceInfos)
  854. {
  855. for (int i = 0; i < newVideoDeviceInfos.Count(); i++)
  856. {
  857. if (newVideoDeviceInfos[i].ToString() != _currentOutputVideoInfoList[i].ToString())
  858. {
  859. return true;
  860. }
  861. }
  862. return false;
  863. }
  864. public void ChangeRealTimeCaptureSetting(bool isStart)
  865. {
  866. LiveVideoStatusChecker.Instance.IsRealTimeCapturing = isStart;
  867. _previewManager.ChangeRealTimeCaptureSetting(isStart);
  868. }
  869. public void CaptureCurrentImage()
  870. {
  871. _realtimeCaptureManager?.CaptureCurrentImage();
  872. }
  873. public void StartRecordVideo()
  874. {
  875. _realtimeCaptureManager?.StartRecordVideo();
  876. }
  877. public void StopRecordVideo(bool isTimeOut)
  878. {
  879. _realtimeCaptureManager?.StopRecordVideo(isTimeOut);
  880. }
  881. }
  882. }