using System; using System.Runtime.InteropServices; namespace SHH.CameraSdk; /// /// 海康播放库 PlayCtrl.dll 的封装 /// 完全参考官方 WinPlayCtrl.cs 定义,提供解码、播放、端口管理等核心能力 /// public static class HikPlayMethods { #region --- 基础配置 (Basic Configuration) --- /// /// PlayCtrl.dll 动态库路径 /// 注意:请确保项目中该路径与实际文件位置一致,否则会导致 DllImport 失败 /// private const string DllName = @"Drivers\\Hikvision\\PlayCtrl.dll"; #endregion #region --- 常量定义 (Constants) --- /// 最大支持的通道数 public const int PLAYM4_MAX_SUPPORTS = 500; // 流模式常量 public const int STREAME_REALTIME = 0; // 实时流模式 public const int STREAME_FILE = 1; // 文件流模式 // 帧类型常量(音频/视频) public const int T_AUDIO16 = 101; // 16位音频帧 public const int T_AUDIO8 = 100; // 8位音频帧 public const int T_UYVY = 1; // UYVY格式视频帧 public const int T_YV12 = 3; // YV12格式视频帧(常用) public const int T_RGB32 = 7; // RGB32格式视频帧 // 显示缓冲区大小常量 public const int MAX_DIS_FRAMES = 50; // 最大显示缓冲帧数 public const int MIN_DIS_FRAMES = 1; // 最小显示缓冲帧数 // 源缓冲区大小常量(单位:字节) public const int SOURCE_BUF_MAX = 1024 * 100000; // 最大源缓冲区(100MB) public const int SOURCE_BUF_MIN = 1024 * 50; // 最小源缓冲区(50KB) // 错误码常量(PlayCtrl.dll 返回错误标识) public const int PLAYM4_NOERROR = 0; // 无错误 public const int PLAYM4_PARA_OVER = 1; // 参数超出范围 public const int PLAYM4_ORDER_ERROR = 2; // 函数调用顺序错误 public const int PLAYM4_TIMER_ERROR = 3; // 定时器初始化错误 public const int PLAYM4_DEC_VIDEO_ERROR = 4; // 视频解码错误 public const int PLAYM4_DEC_AUDIO_ERROR = 5; // 音频解码错误 public const int PLAYM4_ALLOC_MEMORY_ERROR = 6; // 内存分配错误 public const int PLAYM4_OPEN_FILE_ERROR = 7; // 打开文件错误 public const int PLAYM4_CREATE_OBJ_ERROR = 8; // 创建对象错误 public const int PLAYM4_CREATE_DDRAW_ERROR = 9; // 创建DirectDraw错误 public const int PLAYM4_CREATE_OFFSCREEN_ERROR = 10;// 创建离屏表面错误 public const int PLAYM4_BUF_OVER = 11; // 缓冲区溢出 public const int PLAYM4_CREATE_SOUND_ERROR = 12; // 创建音频设备错误 public const int PLAYM4_SET_VOLUME_ERROR = 13; // 设置音量错误 public const int PLAYM4_SUPPORT_FILE_ONLY = 14; // 仅支持文件流 public const int PLAYM4_SUPPORT_STREAM_ONLY = 15; // 仅支持实时流 public const int PLAYM4_SYS_NOT_SUPPORT = 16; // 系统不支持该功能 public const int PLAYM4_FILEHEADER_UNKNOWN = 17; // 文件头格式未知 public const int PLAYM4_VERSION_INCORRECT = 18; // 版本不匹配 public const int PLAYM4_INIT_DECODER_ERROR = 19; // 解码器初始化错误 public const int PLAYM4_CHECK_FILE_ERROR = 20; // 校验文件错误 public const int PLAYM4_INIT_TIMER_ERROR = 21; // 初始化定时器错误 public const int PLAYM4_BLT_ERROR = 22; // 图像绘制错误 public const int PLAYM4_UPDATE_ERROR = 23; // 更新显示错误 // PTZ控制命令常量(保留自定义逻辑,官方示例未包含) public const uint ZOOM_IN = 11; // 焦距变大(拉近) public const uint ZOOM_OUT = 12; // 焦距变小(拉远) public const uint FOCUS_NEAR = 13; // 焦点前调 public const uint FOCUS_FAR = 14; // 焦点后调 public const uint IRIS_OPEN = 15; // 光圈扩大 public const uint IRIS_CLOSE = 16; // 光圈缩小 public const uint TILT_UP = 21; // 云台上仰 public const uint TILT_DOWN = 22; // 云台下俯 public const uint PAN_LEFT = 23; // 云台左转 public const uint PAN_RIGHT = 24; // 云台右转 public const uint UP_LEFT = 25; // 上左移动 public const uint UP_RIGHT = 26; // 上右移动 public const uint DOWN_LEFT = 27; // 下左移动 public const uint DOWN_RIGHT = 28; // 下右移动 public const uint PAN_AUTO = 29; // 云台自动扫描 #endregion #region --- 结构体定义 (Structs) --- /// /// 帧信息结构体:存储解码后帧的宽高、帧率、序号等关键信息 /// [StructLayout(LayoutKind.Sequential)] public struct FRAME_INFO { public int nWidth; // 帧宽度(像素) public int nHeight; // 帧高度(像素) public int nStamp; // 时间戳 public int nType; // 帧类型(对应 T_XXX 常量) public int nFrameRate; // 帧率(fps) public uint dwFrameNum; // 帧序号 } /// /// 帧位置结构体:存储文件流中帧的位置、时间等信息 /// [StructLayout(LayoutKind.Sequential)] public struct FRAME_POS { public int nFilePos; // 文件中的位置偏移 public int nFrameNum; // 帧序号 public int nFrameTime; // 帧时间(毫秒) public int nErrorFrameNum; // 错误帧数 public IntPtr pErrorTime; // 错误时间数组指针 public int nErrorLostFrameNum; // 丢失的错误帧数 public int nErrorFrameSize; // 错误帧大小 } /// /// 帧类型结构体:存储帧数据缓冲区、大小等信息 /// [StructLayout(LayoutKind.Sequential)] public struct FRAME_TYPE { [MarshalAs(UnmanagedType.LPStr)] public string pDataBuf; // 帧数据缓冲区指针 public int nSize; // 缓冲区大小(字节) public int nFrameNum; // 帧序号 public bool bIsAudio; // 是否为音频帧 public int nReserved; // 保留字段(置0) } #endregion #region --- 委托定义 (Delegates) --- /// /// 解码回调委托 (对应官方 DECCBFUN) /// 功能:解码完成后触发,返回解码后的帧数据 /// /// 播放端口号 /// 解码后数据缓冲区指针 /// 缓冲区大小(字节) /// 帧信息结构体(引用传递) /// 保留字段1(置0) /// 保留字段2(置0) [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate void DECCBFUN( int nPort, IntPtr pBuf, int nSize, ref FRAME_INFO pFrameInfo, int nReserved1, int nReserved2 ); /// /// 显示回调委托 (对应官方 DISPLAYCBFUN) /// 功能:帧数据准备显示时触发,用于自定义渲染逻辑 /// /// 播放端口号 /// 显示数据缓冲区指针 /// 缓冲区大小(字节) /// 显示宽度(像素) /// 显示高度(像素) /// 时间戳 /// 数据类型(对应 T_XXX 常量) /// 保留字段(置0) [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate void DISPLAYCBFUN( int nPort, IntPtr pBuf, int nSize, int nWidth, int nHeight, int nStamp, int nType, int nReserved ); /// /// 文件结束回调委托 /// 功能:文件流播放完成时触发 /// /// 播放端口号 /// 用户自定义数据指针 [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate void FILEENDCALLBACK(int nPort, IntPtr pUser); #endregion #region --- API 导入 (Dll Imports) --- /// /// 获取闲置的播放端口。 /// [警告] 此函数非线程安全,且端口资源有限(最多500个)。 /// 高并发场景下必须加全局锁,防止端口分配冲突。 /// /// 输出参数:获取到的闲置端口号(输出-1表示失败) /// 获取成功返回 true,失败返回 false [DllImport(DllName)] public static extern bool PlayM4_GetPort(ref int nPort); /// /// 释放播放端口 /// 功能:不再使用端口时调用,避免端口资源泄漏 /// /// 要释放的端口号 /// 释放成功返回 true,失败返回 false [DllImport(DllName)] public static extern bool PlayM4_FreePort(int nPort); /// /// 打开流 /// 功能:初始化端口的流缓冲区,准备接收流数据 /// /// 播放端口号 /// 文件头数据缓冲区指针(实时流可为空) /// 缓冲区大小(字节) /// 流缓冲区池大小(字节) /// 打开成功返回 true,失败返回 false [DllImport(DllName)] public static extern bool PlayM4_OpenStream(int nPort, IntPtr pFileHeadBuf, uint nSize, uint nBufPoolSize); /// /// 关闭流 /// 功能:停止接收流数据,释放流缓冲区资源 /// /// 播放端口号 /// 关闭成功返回 true,失败返回 false [DllImport(DllName)] public static extern bool PlayM4_CloseStream(int nPort); /// /// 开始播放 /// 功能:启动解码和显示流程,绑定到指定窗口句柄 /// /// 播放端口号 /// 显示窗口句柄(IntPtr.Zero 表示不绑定窗口) /// 启动成功返回 true,失败返回 false [DllImport(DllName)] public static extern bool PlayM4_Play(int nPort, IntPtr hWnd); /// /// 停止播放 /// 功能:停止解码和显示,释放播放相关资源 /// /// 播放端口号 /// 停止成功返回 true,失败返回 false [DllImport(DllName)] public static extern bool PlayM4_Stop(int nPort); /// /// 输入流数据 /// 功能:向播放端口推送原始流数据,供解码使用 /// /// 播放端口号 /// 流数据缓冲区指针 /// 数据大小(字节) /// 输入成功返回 true,失败返回 false [DllImport(DllName)] public static extern bool PlayM4_InputData(int nPort, IntPtr pBuf, uint nSize); /// /// 设置解码回调 (Ex版本) /// 功能:绑定解码完成后的回调函数,用于获取解码后的帧数据 /// /// 播放端口号 /// 解码回调函数委托 /// 目标缓冲区指针(可为空) /// 目标缓冲区大小(字节) /// 设置成功返回 true,失败返回 false [DllImport(DllName)] public static extern bool PlayM4_SetDecCallBackEx(int nPort, DECCBFUN DecCBFun, IntPtr pDest, int nDestSize); /// /// 设置流打开模式 /// 功能:指定端口接收的流类型(实时流/文件流) /// /// 播放端口号 /// 流模式(对应 STREAME_XXX 常量) /// 设置成功返回 true,失败返回 false [DllImport(DllName)] public static extern bool PlayM4_SetStreamOpenMode(int nPort, uint nMode); /// /// 设置显示缓冲区数量 /// 功能:调整显示缓冲帧数,平衡流畅度与延迟 /// /// 播放端口号 /// 缓冲帧数(范围:MIN_DIS_FRAMES ~ MAX_DIS_FRAMES) /// 设置成功返回 true,失败返回 false [DllImport(DllName)] public static extern bool PlayM4_SetDisplayBuf(int nPort, uint nNum); /// /// 设置叠加模式 /// 功能:配置图像叠加方式及透明色 /// /// 播放端口号 /// 是否启用叠加(1=启用,0=禁用) /// 透明色键值 /// 设置成功返回 true,失败返回 false [DllImport(DllName)] public static extern bool PlayM4_SetOverlayMode(int nPort, int bOverlay, uint colorKey); /// /// 获取最后一次错误码 /// 功能:API 调用失败后,获取具体错误原因(对应 PLAYM4_XXX 错误常量) /// /// 播放端口号 /// 错误码(0 表示无错误) [DllImport(DllName)] public static extern uint PlayM4_GetLastError(int nPort); /// /// 设置视频解码模式 /// 功能:切换硬解码/软解码模式(补充:用于硬件加速优化) /// /// 播放端口号 /// 解码模式(0=软解码,1=硬解码,具体值参考官方文档) /// 设置成功返回 true,失败返回 false [DllImport(DllName)] public static extern bool PlayM4_SetDecVideoMode(int nPort, int nMode); /// /// 获取源缓冲区剩余空间 /// 功能:查询端口流缓冲区的剩余可用空间(字节) /// /// 播放端口号 /// 剩余空间大小(字节) [DllImport(DllName)] public static extern uint PlayM4_GetSourceBufferRemain(int nPort); /// /// 重置源缓冲区 /// 功能:清空端口流缓冲区中的未解码数据 /// /// 播放端口号 /// 重置成功返回 true,失败返回 false [DllImport(DllName)] public static extern bool PlayM4_ResetSourceBuffer(int nPort); #endregion }