在网络上进行摄像头视频通讯

2008-04-10 02:56:48来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折


文章分类:网络、视频,聊天
文章作者:廖长科
(转贴请注明原创作者)

笔者序:也许在写这编文章时,有很多朋友正被老板要求做类似QQ一样的视频聊天软件,在这里,我把自己的一些经验和代码写出来与大家一起分享,高手不要笑我哈!看了这编文章后,你也可以自己做一个简单的网络视频通讯软件,如果自己家里上了网,就可以在公司和家人进行可视通讯了,多爽,不用给电话费了。

本例子使用的是简的老技术(VFW),开发起来相对简单,以下是Delphi代码,你需要先加入VFW.PAS文件,没有这个文件你可以在网上找一下。作者从Delphi4就开始编程,其实Delphi可以做很多事情,只是太多Delphi程序员没有深专技术和思想,没有超越自己,Delphi只是一个开发工具,代码思想是的设计的精髓。
下面让我们一起来讲解一下:

在程序的开始,你需要用capCreateCaptureWindow来创建一个摄像头句柄,
CapWnd := capCreateCaptureWindow(''''预览窗口'''',WS_VISIBLE or WS_CHILD,0,0,320,240,PrevWnd,1);
在后面的参数:PrevWnd代表预览窗口的句柄,你可以指定一个Panel的句柄;320和240代表了窗口的长宽。

if CapWnd = 0 then exit;
capDriverConnect(CapWnd,0); //连接摄像头设备

capDlgVideoFormat(CapWnd); //显示视频设置对话框,进行配置视频的大小、颜色位数等。
capGetVideoFormat(CapWnd,@BmpInInfo,sizeof(BITMAPINFO)); //取得视频图像数据头,后面压缩时需要用到

capPreviewRate(CapWnd, 33); //设置预览视频的频率,33代表第秒30帧。
capPreview(CapWnd, TRUE);

capSetCallbackOnFrame(CapWnd,FrameCallBack);

InitCaptureParams;

最后一句是设置视频压缩参数, 后面会进行说明。其中的capSetCallbackOnFrame(CapWnd,FrameCallBack)是设置每帧视频数据的回调函数,我们就可以将回调时的视频数据通过网络进行传输,这样的就实现了视频聊天的核心了。

回调函数如下的格式:

function FrameCallBack(hWnd: HWND; lpVHdr: PVIDEOHDR): DWORD; stdcall;
var
bKeyFrame : BOOL ;
Buf : PBYTE;
VideoData : TVIDEO_DATA;
OutActSize : dword;
i : integer;
begin
OutActSize := BmpInInfo.bmiHeader.biSizeImage;
Buf := ICSeqCompressFrame(@CapVar,0,lpVHdr.lpData,@bKeyFrame,@OutActSize);

//在这里, OutActSize代表压缩后的视频数据大小
// form1.Label3.Caption := ''''Compressed size:'''' inttostr(OutActSize);


//我用的是UDP方式, 因为UDP数据包大小限制, 所以我控制了数据大小, 超出的数据会发生丢帧
if (OutActSize <= sizeof(videodata.Buf) ) then
begin
zeromemory(@VideoData ,sizeof(TVIDEO_DATA));

//记录是否为关键帧
VideoData.bKeyFrame:=bKeyFrame;


copymemory(@VideoData.Buf, Buf, OutActSize);

VideoData.SampleNum:=SampleNum; //我们可以记录下帧数, 可以做扩展用
VideoData.BufSize:=OutActSize; //记录数据大小, 传输时用

//在这里, 你可以用你喜欢的网络方式传输视频数据,

//cc1.SendBuffer(VideoData,sizeof(TVIDEO_DATA)-SendBufferSize Outactsize);

inc(SampleNum);
end;
result := 0;
end;

其中,PVIDEOHDR类型可以从VFW中看到其定义:
TVIDEOHDR = record
lpData : PBYTE; // 视频数据buffer
dwBufferLength : DWORD; // 数据buffer长度
dwBytesUsed : DWORD;
dwTimeCaptured : DWORD; // 时间长度(毫秒)
dwUser : DWORD;
dwFlags : DWORD;
dwReserved : array[0..3] of DWORD;
end;

在回调函数中, 只用到了视频函数: ICSeqCompressFrame,可以看到此函数传入了CapVar参数,这个参数是由我们先前看到的InitCaptureParams函数产生,下面代码来实现:
function InitCaptureParams : boolean;
begin
result := False;

//初始化CapVar
zeromemory(@CapVar,sizeof(TCOMPVARS));

CapVar.cbSize:=sizeof(CapVar); //必须指定cbSize为TCOMPVARS结构大小
CapVar.dwFlags:=ICMF_COMPVARS_VALID;

CapVar.cbState:=0;

//fccHandler代表压缩编码类型,我们使用的是DIVX的编码器
CapVar.fccHandler:=mmioFOURCC(''''d'''',''''i'''',''''v'''',''''x'''');
CapVar.fccType:=ICTYPE_VIDEO;


//正式连接编码器
CapVar.hic:=ICOpen(ICTYPE_VIDEO, CapVar.fccHandler, ICMODE_COMPRESS);

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:如何在delphi 中画带箭头的直线(改自网上一位论坛版主的vb代码

下一篇:delphi 缓冲画图(内存画图)解决画图闪烁问题