Не удается найти пин-код в фильтре DirectShow по имени / идентификатору, несмотря на то, что это идентификатор, возвращаемый QueryPinInfo

У меня странная проблема при разработке приложения DirectShow. Я использую Delphi 6 с библиотекой компонентов DSPACK DirectShow. Один из экземпляров IBaseFilter, похоже, не распознает принадлежащий ему вывод, когда я пытаюсь найти вывод в фильтре, используя его свойство TPinInfo.achName (_PinInfo). (Обратите внимание, что в этом случае именно IBaseFilter, созданный компонентом TSampleGrabber, демонстрирует это странное поведение).

Последовательность событий, инкапсулированная в следующем примере кода:

  1. Найдите первый доступный входной контакт в экземпляре IBaseFilter. В приведенном ниже коде это пин, переданный в testPinInfo().
  2. Выполните QueryPinInfo() на возвращенном выводе, чтобы получить эту информацию. В возвращенной информации ах-имя пина отображается как "Вход".
  3. Попробуйте найти пин-код "Input" в том же экземпляре IBaseFilter, используя IBaseFilter.findPin().
  4. Верните NIL, указывая, что не удалось найти пин-код с таким именем. Это, на мой взгляд, действительно странное условие (ошибка).

Кто-нибудь знает, какие условия могут вызвать этот сценарий? Я не думаю, что это проблема повреждения памяти, потому что структуры данных выглядят хорошо, когда я проверяю их в отладчике. Возможно ли, что некоторые реализации IBaseFilter пренебрегают для правильной реализации метода FindPin()?

Вот код ниже:

procedure testPinInfo(intfInputPin: IPin);
var
    intfTestPin: IPin;
    pinInfo_input: TPinInfo;
begin
    intfTestPin := nil;

    // Get the pin information.
    ZeroMemory(@pinInfo_input, SizeOf(pinInfo_input));
    intfInputPin.QueryPinInfo(pinInfo_input);

    // Now immediately turn around and try to find the pin in the filter that
    //  owns it, using the name found in pinInfo_input
    pinInfo_input.pFilter.FindPin(pinInfo_input.achName, intfTestPin);

   // >>> intfTestPin is NIL (unassigned).  This is an error.
end;

3 ответа

Решение

Не использовать FindPinУ вас всегда есть лучшие способы сделать это. Ищите неподключенный штифт нужного направления с интересующим вас типом носителя. Если вы ищете специально для предварительного просмотра / захвата булавки, у вас всегда есть возможность использовать IKsPropertySet Интерфейс для однозначного определения необходимых контактов.

У меня была похожая проблема, поэтому я сделал свою собственную версию FindPin:

HRESULT GraphControl::FindPinByName(IBaseFilter* pFilter,LPCWSTR pName,IPin** ppPin)
{
    HRESULT hr = E_FAIL;
    IEnumPins* pEnum = NULL;
    IPin* pPin = NULL;
    DWORD pFetched = 0;
    PIN_INFO pinInfo = {0};

    // Create a pin enumerator
    if(FAILED(pFilter->EnumPins(&pEnum)))
        return E_FAIL;


    // Get the first instance
    hr = pEnum->Next(1,&pPin,&pFetched);

    while( hr == S_OK )
    { 
    pPin->QueryPinInfo(&pinInfo);
    // Compare the names
    if (wcscmp(pName,pinInfo.achName) == 0 )
    {
        // pin names match so use this one and exit
        *ppPin = pPin;
        break;
    }
    SAFE_RELEASE(pinInfo.pFilter);
    SAFE_RELEASE(pPin);

    hr = pEnum->Next(1,&pPin,&pFetched);
    }

    SAFE_RELEASE(pinInfo.pFilter);
    SAFE_RELEASE(pEnum);

    // if the pPin address is null we didnt find a pin with the wanted name
    if(&*pPin == NULL)
        hr = VFW_E_NOT_FOUND;

    return hr;
}

Для FindPin вам нужен соответствующий Id, проверьте QueryId(). Для ввода это обычно "В".

Другие вопросы по тегам