123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- using SkiaSharp;
- using System;
- using System.Diagnostics;
- using System.IO;
- using System.Runtime.InteropServices;
- using System.Threading;
- using System.Threading.Tasks;
- using Vinno.IUS.Common.Log;
- using Vinno.IUS.Common.Utilities;
- using Vinno.vCloud.Common.Vid2;
- using Vinno.vCloud.Common.Vid2.Visuals;
- using Vinno.vCloud.FIS.CrossPlatform.Common.LiveVideo;
- namespace Vinno.vCloud.Common.FIS.LiveVideos
- {
- internal class RealTimeCaptureManager
- {
- private readonly string _storagePath;
- private bool _isTimeOut;
- private bool _isBusy;
- private int _freeTimes;//一次代表300ms
- /// <summary>
- /// Raised when capture image generated.(only for new server)
- /// </summary>
- public event EventHandler<string> CaptureImageGenerated;
- /// <summary>
- /// Raised when record video generated.(only for new server)
- /// </summary>
- public event EventHandler<string> RecordVideoGenerated;
- public RealTimeCaptureManager()
- {
- _storagePath = Path.Combine(vCloudTerminalV2.WorkingFolder, "RealTimeCaptureCache");
- DirectoryHelper.CreateDirectory(_storagePath);
- }
- /// <summary>
- /// 检查录制完而没有来得及上传就断网的视频
- /// </summary>
- public void ReUploadRestVid()
- {
- try
- {
- var restFiles = Directory.GetFiles(_storagePath);
- if (restFiles != null)
- {
- foreach (var restFile in restFiles)
- {
- if (!restFile.EndsWith(".vid"))
- {
- FileHelper.DeleteFile(restFile);
- }
- else
- {
- if (LiveVideoStatusChecker.Instance.IsRealTimeCapturing)
- {
- bool isVideo = false;
- using (var vinnoImage = new VinnoImageData(restFile, OperationMode.Open))
- {
- isVideo = vinnoImage.ImageCount > 1;
- }
- if (isVideo)
- {
- RecordVideoGenerated?.Invoke(this, restFile);
- }
- else
- {
- CaptureImageGenerated?.Invoke(this, restFile);
- }
- }
- else
- {
- FileHelper.DeleteFile(restFile);
- }
- }
- }
- }
- }
- catch (Exception ex)
- {
- Logger.WriteLineError($"RealTimeCaptureManager ReUploadRestVid Error:{ex}");
- }
- }
- public void CaptureCurrentImage()
- {
- if (!LiveVideoStatusChecker.Instance.IsRealTimeCapturing)
- {
- Logger.WriteLineError($"CaptureCurrentImage Error,RealTimeCapture is not start");
- return;
- }
- var image = LiveVideoStatusChecker.Instance.GetCaptureImage();
- if (image == null)
- {
- Logger.WriteLineError($"CaptureCurrentImage Error,Current Capture Image is null");
- return;
- }
- else
- {
- var id = IdHelper.Generate<string>();
- var filePath = Path.Combine(_storagePath, $"{id}.vid");
- if (GenerateSingleFrameVid(filePath, image))
- {
- CaptureImageGenerated?.Invoke(this, filePath);
- }
- else
- {
- Logger.WriteLineError($"GenerateSingleFrameVid Failed");
- }
- }
- }
- private bool GenerateSingleFrameVid(string filePath, CPVideoFrameData image)
- {
- try
- {
- using (var vinnoImageData = new VinnoImageData(filePath, OperationMode.Create))
- {
- var probe = new VinnoProbe("ThirdPart", VinnoProbeType.Linear, new VinnoApplication("ThirdPart", string.Empty, "ThirdPart", "ThirdPart", false), 1);
- vinnoImageData.AddProbe(probe);
- if (image.Data == null || image.Data.Length <= 0)
- {
- return false;
- }
- if (image.Width <= 0 || image.Height <= 0)
- {
- return false;
- }
- VinnoImage vinnoImage = new VinnoImage(0, image.Width, image.Height, GetImage(image.Width, image.Height, image.Data));
- var visual = new Vinno2DVisual();
- visual.Modes.Add(new VinnoMode("HAR", "HAR", VinnoModeType.Tissue));
- visual.ActiveModeType = VinnoModeType.Tissue;
- var physicalCoordinateInfo = new VinnoLinearTVTissuePhysicalCoordinate(1, 0, 1, 0, 0);
- var logicalCoordinateInfo = new VinnoLogicalCoordinate(false, false,
- new VinnoRect(0, 0, 1, 1), VinnoUnit.None, VinnoUnit.None);
- visual.PhysicalCoordinates.Add(VinnoVisualAreaType.Tissue, physicalCoordinateInfo);
- visual.LogicalCoordinates.Add(VinnoVisualAreaType.Tissue, logicalCoordinateInfo);
- vinnoImage.Visuals.Add(visual);
- vinnoImageData.AddImage(vinnoImage);
- }
- if (File.Exists(filePath))
- {
- return true;
- }
- else
- {
- Logger.WriteLineError($"GenerateSingleFrameVid Failed,{filePath} is not exist");
- return false;
- }
- }
- catch (Exception ex)
- {
- Logger.WriteLineError($"GenerateSingleFrameVid Error:{ex}");
- return false;
- }
- }
- private byte[] GetImage(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);
- return bytes;
- }
- }
- 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())
- {
- if (_isBusy)
- {
- Logger.WriteLineError("RealTimeManager StartRecordVideo Fail, it is busy");
- return;
- }
- _isBusy = true;
- _isTimeOut = false;
- _freeTimes = 0;
- Task.Run(() =>
- {
- var stopwatch = new Stopwatch();
- stopwatch.Start();
- try
- {
- var id = IdHelper.Generate<string>();
- var filePath = Path.Combine(_storagePath, $"{id}.vid");
- using (var vinnoImageData = new VinnoImageData(filePath, OperationMode.Create))
- {
- int index = 0;
- int freeTimes = 0;
- while (LiveVideoStatusChecker.Instance.IsRecording)
- {
- var image = LiveVideoStatusChecker.Instance.GetRecordImage();
- if (image != null && image.Height > 0 && image.Width > 0 && image.Data != null && image.Data.Length > 0)
- {
- freeTimes = 0;
- VinnoImage vinnoImage = new VinnoImage(index, image.Width, image.Height, GetImage(image.Width, image.Height, image.Data));
- var visual = new Vinno2DVisual();
- visual.Modes.Add(new VinnoMode("HAR", "HAR", VinnoModeType.Tissue));
- visual.ActiveModeType = VinnoModeType.Tissue;
- var physicalCoordinateInfo = new VinnoLinearTVTissuePhysicalCoordinate(1, 0, 1, 0, 0);
- var logicalCoordinateInfo = new VinnoLogicalCoordinate(false, false,
- new VinnoRect(0, 0, 1, 1), VinnoUnit.None, VinnoUnit.None);
- visual.PhysicalCoordinates.Add(VinnoVisualAreaType.Tissue, physicalCoordinateInfo);
- visual.LogicalCoordinates.Add(VinnoVisualAreaType.Tissue, logicalCoordinateInfo);
- vinnoImage.Visuals.Add(visual);
- vinnoImageData.AddImage(vinnoImage);
- index++;
- }
- else
- {
- freeTimes++;
- if (freeTimes >= 30)//若300ms没有来图
- {
- _freeTimes++;
- freeTimes = 0;
- }
- Thread.Sleep(10);
- }
- }
- stopwatch.Stop();
- bool processFinished = false;
- while (!processFinished)
- {
- var image = LiveVideoStatusChecker.Instance.GetRecordImage();
- if (image != null && image.Height > 0 && image.Width > 0 && image.Data != null && image.Data.Length > 0)
- {
- VinnoImage vinnoImage = new VinnoImage(index, image.Width, image.Height, GetImage(image.Width, image.Height, image.Data));
- var visual = new Vinno2DVisual();
- visual.Modes.Add(new VinnoMode("HAR", "HAR", VinnoModeType.Tissue));
- visual.ActiveModeType = VinnoModeType.Tissue;
- var physicalCoordinateInfo = new VinnoLinearTVTissuePhysicalCoordinate(1, 0, 1, 0, 0);
- var logicalCoordinateInfo = new VinnoLogicalCoordinate(false, false,
- new VinnoRect(0, 0, 1, 1), VinnoUnit.None, VinnoUnit.None);
- visual.PhysicalCoordinates.Add(VinnoVisualAreaType.Tissue, physicalCoordinateInfo);
- visual.LogicalCoordinates.Add(VinnoVisualAreaType.Tissue, logicalCoordinateInfo);
- vinnoImage.Visuals.Add(visual);
- vinnoImageData.AddImage(vinnoImage);
- index++;
- }
- else
- {
- processFinished = true;
- }
- }
- if (stopwatch.ElapsedMilliseconds > 0 && vinnoImageData.ImageCount > 0)
- {
- var imageCount = index + 1;
- double frameRate;
- if (_isTimeOut)
- {
- frameRate = (double)(decimal)imageCount * 1000 / (30000 - _freeTimes * 300);
- }
- else
- {
- frameRate = (double)(decimal)imageCount * 1000 / (stopwatch.ElapsedMilliseconds - _freeTimes * 300);
- }
- var probe = new VinnoProbe("ThirdPart", VinnoProbeType.Linear, new VinnoApplication("ThirdPart", string.Empty, "ThirdPart", "ThirdPart", false), frameRate);
- vinnoImageData.AddProbe(probe);
- }
- else
- {
- Logger.WriteLineError($"Generate Record Video Vid Failed:ImageCount:{vinnoImageData.ImageCount},Index:{index}");
- return;
- }
- }
- if (File.Exists(filePath))
- {
- RecordVideoGenerated?.Invoke(this, filePath);
- }
- else
- {
- Logger.WriteLineError($"GenerateVideoRecordVid Failed,{filePath} is not exist");
- }
- }
- catch (Exception ex)
- {
- Logger.WriteLineError($"Generate Record Video Vid Failed:{ex}");
- stopwatch.Stop();
- }
- finally
- {
- _isBusy = false;
- }
- });
- }
- }
- public void StopRecordVideo(bool isTimeOut)
- {
- _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();
- }
- }
- }
|