LiveVideoPusherManager.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. using System.Threading;
  6. using Vinno.FIS.TRTCClient.Common.Enum;
  7. using Vinno.IUS.Common.Log;
  8. using Vinno.IUS.Common.Network.Leaf;
  9. using Vinno.IUS.Common.Network.Transfer;
  10. using Vinno.vCloud.FIS.CrossPlatform.Common;
  11. using Vinno.vCloud.FIS.CrossPlatform.Common.LiveVideo;
  12. using Vinno.vCloud.Protocol.Infrastructures;
  13. using Vinno.vCloud.Protocol.Messages.Client;
  14. using Vinno.vCloud.Protocol.Messages.Client.Live;
  15. using Vinno.vCloud.Protocol.Messages.Live;
  16. namespace Vinno.vCloud.Common.FIS.LiveVideos
  17. {
  18. internal class LiveVideoPusherManager : ILiveVideoPusherManager
  19. {
  20. private readonly string _terminalId;
  21. private readonly string _terminalName;
  22. private readonly ManualResetEvent _timingRefreshManualResetEvent = new ManualResetEvent(false);
  23. private readonly ClientLeaf _leaf;
  24. private bool _disposed;
  25. private EnumPusherType _currentPushType;
  26. private SonopostLiveVideoPusher _liveVideoPusher;
  27. private readonly List<CPVideoDeviceInfo> _currentVideoDeviceInfoList;
  28. public bool IsPushing => _liveVideoPusher?.IsPushing ?? false;
  29. public EnumPusherType CurrentPushType => _currentPushType;
  30. public event EventHandler<ImageFrameData> PreviewImageReceived;
  31. public event EventHandler<PusherState> PusherStateChanged;
  32. public LiveVideoPusherManager(string terminalId, string terminalName, ClientLeaf leaf)
  33. {
  34. _terminalId = terminalId;
  35. _terminalName = terminalName;
  36. _leaf = leaf;
  37. _currentPushType = EnumPusherType.RtcMerge;
  38. _currentVideoDeviceInfoList = new List<CPVideoDeviceInfo>();
  39. _liveVideoPusher = new SonopostLiveVideoPusher(leaf, terminalId, terminalName);
  40. _liveVideoPusher.PusherStateChanged += OnPusherStateChanegd;
  41. Init();
  42. }
  43. private void Init()
  44. {
  45. RegisterPusherCreations();
  46. InitCurrentPusherType();
  47. }
  48. private void RegisterPusherCreations()
  49. {
  50. if (_liveVideoPusher != null)
  51. {
  52. _liveVideoPusher.RegisterPusher(EnumPusherType.RtmpMerge, () => CrossPlatformHelper.Instance.LiveVideoPusherCreatorForSonopost.CreateRTMPMergePusher());
  53. _liveVideoPusher.RegisterPusher(EnumPusherType.RtmpMulti, () => CrossPlatformHelper.Instance.LiveVideoPusherCreatorForSonopost.CreateRTMPMultiPusher());
  54. _liveVideoPusher.RegisterPusher(EnumPusherType.RtmpSingle, () => CrossPlatformHelper.Instance.LiveVideoPusherCreatorForSonopost.CreateRTMPSinglePusher());
  55. _liveVideoPusher.RegisterPusher(EnumPusherType.RtcMerge, () => CrossPlatformHelper.Instance.LiveVideoPusherCreatorForSonopost.CreateRTCMergePusher());
  56. _liveVideoPusher.RegisterPusher(EnumPusherType.RtcMulti, () => CrossPlatformHelper.Instance.LiveVideoPusherCreatorForSonopost.CreateRTCMultiPusher());
  57. _liveVideoPusher.RegisterPusher(EnumPusherType.RtcSingle, () => CrossPlatformHelper.Instance.LiveVideoPusherCreatorForSonopost.CreateRTCSinglePusher());
  58. }
  59. }
  60. public void LiveStateChanged(LiveEventArgs liveEventArgs)
  61. {
  62. _liveVideoPusher?.LiveStateChanged(liveEventArgs);
  63. }
  64. public void PushModeChanged(LiveDataMode pushLiveMode, LiveProtocol liveProtocol)
  65. {
  66. SetCurrentPusherType(pushLiveMode, liveProtocol);
  67. UpdateDeviceResoution(_currentVideoDeviceInfoList);
  68. //RestartPusher();
  69. }
  70. private void SetCurrentPusherType(LiveDataMode pushLiveMode, LiveProtocol liveProtocol)
  71. {
  72. if (liveProtocol == LiveProtocol.RTC)
  73. {
  74. if (pushLiveMode == LiveDataMode.MergeLive)
  75. {
  76. if (_currentVideoDeviceInfoList.Count <= 1)
  77. {
  78. _currentPushType = EnumPusherType.RtcSingle;
  79. }
  80. else
  81. {
  82. _currentPushType = EnumPusherType.RtcMerge;
  83. }
  84. }
  85. else if (pushLiveMode == LiveDataMode.OnlyLive)
  86. {
  87. _currentPushType = EnumPusherType.RtcMulti;
  88. }
  89. else
  90. {
  91. throw new Exception($"Live Video Pusher Manager SetCurrentPusherType Error:Unknown Pusher Type:{pushLiveMode}|{liveProtocol}");
  92. }
  93. }
  94. else if (liveProtocol == LiveProtocol.Rtmp)
  95. {
  96. if (pushLiveMode == LiveDataMode.MergeLive)
  97. {
  98. if (_currentVideoDeviceInfoList.Count <= 1)
  99. {
  100. _currentPushType = EnumPusherType.RtmpSingle;
  101. }
  102. else
  103. {
  104. _currentPushType = EnumPusherType.RtmpMerge;
  105. }
  106. }
  107. else if (pushLiveMode == LiveDataMode.OnlyLive)
  108. {
  109. _currentPushType = EnumPusherType.RtmpMulti;
  110. }
  111. else
  112. {
  113. throw new Exception($"Live Video Pusher Manager SetCurrentPusherType Error:Unknown Pusher Type:{pushLiveMode}|{liveProtocol}");
  114. }
  115. }
  116. else
  117. {
  118. throw new Exception($"Live Video Pusher Manager SetCurrentPusherType Error:Unknown Pusher Type:{pushLiveMode}|{liveProtocol}");
  119. }
  120. Logger.WriteLineInfo($"Live VideoManager Current Push Type:{_currentPushType}");
  121. }
  122. public void RestartPusher()
  123. {
  124. _liveVideoPusher?.ReStartPusher();
  125. }
  126. private void OnPusherStateChanegd(object sender, PusherState e)
  127. {
  128. PusherStateChanged?.Invoke(this, e);
  129. }
  130. public void SetIsPaused(bool isPaused)
  131. {
  132. _liveVideoPusher?.SetIsPaused(isPaused);
  133. }
  134. private void UpdateDeviceResoution(List<CPVideoDeviceInfo> videoDeviceInfos)
  135. {
  136. try
  137. {
  138. Logger.WriteLineInfo("LiveVideo PusherManager UpdateDeviceResoution");
  139. var list = new List<CPVideoDeviceInfo>();
  140. if (videoDeviceInfos != null)
  141. {
  142. foreach (var device in videoDeviceInfos)
  143. {
  144. var item = device.Clone() as CPVideoDeviceInfo;
  145. var cability = CrossPlatformHelper.Instance.HardwareDetector.GetMaxResolutionUnderTheSpecial(item.Id, item.Width, item.Height, _currentPushType, device.Category);
  146. if (cability != null)
  147. {
  148. item.Width = cability.Width;
  149. item.Height = cability.Height;
  150. }
  151. list.Add(item);
  152. }
  153. }
  154. UpdateLiveChannelInfos(list);
  155. _liveVideoPusher?.StopPusher();
  156. }
  157. catch (Exception ex)
  158. {
  159. Logger.WriteLineError($"UpdateDeviceResoution Error:{ex}");
  160. }
  161. }
  162. public void SetMute(bool isMute)
  163. {
  164. _liveVideoPusher?.SetMute(isMute);
  165. }
  166. public List<string> GetBrandList()
  167. {
  168. var brandList = new List<string>();
  169. using (var request = MessagePool.GetMessage<GetPushLiveConfigRequest>())
  170. {
  171. request.TerminalId = _terminalId;
  172. var resultMessage = _leaf.Send(request);
  173. var result = GetPushLiveConfigResult.Convert(resultMessage);
  174. if (result != null)
  175. {
  176. foreach (var brand in result.PushLiveConfigs)
  177. {
  178. brandList.Add(brand.Brand);
  179. }
  180. }
  181. }
  182. return brandList;
  183. }
  184. public List<string> GetModelList(string brand)
  185. {
  186. if (string.IsNullOrWhiteSpace(brand))
  187. {
  188. Logger.WriteLineError($"LiveVideoPusherManager GetModelList Error:brand is null");
  189. return new List<string>();
  190. }
  191. var modelList = new List<string>();
  192. using (var request = MessagePool.GetMessage<GetPushLiveConfigRequest>())
  193. {
  194. request.TerminalId = _terminalId;
  195. var resultMessage = _leaf.Send(request);
  196. var result = GetPushLiveConfigResult.Convert(resultMessage);
  197. if (result != null)
  198. {
  199. var selectedBrand = result.PushLiveConfigs.FirstOrDefault(x => x.Brand == brand);
  200. if (selectedBrand != null && selectedBrand.PushLiveModelConfigs != null)
  201. {
  202. foreach (var model in selectedBrand.PushLiveModelConfigs)
  203. {
  204. modelList.Add(model.Model);
  205. }
  206. }
  207. }
  208. }
  209. return modelList;
  210. }
  211. public DeviceRecommandResolution GetRecommandResolution(string brand, string model)
  212. {
  213. try
  214. {
  215. if (string.IsNullOrWhiteSpace(brand))
  216. {
  217. Logger.WriteLineError($"LiveVideoPusherManager GetRecommandResolution Error:brand is null");
  218. return null;
  219. }
  220. if (string.IsNullOrWhiteSpace(model))
  221. {
  222. Logger.WriteLineError($"LiveVideoPusherManager GetRecommandResolution Error:model is null");
  223. return null;
  224. }
  225. using (var request = MessagePool.GetMessage<GetPushLiveConfigRequest>())
  226. {
  227. request.TerminalId = _terminalId;
  228. var resultMessage = _leaf.Send(request);
  229. var result = GetPushLiveConfigResult.Convert(resultMessage);
  230. if (result != null)
  231. {
  232. var selectedBrand = result.PushLiveConfigs.FirstOrDefault(x => x.Brand == brand);
  233. if (selectedBrand != null && selectedBrand.PushLiveModelConfigs != null)
  234. {
  235. var selectedModel = selectedBrand.PushLiveModelConfigs.FirstOrDefault(x => x.Model == model);
  236. if (selectedModel != null)
  237. {
  238. return new DeviceRecommandResolution(brand, null, model, selectedModel.RecommendWidth, selectedModel.RecommendHeight);
  239. }
  240. else
  241. {
  242. Logger.WriteLineError($"LiveVideoPusherManager GetRecommandResolution Error:Model Didn't find RecommandResolution");
  243. return null;
  244. }
  245. }
  246. else
  247. {
  248. Logger.WriteLineError($"LiveVideoPusherManager GetRecommandResolution Error:Brand Didn't find");
  249. return null;
  250. }
  251. }
  252. }
  253. return null;
  254. }
  255. catch (Exception ex)
  256. {
  257. Logger.WriteLineError($"LiveVideoPusherManager GetRecommandResolution Error:{ex}");
  258. return null;
  259. }
  260. }
  261. private void InitCurrentPusherType()
  262. {
  263. var brandList = new List<DeviceBrandInfo>();
  264. using (var request = MessagePool.GetMessage<GetPushLiveConfigRequest>())
  265. {
  266. request.TerminalId = _terminalId;
  267. var resultMessage = _leaf.Send(request);
  268. var result = GetPushLiveConfigResult.Convert(resultMessage);
  269. if (result != null)
  270. {
  271. SetCurrentPusherType(result.PushLiveMode, result.LiveProtocol);
  272. }
  273. }
  274. }
  275. private void UpdateLiveChannelInfos(IEnumerable<CPVideoDeviceInfo> infos)
  276. {
  277. var version = Assembly.GetExecutingAssembly().GetName().Version;
  278. using (var request = MessagePool.GetMessage<NewUpdateTerminalMultiRelatedInfoRequest>())
  279. {
  280. request.TerminalName = _terminalName;
  281. request.Version = version.ToString();
  282. var terminalChannels = new List<TerminalChannelInfoMessage>();
  283. foreach (var info in infos)
  284. {
  285. Logger.WriteLineInfo($"Update Channel Info:{info}");
  286. var channelMessage = new TerminalChannelInfoMessage();
  287. channelMessage.Width = info.Width;
  288. channelMessage.Height = info.Height;
  289. channelMessage.Name = info.Category.ToString();
  290. channelMessage.Enable = info.IsEnable && info.IsAvailable;
  291. channelMessage.Fps = info.FrameRate;
  292. channelMessage.Bitrate = info.Bitrate;
  293. channelMessage.Brand = info.Brand;
  294. channelMessage.ModelId = info.ModelId;
  295. channelMessage.Category = (LiveChannelCategory)info.Category;
  296. terminalChannels.Add(channelMessage);
  297. }
  298. request.TerminalChannels = terminalChannels;
  299. var result = _leaf.Send(request);
  300. var resultMsg = ResultMessage.Convert(result);
  301. string channelInfos = string.Empty;
  302. if (infos != null)
  303. {
  304. foreach (var info in infos)
  305. {
  306. channelInfos += info.ToString();
  307. }
  308. }
  309. if (resultMsg == CCR.OK)
  310. {
  311. Logger.WriteLineInfo($"UpdateLiveChannelInfos Success! {channelInfos}");
  312. }
  313. else
  314. {
  315. Logger.WriteLineError($"UpdateLiveChannelInfos Fail! {channelInfos}");
  316. }
  317. }
  318. }
  319. public void StartPreview(EnumLiveChannelCategory category)
  320. {
  321. if (_liveVideoPusher?.LivePusher is PusherBase pusher)
  322. {
  323. pusher.PreviewImageReceived += OnPreviewImageReceived;
  324. pusher.StartPreview(category);
  325. }
  326. }
  327. public void StopPreview()
  328. {
  329. if (_liveVideoPusher?.LivePusher is PusherBase pusher)
  330. {
  331. pusher.PreviewImageReceived -= OnPreviewImageReceived;
  332. pusher.StopPreview();
  333. }
  334. }
  335. private void OnPreviewImageReceived(object sender, ImageFrameData e)
  336. {
  337. PreviewImageReceived?.Invoke(sender, e);
  338. }
  339. public void Dispose()
  340. {
  341. if (!_disposed)
  342. {
  343. DoDispose();
  344. GC.SuppressFinalize(this);
  345. _disposed = true;
  346. }
  347. }
  348. public void DoDispose()
  349. {
  350. _timingRefreshManualResetEvent.Set();
  351. StopPreview();
  352. if (_liveVideoPusher != null)
  353. {
  354. _liveVideoPusher.PusherStateChanged -= OnPusherStateChanegd;
  355. _liveVideoPusher.Dispose();
  356. _liveVideoPusher = null;
  357. }
  358. }
  359. public void UpdateCurrentVideoDeviceInfoList(List<CPVideoDeviceInfo> infos)
  360. {
  361. _currentVideoDeviceInfoList.Clear();
  362. if (infos != null)
  363. {
  364. foreach (var info in infos)
  365. {
  366. var item = info.Clone() as CPVideoDeviceInfo;
  367. _currentVideoDeviceInfoList.Add(item);
  368. }
  369. }
  370. _liveVideoPusher.UpdateCurrentVideoDeviceInfoList(infos);
  371. if (_currentPushType == EnumPusherType.RtcSingle || _currentPushType == EnumPusherType.RtcMerge)
  372. {
  373. PushModeChanged(LiveDataMode.MergeLive, LiveProtocol.RTC);
  374. }
  375. else if (_currentPushType == EnumPusherType.RtcMulti)
  376. {
  377. PushModeChanged(LiveDataMode.OnlyLive, LiveProtocol.RTC);
  378. }
  379. else if (_currentPushType == EnumPusherType.RtmpSingle || _currentPushType == EnumPusherType.RtmpMerge)
  380. {
  381. PushModeChanged(LiveDataMode.MergeLive, LiveProtocol.Rtmp);
  382. }
  383. else if (_currentPushType == EnumPusherType.RtmpMulti)
  384. {
  385. PushModeChanged(LiveDataMode.OnlyLive, LiveProtocol.Rtmp);
  386. }
  387. }
  388. ~LiveVideoPusherManager()
  389. {
  390. Dispose();
  391. }
  392. }
  393. }