Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I've done this with YUV frames captured from a CCD camera. Unfortunately, there are a number of different YUV formats. I believe the one that Apple uses for the <code>GL_YCBCR_422_APPLE</code> texture format is technically 2VUY422. To convert an image from a YUV422 frame generated by an IIDC Firewire camera to 2VUY422, I've used the following: </p> <pre><code>void yuv422_2vuy422(const unsigned char *theYUVFrame, unsigned char *the422Frame, const unsigned int width, const unsigned int height) { int i =0, j=0; unsigned int numPixels = width * height; unsigned int totalNumberOfPasses = numPixels * 2; register unsigned int y0, y1, y2, y3, u0, u2, v0, v2; while (i &lt; (totalNumberOfPasses) ) { u0 = theYUVFrame[i++]-128; y0 = theYUVFrame[i++]; v0 = theYUVFrame[i++]-128; y1 = theYUVFrame[i++]; u2 = theYUVFrame[i++]-128; y2 = theYUVFrame[i++]; v2 = theYUVFrame[i++]-128; y3 = theYUVFrame[i++]; // U0 Y0 V0 Y1 U2 Y2 V2 Y3 // Remap the values to 2VUY (YUYS?) (Y422) colorspace for OpenGL // Y0 U Y1 V Y2 U Y3 V // IIDC cameras are full-range y=[0..255], u,v=[-127..+127], where display is "video range" (y=[16..240], u,v=[16..236]) the422Frame[j++] = ((y0 * 240) / 255 + 16); the422Frame[j++] = ((u0 * 236) / 255 + 128); the422Frame[j++] = ((y1 * 240) / 255 + 16); the422Frame[j++] = ((v0 * 236) / 255 + 128); the422Frame[j++] = ((y2 * 240) / 255 + 16); the422Frame[j++] = ((u2 * 236) / 255 + 128); the422Frame[j++] = ((y3 * 240) / 255 + 16); the422Frame[j++] = ((v2 * 236) / 255 + 128); } } </code></pre> <p>For efficient display of a YUV video source, you may wish to use <a href="http://developer.apple.com/documentation/graphicsimaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/opengl_texturedata.html#//apple_ref/doc/uid/TP40001987-CH407-SW24" rel="noreferrer">Apple's client storage extension</a>, which you can set up using something like the following:</p> <pre><code>glEnable(GL_TEXTURE_RECTANGLE_EXT); glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 1); glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_EXT, videoImageWidth * videoImageHeight * 2, videoTexture); glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_SHARED_APPLE); glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, videoImageWidth, videoImageHeight, 0, GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE, videoTexture); </code></pre> <p>This lets you quickly change out the data stored within your client-side video texture before each frame to be displayed on the screen.</p> <p>To draw, you could then use code like the following:</p> <pre><code>glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_TEXTURE_2D); glViewport(0, 0, [self frame].size.width, [self frame].size.height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); NSRect bounds = NSRectFromCGRect([self bounds]); glOrtho( (GLfloat)NSMinX(bounds), (GLfloat)NSMaxX(bounds), (GLfloat)NSMinY(bounds), (GLfloat)NSMaxY(bounds), -1.0, 1.0); glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 1); glTexSubImage2D (GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, videoImageWidth, videoImageHeight, GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE, videoTexture); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, videoImageHeight); glTexCoord2f(0.0f, videoImageHeight); glVertex2f(0.0f, 0.0f); glTexCoord2f(videoImageWidth, videoImageHeight); glVertex2f(videoImageWidth, 0.0f); glTexCoord2f(videoImageWidth, 0.0f); glVertex2f(videoImageWidth, videoImageHeight); glEnd(); </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload