2012-10-01 26 views
17

對於我目前的項目,我正在閱讀iPhone的主要相機輸出。然後通過方法將pixelbuffer轉換爲緩存的OpenGL紋理:CVOpenGLESTextureCacheCreateTextureFromImage。這在處理用於預覽的相機框架時效果很好。測試與iPhone 3GS,4,4S,iPod Touch(第4代)和IOS5,IOS6的不同組合。CVOpenGLESTextureCacheCreateTextureFromImage無法創建IOSurface

但是,對於實際的最終圖像,具有非常高的分辨率,這僅適用於這些組合:

  • 的iPhone 3GS + IOS 5.1.1
  • iPhone 4 + IOS 5.1.1
  • iPhone 4S的IOS + 6.0
  • 的iPod touch(第4代)+ IOS 5.0

這不適合工作:iPhone 4 + iOS6的。在控制檯

確切的錯誤信息:

Failed to create IOSurface image (texture) 
2012-10-01 16:24:30.663 GLCameraRipple[676:907] Error at CVOpenGLESTextureCacheCreateTextureFromImage -6683 

我已經改變從蘋果GLCameraRipple項目隔離這個問題。你可以在這裏看看我的版本:http://lab.bitshiftcop.com/iosurface.zip

以下是我的stilloutput添加到當前會話:

- (void)setupAVCapture 
{ 
    //-- Create CVOpenGLESTextureCacheRef for optimal CVImageBufferRef to GLES texture conversion. 
    CVReturn err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, [EAGLContext currentContext], NULL, &_videoTextureCache); 
    if (err) 
    { 
     NSLog(@"Error at CVOpenGLESTextureCacheCreate %d", err); 
     return; 
    } 

    //-- Setup Capture Session. 
    _session = [[AVCaptureSession alloc] init]; 
    [_session beginConfiguration]; 

    //-- Set preset session size. 
    [_session setSessionPreset:_sessionPreset]; 

    //-- Creata a video device and input from that Device. Add the input to the capture session. 
    AVCaptureDevice * videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 
    if(videoDevice == nil) 
     assert(0); 

    //-- Add the device to the session. 
    NSError *error;   
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error]; 
    if(error) 
     assert(0); 

    [_session addInput:input]; 

    //-- Create the output for the capture session. 
    AVCaptureVideoDataOutput * dataOutput = [[AVCaptureVideoDataOutput alloc] init]; 
    [dataOutput setAlwaysDiscardsLateVideoFrames:YES]; // Probably want to set this to NO when recording 

    //-- Set to YUV420. 
    [dataOutput setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] 
                  forKey:(id)kCVPixelBufferPixelFormatTypeKey]]; // Necessary for manual preview 

    // Set dispatch to be on the main thread so OpenGL can do things with the data 
    [dataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()]; 


    // Add still output 
    stillOutput = [[AVCaptureStillImageOutput alloc] init]; 
    [stillOutput setOutputSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]]; 
    if([_session canAddOutput:stillOutput]) [_session addOutput:stillOutput]; 

    [_session addOutput:dataOutput]; 
    [_session commitConfiguration]; 

    [_session startRunning]; 
} 

這裏就是我拍攝的靜止輸出並對其進行處理:

- (void)capturePhoto 
{ 
    AVCaptureConnection *videoConnection = nil; 
    for (AVCaptureConnection *connection in stillOutput.connections) { 
     for (AVCaptureInputPort *port in [connection inputPorts]) { 
      if ([[port mediaType] isEqual:AVMediaTypeVideo]) { 
       videoConnection = connection; 
       break; 
      } 
     } 
     if (videoConnection) { break; } 
    } 

    [stillOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: 
    ^(CMSampleBufferRef imageSampleBuffer, NSError *error) { 
     // Process hires image 
     [self captureOutput:stillOutput didOutputSampleBuffer:imageSampleBuffer fromConnection:videoConnection]; 
    }]; 
} 

以下是紋理的創建方式:

- (void)captureOutput:(AVCaptureOutput *)captureOutput 
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
     fromConnection:(AVCaptureConnection *)connection 
{ 
    CVReturn err; 
    CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    size_t width = CVPixelBufferGetWidth(pixelBuffer); 
    size_t height = CVPixelBufferGetHeight(pixelBuffer); 

    if (!_videoTextureCache) 
    { 
     NSLog(@"No video texture cache"); 
     return; 
    } 

    if (_ripple == nil || 
     width != _textureWidth || 
     height != _textureHeight) 
    { 
     _textureWidth = width; 
     _textureHeight = height; 

     _ripple = [[RippleModel alloc] initWithScreenWidth:_screenWidth 
               screenHeight:_screenHeight 
               meshFactor:_meshFactor 
               touchRadius:5 
               textureWidth:_textureWidth 
              textureHeight:_textureHeight]; 

     [self setupBuffers]; 
    } 

    [self cleanUpTextures]; 

    NSLog(@"%zi x %zi", _textureWidth, _textureHeight); 

    // RGBA texture 
    glActiveTexture(GL_TEXTURE0); 
    err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, 
                 _videoTextureCache, 
                 pixelBuffer, 
                 NULL, 
                 GL_TEXTURE_2D, 
                 GL_RGBA, 
                 _textureWidth, 
                 _textureHeight, 
                 GL_BGRA, 
                 GL_UNSIGNED_BYTE, 
                 0, 
                 &_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); 
} 

任何解決這個問題的建議?

+0

我一直在多個設備上進行測試,直到現在它仍然是獨特的組合:iPhone 4 + IOS6.0。即使iPod touch(第4代)也可以將相機幀轉換爲GLES紋理。 – polyclick

回答

1

我們不能將靜止圖像紋理投射到CVOpenGLESTextureCacheRef。核心視頻可讓您將視頻幀直接映射到OpenGL紋理。使用Core Video創建紋理的視頻緩衝區,並將它們提供給我們,並存儲在視頻內存中。

要創建opengles質地這個鏈接可以幫助你 Link

2

的iPhone 4(以及在iPhone 3GS和iPod touch 4代)採用了PowerVR SGX 535 GPU,爲此maximum OpenGL ES texture size is 2048x2048。此值可通過致電

glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); 

iPod Touch第4代。相機分辨率爲720x960,iPhone 3GS爲640x1136,但iPhone 4的後置相機分辨率爲1936x2592,這太大而無法適應單一紋理。

您可以始終以較小的尺寸重寫捕捉的圖像,同時保留寬高比(1529x2048)。 Brad Larson在his GPUImage framework上做了這件事,但它非常簡單,只需使用Core Graphics重繪原始像素緩衝區的數據,然後將另一個像素緩衝區從重繪數據中取出即可。框架的其餘部分也是一個很好的資源。