Visualizando áudio de TV

[O recurso associado a esta página, DirectShow, é um recurso herdado. Foi substituído por MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation. Esses recursos foram otimizados para Windows 10 e Windows 11. A Microsoft recomenda fortemente que o novo código use MediaPlayer, IMFMediaEngine e Audio/Video Capture in 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.]

Para visualizar o áudio de TV, encaminhe o pino do Decodificador de Áudio no filtro da barra cruzada para o pino do Sintonizador de Áudio. Para ativar o mudo do áudio, encaminhe o pino do Decodificador de Áudio para -1, conforme mostrado no diagrama a seguir. (Filtros de barra cruzada são descritos em Trabalhando com barras cruzadas.)

roteando o pino do decodificador de áudio

A abordagem básica é a seguinte:

  1. Use o método ICaptureGraphBuilder2::FindInterface para localizar o filtro de barra cruzada.
  2. Use o método IAMCrossbar::get_CrossbarPinInfo para enumerar os pinos de entrada e saída do filtro de barra cruzada. Pesquise um pino de saída do decodificador de áudio e um pino de entrada do sintonizador de áudio.
  3. Se você encontrar os pinos corretos, chame IAMCrossbar::Route para rotear os pinos. Caso contrário, procure upstream outra barra cruzada e repita o processo.
  4. Para ativar o mudo do áudio, encaminhe o pino do decodificador de áudio para -1.

A maioria dos sintonizadores de TV usa um único filtro de barra cruzada, mas alguns usam dois filtros de barra cruzada. Portanto, talvez seja necessário pesquisar uma segunda barra cruzada se a primeira falhar.

Observação

Ao contrário do que você pode esperar, nenhum filtro de captura de áudio ou renderizador de áudio é necessário para visualizar o áudio, pois há uma conexão física entre o sintonizador cartão e o som cartão.

 

O código a seguir mostra essas etapas com mais detalhes. Primeiro, aqui está uma função auxiliar que pesquisa um filtro de barra cruzada para um tipo de pino especificado:

HRESULT FindCrossbarPin(
    IAMCrossbar *pXBar,                 // Pointer to the crossbar.
    PhysicalConnectorType PhysicalType, // Pin type to match.
    PIN_DIRECTION Dir,                  // Pin direction.
    long *pIndex)       // Receives the index of the pin, if found.
{
    BOOL bInput = (Dir == PINDIR_INPUT ? TRUE : FALSE);

    // Find out how many pins the crossbar has.
    long cOut, cIn;
    HRESULT hr = pXBar->get_PinCounts(&cOut, &cIn);
    if (FAILED(hr)) return hr;
    // Enumerate pins and look for a matching pin.
    long count = (bInput ? cIn : cOut);
    for (long i = 0; i < count; i++)
    {
        long iRelated = 0;
        long ThisPhysicalType = 0;
        hr = pXBar->get_CrossbarPinInfo(bInput, i, &iRelated,
            &ThisPhysicalType);
        if (SUCCEEDED(hr) && ThisPhysicalType == PhysicalType)
        {
            // Found a match, return the index.
            *pIndex = i;
            return S_OK;
        }
    }
    // Did not find a matching pin.
    return E_FAIL;
}

A próxima função tenta ativar ou silenciar o áudio, dependendo do valor do parâmetro bActivate . Ele pesquisa o filtro de barra cruzada especificado para os pinos necessários. Se ele não conseguir encontrá-los, retornará um código de erro.

HRESULT ConnectAudio(IAMCrossbar *pXBar, BOOL bActivate)
{
    // Look for the Audio Decoder output pin.
    long i = 0;
    HRESULT hr = FindCrossbarPin(pXBar, PhysConn_Audio_AudioDecoder,
        PINDIR_OUTPUT, &i);
    if (SUCCEEDED(hr))
    {
        if (bActivate)  // Activate the audio. 
        {
            // Look for the Audio Tuner input pin.
            long j = 0;
            hr = FindCrossbarPin(pXBar, PhysConn_Audio_Tuner, 
                PINDIR_INPUT, &j);
            if (SUCCEEDED(hr))
            {
                return pXBar->Route(i, j);
            }
        }
        else  // Mute the audio
        {
            return pXBar->Route(i, -1);
        }
    }
    return E_FAIL;
}

A próxima função pesquisa no grafo de filtro um filtro de barra cruzada. Se encontrar um, ele tentará ativar ou silenciar o áudio (usando a função anterior). Se essa operação falhar, o método pesquisa upstream uma segunda barra cruzada e tenta novamente. Para obter uma abordagem mais generalizada para gerenciar vários filtros de barra cruzada em um grafo, consulte a classe CCrossbar no aplicativo de exemplo AmCap.

HRESULT ActivateAudio(ICaptureGraphBuilder2 *pBuild, IBaseFilter *pSrc,
  BOOL bActivate)
{
    // Search upstream for a crossbar.
    IAMCrossbar *pXBar1 = NULL;
    HRESULT hr = pBuild->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, pSrc,
        IID_IAMCrossbar, (void**)&pXBar1);
    if (SUCCEEDED(hr)) 
    {
        hr = ConnectAudio(pXBar1, bActivate);
        if (FAILED(hr))
        {
            // Look for another crossbar.
            IBaseFilter *pF = NULL;
            hr = pXBar1->QueryInterface(IID_IBaseFilter, (void**)&pF);
            if (SUCCEEDED(hr)) 
            {
                // Search upstream for another one.
                IAMCrossbar *pXBar2 = NULL;
                hr = pBuild->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, pF,
                    IID_IAMCrossbar, (void**)&pXBar2);
                pF->Release();
                if (SUCCEEDED(hr))
                {
                    hr = ConnectAudio(pXBar2, bActivate);
                    pXBar2->Release();
                }
            }
        }
        pXBar1->Release();
    }
    return hr;
}

O código a seguir mostra como chamar essas funções:

// Build the analog TV graph (not shown).
// Activate the audio.
hr = ActivateAudio(pBuild, pCap, TRUE);
// Later, mute the audio.
hr = ActivateAudio(pBuild, pCap, FALSE);

Observe que essas funções de exemplo repetem muitas das mesmas chamadas de função. Por exemplo, eles enumeram os pinos da barra cruzada a cada vez. Em um aplicativo real, você pode armazenar em cache algumas dessas informações.

Áudio analógico de televisão

Trabalhando com barras cruzadas