【问题标题】:Directshow capturing video to AVIDirectshow 将视频捕获到 AVI
【发布时间】:2026-01-29 15:25:01
【问题描述】:

我正在尝试通过 Windows 开发中心上的 DirectShow 示例来制作我自己的可以捕获屏幕和音频到视频的应用程序。 https://msdn.microsoft.com/en-us/library/windows/desktop/dd318627(v=vs.85).aspx

当我运行 RenderStream 方法失败并且 HRESULT_CODE 是 16387。

这是我的代码。我已经阅读了很多示例,并且无法完全理解这一切。我很想得到一些真正基本的东西,这样我就可以自己扩展它。

我意识到这不是最佳实践等。我对 C++ 非常生疏,并且对 DirectShow 很陌生,所以请不要太挑剔,请随意解释,就像我有点简单!

这是我的代码:

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);
        }
    };
    IBaseFilter *pCap = 0;
    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:\\Example.avi", // File name.
                &pMux,              // Receives a pointer to the mux.
                NULL);              // (Optional) Receives a pointer to the file sink.

            if (SUCCEEDED(hr))
            {
                hr = pBuild->RenderStream(
                    &PIN_CATEGORY_CAPTURE, // Pin category.
                    &MEDIATYPE_Audio,      // Media type.
                    pCap,                  // 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.
                        pCap,                  // 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
                {
                    DWORD error = HRESULT_CODE(hr);
                }
            }
            else
            {
                DWORD error = HRESULT_CODE(hr);
            }
        }
    }
    else
    {
        DWORD error = HRESULT_CODE(hr);
    }
}

【问题讨论】:

  • 您无法写入 C:\ 根文件夹。
  • 请同时使用更好的错误处理:_com_error err(hr); LPCTSTR errMsg = err.ErrorMessage(); 这样我们就可以了解这里发生了什么。
  • 感谢大家的反馈。我已将 AVI 位置更改为临时文件夹,并返回改进的错误处理 - “+ errMsg 0x0556FEB0 “无效指针” wchar_t * “.. 这似乎与下面 Martin 的建议相匹配,我认为,因此将努力弄清楚添加捕获设备和枚举。

标签: c++ directshow video-capture audio-recording


【解决方案1】:

正如 Andrew Komiagin 在评论中已经建议的那样。不要使用“c:\Example.avi”作为目标文件。如果您没有 root 的访问权限,可能会导致不必要的问题。

此外,在您的代码中,您没有在任何地方定义捕获设备(输入设备)。

中的变量pCap
pBuild->RenderStream

在您的代码中设置为 0(NULL)。它必须是捕获设备。 RenderStream 期待捕获设备或渲染器,从不为 NULL。 如果您搜索错误代码,请使用十六进制。 16387 是 0x4003,这是输入引脚的问题。难怪,它是零。

看这里

https://msdn.microsoft.com/en-us/library/windows/desktop/dd377566(v=vs.85).aspx

了解如何获取捕获设备。

【讨论】:

  • 以管理员身份启动或调整文件夹权限应该仍然可以正常工作。
  • @deW1 我改了文字。
  • 所以我已经实现了设备的枚举,并选择了第一个找到的音频和视频设备来启动它。不幸的是,现在我收到错误 + errMsg 0x09910DB8 “参数不正确。” wchar_t*
  • @JustinC 0x09910DB8 看起来更像一个指针。它不是有效的 HRESULT。如果没有看到您的新代码,就不可能给出答案。我想已经发生了很大变化,所以最好打开一个新问题。如果只有一小部分发生了变化,请更新您的问题。确保将更改标记为 UPDATE 否则我和其他人到目前为止所做的答案将不再匹配(这可能会导致投票失败)。如果您不确定,请打开一个新问题,将您的代码缩减为仅显示错误的小示例,而不是整个渲染管道。
  • 谢谢马丁,我已经更改了相当多的代码,所以发布了一个新问题,包括更新的代码。*.com/questions/29670733/…
【解决方案2】:

这里的问题与您的新问题相同:Directshow RenderStream "the parameter is incorrect" 是无意的第二次创建 CLSID_CaptureGraphBuilder2 实例 (details)。

另请注意,错误代码是HRESULT 值。这就是说明操作状态的原因。一旦您尝试获取字符串并获取指向字符的指针,指针(0x055...0x099...)就不是错误代码,它只是一些没有特殊含义的随机地址。代码是关键。

【讨论】: