【问题标题】:Directshow RenderStream "the parameter is incorrect"Directshow RenderStream“参数不正确”
【发布时间】:2015-06-22 14:59:06
【问题描述】:

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

【问题讨论】:

  • 您的代码在枚举名字对象的循环周围存在内存/引用泄漏。并非所有执行路径都可以pMoniker->Release
  • 那你也不用pEnum->Release

标签: c++ video directshow audio-recording


【解决方案1】:

除了代码中的其他问题(参见 cmets)之外,主要问题是复制/粘贴问题:您创建了两次 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 调用并保持弹出消息窗口,您将查看应用程序中的图表并立即发现问题。

【讨论】:

  • 我没看到 :-(
  • 感谢罗曼和马丁的帮助。我的代码现在运行没有错误。我没有最终得到我的 AVI 文件,但会采纳您的建议并努力理解这些图表。
  • 大家好,不幸的是,我仍然无法解决这个问题。我的代码运行没有任何错误,但似乎没有做任何事情。我添加了 AddToROT 方法并尝试在 GraphEdit 中找到我的图表 - 不显示远程图表 - 并且 GraphEditNext - 找不到任何可能是我的图表的东西......如果有人可以提供更多建议或提示,他们将不胜感激..一旦我开始看到一些事情发生,我相信我将能够获得一些动力..
  • 实际上我已经设法将代码放入以将图形保存到文件中并将其加载到 GraphEditNext 中。当我运行它时,它会创建我的 AVI 文件!好消息...所以我现在的问题是 - 代码中的什么实际上以编程方式运行图形??
  • 带有AddToROT 和GraphEdit 的应用程序应该在有或没有提升权限的情况下启动。否则,应用程序看不到对方。然后,您需要安装 Windows SDK 或至少从其中注册 proppage.dll。很难说更多,因为需要调试才能看到其余部分。
【解决方案2】:

我不习惯RenderStream,因为我更喜欢手动构建图表。但是对于所有 Render 方法,您必须在渲染图形之前添加过滤器。我认为这包括 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;

它更具可读性。

【讨论】:

  • 谢谢马丁,我听从了你的建议,但它仍然以同样的方式失败。我将更新上面的问题以反映最新的代码。
  • @JustinC:代码其实是0x80070057ERROR_INVALID_PARAMETER“参数不正确。”。使用alax.info/blog/1383 查找代码
  • 啊哈,所以我得到的代码是 0x09078100“参数不正确。”...我尝试了链接并启动了应用程序,但我无法让它工作。可惜了,听起来很有用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-23
  • 2019-05-23
  • 2015-05-27
  • 2012-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多