Arbeiten mit Querleisten

[Das dieser Seite zugeordnete Feature DirectShow ist ein Legacyfeature. Es wurde von MediaPlayer, IMFMediaEngine und Audio/Video Capture in Media Foundation abgelöst. Diese Features wurden für Windows 10 und Windows 11 optimiert. Microsoft empfiehlt dringend, dass neuer Code mediaPlayer, IMFMediaEngine und Audio/Video Capture in Media Foundation anstelle von DirectShow verwendet, wenn möglich. Microsoft schlägt vor, dass vorhandener Code, der die Legacy-APIs verwendet, so umgeschrieben wird, dass nach Möglichkeit die neuen APIs verwendet werden.]

Wenn eine Videoaufnahme Karte über mehrere physische Eingaben verfügt oder mehrere Hardwarepfade für Daten unterstützt, kann das Filterdiagramm den Analog Video Crossbar Filter enthalten. Der Capture Graph Builder fügt diesen Filter bei Bedarf automatisch hinzu. sie wird über den Erfassungsfilter Upstream. Abhängig von der Hardware kann das Filterdiagramm mehrere instance des Querleistenfilters enthalten.

Der Querleistenfilter macht die IAMCrossbar-Schnittstelle verfügbar, mit der Sie eine bestimmte Eingabe an eine bestimmte Ausgabe weiterleiten können. Ein Video-Karte kann beispielsweise über einen Koaxialanschluss und einen S-Video-Eingang verfügen. Diese werden als Eingabenadeln auf dem Querleistenfilter dargestellt. Um eine Eingabe auszuwählen, leiten Sie den entsprechenden Eingabepin mithilfe der IAMCrossbar::Route-Methode an den Ausgabepin der Querleiste weiter.

Um Balkenfilter im Diagramm zu finden, können Sie die ICaptureGraphBuilder2::FindInterface-Methode verwenden, um nach Filtern zu suchen, die IAMCrossbar unterstützen. Der folgende Code sucht z. B. nach zwei Kreuzleisten:

// Search upstream for a crossbar.
IAMCrossbar *pXBar1 = NULL;
hr = pBuild->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, pSrc,
        IID_IAMCrossbar, (void**)&pXBar1);
if (SUCCEEDED(hr)) 
{
    // Found one crossbar. Get its IBaseFilter interface.
    IBaseFilter *pFilter = NULL;
    hr = pXBar1->QueryInterface(IID_IBaseFilter, (void**)&pFilter);
    if (SUCCEEDED(hr)) 
    {
        // Search upstream for another crossbar.
        IAMCrossbar *pXBar2 = NULL;
        hr = pBuild->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, pFilter,
                 IID_IAMCrossbar, (void**)&pXBar2);
        pFilter->Release();

        if (SUCCEEDED(hr))
        {
            /* ... */
            pXBar2->Release();
        }
    }
    pXBar1->Release();
}

Einen allgemeineren Ansatz finden Sie in der CCrossbar-Klasse im AmCap-Beispiel.

Sobald Sie über einen Zeiger auf die IAMCrossbar-Schnittstelle verfügen, können Sie Informationen zum Kreuzleistenfilter abrufen, einschließlich des physischen Typs der einzelnen Pins und der Matrix, an die Eingabestifte weitergeleitet werden können.

  • Um den Typ des physischen Connectors zu bestimmen, dem ein Pin entspricht, rufen Sie die IAMCrossbar::get_CrossbarPinInfo-Methode auf. Die -Methode gibt einen Member der PhysicalConnectorType-Enumeration zurück. Beispielsweise gibt ein S-Video-Pin den Wert PhysConn_Video_SVideo zurück.

    Die get_CrossbarInfo-Methode gibt auch an, ob zwei Pins miteinander verbunden sind. Ein Videotuner-Pin kann z. B. mit einem Audiotuner-Pin verknüpft sein. Verwandte Pins haben die gleiche Pinrichtung und sind in der Regel Teil derselben physischen Buchse oder Verbindung auf der Karte.

  • Rufen Sie die IAMCrossbar::CanRoute-Methode auf, um zu bestimmen, ob Sie einen Eingabepin an einen bestimmten Ausgabepin weiterleiten können.

  • Um das aktuelle Routing zwischen Pins zu bestimmen, rufen Sie die IAMCrossbar::get_IsRoutedTo-Methode auf.

Die vorherigen Methoden geben alle Pins nach Indexnummer an, wobei Ausgabe- und Eingabepins beide von null indiziert sind. Rufen Sie die IAMCrossbar::get_PinCounts-Methode auf, um die Anzahl der Pins im Filter zu ermitteln.

Der folgende Code zeigt z. B. Informationen zu einem Querleistenfilter im Konsolenfenster an:

// Helper function to associate a name with the type.
const char * GetPhysicalPinName(long lType)
{
    switch (lType) 
    {
    case PhysConn_Video_Tuner:            return "Video Tuner";
    case PhysConn_Video_Composite:        return "Video Composite";
    case PhysConn_Video_SVideo:           return "S-Video";
    case PhysConn_Video_RGB:              return "Video RGB";
    case PhysConn_Video_YRYBY:            return "Video YRYBY";
    case PhysConn_Video_SerialDigital:    return "Video Serial Digital";
    case PhysConn_Video_ParallelDigital:  return "Video Parallel Digital"; 
    case PhysConn_Video_SCSI:             return "Video SCSI";
    case PhysConn_Video_AUX:              return "Video AUX";
    case PhysConn_Video_1394:             return "Video 1394";
    case PhysConn_Video_USB:              return "Video USB";
    case PhysConn_Video_VideoDecoder:     return "Video Decoder";
    case PhysConn_Video_VideoEncoder:     return "Video Encoder";
        
    case PhysConn_Audio_Tuner:            return "Audio Tuner";
    case PhysConn_Audio_Line:             return "Audio Line";
    case PhysConn_Audio_Mic:              return "Audio Microphone";
    case PhysConn_Audio_AESDigital:       return "Audio AES/EBU Digital";
    case PhysConn_Audio_SPDIFDigital:     return "Audio S/PDIF";
    case PhysConn_Audio_SCSI:             return "Audio SCSI";
    case PhysConn_Audio_AUX:              return "Audio AUX";
    case PhysConn_Audio_1394:             return "Audio 1394";
    case PhysConn_Audio_USB:              return "Audio USB";
    case PhysConn_Audio_AudioDecoder:     return "Audio Decoder";
        
    default:                              return "Unknown Type";
    }    
}

void DisplayCrossbarInfo(IAMCrossbar *pXBar)
{
    HRESULT hr;
    long cOutput = -1, cInput = -1;
    hr = pXBar->get_PinCounts(&cOutput, &cInput);

    for (long i = 0; i < cOutput; i++)
    {
        long lRelated = -1, lType = -1, lRouted = -1;

        hr = pXBar->get_CrossbarPinInfo(FALSE, i, &lRelated, &lType);
        hr = pXBar->get_IsRouted(i, &lRouted);

        printf("Output pin %d: %s\n", i, GetPhysicalPinName(lType));
        printf("\tRelated out: %d, Routed in: %d\n", lRelated, lRouted);
        printf("\tSwitching Matrix: ");

        for (long j = 0; j < cInput; j++)
        {
            hr = pXBar->CanRoute(i, j);
            printf("%d-%s", j, (S_OK == hr ? "Yes" : "No"));
        }
        printf("\n\n");
    }

    for (i = 0; i < cInput; i++)
    {
        long lRelated = -1, lType = -1;

        hr = pXBar->get_CrossbarPinInfo(TRUE, i, &lRelated, &lType);

        printf("Input pin %d - %s\n", i, GetPhysicalPinName(lType));
        printf("\tRelated in: %d\n", lRelated);
    }
}

Für eine hypothetische Karte kann diese Funktion die folgende Ausgabe erzeugen:

Output pin 0: S-Video
    Related out: 2, Routed in: 0
    Switching Matrix: 0-Yes 1-No 2-No 3-No
Output pin 1 - Video Tuner
    Related out: 2, Routed in: 1
    Switching Matrix: 0-No 1-Yes 2-No 3-No
Output pin 2 - Audio decoder
    Related out: 1, Routed in: -1
    Switching Matrix: 0-No 1-No 2-Yes 3-Yes

Input pin 0 - S-Video
    Related in: 2
Input pin 1 - Video Tuner
    Related in: 3
Input pin 2 - Audio line
    Related in: 0
Input pin 3 - Audio tuner
    Related in: 1

Auf der Ausgabeseite beziehen sich der S-Video und der Videotuner beide auf den Audiodecoder. Auf der Eingabeseite bezieht sich der Videotuner auf den Audiotuner, und der S-Video bezieht sich auf die Audiozeile in. Der S-Video-Eingang wird an die S-Video-Ausgabe weitergeleitet. und die Videotunereingabe wird an die Ausgabe des Videotuners weitergeleitet. Derzeit wird nichts an den Audiodecoder weitergeleitet, aber entweder die Audiozeile in oder der Audiotuner kann an ihn weitergeleitet werden.

Sie können das vorhandene Routing ändern, indem Sie die IAMCrossbar::Route-Methode aufrufen.