123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540 |
- using System;
- using System.Threading.Tasks;
- using Vinno.IUS.Common.Log;
- using Vinno.IUS.Common.Network.Leaf;
- using Vinno.IUS.Common.Network.Transfer;
- using Vinno.vCloud.FIS.CrossPlatform.Common;
- using Vinno.vCloud.FIS.CrossPlatform.Common.Enum;
- using Vinno.vCloud.FIS.CrossPlatform.Common.LiveVideo;
- using Vinno.vCloud.FIS.CrossPlatform.Common.LiveVideo.Interface;
- using Vinno.vCloud.Protocol.Infrastructures;
- using Vinno.vCloud.Protocol.Messages.Client.Live;
- using Vinno.vCloud.Protocol.Messages.Live;
- namespace Vinno.vCloud.Common.FIS.LiveVideos
- {
- internal class LiveClient : IDisposable
- {
- private readonly ClientLeaf _clientLeaf;
- private readonly object _getLiveProtocolLock = new object();
- private readonly int _usScreenWidth;
- private readonly int _usScreenHeight;
- private ILiveVideoPusher _pusher;
- private PushHeartRateKeeper _pushHeartRateKeeper;
- private EnumLiveStates _liveState;
- private LiveProtocol _liveProtocol;
- /// <summary>
- /// Preview local camera capured changed
- /// </summary>
- public event EventHandler<CPVideoFrameData> PreviewCameraCapured;
- /// <summary>
- /// Raised when live changed to protocol
- /// </summary>
- public event EventHandler<LiveProtocol> LiveProtocolChanged;
- /// <summary>
- /// The event to notificate the US to show or hide the live video out put window
- /// </summary>
- public event EventHandler<LiveNotificationArgs> LiveNotification;
- public LiveClient(ClientLeaf clientLeaf, int usScreenWidth, int usScreenHeight)
- {
- _clientLeaf = clientLeaf;
- _liveState = EnumLiveStates.Idle;
- _liveProtocol = LiveProtocol.RTC;
- _usScreenWidth = usScreenWidth;
- _usScreenHeight = usScreenHeight;
- }
- /// <summary>
- /// Start Pusher
- /// </summary>
- public void Start(LiveProtocol liveProtocol)
- {
- try
- {
- var pushConfiguration = CPCombineSmartPushConfiguration.Instance;
- if (_liveState == EnumLiveStates.TerminalIsPushing)
- {
- Logger.WriteLineInfo($"LiveClient is pushing ,not do start");
- return;
- }
- bool isStartPush = false;
- pushConfiguration.IsPushOnce = true;
- if (liveProtocol == LiveProtocol.RTC)
- {
- //直播推流
- if (pushConfiguration.ShouldPushData)
- {
- if (_pusher == null)
- {
- _pusher = CrossPlatformHelper.Instance.LiveVideoPusherCreator.CreateRtcPusher(
- pushConfiguration.RoomId,
- pushConfiguration.TerminalId,
- pushConfiguration.UserSign,
- pushConfiguration.Resolution,
- pushConfiguration.PushDataSourceType,
- _usScreenWidth,
- _usScreenHeight,
- UpdateLiveState);
- _pusher.PreviewCameraCapured += OnPreviewCameraCapured;
- _pusher.LiveNotification += OnLiveNotification;
- }
- isStartPush = _pusher.Start(pushConfiguration);
- }
- }
- else
- {
- //直播推流
- if (pushConfiguration.ShouldPushData)
- {
- if (_pusher == null)
- {
- _pusher = CrossPlatformHelper.Instance.LiveVideoPusherCreator.CreateRtmpPusher(pushConfiguration.TerminalId, _usScreenWidth, _usScreenHeight, UpdateLiveState);
- _pusher.PreviewCameraCapured += OnPreviewCameraCapured;
- _pusher.LiveNotification += OnLiveNotification;
- }
- isStartPush = _pusher.Start(pushConfiguration);
- }
- }
- if (isStartPush)
- {
- StopPushHeartRateKeeper();
- StartPushHeartRateKeeper(pushConfiguration);
- }
- }
- catch (Exception ex)
- {
- Logger.WriteLineError($"LiveClient start failed ex;{ex}");
- _liveState = EnumLiveStates.Idle;
- }
- }
- private void StartPushHeartRateKeeper(CPCombineSmartPushConfiguration pushConfiguration)
- {
- _pushHeartRateKeeper = new PushHeartRateKeeper(pushConfiguration.TerminalId, pushConfiguration.LiveServiceUrl, _clientLeaf);
- _pushHeartRateKeeper.Offlined += OnOfflined;
- _pushHeartRateKeeper.Start();
- }
- /// <summary>
- /// Start only Preview capture camera
- /// </summary>
- public async void StartOnlyPreviewImage()
- {
- await Task.Run(() =>
- {
- try
- {
- Logger.WriteLineInfo($"LiveClient start Preview Camera begin");
- var liveProtocol = GetLiveProtocol();
- var pushConfiguration = CPCombineSmartPushConfiguration.Instance;
- pushConfiguration.IsPushOnce = true;
- if (liveProtocol == LiveProtocol.RTC)
- {
- //only show local camera data
- if (_pusher == null)
- {
- _pusher = CrossPlatformHelper.Instance.LiveVideoPusherCreator.CreateRtcPusher(
- uint.MinValue,
- pushConfiguration.TerminalId,
- string.Empty,
- pushConfiguration.Resolution,
- pushConfiguration.PushDataSourceType,
- _usScreenWidth,
- _usScreenHeight,
- UpdateLiveState);
- _pusher.PreviewCameraCapured += OnPreviewCameraCapured;
- _pusher.LiveNotification += OnLiveNotification;
- }
- _pusher.Start(pushConfiguration);
- }
- else
- {
- if (_pusher == null)
- {
- _pusher = CrossPlatformHelper.Instance.LiveVideoPusherCreator.CreateRtmpPusher(pushConfiguration.TerminalId, _usScreenWidth, _usScreenHeight, UpdateLiveState);
- _pusher.PreviewCameraCapured += OnPreviewCameraCapured;
- _pusher.LiveNotification += OnLiveNotification;
- }
- _pusher.Start(pushConfiguration);
- }
- Logger.WriteLineInfo($"LiveClient start Preview Camera end");
- }
- catch (Exception ex)
- {
- Logger.WriteLineError($"LiveClient start only preview image failed ex;{ex}");
- }
- });
- }
- /// <summary>
- /// Stop pusher
- /// </summary>
- public void Stop()
- {
- StopPushHeartRateKeeper();
- CPCombineSmartPushConfiguration.Instance.ShouldPushData = false;
- if (_pusher != null)
- {
- _pusher.Stop();
- }
- _liveState = EnumLiveStates.Idle;
- LiveVideoStatusChecker.Instance.IsPushing = false;
- Logger.WriteLineInfo("Live Client Stop Push");
- }
- private void StopPushHeartRateKeeper()
- {
- if (_pushHeartRateKeeper != null)
- {
- _pushHeartRateKeeper.Offlined -= OnOfflined;
- _pushHeartRateKeeper.Stop();
- _pushHeartRateKeeper = null;
- }
- }
- /// <summary>
- /// Set push live status ,but _pusher is exist
- /// </summary>
- /// <param name="livePushStatus"></param>
- public void SetPushStatus(EnumLivePushStatus livePushStatus)
- {
- if (_pusher != null)
- {
- CPCombineSmartPushConfiguration.Instance.SetPushStatus(livePushStatus);
- Logger.WriteLineInfo($"LiveClient SetPushStatus:{livePushStatus}");
- }
- }
- /// <summary>
- /// Set enable preview camera capture data
- /// </summary>
- /// <param name="isShowPreview"></param>
- public void SetPreviewCamera(bool isShowPreview)
- {
- if (_pusher != null)
- {
- _pusher.SetPreviewCamera(isShowPreview);
- Logger.WriteLineInfo($"LiveClient set preview camera :{isShowPreview}");
- }
- }
- public void ChangeCamera(string cameraId)
- {
- if (_pusher != null)
- {
- _pusher.ChangeCamera(cameraId);
- Logger.WriteLineInfo($"LiveClient change camera id:{cameraId}");
- }
- }
- public void ChangeMic(string micId)
- {
- if (_pusher != null)
- {
- _pusher.ChangeMic(micId);
- Logger.WriteLineInfo($"LiveClient change mic id:{micId}");
- }
- }
- /// <summary>
- /// Set live mute
- /// </summary>
- /// <param name="isMute"></param>
- public void SetMute(bool isMute)
- {
- if (_pusher != null)
- {
- _pusher.SetMute(isMute);
- Logger.WriteLineInfo($"LiveClient set mute :{isMute}");
- }
- }
- private async void UpdateLiveState(EnumLiveStates liveState)
- {
- try
- {
- await Task.Run(() =>
- {
- if (_liveState != liveState)
- {
- try
- {
- _liveState = liveState;
- if (_liveState == EnumLiveStates.TerminalIsPushing)
- {
- SetPushStatus(EnumLivePushStatus.Pushing);
- LiveVideoStatusChecker.Instance.IsPushing = true;
- }
- _clientLeaf?.Send(new UpdateTerminalLiveStateRequest()
- {
- TerminalId = CPCombineSmartPushConfiguration.Instance.TerminalId,
- State = (LiveStates)liveState
- });
- Logger.WriteLineInfo($"LiveClient UpdateLiveState: {liveState},TerminalId:{CPCombineSmartPushConfiguration.Instance.TerminalId}");
- }
- catch (Exception ex)
- {
- Logger.WriteLineError($"UpdateLiveState {_liveState} Error:{ex}");
- _liveState = EnumLiveStates.Idle;
- }
- }
- });
- }
- catch (Exception e)
- {
- Logger.WriteLineInfo($"LiveClient UpdateLiveState failed ex:{e}");
- }
- }
- private void OnPreviewCameraCapured(object sender, CPVideoFrameData data)
- {
- PreviewCameraCapured?.Invoke(this, data);
- }
- private void OnOfflined(object sender, EventArgs e)
- {
- Logger.WriteLineInfo($"LiveClient Push OnOfflined TerminalId:{CPCombineSmartPushConfiguration.Instance.TerminalId}");
- //Retry();
- }
- /// <summary>
- /// Disposed when live video feature disposed
- /// </summary>
- public void Dispose()
- {
- CPCombineSmartPushConfiguration.Instance.ShowPreviewImage = false;
- Stop();
- if (_pusher != null)
- {
- _pusher.PreviewCameraCapured -= OnPreviewCameraCapured;
- _pusher.LiveNotification -= OnLiveNotification;
- _pusher = null;
- }
- }
- /// <summary>
- /// retry live pushing
- /// </summary>
- public void Retry(LiveProtocol liveProtocol)
- {
- try
- {
- if (_clientLeaf != null && _clientLeaf.Online && CPCombineSmartPushConfiguration.Instance.PushStatus == EnumLivePushStatus.Pushing)// network connected and Pushing
- {
- // check server live room exist
- var request = MessagePool.GetMessage<CheckTerminalRoomRequest>();
- request.TerminalId = CPCombineSmartPushConfiguration.Instance.TerminalId;
- var result = _clientLeaf.Send(request);
- var checkTerminalRoomResult = CheckTerminalRoomResult.Convert(result);
- if (checkTerminalRoomResult == null || !checkTerminalRoomResult.IsExist)
- {
- Logger.WriteLineError($"LiveClient Retry, Check server live room no exist");
- SetPushStatus(EnumLivePushStatus.Ide);
- CPCombineSmartPushConfiguration.Instance.PushUrl = string.Empty;
- return;
- }
- //server live room exist ,do next code
- lock (CPCombineSmartPushConfiguration.Instance)
- {
- Logger.WriteLineInfo($"LiveClient RetryLive begin");
- Stop();
- CPCombineSmartPushConfiguration.Instance.ShouldPushData = true;
- SetPushStatus(EnumLivePushStatus.Ide);
- Start(liveProtocol);
- Logger.WriteLineInfo($"LiveClient RetryLive end");
- }
- }
- else
- {
- //Logger.WriteLineInfo($"LiveClient RetryLive:_clientLeafOnline:{_clientLeaf.Online} PushStatus:{CombineSmartPushConfiguration.Instance.PushStatus}");
- }
- }
- catch (Exception ex)
- {
- Logger.WriteLineError($"LiveClient Retry failed:{ex}");
- }
- }
- /// <summary>
- /// Speed live test network and auto select good network to server
- /// </summary>
- /// <param name="configuration"></param>
- /// <returns></returns>
- public bool StartSpeedTest()
- {
- bool result = false;
- try
- {
- var liveProtocol = GetLiveProtocol();
- if (liveProtocol == LiveProtocol.RTC) // only test live protocol RTC
- {
- var pusher = CrossPlatformHelper.Instance.LiveVideoPusherCreator.CreateRtcPusher(uint.MinValue, string.Empty, string.Empty, CPCombineSmartPushConfiguration.Instance.Resolution, CPCombineSmartPushConfiguration.Instance.PushDataSourceType, _usScreenWidth,
- _usScreenHeight, null);
- if (pusher != null)
- {
- using (var getLiveRoomSignRequest = MessagePool.GetMessage<GetLiveRoomSignRequest>())
- {
- var userId = Guid.NewGuid().ToString();
- getLiveRoomSignRequest.RoomId = userId;
- var getLiveRoomSignResult =
- GetLiveRoomSignResult.Convert(_clientLeaf?.Send(getLiveRoomSignRequest));
- if (getLiveRoomSignResult != null)
- {
- var userSign = getLiveRoomSignResult.UserSign;
- var appId = (uint)getLiveRoomSignResult.AppId;
- CPCombineSmartPushConfiguration.Instance.IsPushOnce = true;
- result = pusher.StartSpeedTest(appId, userId, userSign);
- }
- }
- }
- }
- else
- {
- // 内网 不需要处理
- Logger.WriteLineInfo($"LiveClient StartSpeedTest LiveProtocol:{liveProtocol}, do not speedTest ");
- return true;
- }
- }
- catch (Exception ex)
- {
- Logger.WriteLineError($"LiveClient StartSpeedTest ex:{ex}");
- }
- return result;
- }
- /// <summary>
- /// Notify server satatus and resolutions
- /// </summary>
- /// <param name="terminalName">The terminal id.</param>
- /// <param name="isCameraLiveEnabled"></param>
- /// <param name="serialNumber">device dongledId to fix hainan project, if vbox should ingnore</param>
- internal async void NotifyStatusAndResolutions(string terminalId)
- {
- await Task.Run(() =>
- {
- try
- {
- var liveProtocol = GetLiveProtocol();
- if (liveProtocol == LiveProtocol.RTC)
- {
- //获取Terminal 和 Camera Resolution
- var pusher = CrossPlatformHelper.Instance.LiveVideoPusherCreator.CreateRtcPusher(uint.MinValue, string.Empty, string.Empty, CPCombineSmartPushConfiguration.Instance.Resolution, CPCombineSmartPushConfiguration.Instance.PushDataSourceType, _usScreenWidth,
- _usScreenHeight, null);
- if (pusher != null)
- {
- using (var changeCameraSettingRequest = new ChangeCameraSettingRequest()
- {
- TerminalId = terminalId,
- IsMergeChannel = true,
- TerminalWidth = pusher.TerminalWidth,
- TerminalHeight = pusher.TerminalHeight,
- CameraWidth = pusher.CameraWidth,
- CameraHeight = pusher.CameraHeight
- })
- {
- var result = _clientLeaf?.Send(changeCameraSettingRequest);
- var resultMsg = ChangeCameraSettingResult.Convert(result);
- if (resultMsg != null && resultMsg.IsSuccess)
- {
- Logger.WriteLineInfo($"UpdateTerminalRelatedInfoRequest success RTC, PushDataSourceType :{CPCombineSmartPushConfiguration.Instance.PushDataSourceType}, " +
- $"TerminalSize:{changeCameraSettingRequest.TerminalWidth}*{changeCameraSettingRequest.TerminalHeight} " +
- $"CameraSize: {changeCameraSettingRequest.CameraWidth}*{changeCameraSettingRequest.CameraHeight}");
- }
- else
- {
- Logger.WriteLineError($"ChangeCameraSettingRequest failed");
- }
- }
- }
- }
- else
- {
- var pusher = CrossPlatformHelper.Instance.LiveVideoPusherCreator.CreateRtmpPusher(terminalId, _usScreenWidth, _usScreenHeight, null);
- pusher.UpdateResolution(CPCombineSmartPushConfiguration.Instance);
- if (pusher != null)
- {
- using (var changeCameraSettingRequest = new ChangeCameraSettingRequest()
- {
- TerminalId = terminalId,
- IsMergeChannel = true,
- TerminalWidth = pusher.TerminalWidth,
- TerminalHeight = pusher.TerminalHeight,
- CameraWidth = pusher.CameraWidth,
- CameraHeight = pusher.CameraHeight
- })
- {
- var result = _clientLeaf?.Send(changeCameraSettingRequest);
- var resultMsg = ChangeCameraSettingResult.Convert(result);
- if (resultMsg != null && resultMsg.IsSuccess)
- {
- Logger.WriteLineInfo($"UpdateTerminalRelatedInfoRequest success ,RTMP PushDataSourceType :{CPCombineSmartPushConfiguration.Instance.PushDataSourceType}" +
- $"TerminalWidth:{pusher.TerminalWidth} TerminalHeight:{pusher.TerminalHeight} " +
- $"CameraWidth: {pusher.CameraWidth} CameraHeight:{pusher.CameraHeight}");
- }
- else
- {
- Logger.WriteLineError($"UpdateTerminalRelatedInfoRequest failed");
- }
- }
- }
- }
- Retry(liveProtocol);
- }
- catch (Exception e)
- {
- Logger.WriteLineError($"Get resolutions ex:{e}");
- }
- });
- }
- /// <summary>
- /// get live Protocol Rtmp or Rtc
- /// </summary>
- private LiveProtocol GetLiveProtocol()
- {
- lock (_getLiveProtocolLock)
- {
- LiveProtocol liveProtocol = LiveProtocol.RTC;
- try
- {
- using (var request = MessagePool.GetMessage<GetLiveProtocolRequest>())
- {
- var result = _clientLeaf?.Send(request);
- var getLiveProtocolResult = GetLiveProtocolResult.Convert(result);
- if (getLiveProtocolResult != null)
- {
- liveProtocol = getLiveProtocolResult.LiveProtocol;
- }
- }
- }
- catch (Exception ex)
- {
- Logger.WriteLineError($"Terminal get live protocol failed {ex}");
- }
- if (_liveProtocol != liveProtocol)
- {
- _liveProtocol = liveProtocol;
- Logger.WriteLineInfo($"Terminal get live protocol:{liveProtocol}");
- LiveProtocolChanged?.Invoke(this, _liveProtocol);
- }
- return liveProtocol;
- }
- }
- private void OnLiveNotification(object sender, LiveNotificationArgs e)
- {
- LiveNotification?.Invoke(this, e);
- }
- }
- }
|