gpt4 book ai didi

opengl - 如何使用 GLSL 正确解压缩 V210 视频帧?

转载 作者:行者123 更新时间:2023-11-28 21:39:49 24 4
gpt4 key购买 nike

我有来自采集卡的 10 位 YUV (V210) 视频帧,我想在 GLSL 着色器中解压缩这些数据,并最终转换为 RGB 以进行屏幕输出。我在 Linux (OpenGL 4.3) 上使用 Quadro 4000 卡。

我正在使用以下设置上传纹理:

video frame: 720x486 pixels

physically occupies 933120 bytes in 128-byte aligned memory (stride of 1920)

texture is currently uploaded as 480x486 pixels (stride/4 x height) since this matches the byte count of the data

internalFormat of GL_RGB10_A2

format of GL_RGBA

type of GL_UNSIGNED_INT_2_10_10_10_REV

filtering is currently set to GL_NEAREST

为清楚起见,这里是上传命令:

int stride = ((m_videoWidth + 47) / 48) * 128;

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, stride / 4, m_videoHeight, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, bytes);

数据本身是这样打包的:

U Y V A |尤雅 | V Y U A |是的是的

或在此处查看 Blackmagic 的插图:http://i.imgur.com/PtXBJbS.png

每个纹素总共 32 位(“R、G、B” channel 各 10 位,alpha channel 2 位)。复杂的地方是 6 个像素被打包到这个 128 位的 block 中。这些 block 简单地重复上述模式,直到帧结束。

我知道可以使用 texture2D(tex, coord).rgb 访问每个纹素的组件,但由于每个纹素的顺序不同(例如 UYV 与 YUY),我知道必须操纵纹理坐标考虑到这一点。

但是,我不确定如何处理这个纹理中包含的像素比 GL 知道的更多的事实,我认为这意味着我必须考虑按比例放大/缩小以及最小/mag 过滤(我需要双线性)在我的着色器内部。输出窗口需要能够是任意大小(小于、等于或大于纹理),因此着色器不应该有任何与之相关的常量。

我怎样才能做到这一点?

最佳答案

这是包含所有 channel 和 RGB 转换的完整着色器(但未执行过滤):

#version 130
#extension GL_EXT_gpu_shader4 : enable
in vec2 texcoord;
uniform mediump sampler2D tex;
out mediump vec4 color;

// YUV offset
const vec3 yuvOffset = vec3(-0.0625, -0.5, -0.5);

// RGB coefficients
// BT.601 colorspace
const vec3 Rcoeff = vec3(1.1643, 0.000, 1.5958);
const vec3 Gcoeff = vec3(1.1643, -0.39173, -0.81290);
const vec3 Bcoeff = vec3(1.1643, 2.017, 0.000);

// U Y V A | Y U Y A | V Y U A | Y V Y A

int GROUP_FOR_INDEX(int i) {
return i / 4;
}

int SUBINDEX_FOR_INDEX(int i) {
return i % 4;
}

int _y(int i) {
return 2 * i + 1;
}

int _u(int i) {
return 4 * (i/2);
}

int _v(int i) {
return 4 * (i / 2) + 2;
}

int offset(int i) {
return i + (i / 3);
}

vec3 ycbcr2rgb(vec3 yuvToConvert) {
vec3 pix;
yuvToConvert += yuvOffset;
pix.r = dot(yuvToConvert, Rcoeff);
pix.g = dot(yuvToConvert, Gcoeff);
pix.b = dot(yuvToConvert, Bcoeff);
return pix;
}

void main(void) {
ivec2 size = textureSize2D(tex, 0).xy; // 480x486
ivec2 sizeOrig = ivec2(size.x * 1.5, size.y); // 720x486

// interpolate 0,0 -> 1,1 texcoords to 0,0 -> 720,486
ivec2 texcoordDenorm = ivec2(texcoord * sizeOrig);

// 0 1 1 2 3 3 4 5 5 6 7 7 etc.
int yOffset = offset(_y(texcoordDenorm.x));
int sourceColumnIndexY = GROUP_FOR_INDEX(yOffset);

// 0 0 1 1 2 2 4 4 5 5 6 6 etc.
int uOffset = offset(_u(texcoordDenorm.x));
int sourceColumnIndexU = GROUP_FOR_INDEX(uOffset);

// 0 0 2 2 3 3 4 4 6 6 7 7 etc.
int vOffset = offset(_v(texcoordDenorm.x));
int sourceColumnIndexV = GROUP_FOR_INDEX(vOffset);

// 1 0 2 1 0 2 1 0 2 etc.
int compY = SUBINDEX_FOR_INDEX(yOffset);

// 0 0 1 1 2 2 0 0 1 1 2 2 etc.
int compU = SUBINDEX_FOR_INDEX(uOffset);

// 2 2 0 0 1 1 2 2 0 0 1 1 etc.
int compV = SUBINDEX_FOR_INDEX(vOffset);

vec4 y = texelFetch(tex, ivec2(sourceColumnIndexY, texcoordDenorm.y), 0);
vec4 u = texelFetch(tex, ivec2(sourceColumnIndexU, texcoordDenorm.y), 0);
vec4 v = texelFetch(tex, ivec2(sourceColumnIndexV, texcoordDenorm.y), 0);

vec3 outColor = ycbcr2rgb(vec3(y[compY], u[compU], v[compV]));

color = vec4(outColor, 1.0);
}

如果要在屏幕上放大图像,那么您可能需要进行双线性过滤,但这需要在着色器中执行。

关于opengl - 如何使用 GLSL 正确解压缩 V210 视频帧?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20317882/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com