📄 dxconstruction.cpp
字号:
// DXConstruction.cpp: implementation of the CDXConstruction class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "tryshot.h"
#include "tryshotDlg.h"
#include "DXConstruction.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CDXConstruction::CDXConstruction()
{
mBasicVideo=NULL;//
mCGBer2=NULL;
mEvent=NULL;//
mGraph=NULL;//
mMediaControl=NULL;//
mSeeking=NULL;//
mVideoWindow=NULL;//
mSampleGrabber=NULL;//
mObjectTableEntry=0;
lWidth=640;
lHeight=480;
}
CDXConstruction::~CDXConstruction()
{
Release();
}
void CDXConstruction::Release()
{
if (mBasicVideo)
{
mBasicVideo->Release();
mBasicVideo=NULL;
}
if (mSampleGrabber)
{
mSampleGrabber->Release();
mSampleGrabber=NULL;
}
if (mEvent)
{
mEvent->Release();
mEvent=NULL;
}
if (mMediaControl)
{
mMediaControl->Release();
mMediaControl=NULL;
}
if (mSeeking)
{
mSeeking->Release();
mSeeking=NULL;
}
if (mVideoWindow)
{
mVideoWindow->put_Visible(OAFALSE);
mVideoWindow->put_MessageDrain((OAHWND)NULL);
mVideoWindow->put_Owner(OAHWND(0));
mVideoWindow->Release();
mVideoWindow=NULL;
}
RemoveFromObjectTable();
if (mCGBer2)
{
mCGBer2->Release();
mCGBer2=NULL;
}
if (mGraph)
{
mGraph->Release();
mGraph=NULL;
}
}
void CDXConstruction::AddToObjectTable()
{
IMoniker * pMoniker = 0;
IRunningObjectTable * objectTable = 0;
if (SUCCEEDED(GetRunningObjectTable(0, &objectTable)))
{
WCHAR wsz[256];
wsprintfW(wsz, L"FilterGraph %08p pid %08x", (DWORD_PTR)mGraph, GetCurrentProcessId());
HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker);
if (SUCCEEDED(hr))
{
hr = objectTable->Register(0, mGraph, pMoniker, &mObjectTableEntry);
pMoniker->Release();
}
objectTable->Release();
}
}
void CDXConstruction::RemoveFromObjectTable()
{
IRunningObjectTable * objectTable = 0;
if (SUCCEEDED(GetRunningObjectTable(0, &objectTable)))
{
objectTable->Revoke(mObjectTableEntry);
objectTable->Release();
mObjectTableEntry = 0;
}
}
BOOL CDXConstruction::Create()
{
if (!mGraph)
{
if (SUCCEEDED(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&mGraph)))
{
AddToObjectTable();
return QueryInterfaces();
}
mGraph = 0;
}
return FALSE;
}
BOOL CDXConstruction::QueryInterfaces()
{
if (mGraph)
{
HRESULT hr = NOERROR;
hr |= mGraph->QueryInterface(IID_IMediaControl, (void **)&mMediaControl);
//--------控制:run,pausing,stop......
hr |= mGraph->QueryInterface(IID_IMediaEventEx, (void **)&mEvent);
//-------- :事件提醒
hr |= mGraph->QueryInterface(IID_IBasicVideo, (void **)&mBasicVideo);
// :用以设置视频属性
// hr |= mGraph->QueryInterface(IID_IBasicAudio, (void **)&mBasicAudio);
hr |= mGraph->QueryInterface(IID_IVideoWindow, (void **)&mVideoWindow);
// :设置视频窗口的宿主,位置,及其他属性
//video render filter和filter graph manager都有这个接口,应用程序应该用filter graph的这个
//当使用多个video render时,要使用render filter上的这个接口
//使用video window作为子窗口的mfc程序必须定义一个空的WM_ERASEBKGND消息
//否则子窗口绘制会发生错误
//可以用CBaseVideoWindow类实现这个接口
hr |= mGraph->QueryInterface(IID_IMediaSeeking, (void **)&mSeeking);
//用以在视频流中定位
if (mSeeking)
{
mSeeking->SetTimeFormat(&TIME_FORMAT_MEDIA_TIME);
}
return SUCCEEDED(hr);
}
return FALSE;
}
BOOL CDXConstruction::RenderCaptureLink(ISampleGrabberCB *pCB)
{
BOOL brlt=FALSE;
IBaseFilter *pCap=NULL;
if (GetCaptureDevice(&pCap))//采集设备
{
IBaseFilter *psgrdr=NULL;
if (GetSGRdr(&psgrdr,pCB))//SampleRender
{
IBaseFilter *pNullRdr=NULL;
if (GetNRdr(&pNullRdr))//Video_Render
{
if (Build_Capture_Graph(pCap,psgrdr,pNullRdr))//用CaptureGraphBuilder2构建捕捉链路
{
brlt=TRUE;
}
pNullRdr->Release();
}
psgrdr->Release();
}
pCap->Release();
}
return TRUE;
}
BOOL CDXConstruction::SetDisplayWindow(HWND inWindow)
{
if (mVideoWindow)
{
// long lVisible;
// mVideoWindow->get_Visible(&lVisible);
// Hide the video window first
mVideoWindow->put_Visible(OAFALSE);
//----利用IVideoWindow接口的方法:
//----设置窗口的可见性-----OAFALSE表示窗口隐藏
HRESULT TPHR=mVideoWindow->put_Owner((OAHWND)inWindow);
//--------------为video window设定视频在哪个窗口播放
RECT windowRect;
::GetClientRect(inWindow, &windowRect);
//取得窗口大小
mVideoWindow->put_Left(0);
mVideoWindow->put_Top(0);
mVideoWindow->put_Width(windowRect.right - windowRect.left);
mVideoWindow->put_Height(windowRect.bottom - windowRect.top);
mVideoWindow->put_WindowStyle(WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS);
mVideoWindow->put_MessageDrain((OAHWND) inWindow);
//指定video window向哪个窗口发送消息
// Restore the video window
if (inWindow != NULL)
{
// mVideoWindow->put_Visible(lVisible);
mVideoWindow->put_Visible(OATRUE);
}
else
{
mVideoWindow->put_Visible(OAFALSE);
}
return TRUE;
}
return FALSE;
}
BOOL CDXConstruction::SetNotifyWindow(HWND inWindow)
{
if (mEvent)
{
mEvent->SetNotifyWindow((OAHWND)inWindow, WM_GRAPHNOTIFY, 0);
return TRUE;
}
return FALSE;
}
BOOL CDXConstruction::Pause()
{
if (mGraph && mMediaControl)
{
if (!IsPaused())
{
if (SUCCEEDED(mMediaControl->Pause()))
{
return TRUE;
}
}
else
{
return TRUE;
}
}
return FALSE;
}
BOOL CDXConstruction::IsPaused()
{
if (mGraph && mMediaControl)
{
OAFilterState state = State_Stopped;
if (SUCCEEDED(mMediaControl->GetState(10, &state)))
{
return state == State_Paused;
}
}
return FALSE;
}
BOOL CDXConstruction::Run()
{
if (mGraph && mMediaControl)
{
if (!IsRunning())
{
if (SUCCEEDED(mMediaControl->Run()))
{
return TRUE;
}
}
else
{
return TRUE;
}
}
return FALSE;
}
BOOL CDXConstruction::IsRunning()
{
if (mGraph && mMediaControl)
{
OAFilterState state = State_Stopped;
if (SUCCEEDED(mMediaControl->GetState(10, &state)))
{
return state == State_Running;
}
}
return FALSE;
}
BOOL CDXConstruction::Stop()
{
if (mGraph && mMediaControl)
{
if (!IsStopped())
{
if (SUCCEEDED(mMediaControl->Stop()))
{
return TRUE;
}
}
else
{
return TRUE;
}
}
return FALSE;
}
BOOL CDXConstruction::IsStopped()
{
if (mGraph && mMediaControl)
{
OAFilterState state = State_Stopped;
if (SUCCEEDED(mMediaControl->GetState(10, &state)))
{
return state == State_Stopped;
}
}
return FALSE;
}
BOOL CDXConstruction::GetCaptureDevice(IBaseFilter **ppCap)
{
BOOL brlt=FALSE;
// Create the System Device Enumerator.
HRESULT hr;
ICreateDevEnum *pSysDevEnum = NULL;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void **)&pSysDevEnum);
if (FAILED(hr))
{
return brlt;
}
// Obtain a class enumerator for the video compressor category.
IEnumMoniker *pEnumCat = NULL;
hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
&pEnumCat, 0);
if (hr == S_OK)
{
// Enumerate the monikers.
IMoniker *pMoniker = NULL;
ULONG cFetched;
pEnumCat->Reset();
//////////////////////////////////////////////////////////////////////////
// pEnumCat->Skip(1);
//////////////////////////////////////////////////////////////////////////
if (pEnumCat->Next(1,&pMoniker,&cFetched)==S_OK)
{
IPropertyBag *pPropBag;
hr=pMoniker->BindToStorage(0,0,IID_IPropertyBag,(void**)&pPropBag);
if (SUCCEEDED(hr))
{
VARIANT varName;
VariantInit(&varName);
hr=pPropBag->Read(L"FriendlyName",&varName,0);
// char friendlyname [256];
// friendlyname[0]=0;
// WideCharToMultiByte(CP_ACP,0,varName.bstrVal,-1,friendlyname,256,NULL,NULL);
// CString fnm=friendlyname;
// if (SUCCEEDED(hr))
// {
// AfxMessageBox(fnm);
// }
if (ppCap)
{
hr=pMoniker->BindToObject(NULL,NULL,IID_IBaseFilter,(void**)ppCap);
if (SUCCEEDED(hr))
{
if (mGraph && *ppCap)
{
if (SUCCEEDED(mGraph->AddFilter(*ppCap, varName.bstrVal)))
{
brlt=TRUE;
}
}
}
}
VariantClear(&varName);
pPropBag->Release();
}
}
pMoniker->Release();
}
pEnumCat->Release();
pSysDevEnum->Release();
return brlt;
}
BOOL CDXConstruction::GetSGRdr(IBaseFilter **psgr,ISampleGrabberCB *pCB)
{
BOOL brlt=FALSE;
HRESULT hr;
if (SUCCEEDED(CoCreateInstance(CLSID_SampleGrabber,
NULL,
CLSCTX_INPROC_SERVER,
IID_IBaseFilter,
(LPVOID *)psgr)))
{
hr=(*psgr)->QueryInterface(IID_ISampleGrabber,(void **)&mSampleGrabber);
if (SUCCEEDED(hr))
{
//--------将Sample Grabber的格式订好-----------
AM_MEDIA_TYPE amt;
ZeroMemory(&amt,sizeof(AM_MEDIA_TYPE));
amt.majortype=MEDIATYPE_Video;
amt.subtype=MEDIASUBTYPE_RGB24;
amt.pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(VIDEOINFOHEADER));
if (amt.pbFormat!=NULL)
{
VIDEOINFOHEADER *pVH=(VIDEOINFOHEADER*)amt.pbFormat;
ZeroMemory(pVH,sizeof(VIDEOINFOHEADER));
pVH->bmiHeader.biBitCount=24;//每像素比特数
pVH->bmiHeader.biWidth=lWidth;
pVH->bmiHeader.biHeight=lHeight;
pVH->bmiHeader.biPlanes=1;//必须是1
pVH->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
pVH->bmiHeader.biSizeImage=DIBSIZE(pVH->bmiHeader);
amt.formattype=FORMAT_VideoInfo;
amt.cbFormat=sizeof(VIDEOINFOHEADER);
amt.bFixedSizeSamples=TRUE;
amt.lSampleSize=DIBSIZE(pVH->bmiHeader);
hr=mSampleGrabber->SetMediaType(&amt);
if (SUCCEEDED(hr))
{
if (mGraph && *psgr)
{
if (SUCCEEDED(mGraph->AddFilter(*psgr,L"SampleGrabber")))
{
mSampleGrabber->SetBufferSamples(TRUE);
mSampleGrabber->SetOneShot(FALSE);
mSampleGrabber->SetCallback(pCB,1);
brlt=TRUE;
}
}
}
}
CoTaskMemFree(amt.pbFormat);
}
}
return brlt;
}
BOOL CDXConstruction::GetNRdr(IBaseFilter **pNdr)
{
BOOL brlt=FALSE;
if (SUCCEEDED(CoCreateInstance(CLSID_VideoRenderer,
NULL,
CLSCTX_INPROC_SERVER,
IID_IBaseFilter,
(LPVOID *)pNdr)))
{
if (mGraph && *pNdr)
{
if (SUCCEEDED(mGraph->AddFilter(*pNdr,L"Null_Render")))
{
brlt=TRUE;
}
}
}
return brlt;
}
BOOL CDXConstruction::Build_Capture_Graph(IBaseFilter *pS,
IBaseFilter *psample,
IBaseFilter *pR)
{
BOOL brlt=FALSE;
if (SUCCEEDED(CoCreateInstance((REFCLSID)CLSID_CaptureGraphBuilder2,
NULL,
CLSCTX_INPROC_SERVER,
(REFIID)IID_ICaptureGraphBuilder2,
(void**)&mCGBer2)))
{
if (mGraph && mCGBer2)
{
if (SUCCEEDED(mCGBer2->SetFiltergraph(mGraph)))
{
//尝试用预览和捕捉模式连接链路
if (SUCCEEDED(mCGBer2->RenderStream(&PIN_CATEGORY_PREVIEW,
&MEDIATYPE_Video,
pS,
psample,
pR)))
{
IAMStreamConfig *pConfig=NULL;
if (SUCCEEDED(mCGBer2->FindInterface(&PIN_CATEGORY_CAPTURE,
&MEDIATYPE_Video,
pS,
IID_IAMStreamConfig,
(void**)&pConfig)))
{
//-------重新设定图像的尺寸-----
AM_MEDIA_TYPE *pamt={0};
if (SUCCEEDED(pConfig->GetFormat(&pamt)))
{
if((pamt->majortype==MEDIATYPE_Video) &&
(pamt->subtype==MEDIASUBTYPE_RGB24) &&
(pamt->formattype==FORMAT_VideoInfo) &&
(pamt->cbFormat>=sizeof(VIDEOINFOHEADER))&&
(pamt->pbFormat!=NULL))
{
VIDEOINFOHEADER *pVih=(VIDEOINFOHEADER*)pamt->pbFormat;
pVih->bmiHeader.biWidth=lWidth;
pVih->bmiHeader.biHeight=lHeight;
if (SUCCEEDED(pConfig->SetFormat(pamt)))
{
brlt=TRUE;
}
}
DeleteMediaType(pamt);
}
}
SAFE_RELEASE(pConfig);
}
}
}
}
return brlt;
}
BOOL CDXConstruction::Get_Photo(CString str,BYTE * pD, HWND hwnd_nmb)
{
BOOL brlt=FALSE;
long lbuffersize=0;
mSampleGrabber->GetCurrentBuffer(&lbuffersize,NULL);
char *pBf=new char[lbuffersize];
mSampleGrabber->GetCurrentBuffer(&lbuffersize,(long*)pBf);
HANDLE hr=(CreateFile( (LPCSTR)str,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
NULL,
NULL));
if (SUCCEEDED(hr))
{
BITMAPFILEHEADER bfh;
memset(&bfh,0,sizeof(BITMAPFILEHEADER));
bfh.bfType='MB';
bfh.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+lbuffersize;
bfh.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
DWORD dwWritten = 0;
WriteFile(hr,//文件句柄
&bfh,//数据块
sizeof( bfh ),//尺寸(Byte)
&dwWritten,//记录写了多少个Byte
NULL );//将FileHeader准备好
BITMAPINFOHEADER bih;
memset(&bih,0,sizeof(BITMAPINFOHEADER));
bih.biSize=sizeof(bih);
bih.biWidth=lWidth;
bih.biHeight=lHeight;
bih.biPlanes=1;
bih.biBitCount=24;
dwWritten=0;
WriteFile(hr,
&bih,
sizeof(bih),
&dwWritten,
NULL);
dwWritten=0;
WriteFile(hr,
pBf,
lbuffersize,
&dwWritten,
NULL);
CloseHandle(hr);
// Display the bitmap bits on the dialog's preview window
memcpy(pD,pBf,lbuffersize);
DisplayCapturedBits(pD, &bih, hwnd_nmb);
}
delete []pBf;
return brlt;
}
BOOL CDXConstruction::DisplayCapturedBits(BYTE *pBuffer, BITMAPINFOHEADER *pbih, HWND hwnd_nmb)
{
if (!hwnd_nmb || !pBuffer)
return FALSE;
RECT rc;
::GetWindowRect( hwnd_nmb, &rc );
long lStillWidth = rc.right - rc.left;
long lStillHeight = rc.bottom - rc.top;
HDC hdcStill = GetDC( hwnd_nmb );
PAINTSTRUCT ps;
BeginPaint(hwnd_nmb, &ps);
SetStretchBltMode(hdcStill, COLORONCOLOR);
StretchDIBits( hdcStill, 0, 0,
lStillWidth, lStillHeight,
0, 0, lWidth, lHeight,
pBuffer,
(BITMAPINFO*) pbih,
DIB_RGB_COLORS,
SRCCOPY );
EndPaint(hwnd_nmb, &ps);
ReleaseDC( hwnd_nmb, hdcStill );
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -