0

I'm getting one buffer in YUYV 4:2:2 format from v4l. I would like to separate Y & UV from this buffer to get 2 buffers: buffer Y & buffer UV to be able to pass it to OpenGL and display the image in C++.

The buffer length is 1280 * 720 * 2 = 1843200 bytes

Is it possible, what is the algorithm?

V4L is sending one buffer 4:2:2 YUV but my shader is waiting 2 buffers

const char gFragmentNV12ToRGB[] =
    "#version 320 es\n"
    "precision highp float;\n"
    "in vec2 TexCoords;\n"
    "out vec4 color;\n"
    "uniform sampler2D text;\n"
    "layout(binding = 0) uniform sampler2D textureY;\n"
    "layout(binding = 1) uniform sampler2D textureUV;\n"
    "void main() {\n"
    "   float r, g, b, y, u, v;\n"
    "   y = texture(textureY, TexCoords).r;\n"
    "   u = texture(textureUV, TexCoords).r - 0.5;\n"
    "   v = texture(textureUV, TexCoords).a - 0.5;\n"
    "   r = y + 1.13983 * v;\n"
    "   g = y - 0.39465 * u - 0.58060 * v;\n"
    "   b = y + 2.03211 * u;\n"
    "   color = vec4(r, g, b, 1.0);\n"
    "}\n";

So I need to split my buffer first, but don't know how to proceed as I don't know the structure of the YUYV buffer...

The best would be to be able to send one buffer to GPU and he does the job...

genpfault
  • 51,148
  • 11
  • 85
  • 139
X6Entrepreneur
  • 971
  • 2
  • 10
  • 30
  • Are you sure you only have 4 bits for every component? That will not produce very high-quality images – Botje Aug 05 '21 at 14:12
  • 1
    @Botje: based on OP's numbers that's 8-bit per component; recall that YUYV 4:2:2 implies that the UV planes are sub-sampled. – Yakov Galka Aug 05 '21 at 16:50
  • Doh. Good point. – Botje Aug 05 '21 at 19:46
  • any idea, I have one buffer YUV would like to split into one buffer Y and one buffer UV – X6Entrepreneur Aug 05 '21 at 22:51
  • @DevAndroid: which version of OpenGL are you using? If you have compute, I'd simply fire up a compute shader to split the data into `YYYY` 1-channel texture and `UVUV` 2-channel texture (similar [to this answer](https://stackoverflow.com/a/55342921/277176)). Also note that, unless you need to do filtering, you could directly render YUV 4:2:2 onto the screen with an appropriate shader. – Yakov Galka Aug 06 '21 at 16:56
  • @YakovGalka I'm using OpenGL ES 3.0 (#version 320 es). Yes I need that shader takes in parameter one buffer YUV and display it. If it's possible to render YUV to texture that would be very nice ! But never found a solution or a sample to do that – X6Entrepreneur Aug 20 '21 at 09:07
  • @DevAndroid: so, did you try implementing it on your own? What problems did you face? Perhaps update your question with some of your attempts and specific problems you faced (do you not know how to create the buffers? do you not know how to attach them? did your shader compilation failed? etc)... Your current questions are: "is it possible?" -- of course, YES; "what is the algorithm?" -- "copy from YUV to Y and UV". You are obviously asking for an implementation instead -- and you are more likely to get one if you show your failed attempts. – Yakov Galka Aug 23 '21 at 18:21
  • @YakovGalka Yes I don't know just how to split the Y and UV buffer, I don't understand how the buffer YUYV 4:2:2 how it is structured. Is it possible to send one sampler to shader and display it directly (for this I will need a sample shader) or maybe use CPU split buffer first and then send it to my shader (I'll edit my question) – X6Entrepreneur Aug 27 '21 at 13:29
  • @YakovGalka any idea ? – X6Entrepreneur Sep 06 '21 at 08:34
  • @DevAndroid interpolate the us in the vs and the vs in the us. – Yakov Galka Sep 07 '21 at 00:51

1 Answers1

0

I finally found how to render YUV 4:2:2 from one sampler only using OpenGL ES 3.0 ... To bad there are no examples on net ...

Here is the final shader

const char gFragment4:2:2ToRGB[] =
    "#version 320 es\n"
    "precision highp float;\n"
    "in vec2 TexCoords;\n"
    "out vec4 color;\n"
    "layout(binding = 0) uniform sampler2D textureYUV;\n"
    "void main() {\n"
    "   float r, g, b, y, u, v;\n"
    "   y = texture(textureYUV, TexCoords).r;\n"
    "   u = texture(textureYUV, TexCoords).g - 0.5;\n"
    "   v = texture(textureYUV, TexCoords).a - 0.5;\n"
    "   r = y + 1.13983 * v;\n"
    "   g = y - 0.39465 * u - 0.58060 * v;\n"
    "   b = y + 2.03211 * u;\n"
    "   color = vec4(r, g, b, 1.0);\n"
    "}\n";
X6Entrepreneur
  • 971
  • 2
  • 10
  • 30