Skip to content

Instantly share code, notes, and snippets.

@crearo
Last active August 1, 2024 01:57
Show Gist options
  • Save crearo/0d50442145b63c6c288d1c1675909990 to your computer and use it in GitHub Desktop.
Save crearo/0d50442145b63c6c288d1c1675909990 to your computer and use it in GitHub Desktop.
A fragment shader to convert NV12 to RGB.
/** A fragment shader to convert NV12 to RGB.
* Input textures Y - is a block of size w*h.
* texture UV is of size w*h/2.
* Remember, both U and V are individually of size w/2*h/2, but they are interleaved.
* The layout looks like this :
* ----------
* | |
* | Y | size = w*h
* | |
* |________|
* |UVUVUVUV|size = w/2*h/2
* |UVUVUVUV|size = w/2*h/2
* ----------
*/
precision highp float;
varying vec2 vTextureCoord;
uniform sampler2D sTextureY;
uniform sampler2D sTextureUV;
uniform float sBrightnessValue;
uniform float sContrastValue;
void main (void) {
float r, g, b, y, u, v;
// We had put the Y values of each pixel to the R,G,B components by GL_LUMINANCE,
// that's why we're pulling it from the R component, we could also use G or B
y = texture2D(sTextureY, vTextureCoord).r;
// We had put the U and V values of each pixel to the A and R,G,B components of the
// texture respectively using GL_LUMINANCE_ALPHA. Since U,V bytes are interspread
// in the texture, this is probably the fastest way to use them in the shader
u = texture2D(sTextureUV, vTextureCoord).r - 0.5;
v = texture2D(sTextureUV, vTextureCoord).a - 0.5;
// The numbers are just YUV to RGB conversion constants
r = y + 1.13983*v;
g = y - 0.39465*u - 0.58060*v;
b = y + 2.03211*u;
r = r * sContrastValue + sBrightnessValue;
g = g * sContrastValue + sBrightnessValue;
b = b * sContrastValue + sBrightnessValue;
// We finally set the RGB color of our pixel
gl_FragColor = vec4(r, g, b, 1.0);
}
@AhmedX6
Copy link

AhmedX6 commented Dec 2, 2020

Hello could you share the code that's using this shader. I get a weird result (green image)

@crearo
Copy link
Author

crearo commented Dec 3, 2020

Checkout http://github.com/crearo/grafika. I haven't touched this code in a while so I'm not certain if you'll find it there.

In general though, if you're getting a green image, you're close. Swap U with V as an initial try.

@AhmedX6
Copy link

AhmedX6 commented Dec 7, 2020

Hi Crearo,

Thanks for your answer.
I'm using OPENGL ES on AOSP.

glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, cameraTexY);
    glUniform1i(locTexY, GL_ZERO);
    glBindVertexArray(VAO);
    glTexSubImage2D(GL_TEXTURE_2D, GL_ZERO, GL_ZERO, GL_ZERO, mVideoCapture.getWidth(),
                    mVideoCapture.getHeight(), GL_RED, GL_UNSIGNED_BYTE, mVideoCapture.getYBuffer()); //Y buffer size is 345600
    glBufferSubData(GL_ARRAY_BUFFER, GL_ZERO, sizeof(vertices), vertices);

    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, cameraTexU);
    glUniform1i(locTexU, GL_ZERO);
    glBindVertexArray(VAO);
    glTexSubImage2D(GL_TEXTURE_2D, GL_ZERO, GL_ZERO, GL_ZERO, mVideoCapture.getWidth() / 2,
                    mVideoCapture.getHeight() / 2, GL_RED, GL_UNSIGNED_BYTE, mVideoCapture.getUVBuffer()); //UV buffer size 172800
    glBufferSubData(GL_ARRAY_BUFFER, GL_ZERO, sizeof(vertices), vertices);

When I swap I got blue image.. But still unable to decode colors :/

A little help would be appreciated.

Thanks a lot

@tqk2811
Copy link

tqk2811 commented Aug 27, 2021

Hello could you share the code that's using this shader. I get a weird result (green image)

Haha, I got red image at first try.
image


And seem like got some bropblem with image
image


NV12Render for anyone need example
image

@xueshenan
Copy link

@tqk2811 I have same problem, always display red image.
Have you solved this problem yet?

@tqk2811
Copy link

tqk2811 commented Dec 1, 2023

@tqk2811 I have same problem, always display red image. Have you solved this problem yet?

-Check width and linesize
-Check color order: ex rgba and bgra ....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment