使用微软的VFW
具体步骤如下
1.创建“捕获窗”
在进行视频捕获之前必需要先创建一个“捕获窗”,并以它为基础进行所有的捕获及设置操作。“捕获窗”用AVICap窗口类的“CapCreateCaptureWindow”函数来创建,其窗口风格一般为WS_CHILD和WS_VISIBLE。
捕获窗类似于标准控件(如按钮、列表框等),并具有下列功能:
●将视频流和音频流捕获到一个AVI文件中;
●动态地同视频和音频输入器件连接或断开;
●以Overlay或Preview模式对输入的视频流进行实时显示;
●在捕获时,可指定所用的文件名并能将捕获文件的内容拷贝到另一个文件;
●设置捕获速率;
●显示控制视频源、视频格式、视频压缩的对话框;
●创建、保存或载入调色板;
●将图像和相关的调色板拷贝到剪贴板;
●将捕获的单帧图像保存为DIB格式的文件。
2.关联捕获窗和驱动程序
单独定义的一个捕获窗是不能工作的,它必需与一个设备相关联,这样才能取得视频信号。用函数CapDriverConnect可使一个捕获窗与一个设备驱动程序相关联。
3.设置视频设备的属性
通过设置TcaptureParms结构变量的各个成员变量,可以控制设备的采样频率、中断采样按键、状态行为等等。设置好TCaptureParms结构变量后,可以用函数CapCaptureSetSetup使设置生效。之后还可以用CapPreviewScale、CapPreviewRate来设置预览的比例与速度,也可以直接使用设备的默认值。
4.打开预览
利用函数CapOverlay选择是否采用叠加模式预览,这样占用系统资源小,并且视频显示速度快。然后用CapPreview启动预览功能,这时就可以在屏幕上看到来自摄像机的图像了。
通过以上4步就可以建立一个基本的视频捕获程序。但如果想自已处理从设备捕获到的视频数据,则要使用捕获窗回调函数来处理,比如一帧一帧地获得视频数据或以流的方式获得视频数据等等。
实例编程
下面以一个一帧一帧地从视频设备上捕获视频数据的Delphi程序为例,来说明每个函数的作用以及开发过程。
该程序的功能是可以在屏幕上显视捕获到的视频,并可以获得每一帧的图像数据。
新建一个工程,并将AVICAP32.PAS包含到USES中。
在Form1上放置一个TPanel控件,设Name为“gCapVideoArea”,该控件用于显示视频。再放置两个TButton控件,一个Name为“Openvideo”,另一个Name为“Closevideo”。
定义全局变量:
var
//定义捕获窗句柄
ghCapWnd: THandle;
//可以得到视频数据指针的结构变量,用于回调函数中
VideoStr: LPVIDEOHDR;
//用于设置设备属性的结构变量
CapParms: TCaptureParms;
在Name为“Openvideo”的TButton 的Click事件中写入以下代码:
procedure TForm1.OpenvideoClick(Sender: TObject);
begin
//使用Tpanel控件来创建捕获窗口
ghCapWnd := CapCreateCaptureWindow
( PChar(‘KruwoSoft'), //捕获窗口的名字
WS_CHILD or WS_VISIBLE,//窗口样式
0, //X坐标
0, //Y坐标
gCapVideoArea.Width, //窗口宽
gCapVideoArea.Height, //窗口高
gCapVideoArea.Handle, //窗口句柄
0); //一般为0
{为了能够捕获视频帧,要启动一个捕获帧回调函数VideoStreamCallBack。捕获一个视频流或当前设备状态时分别使用以下函数:
//捕获一个视频流
CapSetCallbackOnVideoStream;
//得到一个设备错误
CapSetCallbackOnError;
//得到一个设备状态
CapSetCallbackOnStatus
}
//定义一个帧捕获回调函数
CapSetCallbackOnFrame (ghCapWnd,LongInt(@VideoStreamCallBack));
//将一个捕获窗口与一个设备驱程相关联,第二个参数是个序号,当系统中装有多个显视驱动程序时,其值分别依次为0到总个数
CapDriverConnect(ghCapWnd, 0);
//设置设备属性的结构变量
CapParms.dwRequestMicroSecPerFrame:=40000;
CapParms.fLimitEnabled := FALSE;
CapParms.fCaptureAudio := FALSE; // NO Audio
CapParms.fMCIControl := FALSE;
CapParms.fYield := TRUE;
CapParms.vKeyAbort := VK_ESCAPE;
CapParms.fAbortLeftMouse := FALSE;
CapParms.fAbortRightMouse := FALSE;
//使设置生效
CapCaptureSetSetup(ghCapWnd,LongInt(@CapParms),sizeof(TCAPTUREPARMS));
//设置预览时的比例
CapPreviewScale(ghCapWnd, 1);
//设置预览时的帧频率
CapPreviewRate(ghCapWnd,66);
//如果要捕获视频流,则要使用函数指定不生成文件。否则将会自动生成AVI文件
CapCaptureSequenceNoFile(ghCapWnd);
//指定是否使用叠加模式,使用为1,否则为0
CapOverlay(ghCapWnd, 1);
//打开预览
CapPreview(ghCapWnd, 1);
end;
在Name为“Closevideo”的TButton 的Click事件中写入以下代码:
procedure TForm1.ClosevideoClick(Sender: TObject);
begin
//停止捕获
capCaptureAbort(ghCapWnd);
//将捕获窗同驱动器断开
capDriverDisconnect(ghCapWnd);
end;
定义捕获帧回调函数:
function FrameCallBack(hWnd:HWND; lpVHdr:LongInt) :LongInt; stdcall;
var
DataPoint:^byte;
DibLen,RectWidth,RectHeight:integer;
begin
//转换从回调函数中得到的指针
VideoStr:=LPVIDEOHDR(lpVHdr);
//得到返回的数据大小
DibLen:=VideoStr^.dwBufferLength;
GetMem(DataPoint,64000);
//将帧数据COPY到一个内存中,注意DATAPOINT要先分配空间
CopyMemory(DataPoint,VideoStr^.lpData,Diblen);
//一些其他处理
……
end;
灵活地使用AVICap窗口类的回调函数可以满足各种不同的需求,但要注意从视频卡中捕获的视频数据的格式和图像的长宽要参考视频卡的参数。而且有些视频卡通过设置可支持多种的格式和图像长宽,所以在还原图像时要注意参考所用的视频卡的参数。
--------------------------------------------------------------------------------
视频采集,存成avi
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls;
type
TForm1 = class(TForm)
Panel1: TPanel;
OpenVideo: TButton;
CloseVideo: TButton;
GrabFrame: TButton;
SaveBMP: TButton;
StartAVI: TButton;
StopAVI: TButton;
SaveDialog1: TSaveDialog;
procedure FormCreate(Sender: TObject);
procedure OpenVideoClick(Sender: TObject);
procedure CloseVideoClick(Sender: TObject);
procedure GrabFrameClick(Sender: TObject);
procedure SaveBMPClick(Sender: TObject);
procedure StartAVIClick(Sender: TObject);
procedure StopAVIClick(Sender: TObject);
private
{ Private declarations }
hWndC : THandle;
CapturingAVI : bool;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
const WM_CAP_START = WM_USER;
const WM_CAP_STOP = WM_CAP_START + 68;
const WM_CAP_DRIVER_CONNECT = WM_CAP_START + 10;
const WM_CAP_DRIVER_DISCONNECT = WM_CAP_START + 11;
const WM_CAP_SAVEDIB = WM_CAP_START + 25;
const WM_CAP_GRAB_FRAME = WM_CAP_START + 60;
const WM_CAP_SEQUENCE = WM_CAP_START + 62;
const WM_CAP_FILE_SET_CAPTURE_FILEA = WM_CAP_START + 20;
function capCreateCaptureWindowA(lpszWindowName : PCHAR;
dwStyle : longint;
x : integer;
y : integer;
nWidth : integer;
nHeight : integer;
ParentWin : HWND;
nId : integer): HWND;
STDCALL EXTERNAL 'AVICAP32.DLL';
procedure TForm1.FormCreate(Sender: TObject);
begin
CapturingAVI := false;
hWndC := 0;
SaveDialog1.Options :=
[ofHideReadOnly, ofNoChangeDir, ofPathMustExist]
end;
procedure TForm1.OpenVideoClick(Sender: TObject);
begin
hWndC := capCreateCaptureWindowA('My Own Capture Window',
WS_CHILD or WS_VISIBLE ,
Panel1.Left,
Panel1.Top,
Panel1.Width,
Panel1.Height,
Form1.Handle,
0);
if hWndC <> 0 then
SendMessage(hWndC, WM_CAP_DRIVER_CONNECT, 0, 0);
end;
procedure TForm1.CloseVideoClick(Sender: TObject);
begin
if hWndC <> 0 then begin
SendMessage(hWndC, WM_CAP_DRIVER_DISCONNECT, 0, 0);
hWndC := 0;
end;
end;
procedure TForm1.GrabFrameClick(Sender: TObject);
begin
if hWndC <> 0 then
SendMessage(hWndC, WM_CAP_GRAB_FRAME, 0, 0);
end;
procedure TForm1.SaveBMPClick(Sender: TObject);
begin
if hWndC <> 0 then begin
SaveDialog1.DefaultExt := 'bmp';
SaveDialog1.Filter := 'Bitmap files (*.bmp)|*.bmp';
if SaveDialog1.Execute then
SendMessage(hWndC,
WM_CAP_SAVEDIB,
0,
longint(pchar(SaveDialog1.FileName)));
end;
end;
procedure TForm1.StartAVIClick(Sender: TObject);
begin
if hWndC <> 0 then begin
SaveDialog1.DefaultExt := 'avi';
SaveDialog1.Filter := 'AVI files (*.avi)|*.avi';
if SaveDialog1.Execute then begin
CapturingAVI := true;
SendMessage(hWndC,
WM_CAP_FILE_SET_CAPTURE_FILEA,
0,
Longint(pchar(SaveDialog1.FileName)));
SendMessage(hWndC, WM_CAP_SEQUENCE, 0, 0);
end;
end;
end;
procedure TForm1.StopAVIClick(Sender: TObject);
begin
if hWndC <> 0 then begin
SendMessage(hWndC, WM_CAP_STOP, 0, 0);
CapturingAVI := false;
end;
end;
end.