Directshow RenderStream“参数不正确”

时间:2015-04-16 09:34:12

标签: c++ video directshow audio-recording

我正在尝试通过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);
    }
}

2 个答案:

答案 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;

它更具可读性。