当两者都接受 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
是典型的过滤器无法协商媒体类型以流式传输数据的情况。可能有几个问题导致提到的错误场景。
首先,您将展示如何构建媒体类型。这很重要,但源过滤器的 GetMediaType
和 CheckMediaType
方法的作用也很重要。一个必须正确暴露这个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。
当您看到它的渲染器无法连接并拒绝连接时,您有兴趣检查它拒绝的媒体类型,并提供完整的详细信息。
我标记了 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
是典型的过滤器无法协商媒体类型以流式传输数据的情况。可能有几个问题导致提到的错误场景。
首先,您将展示如何构建媒体类型。这很重要,但源过滤器的 GetMediaType
和 CheckMediaType
方法的作用也很重要。一个必须正确暴露这个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。
当您看到它的渲染器无法连接并拒绝连接时,您有兴趣检查它拒绝的媒体类型,并提供完整的详细信息。