Localizar um pino não conectado em um filtro

[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.]

Este tópico descreve como encontrar um pino não conectado em um filtro. Localizar um pino não conectado é útil quando você está conectando filtros.

Em um cenário típico de criação de grafo do DirectShow, você precisa de um pino não conectado que corresponda a uma direção de pino específica (entrada ou saída). Por exemplo, ao conectar dois filtros, você conecta um pino de saída de um filtro a um pino de entrada do outro filtro. Ambos os pinos devem ser desconectados antes de conectá-los.

Primeiro, precisamos de uma função que teste se um pino está conectado a outro pino. Essa função chama o método IPin::ConnectedTo para testar se o pino está conectado a outro pino.

// Query whether a pin is connected to another pin.
//
// Note: This function does not return a pointer to the connected pin.

HRESULT IsPinConnected(IPin *pPin, BOOL *pResult)
{
    IPin *pTmp = NULL;
    HRESULT hr = pPin->ConnectedTo(&pTmp);
    if (SUCCEEDED(hr))
    {
        *pResult = TRUE;
    }
    else if (hr == VFW_E_NOT_CONNECTED)
    {
        // The pin is not connected. This is not an error for our purposes.
        *pResult = FALSE;
        hr = S_OK;
    }

    SafeRelease(&pTmp);
    return hr;
}

Observação

Este exemplo usa a função SafeRelease para liberar ponteiros de interface.

 

Em seguida, precisamos de uma função que teste se um pino corresponde a uma direção de pino especificada. Essa função chama o método IPin::QueryDirection para obter a direção do pino.

// Query whether a pin has a specified direction (input / output)
HRESULT IsPinDirection(IPin *pPin, PIN_DIRECTION dir, BOOL *pResult)
{
    PIN_DIRECTION pinDir;
    HRESULT hr = pPin->QueryDirection(&pinDir);
    if (SUCCEEDED(hr))
    {
        *pResult = (pinDir == dir);
    }
    return hr;
}

A próxima função corresponde a um pino por ambos os critérios (direção do pino e status de conexão).

// Match a pin by pin direction and connection state.
HRESULT MatchPin(IPin *pPin, PIN_DIRECTION direction, BOOL bShouldBeConnected, BOOL *pResult)
{
    assert(pResult != NULL);

    BOOL bMatch = FALSE;
    BOOL bIsConnected = FALSE;

    HRESULT hr = IsPinConnected(pPin, &bIsConnected);
    if (SUCCEEDED(hr))
    {
        if (bIsConnected == bShouldBeConnected)
        {
            hr = IsPinDirection(pPin, direction, &bMatch);
        }
    }

    if (SUCCEEDED(hr))
    {
        *pResult = bMatch;
    }
    return hr;
}

Por fim, a função a seguir usa a interface IEnumPins para executar um loop pelos pinos no filtro. O chamador especifica a direção do pino desejada. Para cada pino, a função chama MatchPin para testar se o pino é uma correspondência. Se a direção corresponder e o pino não estiver conectado, a função retornará um ponteiro para o pino correspondente no parâmetro ppPin .

// Return the first unconnected input pin or output pin.
HRESULT FindUnconnectedPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin)
{
    IEnumPins *pEnum = NULL;
    IPin *pPin = NULL;
    BOOL bFound = FALSE;

    HRESULT hr = pFilter->EnumPins(&pEnum);
    if (FAILED(hr))
    {
        goto done;
    }

    while (S_OK == pEnum->Next(1, &pPin, NULL))
    {
        hr = MatchPin(pPin, PinDir, FALSE, &bFound);
        if (FAILED(hr))
        {
            goto done;
        }
        if (bFound)
        {
            *ppPin = pPin;
            (*ppPin)->AddRef();
            break;
        }
        SafeRelease(&pPin);
    }

    if (!bFound)
    {
        hr = VFW_E_NOT_FOUND;
    }

done:
    SafeRelease(&pPin);
    SafeRelease(&pEnum);
    return hr;
}

Para obter um exemplo de como essa função pode ser usada, consulte Conectar dois filtros.

Enumerando pinos

Técnicas gerais de Graph-Building

ICaptureGraphBuilder2::FindPin