降低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 SHH.CameraSdk.HikFeatures;
@@ -487,20 +488,27 @@ public class HikVideoSource : BaseVideoSource,
return;
}
// =================================================================================
// 🚀 [新增代码] 尝试开启 GPU 硬解码 (1=开启, 0=关闭)
// 位置:必须在 OpenStream 成功之后SetDecCallBack 之前
// =================================================================================
try
{
HikPlayMethods.PlayM4_SetHardWareDecode(_playPort, 1);
_sdkLog.Information($"[Perf] Hik 尝试开启硬解码. ID:{_config.Id} Port:{_playPort}");
}
catch (Exception ex)
{
// 即使失败也不影响流程,仅记录警告
_sdkLog.Warning($"[Perf] Hik 开启硬解码失败: {ex.Message}");
}
//// =================================================================================
//// 🚀 [新增代码] 性能优化:适配新版 SDK 开启硬解码
//// =================================================================================
//try
//{
// // 尝试调用 Ex 版本的接口 (参数 2 表示 D3D11 硬解)
// if (HikPlayMethods.PlayM4_SetDecodeEngineEx(_playPort, 1))
// {
// _sdkLog.Information($"[Perf] Hik 强制硬解码(SetDecodeEngineEx)已开启. ID:{_config.Id}");
// }
// else
// {
// // 如果返回 false打印一下错误码
// uint err = HikPlayMethods.PlayM4_GetLastError(_playPort);
// _sdkLog.Warning($"[Perf] Hik 硬解码开启失败 Err={err}.");
// }
//}
//catch (EntryPointNotFoundException)
//{
// _sdkLog.Warning($"[Perf] PlayM4_SetDecodeEngineEx 也没找到,这太奇怪了。");
//}
HikPlayMethods.PlayM4_SetDecCallBackEx(_playPort, _decCallBack, IntPtr.Zero, 0);
@@ -536,7 +544,7 @@ public class HikVideoSource : BaseVideoSource,
/// <param name="nReserved2"></param>
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
private void SafeOnDecodingCallBack(int nPort, IntPtr pBuf, int nSize, ref HikPlayMethods.FRAME_INFO pFrameInfo, int nReserved1, int nReserved2)
private unsafe void SafeOnDecodingCallBack(int nPort, IntPtr pBuf, int nSize, ref HikPlayMethods.FRAME_INFO pFrameInfo, int nReserved1, int nReserved2)
{
//Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")} 帧抵达.");
@@ -633,11 +641,35 @@ public class HikVideoSource : BaseVideoSource,
smartFrame = _framePool.Get();
if (smartFrame == null) return; // 池满丢帧
// Optimized: [原因] 使用局部作用域封装 YUV 转换,确保原生指针尽快脱离
using (var rawYuvWrapper = Mat.FromPixelData(currentHeight + currentHeight / 2, currentWidth, MatType.CV_8UC1, pBuf))
{
Cv2.CvtColor(rawYuvWrapper, smartFrame.InternalMat, ColorConversionCodes.YUV2BGR_YV12);
}
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
);
//// Optimized: [原因] 使用局部作用域封装 YUV 转换,确保原生指针尽快脱离
//using (var rawYuvWrapper = Mat.FromPixelData(currentHeight + currentHeight / 2, currentWidth, MatType.CV_8UC1, pBuf))
//{
// Cv2.CvtColor(rawYuvWrapper, smartFrame.InternalMat, ColorConversionCodes.YUV2BGR_YV12);
//}
// =========================================================
// 【新增防御】: 检查转换结果是否有效