using JsonRpcLite.Rpc; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using Vinno.FIS.TRTCClient.Common.Enum; using Vinno.IUS.Common.Log; using Vinno.vCloud.Common.FIS.Helper; using Vinno.vCloud.Common.FIS.Notification; using Vinno.vCloud.FIS.CrossPlatform.Common; using Vinno.vCloud.FIS.CrossPlatform.Common.Enum; using Vinno.vCloud.FIS.CrossPlatform.Common.LiveVideo; using WingInterfaceLibrary.Enum; using WingInterfaceLibrary.Enum.NotificationEnum; using WingInterfaceLibrary.Interface; using WingInterfaceLibrary.LiveConsultation; using WingInterfaceLibrary.Notifications; using WingInterfaceLibrary.Notifications.Consultation; using WingInterfaceLibrary.Notifications.Education; using WingInterfaceLibrary.Notifications.Live; namespace Vinno.vCloud.Common.FIS.LiveVideos { internal class LiveVideoV2 : ILiveVideoV2 { private readonly string _token; private readonly JsonRpcClient _client; private readonly IDeviceService _deviceService; private readonly ILiveConsultationService _liveConsultationService; private readonly IEducationService _educationService; private readonly object _operateLocker = new object(); private readonly object _locker = new object(); private readonly string _uniqueId; private readonly ILiveVideoPusherManagerV2 _pusherManager; private readonly IPreviewManagerV2 _previewManager; private readonly RealTimeCaptureManager _realtimeCaptureManager; private readonly FISWebSocket _websocket; private readonly List _currentVideoDeviceInfoList; private readonly List _currentOutputVideoInfoList; private readonly int _usScreenWidth; private readonly int _usScreenHeight; private bool _isMainLiveVideoDisabled; private string _currentHeartRateCode; private bool _disposed; private bool _liveVideoEnabled; private bool _firstCommit; private string _oldPreviewCameraId; private RainbowImageDetectConfig _rainbowImageDetectConfig; private bool _isPaused; private bool _cameraLiveEnabled; private int _cameraPreviewWidth; private int _cameraPreviewHeight; private byte[] _previewBuffer; private string _cameraId; private string _micDeviceId; private bool _isMute; /// /// Raised when camera Preview Excute /// public event EventHandler PreviewCameraCaptured; /// /// Raised when Camera Preview Image Size Changed /// public event EventHandler CameraPreviewImageSizeChanged; /// /// The event to notificate the US to show or hide the live video out put window /// public event EventHandler LiveNotification; /// /// Raised when capture image generated.(only for new server) /// public event EventHandler CaptureImageGenerated; /// /// Raised when record video generated.(only for new server) /// public event EventHandler RecordVideoGenerated; public LiveVideoV2(string token, string uniqueId, int usScreenWidth, int usScreenHeight, FISWebSocket websocket, JsonRpcClient client, string deviceModel, string deviceType, string softwareVersion) { _token = token; _uniqueId = uniqueId; if (websocket != null) { _websocket = websocket; _websocket.NotificationReceived += OnNotificationReceived; } _client = client; _deviceService = _client?.CreateProxy(); _liveConsultationService = _client?.CreateProxy(); _educationService = _client?.CreateProxy(); _usScreenWidth = usScreenWidth; _usScreenHeight = usScreenHeight; _previewBuffer = new byte[0]; _firstCommit = true; _currentOutputVideoInfoList = new List(); _currentVideoDeviceInfoList = new List(); _pusherManager = new LiveVideoPusherManagerV2(_token, _liveConsultationService, _deviceService, _educationService, _uniqueId, deviceModel, deviceType, softwareVersion); _pusherManager.LiveVideoNotification += OnLiveVideoNotification; _previewManager = new PreviewManagerV2(_pusherManager, _uniqueId); _previewManager.PreviewImageReceived += OnPreviewImageReceived; RainbowImageDetector.Instance.IsPaused += OnIsPaused; if (CommonParameter.Instance.IsSonopost) { _realtimeCaptureManager = new RealTimeCaptureManager(); _realtimeCaptureManager.CaptureImageGenerated += OnCaptureImageGenerated; _realtimeCaptureManager.RecordVideoGenerated += OnRecordVideoGenerated; } } public void ReUploadRestVid() { _realtimeCaptureManager?.ReUploadRestVid(); } private void OnRecordVideoGenerated(object sender, string e) { RecordVideoGenerated?.Invoke(this, e); } private void OnCaptureImageGenerated(object sender, string e) { CaptureImageGenerated?.Invoke(this, e); } private void OnPreviewImageReceived(object sender, ImageFrameData data) { if (data == null) { return; } if (_cameraPreviewHeight != data.Height || _cameraPreviewWidth != data.Width) { _cameraPreviewHeight = data.Height; _cameraPreviewWidth = data.Width; Array.Resize(ref _previewBuffer, data.Size); CameraPreviewImageSizeChanged?.Invoke(this, new ImageSize(_cameraPreviewWidth, _cameraPreviewHeight)); } Marshal.Copy(data.Data, _previewBuffer, 0, data.Size); PreviewCameraCaptured?.Invoke(this, _previewBuffer); } /// /// Speed live test network and auto select good network to server /// /// public bool StartSpeedTest() { bool speedTest = false; if (_pusherManager != null) { speedTest = _pusherManager.StartSpeedTest(); } return speedTest; } private void OnNotificationReceived(object sender, NotificationArgs e) { switch (e.NotificationType) { case NotificationTypeEnum.StartLiveToDeviceNotification: try { Logger.WriteLineInfo($"LiveVideoV2 StartLiveToDeviceNotification Receive"); if (e.Params is StartLiveToDeviceNotification startLiveToDeviceNotification) { HandleStartLiveToDeviceNotification(startLiveToDeviceNotification); } } catch (Exception ex) { Logger.WriteLineError($"LiveVideoV2 Handle StartLiveToDeviceNotification Error:{ex}"); } break; case NotificationTypeEnum.CloseLiveToDeviceNotification: try { Logger.WriteLineInfo($"LiveVideoV2 CloseLiveToDeviceNotification Receive"); HandleCloseLiveToDeviceNotification(); } catch (Exception ex) { Logger.WriteLineError($"LiveVideoV2 Handle CloseLiveToDeviceNotification Error:{ex}"); } break; case NotificationTypeEnum.ModifyDeviceMergedVideoSizeNotification: try { Logger.WriteLineInfo($"LiveVideoV2 ModifyDeviceMergedVideoSizeNotification Receive"); if (e.Params is ModifyDeviceMergedVideoSizeNotification modifyDeviceMergedVideoSizeNotification) { HandleModifyDeviceMergedVideoSizeNotification(modifyDeviceMergedVideoSizeNotification); } } catch (Exception ex) { Logger.WriteLineError($"LiveVideoV2 Handle ModifyDeviceMergedVideoSizeNotification Error:{ex}"); } break; case NotificationTypeEnum.StartConsolutionHeartRateToDeviceNotification: try { Logger.WriteLineInfo($"LiveVideoV2 StartConsolutionHeartRateToDeviceNotification Receive"); if (e.Params is StartConsolutionHeartRateToDeviceNotification startConsolutionHeartRateToDeviceNotification) { HandleStartConsolutionHeartRateToDeviceNotification(startConsolutionHeartRateToDeviceNotification); } } catch (Exception ex) { Logger.WriteLineError($"LiveVideoV2 Handle StartConsolutionHeartRateToDeviceNotification Error:{ex}"); } break; case NotificationTypeEnum.CloseConsolutionHeartRateToDeviceNotification: try { Logger.WriteLineInfo($"LiveVideoV2 CloseConsolutionHeartRateToDeviceNotification Receive"); if (e.Params is CloseConsolutionHeartRateToDeviceNotification closeConsolutionHeartRateToDeviceNotification) { HandleCloseConsolutionHeartRateToDeviceNotification(closeConsolutionHeartRateToDeviceNotification); } } catch (Exception ex) { Logger.WriteLineError($"LiveVideoV2 Handle CloseConsolutionHeartRateToDeviceNotification Error:{ex}"); } break; case NotificationTypeEnum.StartEducationHeartRateToDeviceNotification: try { Logger.WriteLineInfo($"LiveVideoV2 StartEducationHeartRateToDeviceNotification Receive"); if (e.Params is StartEducationHeartRateToDeviceNotification startEducationHeartRateToDeviceNotification) { HandleStartEducationHeartRateToDeviceNotification(startEducationHeartRateToDeviceNotification); } } catch (Exception ex) { Logger.WriteLineError($"LiveVideoV2 Handle StartEducationHeartRateToDeviceNotification Error:{ex}"); } break; case NotificationTypeEnum.CloseCourseHeartRateToDeviceNotification: try { Logger.WriteLineInfo($"LiveVideoV2 CloseCourseHeartRateToDeviceNotification Receive"); if (e.Params is CloseCourseHeartRateToDeviceNotification closeCourseHeartRateToDeviceNotification) { HandleCloseCourseHeartRateToDeviceNotification(closeCourseHeartRateToDeviceNotification); } } catch (Exception ex) { Logger.WriteLineError($"LiveVideoV2 Handle CloseCourseHeartRateToDeviceNotification Error:{ex}"); } break; case NotificationTypeEnum.ChangeConsultationToDeviceNotification: try { Logger.WriteLineInfo($"LiveVideoV2 ChangeConsultationToDeviceNotification Receive"); if (e.Params is ChangeConsultationToDeviceNotification changeConsultationToDeviceNotification) { HandleChangeConsultationToDeviceNotification(changeConsultationToDeviceNotification); } } catch (Exception ex) { Logger.WriteLineError($"LiveVideoV2 Handle ChangeConsultationToDeviceNotification Error:{ex}"); } break; } } private void HandleCloseLiveToDeviceNotification() { lock (_operateLocker) { if (_isPaused) { Logger.WriteLineInfo($"Receive CloseLiveToDeviceNotification,but it is paused,so skipped it."); return; } _currentHeartRateCode = string.Empty; _pusherManager.LiveStateChanged(new LiveEventArgs(false)); } } private void HandleModifyDeviceMergedVideoSizeNotification(ModifyDeviceMergedVideoSizeNotification modifyDeviceMergedVideoSizeNotification) { lock (_operateLocker) { if (vCloudServerConfig.Instance.MergedChannel != modifyDeviceMergedVideoSizeNotification.MergedChannel) { vCloudServerConfig.Instance.MergedChannel = modifyDeviceMergedVideoSizeNotification.MergedChannel; _currentHeartRateCode = string.Empty; _pusherManager.LiveStateChanged(new LiveEventArgs(false)); } else { if (modifyDeviceMergedVideoSizeNotification.VideoDeviceInfos == null) { if (_currentOutputVideoInfoList.Count > 0) { _currentHeartRateCode = string.Empty; _pusherManager.LiveStateChanged(new LiveEventArgs(false)); } } else { if (modifyDeviceMergedVideoSizeNotification.VideoDeviceInfos.Count != _currentOutputVideoInfoList.Count) { _currentHeartRateCode = string.Empty; _pusherManager.LiveStateChanged(new LiveEventArgs(false)); } else { var deviceInfos = new List(); foreach (var device in modifyDeviceMergedVideoSizeNotification.VideoDeviceInfos) { deviceInfos.Add(DTOConverter.ConvertVideoDeviceDTOToVideoDeviceOutputInfoDTO(device)); } if (IsDifferent(deviceInfos)) { _currentHeartRateCode = string.Empty; _pusherManager.LiveStateChanged(new LiveEventArgs(false)); } } } } } } private void HandleStartConsolutionHeartRateToDeviceNotification(StartConsolutionHeartRateToDeviceNotification startConsolutionHeartRateToDeviceNotification) { _currentHeartRateCode = startConsolutionHeartRateToDeviceNotification.LiveRoomCode; _pusherManager.StartHeartRateKeeper(startConsolutionHeartRateToDeviceNotification.LiveRoomCode, startConsolutionHeartRateToDeviceNotification.IntervalSeconds, EnumHeartRateType.LiveConsultation); } private void HandleStartEducationHeartRateToDeviceNotification(StartEducationHeartRateToDeviceNotification startEducationHeartRateToDeviceNotification) { _currentHeartRateCode = startEducationHeartRateToDeviceNotification.LiveRoomCode; _pusherManager.StartHeartRateKeeper(startEducationHeartRateToDeviceNotification.LiveRoomCode, startEducationHeartRateToDeviceNotification.IntervalSeconds, EnumHeartRateType.Education); } private void HandleCloseConsolutionHeartRateToDeviceNotification(CloseConsolutionHeartRateToDeviceNotification closeConsolutionHeartRateToDeviceNotification) { if (_currentHeartRateCode != closeConsolutionHeartRateToDeviceNotification.LiveRoomCode) { Logger.WriteLineInfo($"Current HeartRate Code:{_currentHeartRateCode},not {closeConsolutionHeartRateToDeviceNotification.LiveRoomCode}"); return; } _currentHeartRateCode = string.Empty; _pusherManager.StopHeartRateKeeper(); } private void HandleCloseCourseHeartRateToDeviceNotification(CloseCourseHeartRateToDeviceNotification closeCourseHeartRateToDeviceNotification) { if (_currentHeartRateCode != closeCourseHeartRateToDeviceNotification.LiveRoomCode) { Logger.WriteLineInfo($"Current HeartRate Code:{_currentHeartRateCode},not {closeCourseHeartRateToDeviceNotification.LiveRoomCode}"); return; } _currentHeartRateCode = string.Empty; _pusherManager.StopHeartRateKeeper(); } private void HandleChangeConsultationToDeviceNotification(ChangeConsultationToDeviceNotification changeConsultationToDeviceNotification) { if (_currentHeartRateCode != changeConsultationToDeviceNotification.ConsultationCode) { Logger.WriteLineInfo($"Current HeartRate Code Change From {_currentHeartRateCode} to {changeConsultationToDeviceNotification.ConsultationCode}"); _currentHeartRateCode = changeConsultationToDeviceNotification.ConsultationCode; _pusherManager.ChangeHeartRateCode(changeConsultationToDeviceNotification.ConsultationCode); } } private void HandleStartLiveToDeviceNotification(StartLiveToDeviceNotification startLiveToDeviceNotification) { lock (_operateLocker) { if (_isPaused) { Logger.WriteLineInfo($"Receive StartLiveToDeviceNotification,but it is paused,so skipped it."); return; } if (startLiveToDeviceNotification.VideoDeviceOutputList?.Count == 0) { Logger.WriteLineError("LiveVideoV2 Receive StartLiveToDeviceNotification,But the VideoDeviceOutputInfo Count is 0"); return; } _currentOutputVideoInfoList.Clear(); foreach (var device in startLiveToDeviceNotification.VideoDeviceOutputList) { _currentOutputVideoInfoList.Add(DTOConverter.ConvertVideoDeviceOutputInfoToVideoDeviceOutputInfoDTO(device)); } IExtendedData extendedData; switch (vCloudServerConfig.Instance.LiveProtocolType) { case TransactionStatusEnum.TRTC: extendedData = CreateExtentedData(EnumLiveProtocol.RTC, startLiveToDeviceNotification, _micDeviceId, _isMute); break; case TransactionStatusEnum.VRTC: Logger.WriteLineError("LiveVideoV2 Current doesn't support VRTC Mode"); return; default: extendedData = CreateExtentedData(EnumLiveProtocol.Rtmp, startLiveToDeviceNotification, _micDeviceId, _isMute); break; } Logger.WriteLineInfo($"ExtendedData:{extendedData}"); if (extendedData != null) { var pushMode = startLiveToDeviceNotification.MergedChannel ? EnumLiveDataMode.MergeLive : EnumLiveDataMode.OnlyLive; var liveProtocol = extendedData is RtcExtendedData ? EnumLiveProtocol.RTC : EnumLiveProtocol.Rtmp; var liveEventArgs = new LiveEventArgs(true, liveProtocol, pushMode, extendedData); _pusherManager.LiveStateChanged(liveEventArgs); } } } private void DoDispose() { if (!_disposed) { RainbowImageDetector.Instance.IsPaused -= OnIsPaused; RainbowImageDetector.Instance.StopDetect(); if (_websocket != null) { _websocket.NotificationReceived -= OnNotificationReceived; } _currentHeartRateCode = string.Empty; _pusherManager.Dispose(); _pusherManager.LiveVideoNotification -= OnLiveVideoNotification;//需放在Dispose之后,否则收不到Close的通知 _previewManager.PreviewImageReceived -= OnPreviewImageReceived; _previewManager.Dispose(); if (_realtimeCaptureManager != null) { _realtimeCaptureManager.CaptureImageGenerated -= OnCaptureImageGenerated; _realtimeCaptureManager.RecordVideoGenerated -= OnRecordVideoGenerated; _realtimeCaptureManager.StopRecordVideo(false); _realtimeCaptureManager.ClearImageCache(); } _disposed = true; } } private void OnIsPaused(object sender, bool e) { lock (_operateLocker) { Logger.WriteLineInfo($"LiveVideoV2 Set IsPaused:{e}"); if (e) { _isPaused = true; _pusherManager.SetIsPaused(e); _previewManager.SetIsPaused(e); } else { _pusherManager.SetIsPaused(e); _previewManager.SetIsPaused(e); _isPaused = false; } } } private void OnLiveVideoNotification(object sender, LiveNotificationArgs e) { LiveNotification?.Invoke(this, e); } /// /// /// /// /// /// public void ChangeCameraSettings(bool enableCameraLive, string cameraId, string micId, bool showPreviewImage, bool enableLiveVideo, bool isMute) { lock (_locker) { var needNotifyServer = false; if (!enableCameraLive) { cameraId = null; showPreviewImage = false; } if (_firstCommit) { _firstCommit = false; needNotifyServer = true; } if (_cameraId != cameraId) { _cameraId = cameraId; needNotifyServer = true; } _isMainLiveVideoDisabled = !enableLiveVideo; if (_liveVideoEnabled != enableLiveVideo) { _liveVideoEnabled = enableLiveVideo; needNotifyServer = true; } if (_cameraLiveEnabled != enableCameraLive) { _cameraLiveEnabled = enableCameraLive; needNotifyServer = true; } if (needNotifyServer) { var infos = GetVideoDeviceInfos(enableLiveVideo, enableCameraLive, cameraId); _currentVideoDeviceInfoList.Clear(); foreach (var info in infos) { var item = info.Clone() as CPVideoDeviceOutputInfo; _currentVideoDeviceInfoList.Add(item); } _previewManager.UpdateCurrentVideoDeviceInfoList(infos); } if (_micDeviceId != micId) { _micDeviceId = micId; _pusherManager.SwitchMic(micId); } if (_isMute != isMute) { _isMute = isMute; _pusherManager.SetMute(isMute); } if (showPreviewImage && cameraId != null) { if (cameraId != _oldPreviewCameraId && _previewManager.IsPreviewing) { _previewManager.StopPreview(true); } _oldPreviewCameraId = cameraId; _previewManager.StartPreview(cameraId, 640, 480, 20, EnumLiveChannelCategory.Auxiliary1); } else { _previewManager.StopPreview(false); } } } public void ChangeCameraSettingsForSonopost(bool showPreviewImage, EnumLiveChannelCategory previewLiveChannel, IEnumerable infos, string micId, bool isMute, RainbowImageDetectConfig rainbowImageDetectConfig) { lock (_locker) { bool needNotifyServer = false; if (_firstCommit) { _firstCommit = false; needNotifyServer = true; } if (infos == null) { if (_currentVideoDeviceInfoList.Count != 0 || needNotifyServer) { _currentVideoDeviceInfoList.Clear(); _previewManager.UpdateCurrentVideoDeviceInfoList(new List()); } } else { var mainInfo = infos.FirstOrDefault(x => x.Category == EnumLiveChannelCategory.Main); if (mainInfo == null)//关闭主通道直播 { _realtimeCaptureManager?.ClearImageCache(); _isMainLiveVideoDisabled = true; } else { _isMainLiveVideoDisabled = false; } var newInfos = new List(); foreach (var info in infos) { string idForServer = null; switch (info.Category) { case EnumLiveChannelCategory.Main: idForServer = _uniqueId; break; case EnumLiveChannelCategory.Auxiliary1: idForServer = "Camera1"; break; case EnumLiveChannelCategory.Auxiliary2: idForServer = "Camera2"; break; case EnumLiveChannelCategory.Auxiliary3: idForServer = "Camera3"; break; } var item = new CPVideoDeviceOutputInfo { VideoDeviceId = info.Id, IdForServer = idForServer, VideoDeviceSourceType = info.Category == EnumLiveChannelCategory.Main ? EnumVideoDeviceSourceType.Desktop : EnumVideoDeviceSourceType.Camera, Category = info.Category, OutputWidth = info.Width, OutputHeight = info.Height, }; newInfos.Add(item); } if (newInfos.Count() != _currentVideoDeviceInfoList.Count() || needNotifyServer) { _currentVideoDeviceInfoList.Clear(); foreach (var info in newInfos) { var item = info.Clone() as CPVideoDeviceOutputInfo; _currentVideoDeviceInfoList.Add(item); } _previewManager.UpdateCurrentVideoDeviceInfoList(newInfos.ToList()); } else { if (IsDifferent(newInfos.ToList()) || needNotifyServer) { _currentVideoDeviceInfoList.Clear(); foreach (var info in newInfos) { var item = info.Clone() as CPVideoDeviceOutputInfo; _currentVideoDeviceInfoList.Add(item); } _previewManager.UpdateCurrentVideoDeviceInfoList(newInfos.ToList()); } } } if (_micDeviceId != micId) { _micDeviceId = micId; _pusherManager.SwitchMic(micId); } if (_isMute != isMute) { _isMute = isMute; _pusherManager.SetMute(isMute); } var device = infos.FirstOrDefault(x => x.Category == previewLiveChannel); if (showPreviewImage && device != null) { if (device.Id != _oldPreviewCameraId && _previewManager.IsPreviewing) { _previewManager.StopPreview(true); } _oldPreviewCameraId = device.Id; _previewManager.StartPreview(device.Id, device.Width, device.Height, device.FrameRate, device.Category); } else { _previewManager.StopPreview(false); } } var init = false; var updateEnable = false; var updateIntervalTime = false; if (_rainbowImageDetectConfig == null) { updateEnable = true; updateIntervalTime = true; init = true; _rainbowImageDetectConfig = rainbowImageDetectConfig; } else { if (_rainbowImageDetectConfig.IsDetectRainbowImage != rainbowImageDetectConfig.IsDetectRainbowImage) { _rainbowImageDetectConfig.IsDetectRainbowImage = rainbowImageDetectConfig.IsDetectRainbowImage; updateEnable = true; } if (_rainbowImageDetectConfig.BeforeDisableIntervalTime != rainbowImageDetectConfig.BeforeDisableIntervalTime) { _rainbowImageDetectConfig.BeforeDisableIntervalTime = rainbowImageDetectConfig.BeforeDisableIntervalTime; updateIntervalTime = true; } if (_rainbowImageDetectConfig.BeforeEnableIntervalTime != rainbowImageDetectConfig.BeforeEnableIntervalTime) { _rainbowImageDetectConfig.BeforeEnableIntervalTime = rainbowImageDetectConfig.BeforeEnableIntervalTime; updateIntervalTime = true; } if (_rainbowImageDetectConfig.AfterEnableIntervalTime != rainbowImageDetectConfig.AfterEnableIntervalTime) { _rainbowImageDetectConfig.AfterEnableIntervalTime = rainbowImageDetectConfig.AfterEnableIntervalTime; updateIntervalTime = true; } if (_rainbowImageDetectConfig.ScanIntervalTime != rainbowImageDetectConfig.ScanIntervalTime) { _rainbowImageDetectConfig.ScanIntervalTime = rainbowImageDetectConfig.ScanIntervalTime; updateIntervalTime = true; } } UpdateRainbowImageDetectConfig(updateEnable, init, updateIntervalTime); } private void UpdateRainbowImageDetectConfig(bool updateEnable, bool init, bool updateIntervalTime) { if (init) { CrossPlatformHelper.Instance.DriverHelper.InitializeCaptureCard(_rainbowImageDetectConfig.CaptureCardList); } if (updateIntervalTime) { RainbowImageDetector.Instance.SetIntervalTime(_rainbowImageDetectConfig.BeforeDisableIntervalTime, _rainbowImageDetectConfig.BeforeEnableIntervalTime, _rainbowImageDetectConfig.AfterEnableIntervalTime, _rainbowImageDetectConfig.ScanIntervalTime); } if (updateEnable) { if (_rainbowImageDetectConfig.IsDetectRainbowImage) { RainbowImageDetector.Instance.StartDetect(); } else { RainbowImageDetector.Instance.StopDetect(); } } } public void Dispose() { DoDispose(); GC.SuppressFinalize(this); } private List GetVideoDeviceInfos(bool liveVideoEnabled, bool cameraEnabled, string cameraId) { var videoInfoList = new List(); if (liveVideoEnabled) { videoInfoList.Add(new CPVideoDeviceOutputInfo { Category = EnumLiveChannelCategory.Main, VideoDeviceId = _uniqueId, IdForServer = _uniqueId, VideoDeviceSourceType = EnumVideoDeviceSourceType.Desktop, OutputHeight = _usScreenHeight, OutputWidth = _usScreenWidth, }); if (cameraEnabled) { videoInfoList.Add(new CPVideoDeviceOutputInfo { Category = EnumLiveChannelCategory.Auxiliary1, IdForServer = "Camera1", VideoDeviceId = cameraId, VideoDeviceSourceType = EnumVideoDeviceSourceType.Camera, OutputHeight = 480, OutputWidth = 640, }); } } return videoInfoList; } private IExtendedData CreateExtentedData(EnumLiveProtocol protocol, StartLiveToDeviceNotification notification, string micId, bool isMute) { if (protocol == EnumLiveProtocol.RTC) { var rtcExtentedData = new RtcExtendedData(null, micId, isMute); rtcExtentedData.AppId = notification.AppId; rtcExtentedData.RoomId = notification.RoomNo; if (notification.MergedChannel) { if (notification.MergedVideoOutputHeight == 720 && notification.MergedVideoOutputWidth == 1280) { rtcExtentedData.IsMergeChannel = notification.MergedChannel; rtcExtentedData.MergeType = EnumMergeType.Merge1280X720; } else { rtcExtentedData.IsMergeChannel = notification.MergedChannel; rtcExtentedData.MergeType = EnumMergeType.Merge1920X1080; } } else { rtcExtentedData.IsMergeChannel = notification.MergedChannel; rtcExtentedData.MergeType = EnumMergeType.None; } int cameraNo = 0; if (notification.VideoDeviceOutputList != null && notification.VideoDeviceOutputList.Count > 0) { for (int i = 0; i < notification.VideoDeviceOutputList.Count(); i++) { EnumLiveChannelCategory enumLiveChannelCategory; var userId = notification.VideoDeviceOutputList[i].VideoDeviceId; var userSign = notification.VideoDeviceOutputList[i].VideoDeviceSign; if (notification.VideoDeviceOutputList[i].VideoDeviceSourceType == VideoDeviceSourceTypeEnum.Desktop) { enumLiveChannelCategory = EnumLiveChannelCategory.Main; } else { switch (cameraNo) { case 0: enumLiveChannelCategory = EnumLiveChannelCategory.Auxiliary1; cameraNo++; break; case 1: enumLiveChannelCategory = EnumLiveChannelCategory.Auxiliary2; cameraNo++; break; case 2: enumLiveChannelCategory = EnumLiveChannelCategory.Auxiliary3; cameraNo++; break; default: continue; } } var width = notification.VideoDeviceOutputList[i].OutputWidth; var height = notification.VideoDeviceOutputList[i].OutputHeight; var fps = notification.VideoDeviceOutputList[i].VideoFps; var bitrate = notification.VideoDeviceOutputList[i].VideoBitrate; var minBitrate = notification.VideoDeviceOutputList[i].MinVideoBitrate; rtcExtentedData.UserInfos.Add(new RtcUserInfo(enumLiveChannelCategory, userId, userSign, width, height, fps, bitrate, minBitrate)); } } return rtcExtentedData; } else if (protocol == EnumLiveProtocol.Rtmp) { var rtmpExtendedData = new RtmpExtendedData(null, micId, isMute); if (notification.MergedChannel) { if (notification.MergedVideoOutputHeight == 720 && notification.MergedVideoOutputWidth == 1280) { rtmpExtendedData.IsMergeChannel = notification.MergedChannel; rtmpExtendedData.MergeType = EnumMergeType.Merge1280X720; } else { rtmpExtendedData.IsMergeChannel = notification.MergedChannel; rtmpExtendedData.MergeType = EnumMergeType.Merge1920X1080; } } else { rtmpExtendedData.IsMergeChannel = notification.MergedChannel; rtmpExtendedData.MergeType = EnumMergeType.None; } int cameraNo = 0; if (notification.VideoDeviceOutputList != null && notification.VideoDeviceOutputList.Count > 0) { for (int i = 0; i < notification.VideoDeviceOutputList.Count(); i++) { EnumLiveChannelCategory enumLiveChannelCategory; if (notification.VideoDeviceOutputList[i].LiveData == null) { Logger.WriteLineError($"{notification.VideoDeviceOutputList[i].VideoDeviceId}'s RtmpPushUrl is null"); } var pushUrl = notification.VideoDeviceOutputList[i].LiveData?.RtmpPushUrl; if (notification.VideoDeviceOutputList[i].VideoDeviceSourceType == VideoDeviceSourceTypeEnum.Desktop) { enumLiveChannelCategory = EnumLiveChannelCategory.Main; } else { switch (cameraNo) { case 0: enumLiveChannelCategory = EnumLiveChannelCategory.Auxiliary1; cameraNo++; break; case 1: enumLiveChannelCategory = EnumLiveChannelCategory.Auxiliary2; cameraNo++; break; case 2: enumLiveChannelCategory = EnumLiveChannelCategory.Auxiliary3; cameraNo++; break; default: continue; } } var width = notification.VideoDeviceOutputList[i].OutputWidth; var height = notification.VideoDeviceOutputList[i].OutputHeight; ; rtmpExtendedData.UserInfos.Add(new RtmpUserInfo(enumLiveChannelCategory, pushUrl, width, height)); } } return rtmpExtendedData; } return null; } /// /// 获取品牌列表 /// /// public List GetBrandList() { return _pusherManager?.GetBrandList(); } /// /// 获取型号列表 /// /// /// /// public List GetModelList(string brand) { return _pusherManager?.GetModelList(brand); } /// /// 获取推荐分辨率 /// /// /// /// public DeviceRecommandResolution GetRecommandResolution(string brand, string model) { return _pusherManager?.GetRecommandResolution(brand, model); } private bool IsDifferent(List newVideoDeviceInfos) { for (int i = 0; i < newVideoDeviceInfos.Count(); i++) { if (newVideoDeviceInfos[i].ToString() != _currentVideoDeviceInfoList[i].ToString()) { return true; } } return false; } private bool IsDifferent(List newVideoDeviceInfos) { for (int i = 0; i < newVideoDeviceInfos.Count(); i++) { if (newVideoDeviceInfos[i].ToString() != _currentOutputVideoInfoList[i].ToString()) { return true; } } return false; } public void ChangeRealTimeCaptureSetting(bool isStart) { LiveVideoStatusChecker.Instance.IsRealTimeCapturing = isStart; _previewManager.ChangeRealTimeCaptureSetting(isStart); } public void CaptureCurrentImage() { _realtimeCaptureManager?.CaptureCurrentImage(); } public void StartRecordVideo() { _realtimeCaptureManager?.StartRecordVideo(); } public void StopRecordVideo(bool isTimeOut) { _realtimeCaptureManager?.StopRecordVideo(isTimeOut); } public CPBase64ImageData GetCurrentCaptureFrame() { if (_isMainLiveVideoDisabled) { return new CPBase64ImageData(0, 0, "", EnumFailReasonForNullBase64Data.LiveVideoIsDisabled); } return _realtimeCaptureManager?.GetCurrentCaptureFrame(); } } }