📄 博客园 - 信息时代的生存哲学 - 视频捕获软件开发完全教学.htm
字号:
<P>WS_CHILD | WS_VISIBLE, // window style</P>
<P>0, 0, 160, 120, // window position and dimensions</P>
<P>(HWND) hwndParent,</P>
<P>(int) nID /* child ID */);</P>
<P><BR>2.连接到捕获驱动(Connecting to a Capture Driver)</P>
<P>下面的例子是将MSVIDEO驱动连接到句柄为hWndC的捕获窗口, 然后调用capDriverDisconnect宏来断接.</P>
<P>fOK = SendMessage (hWndC, WM_CAP_DRIVER_CONNECT, 0, 0L);</P>
<P>//</P>
<P>// Or, use the macro to connect to the MSVIDEO driver:</P>
<P>// fOK = capDriverConnect(hWndC, 0);</P>
<P>//</P>
<P>// Place code to set up and capture video here.</P>
<P>//</P>
<P>capDriverDisconnect (hWndC);</P>
<P><BR>3.列举所有已安装的捕获驱动(Enumerating Installed Capture Drivers)</P>
<P>下面的例子使用capGetDriverDescription函数得到已安装的捕获驱动的名称及版本:</P>
<P>char szDeviceName[80];</P>
<P>char szDeviceVersion[80];</P>
<P><BR>for (wIndex = 0; wIndex < 10; wIndex++)</P>
<P>{</P>
<P>if (capGetDriverDescription (wIndex, szDeviceName,</P>
<P>sizeof (szDeviceName), szDeviceVersion,</P>
<P>sizeof (szDeviceVersion))</P>
<P>{</P>
<P>// Append name to list of installed capture drivers</P>
<P>// and then let the user select a driver to use.</P>
<P>}</P>
<P>}</P>
<P><BR>4.得到捕获驱动的性能(Obtaining the Capabilities of a Capture Driver)</P>
<P>发送WM_CAP_DRIVER_GET_CAPS消息可以得到捕获驱动的性能,并保存入一个CAPDRIVERCAPS结构.每当程序连接一个新的捕获驱动到一个捕获窗口时,
就应该更新CAPDRIVERCAPS结构. 下面的程序举例说明了如何使用capDriverGetCaps宏来得到捕获驱动的性能:</P>
<P><BR>CAPDRIVERCAPS CapDrvCaps;</P>
<P>SendMessage (hWndC, WM_CAP_DRIVER_GET_CAPS,</P>
<P>sizeof (CAPDRIVERCAPS), (LONG) (LPVOID) &CapDrvCaps);</P>
<P>// Or, use the macro to retrieve the driver capabilities.</P>
<P>// capDriverGetCaps(hWndC, &CapDrvCaps, sizeof (CAPDRIVERCAPS));</P>
<P><BR>5.得到捕获窗口的状态(Obtaining the Status of a Capture Window)</P>
<P>下面的例子使用SetWindowPos函数使捕获窗口与进来的视频流尺寸保持一致, 视频流的基本信息是使用capGetStatus宏得到的,
保存在CAPSTATUS结构中.</P>
<P><BR>CAPSTATUS CapStatus;</P>
<P>capGetStatus(hWndC, &CapStatus, sizeof (CAPSTATUS));</P>
<P>SetWindowPos(hWndC, NULL, 0, 0, CapStatus.uiImageWidth,</P>
<P>CapStatus.uiImageHeight, SWP_NOZORDER | SWP_NOMOVE);</P>
<P><BR>6.显示对话框设置视频特征(Displaying Dialog Boxes to Set Video Characteristics)</P>
<P>每个视频捕获卡一般能提供三个不同的对话框用于控制视频捕获及数字化处理. 下面的例子说明如何显示这些对话框,
在显示这些对话框之前,使用了capDriverGetCaps宏来检查CAPDRIVERCAPS结构, 以检测该卡是否有显示这些对话框:</P>
<P><BR>CAPDRIVERCAPS CapDrvCaps;</P>
<P>capDriverGetCaps(hWndC, &CapDrvCaps, sizeof (CAPDRIVERCAPS));</P>
<P><BR>// Video source dialog box.</P>
<P>if (CapDriverCaps.fHasDlgVideoSource)</P>
<P>capDlgVideoSource(hWndC);</P>
<P><BR>// Video format dialog box.</P>
<P>if (CapDriverCaps.fHasDlgVideoFormat)</P>
<P>{</P>
<P>capDlgVideoFormat(hWndC);</P>
<P>// Are there new image dimensions?</P>
<P>capGetStatus(hWndC, &CapStatus, sizeof (CAPSTATUS));</P>
<P>// If so, notify the parent of a size change.</P>
<P>}</P>
<P><BR>// Video display dialog box.</P>
<P>if (CapDriverCaps.fHasDlgVideoDisplay)</P>
<P>capDlgVideoDisplay(hWndC);</P>
<P><BR>7.得到和设置视频格式(Obtaining and Setting the Video Format)</P>
<P>BITMAPINFO结构的长度既适应于标准的也适应于压缩的数据格式, 所有程序必须总是询问此结构的尺寸以便在得到当前的视频格式之前分配内存.
下面的例子就是使用capGetVideoFormatSize宏来得到缓冲区尺寸并调用capGetVideoFormat宏来得到当前的视频格式.</P>
<P><BR>LPBITMAPINFO lpbi;</P>
<P>DWORD dwSize;</P>
<P>dwSize = capGetVideoFormatSize(hWndC);</P>
<P>lpbi = GlobalAllocPtr (GHND, dwSize);</P>
<P>capGetVideoFormat(hWndC, lpbi, dwSize);</P>
<P><BR>// Access the video format and then free the allocated memory.</P>
<P><BR>程序可以使用capSetVideoFormat宏(或WM_CAP_SET_VIDEOFORMAT消息)发送一个BITMAPINFO头结构给捕获窗口,
因为视频格式是设备细节, 你的程序应该检查返回值以便确定此格式是否已被接受.</P>
<P><BR>8. 预览视频(Previewing Video)</P>
<P>下面的例子使用capPreviewRate宏来设置每66毫秒显示一帧, 并使用capPreview宏将它放置在捕获窗口里.</P>
<P><BR>capPreviewRate(hWndC, 66); // rate, in milliseconds</P>
<P>capPreview(hWndC, TRUE); // starts preview</P>
<P>// Preview</P>
<P>capPreview(hWnd, FALSE); // disables preview</P>
<P><BR>9.将视频设置为overlay模式(Enabling Video Overlay)</P>
<P>下面的例子: capDriverGetCaps宏确定此捕获卡是否有overlay功能, 如果有就使用宏来设置它</P>
<P><BR>CAPDRIVERCAPS CapDrvCaps;</P>
<P>capDriverGetCaps(hWndC, &CapDrvCaps, sizeof (CAPDRIVERCAPS));</P>
<P><BR>if (CapDrvCaps.fHasOverlay)</P>
<P>capOverlay(hWndC, TRUE);</P>
<P><BR>10.命名捕获文件(Naming the Capture File)</P>
<P>下面的例子: 使用capFileSetCaptureFile宏来指定预备文件名为:MYCAP.AVI,
capFileAlloc宏预先指定它的大小为5M.</P>
<P><BR>char szCaptureFile[] = "MYCAP.AVI";</P>
<P>capFileSetCaptureFile( hWndC, szCaptureFile);</P>
<P>capFileAlloc( hWndC, (1024L * 1024L * 5));</P>
<P><BR>11.格式化声频捕获(Formatting Audio Capture)</P>
<P>下面的例子使用capSetAudioFormat来设置声频格式为:11kHz, PCM 8位, 立体声</P>
<P><BR>WAVEFORMATEX wfex;</P>
<P>wfex.wFormatTag = WAVE_FORMAT_PCM;</P>
<P>wfex.nChannels = 2; // Use stereo</P>
<P>wfex.nSamplesPerSec = 11025;</P>
<P>wfex.nAvgBytesPerSec = 22050;</P>
<P>wfex.nBlockAlign = 2;</P>
<P>wfex.wBitsPerSample = 8;</P>
<P>wfex.cbSize = 0;</P>
<P><BR>capSetAudioFormat(hWndC, &wfex, sizeof(WAVEFORMATEX));</P>
<P><BR>12.改变视频捕获设置(Changing a Video Capture Setting)</P>
<P>下面的例子使用capCaptureGetSetup和capCaptureSetSetup宏得将捕获帧数从缺省的15帧改成每秒10帧.</P>
<P><BR>CAPTUREPARMS CaptureParms;</P>
<P>float FramesPerSec = 10.0;</P>
<P><BR>capCaptureGetSetup(hWndC, &CaptureParms, sizeof(CAPTUREPARMS));</P>
<P><BR>CaptureParms.dwRequestMicroSecPerFrame = (DWORD) (1.0e6
/FramesPerSec);</P>
<P>capCaptureSetSetup(hWndC, &CaptureParms, sizeof (CAPTUREPARMS));</P>
<P><BR>13.捕获数据(Capturing Data)</P>
<P>下面的例子使用capCaptureSequence宏来开始捕获视频并使用capFileSaveAs宏来将捕获的数据拷贝至NEWFILE.AVI文件中.</P>
<P><BR>char szNewName[] = "NEWFILE.AVI";</P>
<P>// Set up the capture operation.</P>
<P>capCaptureSequence(hWndC);</P>
<P>// Capture.</P>
<P>capFileSaveAs(hWndC, szNewName);</P>
<P><BR>14.增加一个信息块(Adding an Information Chunk)</P>
<P>如果你需要在你的程序捕获的声频和视频数据中加入你的其他信息, 你可以创建一个信息块并将它们插入捕获文件中, 信息块可以包含一些典型的信息,
例如:版权信息,视频来源, 外部定位信息等. 下面的例子使用capFileSetInfoChunk宏来插入一个信息块,
里面包含了一个SMPTE的时间代码.</P>
<P><BR>// This example assumes the application controls</P>
<P>// the video source for preroll and postroll.</P>
<P>CAPINFOCHUNK cic;</P>
<P>// .</P>
<P>// .</P>
<P>// .</P>
<P>cic.fccInfoID = infotypeSMPTE_TIME;</P>
<P>cic.lpData = "00:20:30:12";</P>
<P>cic.cbData = strlen (cic.lpData) + 1;</P>
<P>capFileSetInfoChunk (hwndC, &cic);</P>
<P><BR>15.在程序中加入一个回调函数(Adding Callback Functions to an Application)</P>
<P>一个程序可以为捕获窗口登记一个回调函数以便在以下的这些情况下通知程序.</P>
<P><BR>状态改变</P>
<P>错误发生</P>
<P>视频框架和声频缓冲区变得可用</P>
<P>程序应用在捕获视频流的过程中接收</P>
<P><BR>下面的例子创建一个捕获窗口并登记状态,错误,视频流和框架回调函数在消息处理对列中, 也包括了一个终止回调函数的说明.</P>
<P><BR>case WM_CREATE:</P>
<P>{</P>
<P>char achDeviceName[80] </P>
<P>char achDeviceVersion[100] </P>
<P>char achBuffer[100] </P>
<P>WORD wDriverCount = 0 </P>
<P>WORD wIndex </P>
<P>WORD wError </P>
<P>HMENU hMenu </P>
<P><BR>// Create a capture window using the capCreateCaptureWindow macro.</P>
<P>ghWndCap = capCreateCaptureWindow((LPSTR)"Capture Window",</P>
<P>WS_CHILD | WS_VISIBLE, 0, 0, 160, 120, (HWND) hWnd, (int) 0);</P>
<P><BR>// Register the error callback function using the</P>
<P>// capSetCallbackOnError macro.</P>
<P>capSetCallbackOnError(ghWndCap, fpErrorCallback);</P>
<P><BR>// Register the status callback function using the</P>
<P>// capSetCallbackOnStatus macro.</P>
<P>capSetCallbackOnStatus(ghWndCap, fpStatusCallback);</P>
<P><BR>// Register the video-stream callback function using the</P>
<P>// capSetCallbackOnVideoStream macro.</P>
<P>capSetCallbackOnVideoStream(ghWndCap, fpVideoCallback);</P>
<P><BR>// Register the frame callback function using the</P>
<P>// capSetCallbackOnFrame macro.</P>
<P>capSetCallbackOnFrame(ghWndCap, fpFrameCallback);</P>
<P><BR>// Connect to a capture driver</P>
<P><BR>break;</P>
<P>}</P>
<P>case WM_CLOSE:</P>
<P>{</P>
<P>// Use the capSetCallbackOnFrame macro to</P>
<P>// disable the frame callback. Similar calls exist for the other</P>
<P>// callback functions.</P>
<P><BR>capSetCallbackOnFrame(hWndC, NULL);</P>
<P><BR>break;</P>
<P>}</P>
<P><BR>16.创建一个状态回调函数(Creating a Status Callback Function)</P>
<P>下面的例子是创建一个简单的状态回调函数,登记此回调函数使用capSetCallbackOnStatus宏.</P>
<P><BR>// StatusCallbackProc: status callback function</P>
<P>// hWnd: capture window handle</P>
<P>// nID: status code for the current status</P>
<P>// lpStatusText: status text string for the current status</P>
<P>//</P>
<P>LRESULT PASCAL StatusCallbackProc(HWND hWnd, int nID,</P>
<P>LPSTR lpStatusText)</P>
<P>{</P>
<P>if (!ghWndMain)</P>
<P>return FALSE;</P>
<P><BR>if (nID == 0) { // Clear old status messages.</P>
<P>SetWindowText(ghWndMain, (LPSTR) gachAppName);</P>
<P>return (LRESULT) TRUE;</P>
<P>}</P>
<P>// Show the status ID and status text...</P>
<P>wsprintf(gachBuffer, "Status# %d: %s", nID, lpStatusText);</P>
<P><BR>SetWindowText(ghWndMain, (LPSTR)gachBuffer);</P>
<P>return (LRESULT) TRUE;</P>
<P>}</P>
<P><BR>17.创建一个错误回调函数( Creating an Error Callback Function)</P>
<P>下面的例子是创建一个简单的错误回调函数,登记此回调函数使用capsetCallbackOnError宏:</P>
<P><BR>// ErrorCallbackProc: error callback function</P>
<P>// hWnd: capture window handle</P>
<P>// nErrID: error code for the encountered error</P>
<P>// lpErrorText: error text string for the encountered error</P>
<P>//</P>
<P>LRESULT PASCAL ErrorCallbackProc(HWND hWnd, int nErrID,</P>
<P>LPSTR lpErrorText)</P>
<P>{</P>
<P>if (!ghWndMain)</P>
<P>return FALSE;</P>
<P><BR>if (nErrID == 0) // Starting a new major function.</P>
<P>return TRUE; // Clear out old errors.</P>
<P><BR>// Show the error identifier and text.</P>
<P>wsprintf(gachBuffer, "Error# %d", nErrID);</P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -