Share via


Passaggio 4. Impostare le proprietà dell'allocatore

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

Questo è il passaggio 4 dell'esercitazione Scrittura di filtri di trasformazione.

Nota

Questo passaggio non è necessario per i filtri che derivano da CTransInPlaceFilter.

 

Dopo due pin accettano un tipo di supporto, selezionano un allocatore per la connessione e negoziano le proprietà dell'allocatore, ad esempio le dimensioni del buffer e il numero di buffer.

Nella classe CTransformFilter sono presenti due allocatori, uno per la connessione pin upstream e uno per la connessione pin downstream. Il filtro upstream seleziona l'allocatore upstream e sceglie anche le proprietà dell'allocatore. Il pin di input accetta qualsiasi decisione del filtro upstream. Se è necessario modificare questo comportamento, eseguire l'override del metodo CBaseInputPin::NotifyAllocator .

Il pin di output del filtro di trasformazione seleziona l'allocatore downstream. Esegue i passaggi seguenti:

  1. Se il filtro downstream può fornire un allocatore, il pin di output usa quello. In caso contrario, il pin di output crea un nuovo allocatore.
  2. Il pin di output ottiene i requisiti dell'allocatore del filtro downstream (se presente) chiamando IMemInputPin::GetAllocatorRequirements.
  3. Il pin di output chiama il metodo CTransformFilter del filtro di trasformazione::D ecideBufferSize , che è virtuale puro. I parametri di questo metodo sono un puntatore all'allocatore e una struttura ALLOCATOR_PROPERTIES con i requisiti del filtro downstream. Se il filtro downstream non ha requisiti di allocatore, la struttura viene zero.
  4. Nel metodo DecideBufferSize la classe derivata imposta le proprietà dell'allocatore chiamando IMemAllocator::SetProperties.

In genere, la classe derivata selezionerà le proprietà dell'allocatore in base al formato di output, ai requisiti del filtro downstream e ai propri requisiti del filtro. Provare a selezionare le proprietà compatibili con la richiesta del filtro downstream. In caso contrario, il filtro downstream potrebbe rifiutare la connessione.

Nell'esempio seguente il codificatore RLE imposta valori minimi per le dimensioni del buffer, l'allineamento del buffer e il numero di buffer. Per il prefisso, usa qualsiasi valore richiesto dal filtro downstream. Il prefisso è in genere zero byte, ma alcuni filtri lo richiedono. Ad esempio, il filtro AVI Mux usa il prefisso per scrivere intestazioni RIFF.

HRESULT CRleFilter::DecideBufferSize(
    IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProp)
{
    AM_MEDIA_TYPE mt;
    HRESULT hr = m_pOutput->ConnectionMediaType(&mt);
    if (FAILED(hr))
    {
        return hr;
    }

    ASSERT(mt.formattype == FORMAT_VideoInfo);
    BITMAPINFOHEADER *pbmi = HEADER(mt.pbFormat);
    pProp->cbBuffer = DIBSIZE(*pbmi) * 2; 
    if (pProp->cbAlign == 0)
    {
        pProp->cbAlign = 1;
    }
    if (pProp->cBuffers == 0)
    {
        pProp->cBuffers = 1;
    }
    // Release the format block.
    FreeMediaType(mt);

    // Set allocator properties.
    ALLOCATOR_PROPERTIES Actual;
    hr = pAlloc->SetProperties(pProp, &Actual);
    if (FAILED(hr)) 
    {
        return hr;
    }
    // Even when it succeeds, check the actual result.
    if (pProp->cbBuffer > Actual.cbBuffer) 
    {
        return E_FAIL;
    }
    return S_OK;
}

L'allocatore potrebbe non essere in grado di corrispondere esattamente alla richiesta. Pertanto, il metodo SetProperties restituisce il risultato effettivo in una struttura ALLOCATOR_PROPERTIES separata (il parametro Actual , nell'esempio precedente). Anche quando SetProperties ha esito positivo, è necessario controllare il risultato per assicurarsi di soddisfare i requisiti minimi del filtro.

Allocatori personalizzati

Per impostazione predefinita, tutte le classi di filtro usano la classe CMemAllocator per gli allocatori. Questa classe alloca memoria dallo spazio indirizzi virtuale del processo client (usando VirtualAlloc). Se il filtro deve usare un altro tipo di memoria, ad esempio le superfici DirectDraw, è possibile implementare un allocatore personalizzato. È possibile usare la classe CBaseAllocator o scrivere una classe allocator completamente nuova. Se il filtro ha un allocatore personalizzato, eseguire l'override dei metodi seguenti, a seconda del pin usato dall'allocatore:

Se l'altro filtro rifiuta di connettersi usando l'allocatore personalizzato, il filtro può non riuscire la connessione oppure connettersi con l'allocatore dell'altro filtro. In quest'ultimo caso, potrebbe essere necessario impostare un flag interno che indica il tipo di allocatore. Per un esempio di questo approccio, vedere Classe CDrawImage.

Avanti: Passaggio 5. Trasformare l'immagine.

Scrittura di filtri DirectShow