Etapa 4. Definir propriedades do alocador

[O recurso associado a esta página, DirectShow, é um recurso herdado. Foi substituído por MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation. Esses recursos foram otimizados para Windows 10 e Windows 11. A Microsoft recomenda fortemente que o novo código use MediaPlayer, IMFMediaEngine e Audio/Video Capture in 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 Escrevendo filtros de transformação.

Observação

Esta etapa não é necessária para filtros derivados 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 conexão de pino upstream e outro para a conexão de pino downstream. O filtro upstream seleciona o alocador upstream e também escolhe as propriedades do alocador. O pino de entrada aceita o que o filtro de upstream decidir. Se você precisar modificar esse comportamento, substitua o método CBaseInputPin::NotifyAllocator .

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

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

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

No exemplo a seguir, o codificador RLE define valores mínimos para o tamanho do buffer, o alinhamento do buffer e a contagem de buffers. Para o prefixo, ele usa qualquer valor que o filtro downstream solicitou. O prefixo normalmente é zero bytes, mas alguns filtros exigem isso. Por exemplo, o filtro AVI Mux usa o prefixo para gravar 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 conseguir corresponder exatamente à sua solicitação. Portanto, o método SetProperties retorna o resultado real em uma estrutura ALLOCATOR_PROPERTIES separada (o parâmetro Actual , no exemplo anterior). Mesmo quando SetProperties for bem-sucedido, você deverá marcar o resultado para garantir que eles atendam aos requisitos mínimos do filtro.

Alocadores personalizados

Por padrão, todas as classes de filtro usam a classe CMemAllocator para seus alocadores. Essa 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 gravar 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 se conectar usando o alocador personalizado, o filtro poderá falhar na conexão ou se conectar ao alocador do outro filtro. No último caso, talvez seja necessário definir um sinalizador interno indicando o tipo de alocador. Para obter um exemplo dessa abordagem, consulte Classe CDrawImage.

Próximo: Etapa 5. Transforme a Imagem.

Escrevendo filtros do DirectShow