Board logo

标题: [多媒体] VB视频调用问题 [打印本页]

作者: yeeyoo    时间: 2010-4-30 21:50     标题: VB视频调用问题

在VB里面我用capCreateCaptureWindow函数可以调用笔记本自带的摄像头,但是现在需要调用外来视频源(比如USB的视频),请问该怎么修改参数?或是要用其它的什么函数?哪位同仁知道拜托啦,急!

函数capCreateCaptureWindow的完整声明如下:
Private Declare Function capCreateCaptureWindow Lib "avicap32.dll" Alias "capCreateCaptureWindowA" (ByVal lpszWindowName As String, _
ByVal dwStyle As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hwndParent As Long, ByVal nID As Long) As Long
作者: Nothing    时间: 2010-5-5 10:40

3.2使用视频捕获
3.2.1创建捕获窗体

下面的例子通过使用capCreateCaptureWindow函数来创建一个捕获窗体

hWndC = capCreateCaptureWindow (

    (LPSTR) "My Capture Window",       // 如果是Pop-up窗口的窗口名称

    WS_CHILD | WS_VISIBLE,          // 窗口类型

    0, 0, 160, 120,                      // 窗口位置和尺寸

    (HWND) hwndParent,

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






3.2.2连接到一个捕获驱动器

下面举例,如何通过捕获窗口的句柄hWndC连接到MS VIDEO驱动程序上,同时还演示了如何断开连接。使用capDriverDisconnect:

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

// 或者使用宏连接:



// fOK = capDriverConnect(hWndC, 0);







// 关闭连接

capDriverDisconnect (hWndC);





3.2.3列举安装的捕获驱动程序

使用capGetDriverDescription 函数来获得系统已经安装的所有捕获驱动程序的名称和版本。

char szDeviceName[80];

char szDeviceVersion[80];

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

{

    if (capGetDriverDescription (wIndex, szDeviceName,

        sizeof (szDeviceName), szDeviceVersion,

        sizeof (szDeviceVersion))

    {

        // 加入名字到一个已经安装的设备列表中



        // 让用户选择一个使用。

    }

}









3.2.4获得捕获驱动器的性能参数

       WM_CAP_DRIVER_GET_CAPS消息可以返回捕获驱动程序以及其硬件的性能参数。这些信息存放在一个CAPDRIVERCAPS的数据结构中。当你的应用程序的捕获窗口连接到一个新的捕获驱动器后,都会刷新这个CAPDRIVERCAPS数据结构。下面将使用capDriverGetCaps宏来获得捕获设备的性能参数。

CAPDRIVERCAPS CapDrvCaps;

SendMessage (hWndC, WM_CAP_DRIVER_GET_CAPS,

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

// 或者,使用宏来获得驱动器的新能参数



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







3.2.5获得捕获窗口状态(Status)

下面例子使用SetWindowPos函数区设置捕获窗口的尺寸,这个尺寸的大小是基于输入的视频流大小的。输入视频流的尺寸大小由capGetStatus宏来获得,获得信息放在一个CAPSTATUS的数据结构体中。





CAPSTATUS CapStatus;

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

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

             CapStatus.uiImageHeight, SWP_NOZORDER | SWP_NOMOVE);


3.2.6显示对话框区设置视频属性

       每个捕获驱动器都可以提高3个以上的不同对话框来控制数字视频的特性和捕获处理。下面的例子示范如何显示这些对话框。在显示每个对话框前,该例会调用capDriverGetCaps宏并且检查返回的CAPDRIVERCAPS对象来查看是否可以能够显示特定的对话框。





CAPDRIVERCAPS CapDrvCaps;

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

// 视频源对话框



if (CapDriverCaps.fHasDlgVideoSource)

    capDlgVideoSource(hWndC);  

// 视频格式对话框



if (CapDriverCaps.fHasDlgVideoFormat)

{

    capDlgVideoFormat(hWndC);

    // 是否由新的图像尺寸?Are there new image dimensions?



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

    // 如果有,发送通知给父窗口,告诉它尺寸改变了



}  

// 视频显示对话框



if (CapDriverCaps.fHasDlgVideoDisplay)

    capDlgVideoDisplay(hWndC);





3.2.7获得和设定视频格式

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





LPBITMAPINFO lpbi;

DWORD dwSize;





dwSize = capGetVideoFormatSize(hWndC);

lpbi = GlobalAllocPtr (GHND, dwSize);

capGetVideoFormat(hWndC, lpbi, dwSize);





// 访问视频格式,并且释放分配的内存。







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





3.2.8预览视频
       下面使用capPreviewRate宏来设置预览模式的帧频率为66毫秒/帧,使用capPreview宏在捕获窗口预览图像。





capPreviewRate(hWndC, 66);      // 速度,微秒



capPreview(hWndC, TRUE);       // 开始预览







capPreview(hWnd, FALSE);        // 屏蔽预览





3.2.9允许视频覆盖(Overlay)

下面使用capDriverGetCaps宏去检测这个捕获驱动是否支持覆盖(Overlay)模式,如果支持,就允许视频覆盖模式;





CAPDRIVERCAPS CapDrvCaps;

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

if (CapDrvCaps.fHasOverlay)

    capOverlay(hWndC, TRUE);







3.2.10捕获文件命名

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





char szCaptureFile[] = "MYCAP.AVI";

capFileSetCaptureFile( hWndC, szCaptureFile);

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



3.2.11格式化音频捕获

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





WAVEFORMATEX wfex;

wfex.wFormatTag = WAVE_FORMAT_PCM;

wfex.nChannels = 2;                     // 使用立体声

wfex.nSamplesPerSec = 11025;

wfex.nAvgBytesPerSec = 22050;

wfex.nBlockAlign = 2;

wfex.wBitsPerSample = 8;

wfex.cbSize = 0;

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





3.2.12改变视频捕获设置

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





CAPTUREPARMS CaptureParms;

float FramesPerSec = 10.0;

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

CaptureParms.dwRequestMicroSecPerFrame = (DWORD) (1.0e6 /

    FramesPerSec);

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





3.2.13捕获数据

       下例使用capCaptureSequence宏开始视频捕获,使用capFileSaveAs宏从捕获文件拷贝数据到其他文件NEWFILE.AVI中。





char szNewName[] = "NEWFILE.AVI";

// Set up the capture operation.

capCaptureSequence(hWndC);

// Capture.

capFileSaveAs(hWndC, szNewName);





3.2.14加入信息块

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





//  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);





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

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 ;



    // 使用capCreateCaptureWindow宏创建一个捕获窗体.



    ghWndCap = capCreateCaptureWindow((LPSTR)"Capture Window",

        WS_CHILD | WS_VISIBLE, 0, 0, 160, 120, (HWND) hWnd, (int) 0);



    // 使用capSetCallbackOnError宏注册错误回调函数



     capSetCallbackOnError(ghWndCap, fpErrorCallback);



    // 使用capSetCallbackOnStatus宏注册状态回调函数



    capSetCallbackOnStatus(ghWndCap, fpStatusCallback);



    //使用capSetCallbackOnVideoStream宏注册视频流回调函数

    capSetCallbackOnVideoStream(ghWndCap, fpVideoCallback);



    //使用capSetCallbackOnFrame宏注册帧回调函数

    capSetCallbackOnFrame(ghWndCap, fpFrameCallback);



    // 连接到一个捕获驱动器上







    break;

}

case WM_CLOSE:

{

//使用capSetCallbackOnFrame宏关闭帧回调函数

// 类似可调用其他存在的回调函数。







    capSetCallbackOnFrame(hWndC, NULL);

  break;

}











3.2.16创建一个状态回调函数

下面的例子是一个简单的状态回调函数,使用capSetCallbackOnStatus宏来注册这个回调函数。

// StatusCallbackProc: 状态回调函数



// hWnd:            捕获窗体句柄



// nID:              当前状态的状态码



// lpStatusText:       当前状态的文本字符

//

LRESULT PASCAL StatusCallbackProc(HWND hWnd, int nID,

    LPSTR lpStatusText)

{

    if (!ghWndMain)

        return FALSE;



    if (nID == 0) {           // 清除旧的状态信息

        SetWindowText(ghWndMain, (LPSTR) gachAppName);

        return (LRESULT) TRUE;

    }

    // 显示状态ID和状态文本..



    wsprintf(gachBuffer, "Status# %d: %s", nID, lpStatusText);



    SetWindowText(ghWndMain, (LPSTR)gachBuffer);

    return (LRESULT) TRUE;

}



3.2.17创建一个错误的回调函数

下面例子是一个简单的错误回调函数。通过capSetCallbackOnError宏来注册回调。

// ErrorCallbackProc:    错误回调函数



// hWnd:              捕获窗口句柄



// nErrID:              错误代码



// lpErrorText:          关于错误的文本信息

//

LRESULT PASCAL ErrorCallbackProc(HWND hWnd, int nErrID,

    LPSTR lpErrorText)

{



    if (!ghWndMain)

        return FALSE;



    if (nErrID == 0)            // Starting a new major function.

        return TRUE;          // 清除旧的错误



    // 显示错误ID和错误文本信息



    wsprintf(gachBuffer, "Error# %d", nErrID);



    MessageBox(hWnd, lpErrorText, gachBuffer,

               MB_OK | MB_ICONEXCLAMATION);



    return (LRESULT) TRUE;

}





3.2.18创建一个帧回调函数

下面是一个简单的帧回调函数。通过capSetCallbackFrame宏来注册回调函数。





// FrameCallbackProc:   帧回调函数



// hWnd:              捕获窗体句柄



// lpVHdr:             指向一个包含帧信息的数据结构体

//

LRESULT PASCAL FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr)

{

    if (!ghWndMain)

        return FALSE;



    wsprintf(gachBuffer, "Preview frame# %ld ", gdwFrameNum++);

    SetWindowText(ghWndMain, (LPSTR)gachBuffer);

    return (LRESULT) TRUE ;

}
作者: prairiewolf    时间: 2010-12-4 15:54

我用VB写的读取摄像头序号的程序,只能列出序号为“0”的摄像头来,不知道是为什么。
以下是摘自楼上的回复。
char szDeviceName[80];
char szDeviceVersion[80];
for (wIndex = 0; wIndex < 10; wIndex++)
{
    if (capGetDriverDescription (wIndex, szDeviceName,
        sizeof (szDeviceName), szDeviceVersion,
        sizeof (szDeviceVersion))
    {
        // 加入名字到一个已经安装的设备列表中
         // 让用户选择一个使用。
    }
}
以下代码是我用VB写的,语法跟上面不一样,但运行起来就只能列出序号为“0”的摄像头,不知道是什么原因
'---list all the various video sources---
Function ListVideoSources()
    Dim DriverName As String * 80
    Dim DriverVersion As String * 80
    Label1.Caption = ""
    For i = 0 To 9
        If capGetDriverDescriptionA(i, DriverName, 80, DriverVersion, 80) Then
            Label1.Caption = Label1.Caption & "第" & i & "个摄像头" & Trim(DriverName) & vbCrLf
        End If
    Next
End Function
作者: Nothing    时间: 2010-12-7 21:35

你的传值不对
注意capGetDriverDescriptionA和capGetDriverDescriptionW的区别
作者: ytw6176    时间: 2011-1-2 16:15

不知所云。




欢迎光临 编程开发论坛 (http://bbs.lihuasoft.net/) Powered by Discuz! 6.0.0