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