我希望汇总所有窗口的实时表示。就像Mission Control(Exposé)一样,我想非常快地访问任何给定的NSWindow或屏幕的图像缓冲区。理想情况下,我想在我自己的OpenGL上下文中合成这些实时图像,以便我可以操作它们(缩放并移动窗口屏幕捕获)。
太慢的事情:
CGDisplayCreateImage
CGWindowListCreateImage
CGDisplayIDToOpenGLDisplayMask
& CGLCreateContext
& CGBitmapContextCreate
还有其他想法吗?我正在努力实现60 fps捕获/复合/输出,但我能用这些方法获得的最佳效果是~5 fps(在视网膜显示器上捕获整个屏幕)。
答案 0 :(得分:5)
不幸的是,我还没有找到快速捕获单个窗口的帧缓冲区,但我发现了下一个最好的东西。这是一种快速捕获整个屏幕的实时视图到OpenGL中的方法:
AVFoundation设置
_session = [[AVCaptureSession alloc] init];
_session.sessionPreset = AVCaptureSessionPresetPhoto;
AVCaptureScreenInput *input = [[AVCaptureScreenInput alloc] initWithDisplayID:kCGDirectMainDisplay];
input.minFrameDuration = CMTimeMake(1, 60);
[_session addInput:input];
AVCaptureVideoDataOutput *output = [[AVCaptureVideoDataOutput alloc] init];
[output setAlwaysDiscardsLateVideoFrames:YES];
[output setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
[_session addOutput:output];
[_session startRunning];
在每个AVCaptureVideoDataOutput
框架
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
const size_t bufferWidth = CVPixelBufferGetWidth(pixelBuffer);
const size_t bufferHeight = CVPixelBufferGetHeight(pixelBuffer);
CVOpenGLTextureRef texture;
CVOpenGLTextureCacheCreateTextureFromImage(kCFAllocatorDefault, _textureCache, pixelBuffer, NULL, &texture);
CVOpenGLTextureCacheFlush(_textureCache, 0);
// Manipulate and draw the texture however you want...
const GLenum target = CVOpenGLTextureGetTarget(texture);
const GLuint name = CVOpenGLTextureGetName(texture);
// ...
glEnable(target);
glBindTexture(target, name);
CVOpenGLTextureRelease(texture);
}
<强>清理强>
[_session stopRunning];
CVOpenGLTextureCacheRelease(_textureCache);
将AVCaptureVideoDataOutput
图像作为纹理导入OpenGL的其他一些实现之间的巨大差异在于它们可能使用CVPixelBufferLockBaseAddress
,CVPixelBufferGetBaseAddress
,glTexImage2D
和{ {1}}。这种方法的问题在于它通常非常冗余和缓慢。 CVPixelBufferUnlockBaseAddress
将确保它所传递的内存不是GPU内存,并将其全部复制到通用CPU内存。这是不好的!毕竟,我们只是使用CVPixelBufferLockBaseAddress
将其复制回GPU。
因此,我们可以利用glTexImage2D
已经位于GPU内存CVPixelBuffer
的事实。
我希望这可以帮助其他人...... CVOpenGLTextureCacheCreateTextureFromImage
套件的文档非常完整,其iOS对应CVOpenGLTextureCache
只有更好的文档记录。
60%CPU,20%CPU捕获2560x1600桌面!