目前我正在开发基于 DirectShow 的应用程序来配置电视采集卡。它应该适用于那里的大多数采集卡,因此它必须尽可能通用。
由于大多数采集卡制造商似乎提出了不同的配置方式,因此我的应用程序将尝试分析相关的过滤器及其引脚。一个常见的问题是检查某个引脚是否可以直接连接到渲染器,或者它首先需要一个编码器/多路复用器。
注意:我在 VB.NET 中使用DirectShow .NET库,但如果您愿意,可以使用 C# 或 C++ 回答。
AMMediaType
我尝试使用以下功能检查输出引脚是否接受某个:
Private Function Check1(filter As IBaseFilter, type As AMMediaType) As Boolean
Dim enumPins As IEnumPins = Nothing
If filter.EnumPins(enumPins) = 0 Then
Dim pin(0) As IPin
While (enumPins.Next(1, pin, Nothing) = 0)
Dim accepted As Boolean = (pin(0).QueryAccept(type) = 0)
Marshal.ReleaseComObject(pin(0))
If accepted Then Return True
End While
End If
Return False
End Function
这个函数总是返回False
。经过一些调试,我发现QueryAccept
总是返回-2147467259
. 文档没有提到这样的返回值。经过更多调查,我发现QueryAccept
它用于提出新的 MediaType,所以我假设 QueryAccept 仅在调用引脚已连接时才有效。在这里阅读更多。
AMMediaType
我可以使用以下函数检查输出引脚是否首选某个选项:
Private Function Check2(filter As IBaseFilter, type As AMMediaType) As Boolean
Dim enumPins As IEnumPins = Nothing
If filter.EnumPins(enumPins) = 0 Then
Dim pin(0) As IPin
While (enumPins.Next(1, pin, Nothing) = 0)
Dim enumMediaTypes As IEnumMediaTypes = Nothing
If pin(0).EnumMediaTypes(enumMediaTypes) = 0 Then
Dim mediaType(0) As AMMediaType
While (enumMediaTypes.Next(1, mediaType, Nothing) = 0)
Dim equals As Boolean = (type Is Nothing OrElse
(type.majorType = Nothing OrElse mediaType(0).majorType = type.majorType) AndAlso
(type.subType = Nothing OrElse mediaType(0).subType = type.subType) AndAlso
(type.formatType = Nothing OrElse mediaType(0).formatType = type.formatType))
DsUtils.FreeAMMediaType(mediaType(0))
If equals Then
Return True
End If
End While
End If
End While
End If
Return False
End Function
通过枚举EnumMediaTypes
,我可以确定某个AMMediaType
是否被列为首选。但是,这并不能保证可以建立连接。通常有一些类型不包含在此枚举中,但仍可用于连接。有时这个枚举是空的。
我正在寻找的是一种方法来确定一个过滤器是否可以直接连接到另一个过滤器,或者它应该首先连接到一个编码器/多路复用器。有人知道我怎么能做到这一点吗?
注意:简单地连接过滤器并使用返回值来确定它是否成功,不是一种选择。以我的经验,ICaptureGraphBuilder::RenderStream经常S_OK
在没有建立连接的情况下返回。例如,尝试MediaType.AnalogVideo
在没有模拟视频引脚时使用。