Working with Pin Categories

 
Microsoft DirectShow 9.0

Working with Pin Categories

To search on a filter for a pin with a given pin category, you can use the ICaptureGraphBuilder2::FindPin method. The following example searches for a video preview pin:

int i = 0;
hr = pBuild->FindPin(
    pFilter,               // Pointer to a filter to search.
    PINDIR_OUTPUT,         // Which pin direction?
    &PIN_CATEGORY_PREVIEW, // Which category? (NULL means "any category")
    &MEDIATYPE_Video,      // What media type? (NULL means "any type")
    FALSE,                 // Must be connected?
    i,                     // Get the i'th matching pin (0 = first match)
    &pPin                  // Receives a pointer to the pin.
);

The first parameter is a pointer to the filter's IBaseFilter interface. The next three parameters specify the direction, pin category, and media type. The value FALSE in the fifth parameter indicates that the pin can be either connected or unconnected. (For the exact definitions of these parameters, refer to the documentation for the method.) If the method finds a matching pin, it returns a pointer to the IPin interface in the pPin parameter.

Although the FindPin method is convenient, you can also write your own helper functions if you prefer. To determine a pin's category, call the IKsPropertySet::Get method as described in the topic Pin Property Set.

The following code shows a helper function that checks whether a pin matches a specified category:

BOOL PinMatchesCategory(IPin *pPin, const GUID& Category)
{
    if (pPin == NULL) return E_POINTER;

    BOOL bFound = FALSE;
    IKsPropertySet *pKs;
    HRESULT hr = pPin->QueryInterface(IID_IKsPropertySet, (void **)&pKs);
    if (SUCCEEDED(hr))
    {
        GUID PinCategory;
        DWORD cbReturned;
        hr = pKs->Get(AMPROPSETID_Pin, AMPROPERTY_PIN_CATEGORY, NULL, 0, 
            &PinCategory, sizeof(GUID), &cbReturned);
        if (SUCCEEDED(hr))
        {
            bFound = (PinCategory == Category);
        }
        pKs->Release();
    }
    return bFound;
}

The next example is a function that searches for a pin by category, similar to the FindPin method:

HRESULT FindPinByCategory(
    IBaseFilter *pF,      // Pointer to the filter to search.
    PIN_DIRECTION PinDir, // Direction of the pin.
    const GUID& Category, // Pin category.
    IPin **ppPin)         // Receives a pointer to the pin.
{
    if (!pF || !ppPin) return E_POINTER;

    *ppPin = 0;
    HRESULT hr;
    IEnumPins *pEnum = 0;
    if (SUCCEEDED(pF->EnumPins(&pEnum)))
    {
        IPin *pPin = 0;
        while (hr = pEnum->Next(1, &pPin, 0), hr == S_OK)
        {
            PIN_DIRECTION ThisPinDir;
            hr = pPin->QueryDirection(&ThisPinDir);
            if (FAILED(hr))
            {
                pPin->Release();
                pEnum->Release();
                return E_UNEXPECTED; // Something strange happened.
            }
            if ((ThisPinDir == PinDir) && 
                PinMatchesCategory(pPin, Category))
            {
                *ppPin = pPin;  // Caller must release the interface.
                pEnum->Release();
                return S_OK;
            }
            pPin->Release();
        }
        pEnum->Release();
    }
    // No pin matches.
    return E_FAIL;
}

The following code uses the previous function to search for a video port pin on a filter:

IPin *pVP; 
hr = FindPinByCategory(pFilter, PINDIR_OUTPUT, 
    PIN_CATEGORY_VIDEOPORT, &pVP);
if (SUCCEEDED(hr))
{
    // Use pVP ... 
    // Release when you are done.
    pVP->Release();
}

For more information about property sets, refer to the Microsoft® Windows® Driver Development Kit (DDK) documentation.

See Also