网络上一大堆的视频捕捉代码,比如:
代码
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
0
,
0
,
160
,
120
,
//
window position and dimensions
(HWND) hwndParent,
(
int
) nID
/*
child ID *
2. 链接捕捉设备
代码
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. 获取捕捉设备的能力
代码
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,
0
,
0
, 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#封装实际上还有很多方法没有实现。