代碼說明:
1.從StartCap和StopCap的按鈕事件可以看得出主要實現寫文件頭和文件尾的功能,注意 _write函數。
2.而上一章我們講到了回調函數StreamDirectReadCallback,主要是將數據寫到內存中,從代碼能看出回調中是邊寫內存 邊寫文件的代碼,而且輸出就是.264文件。由於回調從啟動開始(允許被客戶端訪問),就一直不停的在調用這個回調,根據斷點調試可以看得 出當frameType == PktSysHeader時表示的就是文件頭,並且只執行一次,這樣在點擊StartCap按鈕時就直接將這個保存的文件頭的數據寫入文 件了,用UE打開.264的文件可以發現前幾個字符總是以4HKH開頭的文件。
3.注意gFileHandle是一個文件指針數組,文件被打開後回調 中就一直往這個文件指針寫數據!!
C#:
//用於存放頭文件
byte[] FileHeader;
//文件頭長度
int FileHeaderLen;
//是否開始捕獲文件 0 未啟用 1 啟用
volatile int CaptureState;
/// <summary>
/// 開始錄像
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnStart_Click(object sender, EventArgs e)
{
//寫入頭文件
using (FileStream fs = new FileStream("C:\\hik.264", FileMode.Create))
{
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(FileHeader);
bw.Flush();
bw.Close();
}
CaptureState = 1;
}
uint endCode = 0x00000002;
/// <summary>
/// 停止錄像
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnStop_Click(object sender, EventArgs e)
{
CaptureState = 0;
using (FileStream fs = new FileStream("C:\\hik.264", FileMode.Append))
{
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(endCode);
bw.Close();
}
}
public int STREAM_DIRECT_READ_CALLBACK1(int channelNum, IntPtr DataBuf, int Length, FrameType_t frameType, IntPtr context)
{
//int status = 0;
//HikServer.MP4_ServerWriteDataEx(channelNum, DataBuf, Length, (int)frameType, status, 0);
//return 0;
int status = 0;
if (frameType > 0)
{
if (frameType == FrameType_t.PktSysHeader)
{
FileHeader = new byte[Length];
Marshal.Copy(DataBuf, FileHeader, 0, Length);
FileHeaderLen = Length;
}
if (frameType == FrameType_t.PktIFrames || frameType == FrameType_t.PktSubIFrames)
status = 1;
else
status = 0;
if (frameType == FrameType_t.PktMotionDetection || frameType == FrameType_t.PktOrigImage)
return 0;
}
if (Length == 0)
{
//TRACE("no data ?\n");
return 0;
}
if (frameType == FrameType_t.PktAudioFrames)
{
WriterVideoCapture(Length, DataBuf);
//寫文件
// _write(gFileHandleQcif[channelNum],DataBuf,Length);
//HikServer.MP4_ServerWriteDataEx(channelNum, DataBuf, Length, (int)frameType, status, 1);
// _write(gFileHandle[channelNum], DataBuf, Length);
HikServer.MP4_ServerWriteDataEx(channelNum, DataBuf, Length, (int)frameType, status, 0);
}
else if (frameType == FrameType_t.PktSubIFrames || frameType == FrameType_t.PktSubPFrames || frameType == FrameType_t.PktSubBBPFrames || frameType == FrameType_t.PktSubSysHeader)
{
// _write(gFileHandleQcif[channelNum],DataBuf,Length);
HikServer.MP4_ServerWriteDataEx(channelNum, DataBuf, Length, (int)frameType, status, 1);
}
else
{
WriterVideoCapture(Length, DataBuf);
HikServer.MP4_ServerWriteDataEx(channelNum, DataBuf, Length, (int)frameType, status, 0);
}
return 0;
}
/// <summary>
/// 將數據流寫入視頻文件
/// </summary>
/// <param name="length"></param>
/// <param name="dataBuf"></param>
private void WriterVideoCapture(int length, IntPtr dataBuf)
{
if (CaptureState == 1)
{
using (FileStream fs = new FileStream("C:\\hik.264", FileMode.Append))
{
BinaryWriter bw = new BinaryWriter(fs);
byte[] byteBuf = new byte[length];
Marshal.Copy(dataBuf, byteBuf, 0, length);
bw.Write(byteBuf);
bw.Flush();
bw.Close();
}
}
}