做过海康视频卡的朋友请进!关于视频录像的问题?

龙宜坡 2008-10-22 08:44:29
DS40xxSDK.dll中存在以下连个方法
DLLEXPORT_API int __stdcall StartVideoCapture(HANDLE hChannelHandle);
DLLEXPORT_API int __stdcall StopVideoCapture(HANDLE hChannelHandle);

我在C#中定义了以下方法
/// <summary>
/// 启动主通道编码数据流捕获
/// 说 明: 启动主通道编码数据流捕获。用户程序可以使用直接读取方式,使用
/// StreamDirectReadCallback回调函数直接对数据流进行处理;也可以与H卡一样,通过消息读取方式,等SDK向用户程序发送在 RegisterMessageNotifyHandle中注册的消息,用户程序使用ReadStreamData来读取数据流。
/// </summary>
/// <param name="hChannelHandle">通道句柄</param>
/// <returns>成功返回0;失败返回错误号</returns>
[DllImport("DS40xxSDK.dll")]
public static extern int StartVideoCapture(IntPtr hChannelHandle);

/// <summary>
/// 停止主通道编码数据流捕获
/// </summary>
/// <param name="hChannelHandle">通道句柄</param>
/// <returns>成功返回0;失败返回错误号</returns>
[DllImport("DS40xxSDK.dll")]
public static extern int StopVideoCapture(IntPtr hChannelHandle);

/// <summary>
/// 编码数据流直接读取回调函数委托
/// </summary>
/// <param name="channelNumber">通道号</param>
/// <param name="DataBuf">缓冲区地址</param>
/// <param name="Length">缓冲区长度</param>
/// <param name="FrameType">缓冲区数据帧类型</param>
/// <param name="context">设备上下文</param>
/// <returns></returns>
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int STREAM_DIRECT_READ_CALLBACK(uint channelNumber, IntPtr DataBuf, uint Length, int FrameType, IntPtr context);

/// <summary>
/// 编码数据流直接读取回调函数
/// </summary>
/// <param name="channelNumber">通道号</param>
/// <param name="DataBuf">缓冲区地址</param>
/// <param name="Length">缓冲区长度</param>
/// <param name="FrameType">缓冲区数据帧类型</param>
/// <param name="context">设备上下文</param>
/// <returns></returns>
public static int _StreamDirectReadCallBack(uint channelNumber, IntPtr DataBuf, uint Length, int FrameType, IntPtr context)
{

}
在这个回调函数中,我怎么才能把视频数据保存到文件?谢谢
解决问题,全分奉上!
...全文
704 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
guoln1010 2011-06-14
  • 打赏
  • 举报
回复
[Quote=引用楼主 goga21cn 的回复:]
DS40xxSDK.dll中存在以下连个方法
DLLEXPORT_API int __stdcall StartVideoCapture(HANDLE hChannelHandle);
DLLEXPORT_API int __stdcall StopVideoCapture(HANDLE hChannelHandle);

我在C#中定义了以下方法
/// <summary>
/// ……
[/Quote]
typedef int (__stdcall *TwVideoStreamCallback)(int nChannel, VOID *DataBuf, int width, int height, BOOL bField2, void *Context, __int64 pts)
功能:提供视频原始数据流给用户
参数:[in]nChannel,通道索引号
[in]DataBuf,数据缓存的指针
[in]width,视频宽度
[in]height,视频高度
[in]bField2,是否是偶场数据
[in]Context,上下文指针
[in]pts,帧时间戳
返回:成功返回TRUE,否则返回FALSE
怎么来写程序,我买的板卡没有实例,不知道怎么开发?
guoln1010 2011-06-14
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 greystar 的回复:]
从而获取某个地址的数据.databuffers这是一个byte[],你可自己开辟.Length这个可用.

我没搞过视频卡.不过理论上我觉得应该是我上面这样.


private void vc_VideoCaptured(object sender, VIDEOHDR hdr)
{
if (this.chanel == null || !this.chanel.Conn……
[/Quote]
这位仁兄,能帮我看看我说我这个视频采集卡的回调函数吗?我不太明白怎么将视频显示在界面窗口上?
BOOL TwRegisterVideoStreamCallback(TwVideoStreamCallback VideoStreamCallback, void *Context)
功能:注册视频数据流回调函数
参数:[in]VideoStreamReadCallback,指定的回调函数指针
[in]Context,指定的回调函数上下文指针
返回:成功返回TRUE,否则返回FALSE,调用TwGetLastError获取错误码
fusongbai 2009-02-03
  • 打赏
  • 举报
回复
你们都是高手啊!学习学习
龙宜坡 2008-10-23
  • 打赏
  • 举报
回复
解决了!!!结贴
龙宜坡 2008-10-22
  • 打赏
  • 举报
回复
写入是没有问题,不过,这是个回调函数,在启动录像后,将不停的向某个文件中写入数据,我每次录像的
文件只有6KB,代码如下,
public static int _StreamDirectReadCallBack(uint channelNumber, IntPtr DataBuf, uint Length, FrameType_t FrameType, IntPtr context)
{
byte[][] FileHeader = new byte[64][];
FileHeader[channelNumber] = new byte[Length];
if (FrameType > 0)
{
if (FrameType == FrameType_t.PktSysHeader)
{

Marshal.Copy(DataBuf, FileHeader[channelNumber], 0, (int)Length);
}
}

string fileName = "D:\\" + DateTime.Now.ToString("yyyyMMdd") + ".264";

FileStream fileStream;

if (!System.IO.File.Exists(fileName))
{
System.IO.File.Create(fileName);
}

fileStream = System.IO.File.OpenWrite(fileName);

fileStream.Write(FileHeader[channelNumber], 0, (int)Length);
fileStream.Close();
return 0;
}

怎么可以在上次文件里继续写入数据?
龙宜坡 2008-10-22
  • 打赏
  • 举报
回复
public static int _StreamDirectReadCallBack(uint channelNumber, IntPtr DataBuf, uint Length, int FrameType, IntPtr context)
{

}

这个函数参数中context在C++中的定义是void *context,标注为"设备上下文",我在C#定义为IntPtr没问题吧?
另外,请教"设备上下文"是什么意思?在C#中应做何理解?

谢谢!
龙宜坡 2008-10-22
  • 打赏
  • 举报
回复
@greystar
感谢!
龙宜坡 2008-10-22
  • 打赏
  • 举报
回复
视频和音频一起写入?我试下!
greystar 2008-10-22
  • 打赏
  • 举报
回复
从而获取某个地址的数据.databuffers这是一个byte[],你可自己开辟.Length这个可用.

我没搞过视频卡.不过理论上我觉得应该是我上面这样.


private void vc_VideoCaptured(object sender, VIDEOHDR hdr)
{
if (this.chanel == null || !this.chanel.Connected) return;
try
{
byte[] data = new byte[hdr.dwBytesUsed];
Marshal.Copy(hdr.lpData, data, 0, hdr.dwBytesUsed);
this.chanel.SendVideo(data);
}
catch (System.Exception ex)
{


}
}
greystar 2008-10-22
  • 打赏
  • 举报
回复
可通过System.Runtime.InteropServices.Marshal.Copy(DataBuf, databuffers, 0, databuffers.Length);
ximi82878 2008-10-22
  • 打赏
  • 举报
回复
好强大,学习,收藏,帮顶
greystar 2008-10-22
  • 打赏
  • 举报
回复
DataBuf这个是数据缓冲区的地址.把这块的数据读出来,写入到你自己的流中去.
龙宜坡 2008-10-22
  • 打赏
  • 举报
回复
这个录像让我郁闷了一天!
谁能给点这个回调函数内数据处理的代码?
我很懒 2008-10-22
  • 打赏
  • 举报
回复
视频采集卡,我也开发过,是天敏的
up
龙宜坡 2008-10-22
  • 打赏
  • 举报
回复


//typedef int (*STREAM_DIRECT_READ_CALLBACK)(ULONG channelNumber,void *DataBuf,DWORD Length,int FrameType,void *context);
int __cdecl StreamDirectReadCallback(ULONG channelNum,void *DataBuf,DWORD Length,int frameType,void *context)
{

BOOL breakable;

int nframetype =0;
CHKVisionDlg *hkdlg = (CHKVisionDlg *)context;

if(frameType >0)
{
if (frameType == PktSysHeader)
{
memcpy(FileHeader[channelNum],DataBuf,Length);
FileHeaderLen = Length;
}
else if (frameType == PktSubSysHeader)
{
memcpy(FileHeaderQcif[channelNum],DataBuf,Length);
FileHeaderLen = Length;
}
if (frameType == PktMotionDetection)
{
int result[4];

if(bOverlayMode)
{
hkdlg->m_VideoWin.DrawVectEx(channelNum, (char *)DataBuf);
}
else
{
hkdlg->m_bMoving[channelNum] = TRUE;
memcpy(motionData[channelNum],(char*)DataBuf,Length);
}

MotionAnalyzer(ChannelHandle[channelNum],(char*)DataBuf,15,result);
if((result[0] + result[1] + result[2] + result[3]))
{
if (channelNum ==0)
TRACE("!!!!!!!!!!!!!!!!CH=%d motion detect result is %d %d %d %d\n",channelNum,result[0],\
result[1],result[2],result[3]);
// Trigger函数的作用是把报警前的数据按setup里面的设置,把相应的警前帧写入文件
if(!hkdlg->baftermotion[channelNum])
alarmFile[channelNum].Trigger(gFileHandle[channelNum]);
//每次有移动侦测帧上来,自动把ualreadywriteframes[channelNum]清为0 ,为写入警后帧作准备
hkdlg->ualreadywriteframes[channelNum]=0;
hkdlg->baftermotion[channelNum]=TRUE;
}
return 0;
}
if (frameType == PktIFrames || frameType ==PktSubIFrames)
breakable = TRUE;
else
breakable = FALSE;

}
gChannelTotalLength[channelNum].QuadPart +=Length;
gCurrentFileLen[channelNum] +=Length;
if ((gCurrentFileLen[channelNum] > gFileSize*1000*1000) && (breakable) )
{
char fileName[256];
CTime m_StartTime1=CTime::GetCurrentTime();
CString csStartTime=m_StartTime1.Format("%Y%m%d%H%M%S");


if (gFileHandle[channelNum])
{
_close(gFileHandle[channelNum]);
sprintf(fileName, "ch%02d_%s.264", channelNum,csStartTime);
gFileHandle[channelNum] = _open(fileName,_O_CREAT|_O_BINARY|_O_WRONLY|_O_TRUNC,_S_IREAD|_S_IWRITE);
_write(gFileHandle[channelNum],FileHeader[channelNum],FileHeaderLen);
}
if (gFileHandleQcif[channelNum])
{
_close(gFileHandleQcif[channelNum]);
sprintf(fileName, "ch%02d_%s_sub.264", channelNum,csStartTime);
gFileHandleQcif[channelNum] = _open(fileName,_O_CREAT|_O_BINARY|_O_WRONLY|_O_TRUNC,_S_IREAD|_S_IWRITE);
_write(gFileHandleQcif[channelNum],FileHeaderQcif[channelNum],FileHeaderLen);
}
gCurrentFileLen[channelNum] -=gFileSize*1000*1000;
}
if(bAlarmFileSave)
{
if(frameType == PktSysHeader)
_write(gFileHandle[channelNum],DataBuf,Length);
else
{
//统计移动侦测帧上来之后的音视频数据,统计它们 ,并把它们写入文件,每一次有 新的移动侦测数据上来,
//ualreadywriteframes都会先清0,然后统计写入文件的音视频数据
hkdlg->ualreadywriteframes[channelNum] += hkdlg->TypeToFrames((FrameType_t)frameType);
if (hkdlg->ualreadywriteframes[channelNum] <6*(25+25)) //录制移动侦测帧上来之后 6秒钟的音视频数据,也就是警后数据
_write(gFileHandle[channelNum],DataBuf,Length);
else
{
// 如果移动侦测上来之后,写入文件的音视频数据已经足够,那么把接下来上来的音视频数据压缓冲,
// 压入缓冲的数据有两种处理方式:1 如果缓冲满了,自动被删除;2 作为下次报警上来的警前帧写入文件; 
alarmFile[channelNum].FramePush(gFileHandle[channelNum],(unsigned char *)DataBuf,Length,(FrameType_t)frameType,breakable);
hkdlg->baftermotion[channelNum] = FALSE;
}
}
}
else
{
if(frameType ==PktAudioFrames)
{
_write(gFileHandle[channelNum],DataBuf,Length);
_write(gFileHandleQcif[channelNum],DataBuf,Length);

}else if (frameType ==PktSubIFrames || frameType ==PktSubPFrames || frameType == PktSubBBPFrames || frameType == PktSubSysHeader)
{

_write(gFileHandleQcif[channelNum],DataBuf,Length);

}else
{
_write(gFileHandle[channelNum],DataBuf,Length);

}
}
return 0;
}




以上这段代码
龙宜坡 2008-10-22
  • 打赏
  • 举报
回复
fileStream = System.IO.File.Open(fileName,FileMode.Append);


很是感谢!

我再仔细看看他们给的C++示例!
greystar 2008-10-22
  • 打赏
  • 举报
回复
filemode.Append
greystar 2008-10-22
  • 打赏
  • 举报
回复
你写文件时要使用追加的方式,
public FileStream (
string path,
FileMode mode,
FileAccess access,
FileShare share
)

110,539

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧