2024-06-23 17:36:53 +08:00

269 lines
5.3 KiB
C++

// CaptureVideo.h: interface for the CCaptureVideo class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_CAPTUREVIDEO_H__D9B9F1BB_9049_48A7_B185_0CB960BA76E3__INCLUDED_)
#define AFX_CAPTUREVIDEO_H__D9B9F1BB_9049_48A7_B185_0CB960BA76E3__INCLUDED_
#include <list>
#include <DShow.h>
#include "atlbase.h"
#include <qedit.h>
#include "XvidEnc.h"
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// 0 拷贝 1 编码 2 发送
enum
{
CMD_CAN_COPY,
CMD_CAN_SEND
};
#define SAFE_RELEASE( x ) \
if ( NULL != x ) \
{ \
x->Release( ); \
x = NULL; \
}
class SmartString
{
public:
SmartString():str(NULL) {}
SmartString(char* pStr):str(NULL)
{
if (pStr)
{
int size = int(strlen(pStr));
str = new char[size+1];
strcpy(str, pStr);
}
}
SmartString(SmartString& sStr)
{
SetString(sStr.GetBuffer());
}
~SmartString()
{
if (str)
delete[] str;
}
SmartString& operator =(char* pStr)
{
SetString(pStr);
return *this;
}
SmartString& operator =(SmartString& sStr)
{
SetString(sStr.GetBuffer());
return *this;
}
char* GetBuffer() {return str;}
protected:
void SetString(char *pStr)
{
if (str)
delete[] str;
if (!pStr)
{
str = NULL;
}
else
{
int size = int(strlen(pStr));
str = new char[size + 1];
strcpy(str, pStr);
}
}
char* str;
};
class ResolutionInfo
{
public:
ResolutionInfo():next(NULL){}
~ResolutionInfo()
{
if (next)
delete next;
}
SmartString Resolution; //分辨率
ResolutionInfo* next;
};
class DeviceInfo
{
public:
DeviceInfo():next(NULL), deviceId(-1),resInfo(NULL) {}
~DeviceInfo()
{
if (resInfo)
delete resInfo;
if (next)
delete next;
}
SmartString friendlyName; //设备名
int deviceId; //视频设备驱动个数
ResolutionInfo* resInfo;
DeviceInfo* next;
};
class CSampleGrabberCB : public ISampleGrabberCB
{
public:
long lWidth ;
long lHeight ;
BITMAPINFO *lpbmi; //位图文件头
BYTE* m_lpFullBits; //图像数据
DWORD dwSize; //数据大小
BOOL bStact; //发送状态 0可以复制 1可以发送
public:
CSampleGrabberCB()
{
lWidth = 0 ;
lHeight = 0 ;
lpbmi = NULL;
m_lpFullBits = NULL;
bStact = CMD_CAN_COPY;
dwSize = 0;
}
~CSampleGrabberCB()
{
if (m_lpFullBits)
{
delete[] m_lpFullBits;
}
if (lpbmi)
{
delete[] lpbmi;
}
}
LPBITMAPINFO ConstructBI(int biBitCount, int biWidth, int biHeight)
{
int color_num = biBitCount <= 8 ? 1 << biBitCount : 0;
int nBISize = sizeof(BITMAPINFOHEADER) + (color_num * sizeof(RGBQUAD));
lpbmi = (BITMAPINFO *) new BYTE[nBISize];
BITMAPINFOHEADER *lpbmih = &(lpbmi->bmiHeader);
lpbmih->biSize = sizeof(BITMAPINFOHEADER);
lpbmih->biWidth = biWidth;
lpbmih->biHeight = biHeight;
lpbmih->biPlanes = 1;
lpbmih->biBitCount = biBitCount;
lpbmih->biCompression = BI_RGB;
lpbmih->biXPelsPerMeter = 0;
lpbmih->biYPelsPerMeter = 0;
lpbmih->biClrUsed = 0;
lpbmih->biClrImportant = 0;
lpbmih->biSizeImage = (((lpbmih->biWidth * lpbmih->biBitCount + 31) & ~31) >> 3) * lpbmih->biHeight;
/////////////////////初始化成员数据///////////////////////////////////////////////
dwSize=lpbmih->biSizeImage;
m_lpFullBits=new BYTE[dwSize+10];
ZeroMemory(m_lpFullBits,dwSize+10);
if (biBitCount >= 16)
return lpbmi;
return lpbmi;
}
LPBITMAPINFO GetBmpInfo()
{
lpbmi=ConstructBI(24, lWidth, lHeight);
return lpbmi;
}
BYTE* GetNextScreen(DWORD &nSize) //得到下一帧数据
{
nSize=dwSize;
return (BYTE*)m_lpFullBits; //还是很简单 就是返回一个缓冲区的指针,可这个指针是怎么获取到视频数据的呢?
}
STDMETHODIMP_(ULONG) AddRef() { return 2; }
STDMETHODIMP_(ULONG) Release() { return 1; }
STDMETHODIMP QueryInterface(REFIID riid, void ** ppv)
{
if( riid == IID_ISampleGrabberCB || riid == IID_IUnknown )
{
*ppv = (void *) static_cast<ISampleGrabberCB*> ( this );
return NOERROR;
}
return E_NOINTERFACE;
}
STDMETHODIMP SampleCB( double SampleTime, IMediaSample * pSample )
{
return 0;
}
//回调函数 在这里得到 bmp 的数据
STDMETHODIMP BufferCB( double dblSampleTime, BYTE * pBuffer, long lBufferSize )
{
if (!pBuffer)
return E_POINTER;
if (bStact == CMD_CAN_COPY) //未初始化 发送的同差异的一样
{
ZeroMemory(m_lpFullBits,dwSize+10);
memcpy(m_lpFullBits,pBuffer,lBufferSize); //从这里得到视频的数据,他为什么能得到视频的数据呢??
InterlockedExchange((LPLONG)&bStact,CMD_CAN_SEND); //原子自增可以发送
}
return 0;
}
};
class CCaptureVideo
{
friend class CSampleGrabberCB;
public:
CCaptureVideo();
virtual ~CCaptureVideo();
CSampleGrabberCB mCB;
int EnumDevices(DeviceInfo *head);
LPBITMAPINFO GetBmpInfo();
HRESULT Start(int iDeviceID,HWND hWnd = NULL, int width = 320, int height = 240);
HRESULT Stop();
HRESULT InitCaptureGraphBuilder();
bool BindFilter(int deviceId, IBaseFilter **pFilter);
void FreeMediaType(AM_MEDIA_TYPE& mt);
LPBYTE GetDIB(DWORD& nSize);
void SendEnd(); //发送结束
ICaptureGraphBuilder2* m_pCapture;
IGraphBuilder * m_pGB;
IMediaControl* m_pMC;
IBaseFilter* m_pBF;
IBaseFilter* m_pNullRenderer;
ISampleGrabber* m_pGrabber;
int m_nWidth ; // 分辨率 宽 X 高
int m_nHeight;
CXvidEnc *m_pEnc;
BOOL m_bIsStarted;
};
#endif // !defined(AFX_CAPTUREVIDEO_H__D9B9F1BB_9049_48A7_B185_0CB960BA76E3__INCLUDED_)