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;
}