123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- using System;
- using System.Runtime.InteropServices;
- using System.Threading.Tasks;
- using Vinno.FIS.TRTCClient.Common.Enum;
- 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.Consultation.Interface;
- 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.Messages.Live;
- namespace Vinno.vCloud.Common.FIS.Consultation
- {
- public abstract class VideoProvider : IDisposable
- {
- private readonly ConsultationVideoFrameData _consultationVideoFrameData;
- private readonly object _connectionKeeperLock = new object();
- private ConsultationConnectionKeeper _connectionKeeper;
- private string _liveServiceUrl;
- protected ConsultationMemberInfo _consultationMemberInfo;
- protected bool _disposed;
- public event EventHandler Offlined;
- public ConsultationMemberInfo ConsultationMemberInfo
- {
- get => _consultationMemberInfo;
- set
- {
- _consultationMemberInfo = value;
- }
- }
- /// <summary>
- /// Video frame arrived
- /// </summary>
- public event EventHandler<ConsultationVideoFrameData> VideoFrameArrived;
- public VideoProvider(ConsultationMemberInfo consultationMemberInfo)
- {
- _consultationMemberInfo = consultationMemberInfo;
- _consultationVideoFrameData = new ConsultationVideoFrameData(null, _consultationMemberInfo);
- }
- public abstract void Dispose();
- protected void UpdateFrame(CPVideoFrameData data)
- {
- _consultationVideoFrameData.VideoFrameData = data;
- VideoFrameArrived?.Invoke(this, _consultationVideoFrameData);
- }
- public void StartConnectionKeeper(string roomId, string userId, ClientLeaf leaf, bool isDelayStart = true)
- {
- lock (_connectionKeeperLock)
- {
- if (leaf == null)
- {
- Logger.WriteLineError("Start video provider Chat Connection Keeper failed,the leaf is null");
- return;
- }
- var liveServiceUrl = GetLiveServiceUrl(leaf);
- if (string.IsNullOrEmpty(liveServiceUrl))
- {
- Logger.WriteLineError($"Start video provider Chat Connection Keeper failed,the live Service Url is null!");
- return;
- }
- _connectionKeeper = new ConsultationConnectionKeeper(roomId, userId, liveServiceUrl);
- _connectionKeeper.Offlined += OnOfflined;
- _connectionKeeper.ClientLeafClosed += OnConnectionKeeperLeafClose;
- _connectionKeeper.Start(isDelayStart);
- }
- }
- /// <summary>
- /// Get live service url
- /// </summary>
- /// <returns></returns>
- private string GetLiveServiceUrl(ClientLeaf leaf)
- {
- try
- {
- if (string.IsNullOrEmpty(_liveServiceUrl))
- {
- using (var request = MessagePool.GetMessage<GetLiveServiceUrlRequest>())
- {
- var result = leaf.Send(request);
- if (result != null)
- {
- var resultMessage = GetLiveServiceUrlResult.Convert(result);
- if (resultMessage != null)
- {
- _liveServiceUrl = resultMessage.Url;
- }
- }
- }
- }
- return _liveServiceUrl;
- }
- catch (Exception ex)
- {
- Logger.WriteLineError($"Get live service url error: {ex}");
- }
- return null;
- }
- private void OnConnectionKeeperLeafClose(object sender, EventArgs e)
- {
- lock (_connectionKeeperLock)
- {
- _connectionKeeper.Offlined -= OnOfflined;
- _connectionKeeper.ClientLeafClosed -= OnConnectionKeeperLeafClose;
- _connectionKeeper.Stop();
- Offlined?.Invoke(this, e);
- }
- }
- private void OnOfflined(object sender, EventArgs e)
- {
- Offlined?.Invoke(this, e);
- Logger.WriteLineInfo($"Connection keeper offline ");
- }
- internal void StopConnectionKeeper()
- {
- if (_connectionKeeper != null)
- {
- _connectionKeeper.Offlined -= OnOfflined;
- _connectionKeeper.ClientLeafClosed -= OnConnectionKeeperLeafClose;
- _connectionKeeper?.Stop();
- _connectionKeeper = null;
- }
- }
- }
- public class RtcVideoProvider : VideoProvider
- {
- public RtcVideoProvider(ConsultationMemberInfo consultationMemberInfo) : base(consultationMemberInfo)
- {
- }
- public override void Dispose()
- {
- }
- }
- public class RtmpVideoProvider : VideoProvider
- {
- private IRtmpPlayer _smartPlayer;
- private int _videoBufferSize = 300;
- private bool _isClosed;
- private readonly object _locker = new object();
- public RtmpVideoProvider(ConsultationMemberInfo consultationMemberInfo) : base(consultationMemberInfo)
- {
- CreateSmartPlayer(consultationMemberInfo.PullRtmpUrl);
- }
- private void CreateSmartPlayer(string url)
- {
- if (!string.IsNullOrEmpty(url))
- {
- _smartPlayer = CrossPlatformHelper.Instance.RtmpPlayerCreator.CreateLivePlayer(url);
- _smartPlayer.Buffer = _videoBufferSize;
- _smartPlayer.VideoFrameReceived += OnVideoFrameReceived;
- Task.Run(async () =>
- {
- await Task.Delay(3000);
- lock (_locker)
- {
- if (!_isClosed)
- {
- _smartPlayer.Play();
- }
- }
- });
- }
- }
- private void CloseSmartPlayer()
- {
- if (_smartPlayer != null)
- {
- lock (_locker)
- {
- _isClosed = true;
- }
- _smartPlayer.VideoFrameReceived -= OnVideoFrameReceived;
- _smartPlayer.Stop();
- _smartPlayer = null;
- }
- }
- private void OnVideoFrameReceived(object sender, CPVideoFrameData e)
- {
- UpdateFrame(e);
- }
- public override void Dispose()
- {
- if (_disposed)
- return;
- CloseSmartPlayer();
- StopConnectionKeeper();
- _disposed = true;
- }
- ~RtmpVideoProvider()
- {
- }
- }
- public class RtmpVideoPusher : VideoProvider
- {
- private IRtmpPusherV2 _smartPublisher;
- private CPVideoFrameData _videoFrameData;
- public RtmpVideoPusher(ConsultationMemberInfo consultationMemberInfo, string videoDeviceId, string micDeviceId) : base(consultationMemberInfo)
- {
- var deviceInfo = new CPVideoDeviceOutputInfo
- {
- VideoDeviceId = videoDeviceId,
- IdForServer = "",
- VideoDeviceSourceType = EnumVideoDeviceSourceType.Camera,
- OutputWidth = 640,
- OutputHeight = 480,
- Category = EnumLiveChannelCategory.Main,
- };
- _smartPublisher = CrossPlatformHelper.Instance.RtmpPusherCreator.CreateLivePusherV2(deviceInfo, consultationMemberInfo.PushUrl, micDeviceId, 640, 480);
- _smartPublisher.ImageFrameReceived += OnImageFrameReceived;
- _smartPublisher.Start();
- }
- ~RtmpVideoPusher()
- {
- }
- public override void Dispose()
- {
- if (_disposed)
- return;
- if (_smartPublisher != null)
- {
- _smartPublisher.ImageFrameReceived -= OnImageFrameReceived;
- _smartPublisher.Stop();
- _smartPublisher.Dispose();
- _smartPublisher = null;
- }
- StopConnectionKeeper();
- _disposed = true;
- }
- private void OnImageFrameReceived(object sender, ImageFrameData e)
- {
- if (_videoFrameData == null)
- {
- _videoFrameData = new CPVideoFrameData(e.Width, e.Height, new byte[e.Size]);
- }
- else if (_videoFrameData.Height != e.Height || _videoFrameData.Width != e.Width)
- {
- _videoFrameData.Height = e.Height;
- _videoFrameData.Width = e.Width;
- _videoFrameData.Data = new byte[e.Size];
- }
- Marshal.Copy(e.Data, _videoFrameData.Data, 0, e.Size);
- UpdateFrame(_videoFrameData);
- }
- public void SetMute(bool isMute)
- {
- if (_smartPublisher != null)
- {
- _smartPublisher.SetMute(isMute);
- }
- }
- public void SwitchCamera()
- {
- if (_smartPublisher != null)
- {
- //TODOFelix
- }
- }
- }
- }
|