Dshow获取设备信息

dshow入门开发可以参照网上流行的dshow开发笔记,这里写了一个获取设备信息的类,抛个砖,主要功能是获取所以能用枚举器得到的设备信息保存,并获取每个设备支持的输出媒体类型


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

#define __LOGOUT(s) 

#define ThrowStdExp(s) { \
	char expMsg[4096];\
	sprintf(expMsg,"%s:%s %d",s,__FILE__,__LINE__);\
	throw std::exception(expMsg); \
}

#define DEVICE_CAP_VIDEO_TYPE 0 
#define DEVICE_CAP_AUDIO_TYPE 1

struct MediaInfoContext
{
	int iPixFormat;
	int iWidth;
	int iHeight;


};

void printAmInfo(AM_MEDIA_TYPE* p,bool bVideo = true);


class CDShowCapInfo
{
public:
	CDShowCapInfo(void)
	{

	}
	~CDShowCapInfo(void)
	{
		realseOptions();
	}
	 void setType(int iType)
	{
		m_iType = iType;
	}

	int getType()
	{
		return m_iType;
	}

	void setFriendlyName(wstring wszName)
	{
		m_wszFriendlyName = wszName;
	}
	wstring getFriendlyName()
	{
		return m_wszFriendlyName;
	}

	int getMediaOptionCount()
	{
		return m_vecMediaInfo.size();
	}

	void putMediaOption(AM_MEDIA_TYPE* mediaInfo)
	{
		m_vecMediaInfo.push_back(mediaInfo);
	}

	//获取output pin 支持的媒体类型
	AM_MEDIA_TYPE* getMediaOption(int iIndex)
	{
		if (iIndex < m_vecMediaInfo.size())
		{
			AM_MEDIA_TYPE* info = m_vecMediaInfo.at(iIndex);
			return info;
		}
		else
		{
			return NULL;
		}
	}

	 void realseOptions()
	 {
		 for (int i=0;i m_vecMediaInfo;
};

class CDshowCapInfoMgr
{
public:
	CDshowCapInfoMgr()
	{
	
	}
	~CDshowCapInfoMgr()
	{
		releaseInfos();
	}

	CDShowCapInfo* getVideoInfo(int iIndex)
	{
		if(iIndex < m_vecVideoCap.size())
		{
			return m_vecVideoCap.at(iIndex);
		}
		
		return NULL;
	}

	CDShowCapInfo* getAudioInfo(int iIndex)
	{
		if(iIndex < m_vecAudioCap.size())
		{
			return m_vecAudioCap.at(iIndex);
		}

		return NULL;
	}
	bool enumAllCapInfo();
	bool refreshDevicesCapInfo()
	{

	}
	void releaseInfos()
	{
		int i=0;
		for (i=0;iQueryInterface(IID_IKsPropertySet, (void **)&pKs);
		if (FAILED(hr))
		{
			// The pin does not support IKsPropertySet.
			return hr;
		}
		// Try to retrieve the pin category.
		DWORD cbReturned;
		hr = pKs->Get(AMPROPSETID_Pin, AMPROPERTY_PIN_CATEGORY, NULL, 0, 
			pPinCategory, sizeof(GUID), &cbReturned);

		// If this succeeded, pPinCategory now contains the category GUID.

		pKs->Release();
		return hr;
	}
public:
	void printCapDetail()
	{
		int i = 0;
		for (i =0;igetFriendlyName().c_str());
			for(int j=0;jgetMediaOptionCount();j++)
			{
				printf("%d: ",j);
				AM_MEDIA_TYPE* pMtype = pVcap->getMediaOption(j);
				if (pMtype->formattype == FORMAT_VideoInfo)
				{
					VIDEOINFOHEADER* vInfo1 = (VIDEOINFOHEADER*)pMtype->pbFormat;
					 char fourCC[5] = {0};
					 memcpy(fourCC,&vInfo1->bmiHeader.biCompression,4);
					printf("pixformat: %s fps: %lld  width: %d height: %d planes: %d",
						fourCC, 
						10000000LL/vInfo1->AvgTimePerFrame,
						vInfo1->bmiHeader.biWidth,
						vInfo1->bmiHeader.biHeight,
						vInfo1->bmiHeader.biPlanes
						);
				}
				else if (pMtype->formattype == FORMAT_VideoInfo2)
				{
					VIDEOINFOHEADER2* vInfo1 = (VIDEOINFOHEADER2*)pMtype->pbFormat;
					char fourCC[5] = {0};
					memcpy(fourCC,&vInfo1->bmiHeader.biCompression,4);
					printf("pix format: %s fps: %lld width: %d height: %d planers: %d",
						fourCC, 10000000LL/vInfo1->AvgTimePerFrame,
						vInfo1->bmiHeader.biWidth,
						vInfo1->bmiHeader.biHeight,
						vInfo1->bmiHeader.biPlanes
						);
				}
				else
				{
					printf("unknown type...");
				}

				printf("\r\n");
			}
		}

		for (i =0;igetFriendlyName().c_str());

			for(int j=0;jgetMediaOptionCount();j++)
			{
				printf("%d: ",j);
				AM_MEDIA_TYPE* pMtype = pAcap->getMediaOption(j);
				if (pMtype->formattype == FORMAT_WaveFormatEx)
				{
					WAVEFORMATEX* Info = (WAVEFORMATEX*)pMtype->pbFormat;
					printf("channel: %d sample: %d bitrate: %d",Info->nChannels,Info->wBitsPerSample,Info->nSamplesPerSec);
				}
				printf("\r\n");
			}

		}
	}

private:
	vector m_vecVideoCap;
	vector m_vecAudioCap;

};


#include "DShowDevicesInfo.h"

void printAmInfo(AM_MEDIA_TYPE* p,bool bVideo)
{
	if(bVideo){
	VIDEOINFOHEADER* vInfo1 = (VIDEOINFOHEADER*)p->pbFormat;
	if (p->formattype == FORMAT_VideoInfo)
	{
		VIDEOINFOHEADER* vInfo1 = (VIDEOINFOHEADER*)p->pbFormat;
		char fourCC[5] = {0};
		memcpy(fourCC,&vInfo1->bmiHeader.biCompression,4);
		printf("pixformat: %s fps: %lld  width: %d height: %d planes: %d",
			fourCC, 
			10000000LL/vInfo1->AvgTimePerFrame,
			vInfo1->bmiHeader.biWidth,
			vInfo1->bmiHeader.biHeight,
			vInfo1->bmiHeader.biPlanes
			);
	}
	else if (p->formattype == FORMAT_VideoInfo2)
	{
		VIDEOINFOHEADER2* vInfo1 = (VIDEOINFOHEADER2*)p->pbFormat;
		char fourCC[5] = {0};
		memcpy(fourCC,&vInfo1->bmiHeader.biCompression,4);
		printf("pix format: %s fps: %lld width: %d height: %d planers: %d",
			fourCC, 10000000LL/vInfo1->AvgTimePerFrame,
			vInfo1->bmiHeader.biWidth,
			vInfo1->bmiHeader.biHeight,
			vInfo1->bmiHeader.biPlanes
			);
	}
	else
	{
		printf("unknown type...");
	}

	}
	else
	{
		if (p->formattype == FORMAT_WaveFormatEx)
		{
			WAVEFORMATEX* Info = (WAVEFORMATEX*)p->pbFormat;
			printf("channel: %d sample: %d bitrate: %d",Info->nChannels,Info->wBitsPerSample,Info->nSamplesPerSec);
		}
		else
		{
			printf("unknown type...");
		}
	}
}



bool CDshowCapInfoMgr::enumAllCapInfo()
{
	return enumDevicesCapInfo(false) && enumDevicesCapInfo(true);
}

bool CDshowCapInfoMgr::enumDevicesCapInfo(bool audio)
{
	//枚举的文档资料: http://msdn.microsoft.com/en-us/library/dd377566(v=vs.85).aspx
	CComPtr de;
	HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&de);
	if (hr != NOERROR) {
		__LOGOUT("Can't create CLSID_SystemDeviceEnum object");
		return false;
	}

	CComPtr em;
	if (audio) {
		hr = de->CreateClassEnumerator(CLSID_AudioInputDeviceCategory,&em, 0);
	} else {
		hr = de->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&em, 0);
	}
	if (hr != NOERROR) {
		__LOGOUT("Can't create CLSID_***InputDeviceCategory object");
		return false;
	}

	ULONG got;
	IMoniker *m;
	em->Reset();
	while(hr = em->Next(1, &m, &got), hr==S_OK)
	{
		IPropertyBag *pb;
		hr = m->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pb);
		if(!SUCCEEDED(hr)) continue ;
		CDShowCapInfo* pCapInfo = new CDShowCapInfo();
		VARIANT var;	
		var.vt = VT_BSTR;
		hr = pb->Read(L"FriendlyName", &var, NULL);
		if (hr == S_OK) {
			wstring szName;
			szName.append((wchar_t*)var.bstrVal);
			pCapInfo->setFriendlyName(szName);
			SysFreeString(var.bstrVal);
		}
		CComPtr device;
		hr = m->BindToObject(NULL,NULL,IID_IBaseFilter,(void**)&device);
		if (hr != S_OK)
		{
			__LOGOUT("Create Device faild, BindToObjcet error");
		}
		CComPtr emp;
		hr = device->EnumPins(&emp);
		if (FAILED(hr)) {
			throw std::exception("EnumPins failed");
		}

		AM_MEDIA_TYPE* canVideoMt=0;
		AM_MEDIA_TYPE* canAudioMt=0;
		IPin* pin;
		ULONG nPin;
		while(emp->Next(1, &pin, &nPin) == S_OK) {
			PIN_DIRECTION pinDir;
			hr = pin->QueryDirection(&pinDir);
			if (FAILED(hr)) {
				pin->Release();
				throw std::exception("QueryDirection failed");
			}
			if (pinDir != PINDIR_OUTPUT) {
				pin->Release();
				continue;
			}
			CComPtr emt;
			hr = pin->EnumMediaTypes(&emt);
			if (FAILED(hr)) {
				pin->Release();
				throw std::exception("EnumMediaTypes failed");
			}
			GUID pinCat;
			if (GetPinCategory(pin, &pinCat) == S_OK) {
				if (pinCat != PIN_CATEGORY_CAPTURE) continue;
			}
			pin->Release();

			AM_MEDIA_TYPE* mt=0;
			ULONG nMt=0;
			while(emt->Next(1, &mt, &nMt) == S_OK) {
				if(mt)
				{	pCapInfo->putMediaOption(mt); 	}
			}

		}

		pb->Release();
		m->Release();
		if (!pCapInfo->getFriendlyName().empty())
		{
			if (audio)
			{
				pCapInfo->setType(DEVICE_CAP_AUDIO_TYPE);
				m_vecAudioCap.push_back(pCapInfo);
			}
			else
			{
				pCapInfo->setType(DEVICE_CAP_VIDEO_TYPE);
				m_vecVideoCap.push_back(pCapInfo);
			}
		}
		else
		{	delete pCapInfo;	}
	}
	return true;

}




你可能感兴趣的:(development,Windows,C/C++)