c#實現調用筆記本攝像頭,實現視頻采集


1.關於avicap32.dll基本概念

VFW(Video For Window)技術是Microsoft公司為開發Windows平台下的視頻應用程序提供的軟件工具包,提供了一系列應用程序編程接口(API),用戶可以通過這些接口很 方便地實現視頻捕獲、視頻編輯及視頻播放等通用功能,還可利用回調函數開發比較復雜的視頻應用程序。該技術的特點是播放視頻時不需要專用的硬件設備,而且 應用靈活,可以滿足視頻應用程序開發的需要。Windows操作系統自身就攜帶了VFW技術,系統安裝時,會自動安裝VFW的相關組件。

AVICAP32.DLL:包含執行視頻捕獲的函數,給AVI文件的I/O處理和視頻,音頻設備驅動程序提供一個高級接口。 MSVIDEO.DLL:包含一套特殊的DrawDib函數,用來處理程序上的視頻操作。MCIAVI.DRV:包括對VFW的MCI命令解釋器的驅動程序。AVIFILE.DLL:包含由標准多媒體I/O(mmio)函數提供的更高級的命令,用來訪問.AVI文件。ICM:壓縮管理器,用於管理的視頻壓縮/解壓縮的編譯碼器。ACM:音頻壓縮管理器,提供與ICM相似的服務,適用於波形音頻。

2.關於avicap32.dll重要函數的參數的介紹

(1)capCreateCaptureWindow函數

該函數用於創建一個視頻捕捉窗口。語法如下:

        [DllImport("avicap32.dll")]

        public static extern IntPtr capCreateCaptureWindowA(byte[] lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, int nID);

參數說明如下。

l     lpszWindowName:標識窗口的名稱。

l     dwStyle:標識窗口風格。

l     x、y:標識窗口的左上角坐標。

l     nWidth、nHeight:標識窗口的寬度和高度。

l     hWnd:標識父窗口句柄。

l     nID:標識窗口ID。

l     返回值:視頻捕捉窗口句柄

(2)SendMessage函數

用於向Windows系統發送消息機制。

[DllImport("User32.dll")]

private static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam);

參數說明如下。

l     hWnd:窗口句柄。

l     wMsg:將要發送的消息。

l     wParam、lParam:消息的參數,每個消息都有兩個參數,參數設置由發送的消息而定。

 3.

using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Text;

namespace AVI
{
public class AviCapture
{
#region 導入API函數

[DllImport("avicap32.dll")]//包含了執行視頻捕獲的函數,它給AVI文件I/O和視頻、音頻設備驅動程序提供一個高級接口
public static extern IntPtr capCreateCaptureWindow(string lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hwndParent, int nID);
/************參數說明*************
* 
* 函數:capCreateCaptureWindow
* 
* lpszWindowName:標識窗口的名稱
* dwStyle:標識窗口風格
* x、y:標識窗口的左上角坐標
* nWidth、nHeight:標識窗口的寬度和高度
* hWnd:標識父窗口句柄
* nID:標識窗口ID
* 
* 返回值:視頻捕捉窗口句柄。
* 
********************************/

[DllImport("AVICAP32.dll", CharSet = CharSet.Unicode)]
public static extern bool capGetDriverDescription(int wDriverIndex, StringBuilder lpszName, int cbName, StringBuilder 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, int 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 bool SendMessage(IntPtr hWnd, int wMsg, int wParam, ref CAPDRIVERCAPS lParam);
[DllImport("User32.dll")]
public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, ref CAPTUREPARMS lParam);
[DllImport("User32.dll")]
public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, ref CAPSTATUS 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);

#endregion


#region 消息常量(向窗口發送消息的指令)

//消息常量 -------------------------------------------- 
public const int WM_START = 0x400;    //此並非攝像頭消息0x400表示的就是1024 
public const int WS_CHILD = 0x40000000;
public const int WS_VISIBLE = 0x10000000;
public const int SWP_NOMOVE = 0x2;
public const int SWP_NOZORDER = 0x4;
public const int WM_CAP_GET_CAPSTREAMPTR = WM_START + 1;
public const int WM_CAP_SET_CALLBACK_ERROR = WM_START + 2;//設置收回錯誤
public const int WM_CAP_SET_CALLBACK_STATUS = WM_START + 3;//設置收回狀態
public const int WM_CAP_SET_CALLBACK_YIELD = WM_START + 4;//設置收回出產
public const int WM_CAP_SET_CALLBACK_FRAME = WM_START + 5;//設置收回結構
public const int WM_CAP_SET_CALLBACK_VIDEOSTREAM = WM_START + 6;//設置收回視頻流
public const int WM_CAP_SET_CALLBACK_WAVESTREAM = WM_START + 7;//設置收回視頻波流
public const int WM_CAP_GET_USER_DATA = WM_START + 8;//獲得使用者數據
public const int WM_CAP_SET_USER_DATA = WM_START + 9;//設置使用者數據
public const int WM_CAP_DRIVER_CONNECT = WM_START + 10;//驅動程序連接
public const int WM_CAP_DRIVER_DISCONNECT = WM_START + 11;//斷開啟動程序連接
public const int WM_CAP_DRIVER_GET_NAME = WM_START + 12;//獲得驅動程序名字
public const int WM_CAP_DRIVER_GET_VERSION = WM_START + 13;//獲得驅動程序版本
public const int WM_CAP_DRIVER_GET_CAPS = WM_START + 14;//獲得驅動程序帽子
public const int WM_CAP_FILE_SET_CAPTURE_FILE = WM_START + 20;//設置捕獲文件
public const int WM_CAP_FILE_GET_CAPTURE_FILE = WM_START + 21;//獲得捕獲文件
public const int WM_CAP_FILE_ALLOCATE = WM_START + 22;//分派文件
public const int WM_CAP_FILE_SAVEAS = WM_START + 23;//另存文件為
public const int WM_CAP_FILE_SET_INFOCHUNK = WM_START + 24;//設置開始文件
public const int WM_CAP_FILE_SAVEDIB = WM_START + 25;//保存文件
public const int WM_CAP_EDIT_COPY = WM_START + 30;//編輯復制
public const int WM_CAP_SET_AUDIOFORMAT = WM_START + 35;//設置音頻格式
public const int WM_CAP_GET_AUDIOFORMAT = WM_START + 36;//捕獲音頻格式
public const int WM_CAP_DLG_VIDEOFORMAT = WM_START + 41;//1065 打開視頻格式設置對話框
public const int WM_CAP_DLG_VIDEOSOURCE = WM_START + 42;//1066 打開屬性設置對話框,設置對比度亮度等
public const int WM_CAP_DLG_VIDEODISPLAY = WM_START + 43;//1067 打開視頻顯示
public const int WM_CAP_GET_VIDEOFORMAT = WM_START + 44;//1068 獲得視頻格式
public const int WM_CAP_SET_VIDEOFORMAT = WM_START + 45;//1069 設置視頻格式
public const int WM_CAP_DLG_VIDEOCOMPRESSION = WM_START + 46;//1070 打開壓縮設置對話框
public const int WM_CAP_SET_PREVIEW = WM_START + 50;//設置預覽
public const int WM_CAP_SET_OVERLAY = WM_START + 51;//設置覆蓋
public const int WM_CAP_SET_PREVIEWRATE = WM_START + 52;//設置預覽比例
public const int WM_CAP_SET_SCALE = WM_START + 53;//設置刻度
public const int WM_CAP_GET_STATUS = WM_START + 54;//獲得狀態
public const int WM_CAP_SET_SCROLL = WM_START + 55;//設置卷
public const int WM_CAP_GRAB_FRAME = WM_START + 60;//逮捕結構
public const int WM_CAP_GRAB_FRAME_NOSTOP = WM_START + 61;//停止逮捕結構
public const int WM_CAP_SEQUENCE = WM_START + 62;//次序
public const int WM_CAP_SEQUENCE_NOFILE = WM_START + 63;//使用WM_CAP_SEUENCE_NOFILE消息(capCaptureSequenceNoFile宏),可以不向磁盤文件寫入數據。該消息僅在配合回調函數時有用,它允許你的應用程序直接使用音視頻數據。
public const int WM_CAP_SET_SEQUENCE_SETUP = WM_START + 64;//設置安裝次序
public const int WM_CAP_GET_SEQUENCE_SETUP = WM_START + 65;//獲得安裝次序
public const int WM_CAP_SET_MCI_DEVICE = WM_START + 66;//設置媒體控制接口
public const int WM_CAP_GET_MCI_DEVICE = WM_START + 67;//獲得媒體控制接口
public const int WM_CAP_STOP = WM_START + 68;//停止
public const int WM_CAP_ABORT = WM_START + 69;//異常中斷
public const int WM_CAP_SINGLE_FRAME_OPEN = WM_START + 70;//打開單一的結構
public const int WM_CAP_SINGLE_FRAME_CLOSE = WM_START + 71;//關閉單一的結構
public const int WM_CAP_SINGLE_FRAME = WM_START + 72;//單一的結構
public const int WM_CAP_PAL_OPEN = WM_START + 80;//打開視頻
public const int WM_CAP_PAL_SAVE = WM_START + 81;//保存視頻
public const int WM_CAP_PAL_PASTE = WM_START + 82;//粘貼視頻
public const int WM_CAP_PAL_AUTOCREATE = WM_START + 83; //自動創造
public const int WM_CAP_PAL_MANUALCREATE = WM_START + 84;//手動創造
public const int WM_CAP_SET_CALLBACK_CAPCONTROL = WM_START + 85;// 設置收回的錯誤

#endregion 消息常量


#region 結構體

/*********VideoHdr 結構體*********
* 
* 定義了視頻數據塊的頭信息,
* 在編寫回調函數時常用到其數據成員lpData(指向數據緩存的指針)和dwBufferLength(數據緩存的大小)。
* 視頻幀到緩存的捕獲則需要應用回調函數和相應的數據塊結構 VIDEOHDR
* 
*******************************/

[StructLayout(LayoutKind.Sequential)]
public struct VIDEOHDR
{
public IntPtr lpData;                 /* 指向數據緩存的指針 */
public int dwBufferLength;         /* 數據緩存的大小 */
public int dwBytesUsed;            /* Bytes actually used */
public int dwTimeCaptured;         /* Milliseconds from start of stream */
public int dwUser;                 /* for client's use */
public int dwFlags;                /* assorted flags (see defines) */
public int dwReserved;          /* reserved for driver */
}


/*********BitmapInfoHeader 結構體*********
* 
* BitmapInfoHeader定義了位圖的頭部信息
* 
****************************************/

[StructLayout(LayoutKind.Sequential)]
public struct BITMAPINFOHEADER
{
public int biSize;
public int biWidth;
public int biHeight;
public short biPlanes;
public short biBitCount;
public int biCompression;
public int biSizeImage;
public int biXPelsPerMeter;
public int biYPelsPerMeter;
public int biClrUsed;
public int biClrImportant;
}


/*********BitmapInfo 結構體*********
* 
* BitmapInfo 定義了位圖信息
* 
***********************************/

[StructLayout(LayoutKind.Sequential)]
public struct BITMAPINFO
{
public BITMAPINFOHEADER bmiHeader;
public int bmiColors;
}


/*********CAPTUREPARMS 結構體*********
* 
* CAPTUREPARMS 包含控制視頻流捕獲過程的參數,如捕獲幀頻、指定鍵盤或鼠標鍵以終止捕獲、捕獲時間限制等
* 
***********************************/

[StructLayout(LayoutKind.Sequential)]
public struct CAPTUREPARMS
{
public int dwRequestMicroSecPerFrame;             // 期望的楨播放率,以毫秒為單位,默認為66667,相當於15楨每秒。
public bool fMakeUserHitOKToCapture;             // Show "Hit OK to cap" dlg?開始捕獲標志位,如果值為真,則在開始捕獲前要產生一個詢問對話框,默認為假。
public uint wPercentDropForError;               //所允許的最大丟楨百分比,可以從0變化到100,默認值為10。
public bool fYield;                     /*另起線程標志位,如果為真,則程序重新啟動一個線程用於視頻流的捕獲,默認值是假。
但是如果你是為了真,你必須要在程序中處理一些潛在的操作,因為當視頻捕獲時,其他操作並沒有被屏蔽。*/
public int dwIndexSize;                       // 在AVI文件中所允許的最大數目的索引項(32K)
public uint wChunkGranularity;               // AVI文件的邏輯尺寸,以字節為單位。如果值是0,則說明該尺寸漸增 在 Win32程序中無用。(2K)
public bool fUsingDOSMemory;                // Use DOS buffers?
public uint wNumVideoRequested;            // 所被允許分配的最大視頻緩存
public bool fCaptureAudio;                // 音頻標志位,如果音頻流正在捕獲,則該值為真。
public uint wNumAudioRequested;          // 最大數量的音頻緩存,默認值為10。
public uint vKeyAbort;                  // 終止流捕獲的虛擬鍵盤碼,默認值為VK_ESCAPE
[MarshalAs(UnmanagedType.Bool)]
public bool fAbortLeftMouse;           // 終止鼠標左鍵標志位,如果該值為真,則在流捕獲過程中如果點擊鼠標左鍵則該捕獲終止,默認值為真。
public bool fAbortRightMouse;                 // Abort on right mouse?
public bool fLimitEnabled;                   // 捕獲操作時間限制,如果為真,則時間到了以后捕獲操作終止,默認為假
public uint wTimeLimit;                     // 具體終止時間,只有 fLimitEnabled是真時.該位才有效
public bool fMCIControl;                   // Use MCI video source?
public bool fStepMCIDevice;               // Step MCI device?MCI 設備標志。
public int dwMCIStartTime;               // Time to start in MS
public int dwMCIStopTime;               // Time to stop in MS
public bool fStepCaptureAt2x;          // Perform spatial averaging 2x
public int wStepCaptureAverageFrames; // 當基於平均采樣來創建楨時,楨的采樣時間,典型值是5
public int dwAudioBufferSize;        // 音頻緩存的尺寸,如果用默認值0,緩存尺寸是最大0.5秒,或10k字節。
public int fDisableWriteCache;      // Attempt to disable write cache
public int AVStreamMaster;         //音視頻同步標志。
}


/*********CAPDRIVERCAPS 結構體*********
* 
* CAPDRIVERCAPS 定義了捕獲驅動器的能力,如有無視頻疊加能力、有無控制視頻源、視頻格式的對話框等
* 
**************************************/

[StructLayout(LayoutKind.Sequential)]
public struct CAPDRIVERCAPS
{
[MarshalAs(UnmanagedType.U2)]
public UInt16 wDeviceIndex;         //捕獲驅動器的索引值,該值可以由0到9變化。
[MarshalAs(UnmanagedType.Bool)]
public bool fHasOverlay;            // 視頻疊加標志,如果設備支持視頻疊加這該位是真。
[MarshalAs(UnmanagedType.Bool)]
public bool fHasDlgVideoSource;     //視頻資源對話框標志位,如果設備支持視頻選擇、控制對話框,該值為真。
[MarshalAs(UnmanagedType.Bool)]
public bool fHasDlgVideoFormat;     //視頻格式對話框標志位,如果設備支持對視頻格式對話框的選擇,該位真。
[MarshalAs(UnmanagedType.Bool)]
public bool fHasDlgVideoDisplay;    //視頻展示對話框標志位,如果設備支持對視頻捕獲緩存區的重新播放,該位是真。
[MarshalAs(UnmanagedType.Bool)]
public bool fCaptureInitialized;    //捕獲安裝標志位,如果捕獲驅動器已經成功連接,該值為真。
//[MarshalAs(UnmanagedType.Bool)]
public bool fDriverSuppliesPalettes; //驅動器調色板標志位,如果驅動器能創建調色板,則該位是真。
[MarshalAs(UnmanagedType.I4)]
public int hVideoIn;
[MarshalAs(UnmanagedType.I4)]
public int hVideoOut;
[MarshalAs(UnmanagedType.I4)]
public int hVideoExtIn;
[MarshalAs(UnmanagedType.I4)]
public int hVideoExtOut;
}


/*********CAPSTATUS 結構體*********
* 
* CAPSTATUS 定義了捕獲窗口的當前狀態,如圖像的寬、高等
* 
**************************************/

[StructLayout(LayoutKind.Sequential)]
public struct CAPSTATUS
{
public int uiImageWidth;                         //圖像寬度
public int uiImageHeight;                       //圖像高度
public bool fLiveWindow;                       //活動窗口標記,如果窗口正以預覽的方式展示圖像,那么該值為真
public bool fOverlayWindow;                   //疊加窗口標志位,如果正在使用硬件疊加,則該位是真。
public bool fScale;                          //輸入所放標志位,如果窗口是正在縮放視頻到客戶區,那么該位是真。當使用硬件疊加時,改位無效。
public Point ptScroll;                      //被展示在窗口客戶區左上角的那個象素的x、y坐標偏移量。
public bool fUsingDefaultPalette;          //默認調色板標志位,如果捕獲窗口正在使用當前默認調色板,該值為真
public bool fAudioHardware;               // 音頻硬件標志位,如果系統已經安裝了音頻硬件,該值為真。
public bool fCapFileExists;              //捕獲文件標志位,如果一個捕獲文件已經被創建,該值為真
public int dwCurrentVideoFrame;         // 當前或最近流捕獲過程中,所處理的楨的數目。包括丟棄的楨。
public int dwCurrentVideoFramesDropped;//當前流捕獲過程中丟棄的楨的數目。
public int dwCurrentWaveSamples;      // # of wave samples cap'td
public int dwCurrentTimeElapsedMS;   // 從當前流捕獲開始計算,程序所用的時間,以毫秒為單位。
public IntPtr hPalCurrent;          // 當前剪切板的句柄。
public bool fCapturingNow;         // 捕獲標志位,當捕獲是正在進行時,改位是真
public int dwReturn;              // 錯誤返回值,當你的應用程序不支持錯誤回調函數時可以應用改位
public int wNumVideoAllocated;   // 被分配的視頻緩存的數目。
public int wNumAudioAllocated;  // 被分配的音頻緩存的數目。
}


#endregion


#region 基本函數

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

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);
}
#endregion
}
} 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM