2012-10-01 9 views
17

私の現在のプロジェクトでは、iPhoneのメインカメラ出力を読み込んでいます。次に、ピクセルバッファをキャッシュされた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にキャストできません。 Core Videoを使用すると、ビデオフレームを直接OpenGLテクスチャにマップできます。コアビデオがテクスチャを作成してビデオメモリに保存したビデオバッファを使用します。このリンクは、iPhone 4あなた Link

    2

    役立つことopenglesテクスチャを作成するには

    (だけでなく、iPhone 3GSおよびiPod touchの第4世代は。)のためのmaximum OpenGL ES texture size is 2048x2048PowerVR SGX 535 GPUを使用しています。この値は、

    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); 
    

    を呼び出すと見つかります。iPod Touch 4th gen。 720x960のカメラ解像度とiPhone 3GS、640x1136を持っていますが、iPhone 4のリアカメラの解像度は1936x2592で、大きすぎると1つのテクスチャに収まりません。

    キャプチャした画像は、アスペクト比(1529x2048)を維持したまま、小さなサイズでいつでも書き換えることができます。 Brad Larsonはhis GPUImage frameworkでこれを行いますが、Core Graphicsを使用して元のピクセルバッファのデータを再描画した後、別のピクセルバッファを再描画データから作成するだけで簡単です。残りのフレームワークも素晴らしいリソースです。

    関連する問題