2012-11-29 62 views
0

目前我正在開發基於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總是返回-2147467259The documentation沒有提到這樣的返回值。經過一番調查後,我發現QueryAccept用於提出一個新的MediaType,所以我假設QueryAccept只在調用引腳已連接時才起作用。 Read more here

我可以檢查是否一定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,而沒有模擬視頻引腳。

+1

如果您想檢查引腳是否可以直接連接,那麼只需從源濾波器的輸出引腳和渲染器的輸入引腳並執行[IPin :: Connect](http://msdn.microsoft.com/zh-cn/ .com/de-de/library/windows/desktop/dd390420(v = vs.85).aspx)。如果源爲RGB24或YUY2或NV12等原始視頻類型,則只能直接連接到視頻渲染。但通常你需要在它們之間有一個解碼器。對於電視卡,這將是一個MPEG2或H.264解碼器。 – CPlusSharp

+0

@CPlusSharp:我試過IPin :: Connect,但是在某些情況下沒有按預期工作。不過,這啓發了我使用IGraphBuilder :: Connect。看到我自己的答案。 –

回答

0

而不是ICaptureGraphBuilder::RenderStream,我結束了使用IGraphBuilder::Connect,但只用於檢查連接是否可能。連接過濾器後,下列功能會立即斷開過濾器,並使用HRESULT來確定連接是否成功的:

Private Function Check3(graph As IGraphBuilder, filterOut As IBaseFilter, filterIn As IBaseFilter, type As AMMediaType) As Boolean 
    Dim result As Boolean 

    ' Enumerate output pins 
    Dim enumPinsOut As IEnumPins = Nothing 
    If filterOut.EnumPins(enumPinsOut) = 0 Then 
    Dim pinOut(0) As IPin 
    While enumPinsOut.Next(1, pinOut, Nothing) = 0 

     ' Enumerate output media types 
     Dim enumMediaTypes As IEnumMediaTypes = Nothing 
     If pinOut(0).EnumMediaTypes(enumMediaTypes) = 0 Then 
     Dim mediaType(0) As AMMediaType 
     While enumMediaTypes.Next(1, mediaType, Nothing) = 0 

      ' Compare media types 
      If type Is Nothing OrElse 
      (type.majorType = Nothing OrElse type.majorType = mediaType(0).majorType) AndAlso 
      (type.subType = Nothing OrElse type.subType = mediaType(0).subType) AndAlso 
      (type.formatType = Nothing OrElse type.formatType = mediaType(0).formatType) Then 

      ' Enumerate input pins 
      Dim enumPinsIn As IEnumPins = Nothing 
      If filterIn.EnumPins(enumPinsIn) = 0 Then 
       Dim pinIn(0) As IPin 
       While enumPinsIn.Next(1, pinIn, Nothing) = 0 

       ' Evaluate connection return value 
       Dim hr As Integer = graph.Connect(pinOut(0), pinIn(0)) 
       graph.Disconnect(pinOut(0)) 
       result = (hr = 0) 
       If result = False Then Console.WriteLine(DsError.GetErrorText(hr)) 

       Marshal.ReleaseComObject(pinIn(0)) 
       If result = True Then Exit While 
       End While 
      End If 
      End If 

      DsUtils.FreeAMMediaType(mediaType(0)) 
      If result = True Then Exit While 
     End While 
     End If 

     Marshal.ReleaseComObject(pinOut(0)) 
     If result = True Then Exit While 
    End While 
    End If 

    Return result 
End Function 
+1

如果您使用IGraphBuilder :: Connect,則DirectShow使用[智能連接](http://msdn.microsoft.com/en-us/library/windows/desktop/dd390342(v = vs.85).aspx)並插入中間值過濾器!那就是我在第一條評論中的意思。通過這種方式,您需要記住在斷開連接後刪除現在未使用的過濾器(中間過濾器)。 – CPlusSharp

1

要檢查是否引腳可以連接你需要嘗試將它們連接起來。然而,「常用」連接方法IGraphBuilder::Connect包括所謂的智能連接,其開始試圖在中間插入額外的過濾器。如果你不想要這個,你有IGraphBuilder::ConnectDirect方法。不要直接調用IPin::Connect:雖然它可能工作正常,但它不應該直接調用,ConnectDirect會爲您調用它。

請注意,對於ConnectDirect,您還需要提供介質類型。空媒體類型可能會消失,或者您可能想要嘗試從輸出引腳枚舉的媒體類型。基本上,這是默認的行爲:輸出引腳會嘗試作爲參數提供的媒體類型(如果不爲空),然後嘗試自己的,然後它嘗試通過對等輸入引腳枚舉的,然後智能連接開始工作(除非它是ConnectDirect呼叫)。

全部RenderStream和朋友都在上面提到的包裝。

另外,-21474672590x80004005E_FAIL "Unspecified error"

相關問題