我正在尝试通过Windows开发中心的DirectShow示例来制作我自己的应用程序,可以捕获屏幕和音频到视频:Capturing Video to an AVI File
当下面的代码运行时,它在第一次RenderStream调用时失败并显示错误: + errMsg 0x09910DB8“参数不正确。” wchar_t的*
有没有人知道如何找出哪个参数不正确?
void AudioVideoBuilder::AVBuilder::MakeVideo()
{
IGraphBuilder *pGraph = NULL;
ICaptureGraphBuilder2 *pBuild = NULL;
// Create the Filter Graph Manager.
HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL,
CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
if (SUCCEEDED(hr))
{
// Create the Capture Graph Builder.
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,
(void **)&pBuild);
if (SUCCEEDED(hr))
{
pBuild->SetFiltergraph(pGraph);
}
};
if (SUCCEEDED(hr))
{
// Create the Capture Graph Builder.
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2,
NULL,
CLSCTX_INPROC_SERVER,
IID_ICaptureGraphBuilder2,
(void**)&pBuild);
IBaseFilter *pMux;
if (SUCCEEDED(hr))
{
hr = pBuild->SetOutputFileName(
&MEDIASUBTYPE_Avi, // Specifies AVI for the target file.
L"C:\\Temp\\Example.avi", // File name.
&pMux, // Receives a pointer to the mux.
NULL); // (Optional) Receives a pointer to the file sink.
if (SUCCEEDED(hr))
{
IBaseFilter *audioFilter;
IBaseFilter *videoFilter;
//GetAudioAndVideoFilters(audioFilter, videoFilter);
IEnumMoniker *pEnum;
CaptureDeviceSelector deviceSelector;
HRESULT hr = deviceSelector.EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum);
if (SUCCEEDED(hr))
{
IMoniker *pMoniker = NULL;
while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
{
IPropertyBag *pPropBag;
HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
if (FAILED(hr))
{
pMoniker->Release();
continue;
}
VARIANT var;
VariantInit(&var);
// Get description or friendly name.
hr = pPropBag->Read(L"Description", &var, 0);
if (FAILED(hr))
{
hr = pPropBag->Read(L"FriendlyName", &var, 0);
}
//if (var == "screen-capture-recorder")
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&videoFilter);
if (SUCCEEDED(hr))
{
break;
}
}
hr = deviceSelector.EnumerateDevices(CLSID_AudioInputDeviceCategory, &pEnum);
if (SUCCEEDED(hr))
{
while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
{
IPropertyBag *pPropBag;
HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
if (FAILED(hr))
{
pMoniker->Release();
continue;
}
VARIANT var;
VariantInit(&var);
// Get description or friendly name.
hr = pPropBag->Read(L"Description", &var, 0);
if (FAILED(hr))
{
hr = pPropBag->Read(L"FriendlyName", &var, 0);
}
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&audioFilter);
if (SUCCEEDED(hr))
{
break;
}
}
}
}
//ADDED BASED ON MARTIN'S SUGGESTED ANSWER
hr = pGraph->AddFilter(audioFilter, NULL);
if (FAILED(hr))
{
_com_error err(hr);
LPCTSTR errMsg = err.ErrorMessage();
return;
}
hr = pGraph->AddFilter(videoFilter, NULL);
if (FAILED(hr))
{
_com_error err(hr);
LPCTSTR errMsg = err.ErrorMessage();
return;
}
hr = pBuild->RenderStream(
&PIN_CATEGORY_CAPTURE, // Pin category.
&MEDIATYPE_Audio, // Media type.
audioFilter, // Capture filter.
NULL, // Intermediate filter (optional).
pMux); // Mux or file sink filter.
if (SUCCEEDED(hr))
{
hr = pBuild->RenderStream(
&PIN_CATEGORY_CAPTURE, // Pin category.
&MEDIATYPE_Video, // Media type.
videoFilter, // Capture filter.
NULL, // Intermediate filter (optional).
pMux); // Mux or file sink filter.
// Release the mux filter.
pMux->Release();
IConfigAviMux *pConfigMux = NULL;
hr = pMux->QueryInterface(IID_IConfigAviMux, (void**)&pConfigMux);
if (SUCCEEDED(hr))
{
pConfigMux->SetMasterStream(0);
pConfigMux->Release();
}
IConfigInterleaving *pInterleave = NULL;
hr = pMux->QueryInterface(IID_IConfigInterleaving, (void**)&pInterleave);
if (SUCCEEDED(hr))
{
pInterleave->put_Mode(INTERLEAVE_CAPTURE);
pInterleave->Release();
}
}
else
{
_com_error err(hr);
LPCTSTR errMsg = err.ErrorMessage();
}
}
else
{
DWORD error = HRESULT_CODE(hr);
}
}
}
else
{
DWORD error = HRESULT_CODE(hr);
}
}
答案 0 :(得分:1)
除了代码中的其他问题(请参阅注释),主要问题是复制/粘贴问题:您创建CLSID_CaptureGraphBuilder2
两次。
因此,首先创建对象并将其与过滤器图形关联,然后创建另一个对象。您将源过滤器添加到第一个图表,并请求在另一个图形中创建多路复用器过滤器链。那些肯定无法连接,属于不同的图形,因而错误。
评论第二部分,您可以继续:
if (SUCCEEDED(hr))
{
//// Create the Capture Graph Builder.
//hr = CoCreateInstance(CLSID_CaptureGraphBuilder2,
// NULL,
// CLSCTX_INPROC_SERVER,
// IID_ICaptureGraphBuilder2,
// (void**)&pBuild);
IBaseFilter *pMux;
由于您将要处理DirectShow过滤器图形一段时间,我建议您学习如何使用GraphEdit在运行时探索图形(或者,我宁愿推荐使用GraphStudioNext)。
您可以在代码中的任意位置添加MessageBox
来电并保持弹出消息窗口,您可以查看应用中的图表并立即查看问题。
答案 1 :(得分:0)
我不习惯RenderStream
,因为我更喜欢手工制作图表。但是对于所有渲染方法,您必须在渲染图形之前添加滤镜。我认为这包括RenderStream,即使它没有明确指出:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd390016(v=vs.85).aspx
使用
pGraph->AddFilter(audioFilter,NULL);
在RenderStream之前。当然这也适用于视频。
我强烈建议您至少更改
中的错误检查if(SUCCEED(hr))
{
// do stuff
if(SUCCEED(hr))
{
// do stuff
if(SUCCEED(hr))
{
// do stuff
}
}
}
到
// do stuff
if(FAILED(hr))
return;
// do stuff
if(FAILED(hr))
return;
// do stuff
if(FAILED(hr))
return;
它更具可读性。