Partilhar via


Definindo preferências de desinterlace

[O recurso associado a esta página, DirectShow, é um recurso herdado. Ele foi substituído por MediaPlayer, IMFMediaEngine e Captura de Áudio/Vídeo 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 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.]

O VMR (Renderizador de Mixagem de Vídeo) dá suporte à desinterlacização acelerada por hardware, o que melhora a qualidade de renderização para vídeos entrelaçados. Os recursos exatos disponíveis dependem do hardware subjacente. O aplicativo pode consultar os recursos de desinterlacização de hardware e definir preferências de desinterlacing por meio da interface IVMRDeinterlaceControl (VMR-7) ou da interface IVMRDeinterlaceControl9 (VMR-9). A desinterlacização é executada por fluxo.

Há uma diferença importante no comportamento de interlação entre a VMR-7 e a VMR-9. Em sistemas em que o hardware gráfico não dá suporte à desinterlacização avançada, o VMR-7 pode voltar à sobreposição de hardware e instruí-lo a usar um desinterlação de estilo BOB. Nesse caso, embora a VMR esteja relatando 30fps, o vídeo está sendo renderizado a 60 lançamentos por segundo.

Exceto no caso da VMR-7 usando a sobreposição de hardware, a desinterlacização é executada pelo mixer da VMR. O mixer usa a DDI (interface de driver de dispositivo) de desinterlacização de DXVA (Aceleração de Vídeo) do DirectX para executar a desinterlacização. Essa DDI não pode ser chamada por aplicativos e os aplicativos não podem substituir a funcionalidade de desinterlacização da VMR. No entanto, um aplicativo pode selecionar o modo de desinterlacing desejado, conforme descrito nesta seção.

Observação

Esta seção descreve os métodos IVMRDeinterlaceControl9 , mas as versões do VMR-7 são quase idênticas.

 

Para obter os recursos de desinterlacagem de um fluxo de vídeo, faça o seguinte:

  1. Preencha uma estrutura VMR9VideoDesc com uma descrição do fluxo de vídeo. Detalhes de como preencher essa estrutura são dados posteriormente.
  2. Passe a estrutura para o método IVMRDeinterlaceControl9::GetNumberOfDeinterlaceModes . Chame o método duas vezes. A primeira chamada retorna o número de modos de desinterlace aos quais o hardware dá suporte para o formato especificado. Aloque uma matriz de GUIDs desse tamanho e chame o método novamente, passando o endereço da matriz. A segunda chamada preenche a matriz com GUIDs. Cada GUID identifica um modo de desinterlacagem.
  3. Para obter as capacidades de um modo específico, chame o método IVMRDeinterlaceControl9::GetDeinterlaceModeCaps . Passe a mesma estrutura VMR9VideoDesc , juntamente com um dos GUIDs da matriz. O método preenche uma estrutura VMR9DeinterlaceCaps com os recursos de modo.

O código a seguir mostra essas etapas:

VMR9VideoDesc VideoDesc; 
DWORD dwNumModes = 0;
// Fill in the VideoDesc structure (not shown).
hr = pDeinterlace->GetNumberOfDeinterlaceModes(&VideoDesc, 
    &dwNumModes, NULL);
if (SUCCEEDED(hr) && (dwNumModes != 0))
{
    // Allocate an array for the GUIDs that identify the modes.
    GUID *pModes = new GUID[dwNumModes];
    if (pModes)
    {
        // Fill the array.
        hr = pDeinterlace->GetNumberOfDeinterlaceModes(&VideoDesc, 
            &dwNumModes, pModes);
        if (SUCCEEDED(hr))
        {
            // Loop through each item and get the capabilities.
            for (int i = 0; i < dwNumModes; i++)
            {
                VMR9DeinterlaceCaps Caps;
                hr = pDeinterlace->GetDeinterlaceModeCaps(pModes + i, 
                    &VideoDesc, &Caps);
                if (SUCCEEDED(hr))
                {
                    // Examine the Caps structure.
                }
            }
        }
        delete [] pModes;
    }
}

Agora, o aplicativo pode definir o modo de desinterlacagem para o fluxo, usando os seguintes métodos:

  • O método SetDeinterlaceMode define o modo preferencial. Use GUID_NULL para desativar o desinterlacamento.
  • O método SetDeinterlacePrefs especifica o comportamento se o modo solicitado não estiver disponível.
  • O método GetDeinterlaceMode retorna o modo preferencial definido.
  • O método GetActualDeinterlaceMode retorna o modo real em uso, que pode ser um modo de fallback, se o modo preferencial não estiver disponível.

As páginas de referência do método fornecem mais informações.

Usando a estrutura VMR9VideoDesc

No procedimento fornecido anteriormente, a primeira etapa é preencher uma estrutura VMR9VideoDesc com uma descrição do fluxo de vídeo. Comece obtendo o tipo de mídia do fluxo de vídeo. Você pode fazer isso chamando IPin::ConnectionMediaType no pin de entrada do filtro VMR. Em seguida, confirme se o fluxo de vídeo está entrelaçado. Somente formatos VIDEOINFOHEADER2 podem ser entrelaçados. Se o tipo de formato for FORMAT_VideoInfo, ele deverá ser um quadro progressivo. Se o tipo de formato for FORMAT_VideoInfo2, marcar o campo dwInterlaceFlags para o sinalizador AMINTERLACE_IsInterlaced. A presença desse sinalizador indica que o vídeo está entrelaçado.

Suponha que a variável pBMI seja um ponteiro para a estrutura BITMAPINFOHEADER no bloco de formato. Defina os seguintes valores na estrutura VMR9VideoDesc :

  • dwSize: defina esse campo como sizeof(VMR9VideoDesc).

  • dwSampleWidth: defina esse campo como pBMI->biWidth.

  • dwSampleHeight: defina esse campo como abs(pBMI->biHeight).

  • SampleFormat: este campo descreve as características de entrelaçamento do tipo de mídia. Verifique o campo dwInterlaceFlags na estrutura VIDEOINFOHEADER2 e defina SampleFormat igual ao sinalizador de VMR9_SampleFormat equivalente. Uma função auxiliar para fazer isso é fornecida abaixo.

  • InputSampleFreq: esse campo fornece a frequência de entrada, que pode ser calculada a partir do campo AvgTimePerFrame na estrutura VIDEOINFOHEADER2 . No caso geral, defina dwNumerator como 10000000 e defina dwDenominator como AvgTimePerFrame. No entanto, você também pode marcar para algumas taxas de quadros conhecidas:

    Tempo médio por quadro Taxa de quadros (fps) Numerador Denominador
    166833 59.94 (NTSC) 60000 1001
    333667 29.97 (NTSC) 30000 1001
    417188 23.97 (NTSC) 24.000 1001
    200000 50.00 (PAL) 50 1
    400000 25.00 (PAL) 25 1
    416667 24.00 (Filme) 24 1

     

  • OutputFrameFreq: esse campo fornece a frequência de saída, que pode ser calculada a partir do valor InputSampleFreq e das características de intercalação do fluxo de entrada:

    • Defina OutputFrameFreq.dwDenominator igual a InputSampleFreq.dwDenominator.
    • Se o vídeo de entrada for intercalado, defina OutputFrameFreq.dwNumerator como 2 x InputSampleFreq.dwNumerator. (Após a desinterlacização, a taxa de quadros é dobrada.) Caso contrário, defina o valor como InputSampleFreq.dwNumerator.
  • dwFourCC: defina esse campo como pBMI->biCompression.

A função auxiliar a seguir converte sinalizadores AMINTERLACE_X em valores de VMR9_SampleFormat :

#define IsInterlaced(x) ((x) & AMINTERLACE_IsInterlaced)
#define IsSingleField(x) ((x) & AMINTERLACE_1FieldPerSample)
#define IsField1First(x) ((x) & AMINTERLACE_Field1First)

VMR9_SampleFormat ConvertInterlaceFlags(DWORD dwInterlaceFlags)
{
    if (IsInterlaced(dwInterlaceFlags)) {
        if (IsSingleField(dwInterlaceFlags)) {
            if (IsField1First(dwInterlaceFlags)) {
                return VMR9_SampleFieldSingleEven;
            }
            else {
                return VMR9_SampleFieldSingleOdd;
            }
        }
        else {
            if (IsField1First(dwInterlaceFlags)) {
                return VMR9_SampleFieldInterleavedEvenFirst;
             }
            else {
                return VMR9_SampleFieldInterleavedOddFirst;
            }
        }
    }
    else {
        return VMR9_SampleProgressiveFrame;  // Not interlaced.
    }
}