How can I unzip a V210 video cassette using GLSL?

I have 10-bit YUV (V210) video clips coming from a capture card, and I would like to unpack this data inside the GLSL shader and ultimately convert to RGB to display the screen. I am using a Quadro 4000 card on Linux (OpenGL 4.3).

I load the texture with the following settings:

video frame: 720x486 pixels

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

the texture is currently loaded as 480x486 pixels (step / 4 x height), as this corresponds to the number of data bytes

internalFormat of GL_RGB10_A2

format GL_RGBA

type GL_UNSIGNED_INT_2_10_10_10_REV

Currently filtering

set to GL_NEAREST

The following is the boot command:

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

:

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

Blackmagic : http://i.imgur.com/PtXBJbS.png

32 ( 10 "R, G, B" 2 ). , , 6 128 . .

, 2D (tex, coord).rgb, (, UYV vs YUY) , , .

, , , GL , , , , /, /mag filtering ( ) . (, , ), , .

?

+4
2

, , .

, : , 4 , . , , .

, .

, ?

:

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

, Y. 1d- (720 x 1 ). : , . -, Y :

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


  0      1      2      3      4      5   ..... // out column (0-720)

  0      1      1      2      3      3   ..... // source column index (0-480)
  1      0      2      1      0      2   ..... // Y sample index in column (range 0-2)

Y (Luminance), x. , texel . , . DirectX vec4/float4 , R/G/B/A. , GLSL .

, Y. U V.

, , , . , . .

, , . .

, DirectX. .

!

+5

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

, , , , .

+5

All Articles