Partilhar via


Trabalhando com barras cruzadas

[O recurso associado a esta página, DirectShow, é um recurso herdado. Foi substituído por MediaPlayer, IMFMediaEnginee Audio/Video Capture in Media Foundation. Esses recursos foram otimizados para Windows 10 e Windows 11. A Microsoft recomenda vivamente que o novo código utilize MediaPlayer, IMFMediaEngine e Captura de Áudio/Vídeo no Media Foundation em vez de DirectShow, quando possível. A Microsoft sugere que o código existente que usa as APIs herdadas seja reescrito para usar as novas APIs, se possível.]

Se uma placa de captura de vídeo tiver mais de uma entrada física ou suportar mais de um caminho de hardware para dados, o gráfico de filtro poderá conter o Analog Video Crossbar Filter. O Capture Graph Builder adiciona automaticamente esse filtro quando necessário; ele estará a montante do filtro de captura. Dependendo do hardware, o gráfico de filtro pode conter mais de uma instância do filtro de barra transversal.

O filtro crossbar expõe a interface IAMCrossbar, que pode ser utilizada para rotear uma entrada específica para uma saída específica. Por exemplo, uma placa de vídeo pode ter um conector coaxial e uma entrada S-Video. Estes seriam representados como pinos de entrada no filtro da barra transversal. Para selecionar uma entrada, roteie o pino de entrada correspondente para o pino de saída da barra transversal, usando o método IAMCrossbar::Route.

Para localizar filtros de barra transversal no gráfico, você pode usar o ICaptureGraphBuilder2::FindInterface método para procurar filtros que suportam IAMCrossbar. Por exemplo, o código a seguir procura duas barras cruzadas:

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

Para obter uma abordagem mais generalizada, consulte a classe CCrossbar no AmCap Sample.

Depois de ter um ponteiro para a interface IAMCrossbar, pode-se obter informações sobre o filtro crossbar, incluindo o tipo físico de cada pino e a matriz de quais pinos de entrada podem ser roteados para quais pinos de saída.

  • Para determinar o tipo de conector físico ao qual corresponde um pino, chame o método IAMCrossbar::get_CrossbarPinInfo. O método retorna um membro da enumeraçãoPhysicalConnectorType. Por exemplo, um pino S-Video retorna o valor PhysConn_Video_SVideo.

    O método get_CrossbarInfo também indica se dois pinos estão relacionados entre si. Por exemplo, um pino do sintonizador de vídeo pode estar relacionado a um pino do sintonizador de áudio. Os pinos relacionados têm a mesma direção de pino e normalmente fazem parte da mesma tomada física ou conector na placa.

  • Para determinar se você pode rotear um pino de entrada para um pino de saída específico, chame o IAMCrossbar::CanRoute método.

  • Para determinar o roteamento atual entre pinos, chame o método IAMCrossbar::get_IsRoutedTo.

Todos os métodos anteriores especificam pinos por número de índice, com pinos de saída e pinos de entrada ambos indexados a partir de zero. Chame o método IAMCrossbar::get_PinCounts para encontrar o número de pinos no filtro.

Por exemplo, o código a seguir exibe informações sobre um filtro de barra transversal na janela do 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);
    }
}

Para uma placa hipotética, esta função pode produzir a seguinte saída:

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

No lado da saída, o S-Video e o sintonizador de vídeo estão ambos relacionados com o descodificador de áudio. No lado da entrada, o sintonizador de vídeo está relacionado com o sintonizador de áudio e o S-Video está relacionado com a entrada da linha de áudio. A entrada S-Video é roteada para a saída S-Video; e a entrada do sintonizador de vídeo é encaminhada para a saída do sintonizador de vídeo. Atualmente, nada é encaminhado para o decodificador de áudio, mas tanto a linha de áudio quanto o sintonizador de áudio podem ser encaminhados para o mesmo.

Você pode alterar o roteamento existente chamando o IAMCrossbar::Route método.