首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 視訊監控系列(9):服務端資料擷取——即時抓圖與錄像存檔完整實作

     編輯:關於C#

本文實作服務端兩大核心儲存功能:JPEG 抓圖與 H.264 碼流錄像。重點解析回調中取得檔案頭、資料幀、檔案尾的完整流程,並給出可直接使用的 C# 程式碼。

一、即時抓圖


byte[] imageBuf = new byte[704 * 576 * 2];
int size = imageBuf.Length;

int ret = HikVisionSDK.GetJpegImage(channelHandle, imageBuf, out size, 100);
if (ret == 0)
{
    using (MemoryStream ms = new MemoryStream(imageBuf, 0, size))
    {
        Image img = Image.FromStream(ms);
        img.Save(@"C:\snapshot.jpg", ImageFormat.Jpeg);
    }
}

API 修正:GetJpegImage 簽名為 (IntPtr hChannel, byte[] buf, out int size, uint quality),GetOriginalImage 同理但無 quality 參數。

二、錄像存檔核心邏輯

錄像檔結構:檔案頭 + 多個資料幀 + 檔案尾 (0x00000002)。

關鍵變數


byte[] fileHeader;      // 暫存檔案頭
int fileHeaderLen;
volatile int captureState; // 0=停止, 1=錄製中

開始/停止錄像


private void btnStart_Click(object sender, EventArgs e)
{
    using (var fs = new FileStream(@"C:\hik.264", FileMode.Create))
    using (var bw = new BinaryWriter(fs))
    {
        bw.Write(fileHeader);
    }
    captureState = 1;
}

private void btnStop_Click(object sender, EventArgs e)
{
    captureState = 0;
    uint endCode = 0x00000002;
    using (var fs = new FileStream(@"C:\hik.264", FileMode.Append))
    using (var bw = new BinaryWriter(fs))
    {
        bw.Write(endCode);
    }
}

串流直接讀取回調(核心)


public int STREAM_DIRECT_READ_CALLBACK1(int channelNum, IntPtr dataBuf, int length, FrameType frameType, IntPtr context)
{
    int status = 0;

    if (frameType > 0)
    {
        if (frameType == FrameType.PktSysHeader) // 檔案頭
        {
            fileHeader = new byte[length];
            Marshal.Copy(dataBuf, fileHeader, 0, length);
            fileHeaderLen = length;
        }

        if (frameType == FrameType.PktIFrames || frameType == FrameType.PktSubIFrames)
            status = 1; // 關鍵幀標記
        else
            status = 0;

        if (frameType == FrameType.PktMotionDetection || frameType == FrameType.PktOrigImage)
            return 0;
    }

    if (length == 0) return 0;

    // 寫入伺服器發送緩衝(供客戶端預覽)
    if (frameType == FrameType.PktAudioFrames)
    {
        WriteVideoCapture(length, dataBuf);
        HikServer.MP4_ServerWriteDataEx(channelNum, dataBuf, length, (int)frameType, status, 0);
    }
    else if (frameType == FrameType.PktSubIFrames || frameType == FrameType.PktSubPFrames || frameType == FrameType.PktSubBBPFrames || frameType == FrameType.PktSubSysHeader)
    {
        HikServer.MP4_ServerWriteDataEx(channelNum, dataBuf, length, (int)frameType, status, 1); // 子碼流
    }
    else
    {
        WriteVideoCapture(length, dataBuf); // 主碼流寫檔
        HikServer.MP4_ServerWriteDataEx(channelNum, dataBuf, length, (int)frameType, status, 0);
    }
    return 0;
}

private void WriteVideoCapture(int length, IntPtr dataBuf)
{
    if (captureState == 1)
    {
        using (var fs = new FileStream(@"C:\hik.264", FileMode.Append))
        using (var bw = new BinaryWriter(fs))
        {
            byte[] buf = new byte[length];
            Marshal.Copy(dataBuf, buf, 0, length);
            bw.Write(buf);
        }
    }
}

關鍵點總結

  1. 檔案頭只出現一次:回調中 PktSysHeader 僅第一次觸發,必須暫存供開始錄像時寫入。
  2. 檔案模式:開始用 FileMode.Create,過程用 FileMode.Append,結尾寫入 0x00000002。
  3. 同步寫入發送緩衝:呼叫 MP4_ServerWriteDataEx 才能讓客戶端看到畫面;nImgFormat=0 主碼流、1 子碼流。
  4. 單檔案大小限制:實際部署需加入分割邏輯(依大小/時間)、磁碟空間監控、分時段錄製策略。

驗證方法

用海康官方播放器拖曳產生的 .264 檔,能正常播放即表示錄製無誤。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved