📄 capturedevicedshow.cpp
字号:
#include "StdAfx.h"
#include <iostream>
#include "CaptureDeviceDShow.h"
#include "DirectShowHelpers.h"
using namespace std;
CaptureDeviceDShow::CaptureDeviceDShow(void)
{
}
CaptureDeviceDShow::~CaptureDeviceDShow(void)
{
}
bool CaptureDeviceDShow::initCamera( const std::string &friendlyName, const std::string &devicePath, VideoManInputFormat *aFormat )
{
// Initialize DirectShow and query for needed interfaces
HRESULT hr = initDirectShow();
if ( FAILED( hr ) )
{
cerr << "Failed to initialize DirectShow!" << endl;
freeDirectShow();
return false;
}
identification.friendlyName = friendlyName;
identification.devicePath = devicePath;
hr = prepareMedia( identification.friendlyName, identification.devicePath, aFormat );
if (FAILED(hr))
{
cerr << "Failed preparing media! " << endl;
cerr << "friendlyName: " << identification.friendlyName << endl;
cerr << "devicePath: " << identification.devicePath << endl;
freeDirectShow();
return false;
}
hr = pMC->Run();
if ( FAILED( hr ) )
{
cerr << "Failed running camera!" << endl;
freeDirectShow();
return false;
}
frameCaptured = false;
if ( format.width<=0 || format.height<=0 )
{
freeDirectShow();
return false;
}
if (format.fps<=0)
format.fps=30;
if ( aFormat != NULL )
*aFormat = format;
return true;
}
HRESULT CaptureDeviceDShow::prepareMedia( std::string &friendlyName, std::string &devicePath, VideoManInputFormat *aFormat )
{
HRESULT hr = S_OK;
if ( FAILED ( hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (void**)&pSG) ) )
return hr;
if ( FAILED( pSG->QueryInterface(IID_ISampleGrabber,(void**)&sampleGrabber)) )
return(hr);
//std::string selectedName = name;
hr = findCaptureDevice( &videoSource, friendlyName, devicePath );
if ( SUCCEEDED( hr ) )
{
if ( FAILED(hr = pGB->AddFilter(videoSource, L"Video Source")))
return hr;
}
else
return E_FAIL;
CComPtr<IPin> outPinVideoSource = NULL;
if ( FAILED( hr = getPin( videoSource, PINDIR_OUTPUT, 1, outPinVideoSource ) ) )
return hr;
CComPtr <IAMStreamConfig> pStreamConfig = NULL;
hr = pCGB->FindInterface(&PIN_CATEGORY_CAPTURE,NULL,videoSource,IID_IAMStreamConfig,(void**)&pStreamConfig);
if (FAILED(hr))
return hr;
AM_MEDIA_TYPE mediaType;
//Find the first media type
/*if ( findOneMediaType( outPinVideoSource, &mediaType ) == S_OK )
{
//Set this media type to initilize pin propeties
pStreamConfig->SetFormat( &mediaType );
}*/
if ( aFormat == NULL || aFormat->showDlg )
{
//if( FAILED( hr = displayPinProperties(outPinVideoSource) ) )
// return(hr);
displayPinProperties(outPinVideoSource);
}
else
{
//AM_MEDIA_TYPE mediaType;
bool notFound = false;
if ( FAILED ( hr = findMediaType( outPinVideoSource, aFormat, &mediaType ) ) )
{
notFound = true;
}
else if ( FAILED( hr = pStreamConfig->SetFormat( &mediaType ) ) )
{
return hr;
}
if( notFound )
{
if ( FAILED( hr = displayPinProperties(outPinVideoSource) ) )
return(hr);
}
}
CComPtr <IBaseFilter> pVideoRenderer = NULL;
if ( FAILED( hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&(pVideoRenderer) ) ) )
return hr;
if ( FAILED ( hr = pGB->AddFilter(pVideoRenderer, L"NULL Video Renderer") ) )
return hr;
if ( FAILED( hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (void**)&pSG) ) )
return hr;
if ( FAILED( hr = pSG->QueryInterface(IID_ISampleGrabber,(void**)&sampleGrabber)) )
return(hr);
//Set sampleGrabber format
AM_MEDIA_TYPE _mt;
ZeroMemory(&_mt,sizeof(AM_MEDIA_TYPE));
_mt.majortype = MEDIATYPE_Video;
_mt.formattype = GUID_NULL;
if ( aFormat != NULL )
_mt.subtype = translatePIXEL_FORMAT( aFormat->getPixelFormatOut() );
else
_mt.subtype = translatePIXEL_FORMAT( RGB24 );
if ( FAILED( hr = sampleGrabber->SetMediaType(&_mt) ) )
return hr;
if ( FAILED( hr = pGB->AddFilter(pSG, L"Sample Grabber") ) )
return hr;
//Conect the source and the grabber
if ( FAILED( hr = autoConnectFilters(videoSource,1,pSG,1,pGB) ) )
return hr;
//Conect the grabber and the renderer
if ( FAILED( hr = autoConnectFilters(pSG,1,pVideoRenderer,1,pGB) ) )
return hr;
#ifdef _DEBUG
hr = addToRot( pGB, &dwRegisterROT);
#endif
// AM_MEDIA_TYPE mediaType;
CComPtr<IPin> rendererPin = NULL;
if(FAILED(hr = getPin(pVideoRenderer,PINDIR_INPUT,1,rendererPin))) return(hr);
rendererPin->ConnectionMediaType(&mediaType);
VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) mediaType.pbFormat;
FILTER_INFO filter_info;
videoSource->QueryFilterInfo(&filter_info);
if( filter_info.pGraph != NULL )
filter_info.pGraph->Release();
GUID subtype = mediaType.subtype;
format.width = pvi->bmiHeader.biWidth;
format.height = pvi->bmiHeader.biHeight;
format.fps = referenceTime2fps( pvi->AvgTimePerFrame );
format.setPixelFormat( UNKNOWN, translateMEDIASUBTYPE( mediaType.subtype ) );
FreeMediaType(mediaType);
hr = EnableMemoryBuffer();
if ( aFormat != NULL )
dropFrames = aFormat->dropFrames;
//pMS->SetRate(2);
return hr;
}
inline char *CaptureDeviceDShow::getFrame( bool wait)
{
/* m_CSec.Lock();
if ( mb.size() > 0 )
{
mb.front().blocked = true;
m_CSec.Unlock();
mb.front().media_sample->GetPointer((BYTE**)&pixelBuffer);
frameCaptured = true;
return pixelBuffer;
}
m_CSec.Unlock();
return NULL;*/
if ( mediaSample != NULL )
{
mediaSample->GetPointer((BYTE**)&pixelBuffer);
frameCaptured = true;
return pixelBuffer;
}
return NULL;
}
void CaptureDeviceDShow::releaseFrame()
{
/*if (frameCaptured)
{
pixelBuffer = NULL;
mb.front().media_sample->Release();
mb.front().blocked = false;
mb.pop_front();
frameCaptured = false;
}*/
if ( mediaSample != NULL )
{
pixelBuffer = NULL;
mediaSample->Release();
mediaSample = NULL;
frameCaptured = false;
if ( !dropFrames )
play();
}
}
void CaptureDeviceDShow::play()
{
if ( pMC != NULL )
pMC->Run();
}
void CaptureDeviceDShow::pause()
{
if ( pMC != NULL )
pMC->Pause();
}
void CaptureDeviceDShow::stop()
{
stopMedia();
}
void CaptureDeviceDShow::showPropertyPage()
{
DWORD dwThreadID;
HANDLE hFPropThread = CreateThread(NULL,0,showFilterPropertiesThread,(LPVOID)videoSource,0,&dwThreadID);
}
void CaptureDeviceDShow::getAvailableDevices( std::vector<inputIdentification> &deviceList )
{
//Create a device enumerator
ICreateDevEnum *pSysDevEnum = NULL;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum,(void **)&pSysDevEnum);
if (FAILED(hr))
return;
// Get an enumerator class for the video inpout category
IEnumMoniker *pEnumCat = NULL;
hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0);
if (hr == S_OK)
{
IMoniker *pMoniker = NULL;
ULONG cFetched;
//list=new CStringArray();
while ((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);
if (SUCCEEDED(hr))
{
std::string friendlyName;
int ret = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)varName.pcVal, -1, NULL, 0, NULL, NULL );
std::vector<char> friendlyNameAux( ret + 1 );
WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)varName.pcVal, -1, &friendlyNameAux[0], ret, NULL, NULL );
friendlyName = &friendlyNameAux[0];
hr = pPropBag->Read(L"DevicePath", &varName, 0);
std::string devicePath;
if (SUCCEEDED(hr))
{
int ret = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)varName.pcVal, -1, &friendlyName[0], 0, NULL, NULL );
std::vector<char> deviceAux( ret + 1 );
WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)varName.pcVal, -1, &deviceAux[0], ret, NULL, NULL );
devicePath = &deviceAux[0];
/*std::string aux;
size_t ind = devicePath.find( '?' );
aux.resize( devicePath.length() - ind - 2 );
devicePath.copy( &aux[0], devicePath.length() - ind - 2, ind + 2 );
ind = aux.find( '#' );
std::string type;
type.resize(10);
aux.copy( &type[0], ind, 0 );
type.resize(ind);
std::string pathAux;
pathAux.resize( devicePath.length() );
ind = devicePath.rfind( '#' );
devicePath.resize( ind );
ind = devicePath.rfind( '#' ); //second #
devicePath.erase( devicePath.begin(), devicePath.begin() + ind + 1 );
*/
}
inputIdentification device;
device.devicePath = devicePath;
device.friendlyName = friendlyName;
device.identifier = "DSHOW_CAPTURE_DEVICE";
deviceList.push_back( device );
}
VariantClear(&varName);
SAFE_RELEASE(pPropBag);
}
SAFE_RELEASE(pMoniker);
}
}
SAFE_RELEASE(pEnumCat);
SAFE_RELEASE(pSysDevEnum);
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -