Partilhar via


Definir preferências de desentrelaçamento

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

O Video Mixing Renderer (VMR) suporta desentrelaçamento acelerado por hardware, o que melhora a qualidade de renderização para vídeo entrelaçado. Os recursos exatos que estão disponíveis dependem do hardware subjacente. A aplicação pode consultar as capacidades de desentrelaçamento de hardware e definir preferências de desentrelaçamento através da interface IVMRDeinterlaceControl (VMR-7) ou da interface IVMRDeinterlaceControl9 (VMR-9). O desentrelaçamento é realizado por fluxo.

Há uma diferença importante no comportamento de entrelaçamento entre o VMR-7 e o VMR-9. Em sistemas onde o hardware gráfico não suporta desentrelaçamento avançado, o VMR-7 pode recorrer à sobreposição de hardware e instruí-lo a usar um desentrelaçamento estilo BOB. Neste caso, embora o VMR esteja relatando 30fps, o vídeo está realmente sendo renderizado a 60 flips por segundo.

Exceto quando o VMR-7 utiliza sobreposição de hardware, o desentrelaçamento é realizado pelo misturador do VMR. O misturador usa a interface de driver de dispositivo de desentrelaçamento da DirectX Video Acceleration (DXVA) para executar o desentrelaçamento. Esse DDI não é chamável por aplicativos e os aplicativos não podem substituir a funcionalidade de desentrelaçamento do VMR. No entanto, um aplicativo pode selecionar o modo de desentrelaçamento 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 desentrelaçamento para um fluxo de vídeo, faça o seguinte:

  1. Preencha a estrutura VMR9VideoDesc com uma descrição do fluxo de vídeo. Os pormenores sobre como preencher esta estrutura serão fornecidos mais adiante.
  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 desentrelaçamento que o hardware suporta 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 desentrelaçamento.
  3. Para obter as capacidades de um modo específico, chame o método IVMRDeinterlaceControl9::GetDeinterlaceModeCaps. Deve-se passar a mesma estrutura VMR9VideoDesc, juntamente com um dos GUIDs da matriz. O método preenche uma VMR9DeinterlaceCaps estrutura com os recursos do 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 desentrelaçamento para o fluxo, usando os seguintes métodos:

  • O método SetDeinterlaceMode define o modo preferido. Use GUID_NULL para desativar o desentrelaçamento.
  • O métodoSetDeinterlacePrefs especifica o comportamento se o modo solicitado não estiver disponível.
  • O GetDeinterlaceMode método retorna o modo preferencial que você definiu.
  • O método GetActualDeinterlaceMode retorna o modo real em uso, que pode ser um modo de recurso, 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 dado anteriormente, o primeiro passo é 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 pino de entrada do filtro VMR. Em seguida, confirme se o fluxo de vídeo está entrelaçado. Apenas VIDEOINFOHEADER2 formatos podem ser entrelaçados. Se o tipo de formato for FORMAT_VideoInfo, deve ser um quadro progressivo. Se o tipo de formato for FORMAT_VideoInfo2, verifique o campo dwInterlaceFlags para o sinalizador AMINTERLACE_IsInterlaced. A presença desta bandeira indica que o vídeo está entrelaçado.

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

  • dwSize: Defina este campo como sizeof(VMR9VideoDesc).

  • dwSampleWidth: Defina este campo como pBMI->biWidth.

  • dwSampleHeight: Defina este campo como abs(pBMI->biHeight).

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

  • InputSampleFreq: Este 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 verificar algumas taxas de fotogramas bem 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) 24000 1001
    200000 50.00 (PAL) 50 1
    400000 25.00 (PAL) 25 1
    416667 24.00 (Filme) 24 1

     

  • OutputFrameFreq: Este campo fornece a frequência de saída, que pode ser calculada com base no valor InputSampleFreq e nas características de intercalação do fluxo de entrada.

    • Defina OutputFrameFreq.dwDenominator igual a InputSampleFreq.dwDenominator.
    • Se o vídeo de entrada estiver intercalado, defina OutputFrameFreq.dwNumerator como 2 x InputSampleFreq.dwNumerator. (Após o desentrelaçamento, a taxa de fotogramas é duplicada.) Se não for esse o caso, defina o valor como InputSampleFreq.dwNumerator.
  • dwFourCC: Defina este campo como pBMI->biCompression.

A seguinte função auxiliar converte as flags AMINTERLACE_X em valores 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.
    }
}