7

すべてのウィンドウのライブ表現を集約しようとしています。Mission Control (Exposé) と同じように、任意の NSWindow または画面の画像バッファーに非常に迅速にアクセスしたいと考えています。理想的には、これらのライブ画像を独自の OpenGL コンテキストで合成して、それらを操作できるようにしたいと考えています (Windows スクリーン キャプチャのスケーリングと移動)。

遅すぎるもの:

  • CGDisplayCreateImage
  • CGWindowListCreateImage
  • CGDisplayIDToOpenGLDisplayMaskCGLCreateContext&& _CGBitmapContextCreate

他のアイデアはありますか?私は60 fpsのキャプチャ/合成/出力を達成しようとしていますが、これらの方法のいずれかで得られる最高のものは〜5 fpsです(画面全体をキャプチャするRetinaディスプレイで)。

4

1 に答える 1

6

残念ながら、個々のウィンドウのフレーム バッファをすばやくキャプチャする方法は見つかりませんでしたが、次善の方法を見つけました。これは、画面全体のライブ ビューを 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 に取り込む他の実装との大きな違いはCVPixelBufferLockBaseAddressCVPixelBufferGetBaseAddress、 、glTexImage2D、およびCVPixelBufferUnlockBaseAddress. このアプローチの問題は、通常、非常に冗長で遅いことです。CVPixelBufferLockBaseAddress渡そうとしているメモリが GPU メモリではないことを確認し、すべてを汎用 CPU メモリにコピーします。これは悪いです!結局のところ、それを GPU にコピーして戻すだけglTexImage2Dです。

CVPixelBufferしたがって、が既に GPU メモリにあるという事実を利用できますCVOpenGLTextureCacheCreateTextureFromImage

これが他の誰かの助けになることを願っています...CVOpenGLTextureCacheスイートはひどく文書化されており、対応するiOSCVOpenGLESTextureCacheはわずかに文書化されているだけです.

2560x1600 のデスクトップをキャプチャする 20% の CPU で 60fps!

于 2014-03-28T22:57:18.667 に答える