vfw摄像头采集

参考资料

https://msdn.microsoft.com/en-us/library/windows/desktop/dd757677(v=vs.85).aspx


视频捕获

1)创建捕获窗口

hWndC = capCreateCaptureWindow (

    TEXT("My Capture Window"),   // window name if pop-up

    WS_CHILD | WS_VISIBLE,       // window style

    0, 0, 160, 120,              // window position and dimensions

    (HWND) hwndParent,

    (int) nID /* child ID */);

2)       连接到捕获驱动器

The following example connects the capture window with thehandle hWndC to the MSVIDEO driver and then disconnects them using thecapDriverDisconnect macro:

fOK = SendMessage (hWndC, WM_CAP_DRIVER_CONNECT, 0, 0L);

//

// Or, use the macro to connect to the MSVIDEO driver:

// fOK = capDriverConnect(hWndC, 0);

//

// Place code to set up and capture video here.

//

capDriverDisconnect (hWndC);

3)       枚举安装的捕获驱动程序

char szDeviceName[80];

char szDeviceVersion[80];

 

for (wIndex = 0; wIndex < 10; wIndex++)

{

    if (capGetDriverDescription(

            wIndex,

            szDeviceName,

            sizeof (szDeviceName),

            szDeviceVersion,

            sizeof (szDeviceVersion)

        ))

    {

        // Append name to list of installed capture drivers

        // and then let the user select a driver to use.

    }

}

 

4)       获得性能参数

The WM_CAP_DRIVER_GET_CAPS messagereturns the capabilities of the capture driver and underlying hardware in theCAPDRIVERCAPS structure. Each time an application connects a new capture driverto the capture window, it should update the CAPDRIVERCAPS structure. Thefollowing example uses the capDriverGetCaps macro to obtain the capture drivercapabilities.

CAPDRIVERCAPS CapDrvCaps;

SendMessage (hWndC, WM_CAP_DRIVER_GET_CAPS,

    sizeof (CAPDRIVERCAPS), (LONG) (LPVOID) &CapDrvCaps);

// Or, use the macro to retrieve the driver capabilities.

// capDriverGetCaps(hWndC, &CapDrvCaps, sizeof (CAPDRIVERCAPS));

5)       获得捕获窗口状态

The following example uses the SetWindowPos functionto set the size of the capture window to the overall dimensions of the incomingvideo stream based on information returned by the capGetStatusmacroin the CAPSTATUS structure.



CAPSTATUS CapStatus;

 

capGetStatus(hWndC, &CapStatus, sizeof (CAPSTATUS));

 

SetWindowPos(hWndC, NULL, 0, 0, CapStatus.uiImageWidth,

    CapStatus.uiImageHeight, SWP_NOZORDER | SWP_NOMOVE);

6)       设置视频属性

Each capture driver can provide up tothree different dialog boxes used to control aspects of the video digitizationand capture process. The following example demonstrates how to display thesedialog boxes. Before displaying each dialog box, the example calls the capDriverGetCaps macroand checks the CAPDRIVERCAPS structurereturned to see if the capture driver can display it.

HWND hWndC = capCreateCaptureWindow(TEXT("My Capture Window"),

    WS_CHILD | WS_VISIBLE, 0, 0, 160, 120, hwndParent, nID);

 

CAPDRIVERCAPS CapDriverCaps = { };

CAPSTATUS     CapStatus = { };

 

capDriverGetCaps(hWndC, &CapDriverCaps, sizeof(CAPDRIVERCAPS));

 

// Video source dialog box.

if (CapDriverCaps.fHasDlgVideoSource)

{

    capDlgVideoSource(hWndC);

}

 

// Video format dialog box.

if (CapDriverCaps.fHasDlgVideoFormat)

{

    capDlgVideoFormat(hWndC);

 

    // Are there new image dimensions?

    capGetStatus(hWndC, &CapStatus, sizeof (CAPSTATUS));

 

    // If so, notify the parent of a size change.

}

 

// Video display dialog box.

if (CapDriverCaps.fHasDlgVideoDisplay)

{

    capDlgVideoDisplay(hWndC);

}

7) 获得/设定视频格式

The BITMAPINFO structure is of variable length to accommodate standardand compressed data formats. Because this structure is of variable length,applications must always query the size of the structure and allocate memorybefore retrieving the current video format. The following example usesthe capGetVideoFormatSize macro to retrieve the buffer size and then calls the capGetVideoFormatmacro to retrieve the current video format.

 

BITMAPINFO数据结构体可以实现长度可调节地去适应标准压缩的数据格式。因为它的长度可以变,所以在每次获得当前视频格式前,都必须去查询这个结构的长度以及分配的内存大小。该例子使用了capGetVideoFormatSize宏去获得缓存区大小,使用capGetVideoFormat宏区获得当前视频格式。

 

LPBITMAPINFO lpbi;

DWORD dwSize;

 

dwSize = capGetVideoFormatSize(hWndC);

lpbi = GlobalAllocPtr (GHND, dwSize);

capGetVideoFormat(hWndC, lpbi, dwSize);

 

// Access the video format and then free the allocated memory.

Applications can usethe capSetVideoFormat macro (or the WM_CAP_SET_VIDEOFORMAT message) to send a BITMAPINFO header structure to the capture window. Because videoformats are device specific, your application should check the return value todetermine if the format was accepted.

应用程序使用capSetVideoFormat(WM_CAP_SET_VIDEOFORMAT),把一个BITMAPINFO结构发送给捕获窗口,显示修改。因为视频格式由设备指定的,你的应用程序可以去检查获得的返回值,来知道这个视频格式是不是公开的。

 

 

8)视频预览

The following example usesthe capPreviewRate macro to set the frame display rate for preview mode to 66milliseconds per frame and then uses the capPreview macro to place the capture window in preview mode.

 

// Create the capture window.

HWND hWndC = capCreateCaptureWindow(TEXT("My Capture Window"),

    WS_CHILD | WS_VISIBLE, 0, 0, 160, 120, hwndParent, nID);

 

capPreviewRate(hWndC, 66);     // rate, in milliseconds

capPreview(hWndC, TRUE);       // starts preview

 

// Preview

 

capPreview(hWndC, FALSE);        // disables preview

9)启用视频覆盖

CAPDRIVERCAPS CapDrvCaps;

 

capDriverGetCaps(hWndC, &CapDrvCaps, sizeof (CAPDRIVERCAPS));

 

if (CapDrvCaps.fHasOverlay)

    capOverlay(hWndC, TRUE);

10)命名捕获文件

 下例使用capFileSetCaptureFile宏来指定一个要命名的文件名(mycap.avi),使用capFileAlloc宏去预分配5MB的文件。

The following example usesthe capFileSetCaptureFile macro to specify an alternate filename (MYCAP.AVI) for thecapture file and the capFileAlloc macro to preallocate a file of 5 MB.

 

 

 

 

char szCaptureFile[] = "MYCAP.AVI";

 

capFileSetCaptureFile( hWndC, szCaptureFile);

capFileAlloc( hWndC, (1024L * 1024L * 5));

11)格式化音频

下例使用capSetAudioFormat来设置音频格式为11-KHz PCM 8-bit,立体声。

The following example usescapSetAudioFormat to set the audio format to 11-kHz PCM 8-bit, stereo.

WAVEFORMATEX wfex;

 

wfex.wFormatTag = WAVE_FORMAT_PCM;

wfex.nChannels = 2;                // Use stereo

wfex.nSamplesPerSec = 11025;

wfex.nAvgBytesPerSec = 22050;

wfex.nBlockAlign = 2;

wfex.wBitsPerSample = 8;

wfex.cbSize = 0;

 

capSetAudioFormat(hWndC, &wfex, sizeof(WAVEFORMATEX));

12 改变视频捕获设置

 

The following example usesthe capCaptureGetSetup and capCaptureSetSetup macros to change the capture rate from the default value(15 frames per second) to 10 frames per second

 下例使用capCaptureGetSetupcapCaptureSetSetup宏来改变捕获速度,从默认值(15/)10/秒。

 

CAPTUREPARMS CaptureParms;

float FramesPerSec = 10.0;

 

capCaptureGetSetup(hWndC, &CaptureParms, sizeof(CAPTUREPARMS));

 

CaptureParms.dwRequestMicroSecPerFrame = (DWORD) (1.0e6 /

    FramesPerSec);

capCaptureSetSetup(hWndC, &CaptureParms, sizeof (CAPTUREPARMS));

13 捕获数据

The following example usesthe capCaptureSequence macro to start video capture and the capFileSaveAs macro to copy the captured data from the capture file tothe file NEWFILE.AVI.

 

char szNewName[] = "NEWFILE.AVI";

 

// Set up the capture operation.

 

capCaptureSequence(hWndC);

 

// Capture.

 

capFileSaveAs(hWndC, szNewName);

14)加入信息块

如果你想添加其他信息(除了音视频),你可以建一个信息块并把它们插入到一个捕获文件中去。信息块可以包含这个方面的内容。比如版权信息,视频源的ID,外部显示的时间信息。下面的例子保存外部时间信息SMPTE()到一个信息块中,并加入使用capFileSetInfoChunk宏加入到捕获文件中。

 

If you need to include otherinformation in your application in addition to audio and video, you can createinformation chunks and insert them into a capture file. Information chunks cancontain several types of information, including the details of a copyrightnotice, identification of the video source, or external timing information. Thefollowing example stores external timing information a SMPTE (Society of MotionPicture and Television Engineers) timecode in an information chunk and adds thechunk to a capture file using the capFileSetInfoChunk macro.

 

//  This example assumes the application controls

//  the video source for preroll and postroll.

CAPINFOCHUNK cic;

// .

// .

// .

cic.fccInfoID = infotypeSMPTE_TIME;

cic.lpData = "00:20:30:12";

cic.cbData = strlen (cic.lpData) + 1;

capFileSetInfoChunk (hwndC, &cic);

 

15)加入回调函数

An applicationcan register callback functions with the capture window so that it notifies theapplication in the following circumstances:

·        The status changes

·        Errors occur

·        Video frame and audio buffers become available

·        The application should yield during streaming capture

The followingexample creates a capture window and registers status, error, video stream, andframe callback functions in the message-processing loop of an application. Italso includes a sample statement for disabling a callback function. Subsequentexamples show simple status, error, and frame callback functions.

 

 

 

应用程序可以注册捕获窗口的回调函数,这样就可以把下面的情况通知给应用程序:

l         状态变化了

l         错误发生了

l         视频和音频的缓冲区的数据可以使用了

l         在捕获期间,应用程序将yield

下面的例子将创建一个捕获窗口并在应用的消息循环中,注状态、错误、视频流、帧的回调函数。

case WM_CREATE: 
{ 
    char    achDeviceName[80] ; 
    char    achDeviceVersion[100] ; 
    char    achBuffer[100] ; 
    WORD    wDriverCount = 0 ; 
    WORD    wIndex ; 
    WORD    wError ; 
    HMENU   hMenu ; 
 
    // Create a capture window using the capCreateCaptureWindow macro.
    ghWndCap = capCreateCaptureWindow((LPSTR)"Capture Window", 
        WS_CHILD | WS_VISIBLE, 0, 0, 160, 120, (HWND) hWnd, (int) 0); 
 
    // Register the error callback function using the 
    // capSetCallbackOnError macro. 
    capSetCallbackOnError(ghWndCap, fpErrorCallback); 
 
    // Register the status callback function using the 
    // capSetCallbackOnStatus macro. 
    capSetCallbackOnStatus(ghWndCap, fpStatusCallback); 
 
    // Register the video-stream callback function using the
    // capSetCallbackOnVideoStream macro. 
    capSetCallbackOnVideoStream(ghWndCap, fpVideoCallback); 
 
    // Register the frame callback function using the
    // capSetCallbackOnFrame macro. 
    capSetCallbackOnFrame(ghWndCap, fpFrameCallback); 
 
    // Connect to a capture driver 
 
    break; 
} 
case WM_CLOSE: 
{ 
// Use the capSetCallbackOnFrame macro to 
// disable the frame callback. Similar calls exist for the other 
// callback functions.
 
    capSetCallbackOnFrame(ghWndCap, NULL); 
 
    break; 
} 
 
 

16)创建状态回调函数

The following example is asimple status callback function. Register this callback by using the capSetCallbackOnStatus macro.

 


  
  
TCHAR gachAppName[] = TEXT("Application Name");  // Application name.
TCHAR gachBuffer[100];  // Global buffer.
 
// StatusCallbackProc: status callback function. 
// hWnd:               capture window handle. 
// nID:                status code for the current status. 
// lpStatusText:       status text string for the current status. 
// 
LRESULT PASCAL StatusCallbackProc(HWND hWnd, int nID, 
    LPTSTR lpStatusText) 
{ 
    if (!hWnd) 
        return FALSE; 
 
    if (nID == 0) {
        // Clear old status messages.
        SetWindowText(hWnd, gachAppName); 
        return (LRESULT) TRUE; 
    } 
    // Show the status ID and status text. 
    _stprintf_s(gachBuffer, TEXT("Status# %d: %s"), nID, lpStatusText); 
 
    SetWindowText(hWnd, gachBuffer); 
    return (LRESULT) TRUE; 
} 
 

17)错误回调函数

The following example is asimple error callback function. Register this callback by using the capSetCallbackOnError macro.

 


  
  
TCHAR gachBuffer[100]; // Global buffer.
 
// ErrorCallbackProc: error callback function. 
// hWnd:              capture window handle. 
// nErrID:            error code for the encountered error. 
// lpErrorText:       error text string for the encountered error. 
// 
LRESULT PASCAL ErrorCallbackProc(HWND hWnd, int nErrID,
    LPTSTR lpErrorText) 
{ 
 
    if (!hWnd) 
        return FALSE; 
 
    if (nErrID == 0)            // Starting a new major function. 
        return TRUE;            // Clear out old errors. 
 
    // Show the error identifier and text. 
    _stprintf_s(gachBuffer, TEXT("Error# %d"), nErrID); 
 
    MessageBox(hWnd, lpErrorText, gachBuffer, 
        MB_OK | MB_ICONEXCLAMATION); 
 
    return (LRESULT) TRUE; 
} 

18)帧回调函数

The following example is asimple frame callback function. Register this callback by using the capSetCallbackOnFrame macro.

 

 

 

TCHAR gachBuffer[100];  // Global buffer.
DWORD gdwFrameNum = 0;
 
// FrameCallbackProc: frame callback function. 
// hWnd:              capture window handle. 
// lpVHdr:            pointer to structure containing captured 
//                        frame information. 
// 
LRESULT PASCAL FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr) 
{ 
    if (!hWnd) 
        return FALSE; 
 
    _stprintf_s(gachBuffer, TEXT("Preview frame# %ld "), gdwFrameNum++); 
    SetWindowText(hWnd, gachBuffer); 
    return (LRESULT) TRUE ; 
} 

猜你喜欢

转载自blog.csdn.net/shuilan0066/article/details/80207216