/********************此文可以被转发,但请转发者保留作者的署名权
****李浩 ****msn:lihao_nx@hotmail.com **** ****email:lihaoyxj@gmail.com ****出处:lihaoyxj.cublog.cn ****from:http://blog.csdn.net/lihao_ningxia *****************/ vfw //head file // VideoCapture.h: interface for the VideoCapture class. #if !defined(AFX_VIDEOCAPTURE_H__5C825E61_611A_11D6_889B_000B2B0F84B6__INCLUDED_) #define AFX_VIDEOCAPTURE_H__5C825E61_611A_11D6_889B_000B2B0F84B6__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "CommClient.h" #include "Encoder/libr263.h" // If the parameters below are changed then change following // > cdata & cbuffer_size in VideoNetDlg.cpp // > rgbdata & buffersize in VideoNetDlg.cpp // > update CPARAMS structure before compression // > computation of local_wnd_x para in OnInitDialog() #define QCIF_WIDTH 176 #define QCIF_HEIGHT 144 //#define QCIF_WIDTH 320 //#define QCIF_HEIGHT 240 #define IMAGE_WIDTH QCIF_WIDTH #define IMAGE_HEIGHT QCIF_HEIGHT // 回调函数定义 typedef LRESULT (*CALLBACKFUNC)(HWND,LPVIDEOHDR); class VideoCapture { public: HWND m_capwnd; CStdioFile log; CAPDRIVERCAPS caps; CMutex protectframe; int avgaudiosize; BOOL isOver; CDialog *dlg; BITMAPINFOHEADER m_bmpheader; BITMAPINFO m_bmpinfo; VideoCapture(); virtual ~VideoCapture(); BOOL Initialize(); BOOL SetCapturePara(); void Destroy(); void GetDriverCaps(); void SetAudioFormat(); int AllocateMemory(PBITMAPINFO &bmpinfo); int getFormatSize(BITMAPINFO bmp); int getImageSize(BITMAPINFO bmp); // 启动视频捕获 BOOL StartCapture(HDC BackDC); BOOL StopCapture(); friend LRESULT CALLBACK OnCaptureVideo(HWND hWnd, LPVIDEOHDR lpheader) ; void* m_pParam; protected: void DrawLocalScreen(LPVIDEOHDR lphdr); void InitCompressor(); void CompressFrame(LPVIDEOHDR lphdr); CALLBACKFUNC m_OnCaptureVideo;
// 压缩参数 COMPVARS m_CV; // 视频回放句柄 HDC m_LocalScreenDC; HDRAWDIB m_hdib; // 数据通信接口 CCommClient* m_pCommClient; // Compression parameters.... CParam cparams; // Buffer for storing YUV data.... unsigned int yuv[ QCIF_WIDTH*QCIF_HEIGHT + (QCIF_WIDTH*QCIF_HEIGHT)/2 ]; public: void SetCommClient(CCommClient* pClient); // // 设置采集数据回调接口 // void SetOnCaptureVideoCallback(CALLBACKFUNC OnCaptureVideo, void* pParam); // // 回放远程视频 // void DrawRemoteScreen(char *data, UINT size, HDC hScreenDC); }; #endif // !defined(AFX_VIDEOCAPTURE_H__5C825E61_611A_11D6_889B_000B2B0F84B6__INCLUDED_) //cpp file // Project : VideoNet version 1.1. // // File description // Name : VideoCapture.cpp // Details : Captures the frames from webcam. // #include "Stdafx.h" #include "VideoCapture.h" #include <afxmt.h> #ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#pragma comment(lib,"vfw32")
#pragma comment(lib,"winmm")
// Global varialbes...
int count=0;
unsigned char cdata[10000];
int cbuffer_size=10000;
unsigned char rgbdata[80000];
int buffersize=80000;
// Callback function gets invoked during compression...
// It returns the compressed data byte by byte...
void OwnWriteFunction(int byte)
{
if(count<cbuffer_size)
cdata[count]=(unsigned char)byte;
count++;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
VideoCapture::VideoCapture()
{
m_capwnd = NULL;
isOver = FALSE;
m_OnCaptureVideo = NULL;
log.Open("videocapture.log",CFile::modeCreate | CFile::modeWrite);
}
VideoCapture::~VideoCapture()
{
}
BOOL VideoCapture::Initialize()
{
char devname[100],devversion[100];
char str[200];
int index=0;
// 初始化压缩编码器
InitCompressor();
// 创建摄像头句柄
m_capwnd = capCreateCaptureWindow("Capture",WS_POPUP,0,0,1,1,0,0);
if(m_capwnd==NULL)
{
log.WriteString("\n Unable to create capture window");
return FALSE;
}
// 连接摄像头设备
capSetUserData( m_capwnd, this );
// 显示视频设置对话框,进行配置视频的大小、颜色位数等。
capDlgVideoFormat( m_capwnd );
// 取得视频图像数据头,后面压缩时需要用到
capGetVideoFormat( m_capwnd, &m_bmpinfo, sizeof(BITMAPINFO) );
// 设置回调函数
capSetCallbackOnVideoStream( m_capwnd, OnCaptureVideo );
capGetDriverDescription(index,devname,100,devversion,100);
sprintf(str,"\n Driver name = %s version = %s ",devname,devversion);
log.WriteString(str);
// Connect to webcam driver
if( ! capDriverConnect(m_capwnd,index) )
{
// Device may be open already or it may not have been
// closed properly last time.
AfxMessageBox("Unable to open Video Capture Device");
log.WriteString("\n Unable to connect driver to the window");
m_capwnd=NULL;
return FALSE;
}
// Set the capture parameters
if(SetCapturePara()==FALSE)
{
log.WriteString("\n Setting capture parameters failed");
capDriverDisconnect(m_capwnd);
return FALSE;
}
return TRUE;
}
/**
* Start capturing frames from webcam
*
*/
BOOL VideoCapture::StartCapture(HDC BackDC)
{
m_LocalScreenDC = BackDC;
// 初始化视频回放对象
m_hdib = ::DrawDibOpen();
if( m_hdib != NULL )
{
::DrawDibBegin(
m_hdib,
m_LocalScreenDC,
-1, // don't stretch
-1, // don't stretch
&m_bmpinfo.bmiHeader,
IMAGE_WIDTH, // width of image
IMAGE_HEIGHT, // height of image
0
);
}
// 开始视频采集
if(capCaptureSequenceNoFile(m_capwnd)==FALSE)
{
log.WriteString("\n Failed to capture Sequence ..");
return FALSE;
}
return TRUE;
}
/**
* Stop the capturing process
*
*/
BOOL VideoCapture::StopCapture()
{
capCaptureStop(m_capwnd);
capCaptureAbort(m_capwnd);
Sleep(500);
return TRUE;
}
/**
* Stop the catpure process and disconnect the driver
*
*/
void VideoCapture::Destroy()
{
if(m_capwnd==NULL) return;
// Stop the capturing process
capCaptureAbort(m_capwnd);
// Disable the callback function..
capSetCallbackOnVideoStream(m_capwnd, NULL);
Sleep(300); // This delay is important...
// Finally disconnect the driver
capDriverDisconnect(m_capwnd);
}
/**
*
* Set various capture parameters...
*
*/
BOOL VideoCapture::SetCapturePara()
{
CAPTUREPARMS CapParms={0};
capCaptureGetSetup(m_capwnd,&CapParms,sizeof(CapParms));
CapParms.fAbortLeftMouse = FALSE;
CapParms.fAbortRightMouse = FALSE;
CapParms.fYield = TRUE;
CapParms.fCaptureAudio = FALSE;
CapParms.wPercentDropForError = 50;
CapParms.dwRequestMicroSecPerFrame = (DWORD) ( 1.0e6 / 15.0 ); if(capCaptureSetSetup(m_capwnd,&CapParms,sizeof(CapParms))==FALSE) { log.WriteString("\n Failed to set the capture parameters "); return FALSE; } // Set Video Format capGetVideoFormat(m_capwnd,&m_bmpinfo,sizeof(m_bmpinfo)); m_bmpinfo.bmiHeader.biWidth=IMAGE_WIDTH; m_bmpinfo.bmiHeader.biHeight=IMAGE_HEIGHT; BOOL ret=capSetVideoFormat(m_capwnd,&m_bmpinfo,sizeof(m_bmpinfo)); if(ret==TRUE) log.WriteString("\n Video parameters set properly"); return TRUE; } /** * Allocate Memory for DIB image buffer */ int VideoCapture::AllocateMemory(PBITMAPINFO &bmpinfo) { int size1,size2,size; BITMAPINFO tbmp; char str[200]; capGetVideoFormat(m_capwnd,&tbmp,sizeof(tbmp)); size1 = getFormatSize ( tbmp ); size2 = getImageSize ( tbmp ); size = size1 + size2; sprintf(str,"\n Formatsize = %d imagesize = %d , fun_size = %d ", size1,size2, capGetVideoFormatSize(m_capwnd)); log.WriteString(str); bmpinfo=(BITMAPINFO *) new BYTE[size]; if(bmpinfo==NULL) { AfxMessageBox("Unable to allocate memory"); return -1; } memset(bmpinfo,0,sizeof(*bmpinfo)); capGetVideoFormat(m_capwnd,bmpinfo,sizeof(*bmpinfo)); return size1; } /** * Calculates the Format Size for DIB image */ int VideoCapture::getFormatSize(BITMAPINFO bmp) { int size; size=(bmp.bmiHeader.biSize!=0)?bmp.bmiHeader.biSize :sizeof(BITMAPINFOHEADER); //return (size+ bmp.bmiHeader.biClrUsed *sizeof(RGBQUAD)); return size; //RGBQUAD is absent for 24 bit bmp image. } /* * Calculates the Size of Image */ int VideoCapture::getImageSize(BITMAPINFO bmp) { int size; BITMAPINFOHEADER head=bmp.bmiHeader; if( head.biSizeImage==0 ) { size=( head.biWidth * head.biHeight * head.biBitCount)/8; } else size = head.biSizeImage; return size; } // 设置采集数据回调接口 void VideoCapture::SetOnCaptureVideoCallback(CALLBACKFUNC OnCaptureVideo, void* pParam) { m_OnCaptureVideo = OnCaptureVideo; m_pParam = pParam; } /* Invoked when the video frame is captured by the driver*/ LRESULT CALLBACK OnCaptureVideo(HWND mwnd,LPVIDEOHDR lphdr) { VideoCapture *vidcap=(VideoCapture *)capGetUserData(mwnd); if( vidcap!=NULL ) { vidcap->DrawLocalScreen( lphdr ); vidcap->CompressFrame( lphdr ); // if ( vidcap->m_OnCaptureVideo != NULL ) // { // (*vidcap->m_OnCaptureVideo)( mwnd, lphdr ); // vidcap->DrawLocalScreen( lphdr ); // vidcap->CompressFrame( lphdr ); // } } return TRUE; } void VideoCapture::CompressFrame(LPVIDEOHDR lphdr) { // BOOL bKeyFrame; // DWORD OutActSize; // BYTE* Buf; // OutActSize = m_bmpinfo.bmiHeader.biSizeImage; // bKeyFrame = 0; // Buf = (BYTE*)ICSeqCompressFrame( &m_CV,0,lphdr->lpData,&bKeyFrame,(long*)&OutActSize); Bits bits; // Various count about compression //Convert the data from rgb format to YUV format ConvertRGB2YUV( IMAGE_WIDTH,IMAGE_HEIGHT, lphdr->lpData, yuv ); // Reset the counter count=0; // 压缩数据 cparams.format=CPARAM_QCIF; cparams.inter = CPARAM_INTRA; cparams.Q_intra = 8; cparams.data=yuv; // Data in YUV format... ::CompressFrame(&cparams, &bits); // 传送数据 m_pCommClient->SendPacket( (char*)cdata, count, PACKET_VIDEO ); } void VideoCapture::InitCompressor() { // memset( &m_CV,0,sizeof(COMPVARS) ); // m_CV.cbSize = sizeof( m_CV ); // ICCompressorChoose( m_capwnd, 0, NULL, NULL, &m_CV, "Choose a Compressor" ); // Initialize table for RGB to YUV conversion InitLookupTable(); // Initialize the compressor cparams.format = CPARAM_QCIF; InitH263Encoder(&cparams); // Set up the callback function WriteByteFunction = OwnWriteFunction; // Initialize decompressor InitH263Decoder(); return; } // 回放本地视频 void VideoCapture::DrawLocalScreen(LPVIDEOHDR lphdr) { ::DrawDibDraw( m_hdib, m_LocalScreenDC, 0, // dest : left pos 0, // dest : top pos -1, // don't zoom x -1, // don't zoom y &m_bmpinfo.bmiHeader, // bmp header info lphdr->lpData, // bmp data (lihao_ningxia) |