Etapa 5. Transformar a imagem
[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 5 do tutorial Escrevendo filtros de transformação.
O filtro upstream fornece exemplos de mídia para o filtro de transformação chamando o método IMemInputPin::Receive no pin de entrada do filtro de transformação. Para processar os dados, o filtro de transformação chama o método Transform , que é virtual puro. As classes CTransformFilter e CTransInPlaceFilter usam duas versões diferentes deste método:
- CTransformFilter::Transform usa um ponteiro para o exemplo de entrada e um ponteiro para o exemplo de saída. Antes que o filtro chame o método , ele copia as propriedades de exemplo do exemplo de entrada para o exemplo de saída, incluindo os carimbos de data/hora.
- CTransInPlaceFilter::Transform usa um ponteiro para o exemplo de entrada. O filtro modifica os dados em vigor.
Se o método Transform retornar S_OK, o filtro fornecerá o exemplo downstream. Para ignorar um quadro, retorne S_FALSE. Se houver um erro de streaming, retorne um código de falha.
O exemplo a seguir mostra como o codificador RLE pode implementar esse método. Sua própria implementação pode ser consideravelmente diferente, dependendo do que o filtro faz.
HRESULT CRleFilter::Transform(IMediaSample *pSource, IMediaSample *pDest)
{
// Get pointers to the underlying buffers.
BYTE *pBufferIn, *pBufferOut;
hr = pSource->GetPointer(&pBufferIn);
if (FAILED(hr))
{
return hr;
}
hr = pDest->GetPointer(&pBufferOut);
if (FAILED(hr))
{
return hr;
}
// Process the data.
DWORD cbDest = EncodeFrame(pBufferIn, pBufferOut);
KASSERT((long)cbDest <= pDest->GetSize());
pDest->SetActualDataLength(cbDest);
pDest->SetSyncPoint(TRUE);
return S_OK;
}
Este exemplo pressupõe que EncodeFrame é um método privado que implementa a codificação RLE. O algoritmo de codificação em si não é descrito aqui; para obter detalhes, consulte o tópico "Compactação de bitmap" na documentação do SDK da plataforma.
Primeiro, o exemplo chama IMediaSample::GetPointer para recuperar os endereços dos buffers subjacentes. Ele os passa para o método EncoderFrame privado. Em seguida, ele chama IMediaSample::SetActualDataLength para especificar o comprimento dos dados codificados. O filtro downstream precisa dessas informações para que possa gerenciar o buffer corretamente. Por fim, o método chama IMediaSample::SetSyncPoint para definir o sinalizador de quadro-chave como TRUE. A codificação de comprimento de execução não usa quadros delta, portanto, cada quadro é um quadro-chave. Para quadros delta, defina o valor como FALSE.
Outros problemas que você deve considerar incluem:
Carimbos de data/hora. A classe CTransformFilter carimbou o carimbo de data/hora do exemplo de saída antes de chamar o método Transform . Ele copia os valores de carimbo de data/hora do exemplo de entrada, sem modificá-los. Se o filtro precisar alterar os carimbos de data/hora, chame IMediaSample::SetTime no exemplo de saída.
Formatar alterações. O filtro upstream pode alterar formatos no meio do fluxo anexando um tipo de mídia ao exemplo. Antes de fazer isso, ele chama IPin::QueryAccept no pin de entrada do filtro. Na classe CTransformFilter , isso resulta em uma chamada para CheckInputType seguida por CheckTransform. O filtro downstream também pode alterar os tipos de mídia, usando o mesmo mecanismo. Em seu próprio filtro, há duas coisas para watch:
- Verifique se QueryAccept não retorna aceitações falsas.
- Se o filtro aceitar alterações de formato, marcar para elas dentro do método Transform chamando IMediaSample::GetMediaType. Se esse método retornar S_OK, o filtro deverá responder à alteração de formato.
Para obter mais informações, consulte Alterações de formato dinâmico.
Tópicos. Em CTransformFilter e CTransInPlaceFilter, o filtro de transformação fornece amostras de saída de forma síncrona dentro do método Receive . O filtro não cria threads de trabalho para processar os dados. Normalmente, não há motivo para um filtro de transformação criar threads de trabalho.
Próximo: Etapa 6. Adicionar suporte para COM.
Tópicos relacionados