Compartir a través de


Establecer preferencias de desinterlace

[La característica asociada a esta página, DirectShow, es una característica heredada. Se ha reemplazado por MediaPlayer, IMFMediaEngine y Captura de audio/vídeo en Media Foundation. Esas características se han optimizado para Windows 10 y Windows 11. Microsoft recomienda encarecidamente que el nuevo código use MediaPlayer, IMFMediaEngine y Audio/Video Capture en Media Foundation en lugar de DirectShow, siempre que sea posible. Microsoft sugiere que el código existente que usa las API heredadas se reescriba para usar las nuevas API si es posible.

El representador de mezcla de vídeos (VMR) admite desinterlaces acelerados por hardware, lo que mejora la calidad de representación para el vídeo entrelazado. Las características exactas que están disponibles dependen del hardware subyacente. La aplicación puede consultar las funcionalidades de desinterlacación de hardware y establecer preferencias de desinterlacación mediante la interfaz IVMRDeinterlaceControl (VMR-7) o la interfaz IVMRDeinterlaceControl9 (VMR-9). La desinterlacación se realiza por secuencia.

Hay una diferencia importante en el comportamiento entrelazado entre VMR-7 y VMR-9. En los sistemas en los que el hardware gráfico no admite el desinterlacamiento avanzado, VMR-7 puede revertir a la superposición de hardware e indicarle que use una desinterlace de estilo BOB. En este caso, aunque VMR informa de 30 fps, el vídeo se representa realmente a 60 volteos por segundo.

Excepto en el caso de VMR-7 mediante la superposición de hardware, el mezclador de VMR realiza la desinterlacación. El mezclador usa la interfaz de controlador de dispositivo de desinterlacación de DirectX Video Acceleration (DXVA) para realizar la desinterlacación. Las aplicaciones no pueden llamar a esta DDI y las aplicaciones no pueden reemplazar la funcionalidad de desinterlacación de VMR. Sin embargo, una aplicación puede seleccionar el modo de desinterlace deseado, como se describe en esta sección.

Nota:

En esta sección se describen los métodos IVMRDeinterlaceControl9 , pero las versiones de VMR-7 son casi idénticas.

 

Para obtener las funcionalidades de desinterlacación de una secuencia de vídeo, haga lo siguiente:

  1. Rellene una estructura VMR9VideoDesc con una descripción de la secuencia de vídeo. Más adelante se proporcionan detalles sobre cómo rellenar esta estructura.
  2. Pase la estructura al método IVMRDeinterlaceControl9::GetNumberOfDeinterlaceModes . Llame al método dos veces. La primera llamada devuelve el número de modos de desinterlace que admite el hardware para el formato especificado. Asigne una matriz de GUID de este tamaño y llame al método de nuevo, pasando la dirección de la matriz. La segunda llamada rellena la matriz con GUID. Cada GUID identifica un modo de desinterlazado.
  3. Para obtener las capabiltiies de un modo determinado, llame al método IVMRDeinterlaceControl9::GetDeinterlaceModeCaps . Pase la misma estructura VMR9VideoDesc , junto con uno de los GUID de la matriz. El método rellena una estructura VMR9DeinterlaceCaps con las funcionalidades de modo.

El siguiente código muestra estos pasos:

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;
    }
}

Ahora, la aplicación puede establecer el modo de desinterlace para la secuencia mediante los métodos siguientes:

  • El método SetDeinterlaceMode establece el modo preferido. Use GUID_NULL para desactivar la desinterlacación.
  • El método SetDeinterlacePrefs especifica el comportamiento si el modo solicitado no está disponible.
  • El método GetDeinterlaceMode devuelve el modo preferido que establezca.
  • El método GetActualDeinterlaceMode devuelve el modo real en uso, que podría ser un modo de reserva, si el modo preferido no está disponible.

Las páginas de referencia del método proporcionan más información.

Uso de la estructura VMR9VideoDesc

En el procedimiento especificado anteriormente, el primer paso es rellenar una estructura VMR9VideoDesc con una descripción de la secuencia de vídeo. Empiece por obtener el tipo multimedia de la secuencia de vídeo. Para ello, llame a IPin::ConnectionMediaType en el pin de entrada del filtro VMR. A continuación, confirme si la secuencia de vídeo está entrelazada. Solo los formatos VIDEOINFOHEADER2 se pueden entrelazados. Si el tipo de formato es FORMAT_VideoInfo, debe ser un marco progresivo. Si el tipo de formato es FORMAT_VideoInfo2, compruebe el campo dwInterlaceFlags para la marca AMINTERLACE_IsInterlaced. La presencia de esta marca indica que el vídeo está entrelazado.

Supongamos que la variable pBMI es un puntero a la estructura BITMAPINFOHEADER en el bloque de formato. Establezca los valores siguientes en la estructura VMR9VideoDesc :

  • dwSize: establezca este campo en sizeof(VMR9VideoDesc).

  • dwSampleWidth: establezca este campo en pBMI->biWidth.

  • dwSampleHeight: establezca este campo en abs(pBMI->biHeight).

  • SampleFormat: en este campo se describen las características de interlace del tipo de medio. Compruebe el campo dwInterlaceFlags en la estructura VIDEOINFOHEADER2 y establezca SampleFormat igual a la marca de VMR9_SampleFormat equivalente. A continuación se muestra una función auxiliar para hacerlo.

  • InputSampleFreq: este campo proporciona la frecuencia de entrada, que se puede calcular desde el campo AvgTimePerFrame en la estructura VIDEOINFOHEADER2 . En el caso general, establezca dwNumerator en 100000000 y establezca dwDenominator en AvgTimePerFrame. Sin embargo, también puede comprobar algunas velocidades de fotogramas conocidas:

    Promedio de tiempo por fotograma Velocidad de fotogramas (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 (Película) 24 1

     

  • OutputFrameFreq: este campo proporciona la frecuencia de salida, que se puede calcular a partir del valor InputSampleFreq y las características de intercalación del flujo de entrada:

    • Establezca OutputFrameFreq.dwDenominator igual a InputSampleFreq.dwDenominator.
    • Si el vídeo de entrada está intercalado, establezca OutputFrameFreq.dwNumerator en 2 x InputSampleFreq.dwNumerator. (Después de desinterlazado, se duplica la velocidad de fotogramas). De lo contrario, establezca el valor en InputSampleFreq.dwNumerator.
  • dwFourCC: establezca este campo en pBMI->biCompression.

La siguiente función auxiliar convierte las marcas AMINTERLACE_X en 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.
    }
}