一般ffmpeg是这样枚举的:
//Show Device
void show_dshow_device(){
AVFormatContext *pFmtCtx = avformat_alloc_context();
AVDictionary* options = NULL;
av_dict_set(&options, "list_devices", "true", 0);
AVInputFormat *iformat = av_find_input_format("dshow");
printf("Device Info=============\n");
avformat_open_input(&pFmtCtx, "video=dummy", iformat, &options);
printf("========================\n");
}
但是只能显示到命令行,代码无法直接获取(当然也可以通过获取命令行获取),这种反人类设计,有点无语。能不能直接获取呢?
答案是用DirectShow枚举:条条大路通罗马
int CCapVideo::GetAllCapDevice(CStringArray &Devices)//得到所有的视频捕获设备
{
HRESULT hr;
CComPtr< IBaseFilter > pCap;
IBaseFilter **ppCap = &pCap;
*ppCap = NULL;
// 构造一个枚举器
//
CComPtr< ICreateDevEnum > pCreateDevEnum;
pCreateDevEnum.CoCreateInstance( CLSID_SystemDeviceEnum );
ASSERT(pCreateDevEnum);
if( !pCreateDevEnum )
return 0;
// 枚举视频捕获设备
//
CComPtr< IEnumMoniker > pEm;
pCreateDevEnum->CreateClassEnumerator( CLSID_VideoInputDeviceCategory, &pEm, 0 );
// ASSERT(pEm);
if( !pEm )
return 0;
pEm->Reset( );
// 寻找第一个视频捕获设备
//
while( 1 )
{
ULONG ulFetched = 0;
CComPtr< IMoniker > pM;
hr = pEm->Next( 1, &pM, &ulFetched );
if( hr != S_OK )
break;
// 从moniker中取得property bag interface
CComPtr< IPropertyBag > pBag;
hr = pM->BindToStorage( 0, 0, IID_IPropertyBag, (void**) &pBag );
if( hr != S_OK )
continue;
CComVariant var;
var.vt = VT_BSTR;
hr = pBag->Read( L"FriendlyName", &var, NULL );
if( hr != S_OK )
continue;
// 需要现行的过滤器
//
hr = pM->BindToObject( 0, 0, IID_IBaseFilter, (void**) ppCap );
if( *ppCap )
{
CString szName=(CString)var.bstrVal;
Devices.Add(szName);
}
}
return (int)Devices.GetCount();
}
然后:
sprintf(device_name, "video=这里填写前面获取的摄像头列表即可");
//sprintf(device_name, "video=aoni Webcam");
//sprintf(device_name, "video=screen-capture-recorder");
ifmt=av_find_input_format("dshow");
//Set own video device's name
if (avformat_open_input(&ifmt_ctx, device_name, ifmt, NULL) != 0){
printf("Couldn't open input stream.(无法打开输入流)\n");
return -1;
}
打完收工!