ffmpeg二次开发时获取音频名称有时候在win7系统下的某些电脑会出现截断,导致从flash或者其他获取音频的名称在ffmpeg推流时Could not find audio only device with name 错误。
解决方案:
在ffmpeg中自己实现获取音频设备名称,目前版本ffmpeg虽然有获取设备名称接口,但是目前为止还并未将接口实现,网上常见的获取音视频设备列表的教程只是将设备名称进行cmd控制台窗口输出,无法在二次开发中使用,借鉴网上其他网友的代码并修改,实现了代码获取ffmpeg音视频设备名称的函数,和ffmpeg命令获取音视频设备名称结果是相同的 。
代码部分:
//ffmpeg源码中直接copy
static char *dup_wchar_to_utf8(wchar_t *w)
{
char *s = NULL;
int l = WideCharToMultiByte(CP_UTF8, 0, w, -1, 0, 0, 0, 0);
s = (char*)av_malloc(l);
if (s)
WideCharToMultiByte(CP_UTF8, 0, w, -1, s, l, 0, 0);
return s;
}
HRESULT DS_GetAudioVideoInputDevices(std::vector<string> &vectorDevices, REFGUID guidValue)
{
std::string name;
HRESULT hr;
// 初始化
vectorDevices.clear();
// 初始化COM
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (FAILED(hr))
{
return hr;
}
// 创建系统设备枚举器实例
ICreateDevEnum *pSysDevEnum = NULL;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysDevEnum);
if (FAILED(hr))
{
CoUninitialize();
return hr;
}
// 获取设备类枚举器
IEnumMoniker *pEnumCat = NULL;
hr = pSysDevEnum->CreateClassEnumerator(guidValue, &pEnumCat, 0);
if (hr == S_OK)
{
// 枚举设备名称
IMoniker *pMoniker = NULL;
ULONG cFetched;
while (pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
{
IPropertyBag *pPropBag;
hr = pMoniker->BindToStorage(NULL, NULL, IID_IPropertyBag, (void **)&pPropBag);
if (SUCCEEDED(hr))
{
// 获取设备友好名
VARIANT varName;
VariantInit(&varName);
hr = pPropBag->Read(L"FriendlyName", &varName, NULL);
if (SUCCEEDED(hr))
{
name = dup_wchar_to_utf8(varName.bstrVal);
vectorDevices.push_back(name);
}
VariantClear(&varName);
pPropBag->Release();
}
pMoniker->Release();
} // End for While
pEnumCat->Release();
}
pSysDevEnum->Release();
CoUninitialize();
return hr;
}
使用方式:
std::vector<string> v_audioName;
DS_GetAudioVideoInputDevices(v_audioName, CLSID_AudioInputDeviceCategory);//获取音频列表
DS_GetAudioVideoInputDevices(v_videoName, CLSID_VideoInputDeviceCategory);//获取视频列表