Este artículo proviene de un motor de traducción automática.

Codificación de vídeo

Guardar y reutilizar las configuraciones para la codificación de vídeo

Adi Shavit

Descargar el ejemplo de código

De sistemas de vigilancia remota para plataformas robóticas integradas, aplicaciones que automáticamente o autónomamente grabación vídeo están recibiendo cada vez más ubicuas como el precio de los equipos como cámaras y gotas de espacio de almacenamiento y aumenta el rendimiento computacional.Sin embargo, no configurar remotamente a menudo este tipo de sistemas es una opción, mientras que la implementación e instalación deben ser sencilla y automática.

Recientemente necesitaba una forma para preconfigurar la configuración de grabación de vídeo en un sistema remoto por lo que automáticamente se carga y usar la misma configuración en tiempo de arranque.Una búsqueda Web planteada muchas preguntas similares en varios foros que se remonta más de una década, pero con soluciones sólo parciales y poco satisfactoria.

En este artículo, podrá presentar una forma simple, pero muy general para permitir que las aplicaciones de procesamiento de vídeo guardar vídeo con ajustes de compresión consistente, evitando así tener que especificar manualmente la configuración del códec cada vez que se inicia la aplicación o la máquina.Te voy a mostrar cómo obtener acceso a los búferes de configuración interna de un codec para que puedan ser fácilmente guardados, recargados y reutilizados.Esto funciona para cualquier codec de vídeo instalado en el equipo, sin requerir el uso de las APIs específicas de códec.

Vídeo 101

Datos de vídeo sin procesar están enormes.Considere la posibilidad de una modesta cámara VGA ambling junto a un humilde ritmo de 15 fotogramas por segundo.Cada fotograma de tres canales 640 × 480 píxeles es de 900 KB y genera una velocidad de datos de sobre 13MBps (que se trata de 105Mbps)!Ligeramente menos modestos equipos de vídeo, del tipo que podría encontrar en un teléfono móvil, podrían tener resoluciones de alta definición (HD), velocidades más altas o más de 8 bits de profundidad de color.Una película de 90 minutos HD consumirá aproximadamente 1 TB en forma cruda.Afortunadamente, los datos de vídeo contienen una gran cantidad de redundancia y algoritmos de compresión de vídeo pueden almacenar archivos de vídeo muy eficaz.El tipo de algoritmo de compresión elegido depende de la aplicación en particular, sus necesidades y sus limitaciones.Varios factores varían entre los métodos de compresión, incluyendo tarifas en tiempo real, consideraciones de rendimiento y el equilibrio entre la calidad visual y el tamaño del archivo resultante.

En Windows, servicios de compresión de vídeo son proporcionados por códecs (compresor-descompresor).Me centraré en el vídeo para Windows (VfW) API para guardar archivos de video .avi comprimidos.Audio Video Interleave (AVI) es un formato de archivo contenedor multimedia que puede contener múltiples flujos de audio y vídeo y permite la reproducción de vídeo con audio sincrónica de seleccionados.Te voy a mostrar cómo configuración del códec de compresión puede ser manualmente seleccionada y almacena de forma persistente, por lo que puede ser cargados volver más tarde y reutilizar automáticamente por la aplicación en cualquier equipo donde está instalado el mismo códec.

Guardar vídeo con VfW

Aunque fue introducido en 1992, VfW es una API perdurable, siendo ampliamente utilizada hoy.Nuevas implementaciones de códecs y codec, como la suite de ffmpeg (ffmpeg.org), siguen proporcionando una interfaz VfW en Microsoft Windows.

El flujo típico de un programa de grabación de vídeo normalmente toma la forma de los siguientes pasos:

  1. Crear un nuevo archivo AVI, crear una nueva secuencia de vídeo sin comprimir dentro de ella, elija la configuración de compresión necesaria y crear una nueva secuencia comprimida desde el sin comprimir.
  2. Añadir nuevos fotogramas como desee.
  3. Cuando haya terminado, liberar recursos en orden inverso.

Utilizando VfW parece como sigue:

  1. Abrir y preparar el archivo de vídeo AVI utilizando lo siguiente:
    1. AVIFileInit: Inicializa la biblioteca AVIFile.Se debe llamar antes de utilizar cualquier otra función de AVIFile.
    2. AVIFileOpen: Se abre un archivo AVI.
    3. AVIFileCreateStream: Crea una nueva secuencia de video dentro del archivo AVI.Un archivo AVI puede incluir múltiples flujos (de varios tipos).
    4. AVISaveOptions: Presenta un cuadro de diálogo de opciones de compresión estándar (véase figura 1).Cuando el usuario está terminado de seleccionar las opciones de compresión, las opciones se devuelven en una estructura AVICOMPRESSOPTIONS.
    5. AVIMakeCompressedStream: Crea una secuencia comprimida desde la secuencia sin comprimir devuelta de AVIFileCreateStream y el filtro de compresión devuelto por AVISaveOptions.
    6. AVIStreamSetFormat: Establece el formato de imagen de la secuencia.
  2. Añadir marcos a la secuencia de vídeo:
    1. AVIStreamWrite: Añadir un único fotograma de la secuencia de vídeo.Llamar reiteradas veces con cuadros adicionales como desee.
  3. Limpiar y cerrar:
    1. AVIStreamRelease: Cierra la secuencia comprimida (de AVIMakeCompressedStream).
    2. AVIStreamRelease: Cierra la secuencia sin comprimir (de AVIFileCreateStream).
    3. AVISaveOptionsFree: Libera los recursos asignados por la función AVISaveOptions (esto es a menudo olvidado, conduce a pérdidas de memoria).
    4. AVIFileRelease: Se cierra el archivo AVI (de AVIFileOpen).
    5. AVIFileExit: Salir de la biblioteca AVIFile.

The Video Compression Dialog Box Opened by the AVISaveOptions FunctionFigura 1 el cuadro de diálogo compresión de vídeo abiertos con la función AVISaveOptions

Explica en detalle cómo utilizar VfW para grabación de vídeo está fuera del alcance de este artículo.Puede encontrar muchos ejemplos y tutoriales en línea.Me centraré aquí sólo en paso 1.4: la parte de configuración de selección y codec de compresor.El código fuente que acompaña a este artículo se basa en la aplicación de C++ desde el proyecto de código abierto de OpenCV (opencv.willowgarage.com) y puede descargarse desde code.msdn.microsoft.com/mag201112Video.Sin embargo, son aplicables a las técnicas de muestro aquí — y fácilmente integrado en — cualquier video grabación de aplicación que utiliza la API VfW y no está destinado específicamente a una determinada aplicación o lenguaje de programación.

Soluciones comunes

Como se indica anteriormente, la forma común para especificar la configuración de compresión es llamando a la función AVISaveOptions para mostrar el cuadro de diálogo Opciones de compresión.El usuario puede seleccionar manualmente el códec deseado.El códec seleccionado puede o no puede tener un codec "Configure…" opción, que permite realizar personalizaciones de opciones específicas del códec.Naturalmente, en los sistemas sin un usuario activo o incluso una GUI, este cuadro de diálogo no es una opción.

La alternativa común a selección manual es seleccionar mediante programación un códec determinado utilizando fourcc del códec (código de cuatro caracteres; identificador véase fourcc.org) y configurar algunas propiedades adicionales, generales común a todos los códecs, tales como la velocidad de datos, la calidad y la velocidad de fotogramas clave.El principal inconveniente de este método es que no permite cualquier configuración del códec específico.Además, hace el códec usar cualquiera que sea su actual configuración interna.Estos pueden ser valores predeterminados o, peor aún, la configuración establecida arbitrariamente por otros programas.Además, no todos los códecs fourcc disponibles en un sistema de apoyan la API VfW, que puede causar la creación de transmisión comprimida a fallar.

Algunos códecs proporcionan herramientas de configuración especiales que permiten cambiar su configuración interna externamente.Estas herramientas pueden adoptar la forma de una GUI o una herramienta de línea de comandos.Sin embargo, mayoría de códecs no proporciona herramientas de este tipo, y porque cada herramienta está personalizado para un determinado códec, tendría que aprender su particular sintaxis y uso para sacar provecho de ella.

Lo que yo quería era la flexibilidad de la modalidad de selección manual con selección automática del códec y su configuración interna.

Lo mejor de ambos mundos

En el primer enfoque, la llamada AVISaveOptions devuelve un objeto AVICOMPRESSOPTIONS totalmente lleno en.El segundo enfoque es, esencialmente, llenando algunos de los valores del objeto AVICOMPRESSOPTIONS, desde dentro del código, sin necesidad de utilizar AVISaveOptions.

De hecho, es posible guardar el estado completo códec interno después de llamar a AVISaveOptions para que este Estado pueda restaurarse más tarde sin tener que llamar nuevamente a AVISaveOptions.El secreto de los datos específicos de compresor de vídeo interno y formato es en el opaco punteros lpParms y lpFormat de AVICOMPRESSOPTIONS.Cuando regresó de AVISaveOptions, estos dos punteros contienen todo el AVIMakeCompressedStream función necesita hacer una secuencia comprimida (estos son probablemente los recursos liberados por AVISaveOptionsFree).

La esencia de mi técnica, entonces, está guardando los datos opacos de lpParms y lpFormat para que pueda ser reutilizado.Afortunadamente, esto es fácil de hacer.La estructura AVICOMPRESSOPTIONS contiene miembros de dos enteros útiles, cbParms y cbFormat, que el tamaño de los buffers binarios opacos señalado por lpParms y lpFormat, el respeto del estado­ively.Estos tamaños cambian según el códec específico seleccionado.

En resumen, hay tres binarios "grupos indefinidos" que es necesario guardar después de llamar a AVISaveOptions.Estos son el propio objeto AVICOMPRESSOPTIONS y los dos búferes binarios apuntado por su lpParms y lpFormat miembros.La longitud en bytes de estos búferes está dada, respectivamente, por cbParms y cbFormat.Restaurar la configuración del códec sólo es revertir el proceso: leer las AVICOMPRESSOPTIONS desde el archivo de objeto y establecer su lpParms y lpFormat miembros en los respectivos búferes binarios leen desde el archivo.Los búferes binarios restaurados son asignados y administrados por la propia aplicación.

Hay muchas formas para almacenar datos binarios.Como se muestra en figura 2, mi código de ejemplo guarda los datos en formato binario.Alternativamente, en casos donde deben evitarse los caracteres no imprimibles (como los archivos .txt o .xml), lo he utilizado con éxito para almacenar los búferes de codificación Base-64.

Figura 2 ejemplo de almacenar y restaurar la configuración del Codec

bool CvVideoWriter_VFW::writeCodecParams( char const* configFileName ) const
{
  using namespace std;   
  try
  { // Open config file
    ofstream cfgFile(configFileName, ios::out | ios::binary);          
    cfgFile.exceptions ( fstream::failbit | fstream::badbit );
    // Write AVICOMPRESSOPTIONS struct data
    cfgFile.write(reinterpret_cast<char const*>(&copts_), sizeof(copts_)); 
    if (copts_.cbParms != 0)// Write codec param buffer
      cfgFile.write(reinterpret_cast<char const*>(copts_.lpParms), copts_.cbParms);
    if (copts_.cbFormat != 0)// Write codec format buffer
      cfgFile.write(reinterpret_cast<char const*>(copts_.lpFormat),
        copts_.cbFormat);
  }
  catch (fstream::failure const&)
  { return false; } // Write failed
  return true;
}
bool CvVideoWriter_VFW::readCodecParams( char const* configFileName )
{ 
  using namespace std;
  try
  { // Open config file
    ifstream cfgFile(configFileName, ios::in | ios::binary);
    cfgFile.exceptions (
      fstream::failbit | fstream::badbit | fstream::eofbit );
    // Read AVICOMPRESSOPTIONS struct data
    cfgFile.read(reinterpret_cast<char*>(&copts_), sizeof(copts_));        
    if (copts_.cbParms != 0)
    { copts_Parms_.resize(copts_.cbParms,0);                // Allocate buffer
      cfgFile.read(&copts_Parms_[0], copts_Parms_.size());  // Read param buffer
      copts_.lpParms = &copts_Parms_[0];                    // Set lpParms to buffer
    }
    else
    { copts_Parms_.clear();
      copts_.lpParms = NULL;
    }
    if (copts_.cbFormat != 0)
    { copts_Format_.resize(copts_.cbFormat,0);              // Allocate buffer
      cfgFile.read(&copts_Format_[0], copts_Format_.size());// Read format buffer
      copts_.lpFormat = &copts_Format_[0];                  // Set lpFormat to buffer
    }
    else
    { copts_Format_.clear();
      copts_.lpFormat = NULL;
    }
  }
  catch (fstream::failure const&)
  { // A read failed, clean up
    ZeroMemory(&copts_,sizeof(AVICOMPRESSOPTIONS));
    copts_Parms_.clear();
    copts_Format_.clear();   
    return false; 
  }
  return true;
}

Notas de código de muestra

El código de ejemplo captura vídeo desde una cámara de vídeo o webcam y lo guarda en un archivo AVI. Utiliza la clase OpenCV VideoCapture para acceder a la cámara y capturar el vídeo. Guardar el vídeo se realiza utilizando una versión de la clase OpenCV CvVideoWriter_VFW que modifiqué para guardar la configuración del códec. Trató de mantener los cambios al código original tan pequeños como sea posible. En el código, el segundo argumento de CvVideoWriter_VFW::open es un std::string. Si esta cadena tiene cuatro caracteres (como en un fourcc), se supone que un fourcc y se elige el códec correspondiente a este fourcc: conversión de los cuatro caracteres de 1 byte al código fourcc entero se realiza comúnmente con la macro mmioFOURCC, como en mmioFOURCC('D','I','V','X'); ver tinyurl.com/mmioFOURCC para obtener más detalles. De lo contrario, la cadena es tomada como el nombre de un archivo de configuración del códec. Si existe el archivo, la configuración es leer el archivo y utilizada para la compresión de vídeo. Si no existe, entonces se abre el cuadro de diálogo Opciones de compresión y puede seleccionarse manualmente un códec y su configuración; la configuración elegida, a continuación, se guarda en el archivo el nombre seleccionado para volver a utilizar la próxima vez que se ejecuta la aplicación. Nota: Necesitará una instalación de OpenCV para compilar y ejecutar el código de ejemplo.

Varias ventajas

La solución que presenta tiene varias ventajas. Cambiar la configuración de compresión para una aplicación es sólo una cuestión de cambiar uno de sus argumentos. No es necesario compilar o incluso detener la ejecución app. El método es independiente del codec y funciona para todos los códecs VfW. Algunos códecs permiten incluso procesamiento como marco el tamaño y el desentrelazado de imagen personalizado adicional. Todas estas opciones son capturadas en el archivo de configuración del códec.

El método funciona tan bien en sistemas heredados de Microsoft Windows (desde Windows 2000 adelante) y también con compiladores antiguos como Visual Studio 6.0. También, puede utilizarse con una gran variedad de idiomas que expone la interfaz VfW, como Visual Basic y C#. Se puede implementar para múltiples máquinas independientemente del estado actual de codec interno de cada máquina.

La principal condición es que esta solución está garantizada para trabajar sólo cuando se utiliza la misma versión exacta del códec. Si un códec de falta en un equipo determinado, o es una versión diferente de la que se usa para hacer el archivo de configuración, los resultados podrían ser indeterminados. Obviamente, no puede utilizarse nonVfW codecs, porque esta solución se basa en la API VfW.

Posibles extensiones a este trabajo incluyen asimismo guardar la configuración de audio compresor, que es manejados de forma idéntica configuración compresor de vídeo. También, porque AVISaveOptions admite de forma nativa con múltiples flujos de AVIs, la misma solución funcionará también en estos casos, y la configuración del códec para cada una de las corrientes puede escribirse en un solo archivo.

El otro común y más moderno video y audio procesamiento API de Windows es DirectShow. Es posible implementar una solución similar para DirectShow así, sino es un tema para un artículo futuro.

ADI Shavit es un consultor de visión de equipo. Ha estado trabajando en imagen y video sistemas de procesamiento de más de 15 años, especializada en análisis de video en tiempo real. Él puede ser contactado en adishavit@gmail.com.

Gracias a los siguientes expertos técnicos para revisar este artículo: Dana Shavit y Matthew Wilson