本文示範如何在服務端實現本地視訊預覽,並配置 SDK 使客戶端能成功連線預覽。重點解析初始化順序、視窗移動重繪、關鍵回調註冊與啟動參數設定,附完整 C# 程式碼。
IntPtr channelHandle;
private void Form2_Load(object sender, EventArgs e)
{
// 設定預設制式
HikVisionSDK.SetDefaultVideoStandard(VideoStandard.StandardNTSC);
// 初始化 DSP
if (HikVisionSDK.InitDSPs() < 0)
{
MessageBox.Show("DSP 初始化失敗!");
return;
}
if (HikVisionSDK.GetTotalDSPs() == 0)
{
MessageBox.Show("無可用通道,請確認服務端已啟動。");
return;
}
// 開啟通道 0
channelHandle = HikVisionSDK.ChannelOpen(0);
HikVisionSDK.SetIBPMode(channelHandle, 100, 2, 1, 25); // IBP 間隔、幀率
HikVisionSDK.SetDefaultQuant(channelHandle, 15, 15, 20); // 量化參數
StartVideoPreview();
}
private void StartVideoPreview()
{
Rectangle rect = panel1.ClientRectangle;
HikVisionSDK.StartVideoPreview(channelHandle, panel1.Handle, ref rect, false, (int)VideoFormat.vdfRGB16, 25);
}
// 視窗移動時必須重繪
private void Form2_Move(object sender, EventArgs e)
{
HikVisionSDK.StopVideoPreview(channelHandle);
StartVideoPreview();
}
關鍵點:StartVideoPreview 的 rect 參數直接用 Rectangle 結構;視窗移動需先 StopVideoPreview 再重新啟動,否則畫面會殘留。
// 回調委派必須為成員變數
private STREAM_DIRECT_READ_CALLBACK sdrc;
private void PreviewAndClientConnect()
{
// 1. 註冊碼流直接讀取回調(必須)
sdrc = new STREAM_DIRECT_READ_CALLBACK(STREAM_DIRECT_READ_CALLBACK1);
HikVisionSDK.RegisterStreamDirectReadCallback(sdrc, this.Handle);
// 2. 設定服務端啟動/停止捕獲回調(必須)
HikServer.MP4_ServerSetStart(new StartCap(StartCapCallback));
HikServer.MP4_ServerSetCapIFrame(new MakeIFrame(MakeIFrameCallback)); // 關鍵:客戶端連線觸發 I 幀
// 3. 設定視訊資訊結構
PSERVER_VIDEOINFO info = new PSERVER_VIDEOINFO();
info.m_datatype = new byte[64];
HikServer.MP4_ServerSetBufNum(0, 90); // 發送緩衝 90*8KB
info.m_datatype[0] = (byte)ChannelDataType.SMALLPIC;
info.m_channum = 1;
info.m_waittime = 5;
// 4. 啟動服務端(必須)
if (HikServer.MP4_ServerStart(ref info) == 0)
{
MessageBox.Show("服務端啟動失敗!");
return;
}
// 5. 開啟本地預覽
StartVideoPreview();
}
// 回調實作
public void StartCapCallback(int port) => HikVisionSDK.StartVideoCapture(channelHandle);
public void MakeIFrameCallback(ulong port) => HikVisionSDK.CaptureIFrame(channelHandle);
public int STREAM_DIRECT_READ_CALLBACK1(int channelNum, IntPtr dataBuf, int length, FrameType frameType, IntPtr context)
{
// 僅寫入發送緩衝,不做本地存檔
int status = (frameType == FrameType.PktIFrames || frameType == FrameType.PktSubIFrames) ? 1 : 0;
HikServer.MP4_ServerWriteDataEx(channelNum, dataBuf, length, (int)frameType, status, 0);
return 0;
}
MP4_ServerStart → StartVideoPreview。Rectangle 代替 RECT 結構體傳遞。GetTotalDSPs() 取得所有通道數,GetDspCount() 僅取啟用數。作者花費一周才攻克「本地有畫面、客戶端連得上但無畫面」的問題,關鍵在於補上 MakeIFrame 回調。建議開發者務必細讀 SDK 文件中「伺服器啟動流程」章節。