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:
- 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.
- O pino de saída obtém os requisitos do alocador do filtro a jusante (se houver) chamando IMemInputPin::GetAllocatorRequirements.
- 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.
- 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:
- Pino de entrada: CBaseInputPin::GetAllocator e CBaseInputPin::NotifyAllocator.
- Pino de saída: CBaseOutputPin::DecideAllocator.
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.
Tópicos relacionados