QueryAccept (Upstream)
[O recurso associado a esta página, DirectShow, é um recurso herdado. Foi substituído por MediaPlayer, IMFMediaEnginee Audio/Video Capture na 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 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 pin 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. No entanto, para fazer isso, 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 no próximo exemplo.
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 (consulte ilustração, etapa A).
- Se
QueryAccept
retornar 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 o exemplo, ele deve deixar o tipo de mídia anexado a esse exemplo. Dessa forma, o filtro downstream pode confirmar se o tipo de mídia foi alterado (E).
Se o filtro upstream aceitar a alteração de formato, ele também deverá ser capaz de alternar de volta para o tipo de mídia original, conforme mostrado no diagrama a seguir.
queryaccept (upstream)
Os principais exemplos desse tipo de alteração de formato envolvem os renderizadores de vídeo do DirectShow.
- O filtro de do Renderizador de Vídeo original pode alternar entre 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 possa voltar 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. Posteriormente, ele poderá voltar para RGB se perder a superfície do DirectDraw por qualquer motivo.
- O filtro VMR (Renderizador de Combinação de Vídeo) mais recente se conectará com qualquer formato compatível com o hardware gráfico, incluindo tipos YUV. No entanto, o hardware gráfico pode alterar o passo da superfície do DirectDraw subjacente para otimizar o desempenho. O filtro de VMR usa
QueryAccept
para relatar o novo passo, que é especificado no biWidth membro da estrutura BITMAPINFOHEADER. Os retângulos de origem e de destino no VIDEOINFOHEADER ou VIDEOINFOHEADER2 estrutura identificam a região em que o vídeo deve ser decodificado.
da Nota de Implementação do
É improvável que você escreva um filtro que precise solicitar alterações de formato upstream, pois esse é principalmente um recurso de 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 chamadas QueryAccept
upstream. Armazene as novas informações de formato quando elas chegarem.
Um filtro de transformação de cópia (ou seja, um filtro não trans-in-place) deve implementar um dos seguintes comportamentos:
- Passe as alterações de formato upstream 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 ao exemplo upstream.
- Execute a conversão de formato dentro do filtro. Isso provavelmente é mais fácil do que passar a alteração de formato upstream. No entanto, pode ser menos eficiente do que deixar o filtro decodificador decodificar no formato correto.
- Como último recurso, basta rejeitar 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 tipos de saída YUV e RGB. Este exemplo pressupõe que o filtro faz a conversão em si, em vez de passar a alteração de formato upstream.
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);
}
}