TRTCPusher.cs 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937
  1. using AForge.Video.DirectShow;
  2. using ManageLiteAV;
  3. using System;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Threading;
  7. using Vinno.FIS.TRTCClient.Captures;
  8. using Vinno.FIS.TRTCClient.Common.Enum;
  9. using Vinno.FIS.TRTCClient.Common.Log;
  10. using Vinno.FIS.TRTCClient.Common.Pipe;
  11. using Vinno.FIS.TRTCClient.ImageSender;
  12. namespace Vinno.FIS.TRTCClient
  13. {
  14. internal class TRTCPusher : ITRTCCloudCallback, ITRTCVideoRenderCallback, IDisposable
  15. {
  16. private ITRTCCloud _cloud;
  17. private ITXDeviceManager _deviceManager;
  18. private TRTCVideoFrame _videoFrame;
  19. private CameraImageSenderV2 _imageSender;
  20. private bool _isImageSenderMode;
  21. private bool _isCustomCaptureMode;
  22. private string _deviceId;
  23. private bool _isPushing;
  24. public event EventHandler<VideoFrameArrivedArgs> VideoFrameReceived;
  25. public event EventHandler<TRTCImageFrameData> TRTCImageFrameDataReceived;
  26. private ManualResetEvent _exitResetEvent = new ManualResetEvent(false);
  27. public TRTCPusher(string path, EnumLiveChannelCategory category)
  28. {
  29. _cloud = ITRTCCloud.getTRTCShareInstance();
  30. var logPath = Path.Combine(path, category.ToString());
  31. if (!Directory.Exists(logPath))
  32. {
  33. Directory.CreateDirectory(logPath);
  34. }
  35. _cloud.setLogCompressEnabled(false);
  36. _cloud.setLogLevel(TRTCLogLevel.TRTCLogLevelError);
  37. _cloud.setLogDirPath(logPath);
  38. _cloud.addCallback(this);
  39. _cloud.setLocalVideoRenderCallback(TRTCVideoPixelFormat.TRTCVideoPixelFormat_BGRA32, TRTCVideoBufferType.TRTCVideoBufferType_Buffer, this);
  40. _deviceManager = _cloud.getDeviceManager();
  41. }
  42. public void EnterRoom(TRTCRoomInfo roomInfo)
  43. {
  44. if (roomInfo.IsUSMachineImage)
  45. {
  46. TRTCParams trtcParams = new TRTCParams();
  47. trtcParams.sdkAppId = roomInfo.AppId;
  48. trtcParams.roomId = roomInfo.RoomId;
  49. trtcParams.userId = roomInfo.UserId;
  50. trtcParams.userSig = roomInfo.UserSig;
  51. trtcParams.role = TRTCRoleType.TRTCRoleAnchor;
  52. _cloud.setDefaultStreamRecvMode(false, false);
  53. var resolution = GetResolution(roomInfo.OutputWidth, roomInfo.OutputHeight, true, roomInfo.DeviceId, roomInfo.IsOldServerMode, roomInfo.DeviceWidth, roomInfo.DeviceHeight);
  54. InitVideoParam(resolution, roomInfo.VideoFps, roomInfo.VideoBitrate, roomInfo.MinVideoBitrate);
  55. _cloud.enableCustomVideoCapture(true);//此情况,只有新版,超声机画面的时候满足。旧版超声机不存在分流的情况。
  56. _cloud.setVideoEncoderMirror(false);
  57. var correctMicId = GetCorrectId(HardwareType.Mic, roomInfo.MicDeviceId);
  58. if (!string.IsNullOrEmpty(correctMicId))
  59. {
  60. _deviceManager.setCurrentDevice(TRTCDeviceType.TXMediaDeviceTypeMic, correctMicId);
  61. _cloud.startLocalAudio();//开启本地音频的采集和上行
  62. }
  63. _cloud.muteLocalAudio(roomInfo.IsMute);
  64. _cloud.muteAllRemoteAudio(true);
  65. _cloud.muteAllRemoteVideoStreams(true);
  66. _cloud.enterRoom(ref trtcParams, TRTCAppScene.TRTCAppSceneLIVE);
  67. _isPushing = true;
  68. }
  69. else
  70. {
  71. _deviceId = GetCorrectId(HardwareType.Camera, roomInfo.DeviceId);
  72. if (string.IsNullOrEmpty(_deviceId))
  73. {
  74. Logger.WriteLineError($"Can not get correct device Id:{roomInfo.DeviceId}");
  75. return;
  76. }
  77. TRTCParams trtcParams = new TRTCParams();
  78. trtcParams.sdkAppId = roomInfo.AppId;
  79. trtcParams.roomId = roomInfo.RoomId;
  80. trtcParams.userId = roomInfo.UserId;
  81. trtcParams.userSig = roomInfo.UserSig;
  82. trtcParams.role = TRTCRoleType.TRTCRoleAnchor;
  83. var resolution = GetResolution(roomInfo.OutputWidth, roomInfo.OutputHeight, false, roomInfo.DeviceId, roomInfo.IsOldServerMode, roomInfo.DeviceWidth, roomInfo.DeviceHeight);
  84. InitVideoParam(resolution, roomInfo.VideoFps, roomInfo.VideoBitrate, roomInfo.MinVideoBitrate);
  85. _cloud.setDefaultStreamRecvMode(false, false);
  86. _cloud.setVideoEncoderMirror(false);
  87. var correctMicId = GetCorrectId(HardwareType.Mic, roomInfo.MicDeviceId);
  88. if (!string.IsNullOrEmpty(correctMicId))
  89. {
  90. _deviceManager.setCurrentDevice(TRTCDeviceType.TXMediaDeviceTypeMic, correctMicId);
  91. _cloud.startLocalAudio();//开启本地音频的采集和上行
  92. }
  93. _cloud.muteLocalAudio(roomInfo.IsMute);
  94. _cloud.muteAllRemoteAudio(true);
  95. _cloud.muteAllRemoteVideoStreams(true);
  96. if (_isImageSenderMode)
  97. {
  98. _cloud.enableCustomVideoCapture(true);
  99. _imageSender = GetCameraImageSenderV2(_deviceId, roomInfo.OutputWidth, roomInfo.OutputHeight, roomInfo.Category, roomInfo.IsFillMode, roomInfo.DeviceWidth, roomInfo.DeviceHeight);
  100. _imageSender.VideoFrameDataReceived += OnVideoFrameDataReceived;
  101. _imageSender.PreviewImageFrameDataReceived += OnPreviewImageFrameDataReceived;
  102. _imageSender.Start();
  103. }
  104. else
  105. {
  106. _deviceManager.setCurrentDevice(TRTCDeviceType.TXMediaDeviceTypeCamera, _deviceId);
  107. _cloud.startLocalPreview(IntPtr.Zero);
  108. }
  109. _cloud.enterRoom(ref trtcParams, TRTCAppScene.TRTCAppSceneLIVE);
  110. _isPushing = true;
  111. }
  112. }
  113. private void OnVideoFrameDataReceived(object sender, TRTCVideoFrameData e)
  114. {
  115. SendData((uint)e.Width, (uint)e.Height, e.Data);
  116. }
  117. /// <summary>
  118. /// 发送要推流的数据
  119. /// </summary>
  120. /// <param name="width"></param>
  121. /// <param name="height"></param>
  122. /// <param name="frameBuffer"></param>
  123. public void SendData(uint width, uint height, byte[] frameBuffer)
  124. {
  125. var len = width * height * 3 / 2;
  126. if (_videoFrame == null)
  127. {
  128. _videoFrame = new TRTCVideoFrame();
  129. _videoFrame.videoFormat = TRTCVideoPixelFormat.TRTCVideoPixelFormat_I420;
  130. _videoFrame.bufferType = TRTCVideoBufferType.TRTCVideoBufferType_Buffer;
  131. _videoFrame.data = new byte[len];
  132. _videoFrame.width = width;
  133. _videoFrame.height = height;
  134. _videoFrame.length = len;
  135. _videoFrame.timestamp = 0;
  136. }
  137. _videoFrame.data = frameBuffer;
  138. _cloud?.sendCustomVideoData(_videoFrame);
  139. }
  140. public void ExitRoom()
  141. {
  142. Logger.WriteLineInfo("Exit Room");
  143. _isPushing = false;
  144. _cloud.stopAllRemoteView();
  145. _cloud.stopLocalPreview();
  146. _cloud.stopLocalAudio();
  147. _cloud.muteLocalAudio(true);
  148. _cloud.muteLocalVideo(true);
  149. _exitResetEvent.Reset();
  150. _cloud.exitRoom();
  151. _exitResetEvent.WaitOne(5000);
  152. }
  153. private void InitVideoParam(TRTCVideoResolution resolution, uint fps, uint videoBitrate, uint minVideoBitrate)
  154. {
  155. TRTCVideoEncParam videoEncParams = new TRTCVideoEncParam();
  156. videoEncParams.videoBitrate = videoBitrate;
  157. videoEncParams.minVideoBitrate = minVideoBitrate;
  158. videoEncParams.videoFps = fps;
  159. videoEncParams.videoResolution = resolution;
  160. videoEncParams.resMode = TRTCVideoResolutionMode.TRTCVideoResolutionModeLandscape;
  161. videoEncParams.enableAdjustRes = false;
  162. _cloud.setVideoEncoderParam(ref videoEncParams);
  163. var qosParams = new TRTCNetworkQosParam();
  164. qosParams.preference = TRTCVideoQosPreference.TRTCVideoQosPreferenceClear;
  165. qosParams.controlMode = TRTCQosControlMode.TRTCQosControlModeServer;
  166. _cloud.setNetworkQosParam(ref qosParams);
  167. }
  168. private CameraImageSenderV2 GetCameraImageSenderV2(string id, int width, int height, EnumLiveChannelCategory category, bool isFillMode, int deviceWidth, int deviceHeight)
  169. {
  170. if (width <= 320 && height <= 240)
  171. {
  172. return new Camera320X240SenderV2(id, width, height, category, isFillMode, deviceWidth, deviceHeight);
  173. }
  174. else if (width <= 480 && height <= 360)
  175. {
  176. return new Camera480X360SenderV2(id, width, height, category, isFillMode, deviceWidth, deviceHeight);
  177. }
  178. else if (width <= 640 && height <= 360)
  179. {
  180. return new Camera640X360SenderV2(id, width, height, category, isFillMode, deviceWidth, deviceHeight);
  181. }
  182. else if (width <= 640 && height <= 480)
  183. {
  184. return new Camera640X480SenderV2(id, width, height, category, isFillMode, deviceWidth, deviceHeight);
  185. }
  186. else if (width <= 960 && height <= 544)
  187. {
  188. return new Camera960X540SenderV2(id, width, height, category, isFillMode, deviceWidth, deviceHeight);
  189. }
  190. else if (width <= 960 && height <= 720)
  191. {
  192. return new Camera960X720SenderV2(id, width, height, category, isFillMode, deviceWidth, deviceHeight);
  193. }
  194. else if (width <= 1280 && height <= 720)
  195. {
  196. return new Camera1280X720SenderV2(id, width, height, category, isFillMode, deviceWidth, deviceHeight);
  197. }
  198. else
  199. {
  200. return new Camera1920X1080SenderV2(id, width, height, category, isFillMode, deviceWidth, deviceHeight);
  201. }
  202. }
  203. private TRTCVideoResolution GetResolution(int outputWidth, int outputHeight, bool isUSImage, string deviceId, bool isOldServerMode, int deviceWidth, int deviceHeight)
  204. {
  205. if (isOldServerMode)//老版本因为分辨率是计算好,且该分辨率是支持的。
  206. {
  207. _isImageSenderMode = false;
  208. _isCustomCaptureMode = false;
  209. if (outputWidth <= 120 && outputHeight <= 120)
  210. {
  211. return TRTCVideoResolution.TRTCVideoResolution_120_120;
  212. }
  213. if (outputWidth <= 160 && outputHeight <= 120)
  214. {
  215. return TRTCVideoResolution.TRTCVideoResolution_160_120;
  216. }
  217. if (outputWidth <= 160 && outputHeight <= 160)
  218. {
  219. return TRTCVideoResolution.TRTCVideoResolution_160_160;
  220. }
  221. if (outputWidth <= 256 && outputHeight <= 144)
  222. {
  223. return TRTCVideoResolution.TRTCVideoResolution_256_144;
  224. }
  225. if (outputWidth <= 320 && outputHeight <= 240)
  226. {
  227. return TRTCVideoResolution.TRTCVideoResolution_320_240;
  228. }
  229. if (outputWidth <= 480 && outputHeight <= 360)
  230. {
  231. return TRTCVideoResolution.TRTCVideoResolution_480_360;
  232. }
  233. if (outputWidth <= 480 && outputHeight <= 480)
  234. {
  235. return TRTCVideoResolution.TRTCVideoResolution_480_480;
  236. }
  237. if (outputWidth <= 640 && outputHeight <= 360)
  238. {
  239. return TRTCVideoResolution.TRTCVideoResolution_640_360;
  240. }
  241. if (outputWidth <= 640 && outputHeight <= 480)
  242. {
  243. return TRTCVideoResolution.TRTCVideoResolution_640_480;
  244. }
  245. if (outputWidth <= 960 && outputHeight <= 544)
  246. {
  247. return TRTCVideoResolution.TRTCVideoResolution_960_540;
  248. }
  249. if (outputWidth <= 960 && outputHeight <= 720)
  250. {
  251. return TRTCVideoResolution.TRTCVideoResolution_960_720;
  252. }
  253. if (outputWidth <= 1280 && outputHeight <= 720)
  254. {
  255. return TRTCVideoResolution.TRTCVideoResolution_1280_720;
  256. }
  257. if (outputWidth <= 1920 && outputHeight <= 1080)
  258. {
  259. return TRTCVideoResolution.TRTCVideoResolution_1920_1080;
  260. }
  261. }
  262. else//新版是Server计算的,等比缩放后有些分辨率摄像头是不支持的。
  263. {
  264. if (isUSImage)//超声机画面是由RTCMultiV2填充好传过来,只需直接传给TRTC即可。
  265. {
  266. _isImageSenderMode = false;
  267. _isCustomCaptureMode = true;
  268. if (outputWidth <= 640 && outputHeight <= 480)
  269. {
  270. return TRTCVideoResolution.TRTCVideoResolution_640_480;
  271. }
  272. else if (outputWidth <= 960 && outputHeight <= 544)
  273. {
  274. return TRTCVideoResolution.TRTCVideoResolution_960_540;
  275. }
  276. else if (outputWidth <= 960 && outputHeight <= 720)
  277. {
  278. return TRTCVideoResolution.TRTCVideoResolution_960_720;
  279. }
  280. else if (outputWidth <= 1280 && outputHeight <= 720)
  281. {
  282. return TRTCVideoResolution.TRTCVideoResolution_1280_720;
  283. }
  284. else
  285. {
  286. return TRTCVideoResolution.TRTCVideoResolution_1920_1080;
  287. }
  288. }
  289. else
  290. {
  291. if (SupportResolution(deviceId, outputWidth, outputHeight) && outputHeight == deviceHeight && outputWidth == deviceWidth)//若该分辨率摄像头支持打开
  292. {
  293. if (outputWidth == 120 && outputHeight == 120)//若符合TRTC分辨率,,则直接由TRTC直接打开
  294. {
  295. _isImageSenderMode = false;
  296. _isCustomCaptureMode = false;
  297. return TRTCVideoResolution.TRTCVideoResolution_120_120;
  298. }
  299. else if (outputWidth == 160 && outputHeight == 120)
  300. {
  301. _isImageSenderMode = false;
  302. _isCustomCaptureMode = false;
  303. return TRTCVideoResolution.TRTCVideoResolution_160_120;
  304. }
  305. else if (outputWidth == 160 && outputHeight == 160)
  306. {
  307. _isImageSenderMode = false;
  308. _isCustomCaptureMode = false;
  309. return TRTCVideoResolution.TRTCVideoResolution_160_160;
  310. }
  311. else if (outputWidth == 256 && outputHeight == 144)
  312. {
  313. _isImageSenderMode = false;
  314. _isCustomCaptureMode = false;
  315. return TRTCVideoResolution.TRTCVideoResolution_256_144;
  316. }
  317. else if (outputWidth == 320 && outputHeight == 240)
  318. {
  319. _isImageSenderMode = false;
  320. _isCustomCaptureMode = false;
  321. return TRTCVideoResolution.TRTCVideoResolution_320_240;
  322. }
  323. else if (outputWidth == 480 && outputHeight == 360)
  324. {
  325. _isImageSenderMode = false;
  326. _isCustomCaptureMode = false;
  327. return TRTCVideoResolution.TRTCVideoResolution_480_360;
  328. }
  329. else if (outputWidth == 480 && outputHeight == 480)
  330. {
  331. _isImageSenderMode = false;
  332. _isCustomCaptureMode = false;
  333. return TRTCVideoResolution.TRTCVideoResolution_480_480;
  334. }
  335. else if (outputWidth == 640 && outputHeight == 360)
  336. {
  337. _isImageSenderMode = false;
  338. _isCustomCaptureMode = false;
  339. return TRTCVideoResolution.TRTCVideoResolution_640_360;
  340. }
  341. else if (outputWidth == 640 && outputHeight == 480)
  342. {
  343. _isImageSenderMode = false;
  344. _isCustomCaptureMode = false;
  345. return TRTCVideoResolution.TRTCVideoResolution_640_480;
  346. }
  347. else if (outputWidth == 960 && outputHeight == 544)
  348. {
  349. _isImageSenderMode = false;
  350. _isCustomCaptureMode = false;
  351. return TRTCVideoResolution.TRTCVideoResolution_960_540;
  352. }
  353. else if (outputWidth == 960 && outputHeight == 720)
  354. {
  355. _isImageSenderMode = false;
  356. _isCustomCaptureMode = false;
  357. return TRTCVideoResolution.TRTCVideoResolution_960_720;
  358. }
  359. else if (outputWidth == 1280 && outputHeight == 720)
  360. {
  361. _isImageSenderMode = false;
  362. _isCustomCaptureMode = false;
  363. return TRTCVideoResolution.TRTCVideoResolution_1280_720;
  364. }
  365. else if (outputWidth == 1920 && outputHeight == 1080)
  366. {
  367. _isImageSenderMode = false;
  368. _isCustomCaptureMode = false;
  369. return TRTCVideoResolution.TRTCVideoResolution_1920_1080;
  370. }
  371. else if (outputWidth <= 320 && outputHeight <= 240)//TRTC分辨率不支持,则通过ImageSender传图
  372. {
  373. _isImageSenderMode = true;
  374. _isCustomCaptureMode = true;
  375. return TRTCVideoResolution.TRTCVideoResolution_320_240;
  376. }
  377. else if (outputWidth <= 480 && outputHeight <= 360)
  378. {
  379. _isImageSenderMode = true;
  380. _isCustomCaptureMode = true;
  381. return TRTCVideoResolution.TRTCVideoResolution_480_360;
  382. }
  383. else if (outputWidth <= 640 && outputHeight <= 360)
  384. {
  385. _isImageSenderMode = true;
  386. _isCustomCaptureMode = true;
  387. return TRTCVideoResolution.TRTCVideoResolution_640_360;
  388. }
  389. else if (outputWidth <= 640 && outputHeight <= 480)
  390. {
  391. _isImageSenderMode = true;
  392. _isCustomCaptureMode = true;
  393. return TRTCVideoResolution.TRTCVideoResolution_640_480;
  394. }
  395. else if (outputWidth <= 960 && outputHeight <= 544)
  396. {
  397. _isImageSenderMode = true;
  398. _isCustomCaptureMode = true;
  399. return TRTCVideoResolution.TRTCVideoResolution_960_540;
  400. }
  401. else if (outputWidth <= 960 && outputHeight <= 720)
  402. {
  403. _isImageSenderMode = true;
  404. _isCustomCaptureMode = true;
  405. return TRTCVideoResolution.TRTCVideoResolution_960_720;
  406. }
  407. else if (outputWidth <= 1280 && outputHeight <= 720)
  408. {
  409. _isImageSenderMode = true;
  410. _isCustomCaptureMode = true;
  411. return TRTCVideoResolution.TRTCVideoResolution_1280_720;
  412. }
  413. else if (outputWidth <= 1920 && outputHeight <= 1080)
  414. {
  415. _isImageSenderMode = true;
  416. _isCustomCaptureMode = true;
  417. return TRTCVideoResolution.TRTCVideoResolution_1920_1080;
  418. }
  419. }
  420. else
  421. {
  422. if (outputWidth <= 320 && outputHeight <= 240)//TRTC分辨率不支持,则通过ImageSender传图
  423. {
  424. _isImageSenderMode = true;
  425. _isCustomCaptureMode = true;
  426. return TRTCVideoResolution.TRTCVideoResolution_320_240;
  427. }
  428. else if (outputWidth <= 480 && outputHeight <= 360)
  429. {
  430. _isImageSenderMode = true;
  431. _isCustomCaptureMode = true;
  432. return TRTCVideoResolution.TRTCVideoResolution_480_360;
  433. }
  434. else if (outputWidth <= 640 && outputHeight <= 360)
  435. {
  436. _isImageSenderMode = true;
  437. _isCustomCaptureMode = true;
  438. return TRTCVideoResolution.TRTCVideoResolution_640_360;
  439. }
  440. else if (outputWidth <= 640 && outputHeight <= 480)
  441. {
  442. _isImageSenderMode = true;
  443. _isCustomCaptureMode = true;
  444. return TRTCVideoResolution.TRTCVideoResolution_640_480;
  445. }
  446. else if (outputWidth <= 960 && outputHeight <= 544)
  447. {
  448. _isImageSenderMode = true;
  449. _isCustomCaptureMode = true;
  450. return TRTCVideoResolution.TRTCVideoResolution_960_540;
  451. }
  452. else if (outputWidth <= 960 && outputHeight <= 720)
  453. {
  454. _isImageSenderMode = true;
  455. _isCustomCaptureMode = true;
  456. return TRTCVideoResolution.TRTCVideoResolution_960_720;
  457. }
  458. else if (outputWidth <= 1280 && outputHeight <= 720)
  459. {
  460. _isImageSenderMode = true;
  461. _isCustomCaptureMode = true;
  462. return TRTCVideoResolution.TRTCVideoResolution_1280_720;
  463. }
  464. else if (outputWidth <= 1920 && outputHeight <= 1080)
  465. {
  466. _isImageSenderMode = true;
  467. _isCustomCaptureMode = true;
  468. return TRTCVideoResolution.TRTCVideoResolution_1920_1080;
  469. }
  470. }
  471. }
  472. }
  473. return TRTCVideoResolution.TRTCVideoResolution_640_480;
  474. }
  475. private bool SupportResolution(string deviceId, int width, int height)
  476. {
  477. var videoFilterInfos = new FilterInfoCollection(FilterCategory.VideoInputDevice).OfType<FilterInfo>();
  478. var filterInfo = videoFilterInfos.FirstOrDefault(i => deviceId.Contains(i.MonikerString) || i.MonikerString.Contains(deviceId));
  479. if (filterInfo != null)
  480. {
  481. var videoCaptureDevice = new VideoCaptureDevice(filterInfo.MonikerString);
  482. var capbility = videoCaptureDevice.VideoCapabilities.FirstOrDefault(x => x.FrameSize.Width == width && x.FrameSize.Height == height);
  483. if (capbility != null)
  484. {
  485. Logger.WriteLineInfo($"TRTCPusher SupportResolution True,Id:{deviceId},Width:{width},Height:{height}");
  486. return true;
  487. }
  488. }
  489. Logger.WriteLineInfo($"TRTCPusher SupportResolution False,Id:{deviceId},Width:{width},Height:{height}");
  490. return false;
  491. }
  492. public void onRenderVideoFrame(string userId, TRTCVideoStreamType streamType, TRTCVideoFrame frame)
  493. {
  494. if (!_isImageSenderMode)
  495. {
  496. VideoFrameReceived?.Invoke(this, new VideoFrameArrivedArgs(frame, userId));
  497. }
  498. }
  499. private void OnPreviewImageFrameDataReceived(object sender, TRTCImageFrameData e)
  500. {
  501. if (_isImageSenderMode)
  502. {
  503. TRTCImageFrameDataReceived?.Invoke(this, e);
  504. }
  505. }
  506. /// <summary>
  507. /// Get the Correct Id
  508. /// </summary>
  509. /// <param name="type"></param>
  510. /// <param name="deviceId"></param>
  511. /// <returns></returns>
  512. private string GetCorrectId(HardwareType type, string deviceId)
  513. {
  514. switch (type)
  515. {
  516. case HardwareType.Camera:
  517. var cameraList = _deviceManager.getDevicesList(TRTCDeviceType.TXMediaDeviceTypeCamera);
  518. try
  519. {
  520. var count = cameraList.getCount();
  521. for (uint i = 0; i < count; i++)
  522. {
  523. var id = cameraList.getDevicePID(i);
  524. if (deviceId.Contains(id) || id.Contains(deviceId))
  525. {
  526. return id;
  527. }
  528. }
  529. }
  530. finally
  531. {
  532. cameraList.release();
  533. }
  534. break;
  535. case HardwareType.Mic:
  536. var micList = _deviceManager.getDevicesList(TRTCDeviceType.TXMediaDeviceTypeMic);
  537. try
  538. {
  539. var count = micList.getCount();
  540. for (uint i = 0; i < count; i++)
  541. {
  542. var id = micList.getDevicePID(i);
  543. if (deviceId.Contains(id) || id.Contains(deviceId))
  544. {
  545. return id;
  546. }
  547. }
  548. }
  549. finally
  550. {
  551. micList.release();
  552. }
  553. break;
  554. case HardwareType.Speaker:
  555. var speakerList = _deviceManager.getDevicesList(TRTCDeviceType.TXMediaDeviceTypeSpeaker);
  556. try
  557. {
  558. var count = speakerList.getCount();
  559. for (uint i = 0; i < count; i++)
  560. {
  561. var id = speakerList.getDevicePID(i);
  562. if (deviceId.Contains(id) || id.Contains(deviceId))
  563. {
  564. return id;
  565. }
  566. }
  567. }
  568. finally
  569. {
  570. speakerList.release();
  571. }
  572. break;
  573. }
  574. return string.Empty;
  575. }
  576. public void Dispose()
  577. {
  578. try
  579. {
  580. if (_imageSender != null)
  581. {
  582. _imageSender.VideoFrameDataReceived -= OnVideoFrameDataReceived;
  583. _imageSender.PreviewImageFrameDataReceived -= OnPreviewImageFrameDataReceived;
  584. _imageSender.Stop();
  585. _imageSender = null;
  586. }
  587. ExitRoom();
  588. _cloud.removeCallback(this);
  589. _cloud.setLogCallback(null);
  590. _cloud = null;
  591. ITRTCCloud.destroyTRTCShareInstance();
  592. }
  593. catch (Exception ex)
  594. {
  595. Logger.WriteLineError($"TRTCPusher Dispose Error:{ex}");
  596. }
  597. }
  598. #region callback
  599. public void onAudioEffectFinished(int effectId, int code)
  600. {
  601. // throw new NotImplementedException();
  602. }
  603. public void onCameraDidReady()
  604. {
  605. Logger.WriteLineInfo($"onCameraDidReady");
  606. }
  607. public void onConnectionLost()
  608. {
  609. Logger.WriteLineInfo($"onConnectionLost");
  610. }
  611. public void onConnectionRecovery()
  612. {
  613. Logger.WriteLineInfo($"onConnectionRecovery");
  614. }
  615. public void onConnectOtherRoom(string userId, TXLiteAVError errCode, string errMsg)
  616. {
  617. // throw new NotImplementedException();
  618. }
  619. public void onDeviceChange(string deviceId, TRTCDeviceType type, TRTCDeviceState state)
  620. {
  621. try
  622. {
  623. Logger.WriteLineError($"DeviceChange:{deviceId},type:{type},state:{state}");
  624. if (string.IsNullOrEmpty(_deviceId))
  625. {
  626. return;
  627. }
  628. if (!_isImageSenderMode)
  629. {
  630. if (type == TRTCDeviceType.TXMediaDeviceTypeCamera && (deviceId.Contains(_deviceId) || _deviceId.Contains(deviceId)))
  631. {
  632. if (_isPushing && state == TRTCDeviceState.TRTCDeviceStateRemove)
  633. {
  634. _isPushing = false;
  635. _cloud.stopLocalPreview();
  636. }
  637. else if (!_isPushing && state == TRTCDeviceState.TRTCDeviceStateAdd)
  638. {
  639. _isPushing = true;
  640. _deviceManager.setCurrentDevice(TRTCDeviceType.TXMediaDeviceTypeCamera, _deviceId);
  641. _cloud.startLocalPreview(IntPtr.Zero);
  642. }
  643. }
  644. }
  645. }
  646. catch (Exception ex)
  647. {
  648. Logger.WriteLineError($"onDeviceChange Error:{ex}");
  649. }
  650. }
  651. public void onDisconnectOtherRoom(TXLiteAVError errCode, string errMsg)
  652. {
  653. // throw new NotImplementedException();
  654. }
  655. public void onEnterRoom(int result)
  656. {
  657. Logger.WriteLineInfo($"Enter room :{result}");
  658. }
  659. public void onError(TXLiteAVError errCode, string errMsg, IntPtr arg)
  660. {
  661. Logger.WriteLineError($"onError errCode:{errCode}, msg:{errMsg}, arg:{arg}");
  662. }
  663. public void onExitRoom(int reason)
  664. {
  665. Logger.WriteLineInfo($"Exit room success:{reason}");
  666. _exitResetEvent.Set();
  667. }
  668. public void onFirstAudioFrame(string userId)
  669. {
  670. Logger.WriteLineInfo($"onFirstAudioFrame userId: {userId}");
  671. }
  672. public void onFirstVideoFrame(string userId, TRTCVideoStreamType streamType, int width, int height)
  673. {
  674. Logger.WriteLineInfo($"onFirstVideoFrame userId: {userId}, streamType: {streamType.ToString()}, width:{width}, height:{height}");
  675. }
  676. public void onMicDidReady()
  677. {
  678. Logger.WriteLineInfo($"onMicDidReady");
  679. }
  680. public void onMissCustomCmdMsg(string userId, int cmdId, int errCode, int missed)
  681. {
  682. // throw new NotImplementedException();
  683. }
  684. public void onNetworkQuality(TRTCQualityInfo localQuality, TRTCQualityInfo[] remoteQuality, uint remoteQualityCount)
  685. {
  686. // throw new NotImplementedException();
  687. }
  688. public void onPlayBGMBegin(TXLiteAVError errCode)
  689. {
  690. // throw new NotImplementedException();
  691. }
  692. public void onPlayBGMComplete(TXLiteAVError errCode)
  693. {
  694. // throw new NotImplementedException();
  695. }
  696. public void onPlayBGMProgress(uint progressMS, uint durationMS)
  697. {
  698. // throw new NotImplementedException();
  699. }
  700. public void onRecvCustomCmdMsg(string userId, int cmdID, uint seq, byte[] msg, uint msgSize)
  701. {
  702. // throw new NotImplementedException();
  703. }
  704. public void onRecvSEIMsg(string userId, byte[] message, uint msgSize)
  705. {
  706. // throw new NotImplementedException();
  707. }
  708. public void onRemoteUserEnterRoom(string userId)
  709. {
  710. // throw new NotImplementedException();
  711. }
  712. public void onRemoteUserLeaveRoom(string userId, int reason)
  713. {
  714. // throw new NotImplementedException();
  715. }
  716. public void onScreenCaptureCovered()
  717. {
  718. // throw new NotImplementedException();
  719. }
  720. public void onScreenCapturePaused(int reason)
  721. {
  722. // throw new NotImplementedException();
  723. }
  724. public void onScreenCaptureResumed(int reason)
  725. {
  726. // throw new NotImplementedException();
  727. }
  728. public void onScreenCaptureStarted()
  729. {
  730. // throw new NotImplementedException();
  731. }
  732. public void onScreenCaptureStoped(int reason)
  733. {
  734. // throw new NotImplementedException();
  735. }
  736. public void onSendFirstLocalAudioFrame()
  737. {
  738. // throw new NotImplementedException();
  739. }
  740. public void onSendFirstLocalVideoFrame(TRTCVideoStreamType streamType)
  741. {
  742. // throw new NotImplementedException();
  743. }
  744. public void onSetMixTranscodingConfig(int errCode, string errMsg)
  745. {
  746. // throw new NotImplementedException();
  747. }
  748. public void onSpeedTest(TRTCSpeedTestResult currentResult, uint finishedCount, uint totalCount)
  749. {
  750. // throw new NotImplementedException();
  751. }
  752. public void onStartPublishCDNStream(int errCode, string errMsg)
  753. {
  754. // throw new NotImplementedException();
  755. }
  756. public void onStartPublishing(int errCode, string errMsg)
  757. {
  758. // throw new NotImplementedException();
  759. }
  760. public void onStatistics(TRTCStatistics statis)
  761. {
  762. // throw new NotImplementedException();
  763. }
  764. public void onStopPublishCDNStream(int errCode, string errMsg)
  765. {
  766. // throw new NotImplementedException();
  767. }
  768. public void onStopPublishing(int errCode, string errMsg)
  769. {
  770. // throw new NotImplementedException();
  771. }
  772. public void onSwitchRole(TXLiteAVError errCode, string errMsg)
  773. {
  774. // throw new NotImplementedException();
  775. }
  776. public void onTestMicVolume(uint volume)
  777. {
  778. // throw new NotImplementedException();
  779. }
  780. public void onTestSpeakerVolume(uint volume)
  781. {
  782. // throw new NotImplementedException();
  783. }
  784. public void onTryToReconnect()
  785. {
  786. // throw new NotImplementedException();
  787. }
  788. public void onUserAudioAvailable(string userId, bool available)
  789. {
  790. // throw new NotImplementedException();
  791. }
  792. public void onUserEnter(string userId)
  793. {
  794. // throw new NotImplementedException();
  795. }
  796. public void onUserExit(string userId, int reason)
  797. {
  798. // throw new NotImplementedException();
  799. }
  800. public void onUserSubStreamAvailable(string userId, bool available)
  801. {
  802. // throw new NotImplementedException();
  803. }
  804. public void onUserVideoAvailable(string userId, bool available)
  805. {
  806. // throw new NotImplementedException();
  807. }
  808. public void onUserVoiceVolume(TRTCVolumeInfo[] userVolumes, uint userVolumesCount, uint totalVolume)
  809. {
  810. // throw new NotImplementedException();
  811. }
  812. public void onWarning(TXLiteAVWarning warningCode, string warningMsg, IntPtr arg)
  813. {
  814. Logger.WriteLineWarn($"onWarning errCode: {warningCode}, msg:{warningMsg}, arg:{arg}");
  815. }
  816. public void onSwitchRoom(TXLiteAVError errCode, string errMsg)
  817. {
  818. // throw new NotImplementedException();
  819. }
  820. public void onAudioDeviceCaptureVolumeChanged(uint volume, bool muted)
  821. {
  822. // throw new NotImplementedException();
  823. }
  824. public void onAudioDevicePlayoutVolumeChanged(uint volume, bool muted)
  825. {
  826. // throw new NotImplementedException();
  827. }
  828. internal void SetMute(bool isMute)
  829. {
  830. if (_cloud != null)
  831. {
  832. _cloud.muteLocalAudio(isMute);
  833. }
  834. }
  835. internal void SwitchMic(string micId)
  836. {
  837. if (_cloud != null)
  838. {
  839. _cloud.stopLocalAudio();
  840. var correctMicId = GetCorrectId(HardwareType.Mic, micId);
  841. if (!string.IsNullOrEmpty(correctMicId))
  842. {
  843. var deviceManager = _cloud.getDeviceManager();
  844. deviceManager.setCurrentDevice(TRTCDeviceType.TXMediaDeviceTypeMic, correctMicId);
  845. _cloud.startLocalAudio();//开启本地音频的采集和上行
  846. }
  847. }
  848. }
  849. #endregion callback
  850. public enum HardwareType
  851. {
  852. Mic,
  853. Camera,
  854. Speaker
  855. }
  856. }
  857. }