六.将四个标准对话框改成函数调用形式 系统提供了四个标准的对话框:AudioFormat, VideoFormat, VideoSource, Video Compression,但有时程序希望通过函数控制它们,而不是使用系统提供的那个单一的对话框,此时就应该使用函数调用的方法:
可以通过使用capSetAudioFormat来实现,此时要使用WAVEFORMATEX结构。 例如:改成PCM格式,立体声,16声道,12.05kHz,则: WAVEFORMATEX audioFormat; // 确定宽度 acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT,&dwSize); dwSize = max (dwSize, capGetAudioFormatSize (m_hwCapCapturing)); // 设置参数 audioFormat.wFormatTag = WAVE_FORMAT_PCM; audioFormat.nChannels = 2; audioFormat.nSamplesPerSec = 120500; audioFormat.wBitsPerSample =16; audioFormat.nBlockAlign = nBitsPerSample * nChannels / 8; audioFormat.nAvgBytesPerSec = audioFormat.nBlockAlign * nSamplesPerSec; // 更新 capSetAudioFormat(ghCapWnd,&audioFormat,dwSize); VideoFormat对话框 可以通过使用capSetVideoFormat来实现,此时要使用BITMAPINFOHEADER结构。 例如:设置图片大小为RGB24位岁,大小为230X160 BITMAPINFOHEADER bi; DWORD dwSize,dw; bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = 320; // 起作用 bi.biHeight = 160; // 起作用 bi.biPlanes = 1; bi.biBitCount = 24; bi.biCompression = BI_RGB; bi.biSizeImage = 0; bi.biXPelsPerMeter = 176; bi.biYPelsPerMeter = 144; bi.biClrUsed = 0; bi.biClrImportant = 0; dwSize = bi.biSize + ((bi.biBitCount > 8 || bi.biClrUsed) ? (bi.biClrUsed * sizeof(PALETTEENTRY)) : (2 ^ bi.biBitCount * sizeof(PALETTEENTRY))); dw = capSetVideoFormat(m_hwCapCapturing, &bi, dwSize); VideoSource对话框 没有找到现成的方法,但视频捕获卡提供的CD里面有一个动态链接库可以实现。 Video Compression对话框 可以通过使用ICOpen,ICInfo等函数联合起来,得到当前系统里面的视频压缩驱动的列表,并可选择其一,MSDN里面有一个程序示范了此用户,程序名叫:ICWalk。 --------------------------------------------------------------------------------
在 许多关于视频的软件(如视频会议、可视电话等)开发中,都应用了视频捕获技术。微软为软件开发人员提供了一个专门用于视频捕获的VFW (Video for Windows) SDK。VFW SDK为在Windows系统中实现视频捕获提供了标准的接口,从而大大降低了程序的开发难度。由于VFW SDK只有VC和VB版,没有Delphi版,因此需要在Delphi中一一声明DLL中的各个函数和变量(可以参考MSDN中的VC的函数声明以及变量 定义)。本文分3部分介绍如何利用VFW在Delphi中开发视频捕获程序。 VFW简介 VFW 是微软公司1992年推出的关于数字视频的一个软件包,它能使应用程序通过数字化设备从传统的模拟视频源得到数字化的视频剪辑。VFW的一个关键思想是播 放时不需要专用硬件,为了解决数字视频数据量大的问题,需要对数据进行压缩。它引进了一种叫AVI的文件标准,该标准未规定如何对视频进行捕获、压缩及播 放,仅规定视频和音频该如何存储在硬盘上,以及在AVI文件中交替存储视频帧和与之相匹配的音频数据。VFW使程序员能通过发送消息或设置属性来捕获、播 放和编辑视频剪辑。在Windows 9x系统中,当用户在安装VFW时,安装程序会自动地安装配置视频所需要的组件,如设备驱动程序、视频压缩程序等。 VFW主要由以下6个模块组成: ●AVICAP.DLL:包含执行视频捕获的函数,它给AVI文件的I/O处理和视频、音频设备驱动程序提供一个高级接口; ●MSVIDEO.DLL:包含一套特殊的DrawDib函数,用来处理屏幕上的视频操作; ●MCIAVI.DRV:包括对VFW的MCI命令解释器的驱动程序; ●AVIFILE.DLL:包含由标准多媒体I/O(mmio)函数提供的更高的命令,用来访问.AVI文件; ●压缩管理器(ICM):用于管理的视频压缩/解压缩的编译码器(Codec); ●音频压缩管理器ACM:提供与ICM相似的服务,适用于波形音频。 开发步骤 AVICap 窗口类支持实时的视频流捕获和单帧捕获,并提供对视频源的控制。虽然MCI也提供数字视频服务(比如它为显示.AVI文件的视频提供了AVI VIDEO命令集),为视频叠加提供了Overlay命令集,但这些命令主要是基于文件的操作,它们不能满足实时地从视频缓存中取数据的要求, 对于使用没有视频叠加能力的捕获卡的PC机来说, 用MCI提供的命令集是无法捕获视频流的。而AVICap窗口类在捕获视频方面具有一定的优势,它能直接访问视频缓冲区,不需要生成中间文件,实时性很 强,效率很高。而且,它还可将数字视频捕获到一个文件中。 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窗口类的回调函数可以满足各种不同的需求,但要注意从视频卡中捕获的视频数据的格式和图像的长宽要参考视频卡的参数。而且有些视频卡通过设置可支持多种的格式和图像长宽,所以在还原图像时要注意参考所用的视频卡的参数。 --------------------------------------------------------------------------------
interface uses type var implementation {$R *.DFM} const WM_CAP_START = WM_USER; function capCreateCaptureWindowA(lpszWindowName : PCHAR; procedure TForm1.FormCreate(Sender: TObject); procedure TForm1.OpenVideoClick(Sender: TObject); procedure TForm1.CloseVideoClick(Sender: TObject); procedure TForm1.GrabFrameClick(Sender: TObject); procedure TForm1.SaveBMPClick(Sender: TObject); procedure TForm1.StartAVIClick(Sender: TObject); procedure TForm1.StopAVIClick(Sender: TObject);
发表评论 -孙 涛-
目 录 Windos下视频捕获简史... 1 WDM和视频捕获... 1 VfWWDM Mapper 2 WDM 视频捕获结构... 2 DirectShow应用程序... 3 DirectShow Filter Graph. 3 WDM数据流... 4 视频捕获 Minidrivers. 4 Pins, Streams, Formats. 4 视频流命名约定... 5 DirectShow 视频捕获的接口和属性... 5 捕获数据流类型... 6 流输出数据格式... 6 结束语
Windos下视频捕获简史 VFW技术同样受到了很多批评,它捕获的数据保存到磁盘上会占用大量磁盘空间,每秒数据量超过20M,同时需要大量的客户端支撑软件,VFW体系架构上的不足在视频会议应用上和PC/TV应用上被暴露无遗,这样就要求一种新的视频捕获技术来弥补这些不足。 VFW的体系结构缺乏为视频会议,电视浏览,视频区域捕获和VBI(Vertical Blanking Interval)数据流提供强而有效的支持。一些视频卡等设备开发商在设计自己的产品时,针对这些缺陷,对VFW进行了功能扩展。由于没有统一的标准,我们的应用程序在使用这些扩充的功能时,就必须要写一些基于特定硬件的代码。这就意味着当要改变捕获驱动程序时,就必须要对显卡的驱动程序进行修改。 WDM和视频捕获 l 可以为设备(如基于USB,IEEE 1394通讯方式的摄像头 )提供32位的驱动程序。 l 允许DirectShow 和 WDM 流协同工作。 l 可以在视频捕获设备和DVD/MPEG设备间,为硬件(如video ports 和 chip sets)共享一个分类的驱动程序结构(Stream.sys)。 l 支持多个数据流。 l 允许电视信号调频和输入选择。 l 支持视频区域捕获,区域显示和VBI。 l 允许使用DirectDraw® VPE (Video Port Extensions)管理视频输入。
在一个单独设备上可能会有多个组件共存的情况,这些组件包括DVD解码器,MPEG解码器,视频解码器,调谐器,音频解码器。WDM数据流就是用于解决这种情况而创建的。它是个统一的驱动模型,可以支持所有的这些设备和去处理它们的资源分配。 WDM数据流为标准数据类型和用户自定义数据类型提供了统一的数据模型,同样,它定义了大部分的标准设备的属性,并且根据需要可以很容易地实现扩充。因为按WDM数据流的协议,它支持在设备内核间进行数据传输,而不需要在用户模式下进行数据转换。这样可以获得较高的效率,减少不必要的工作。 操作系统仍然支持VfW驱动程序,但是依赖于VFW的开发将逐渐减少,这是因为下面三个原因: l WDM数据流为基于电视浏览和视频会议的捕获设备提供了优化支持。 l DirectShow提供了更强的功能。 l Microsoft 将不会对VFW进行持续开发。 VfWWDM Mapper VfWWDM mapper 不是全面兼容并且不支持旧VFW的所有功能。例如不支持视频覆盖,也不支持视频端口implementations 。 WDM 视频捕获结构
这种播放性能可以让音视频卡支持Microsoft DirectX®的API,DirectShow 同样可以播放AVI电影文件和Apple QuickTime (.mov)格式文件。 DirectShow 被广泛地应用于Windows 95, Windows 98, 和Windows 2000应用程序。DirectShow 直接和驱动程序通讯,DirectShow 不使用AVICap, 因为AVICap分配了数据缓冲区,如果一个DirectShow 层没有放在AVICap 顶层,那么缓存区数据必须要通过转化去指向它,这样会造成效率地下。 DirectShow Filter Graph 应用程序可以通过Filter Graph管理器来进行数据访问。Filter Graph 管理器会对Filter Graph配置进行管理,同时还会通过Filter Graph控制数据的转移。Filter Graph 管理器提供了一套COM接口,去允许应用程序与Filter Graph实现通讯。 应用程序可以直接调用Filter Graph管理器接口去控制媒体流或者去获得Filter事件。还可以使用DirectShow ActiveX的OCX控件进行程序设计。,还有一套MCI子集命令可以用来向后兼容Microsoft VFW 1.x版本和遵循OM-1 MPEG MCI 规范。
视频捕获 Minidrivers 在Windows 98 和Windows 2000下,视频设备使用WDM 的Minidriver去控制视频数据流,视频捕获 Minidrivers 相当与一个客户端,它会去控制处理硬件设备的图像数据和其他相关数据。Minidrivers提供了如下的功能: 捕获压缩和非压缩的视频数据流,VBI数据,时间编码和其他辅助数据流。 每个针脚都可以支持多种不同的数据格式。比如,一个针脚它可以提供RGB16, RGB24, YVU9, 和 JPEG 数字视频。针脚可以连接到一个共享的系统内存的数据缓存区,它还可以直接连接到硬件设备。 视频流命名约定 在内核模式下,流格式使用KSDATAFORMAT数据结构。这个结构可以被扩展去包含其它特别的数据格式信息。 typedef union { struct { ULONG FormatSize; ULONG Flags; ULONG SampleSize; ULONG Reserved; GUID MajorFormat; GUID SubFormat; GUID Specifier; }; ULONGLONG Alignment; } KSDATAFORMAT, *PKSDATAFORMAT, KSDATARANGE, *PKSDATARANGE;
DirectShow 视频捕获的接口和属性 · IAMAudioInputMixer · IAMDroppedFrames · IAMStreamConfig · IAMVfwCaptureDialogs · IAMVfwCompressDialogs · IcaptureGraphBuilder · ICreateDevEnum 下表列出了DirectShow 接口与捕获驱动程序通讯的相关属性。. DirectShow 接口 IAMTuner IAMTVAudio IAMCrossbar IAMVideoProcAmp IAMAnalogVideoDecoder IAMAnalogVideoEncoder IAMCameraControl
流输出数据格式 KS_VIDEOSTREAM_CAPTURE 主要的视频流格式,用于视频会议和把数据写入磁盘。 KS_VIDEOSTREAM_PREVIEW 用于显示视频,它使用的是没有压缩的数据格式,所以不需要进行特别的解压操作。 KS_VIDEOSTREAM_VBI 用于VBI应用。 KS_VIDEOSTREAM_NABTS 用于NABTS 解码VBI 采样. KS_VIDEOSTREAM_CC KS_VIDEOSTREAM_EDS KS_VIDEOSTREAM_TELETEXT 用于图文信息 KS_VIDEOSTREAM_STILL 用于Still image. KS_VIDEOSTREAM_IS_VPE 用于基于VPE的数据流。 结束语 |