Uso delle barre incrociate

[La funzionalità associata a questa pagina, DirectShow, è una funzionalità legacy. È stata sostituita da MediaPlayer, FMMediaEngine e Audio/Video Capture in Media Foundation. Queste funzionalità sono state ottimizzate per Windows 10 e Windows 11. Microsoft consiglia vivamente che il nuovo codice usi MediaPlayer, FMMediaEngine e Audio/Video Capture in Media Foundation anziché DirectShow, quando possibile. Microsoft suggerisce che il codice esistente che usa le API legacy venga riscritto per usare le nuove API, se possibile.

Se una scheda di acquisizione video ha più di un input fisico o supporta più di un percorso hardware per i dati, il grafico del filtro può contenere il filtro incrociato video analogico. Capture Graph Builder aggiunge automaticamente questo filtro quando necessario; sarà a monte dal filtro di acquisizione. A seconda dell'hardware, il grafico del filtro potrebbe contenere più di un'istanza del filtro a barra incrociata.

Il filtro incrociato espone l'interfaccia IAMCrossbar , che è possibile usare per instradare un determinato input a un determinato output. Ad esempio, una scheda video potrebbe avere un connettore coaxiale e un input S-Video. Questi elementi verranno rappresentati come pin di input sul filtro a barra incrociata. Per selezionare un input, instradare il pin di input corrispondente al pin di output della barra incrociata usando il metodo IAMCrossbar::Route .

Per individuare i filtri a barra incrociata nel grafico, è possibile usare il metodo ICaptureGraphBuilder2::FindInterface per cercare filtri che supportano IAMCrossbar. Ad esempio, il codice seguente cerca due barre incrociate:

// 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();
}

Per un approccio più generalizzato, vedere la classe CCrossbar nell'esempio AmCap.

Dopo avere un puntatore all'interfaccia IAMCrossbar , è possibile ottenere informazioni sul filtro a barra incrociata, incluso il tipo fisico di ogni pin e la matrice di cui è possibile indirizzare i pin di input a quali pin di output.

  • Per determinare il tipo di connettore fisico a cui corrisponde un pin, chiamare il metodo IAMCrossbar::get_CrossbarPinInfo . Il metodo restituisce un membro dell'enumerazione PhysicalConnectorType . Ad esempio, un pin S-Video restituisce il valore PhysConn_Video_SVideo.

    Il metodo get_CrossbarInfo indica anche se due pin sono correlati tra loro. Ad esempio, un pin di tuner video potrebbe essere correlato a un pin di tuner audio. I pin correlati hanno la stessa direzione del pin e in genere fanno parte dello stesso jack fisico o connettore sulla scheda.

  • Per determinare se è possibile instradare un pin di input a un pin di output specifico, chiamare il metodo IAMCrossbar::CanRoute .

  • Per determinare il routing corrente tra i pin, chiamare il metodo IAMCrossbar::get_IsRoutedTo .

I metodi precedenti specificano tutti i pin in base al numero di indice, con pin di output e pin di input sia indicizzati da zero. Chiamare il metodo IAMCrossbar::get_PinCounts per trovare il numero di pin nel filtro.

Ad esempio, il codice seguente visualizza informazioni su un filtro a barra incrociata nella finestra della console:

// 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);
    }
}

Per una scheda ipotetica, questa funzione potrebbe produrre l'output seguente:

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

Sul lato output, il tuner S-Video e il tuner video sono entrambi correlati al decodificatore audio. Sul lato input, il tuner video è correlato al tuner audio e il S-Video è correlato alla linea audio in. L'input S-Video viene instradato all'output S-Video; e l'input del tuner video viene instradato all'output del tuner video. Attualmente non viene instradato nulla al decodificatore audio, ma la linea audio in o il tuner audio potrebbe essere instradato a esso.

È possibile modificare il routing esistente chiamando il metodo IAMCrossbar::Route .