www.gusucode.com > 一个可以在局域网进行视频聊天的源代码 > 一个可以在局域网进行视频聊天的源代码/VoIP/VideoCapture.cpp
//////////////////////////////////////////////////////////////////////////// // // // Project : VideoNet version 1.1. // Description : Peer to Peer Video Conferencing over the LAN. // Author : Nagareshwar Y Talekar ( nsry2002@yahoo.co.in) // Date : 15-6-2004. // // // 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 0, // src :left 0, // src :top IMAGE_WIDTH, // src : width IMAGE_HEIGHT, // src : height DDF_SAME_DRAW // use prev params.... ); } ////////////////////////////////////////////////////////////////////////// // // 设置通信接口 // void VideoCapture::SetCommClient(CCommClient *pClient) { m_pCommClient = pClient; } ////////////////////////////////////////////////////////////////////////// // // 回放远程视频 // void VideoCapture::DrawRemoteScreen(char *data, UINT size, HDC hScreenDC) { int iErrorCode; int iDataSize; u_char* upData; iDataSize = size; upData = (u_char*)data; iErrorCode = DecompressFrame( upData, iDataSize, rgbdata, buffersize ); if ( iErrorCode == 0 ) return; ::DrawDibDraw( m_hdib, hScreenDC, 0, // dest : left pos 0, // dest : top pos -1, // don't zoom x -1, // don't zoom y &m_bmpinfo.bmiHeader, // bmp header info rgbdata, // bmp data 0, // src :left 0, // src :top IMAGE_WIDTH, // src : width IMAGE_HEIGHT, // src : height DDF_SAME_DRAW // use prev params.... ); }