zoukankan      html  css  js  c++  java
  • 关于 web cam 使用自家的摄像头实现 视频捕捉技术 高级篇


    网络上一大堆的视频捕捉代码,比如:

    代码
    public class WebCameraEngine
        {
            
    //  showVideo  calls
            [DllImport("avicap32.dll")]
            
    public static extern IntPtr capCreateCaptureWindowA(byte[] lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, int nID);
            [DllImport(
    "avicap32.dll")]
            
    public static extern bool capGetDriverDescriptionA(short wDriver, byte[] lpszName, int cbName, byte[] lpszVer, int cbVer);
            [DllImport(
    "User32.dll")]
            
    public static extern bool SendMessage(IntPtr hWnd, int wMsg, bool wParam, int lParam);
            [DllImport(
    "User32.dll")]
            
    public static extern bool SendMessage(IntPtr hWnd, int wMsg, short wParam, int lParam);
            [DllImport(
    "User32.dll")]
            
    public static extern bool SendMessage(IntPtr hWnd, int wMsg, short wParam, FrameEventHandler lParam);
            [DllImport(
    "User32.dll")]
            
    public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, ref BitMapInfo lParam);
            [DllImport(
    "User32.dll")]
            
    public static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int cx, int cy, int wFlags);
            [DllImport(
    "avicap32.dll")]
            
    public static extern int capGetVideoFormat(IntPtr hWnd, IntPtr psVideoFormat, int wSize);

            
    //  constants
            public const int WM_USER = 0x400;

            
    public const int WS_CHILD = 0x40000000;
            
    public const int WS_VISIBLE = 0x10000000;

            
    public const int WM_CAP_DRIVER_CONNECT = WM_USER + 10;
            
    public const int WM_CAP_DRIVER_DISCONNECT = WM_USER + 11;

            
    public const int WM_CAP_START = WM_USER;
            
    public const int WM_CAP_STOP = WM_CAP_START + 68;

            
    public const int WM_CAP_SAVEDIB = WM_CAP_START + 25;
            
    public const int WM_CAP_GRAB_FRAME = WM_CAP_START + 60;
            
    public const int WM_CAP_FILE_SET_CAPTURE_FILEA = WM_CAP_START + 20;
            
    public const int WM_CAP_SEQUENCE = WM_CAP_START + 62;
            
    public const int WM_CAP_SEQUENCE_NOFILE = WM_CAP_START + 63;


            
    public const int WM_CAP_SET_OVERLAY = WM_CAP_START + 51;
            
    public const int WM_CAP_SET_CALLBACK_FRAME = WM_USER + 5;
            
    public const int WM_CAP_SET_PREVIEW = WM_USER + 50;
            
    public const int WM_CAP_SET_PREVIEWRATE = WM_USER + 52;
            
    public const int WM_CAP_SET_CALLBACK_VIDEOSTREAM = WM_CAP_START + 6;
            
    public const int WM_CAP_SET_CALLBACK_ERROR = WM_CAP_START + 2;
            
    public const int WM_CAP_SET_CALLBACK_STATUSA = WM_CAP_START + 3;
            
    public const int WM_CAP_SET_SCALE = WM_CAP_START + 53;
            
    public const int WM_CAP_SET_VIDEOFORMAT = WM_USER + 45;

            
    public const int SWP_NOMOVE = 0x2;
            
    public const int SWP_NOZORDER = 0x4;





            
    //  Structures
            [StructLayout(LayoutKind.Sequential)]
            
    public struct VideoHdr
            {
                [MarshalAs(UnmanagedType.I4)]
                
    public int lpData;
                [MarshalAs(UnmanagedType.I4)]
                
    public int dwBufferLength;
                [MarshalAs(UnmanagedType.I4)]
                
    public int dwBytesUsed;
                [MarshalAs(UnmanagedType.I4)]
                
    public int dwTimeCaptured;
                [MarshalAs(UnmanagedType.I4)]
                
    public int dwUser;
                [MarshalAs(UnmanagedType.I4)]
                
    public int dwFlags;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst 
    = 4)]
                
    public int[] dwReserved;
            }

            [StructLayout(LayoutKind.Sequential)]
            
    public struct BitMapInfoHeader
            {
                [MarshalAs(UnmanagedType.I4)]
                
    public Int32 biSize;
                [MarshalAs(UnmanagedType.I4)]
                
    public Int32 biWidth;
                [MarshalAs(UnmanagedType.I4)]
                
    public Int32 biHeight;
                [MarshalAs(UnmanagedType.I2)]
                
    public short biPlanes;
                [MarshalAs(UnmanagedType.I2)]
                
    public short biBitCount;
                [MarshalAs(UnmanagedType.I4)]
                
    public Int32 biCompression;
                [MarshalAs(UnmanagedType.I4)]
                
    public Int32 biSizeImage;
                [MarshalAs(UnmanagedType.I4)]
                
    public Int32 biXPelsPerMeter;
                [MarshalAs(UnmanagedType.I4)]
                
    public Int32 biYPelsPerMeter;
                [MarshalAs(UnmanagedType.I4)]
                
    public Int32 biClrUsed;
                [MarshalAs(UnmanagedType.I4)]
                
    public Int32 biClrImportant;
            }

            [StructLayout(LayoutKind.Sequential)]
            
    public struct BitMapInfo
            {
                [MarshalAs(UnmanagedType.Struct, SizeConst 
    = 40)]
                
    public BitMapInfoHeader bmiHeader;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst 
    = 1024)]
                
    public Int32[] bmiColors;
            }

            
    public delegate void FrameEventHandler(IntPtr lwnd, IntPtr lpVHdr);

            
    //  Public  methods
            public static object GetStructure(IntPtr ptr, ValueType structure)
            {
                
    return Marshal.PtrToStructure(ptr, structure.GetType());
            }

            
    public static object GetStructure(int ptr, ValueType structure)
            {
                
    return GetStructure(new IntPtr(ptr), structure);
            }

            
    public static void Copy(IntPtr ptr, byte[] data)
            {
                Marshal.Copy(ptr, data, 
    0, data.Length);
            }

            
    public static void Copy(int ptr, byte[] data)
            {
                Copy(
    new IntPtr(ptr), data);
            }

            
    public static int SizeOf(object structure)
            {
                
    return Marshal.SizeOf(structure);
            }
        }


    但是使用的例子却没有,特别关于视频流的问题。因此我特地查看了msdn。现在把研究过程写下来:

    http://msdn.microsoft.com/en-us/library/ms713477(VS.85).aspx

    在c#里面的例子,实际上使用了AVICap这个c++的类库。 他的功能包括:

    1. 捕捉视频音频到avi文件

    2. 动态链接、断开捕捉设备

    3. 查看实时的视频信号

    4. 设置捕捉率

    5. 显示设置对话框、palettes

    6. 拷贝图像到剪贴板

    7. 对单个图像进行截图+保存为DIB

    8.  Specify a file to use when capturing and copy the contents of the capture file to another file.(这个没太理解)

    现在对avicap所有方法进行说明:

    1.  建立一个捕捉窗口:

    代码
    hWndC = capCreateCaptureWindow (
        (LPSTR) 
    "My Capture Window"// window name if pop-up 
        WS_CHILD | WS_VISIBLE,       // window style 
        00160120,              // window position and dimensions
        (HWND) hwndParent, 
        (
    int) nID /* child ID *

    2. 链接捕捉设备

    代码
    fOK = SendMessage (hWndC, WM_CAP_DRIVER_CONNECT, 00L); 
    // 
    // 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. 获取捕捉设备的能力

    代码
    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. 获取捕捉窗口的状态

     CAPSTATUS CapStatus;


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

    SetWindowPos(hWndC, NULL, 
    00, CapStatus.uiImageWidth, 
        CapStatus.uiImageHeight, SWP_NOZORDER 
    | SWP_NOMOVE)

     6. 显示设置捕捉窗口

     代码

    CAPDRIVERCAPS CapDrvCaps; 

    capDriverGetCaps(hWndC, 
    &CapDrvCaps, 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. 预览图像

    capPreviewRate(hWndC, 66);     // rate, in milliseconds
    capPreview(hWndC, TRUE);       // starts preview 

    // Preview

    capPreview(hWnd, FALSE);        
    // disables preview 

     8. 判断是否允许图像叠加(overlay)

     CAPDRIVERCAPS CapDrvCaps; 


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

    if (CapDrvCaps.fHasOverlay) 
        capOverlay(hWndC, TRUE);
     

     9. 对视频捕捉文件命名

     char szCaptureFile[] = "MYCAP.AVI";


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

    10.  设置声音捕捉

    代码
    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)); 

     11. 改变视频捕捉设置

    代码
    CAPTUREPARMS CaptureParms;
    float FramesPerSec = 10.0;

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

    CaptureParms.dwRequestMicroSecPerFrame 
    = (DWORD) (1.0e6 / 
        FramesPerSec);
    capCaptureSetSetup(hWndC, 
    &CaptureParms, sizeof (CAPTUREPARMS)); 

     12. 捕捉数据并保存

    char szNewName[] = "NEWFILE.AVI";

    // Set up the capture operation.

    capCaptureSequence(hWndC); 

    // Capture.

    capFileSaveAs(hWndC, szNewName); 
     

     13. 在视频文件中叠加信息

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

    14.  添加一个帧回调函数

    代码
    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 ;

    }

    15. Adding Callback Functions to an Application

    16.  Creating a Status Callback Function

    17.  Creating an Error Callback Function

    reference

    asic Capture Operations

    capCreateCaptureWindow
    WM_CAP_ABORT
    WM_CAP_DRIVER_CONNECT
    WM_CAP_SEQUENCE
    WM_CAP_STOP

    Capture Windows

    CAPSTATUS
    capGetDriverDescription
    WM_CAP_DRIVER_CONNECT
    WM_CAP_DRIVER_DISCONNECT
    WM_CAP_GET_STATUS

    Capture Drivers

    CAPDRIVERCAPS
    WM_CAP_DRIVER_GET_CAPS
    WM_CAP_DRIVER_GET_NAME
    WM_CAP_DRIVER_GET_VERSION
    WM_CAP_GET_AUDIOFORMAT
    WM_CAP_GET_VIDEOFORMAT
    WM_CAP_SET_AUDIOFORMAT
    WM_CAP_SET_VIDEOFORMAT

    Capture Driver Preview and Overlay Modes

    WM_CAP_SET_OVERLAY
    WM_CAP_SET_PREVIEW
    WM_CAP_SET_PREVIEWRATE
    WM_CAP_SET_SCALE
    WM_CAP_SET_SCROLL

    Capture Driver Video Dialog Boxes

    WM_CAP_DLG_VIDEOCOMPRESSION
    WM_CAP_DLG_VIDEODISPLAY
    WM_CAP_DLG_VIDEOFORMAT
    WM_CAP_DLG_VIDEOSOURCE

    Audio Format

    WM_CAP_GET_AUDIOFORMAT
    WM_CAP_SET_AUDIOFORMAT

    Video Capture Settings

    CAPTUREPARMS
    WM_CAP_GET_SEQUENCE_SETUP
    WM_CAP_SET_SEQUENCE_SETUP

    Capture File and Buffers

    CAPTUREPARMS
    WM_CAP_FILE_ALLOCATE
    WM_CAP_FILE_GET_CAPTURE_FILE
    WM_CAP_FILE_SAVEAS
    WM_CAP_FILE_SET_CAPTURE_FILE

    Directly Using Capture Data

    WM_CAP_SEQUENCE_NOFILE

    Capture from MCI Device

    WM_CAP_SET_MCI_DEVICE

    Manual Frame Capture

    WM_CAP_SINGLE_FRAME
    WM_CAP_SINGLE_FRAME_CLOSE
    WM_CAP_SINGLE_FRAME_OPEN

    Still-Image Capture

    WM_CAP_EDIT_COPY
    WM_CAP_FILE_SAVEDIB
    WM_CAP_GRAB_FRAME
    WM_CAP_GRAB_FRAME_NOSTOP

    Advanced Capture Options

    WM_CAP_FILE_SET_INFOCHUNK
    WM_CAP_GET_USER_DATA
    WM_CAP_SET_USER_DATA

    Working with Palettes

    WM_CAP_EDIT_COPY
    WM_CAP_PAL_AUTOCREATE
    WM_CAP_PAL_MANUALCREATE
    WM_CAP_PAL_OPEN
    WM_CAP_PAL_PASTE
    WM_CAP_PAL_SAVE

    Yielding to Other Applications

    WM_CAP_GET_SEQUENCE_SETUP
    WM_CAP_SET_CALLBACK_YIELD
    WM_CAP_SET_SEQUENCE_SETUP

    AVICap Callback Functions

    capControlCallback
    capErrorCallback
    capStatusCallback
    capVideoStreamCallback
    capWaveStreamCallback
    capYieldCallback
    WM_CAP_SET_CALLBACK_CAPCONTROL
    WM_CAP_SET_CALLBACK_ERROR
    WM_CAP_SET_CALLBACK_FRAME
    WM_CAP_SET_CALLBACK_STATUS
    WM_CAP_SET_CALLBACK_VIDEOSTREAM
    WM_CAP_SET_CALLBACK_WAVESTREAM
    WM_CAP_SET_CALLBACK_YIELD

    基本上可以看到,网上那个非常简单的c#封装实际上还有很多方法没有实现。

  • 相关阅读:
    获取<input type="checkbox" >控件的checked值
    网站IIS部署及调试
    winform窗体全屏实现
    ComBox控件的使用
    在vs2005项目中,将.sln文件和.suo文件放在一个独立的文件夹内
    .NET面试题整理
    《url重写——更友好的网站url设计》
    char、varchar、nvarchar三者间的区别
    操作符"??"的用法
    Maven 学习笔记(三)
  • 原文地址:https://www.cnblogs.com/zc22/p/1618086.html
Copyright © 2011-2022 走看看