2011-11-24 124 views
1

我有一个视频应用程序,可以在预览运行时同时进行实时预览以及静态图像捕获。我使用的是应用程序加载时预先生成的4个纹理。我正在访问三个线程的纹理。在线程间共享帧缓冲区

为了使实时预览工作,我必须创建一个Sharegroup(见下文),以便captureOutput方法可以将结果存储在名为FBO_OUT的帧缓冲区中。然后,为了显示到屏幕我需要访问FBO_OUT拨打电话presentRenderbuffer。如果我没有使用Sharegroup,我只是得到了一堆乱码。

CAEAGLLayer* eaglLayer = (CAEAGLLayer *)self.layer; 
eaglLayer.opaque = YES; 
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: 
           [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, 
           kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, 
           nil]; 
oglContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; 
offscreenContext = [[EAGLContext alloc] initWithAPI:[oglContext API] sharegroup:oglContext.sharegroup]; 
if (!oglContext || ![EAGLContext setCurrentContext:oglContext]) { 
    NSLog(@"Problem with OpenGL context."); 
    [self release]; 

    return nil; 
} 

定期,captureOutput里面我需要调用此代码:

#define SHAREGROUP_CONTEXT [[[appDelegate mainViewController] oglView] offscreenContext] 

if ([EAGLContext currentContext] != SHAREGROUP_CONTEXT) { 
    NSLog(@"setting context"); 
    glFlush(); 
    [EAGLContext setCurrentContext:SHAREGROUP_CONTEXT]; 
} 

@synchronized(SHAREGROUP_CONTEXT) 
{ 
    /* process pixels */ 
} 

glFlush(); // at end of method 

这工作得很好,问题是,我现在要做的拍摄静止图像后,同样的事情通过captureStillImageAsynchronouslyFromConnection块(而预览仍在运行),但我又即使我试着让乱码这样做:

AVCaptureConnection *sic = [AVCamUtilities connectionWithMediaType:AVMediaTypeVideo fromConnections:[[self stillImageOutput] connections]]; 

[[self stillImageOutput] captureStillImageAsynchronouslyFromConnection:sic 
                completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) 
{ 

    @synchronized(SHAREGROUP_CONTEXT) 
    { 

     /* generate new textures to process the imageDataSampleBuffer and cry */ 
    } 

这似乎是一个问题机智h上下文和线程。

回答

1

我找到了答案。您需要确保@synchronized块在两种方法。这花了我很长时间才发现,因为我的着色器出现了一些非常奇怪的事情。当XCode认为它们都是大写字母时,其中一个文件名是磁盘上的小写字母。这使着色器在实时预览中工作,但在静止图像捕捉部分给了我一个白色屏幕。不知道为什么。

+0

通过使用'@ synchronized'来锁定您的访问权限,您可能会牺牲一点性能:http://perpendiculo.us/?p=133。一个NSLock的开销少得多,一个pthread互斥量更便宜。我看到过去锁定在我的OpenGL应用程序中消耗了很多性能,所以这可能会加起来。此外,您可以考虑使用单个范围的调度队列,并将访问单个资源(如上下文)的所有操作分派到该队列中。这是一种保证安全访问此共享资源的无锁方法,并且一直是我最近的首选方法。 –