title: Render YUV video in OpenGL of ffmpeg using CVPixelBufferRef and Shaders
body: <p>I'm using to render YUV frames of ffmpeg with the iOS 5.0 method "CVOpenGLESTextureCacheCreateTextureFromImage". </p>
  
  <p>I'm using like the apple example <a href="https://developer.apple.com/library/ios/#samplecode/GLCameraRipple/Introduction/Intro.html" rel="nofollow">GLCameraRipple</a></p>
  
  <p>My result in iPhone screen is this: <a href="http://s48.photobucket.com/albums/f235/korn25/ffmpeg/?action=view&amp;current=Error_YUV.jpg" rel="nofollow">iPhone Screen</a></p>
  
  <p>I need to know I'm doing wrong.</p>
  
  <p>I put part of my code to find errors.</p>
  
  <p>ffmpeg configure frames: </p>
  
  <pre><code>ctx-&gt;p_sws_ctx = sws_getContext(ctx-&gt;p_video_ctx-&gt;width, 
                                  ctx-&gt;p_video_ctx-&gt;height, 
                                  ctx-&gt;p_video_ctx-&gt;pix_fmt, 
                                  ctx-&gt;p_video_ctx-&gt;width, 
                                  ctx-&gt;p_video_ctx-&gt;height,
                                  PIX_FMT_YUV420P, SWS_FAST_BILINEAR, NULL, NULL, NULL);
  
  
  // Framebuffer for RGB data
  ctx-&gt;p_frame_buffer = malloc(avpicture_get_size(PIX_FMT_YUV420P,
                                                  ctx-&gt;p_video_ctx-&gt;width, 
                                                  ctx-&gt;p_video_ctx-&gt;height));
  
  avpicture_fill((AVPicture*)ctx-&gt;p_picture_rgb, ctx-&gt;p_frame_buffer,PIX_FMT_YUV420P, 
                 ctx-&gt;p_video_ctx-&gt;width, 
                 ctx-&gt;p_video_ctx-&gt;height);
  </code></pre>
  
  <p>My render method: </p>
  
  <pre><code>if (NULL == videoTextureCache) {
      NSLog(@"displayPixelBuffer error");
      return;
  }    
  
  
  CVPixelBufferRef pixelBuffer;    
     CVPixelBufferCreateWithBytes(kCFAllocatorDefault, mTexW, mTexH, kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, buffer, mFrameW * 3, NULL, 0, NULL, &amp;pixelBuffer);
  
  
  
  CVReturn err;    
  // Y-plane
  glActiveTexture(GL_TEXTURE0);
  err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, 
                                                     videoTextureCache,
                                                     pixelBuffer,
                                                     NULL,
                                                     GL_TEXTURE_2D,
                                                     GL_RED_EXT,
                                                     mTexW,
                                                     mTexH,
                                                     GL_RED_EXT,
                                                     GL_UNSIGNED_BYTE,
                                                     0,
                                                     &amp;_lumaTexture);
  if (err) 
  {
      NSLog(@"Error at CVOpenGLESTextureCacheCreateTextureFromImage %d", err);
  }   
  
  glBindTexture(CVOpenGLESTextureGetTarget(_lumaTexture), CVOpenGLESTextureGetName(_lumaTexture));
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);     
  
  // UV-plane
  glActiveTexture(GL_TEXTURE1);
  err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, 
                                                     videoTextureCache,
                                                     pixelBuffer,
                                                     NULL,
                                                     GL_TEXTURE_2D,
                                                     GL_RG_EXT,
                                                     mTexW/2,
                                                     mTexH/2,
                                                     GL_RG_EXT,
                                                     GL_UNSIGNED_BYTE,
                                                     1,
                                                     &amp;_chromaTexture);
  if (err) 
  {
      NSLog(@"Error at CVOpenGLESTextureCacheCreateTextureFromImage %d", err);
  }
  
  glBindTexture(CVOpenGLESTextureGetTarget(_chromaTexture), CVOpenGLESTextureGetName(_chromaTexture));
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);     
  
  glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
  
  // Set the view port to the entire view
  glViewport(0, 0, backingWidth, backingHeight);
  
  static const GLfloat squareVertices[] = {
      1.0f, 1.0f,
      -1.0f, 1.0f,
      1.0f,  -1.0f,
      -1.0f,  -1.0f,
  };
  
  GLfloat textureVertices[] = {
      1, 1,
      1, 0,
      0, 1,
      0, 0,
  };
  
  // Draw the texture on the screen with OpenGL ES 2
  [self renderWithSquareVertices:squareVertices textureVertices:textureVertices];
  
  
  // Flush the CVOpenGLESTexture cache and release the texture
  CVOpenGLESTextureCacheFlush(videoTextureCache, 0);    
  CVPixelBufferRelease(pixelBuffer);     
  
   [moviePlayerDelegate bufferDone];
  </code></pre>
  
  <p>RenderWithSquareVertices method</p>
  
  <pre><code>    - (void)renderWithSquareVertices:(const GLfloat*)squareVertices textureVertices:(const GLfloat*)textureVertices
  {
  
  
    // Use shader program.
      glUseProgram(shader.program);
  
  // Update attribute values.
  glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
  glEnableVertexAttribArray(ATTRIB_VERTEX);
  glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GL_FLOAT, 0, 0, textureVertices);
  glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);
  
  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  
  // Present
  glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
  [context presentRenderbuffer:GL_RENDERBUFFER];
  </code></pre>
  
  <p>}</p>
  
  <p>My fragment shader: </p>
  
  <pre><code>uniform sampler2D SamplerY;
  uniform sampler2D SamplerUV;
  
  
  varying highp vec2 _texcoord;
  
  void main()
  {
  
  mediump vec3 yuv;
  lowp vec3 rgb;
  
  yuv.x = texture2D(SamplerY, _texcoord).r;
  yuv.yz = texture2D(SamplerUV, _texcoord).rg - vec2(0.5, 0.5);
  
  // BT.601, which is the standard for SDTV is provided as a reference
  
  /* rgb = mat3(    1,       1,     1,
   0, -.34413, 1.772,
   1.402, -.71414,     0) * yuv;*/
  
  
  // Using BT.709 which is the standard for HDTV
  rgb = mat3(      1,       1,      1,
             0, -.18732, 1.8556,
             1.57481, -.46813,      0) * yuv;
  
     gl_FragColor = vec4(rgb, 1);
  
  }
  </code></pre>
  
  <p>Very thanks, </p>