新增 Mjpegplayer 用来播放 Web 流

This commit is contained in:
2026-01-21 19:03:59 +08:00
parent f79cb6e74d
commit c438edfa0d
71 changed files with 4538 additions and 452 deletions

View File

@@ -1,6 +1,4 @@
using System;
using System.Runtime.InteropServices;
namespace SHH.CameraSdk;
namespace SHH.CameraSdk;
/// <summary>
/// 海康播放库 PlayCtrl.dll 的封装
@@ -343,5 +341,11 @@ public static class HikPlayMethods
[DllImport(DllName)]
public static extern bool PlayM4_ResetSourceBuffer(int nPort);
/// <summary>
/// [新增] 开启硬件解码
/// </summary>
[DllImport(DllName)]
public static extern bool PlayM4_SetHardWareDecode(int nPort, int nMode);
#endregion
}

View File

@@ -54,8 +54,8 @@ public class HikVideoSource : BaseVideoSource,
private volatile int _connectionEpoch = 0; // 连接轮询版本号
// 回调委托强引用防止GC回收
private HikNativeMethods.REALDATACALLBACK? _realDataCallBack;
private HikPlayMethods.DECCBFUN? _decCallBack;
private readonly HikNativeMethods.REALDATACALLBACK _realDataCallBack;
private readonly HikPlayMethods.DECCBFUN _decCallBack;
// 图像处理资源, 内存复用对象
private Mat? _sharedYuvMat;
@@ -77,6 +77,11 @@ public class HikVideoSource : BaseVideoSource,
_timeProvider = new HikTimeSyncProvider(this);
_rebootProvider = new HikRebootProvider(this);
_ptzProvider = new HikPtzProvider(this);
// Modified: [Fix GC Crash] 移除此处的 new REALDATACALLBACK
// 直接使用构造函数初始化的 _realDataCallBack保证委托地址在整个对象生命周期内不变
_realDataCallBack = new HikNativeMethods.REALDATACALLBACK(SafeOnRealDataReceived);
_decCallBack = new HikPlayMethods.DECCBFUN(SafeOnDecodingCallBack);
}
#endregion
@@ -424,8 +429,10 @@ public class HikVideoSource : BaseVideoSource,
bBlocked = false
};
_realDataCallBack = new HikNativeMethods.REALDATACALLBACK(SafeOnRealDataReceived);
_realPlayHandle = HikNativeMethods.NET_DVR_RealPlay_V40(_userId, ref previewInfo, _realDataCallBack, IntPtr.Zero);
// Optimized: [Fix GC Crash] 显式保活,防止 JIT 在 P/Invoke 过程中激进回收(双重保险)
GC.KeepAlive(_realDataCallBack);
return _realPlayHandle >= 0;
}
@@ -480,8 +487,26 @@ public class HikVideoSource : BaseVideoSource,
return;
}
_decCallBack = new HikPlayMethods.DECCBFUN(SafeOnDecodingCallBack);
// =================================================================================
// 🚀 [新增代码] 尝试开启 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}");
}
HikPlayMethods.PlayM4_SetDecCallBackEx(_playPort, _decCallBack, IntPtr.Zero, 0);
// Optimized: [Fix GC Crash] 显式保活
GC.KeepAlive(_decCallBack);
HikPlayMethods.PlayM4_Play(_playPort, IntPtr.Zero);
_sdkLog.Debug($"[SDK] Hik 播放端口初始化成功, ID:{_config.Id} IP:{_config.IpAddress} Port:{_config.Port} Name:{_config.Name}, UserID: {_userId}, 播放端口:{_playPort}");