YV12 à RGB - Quel est le problème avec mon algorithme?

8

J'essaie de convertir YV12 en RVB en utilisant le fragment shader suivant:

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

Ci-dessous, l'image d'origine suivie de l'image convertie. Sur la base de la sortie, pouvez-vous déterminer où je pourrais chercher pour déterminer ce qui cause le décodage incorrect?

La source Image décodée

Erreur 454
la source
Comme l'ont dit les premiers intervenants, il y a certainement un problème avec le nombre d'octets par ligne. Je me demande autre chose. YV12 a des canaux U et V sous-échantillonnés. Comment gérez-vous ce changement de dimension avec votre shader? Quelles sont les tailles de vos textures? Laissez-vous OpenGL gérer cela?
Stéphane Péchard
Dans la boucle de dessin, les données d'image me sont données dans un tableau à 3 éléments où l'ordre est toujours YUV (indépendamment de YV12 ou YUV420p, etc.). J'utilise la largeur / hauteur complète pour l'élément Y et je décale la largeur / hauteur de droite 1 (diviser par 2) pour les éléments UV. Ces textures sont ensuite liées au shader qui gère le reste. Les tailles de texture avec lesquelles j'ai travaillé sont généralement 1280x720.
Erreur 454

Réponses:

5

L'image de sortie présente des lignes décalées les unes contre les autres, ce qui est généralement dû à une distance [octet] incorrecte entre les lignes (foulée). Autrement dit, les calculs de conversion des couleurs sont peut-être corrects, mais vous prenez le pixel source à une mauvaise position et / ou placez le pixel de sortie au mauvais endroit.

Pour des raisons de performances, les images YV12 peuvent utiliser des avancées importantes dans le matériel pour faciliter les performances. Par exemple, une image 320x240 YV12 peut avoir une foulée de 512 et cela signifie que le tampon de données est un espace de données 512x240 (512x240 octets pour Y, suivi de deux tableaux 256x120 pour V et U) où l'image de charge utile à gauche, et là est rembourrage invisible sur la droite.

Roman R.
la source
Je vois que je ne tiens pas compte de la foulée. Je vais implémenter cela quand je peux et mettre à jour la question une fois que je pourrai vérifier si c'est bien le problème.
Erreur 454
En fin de compte, la foulée était la réponse. C'est la seule chose que j'ai changé et maintenant tout fonctionne. Super œil!
Erreur 454
1

Je ne connais rien à la programmation de shaders de fragments, mais pour moi, il semble que la taille des mots de l'entrée et de la sortie varie. Et pour moi, il semble que vous ne faites pas attention au déballage et au reconditionnement des octets YV12 .

bjoernz
la source