当两者都接受 ARGB32 媒体类型时,引脚之间没有组合

No combination between pins when both accept ARGB32 media type

我标记了 directshow 和 directshow.net,因为我同时使用 C++ 和 C# 来创建源过滤器(用于在内存中加载位图),而 c# 提供位图。

几天来我一直被这个问题"There is no common media type between these pins"难住了,因为源过滤器和渲染器过去常常连接,但后来没有连接。源过滤器主要基于 GSSF 示例。

在我的源过滤器中,我允许 1 种媒体类型:

AMOVIESETUP_MEDIATYPE sudMediaTypes[] =
{
    { &MEDIATYPE_Video, &MEDIASUBTYPE_ARGB32 }
};

然后根据位图信息设置媒体类型 header:

HRESULT CPushPinBitmap::CreateMediaTypeFromBMI(BITMAPINFOHEADER *bmi, LONGLONG lFPS)
{
    auto pvi = reinterpret_cast<VIDEOINFOHEADER*>(m_amt.AllocFormatBuffer(SIZE_PREHEADER + bmi->biSize));

    if (pvi == nullptr)
    {
        return E_OUTOFMEMORY;
    }

    ZeroMemory(pvi, m_amt.cbFormat);
    pvi->AvgTimePerFrame = lFPS;
    memcpy(&pvi->bmiHeader, bmi, bmi->biSize);
    m_lBufferSize = GetBitmapSize(&pvi->bmiHeader);
    pvi->bmiHeader.biSizeImage = m_lBufferSize;
    pvi->dwBitRate = m_lBufferSize * static_cast<DWORD>(static_cast<float>(UNITS) / pvi->AvgTimePerFrame) * 8;

    SetRectEmpty(&pvi->rcSource);
    SetRectEmpty(&pvi->rcTarget);

    m_amt.SetType(&MEDIATYPE_Video);
    m_amt.SetSubtype(&MEDIASUBTYPE_ARGB32);
    m_amt.SetFormatType(&FORMAT_VideoInfo);
    m_amt.SetSampleSize(bmi->biSizeImage);
    m_amt.SetTemporalCompression(FALSE);

    return S_OK;
}

从 C# 调用 CreateMediaTypeFromBMI:

public void SetMediaType(ISourceConfig sourceConfig)
{
    var bmi = new BitmapInfoHeader();

    if (bitmap == null)
    {
        int i;
        GetImage(0, IntPtr.Zero, 0, out i);
    }

    bmi.Size = Marshal.SizeOf(typeof(BitmapInfoHeader));
    bmi.Width = bitmapData.Width;
    bmi.Height = bitmapData.Height * -1;
    bmi.Planes = 1;
    bmi.BitCount = 32;
    bmi.Compression = 0;
    bmi.ImageSize = bmi.Width * bmi.Height * bmi.BitCount / 8;
    bmi.XPelsPerMeter = 0;
    bmi.YPelsPerMeter = 0;
    bmi.ClrUsed = 0;
    bmi.ClrImportant = 0;

    var hr = sourceConfig.SetMediaTypeFromBitmap(bmi, fps);
    DsError.ThrowExceptionForHR(hr);
}

调用 ConnectDirect 后,我​​得到 0x80040207。如果我改为调用 RenderStream,我会得到 0x80040217,它告诉我同样的事情,即媒体类型无效。

然后是渲染器过滤器,它是 BlackMagicDesign 提供的用于捕获和渲染的 decklink 渲染器。此渲染器支持 5 种不同类型的媒体,其中第 4 种类型表示 ARGB32 的子类型 guid。

所以我的问题是,如果渲染器支持 ARGB32,并且我告诉源过滤器它的输出引脚是使用视频的 ARGB32,那么 directshow 如何告诉我这些引脚之间没有通用的媒体类型?

哦,我应该注意到 fps 变量 = 10000000 / 30;

错误代码 VFW_E_CANNOT_CONNECT 是典型的过滤器无法协商媒体类型以流式传输数据的情况。可能有几个问题导致提到的错误场景。

首先,您将展示如何构建媒体类型。这很重要,但源过滤器的 GetMediaTypeCheckMediaType 方法的作用也很重要。一个必须正确暴露这个RGB媒体类型,另一个应该接受它。

您可以通过 GraphEdit/GraphStudioNext 验证您的 pin 中的视频是否可渲染到标准视频渲染器(非 Decklink)来检查您应用程序的这一部分。

其次,您正在处理从上到下的 RGB 帧(负 biHeight),我最好的猜测是 Decklink 渲染器不接受这种布局。典型的 RGB 顺序是反向的,从下到上。当库存渲染器经常帮助您并提供兼容的媒体类型,试图协商双方都可接受的东西(或通过转换)时,Decklink 渲染器并不那么灵活,可能会因为这个原因拒绝这种 RGB 媒体类型。您可能需要尝试从下到上,至少要排除这种情况。

第三,除了上面提到的 Decklink 渲染器不灵活之外,该硬件还要求视频格式直接与在线视频参数兼容。它不会像 VMR/EVR 过滤器那样缩放视频,并且视频应严格符合规格、分辨率和帧速率。您必须确保您在媒体类型中给出了准确的值。例如,硬件可能只能以 50、59.94、60 的速率接受 1280x720,而不会接受 25 或 30 fps 的媒体类型。如果是 NTSC 标清视频,则速率应为 29.97 而不是 30。

当您看到它的渲染器无法连接并拒绝连接时,您有兴趣检查它拒绝的媒体类型,并提供完整的详细信息。