Modo sem janelas VMR

[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.]

O modo sem janelas é a maneira preferencial para os aplicativos renderizarem vídeo dentro de uma janela do aplicativo. No modo sem janelas, o Renderizador de Combinação de Vídeos não carrega seu componente gerenciador de janelas e, portanto, não dá suporte às interfaces IBasicVideo ou IVideoWindow . Em vez disso, o aplicativo fornece a janela de reprodução e define um retângulo de destino na área do cliente para a VMR desenhar o vídeo. A VMR usa um objeto clipper DirectDraw para garantir que o vídeo seja recortado na janela do aplicativo e não apareça em nenhuma outra janela. A VMR não subclasse a janela do aplicativo nem instala nenhum gancho de sistema/processo.

No modo sem janelas, a sequência de eventos durante a conexão e a transição para o estado de execução é a seguinte:

  • O filtro upstream propõe um tipo de mídia, que a VMR aceita ou rejeita.
  • Se o tipo de mídia for aceito, a VMR chamará o alocador-apresentador para obter uma superfície DirectDraw. Se a superfície for criada com êxito, os pinos se conectarão e a VMR estará pronta para fazer a transição para o estado de execução.
  • Quando o grafo de filtro é executado, o decodificador chama GetBuffer para obter um exemplo de mídia do alocador. A VMR consulta o alocador-apresentador para garantir que a profundidade do pixel, o tamanho do retângulo e outros parâmetros em sua superfície DirectDraw sejam compatíveis com o vídeo de entrada. Se forem compatíveis, a VMR retornará a superfície DirectDraw para o decodificador. Depois que o decodificador for decodificado na superfície, a Unidade de Sincronização Principal da VMR validará os carimbos de data/hora. Esta unidade bloqueia a chamada receive até que a hora da apresentação chegue. Nesse ponto, a VMR chama PresentImage no alocador-apresentador, que apresenta a superfície para os elementos gráficos cartão.

A ilustração a seguir mostra a VMR no modo sem janelas com vários fluxos de entrada.

vmr no modo sem janelas

Configurando a VMR-7 para o modo sem janelas

Para configurar a VMR-7 para o modo sem janelas, execute todas as seguintes etapas antes de conectar qualquer um dos pinos de entrada da VMR:

  1. Crie o filtro e adicione-o ao grafo.

  2. Chame o método IVMRFilterConfig::SetRenderingMode com o sinalizador VMRMode_Windowless.

  3. Opcionalmente, configure a VMR para vários fluxos de entrada chamando IVMRFilterConfig::SetNumberOfStreams. A VMR cria um pino de entrada para cada fluxo. Use a interface IVMRMixerControl para definir a ordem Z e outros parâmetros para o fluxo. Para obter mais informações, consulte VMR com vários fluxos (modo de combinação).

    Se você não chamar SetNumberOfStreams, a VMR-7 usará como padrão um pino de entrada. Depois que os pinos de entrada estiverem conectados, o número de pinos não poderá ser alterado.

  4. Chame IVMRWindowlessControl::SetVideoClippingWindow para especificar a janela na qual o vídeo renderizado será exibido.

Depois que essas etapas forem concluídas, você poderá conectar os pinos de entrada do filtro VMR. Há várias maneiras de criar o grafo, como conectar pinos diretamente, usar métodos Intelligent Connect, como IGraphBuilder::RenderFile, ou usar o método ICaptureGraphBuilder2::RenderStream do Construtor do Graph de Captura. Para obter mais informações, consulte Técnicas gerais de Graph-Building.

Para definir a posição do vídeo dentro da janela do aplicativo, chame o método IVMRWindowlessControl::SetVideoPosition . O método IVMRWindowlessControl::GetNativeVideoSize retorna o tamanho do vídeo nativo. Durante a reprodução, o aplicativo deve notificar a VMR das seguintes mensagens do Windows:

Observação

Os aplicativos MFC devem definir um manipulador de mensagens WM_ERASEBKGND vazio ou a área de exibição de vídeo não será repinta corretamente.

 

Configurando a VMR-9 para o modo sem janelas

Para configurar a VMR-9 para o modo sem janelas, use as etapas descritas para a VMR-7 para o modo sem janelas, mas use as interfaces IVMRFilterConfig9 e IVMRWindowlessControl9 . A única diferença significativa é que a VMR-9 cria quatro pinos de entrada por padrão, em vez de um pino de entrada. Portanto, você só precisará chamar SetNumberOfStreams se estiver misturando mais de quatro fluxos de vídeo.

Código de exemplo

O código a seguir mostra como criar um filtro VMR-7, adicioná-lo ao grafo de filtro do DirectShow e, em seguida, colocar a VMR no modo sem janelas. Para a VMR-9, use CLSID_VideoMixingRenderer9 em CoCreateInstance e as interfaces VMR-9 correspondentes.

HRESULT InitializeWindowlessVMR(
    HWND hwndApp,         // Application window.
    IFilterGraph* pFG,    // Pointer to the Filter Graph Manager.
    IVMRWindowlessControl** ppWc,  // Receives the interface.
    DWORD dwNumStreams,  // Number of streams to use.
    BOOL fBlendAppImage  // Are we alpha-blending a bitmap?
    )
{
    IBaseFilter* pVmr = NULL;
    IVMRWindowlessControl* pWc = NULL;
    *ppWc = NULL;

    // Create the VMR and add it to the filter graph.
    HRESULT hr = CoCreateInstance(CLSID_VideoMixingRenderer, NULL,
       CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr);
    if (FAILED(hr))
    {
        return hr;
    }
    hr = pFG->AddFilter(pVmr, L"Video Mixing Renderer");
    if (FAILED(hr))
    {
        pVmr->Release();
        return hr;
    }

    // Set the rendering mode and number of streams.  
    IVMRFilterConfig* pConfig;
    hr = pVmr->QueryInterface(IID_IVMRFilterConfig, (void**)&pConfig);
    if (SUCCEEDED(hr)) 
    {
        pConfig->SetRenderingMode(VMRMode_Windowless);

        // Set the VMR-7 to mixing mode if you want more than one video
        // stream, or you want to mix a static bitmap over the video.
        // (The VMR-9 defaults to mixing mode with four inputs.)
        if (dwNumStreams > 1 || fBlendAppImage) 
        {
            pConfig->SetNumberOfStreams(dwNumStreams);
        }
        pConfig->Release();

        hr = pVmr->QueryInterface(IID_IVMRWindowlessControl, (void**)&pWc);
        if (SUCCEEDED(hr)) 
        {
            pWc->SetVideoClippingWindow(hwndApp);
            *ppWc = pWc;  // The caller must release this interface.
        }
    }
    pVmr->Release();

    // Now the VMR can be connected to other filters.
    return hr;
}

Usando o modo sem janelas