Поделиться через


Поиск несоединенного контакта в фильтре

[Функция, связанная с этой страницей DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngine, и аудио/ видео захвата в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует использовать в новом коде MediaPlayer, IMFMediaEngine и аудио/видеозахват в Media Foundation вместо DirectShow, когда это возможно. Корпорация Майкрософт предлагает переписать существующий код, в котором используются устаревшие API, чтобы по возможности использовать новые API.]

В этом разделе описывается, как найти несоединенные контакты на фильтре. Поиск неподключенного контакта полезен при подключении фильтров.

В типичном сценарии построения графа DirectShow требуется несоединяемый контакт, соответствующий определенному направлению закрепления (входные или выходные данные). Например, при подключении двух фильтров вы подключаете выходной контакт из одного фильтра к входному контакту из другого фильтра. Оба контакта должны быть разъедины перед их подключением.

Во-первых, нам нужна функция, которая проверяет, подключен ли контакт к другому контакту. Эта функция вызывает метод IPin::ConnectedTo , чтобы проверить, подключен ли контакт к другому контакту.

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

Примечание

В этом примере функция SafeRelease используется для освобождения указателей интерфейса.

 

Далее нам нужна функция, которая проверяет, соответствует ли закрепление указанному направлению. Эта функция вызывает метод IPin::QueryDirection для получения направления закрепления.

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

Следующая функция соответствует закреплению по обоим критериям (направление закрепления и состояние соединения).

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

Наконец, следующая функция использует интерфейс IEnumPins для циклического перекрестия контактов на фильтре. Вызывающий объект задает нужное направление закрепления. Для каждого контакта функция вызывает MatchPin , чтобы проверить, соответствует ли закрепление. Если направление совпадает, а контакт не подключен, функция возвращает указатель на соответствующий контакт в параметре 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;
}

Пример использования этой функции см. в разделе Подключение двух фильтров.

Перечисление закрепления

Общие методы Graph-Building

ICaptureGraphBuilder2::FindPin