2010-11-21 13 views

Répondre

19

Depuis iOS 4.0, vous pouvez utiliser AVCaptureDeviceInput pour obtenir l'appareil photo en tant qu'entrée de périphérique et le connecter à un AVCaptureVideoDataOutput avec n'importe quel objet que vous souhaitez définir en tant que délégué. En définissant un format BGRA 32bpp pour la caméra, l'objet délégué recevra chaque image de la caméra dans un format parfait pour passer immédiatement à glTexImage2D (ou glTexSubImage2D si le périphérique ne prend pas en charge les textures sans puissance de deux; pense que les appareils MBX entrent dans cette catégorie).

Il y a beaucoup d'options de taille d'image et de fréquence d'image; en un clin d'oeil, vous devrez modifier ceux en fonction de combien vous voulez utiliser le GPU. J'ai trouvé qu'une scène complètement triviale avec juste un quad texturé montrant le dernier cadre, redessiné juste au moment où une nouvelle image arrive sur un iPhone 4, a pu afficher l'alimentation maximale de 720p 24fps de cet appareil sans retard notable. Je n'ai pas effectué de benchmarking plus approfondi que cela, donc j'espère que quelqu'un d'autre peut le conseiller. En principe, selon l'API, les trames peuvent revenir avec un bourrage en mémoire entre les lignes de balayage, ce qui signifierait un remaniement du contenu avant de passer à GL, vous devez donc implémenter un chemin de code pour cela. En pratique, en termes purement empiriques, il semble que la version actuelle d'iOS ne renvoie jamais les images sous cette forme, donc ce n'est pas vraiment un problème de performance.

EDIT: c'est maintenant très proche de trois ans plus tard. Dans l'intervalle Apple a publié iOS 5, 6 et 7. Avec 5, ils ont introduit CVOpenGLESTexture et CVOpenGLESTextureCache, qui sont maintenant la façon intelligente de canaliser la vidéo à partir d'un périphérique de capture dans OpenGL. Apple fournit l'exemple de code here, dont les parties particulièrement intéressantes sont dans RippleViewController.m, plus précisément ses setupAVCapture et captureOutput:didOutputSampleBuffer:fromConnection: - voir les lignes 196-329. Malheureusement, les termes et conditions à éviter toute duplication du code ici sans y attacher l'ensemble du projet, mais la configuration étape par étape est:

  1. créer un CVOpenGLESTextureCacheCreate et un AVCaptureSession;
  2. saisir un AVCaptureDevice approprié pour la vidéo; Créer un AVCaptureDeviceInput avec ce périphérique de capture;
  3. joignez un AVCaptureVideoDataOutput et dites-lui de vous appeler en tant que délégué de tampon d'échantillon.

A la réception de chaque mémoire tampon d'échantillon:

  1. obtenir le CVImageBufferRef de celui-ci;
  2. utiliser CVOpenGLESTextureCacheCreateTextureFromImage pour obtenir Y et UV CVOpenGLESTextureRef s à partir du tampon d'image CV; Obtenir des cibles et des noms de texture à partir des références de texture CV OpenGLES afin de les lier; Combinez la luminance et la chrominance dans votre shader.
+0

Merci pour votre réponse. Je vais le creuser. – Eonil

+1

C'est seulement environ 200 lignes pour relier le tout ensemble; désolé de ne pas avoir publié de code - je n'ai abordé le problème que pendant mon travail, donc je suis contractuellement interdit de poster ce que j'ai. Mais c'est vraiment trivial et j'ai vraiment passé beaucoup plus de temps à déterminer quelles étaient les classes appropriées dans la documentation que j'ai codé. – Tommy

+0

@Eonil Si vous aimez sa réponse, marquez-la comme la réponse acceptée. – pr1001

0

Utilisez RosyWriter pour BEAUCOUP meilleur exemple de rendu vidéo OpenGL. Les performances sont très bonnes, surtout si vous réduisez le framerate (~ 10% à 1080P/30,> = 5% à 1080P/15.