Эх сурвалжийг харах

魔盒新增API GetCurrentCaptureFrame新版云服务连接中,直播开启,图像采集开启的前提下,可以得到预览画面。

felix 11 сар өмнө
parent
commit
3731ca0c8d

+ 5 - 0
FISSDK/FISIMPL/LiveVideoServiceForAndroid.cs

@@ -523,5 +523,10 @@ namespace FISIMPL
         {
             throw new NotImplementedException();
         }
+
+        public FISBase64ImageData GetCurrentCaptureFrame()
+        {
+            throw new NotImplementedException();
+        }
     }
 }

+ 44 - 1
FISSDK/FISIMPL/LiveVideoServiceForWindows.cs

@@ -23,7 +23,7 @@ namespace FISIMPL
         private PipeClient _pipeClient;
         private PipeServer _pipeServer;
         private FISImageFrameData _imageFrameData;
-
+        private FISBase64ImageData _tempBase64ImageData;
         /// <summary>
         /// Raised when local camera live execute
         /// </summary>
@@ -677,6 +677,7 @@ namespace FISIMPL
                     if (_liveVideoV2 == null)
                     {
                         Logger.WriteLineError($"ReUploadRestVid error: live videoV2 feature is null");
+                        return;
                     }
                     _liveVideoV2.ReUploadRestVid();
                 }
@@ -686,5 +687,47 @@ namespace FISIMPL
                 Logger.WriteLineError($"LiveVideoServiceForWindows StopRecordVideo Error:{ex}");
             }
         }
+
+        public FISBase64ImageData GetCurrentCaptureFrame()
+        {
+            try
+            {
+                if (FISIMPL.IsConnectWithOldServer)
+                {
+                    Logger.WriteLineError($"GetCurrentCaptureFrame error: old Server doesn't support");
+                    return new FISBase64ImageData(0, 0, "", FailReasonForNullBase64Data.OldServerNotSupport);
+                }
+                else
+                {
+                    if (_liveVideoV2 == null)
+                    {
+                        Logger.WriteLineError($"GetCurrentCaptureFrame error: live videoV2 feature is null");
+                        return new FISBase64ImageData(0, 0, "", FailReasonForNullBase64Data.vCloudIsDisconnected);
+                    }
+                    var videoFrameData = _liveVideoV2.GetCurrentCaptureFrame();
+                    if (videoFrameData == null)
+                    {
+                        return new FISBase64ImageData(0, 0, "", FailReasonForNullBase64Data.Unknown);
+                    }
+                    else if (_tempBase64ImageData == null)
+                    {
+                        _tempBase64ImageData = new FISBase64ImageData(videoFrameData.Width, videoFrameData.Height, "");
+                    }
+                    else if (_tempBase64ImageData.Width != videoFrameData.Width || _tempBase64ImageData.Height != videoFrameData.Height)
+                    {
+                        _tempBase64ImageData.Width = videoFrameData.Width;
+                        _tempBase64ImageData.Height = videoFrameData.Height;
+                    }
+                    _tempBase64ImageData.Base64Data = videoFrameData.Base64Data;
+                    _tempBase64ImageData.FailMsg = (FailReasonForNullBase64Data)videoFrameData.FailMsg;
+                    return _tempBase64ImageData;
+                }
+            }
+            catch (Exception ex)
+            {
+                Logger.WriteLineError($"LiveVideoServiceForWindows GetCurrentCaptureFrame Error:{ex}");
+                return null;
+            }
+        }
     }
 }

+ 31 - 0
FISSDK/FISSDK/LiveVideo/FISBase64ImageData.cs

@@ -0,0 +1,31 @@
+namespace FISLib.LiveVideo
+{
+    public class FISBase64ImageData
+    {
+        public int Width { get; set; }
+
+        public int Height { get; set; }
+
+        public string Base64Data { get; set; }
+
+        public FailReasonForNullBase64Data FailMsg { get; set; }
+
+        public FISBase64ImageData(int width, int height, string base64Data, FailReasonForNullBase64Data failMsg = FailReasonForNullBase64Data.None)
+        {
+            Width = width;
+            Height = height;
+            Base64Data = base64Data;
+            FailMsg = failMsg;
+        }
+    }
+
+    public enum FailReasonForNullBase64Data
+    {
+        None,//无
+        OldServerNotSupport,//老版本服务器不支持
+        vCloudIsDisconnected,//云服务未连接
+        LiveVideoIsDisabled,//直播未开启
+        RealTimeCaptureIsDisabled,//实时采集功能未开启
+        Unknown,//未知错误
+    }
+}

+ 6 - 0
FISSDK/FISSDK/LiveVideo/ILiveVideoService.cs

@@ -93,5 +93,11 @@ namespace FISLib.LiveVideo
         /// 重新上传未来得及上传的VID文件
         /// </summary>
         void ReUploadRestVid();
+
+        /// <summary>
+        /// 获取采集卡当前预览画面
+        /// </summary>
+        /// <returns></returns>
+        FISBase64ImageData GetCurrentCaptureFrame();
     }
 }

+ 6 - 0
Vinno.FIS.Sonopost/Managers/Interfaces/ILiveVideoManager.cs

@@ -73,5 +73,11 @@ namespace Vinno.FIS.Sonopost.Managers.Interfaces
         /// 超声采集卡名称
         /// </summary>
         FISCameraInfo SonoDevice { get; }
+
+        /// <summary>
+        /// 获取当前采集卡画面
+        /// </summary>
+        /// <returns></returns>
+        FISBase64ImageData GetCurrentCaptureFrame();
     }
 }

+ 13 - 0
Vinno.FIS.Sonopost/Managers/LiveVideoManager.cs

@@ -520,5 +520,18 @@ namespace Vinno.FIS.Sonopost.Managers
                     break;
             }
         }
+
+        public FISBase64ImageData GetCurrentCaptureFrame()
+        {
+            try
+            {
+                return _fisLiveVideoService.GetCurrentCaptureFrame();
+            }
+            catch (Exception ex)
+            {
+                Logger.WriteLineError($"LiveVideoManager GetCurrentCaptureFrame Error:{ex}");
+                return new FISBase64ImageData(0, 0, "", FailReasonForNullBase64Data.Unknown);
+            }
+        }
     }
 }

+ 22 - 0
Vinno.FIS.Sonopost/WebApi/Controllers/LiveController.cs

@@ -494,5 +494,27 @@ namespace Vinno.FIS.Sonopost.WebApi.Controllers
         {
             return Result.Success(SonopostSystemSettings.Instance.SkippedSpeakerDeviceNames);
         }
+
+        [WebApiAction]
+        public Result GetCurrentPreviewImage()
+        {
+            try
+            {
+                var image = LiveVideoManager.GetCurrentCaptureFrame();
+                if (image == null)
+                {
+                    return Result.Success(new FISBase64ImageData(0, 0, "", FailReasonForNullBase64Data.Unknown));
+                }
+                else
+                {
+                    return Result.Success(image);
+                }
+            }
+            catch (Exception ex)
+            {
+                Logger.WriteLineError($"[{nameof(LiveController)}]{nameof(GetCurrentPreviewImage)} error: {ex}");
+                return Result.Fail();
+            }
+        }
     }
 }

+ 6 - 0
Vinno.vCloud.Common.FIS/LiveVideos/ILiveVideoV2.cs

@@ -99,5 +99,11 @@ namespace Vinno.vCloud.Common.FIS.LiveVideos
         /// 重新上传剩余未上传的Vid
         /// </summary>
         void ReUploadRestVid();
+
+        /// <summary>
+        /// 获取采集画面
+        /// </summary>
+        /// <returns></returns>
+        CPBase64ImageData GetCurrentCaptureFrame();
     }
 }

+ 23 - 0
Vinno.vCloud.Common.FIS/LiveVideos/LiveVideoV2.cs

@@ -40,6 +40,7 @@ namespace Vinno.vCloud.Common.FIS.LiveVideos
         private readonly int _usScreenWidth;
         private readonly int _usScreenHeight;
 
+        private bool _isMainLiveVideoDisabled;
         private string _currentHeartRateCode;
         private bool _disposed;
         private bool _liveVideoEnabled;
@@ -449,6 +450,7 @@ namespace Vinno.vCloud.Common.FIS.LiveVideos
                     _realtimeCaptureManager.CaptureImageGenerated -= OnCaptureImageGenerated;
                     _realtimeCaptureManager.RecordVideoGenerated -= OnRecordVideoGenerated;
                     _realtimeCaptureManager.StopRecordVideo(false);
+                    _realtimeCaptureManager.ClearImageCache();
                 }
                 _disposed = true;
             }
@@ -505,6 +507,7 @@ namespace Vinno.vCloud.Common.FIS.LiveVideos
                     _cameraId = cameraId;
                     needNotifyServer = true;
                 }
+                _isMainLiveVideoDisabled = !enableLiveVideo;
                 if (_liveVideoEnabled != enableLiveVideo)
                 {
                     _liveVideoEnabled = enableLiveVideo;
@@ -572,6 +575,16 @@ namespace Vinno.vCloud.Common.FIS.LiveVideos
                 }
                 else
                 {
+                    var mainInfo = infos.FirstOrDefault(x => x.Category == EnumLiveChannelCategory.Main);
+                    if (mainInfo == null)//关闭主通道直播
+                    {
+                        _realtimeCaptureManager?.ClearImageCache();
+                        _isMainLiveVideoDisabled = true;
+                    }
+                    else
+                    {
+                        _isMainLiveVideoDisabled = false;
+                    }
                     var newInfos = new List<CPVideoDeviceOutputInfo>();
                     foreach (var info in infos)
                     {
@@ -605,6 +618,7 @@ namespace Vinno.vCloud.Common.FIS.LiveVideos
                         };
                         newInfos.Add(item);
                     }
+
                     if (newInfos.Count() != _currentVideoDeviceInfoList.Count() || needNotifyServer)
                     {
                         _currentVideoDeviceInfoList.Clear();
@@ -971,5 +985,14 @@ namespace Vinno.vCloud.Common.FIS.LiveVideos
         {
             _realtimeCaptureManager?.StopRecordVideo(isTimeOut);
         }
+
+        public CPBase64ImageData GetCurrentCaptureFrame()
+        {
+            if (_isMainLiveVideoDisabled)
+            {
+                return new CPBase64ImageData(0, 0, "", EnumFailReasonForNullBase64Data.LiveVideoIsDisabled);
+            }
+            return _realtimeCaptureManager?.GetCurrentCaptureFrame();
+        }
     }
 }

+ 34 - 0
Vinno.vCloud.Common.FIS/LiveVideos/RealTimeCaptureManager.cs

@@ -171,6 +171,20 @@ namespace Vinno.vCloud.Common.FIS.LiveVideos
             }
         }
 
+        private CPBase64ImageData GetBase64Data(int width, int height, byte[] data)
+        {
+            var imagePtr = Marshal.AllocHGlobal(data.Length);
+            Marshal.Copy(data, 0, imagePtr, data.Length);
+            using (SKBitmap posterBitmap = new SKBitmap(width, height))
+            {
+                posterBitmap.SetPixels(imagePtr);
+                var bytes = posterBitmap.Encode(SKEncodedImageFormat.Jpeg, 80).ToArray();
+                Marshal.FreeHGlobal(imagePtr);
+                string base64String = Convert.ToBase64String(bytes);
+                return new CPBase64ImageData(width, height, base64String);
+            }
+        }
+
         public void StartRecordVideo()
         {
             if (LiveVideoStatusChecker.Instance.StartRecord())
@@ -298,5 +312,25 @@ namespace Vinno.vCloud.Common.FIS.LiveVideos
             _isTimeOut = isTimeOut;
             LiveVideoStatusChecker.Instance.StopRecord();
         }
+
+        public CPBase64ImageData GetCurrentCaptureFrame()
+        {
+            if (!LiveVideoStatusChecker.Instance.IsRealTimeCapturing)
+            {
+                Logger.WriteLineError($"CaptureCurrentImage Error,RealTimeCapture is not start");
+                return new CPBase64ImageData(0, 0, "", EnumFailReasonForNullBase64Data.RealTimeCaptureIsDisabled);
+            }
+            var imageData = LiveVideoStatusChecker.Instance.GetCaptureImage();
+            if (imageData == null)
+            {
+                return new CPBase64ImageData(0, 0, "", EnumFailReasonForNullBase64Data.Unknown);
+            }
+            return GetBase64Data(imageData.Width, imageData.Height, imageData.Data);
+        }
+
+        public void ClearImageCache()
+        {
+            LiveVideoStatusChecker.Instance.ClearImageCache();
+        }
     }
 }

+ 1 - 0
Vinno.vCloud.FIS.CrossPlatform.Common.Android/Vinno.vCloud.FIS.CrossPlatform.Common.Android.csproj

@@ -59,6 +59,7 @@
     <Compile Include="..\Vinno.vCloud.FIS.CrossPlatform.Common\LiveVideo\CaptureDataInfo.cs" Link="LiveVideo\CaptureDataInfo.cs" />
     <Compile Include="..\Vinno.vCloud.FIS.CrossPlatform.Common\LiveVideo\ChannelStateEventArgs.cs" Link="LiveVideo\ChannelStateEventArgs.cs" />
     <Compile Include="..\Vinno.vCloud.FIS.CrossPlatform.Common\LiveVideo\ChannelStateEventArgsV2.cs" Link="LiveVideo\ChannelStateEventArgsV2.cs" />
+    <Compile Include="..\Vinno.vCloud.FIS.CrossPlatform.Common\LiveVideo\CPBase64ImageData.cs" Link="LiveVideo\CPBase64ImageData.cs" />
     <Compile Include="..\Vinno.vCloud.FIS.CrossPlatform.Common\LiveVideo\CPCombineSmartPushConfiguration.cs" Link="LiveVideo\CPCombineSmartPushConfiguration.cs" />
     <Compile Include="..\Vinno.vCloud.FIS.CrossPlatform.Common\LiveVideo\CPDeviceResolutions.cs" Link="LiveVideo\CPDeviceResolutions.cs" />
     <Compile Include="..\Vinno.vCloud.FIS.CrossPlatform.Common\LiveVideo\CPLiveStatusData.cs" Link="LiveVideo\CPLiveStatusData.cs" />

+ 31 - 0
Vinno.vCloud.FIS.CrossPlatform.Common/LiveVideo/CPBase64ImageData.cs

@@ -0,0 +1,31 @@
+namespace Vinno.vCloud.FIS.CrossPlatform.Common.LiveVideo
+{
+    public class CPBase64ImageData
+    {
+        public int Width { get; set; }
+
+        public int Height { get; set; }
+
+        public string Base64Data { get; set; }
+
+        public EnumFailReasonForNullBase64Data FailMsg { get; set; }
+
+        public CPBase64ImageData(int width, int height, string base64Data, EnumFailReasonForNullBase64Data failMsg = EnumFailReasonForNullBase64Data.None)
+        {
+            Width = width;
+            Height = height;
+            Base64Data = base64Data;
+            FailMsg = failMsg;
+        }
+    }
+
+    public enum EnumFailReasonForNullBase64Data
+    {
+        None,//无
+        OldServerNotSupport,//老版本服务器不支持
+        vCloudIsDisconnected,//云服务未连接
+        LiveVideoIsDisabled,//直播未开启
+        RealTimeCaptureIsDisabled,//实时采集功能未开启
+        Unknown,//未知错误
+    }
+}

+ 8 - 4
Vinno.vCloud.FIS.CrossPlatform.Common/LiveVideo/LiveVideoStatusChecker.cs

@@ -252,12 +252,16 @@ namespace Vinno.vCloud.FIS.CrossPlatform.Common.LiveVideo
         {
             lock (_recordLocker)
             {
-                if (!IsRecording)
-                {
-                    return;
-                }
                 IsRecording = false;
             }
         }
+
+        public void ClearImageCache()
+        {
+            lock (_captureLocker)
+            {
+                _videoFrameData = null;
+            }
+        }
     }
 }