Partilhar via


Passo 4. Definir propriedades do alocador

[O recurso associado a esta página, DirectShow, é um recurso herdado. Foi substituído por MediaPlayer, IMFMediaEnginee Audio/Video Capture in Media Foundation. Esses recursos foram otimizados para Windows 10 e Windows 11. A Microsoft recomenda vivamente que o novo código utilize MediaPlayer, IMFMediaEngine e Captura de Áudio/Vídeo no Media Foundation em vez de DirectShow, quando possível. A Microsoft sugere que o código existente que usa as APIs herdadas seja reescrito para usar as novas APIs, se possível.]

Esta é a etapa 4 do tutorial Writing Transform Filters.

Observação

Esta etapa não é necessária para filtros que derivam de CTransInPlaceFilter.

 

Depois que dois pinos concordam com um tipo de mídia, eles selecionam um alocador para a conexão e negociam as propriedades do alocador, como o tamanho do buffer e o número de buffers.

Na classe CTransformFilter, há dois alocadores, um para a ligação do pino a montante e outro para a ligação do pino a jusante. O filtro ascendente seleciona o alocador ascendente e define as propriedades do alocador. O pino de entrada aceita qualquer decisão tomada pelo filtro a montante. Se necessitar modificar esse comportamento, substitua o método CBaseInputPin::NotifyAllocator.

O pino de saída do filtro de transformação seleciona o alocador a jusante. Ele executa as seguintes etapas:

  1. Se o filtro a jusante puder fornecer um alocador, o pino de saída usará aquele. Caso contrário, o pino de saída cria um novo alocador.
  2. O pino de saída obtém os requisitos do alocador do filtro a jusante (se houver) chamando IMemInputPin::GetAllocatorRequirements.
  3. O pino de saída chama o do filtro de transformação CTransformFilter::D ecideBufferSize método, que é puramente virtual. Os parâmetros para este método são um ponteiro para o alocador e uma estrutura ALLOCATOR_PROPERTIES com os requisitos do filtro a jusante. Se o filtro a jusante não tiver requisitos de alocador, a estrutura será redefinida para zero.
  4. No método DecideBufferSize, a classe derivada define as propriedades do alocador chamando IMemAllocator::SetProperties.

Geralmente, a classe derivada selecionará as propriedades do alocador com base no formato de saída, nos requisitos do filtro a jusante e nos próprios requisitos do filtro. Tente selecionar propriedades que sejam compatíveis com a solicitação do filtro downstream. Caso contrário, o filtro a jusante poderá rejeitar a ligação.

No exemplo a seguir, o codificador RLE define valores mínimos para o tamanho do buffer, alinhamento do buffer e contagem de buffer. Para o prefixo, ele usa qualquer valor que o filtro downstream solicitou. O prefixo é normalmente zero bytes, mas alguns filtros o exigem. Por exemplo, o filtro AVI Mux usa o prefixo para escrever cabeçalhos 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;
}

O alocador pode não ser capaz de corresponder exatamente ao seu pedido. Portanto, o método SetProperties retorna o resultado real em uma estrutura ALLOCATOR_PROPERTIES separada (o parâmetro Atual, no exemplo anterior). Mesmo quando SetProperties é bem-sucedido, deve-se verificar o resultado para assegurar que satisfaça os requisitos mínimos do filtro.

Alocadores Personalizados

Por padrão, todas as classes de filtro usam a classe CMemAllocator para os seus alocadores. Esta classe aloca memória do espaço de endereço virtual do processo do cliente (usando VirtualAlloc). Se o filtro precisar usar algum outro tipo de memória, como superfícies DirectDraw, você poderá implementar um alocador personalizado. Você pode usar a classe CBaseAllocator ou escrever uma classe de alocador totalmente nova. Se o filtro tiver um alocador personalizado, substitua os seguintes métodos, dependendo de qual pino usa o alocador:

Se o outro filtro se recusar a conectar-se usando o seu alocador personalizado, o seu filtro pode optar por falhar a conexão ou conectar-se com o alocador do outro filtro. Neste último caso, talvez seja necessário definir um sinalizador interno indicando o tipo de alocador. Para obter um exemplo dessa abordagem, consulte CDrawImage Class.

Próximo: Passo 5. Transforme a imagem.

Desenvolvimento de filtros DirectShow