Fornire un allocatore personalizzato

[La funzionalità associata a questa pagina, DirectShow, è una funzionalità legacy. È stata sostituita da MediaPlayer, FMMediaEngine e Audio/Video Capture in Media Foundation. Queste funzionalità sono state ottimizzate per Windows 10 e Windows 11. Microsoft consiglia vivamente che il nuovo codice usi MediaPlayer, FMMediaEngine e Audio/Video Capture in Media Foundation anziché DirectShow, quando possibile. Microsoft suggerisce che il codice esistente che usa le API legacy venga riscritto per usare le nuove API, se possibile.

Questa sezione descrive come fornire un allocatore personalizzato per un filtro. Vengono descritte solo le connessioni IMemInputPin , ma i passaggi per una connessione IAsyncReader sono simili.

Definire prima di tutto una classe C++ per l'allocatore. L'allocatore può derivare da una delle classi allocator standard, CBaseAllocator o CMemAllocator oppure è possibile creare una classe allocator completamente nuova. Se si crea una nuova classe, deve esporre l'interfaccia IMemAllocator .

I passaggi rimanenti dipendono dal fatto che l'allocatore appartenga a un pin di input o a un pin di output sul filtro. I pin di input svolgono un ruolo diverso rispetto ai pin di output durante la fase di negoziazione dell'allocatore, perché il pin di output seleziona infine l'allocatore.

Specificare un allocatore personalizzato per un pin di input

Per fornire un allocatore per un pin di input, eseguire l'override del metodo CBaseInputPin::GetAllocator . All'interno di questo metodo, controllare la variabile membro m_pAllocator . Se questa variabile non è NULL, significa che l'allocatore è già stato selezionato per questa connessione, quindi il metodo GetAllocator deve restituire un puntatore a tale allocatore. Se m_pAllocator è NULL, significa che l'allocatore non è stato selezionato, quindi il metodo GetAllocator deve restituire un puntatore all'allocatore preferito del pin di input. In tal caso, creare un'istanza dell'allocatore personalizzato e restituire il puntatore IMemAllocator . Il codice seguente illustra come implementare il metodo GetAllocator :

STDMETHODIMP CMyInputPin::GetAllocator(IMemAllocator **ppAllocator)
{
    CheckPointer(ppAllocator, E_POINTER);
    if (m_pAllocator)  
    {
        // We already have an allocator, so return that one.
        *ppAllocator = m_pAllocator;
        (*ppAllocator)->AddRef();
        return S_OK;
    }

    // No allocator yet, so propose our custom allocator. The exact code
    // here will depend on your custom allocator class definition.
    HRESULT hr = S_OK;
    CMyAllocator *pAlloc = new CMyAllocator(&hr);
    if (!pAlloc)
    {
        return E_OUTOFMEMORY;
    }
    if (FAILED(hr))
    {
        delete pAlloc;
        return hr;
    }

    // Return the IMemAllocator interface to the caller.
    return pAlloc->QueryInterface(IID_IMemAllocator, (void**)ppAllocator);
}

Quando il filtro upstream seleziona un allocatore, chiama il metodo IMemInputPin::NotifyAllocator del pin di input. Eseguire l'override del metodo CBaseInputPin::NotifyAllocator per controllare le proprietà dell'allocatore. In alcuni casi, il pin di input potrebbe rifiutare l'allocatore se non è l'allocatore personalizzato, anche se ciò potrebbe causare l'errore dell'intera connessione pin.

Fornire un allocatore personalizzato per un pin di output

Per fornire un allocatore per un pin di output, eseguire l'override del metodo CBaseOutputPin::InitAllocator per creare un'istanza dell'allocatore:

HRESULT MyOutputPin::InitAllocator(IMemAllocator **ppAllocator)
{
    HRESULT hr = S_OK;
    CMyAllocator *pAlloc = new CMyAllocator(&hr);
    if (!pAlloc)
    {
        return E_OUTOFMEMORY;
    }

    if (FAILED(hr))
    {
        delete pAlloc;
        return hr;
    }

    // Return the IMemAllocator interface.
    return pAlloc->QueryInterface(IID_IMemAllocator, (void**)ppAllocator);
}

Per impostazione predefinita, la classe CBaseOutputPin richiede prima un allocatore dal pin di input. Se tale allocatore non è adatto, il pin di output crea un proprio allocatore. Per forzare la connessione a usare l'allocatore personalizzato, eseguire l'override del metodo CBaseOutputPin::D ecideAllocator . Tuttavia, tenere presente che questo può impedire al pin di output di connettersi con determinati filtri, perché l'altro filtro può richiedere anche un proprio allocatore personalizzato. Una terza opzione consiste nell'cambiare l'ordine: provare prima l'allocatore personalizzato e quindi tornare all'allocatore dell'altro filtro.

Negoziazione di allocatori