Wrong 4:2:2 interpolation in OpenGL example

Ask software engineering and SDK questions for developers working on Mac OS X, Windows or Linux.
  • Author
  • Message
Offline

Steinar H. Gunderson

  • Posts: 70
  • Joined: Fri Aug 14, 2015 12:17 pm

Wrong 4:2:2 interpolation in OpenGL example

PostMon Aug 17, 2015 1:30 pm

Hi,

The DeckLink SDK includes a sample called OpenGLComposite.cpp, that among other things does upsampling/converting from 4:2:2 YCbCr to full RGB. This is done through this shader snippet:

// For U0 Y0 V0 Y1 macropixel, lookup Y0 or Y1 based on whether
// the original texture x coord is even or odd.
" if (fract(floor(tx * true_width + 0.5) / 2.0) > 0.0) \n"
" Y = texture2D(UYVYtex, vec2(tx,ty)).a; \n" // odd so choose Y1
" else \n"
" Y = texture2D(UYVYtex, vec2(tx,ty)).g; \n" // even so choose Y0

This, unfortunately, only makes sense when hitting exactly on a texel. If not, and you sample between them, you'll be doing linear interpolation not against the neighboring texel, but the one two texels away, which causes strange artifacts if you have fine horizontal detail. Doing this kind of interpolation properly in a shader is surprisingly annoying (you'd have to handle the case of interpolating within the macropixel, i.e. between A and G separately from interpolating between two macropixels), so in lieu of universal YCbCr extension support, there are basically two options:

1) Have a separate pass first that does only upsampling to RGB, where you have control over what pixels you sample (instead of trying to map it onto a cube).
2) For 8-bit 4:2:2 specifically, you can actually cheat a bit, by uploading the data twice (this wastes texture bandwidth and memory, but with a PBO at least the upload isn't too expensive, and you save on shader arithmetic): Once as a full-width two-channel texture, and once as a half-width four-channel texture. Then you sample Y from the former (using the G component only, discarding R) and Cb and Cr from the latter (using the R and B components only, discarding G and A), and all interpolation just works by itself.

It would be great if you could correct your example, since it's going to be a very common problem for people who want to do processing in OpenGL, and it's not very nice to have an example that's silently and subtly wrong :-)

Return to Software Developers

Who is online

Users browsing this forum: PainComper and 9 guests