FFmpeg BMP a YUV x264 cambio de color

Cuando codifico una secuencia particular de archivos de imagen BMP a AVC/H.264, los colores se desplazan. ¿Por qué pasó esto?

Pero si convierto los BMP a PNG antes de ejecutar ffmpeg, la conversión de video parece correcta. Mi material de origen está en BMP y preferiría no convertir manualmente todo a PNG para realizar la solución.


Para el propósito de esta pregunta, tomé la secuencia de imágenes y las resumí en estos colores principales que se utilizan:

ingrese la descripción de la imagen aquí

Primer intento de codificación (el blanco puro se vuelve notablemente verde):ffmpeg -i 000.bmp -pix_fmt yuv420p -vcodec libx264 -profile:v main -crf 16 first.mp4

ingrese la descripción de la imagen aquí

Segundo intento (aún peor):ffmpeg -i 000.bmp -vf "colormatrix=bt601:bt709" -pix_fmt yuv420p -vcodec libx264 -profile:v main -crf 16 second.mp4

ingrese la descripción de la imagen aquí

Tercer intento (demasiado brillante):ffmpeg -i 000.bmp -vf "scale=in_range=full:in_color_matrix=bt709:out_range=full:out_color_matrix=bt709" -pix_fmt yuv420p -vcodec libx264 -profile:v main -crf 16 third.mp4

ingrese la descripción de la imagen aquí

Sin embargo, usar una versión PNG de la misma imagen de entrada funciona muy bien:ffmpeg -i 000.png -pix_fmt yuv420p -vcodec libx264 -profile:v main -crf 16 fourth.mp4

ingrese la descripción de la imagen aquí


Estoy usando la última versión de FFmpeg Windows x86-64 (2016-11-22 Git d316b21):

C:\Temp> ffmpeg.exe -version
ffmpeg version N-82597-gd316b21 Copyright (c) 2000-2016 the FFmpeg developers
built with gcc 5.4.0 (GCC)
configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-dxva2
    --enable-libmfx --enable-nvenc --enable-avisynth --enable-bzlib --enable-fontconfig
    --enable-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray
    --enable-libbs2b --enable-libcaca --enable-libfreetype --enable-libgme
    --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame
    --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenh264
    --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libschroedinger
    --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora
    --enable-libtwolame --enable-libvidstab --enable-libvo-amrwbenc --enable-libvorbis
    --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264
    --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg --enable-lzma
    --enable-decklink --enable-zlib
libavutil      55. 40.100 / 55. 40.100
libavcodec     57. 66.106 / 57. 66.106
libavformat    57. 58.100 / 57. 58.100
libavdevice    57.  2.100 / 57.  2.100
libavfilter     6. 67.100 /  6. 67.100
libswscale      4.  3.101 /  4.  3.101
libswresample   2.  4.100 /  2.  4.100
libpostproc    54.  2.100 / 54.  2.100

Para reformular mi pregunta, ¿cómo puedo convertir la secuencia de imágenes BMP en un video H.264 sin cambios de color no deseados?

No estoy seguro, así que confirme antes de considerar esto como una respuesta. Intente con '-vcodec libx264rgb' en lugar de '-vcodec libx264'
Dado que el título de la pregunta trata sobre un cambio de color al codificar en formato YUV, ¿cómo abordará el problema la codificación en RGB? El problema aquí es especificar correcta y completamente los atributos de la fuente, para que swscale pueda transformarla correctamente. También es necesario marcar el flujo de salida para jugadores perezosos/descuidados.
Al OP. ¿Cómo convertiste BMP a PNG? ¿Y cómo se generaron las BMP?
@Mulvya Para mi MCVE en esta pregunta, generé los BMP a mano en MS Paint. Convertí a PNG usando IrfanView. Mirando los archivos en un editor hexadecimal, el BMP no tiene perfil de color ni metadatos relacionados. El PNG parece tener un fragmento gAMA y un fragmento sRGB agregados de manera predeterminada.
@RawBean Sugerencia interesante. Usando -vcodec libx264rgb -profile:v high444(menos -pix_fmt), obtengo un video con colores perfectos sin desviación. Sin embargo, solo se puede reproducir en MPC-HC, no en Windows Explorer o Mozilla Firefox. Creo que sería bueno permanecer dentro del perfil principal de H.264.
@RawBean Después de probar diferentes cosas durante varias horas, en libx264rgbvez de eso , me libx264solucionó el problema. ¡¡Muchas gracias!!

Respuestas (1)

Aparentemente, FFmpeg no establece correctamente los atributos de color de entrada para la entrada BMP (probablemente porque el archivo no contiene esos metadatos) y el decodificador BMP no verifica los atributos marcados manualmente. Sin embargo, podemos forzarlo usando el filtro de formato.

ffmpeg -i 000.bmp -vf format=rgb24 -pix_fmt yuv420p -vcodec libx264 -profile:v main -crf 16 first.mp4
¡Esto funciona perfectamente! Obtiene el mismo resultado que usar una entrada PNG. ¡Muchas gracias! Aún así, esto es un poco loco porque los archivos BMP solo pueden ser RGB24, nada más...
Según el decodificador, los BMP pueden tener un formato de píxel de una paleta de 8 bits o RGB de 5 bits o G de 6 bits, etc. (también pueden tener alfa). Pero sí, el espacio de color es RGB. El decodificador es originalmente de 2005 y su trabajo es llenar la estructura AVFrame pasada a filtros con atributos relevantes. Dado que BMP no ha cambiado mucho y no se usa mucho, nadie se ha molestado en actualizar el código con nuevas banderas agregadas desde entonces.