Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用OpenGL将RGBA转换为NV12?_Opengl_Shader_Yuv_Rgba_Nv12 Nv21 - Fatal编程技术网

如何使用OpenGL将RGBA转换为NV12?

如何使用OpenGL将RGBA转换为NV12?,opengl,shader,yuv,rgba,nv12-nv21,Opengl,Shader,Yuv,Rgba,Nv12 Nv21,我需要将RGBA转换为NV12,使用OpenGL着色器作为编码器输入 已经渲染了两个不同的片段着色器,两个纹理都来自一个摄影机。使用v4l2获取相机图像(YUV)。然后,将YUV转换为RGB,让OpenGL渲染。下一步,我需要将RGB转换为NV12作为编码器输入,因为编码器只接受NV12格式。使用计算着色器将RGB转换为平面YUV,然后将UV平面的采样减少两倍 以下是计算着色器: #version 450 core layout(local_size_x = 32, local_size_y =

我需要将RGBA转换为NV12,使用OpenGL着色器作为编码器输入


已经渲染了两个不同的片段着色器,两个纹理都来自一个摄影机。使用v4l2获取相机图像(YUV)。然后,将YUV转换为RGB,让OpenGL渲染。下一步,我需要将RGB转换为NV12作为编码器输入,因为编码器只接受NV12格式。

使用计算着色器将RGB转换为平面YUV,然后将UV平面的采样减少两倍

以下是计算着色器:

#version 450 core
layout(local_size_x = 32, local_size_y = 32) in;
layout(binding = 0) uniform sampler2D src;
layout(binding = 0) uniform writeonly image2D dst_y;
layout(binding = 1) uniform writeonly image2D dst_uv;
void main() {
    ivec2 id = ivec2(gl_GlobalInvocationID.xy);
    vec3 yuv = rgb_to_yuv(texelFetch(src, id).rgb);
    imageStore(dst_y, id, vec4(yuv.x,0,0,0));
    imageStore(dst_uv, id, vec4(yuv.yz,0,0));
}
有很多不同的YUV约定,我不知道你的编码器期望哪一个。因此,用yuv->rgb转换的倒数替换上面的
rgb_to_yuv

然后进行如下操作:

GLuint in_rgb = ...; // rgb(a) input texture
int width = ..., height = ...; // the size of in_rgb

GLuint tex[2]; // output textures (Y plane, UV plane)

glCreateTextures(GL_TEXTURE_2D, tex, 2);
glTextureStorage2D(tex[0], 1, GL_R8, width, height); // Y plane

// UV plane -- TWO mipmap levels
glTextureStorage2D(tex[1], 2, GL_RG8, width, height);

// use this instead if you need signed UV planes:
//glTextureStorage2D(tex[1], 2, GL_RG8_SNORM, width, height);

glBindTextures(0, 1, &in_rgb);
glBindImageTextures(0, 2, tex);
glUseProgram(compute); // the above compute shader

int wgs[3];
glGetProgramiv(compute, GL_COMPUTE_WORK_GROUP_SIZE, wgs);
glDispatchCompute(width/wgs[0], height/wgs[1], 1);

glUseProgram(0);
glGenerateTextureMipmap(tex[1]); // downsamples tex[1] 

// copy data to the CPU memory:
uint8_t *data = (uint8_t*)malloc(width*height*3/2);
glGetTextureImage(tex[0], 0, GL_RED, GL_UNSIGNED_BYTE, width*height, data);
glGetTextureImage(tex[1], 1, GL_RG, GL_UNSIGNED_BYTE, width*height/2,
    data + width*height);
免责声明:

  • 此代码未经测试
  • 它假设宽度和高度可以被32整除
  • 它可能在某个地方缺少了一个记忆障碍
  • 这并不是从GPU中读取数据的最有效方法——在计算下一帧数据时,您可能至少需要读取一帧数据

我想将YUV约定用作NV12(YYYY UUVV)。所以我需要使用计算着色器来传播Y和UV。最后,我将得到两个纹理Y和UV。但是我如何将这两种纹理组合成一种呢。就像我可以输出一个缓冲区或其他可以保存为NV12格式并可以在yuv播放器中成功显示的东西一样。@JuliaDing:您的NV12使用者的界面是什么?它期望什么?GPU缓冲区?GPU纹理?CPU RAM内存?它是CPU RAM内存。@JuliaDing:我相应地编辑了它。请注意,它给出了
yyyyyyyy uv
,这就是NV12通常的含义。如果您需要
yyyyyyyyyyyyyyuvv
,则需要三种纹理。