2012-02-03 2 views
3

Apple에서 GLCameraRipple 샘플 응용 프로그램을 수정하여 백그라운드 스레드에서 비디오 프레임을 처리하려고합니다. 이 예에서는 다음과 같은 코드를 사용하여 주 스레드에서 각 프레임을 처리GLCrameRipple 예제를 백그라운드 스레드에서 처리하도록 수정하려면 어떻게해야합니까?

다음
dispatch_queue_t videoQueue = dispatch_queue_create("com.test.queue", NULL); 
[dataOutput setSampleBufferDelegate:self queue:videoQueue]; 

프로그램이 충돌 :

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

나는 백그라운드 스레드에서 처리하기 위해이 코드를 변경하는 경우.

Apple 설명서에 지정된대로 두 번째 EAGLContext를 공유하려고하면 녹색 또는 검은 색 화면 만 보입니다.

이 샘플 응용 프로그램을 백그라운드 스레드에서 실행하도록 수정하려면 어떻게해야합니까?

+0

앱이 고장 났을 때 어떤 오류가 발생합니까? –

+0

무슨 뜻으로 이미지가 화면에 표시되어야합니까? 동일한 공유 그룹의 서로 다른 컨텍스트간에 명명 된 GL 리소스를 전달하기 위해 규칙을 따르고 있습니까 (즉, 이전에 플러시, 패스, 이후 플러시)? – Tommy

답변

2

샘플과 함께 작업 한 후 이것은 실제로 매우 흥미로 웠습니다. 여기에있는 문제는 CVOpenGLESTextureCacheCreateTextureFromImage() 기능입니다. 당신이 녹색 질감을 ​​얻을 때 콘솔에 보면 다음과 같은 기록되는 볼 수 있습니다 : (헤더에 따라,

오류

-6661 CVOpenGLESTextureCacheCreateTextureFromImage -6661에서을 현재이 새로운 기능에 대한 문서를 찾을 수있는 유일한 곳)은 kCVReturnInvalidArgument 오류입니다. 이 함수에 대한 인수 중 하나가 잘못된 것입니다.

여기서 문제가되는 것은 CVImageBufferRef입니다. 이 텍스처 캐시 업데이트를 처리하는 블록이 처리되는 동안이 캐시가 할당 해제되거나 변경되는 것 같습니다.

나는이 문제를 해결하기 위해 몇 가지 방법을 시도해 보았고, this answer에 설명 된 것처럼 디스패치 큐와 디스패치 세마포어를 사용했고, 델리게이트가 여전히 주 스레드를 다시 호출하고 다음과 같은 작업을 수행했습니다. 이 오류를 수정하는 것 같다 비동기 블록에 전원을 전달 한 후, 메인 쓰레드에 CVImageBufferRef을 만들기가 가리키는 바이트를 고정하고 유지함으로써

- (void)captureOutput:(AVCaptureOutput *)captureOutput 
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
     fromConnection:(AVCaptureConnection *)connection 
{ 
    if (dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_NOW) != 0) 
    { 
     return; 
    } 

    CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    CVPixelBufferLockBaseAddress(pixelBuffer, 0); 
    CFRetain(pixelBuffer); 

    dispatch_async(openGLESContextQueue, ^{ 
     [EAGLContext setCurrentContext:_context]; 

     // Rest of your processing 

     CVPixelBufferUnlockBaseAddress(pixelBuffer, 0); 
     CFRelease(pixelBuffer); 

     dispatch_semaphore_signal(frameRenderingSemaphore); 
    }); 
} 

. 이 수정을 보여주는 전체 프로젝트는 here에서 다운로드 할 수 있습니다.

나는 여기에 한 가지만 말해 주어야합니다. 이것은 당신에게 어떤 것도 나타나지 않습니다. GLCrameRipple 샘플을 설정하는 방법을 살펴보면 응용 프로그램에서 가장 무거운 작업 인 파급 효과 계산이 백그라운드 대기열에 이미 전달되었습니다. 또한 OpenGL ES에 카메라 데이터를 제공하기 위해 새로운 고속 업로드 경로를 사용하므로 주 스레드에서 실행될 때 병목 현상이 발생하지 않습니다.

듀얼 코어 iPhone 4S에서 프로파일 링 한 필자는이 샘플 애플리케이션의 스톡 버전과 백그라운드 대기열에서 프레임 업로드를 실행하는 수정 된 시스템간에 렌더링 속도 또는 CPU 사용량에 큰 차이가 없음을 확인했습니다. 여전히 진단하는 것은 흥미로운 문제였습니다.

+0

고마워, Brad. 너는 최고야. – dimaxyu

+0

안녕하세요. Brad 님,이 솔루션에 관한 질문이 있습니다. 이 접근법은 OpenGL 객체의 텍스처로 카메라를 사용할뿐만 아니라이 동일한 샘플 버퍼를 사용하여 일부 OpenCV 작업을 수행하려는 경우에 유용할까요? 어떻게 든 대신 그 텍스쳐를 사용하는 것이 좋겠습니까? 이상적으로는 OpenGL을 사용하여 이미지 추적을 수행하는 것이 가장 좋지만 셰이더에서 프로그래밍하는 것이 내 경험을 넘어선 것 같습니다. 감사 – Pochi

관련 문제