using System;
using System.Collections.Generic;
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.Enum;
using Vinno.vCloud.FIS.CrossPlatform.Common.LiveVideo;
using Vinno.vCloud.Protocol.Infrastructures;
using Vinno.vCloud.Protocol.Messages.Client;
using Vinno.vCloud.Protocol.Messages.Client.Live;
using Vinno.vCloud.Protocol.Messages.Live;
namespace Vinno.vCloud.Common.FIS.LiveVideos
{
internal class LiveVideo : ILiveVideo, IDisposable
{
private readonly string _terminalId;
private readonly string _terminalName;
private readonly ClientLeaf _leaf;
private bool _disposed;
private bool _isCameraLiveEnabled;
private bool _isLiveVideoEnabled;
private LiveClient _liveClient;
private bool _cameraMute;
private bool _previewCameraEnabled;
private LiveProtocol _liveProtocol;
private string _cameraId;
private string _micId;
private int _cameraPreviewWidth;
private int _cameraPreviewHeight;
private LiveClient LiveClient
{
get { return _liveClient; }
set
{
if (_liveClient != value)
{
if (_liveClient != null)
{
_liveClient.PreviewCameraCapured -= OnPreviewCameraCaptured;
_liveClient.LiveProtocolChanged -= OnLiveProtocolChanged;
_liveClient.LiveNotification -= OnLiveNotification;
_liveClient.Dispose();
}
_liveClient = value;
if (_liveClient != null)
{
_liveClient.PreviewCameraCapured += OnPreviewCameraCaptured;
_liveClient.LiveProtocolChanged += OnLiveProtocolChanged;
_liveClient.LiveNotification += OnLiveNotification;
_cameraPreviewWidth = 0;
_cameraPreviewHeight = 0;
}
}
}
}
///
/// Raised when live changed to protocol
///
public event EventHandler LiveProtocolChanged;
///
/// The event to notificate the US to show or hide the live video out put window
///
public event EventHandler LiveNotification;
///
/// Raised when camera Preview Excute
///
public event EventHandler PreviewCameraCaptured;
///
/// Raised when Camera Preview Image Size Changed
///
public event EventHandler CameraPreviewImageSizeChanged;
///
/// Create the liveVideo module.
///
///
///
///
///
public LiveVideo(string terminalId, string terminalName, ClientLeaf leaf, int usScreenWidth, int usScreenHeight)
{
_terminalId = terminalId;
_terminalName = terminalName;
_leaf = leaf;
_liveProtocol = LiveProtocol.RTC;
LiveClient = new LiveClient(_leaf, usScreenWidth, usScreenHeight);
_leaf.MessageArrived += OnMessageArrived;
}
~LiveVideo()
{
DoDispose();
}
///
/// Handle the message from network.
///
///
///
private void OnMessageArrived(object sender, Message e)
{
var startLiveNotification = StartLiveNotification.Convert(e);
if (startLiveNotification != null)
{
HandleStatLiveNotification(startLiveNotification);
}
var closeLiveNotification = CloseLiveNotification.Convert(e);
if (closeLiveNotification != null)
{
HandleCloseLiveNotification(closeLiveNotification);
}
}
private void HandleCloseLiveNotification(CloseLiveNotification closeLiveNotification)
{
lock (CPCombineSmartPushConfiguration.Instance)
{
try
{
Logger.WriteLineInfo($"Handle CloseLiveNotification begin");
CPCombineSmartPushConfiguration.Instance.PushUrl = string.Empty;
if (LiveClient != null)
{
LiveClient.SetPushStatus(EnumLivePushStatus.Ide);
LiveClient.Stop();
}
Logger.WriteLineInfo($"Handle CloseLiveNotification end");
}
catch (Exception ex)
{
Logger.WriteLineError($"Handle CloseLiveNotification ex:{ex}");
}
finally
{
CPCombineSmartPushConfiguration.Instance.LiveServiceUrl = string.Empty;
}
}
}
private void HandleStatLiveNotification(StartLiveNotification startLiveNotification)
{
lock (CPCombineSmartPushConfiguration.Instance)
{
try
{
var pushConfiguration = CPCombineSmartPushConfiguration.Instance;
var notificationDetails = $"LiveProtocol:{startLiveNotification.LiveProtocol},TerminalId:{startLiveNotification.TerminalId},IntegerRoomId:{startLiveNotification.IntegerRoomId},UserSign:{startLiveNotification.UserSign},TerminalPushUrl:{startLiveNotification.TerminalPushUrl},LiveServiceUrl:{startLiveNotification.LiveServiceUrl},AppId:{startLiveNotification.AppId}";
Logger.WriteLineInfo($"Handle StartLiveNotification begin,{notificationDetails}");
var terminalUrl = startLiveNotification.TerminalPushUrl;
if (_isLiveVideoEnabled || _isCameraLiveEnabled)
{
if (_isLiveVideoEnabled && !_isCameraLiveEnabled)
{
pushConfiguration.PushDataSourceType = EnumPushDataSourceType.Screen;
pushConfiguration.Mode = EnumPushMode.Screen;
}
else if (!_isLiveVideoEnabled && _isCameraLiveEnabled)
{
pushConfiguration.PushDataSourceType = EnumPushDataSourceType.Camera;
pushConfiguration.Mode = EnumPushMode.Camera;
}
else if (_isLiveVideoEnabled && _isCameraLiveEnabled)
{
pushConfiguration.PushDataSourceType = EnumPushDataSourceType.ScreenAndCamera;
pushConfiguration.Mode = EnumPushMode.CombineTerminal;
}
var protocol = startLiveNotification.LiveProtocol;
if (protocol == LiveProtocol.Rtmp)
{
pushConfiguration.PushUrl = terminalUrl;
}
pushConfiguration.ShouldPushData = true;
pushConfiguration.LiveServiceUrl = startLiveNotification.LiveServiceUrl;
pushConfiguration.AppId = startLiveNotification.AppId;
var roomId = startLiveNotification.IntegerRoomId;
var terminalId = startLiveNotification.TerminalId;
var userSign = startLiveNotification.UserSign;
pushConfiguration.RoomId = (uint)roomId;
pushConfiguration.TerminalId = terminalId;
pushConfiguration.UserSign = userSign;
LiveClient.Start(startLiveNotification.LiveProtocol);
if (_liveProtocol != protocol)
{
_liveProtocol = protocol;
InvokeLiveProtocolChanged(_liveProtocol);
}
}
Logger.WriteLineInfo($"Handle StartLiveNotification end");
}
catch (Exception ex)
{
Logger.WriteLineError($"Handle StartLiveNotification ex:{ex}");
}
}
}
private void OnPreviewCameraCaptured(object sender, CPVideoFrameData data)
{
if (data == null || data.Data == null)
{
return;
}
if (_cameraPreviewHeight != data.Height || _cameraPreviewWidth != data.Width)
{
_cameraPreviewHeight = data.Height;
_cameraPreviewWidth = data.Width;
CameraPreviewImageSizeChanged?.Invoke(this, new ImageSize(_cameraPreviewWidth, _cameraPreviewHeight));
}
PreviewCameraCaptured?.Invoke(this, data.Data);
}
private void DoDispose()
{
if (!_disposed)
{
lock (CPCombineSmartPushConfiguration.Instance)
{
try
{
Logger.WriteLineInfo($"DoDispose:Handle CloseLiveNotification begin");
CPCombineSmartPushConfiguration.Instance.PushUrl = string.Empty;
if (LiveClient != null)
{
LiveClient.SetPushStatus(EnumLivePushStatus.Ide);
LiveClient.Stop();
LiveClient.Dispose();
LiveClient = null;
}
Logger.WriteLineInfo($"DoDispose:Handle CloseLiveNotification end");
}
catch (Exception ex)
{
Logger.WriteLineError($"Handle CloseLiveNotification ex:{ex}");
}
finally
{
CPCombineSmartPushConfiguration.Instance.LiveServiceUrl = string.Empty;
}
}
_leaf.MessageArrived -= OnMessageArrived;
_disposed = true;
}
}
public void Dispose()
{
DoDispose();
GC.SuppressFinalize(this);
}
private void NotifyLiveEnabledChanged()
{
try
{
using (var changeTerminalSupportLiveRequest = new ChangeTerminalLiveEnabledRequest
{ TerminalLiveEnabled = _isLiveVideoEnabled, TerminalName = _terminalName, CameraLiveEnabled = _isCameraLiveEnabled })
{
var changeTerminalSupportLiveServerResult = _leaf.Send(changeTerminalSupportLiveRequest);
var changeTerminalSupportLiveResult = ResultMessage.Convert(changeTerminalSupportLiveServerResult);
if (changeTerminalSupportLiveResult != CCR.OK)
{
Logger.WriteLineError($"On_isCameraLiveEnabledChanged notification failed, _isCameraLiveEnabled:{_isCameraLiveEnabled}");
}
}
}
catch (Exception e)
{
Logger.WriteLineError($"On_isCameraLiveEnabledChanged notification, _isCameraLiveEnabled:{_isCameraLiveEnabled}, ex: {e}");
}
}
///
/// Change CameraSettings to upload server hardware info
///
///
///
///
///
///
///
public void ChangeCameraSettings(bool enableCameraLive, string cameraId, string micId, bool showPreviewImage,
bool enableLiveVideo, bool isMute)
{
lock (CPCombineSmartPushConfiguration.Instance)
{
var pushConfiguration = CPCombineSmartPushConfiguration.Instance;
var needNotifyToServer = false;
var needNotifyLiveStatus = false;
if (enableCameraLive && enableLiveVideo)
{
pushConfiguration.Mode = EnumPushMode.CombineTerminal;
pushConfiguration.PushDataSourceType = EnumPushDataSourceType.ScreenAndCamera;
}
else if (enableLiveVideo)
{
pushConfiguration.Mode = EnumPushMode.Screen;
pushConfiguration.PushDataSourceType = EnumPushDataSourceType.Screen;
}
else
{
pushConfiguration.Mode = EnumPushMode.Camera;
pushConfiguration.PushDataSourceType = EnumPushDataSourceType.Camera;
}
pushConfiguration.VideoDevicePath = cameraId;
if (!enableCameraLive)
{
cameraId = null;
showPreviewImage = false;
}
pushConfiguration.AudioDevicePath = micId;
//是否停止推送
bool stopliveClient = false;
if (_isLiveVideoEnabled != enableLiveVideo && !enableLiveVideo)
{
stopliveClient = true;
}
else if (_isCameraLiveEnabled != enableCameraLive && enableCameraLive && enableLiveVideo) //单路切换双路
{
stopliveClient = true;
Logger.WriteLineInfo($"LiveVideo Screen to ScreenAndCamera");
}
else if (_isLiveVideoEnabled != enableLiveVideo && enableCameraLive && enableLiveVideo) //单路切换双路
{
stopliveClient = true;
Logger.WriteLineInfo($"LiveVideo Camera to ScreenAndCamera");
}
else if (_isCameraLiveEnabled != enableCameraLive && !enableCameraLive && enableLiveVideo) //双路切换单路
{
stopliveClient = true;
Logger.WriteLineInfo($"LiveVideo ScreenAndCamera to Screen");
}
if (_cameraId != pushConfiguration.VideoDevicePath && pushConfiguration.ShouldPushData)//切换摄像头
{
stopliveClient = true;
Logger.WriteLineInfo($"LiveVideo Change Camera");
}
if (_micId != pushConfiguration.AudioDevicePath && pushConfiguration.ShouldPushData)//切换麦克风
{
stopliveClient = true;
Logger.WriteLineInfo($"LiveVideo Change Mic");
}
if (stopliveClient)
{
pushConfiguration.ShowPreviewImage = false;
pushConfiguration.IsMute = true;
LiveClient?.Stop(); // stop and set default
LiveClient?.SetPushStatus(EnumLivePushStatus.Ide);
}
if (!enableCameraLive)//未开摄像头默认静音 true
{
isMute = true;
}
var cameraMute = isMute; //isMute true 静音
pushConfiguration.IsMute = cameraMute;
if (!cameraMute)
{
pushConfiguration.AudioMode = EnumAudioMode.Mic;
}
if (enableCameraLive && enableLiveVideo && showPreviewImage)
{
pushConfiguration.ShowPreviewImage = true;
LiveVideoStatusChecker.Instance.IsPreviewing = true;
}
else
{
pushConfiguration.ShowPreviewImage = false;
LiveVideoStatusChecker.Instance.IsPreviewing = false;
}
if (_previewCameraEnabled != pushConfiguration.ShowPreviewImage)//是否预览
{
_previewCameraEnabled = pushConfiguration.ShowPreviewImage;
if (!pushConfiguration.ShouldPushData)//不在推流
{
if (_previewCameraEnabled)//只是本地预览
{
LiveClient?.StartOnlyPreviewImage();
}
else
{
if (!stopliveClient)
{
LiveClient?.SetPreviewCamera(_previewCameraEnabled);
}
}
}
else
{
if (!stopliveClient)
{
LiveClient?.SetPreviewCamera(_previewCameraEnabled);
}
}
}
if (_cameraId != pushConfiguration.VideoDevicePath)//切换摄像头
{
_cameraId = pushConfiguration.VideoDevicePath;
needNotifyToServer = true;
if (!stopliveClient)
{
LiveClient?.ChangeCamera(_cameraId);
}
Logger.WriteLineInfo($"Change Camera Setting: Camera Id Changed:{_cameraId}");
}
if (_micId != pushConfiguration.AudioDevicePath)
{
_micId = pushConfiguration.AudioDevicePath;
if (!stopliveClient)
{
LiveClient?.ChangeMic(_micId);
}
Logger.WriteLineInfo($"Change Camera Setting: Audio Id Changed:{_micId}");
}
if (_cameraMute != cameraMute)
{
_cameraMute = cameraMute;
_liveClient?.SetMute(_cameraMute);
Logger.WriteLineInfo($"Change Camera Setting: Camera Mute Changed:{_cameraMute}");
}
if (_isLiveVideoEnabled != enableLiveVideo)
{
needNotifyToServer = true;
needNotifyLiveStatus = true;
_isLiveVideoEnabled = enableLiveVideo;
Logger.WriteLineInfo($"Change Camera Setting: Live Video Enabled Changed:{_isLiveVideoEnabled}");
}
if (_isCameraLiveEnabled != enableCameraLive)
{
needNotifyLiveStatus = true;
needNotifyToServer = true;
_isCameraLiveEnabled = enableCameraLive;
Logger.WriteLineInfo($"Change Camera Setting: Camera Live Enabled Changed:{_isCameraLiveEnabled}");
}
if (needNotifyLiveStatus)
{
NotifyLiveEnabledChanged();
}
if (needNotifyToServer && _isLiveVideoEnabled)
{
_liveClient?.NotifyStatusAndResolutions(_terminalId);
}
}
}
///
/// Speed live test network and auto select good network to server
///
///
public bool StartSpeedTest()
{
bool speedTest = false;
if (_liveClient != null)
{
speedTest = _liveClient.StartSpeedTest();
}
return speedTest;
}
private void InvokeLiveProtocolChanged(LiveProtocol liveProtocol)
{
LiveProtocolChanged?.Invoke(this, liveProtocol);
}
private void OnLiveProtocolChanged(object sender, LiveProtocol liveProtocol)
{
_liveProtocol = liveProtocol;
InvokeLiveProtocolChanged(_liveProtocol);
}
private void OnLiveNotification(object sender, LiveNotificationArgs e)
{
LiveNotification?.Invoke(this, e);
}
public void ChangeCameraSettingsForSonopost(bool showPreviewImage, EnumLiveChannelCategory previewLiveChannel, IEnumerable infos, RainbowImageDetectConfig rainbowImageCheckConfig, string micId, bool isMute)
{
throw new NotImplementedException();
}
///
/// 获取品牌列表
///
///
public List GetBrandList()
{
return new List();
}
///
/// 获取型号列表
///
///
///
///
public List GetModelList(string brand)
{
return new List();
}
///
/// 获取推荐分辨率
///
///
///
///
public DeviceRecommandResolution GetRecommandResolution(string brand, string model)
{
return null;
}
}
}