iOS CVImageBuffer distorted from AVCaptureSessionDataOutput with AVCaptureSessionPresetPhoto iOS CVImageBuffer distorted from AVCaptureSessionDataOutput with AVCaptureSessionPresetPhoto ios ios

iOS CVImageBuffer distorted from AVCaptureSessionDataOutput with AVCaptureSessionPresetPhoto


This was a doozy.

As Lio Ben-Kereth pointed out, the padding is 48 as you can see from the debugger

(gdb) po pixelBuffer<CVPixelBuffer 0x2934d0 width=852 height=640 bytesPerRow=3456 pixelFormat=BGRA# => 3456 - 852 * 4 = 48

OpenGL can compensate for this, but OpenGL ES cannot (more info here openGL SubTexturing)

So here is how I'm doing it in OpenGL ES:

(CVImageBufferRef)pixelBuffer   // pixelBuffer containing the raw image data is passed in/* ... */glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, videoFrameTexture_);int frameWidth = CVPixelBufferGetWidth(pixelBuffer);int frameHeight = CVPixelBufferGetHeight(pixelBuffer);size_t bytesPerRow, extraBytes;bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer);extraBytes = bytesPerRow - frameWidth*4;GLubyte *pixelBufferAddr = CVPixelBufferGetBaseAddress(pixelBuffer);if ( [[captureSession sessionPreset] isEqualToString:@"AVCaptureSessionPresetPhoto"] ){    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, frameWidth, frameHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL );    for( int h = 0; h < frameHeight; h++ )    {        GLubyte *row = pixelBufferAddr + h * (frameWidth * 4 + extraBytes);        glTexSubImage2D( GL_TEXTURE_2D, 0, 0, h, frameWidth, 1, GL_BGRA, GL_UNSIGNED_BYTE, row );    }}else{    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, frameWidth, frameHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, pixelBufferAddr);}

Before, I was using AVCaptureSessionPresetMedium and getting 30fps. In AVCaptureSessionPresetPhoto I'm getting 16fps on an iPhone 4. The looping for the sub-texture does not seem to affect the frame rate.

I'm using an iPhone 4 on iOS 5.


Just draw like this.

size_t bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer);int frameHeight = CVPixelBufferGetHeight(pixelBuffer);GLubyte *pixelBufferAddr = CVPixelBufferGetBaseAddress(pixelBuffer);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)bytesPerRow / 4, (GLsizei)frameHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, pixelBufferAddr);


Good point Mats.But as a matter of fact the padding is larger, it's:

bytesPerRow = 4 * bufferWidth + 48;

It works great on the iphone 4 back camera, and solved the issue sotangochips reported about.