Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
[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.]
Esse mecanismo permite que um pino de entrada proponha uma alteração de formato para seu par upstream. O filtro downstream deve anexar um tipo de mídia ao exemplo que o filtro upstream obterá em sua próxima chamada para IMemAllocator::GetBuffer. Para fazer isso, no entanto, o filtro downstream deve fornecer um alocador personalizado para a conexão. Esse alocador deve implementar um método privado que o filtro downstream pode usar para definir o tipo de mídia na próxima amostra.
As seguintes etapas ocorrem:
- O filtro downstream verifica se a conexão de pino usa o alocador personalizado do filtro. Se o filtro upstream possuir o alocador, o filtro downstream não poderá alterar o formato.
- O filtro downstream chama IPin::QueryAccept no pino de saída upstream (veja a ilustração, etapa A).
- Se
QueryAcceptretornar S_OK, o filtro downstream chamará o método privado em seu alocador para definir o tipo de mídia. Dentro desse método privado, o alocador chama IMediaSample::SetMediaType no próximo exemplo disponível (B). - O filtro upstream chama GetBuffer para obter um novo exemplo (C) e IMediaSample::GetMediaType para obter o tipo de mídia (D).
- Quando o filtro upstream entrega a amostra, ele deve deixar o tipo de mídia anexado a essa amostra. Dessa forma, o filtro a jusante pode confirmar que o tipo de mídia foi alterado (E).
Se o filtro upstream aceitar a alteração de formato, ele também deve ser capaz de voltar para o tipo de mídia original, conforme mostrado no diagrama a seguir.
Os principais exemplos desse tipo de alteração de formato envolvem os renderizadores de vídeo DirectShow.
- O filtro Video Renderer original pode alternar entre os tipos RGB e YUV durante o streaming. Quando o filtro se conecta, ele requer um formato RGB que corresponda às configurações de exibição atuais. Isso garante que ele pode recorrer ao GDI se necessário. Após o início do streaming, se o DirectDraw estiver disponível, o renderizador de vídeo solicitará uma alteração de formato para um tipo YUV. Mais tarde, ele pode voltar para RGB se perder a superfície DirectDraw por qualquer motivo.
- O filtro VMR (Video Mixing Renderer) mais recente se conectará a qualquer formato suportado pelo hardware gráfico, incluindo tipos YUV. No entanto, o hardware gráfico pode alterar a passada da superfície DirectDraw subjacente para otimizar o desempenho. O filtro VMR usa
QueryAcceptpara relatar a nova passada, que é especificada no biWidth membro da estrutura BITMAPINFOHEADER. Os retângulos de origem e destino no VIDEOINFOHEADER ou na estrutura VIDEOINFOHEADER2 identificam a região onde o vídeo deve ser decodificado.
Nota de Aplicação
É improvável que você escreva um filtro que precise solicitar alterações de formato upstream, uma vez que este é principalmente um recurso dos renderizadores de vídeo. No entanto, se você escrever um filtro de transformação de vídeo ou um decodificador de vídeo, seu filtro deverá responder corretamente às solicitações do renderizador de vídeo.
Um filtro trans-in-loco que fica entre o renderizador de vídeo e o decodificador deve passar todas as QueryAccept chamadas para cima. Armazene as informações do novo formato quando elas chegarem.
Um filtro de transformação de cópia (ou seja, um filtro não trans-in-loco) deve implementar um dos seguintes comportamentos:
- Passe as alterações de formato a montante e armazene as novas informações de formato quando elas chegarem. Seu filtro deve usar um alocador personalizado para que ele possa anexar o formato à amostra upstream.
- Execute a conversão de formato dentro do filtro. Isso é provavelmente mais fácil do que passar a alteração de formato a montante. No entanto, pode ser menos eficiente do que deixar o filtro do decodificador decodificar no formato correto.
- Como último recurso, simplesmente rejeite a alteração de formato. (Para obter mais informações, consulte o código-fonte do método CTransInPlaceOutputPin::CheckMediaType na biblioteca de classes base do DirectShow.) Rejeitar uma alteração de formato pode reduzir o desempenho, no entanto, porque impede que o renderizador de vídeo use o formato mais eficiente.
O pseudocódigo a seguir mostra como você pode implementar um filtro de transformação de cópia (derivado de CTransformFilter) que pode alternar entre os tipos de saída YUV e RGB. Este exemplo pressupõe que o filtro faça a conversão em si, em vez de passar a alteração de formato para cima.
HRESULT CMyTransform::CheckInputType(const CMediaType *pmt)
{
if (pmt is a YUV type that you support) {
return S_OK;
}
else {
return VFW_E_TYPE_NOT_ACCEPTED;
}
}
HRESULT CMyTransform::CheckTransform(
const CMediaType *mtIn, const CMediaType *mtOut)
{
if (mtOut is a YUV or RGB type that you support)
{
if ((mtIn has the same video dimensions as mtOut) &&
(you support the mtIn-to-mtOut transform))
{
return S_OK;
}
}
// otherwise
return VFW_E_TYPE_NOT_ACCEPTED;
}
// GetMediaType: Return a preferred output type.
HRESULT CMyTransform::GetMediaType(int iPosition, CMediaType *pMediaType)
{
if (iPosition < 0) {
return E_INVALIDARG;
}
switch (iPosition)
{
case 0:
Copy the input type (YUV) to pMediaType
return S_OK;
case 1:
Construct an RGB type that matches the input type.
return S_OK;
default:
return VFW_S_NO_MORE_ITEMS;
}
}
// SetMediaType: Override from CTransformFilter.
HRESULT CMyTransform::SetMediaType(
PIN_DIRECTION direction, const CMediaType *pmt)
{
// Capture this information...
if (direction == PINDIR_OUTPUT)
{
m_bYuv = (pmt->subtype == MEDIASUBTYPE_UYVY);
}
return S_OK;
}
HRESULT CMyTransform::Transform(
IMediaSample *pSource, IMediaSample *pDest)
{
// Look for format changes from downstream.
CMediaType *pMT = NULL;
HRESULT hr = pDest->GetMediaType((AM_MEDIA_TYPE**)&pMT);
if (hr == S_OK)
{
hr = m_pOutput->CheckMediaType(pMT);
if(FAILED(hr))
{
DeleteMediaType(pMT);
return E_FAIL;
}
// Notify our own output pin about the new type.
m_pOutput->SetMediaType(pMT);
DeleteMediaType(pMT);
}
// Process the buffers
if (m_bYuv) {
return ProcessFrameYUV(pSource, pDest);
}
else {
return ProcessFrameRGB(pSource, pDest);
}
}