YV12 a RGB: ¿qué hay de malo en mi algoritmo?

8

Estoy intentando convertir YV12 a RGB usando el siguiente sombreador de fragmentos:

precision mediump float;
uniform sampler2D tex0, tex1, tex2;
varying vec2 v_texCoord;

void main(void) {
    float r, g, b, y, u, v;
    y = texture2D(tex0, v_texCoord).x;
    u = texture2D(tex1, v_texCoord).x;
    v = texture2D(tex2, v_texCoord).x;

    y = 1.1643 * (y - 0.0625);
    u = u - 0.5;
    v = v - 0.5;

    r = y + 1.5958 * v;
    g = y - 0.39173 * u - 0.81290 * v;
    b = y + 2.017 * u;

    gl_FragColor = vec4(r, g, b, 1.0);
}

A continuación se muestra la imagen original seguida de la imagen convertida. Según el resultado, ¿puede determinar dónde podría mirar para determinar qué está causando la decodificación incorrecta?

Fuente Imagen decodificada

Error 454
fuente
Como dijeron los primeros en responder, definitivamente hay un problema con el número de bytes por línea. Me pregunto otra cosa. YV12 tiene canales U y V submuestreados. ¿Cómo gestionas este cambio de dimensión con tu sombreador? ¿Cuáles son los tamaños de tus texturas? ¿Dejas que OpenGL maneje esto?
Stéphane Péchard
En el ciclo de dibujo, los datos de la imagen se me dan en una matriz de 3 elementos donde el orden siempre es YUV (independientemente de YV12 o YUV420p, etc.). Uso el ancho / alto completo para el elemento Y y desplazo el ancho / alto a la derecha 1 (dividir por 2) para los elementos UV. Estas texturas se unen al sombreador que maneja el resto. Los tamaños de textura con los que he estado trabajando suelen ser de 1280x720.
Error 454

Respuestas:

5

La imagen de salida tiene líneas desplazadas una contra otra, lo que generalmente se debe a una distancia incorrecta [byte] entre las líneas (zancada). Es decir, la matemática de conversión de color es quizás correcta, sin embargo, está tomando el píxel de origen de la posición incorrecta y / o colocando el píxel de salida en el lugar incorrecto.

Por razones de rendimiento, las imágenes YV12 pueden estar utilizando pasos extendidos en el hardware para facilitar el rendimiento. Por ejemplo, la imagen de 320x240 YV12 podría tener un paso de 512 y esto significa que el búfer de datos es un espacio de datos de 512x240 (512x240 bytes para Y, seguido de dos matrices de 256x120 para V y U) donde la imagen de carga a la izquierda, y allí Es un relleno invisible a la derecha.

Roman R.
fuente
Veo que no estoy dando cuenta de la zancada. Implementaré esto cuando pueda y actualizaré la pregunta una vez que pueda verificar si este es realmente el problema.
Error 454
Al final, el paso fue la respuesta. Fue lo único que cambié y ahora todo funciona. Gran ojo!
Error 454
1

No sé nada sobre la programación de sombreadores de fragmentos, pero para mí parece que el tamaño de palabra de la entrada y la salida varían. Y a mí me parece que no prestas atención a desempacar y reempacar los bytes YV12 .

bjoernz
fuente