降低CPU使用率,处置好因降低CPU使用率带来的颜色偏差

This commit is contained in:
2026-01-31 10:43:41 +08:00
parent 6661edfc44
commit 4afbf06439
17 changed files with 360 additions and 64 deletions

View File

@@ -1,4 +1,5 @@
using Ayay.SerilogLogs;
using Lennox.LibYuvSharp;
using OpenCvSharp;
using Serilog;
using System.Runtime.ExceptionServices;
@@ -92,7 +93,7 @@ public class DahuaVideoSource : BaseVideoSource
{
string err = NETClient.GetLastError();
NETClient.Logout(_loginId);
throw new Exception($"大华预览失败: {err}");
throw new Exception($"大华预览失败, {err}");
}
_sdkLog.Information($"[SDK] Dahua 取流成功 => RealPlayID:{_realPlayId}");
@@ -184,6 +185,8 @@ public class DahuaVideoSource : BaseVideoSource
// =================================================================================
try
{
_sdkLog.Information($"[Perf] Dahua 尝试开启硬解码. ID:{_config.Id} Port:{_playPort}");
// nDecodeEngine: 1 = 开启硬解码 (Nvidia/Intel)
// 注意:大华 SDK 若不支持会自动降级try-catch 仅为了防止 P/Invoke 签名缺失崩溃
// Optimized: 使用新版接口开启硬件解码,优先尝试 CUDA 以保证 Ayay 的多路并发性能
@@ -195,7 +198,6 @@ public class DahuaVideoSource : BaseVideoSource
// 如果显卡不支持 CUDA降级为普通硬解或软解
PLAY_SetEngine(_playPort, DecodeType.DECODE_HW, RenderType.RENDER_D3D9);
}
_sdkLog.Information($"[Perf] Dahua 尝试开启硬解码. ID:{_config.Id} Port:{_playPort}");
}
catch (Exception ex)
{
@@ -223,7 +225,7 @@ public class DahuaVideoSource : BaseVideoSource
/// </summary>
[HandleProcessCorruptedStateExceptions] // 捕获非托管状态损坏异常 (AccessViolation)
[SecurityCritical]
private void SafeOnDecodingCallBack(int nPort, IntPtr pBuf, int nSize, ref DahuaPlaySDK.FRAME_INFO pFrameInfo, IntPtr nUser, int nReserved2)
private unsafe void SafeOnDecodingCallBack(int nPort, IntPtr pBuf, int nSize, ref DahuaPlaySDK.FRAME_INFO pFrameInfo, IntPtr nUser, int nReserved2)
{
// 1. 基础指针检查
if (pBuf == IntPtr.Zero || nSize <= 0) return;
@@ -307,15 +309,37 @@ public class DahuaVideoSource : BaseVideoSource
smartFrame = _framePool?.Get();
if (smartFrame == null) return; // 池满丢帧
// =========================================================================================
// ⚡ [核心操作:零拷贝转换]
// 大华 PlaySDK 默认输出 I420 (YUV420P)。
// 使用 Mat.FromPixelData 封装指针,避免内存拷贝。
// =========================================================================================
using (var yuvMat = Mat.FromPixelData(currentHeight + currentHeight / 2, currentWidth, MatType.CV_8UC1, pBuf))
{
Cv2.CvtColor(yuvMat, smartFrame.InternalMat, ColorConversionCodes.YUV2BGR_I420);
}
int width = pFrameInfo.nWidth;
int height = pFrameInfo.nHeight;
// 计算 YUV 分量地址
byte* pY = (byte*)pBuf;
byte* pU = pY + (width * height);
byte* pV = pU + (width * height / 4);
// 目标 BGR 地址
byte* pDst = (byte*)smartFrame.InternalMat.Data;
// 调用 LibYuvSharp
// 注意LibYuvSharp 内部通常处理的是 BGR 顺序,
// 如果发现图像发蓝,请将 pU 和 pV 的位置对调
LibYuv.I420ToRGB24(
pY, width,
pU, width / 2,
pV, width / 2,
pDst, width * 3,
width, height
);
//// =========================================================================================
//// ⚡ [核心操作:零拷贝转换]
//// 大华 PlaySDK 默认输出 I420 (YUV420P)。
//// 使用 Mat.FromPixelData 封装指针,避免内存拷贝。
//// =========================================================================================
//using (var yuvMat = Mat.FromPixelData(currentHeight + currentHeight / 2, currentWidth, MatType.CV_8UC1, pBuf))
//{
// Cv2.CvtColor(yuvMat, smartFrame.InternalMat, ColorConversionCodes.YUV2BGR_I420);
//}
// =========================================================================================
// 🛡️ [第三道防线:空结果防御]