YV12 para RGB - O que há de errado com meu algoritmo?


8

Estou tentando converter YV12 em RGB usando o seguinte sombreador de fragmento:

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

Abaixo está a imagem original seguida pela imagem convertida. Com base na saída, você pode determinar onde eu devo procurar para determinar o que está causando a decodificação incorreta?

Fonte Imagem decodificada


Como dito pelos socorristas, há definitivamente um problema com o número de bytes por linha. Eu me pergunto outra coisa. YV12 subamostrou os canais U e V. Como você gerencia essa alteração de dimensão com seu shader? Quais são os tamanhos das suas texturas? Você deixa o OpenGL lidar com isso?
Stéphane Péchard

No loop de desenho, os dados de imagem são fornecidos em uma matriz de 3 elementos em que a ordem é sempre YUV (independentemente de YV12 ou YUV420p etc.). Uso a largura / altura total para o elemento Y e desloco a largura / altura para a direita 1 (divida por 2) para os elementos UV. Essas texturas são então vinculadas ao shader que lida com o restante. Os tamanhos de textura com os quais trabalho normalmente são de 1280x720.
Erro 454

Respostas:


5

A imagem de saída possui linhas deslocadas uma contra a outra, o que geralmente ocorre devido à distância incorreta [byte] entre as linhas (passo). Ou seja, a matemática da conversão de cores talvez esteja correta, no entanto, você está pegando o pixel de origem da posição errada e / ou colocando o pixel de saída no lugar errado.

Por motivos de desempenho, as imagens YV12 podem estar usando avanços estendidos no hardware para facilitar o desempenho. Por exemplo, a imagem YV12 de 320x240 pode ter um passo de 512 e isso significa que o buffer de dados é um espaço de dados de 512x240 (512x240 bytes para Y, seguido por duas matrizes 256x120 para V e U) onde a imagem de carga útil à esquerda e lá é preenchimento invisível à direita.


Vejo que não estou dando conta do progresso. Vou implementar isso quando puder e atualizar a pergunta assim que puder verificar se esse é realmente o problema.
Erro 454

No final, o passo foi a resposta. Foi a única coisa que mudei e agora tudo funciona. Ótimo olho!
Erro 454

1

Não sei nada sobre programação de shader fragment, mas para mim parece que o tamanho da palavra da entrada e da saída varia. E para mim, parece que você não presta atenção em descompactar e reembalar os bytes YV12 .

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.