同系列文章
工程下载
EnumAudioVideoDevices.zip
MF_AudioVideoDevices.h
/* ----------------------------------------------------------
* 文件名称:MF_AudioVideoDevices.h
*
* 作者:秦建辉
*
* 微信:splashcn
*
* 博客:http://www.firstsolver.com/wordpress/
*
* 开发环境:
* Visual Studio V2017
*
* 版本历史:
* V1.1 2018年12月25日
* 增加Json输出,便于C#/JAVA调用
*
* V1.0 2010年10月09日
* 获取音频视频输入设备列表
* ---------------------------------------------------------- */
#pragma once
#include <windows.h>
#include <vector>
#include <Mfidl.h>
#ifndef MACRO_GROUP_DEVICENAME
#define MACRO_GROUP_DEVICENAME
#define MAX_FRIENDLY_NAME_LENGTH 128
#define MAX_MONIKER_NAME_LENGTH 256
typedef struct _TDeviceName
{
WCHAR Name[MAX_FRIENDLY_NAME_LENGTH]; // 设备友好名
WCHAR Moniker[MAX_MONIKER_NAME_LENGTH]; // 设备Moniker名
} TDeviceName;
#endif
#ifdef __cplusplus
extern "C"
{
#endif
/*
功能:用于预加载动态库
返回值:TRUE
*/
BOOL WINAPI Prepare();
/*
功能:获取音频视频输入设备列表
参数说明:
devices:用于存储返回的设备友好名及Moniker名
guid:
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID:获取音频输入设备列表
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID:获取视频输入设备列表
返回值:
错误代码
说明:
基于Media Foundation
列表中的第一个设备为系统缺省设备
capGetDriverDescription只能获得设备驱动名
操作系统要求Windows 7及以上版本(关键)
*/
HRESULT WINAPI MF_GetAudioVideoInputDevices(OUT std::vector<TDeviceName> &devices, REFGUID guid);
/*
功能:获取音频视频输入设备列表
参数说明:
devices:输出,Json字符串,用于存储返回的设备Name和Moniker
cch:输出,有效字符个数,不包括字符串结束符
video:
FALSE:获取音频输入设备列表
TRUE:获取视频输入设备列表
返回值:
错误代码
说明:
基于Media Foundation
列表中的第一个设备为系统缺省设备
capGetDriverDescription只能获得设备驱动名
操作系统要求Windows 7及以上版本(关键)
*/
HRESULT WINAPI MF_GetDeviceSources(OUT TCHAR* &devices, OUT int &cch, BOOL video);
/*
功能:释放内存
参数:
p:要释放的内存指针
*/
VOID WINAPI FreeMemory(LPVOID p);
#ifdef __cplusplus
}
#endif
MF_AudioVideoDevices.cpp
#include "MF_AudioVideoDevices.h"
#include <Mfapi.h>
#include <sstream>
#pragma comment(lib, "Mfplat.lib")
#pragma comment(lib, "Mf.lib")
// 用于预加载
BOOL WINAPI Prepare() { return TRUE; }
HRESULT WINAPI MF_GetAudioVideoInputDevices(OUT std::vector<TDeviceName> &devices, REFGUID guid)
{
devices.clear(); // 初始化
// 初始化Media Foundation
HRESULT hr = MFStartup(MF_VERSION, MFSTARTUP_LITE);
if (SUCCEEDED(hr))
{ // 创建属性搜索页
IMFAttributes *pAttributes = NULL;
hr = MFCreateAttributes(&pAttributes, 1); // 要求Windows Vista
if (SUCCEEDED(hr))
{ // 设置搜索关键字-枚举音频视频设备
hr = pAttributes->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, guid);
if (SUCCEEDED(hr))
{ // 获取搜索结果
IMFActivate **ppDevices = NULL;
UINT32 dwCount = 0;
hr = MFEnumDeviceSources(pAttributes, &ppDevices, &dwCount); // 要求Windows 7
if (SUCCEEDED(hr))
{
if (dwCount == 0)
{ // 没有找到
hr = E_FAIL;
}
else
{
TDeviceName name;
for (DWORD i = 0; i < dwCount; i++)
{ // 获取设备友好名
ppDevices[i]->GetString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, name.Name, MAX_FRIENDLY_NAME_LENGTH, NULL);
// 获取设备Moniker名
ppDevices[i]->GetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, name.Moniker, MAX_MONIKER_NAME_LENGTH, NULL);
devices.push_back(name);
ppDevices[i]->Release();
}
}
CoTaskMemFree(ppDevices); // 释放内存
}
}
pAttributes->Release();
}
MFShutdown(); // 关闭Media Foundation
}
return hr;
}
HRESULT WINAPI MF_GetDeviceSources(OUT TCHAR* &devices, OUT int &cch, BOOL video)
{ // 初始化Media Foundation
HRESULT hr = MFStartup(MF_VERSION, MFSTARTUP_LITE);
if (SUCCEEDED(hr))
{ // 创建属性搜索页
IMFAttributes *pAttributes = NULL;
hr = MFCreateAttributes(&pAttributes, 1); // 要求Windows Vista
if (SUCCEEDED(hr))
{ // 设置搜索关键字-枚举音频视频设备
if (video)
{ // 视频设备
hr = pAttributes->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID);
}
else
{ // 音频设备
hr = pAttributes->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID);
}
if (SUCCEEDED(hr))
{ // 获取搜索结果
IMFActivate **ppDevices = NULL;
UINT32 dwCount = 0;
hr = MFEnumDeviceSources(pAttributes, &ppDevices, &dwCount); // 要求Windows 7
if (SUCCEEDED(hr))
{
if (dwCount == 0)
{ // 没有找到
hr = E_FAIL;
}
else
{
TCHAR Buffer[MAX_MONIKER_NAME_LENGTH];
std::wostringstream os;
os << L"[";
for (DWORD i = 0; i < dwCount; i++)
{
if (i != 0) os << L",";
// 获取设备友好名
ppDevices[i]->GetString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, reinterpret_cast<LPWSTR>(&Buffer), MAX_FRIENDLY_NAME_LENGTH, NULL);
os << L"{\"Name\":\"" << Buffer << L"\",";
// 获取设备Moniker名
ppDevices[i]->GetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, reinterpret_cast<LPWSTR>(&Buffer), MAX_MONIKER_NAME_LENGTH, NULL);
os << L"\"Moniker\":\"" << Buffer << L"\"}";
ppDevices[i]->Release();
}
os << L"]";
std::wstring ws = os.str();
cch = (int)ws.size();
devices = (TCHAR*)CoTaskMemAlloc((cch + 1) << 1);
if (devices == NULL)
{
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
}
else
{
wcscpy_s(devices, cch + 1, ws.c_str());
}
}
CoTaskMemFree(ppDevices); // 释放内存
}
}
pAttributes->Release();
}
MFShutdown(); // 关闭Media Foundation
}
return hr;
}
VOID WINAPI FreeMemory(LPVOID p)
{
if (p != NULL) CoTaskMemFree(p);
}
MF_AudioVideoDevices.def
LIBRARY MF_AudioVideoDevices
EXPORTS
Prepare
MF_GetAudioVideoInputDevices
MF_GetDeviceSources
FreeMemory