2011-01-20 20 views
9

Estoy trabajando en una aplicación para iPhone que pronto voy a mostrar a una audiencia en vivo.Ayuda de demostración de iPhone: ¿alguien sabe de una alternativa más rápida de captura de pantalla a UIGetScreenImage()?

Me gustaría demostrar la aplicación en vivo a través de VGA a un proyector, en lugar de mostrar capturas de pantalla.

Compré un adaptador VGA para iPhone, y he adaptado Rob Terrell's TVOutManager para satisfacer mis necesidades. Lamentablemente, la velocidad de cuadros después de las pruebas en mi televisor en casa no es tan buena, incluso en un iPhone 4 (quizás 4-5 cuadros por segundo, varía).

Creo que la razón de esta lentitud es que la rutina principal que estoy utilizando para capturar la pantalla del dispositivo (que luego se muestra en una pantalla externa) es UIGetScreenImage(). Esta rutina, que ya no se permite como parte de las aplicaciones de envío, es bastante lenta. Aquí está el código que estoy usando para capturar la pantalla (FYI mirrorView es una UIImageView):

CGImageRef cgScreen = UIGetScreenImage(); 
self.mirrorView.image = [UIImage imageWithCGImage:cgScreen]; 
CGImageRelease(cgScreen); 

¿Hay un método más rápido que puedo utilizar para capturar la pantalla del iPhone y lograr una mejor velocidad de cuadro (el rodaje de 20+ fps)? No es necesario pasar la revisión de la aplicación de Apple; este código de demostración no estará en la aplicación de envío. Si alguien sabe de alguna API privada más rápida, ¡realmente agradecería la ayuda!

Además, el código anterior se está ejecutando mediante una repetición de NSTimer que dispara cada 1.0/desiredFrameRate segundos (actualmente cada 0.1 segundos). Me pregunto si, en cambio, incluir esas llamadas en un bloque y usar GCD o un NSOperationQueue podría ser más eficiente que tener el NSTimer invocar mi método obj-c updateTVOut que actualmente contiene esas llamadas. Agradeceríamos algo de información sobre eso también; algunas búsquedas parecen indicar que el envío de mensajes obj-c es algo lento en comparación con otras operaciones.

Por último, como se puede ver arriba, los CGImageRef que UIGetScreenImage() rendimientos se está convirtiendo en un UIImage y después de que UIImage se está pasando a una UIImageView, que es probablemente cambiar el tamaño de la imagen sobre la marcha. Me pregunto si el cambio de tamaño podría ralentizar aún más las cosas. ¿Ideas de cómo hacer esto más rápido?

Respuesta

5

¿Has mirado las alternativas recomendadas de Apple a UIGetScreenImage? Desde el "Notice regarding UIGetScreenImage()" hilo:

Las aplicaciones que utilizan UIGetScreenImage() para capturar imágenes de la cámara en lugar debe utilizar AVCaptureSession y clases relacionadas en el marco de la Fundación AV. Para ver un ejemplo, consulte Technical Q&A QA1702, "Cómo capturar marcos de video de la cámara como imágenes usando AV Foundation". Tenga en cuenta que el uso de AVCaptureSession solo se admite en iOS4 y versiones posteriores.

Las aplicaciones que utilizan UIGetScreenImage() para capturar el contenido de las vistas y capas de la interfaz deberían usar el método -renderInContext: de CALayer en el marco QuartzCore. Para ver un ejemplo, consulte Technical Q&A QA1703, "Captura de pantalla en aplicaciones UIKit".

Las aplicaciones que utilizan UIGetScreenImage() para capturar el contenido de las vistas y capas basadas en OpenGL ES deberían utilizar la función glReadPixels() para obtener datos de píxeles. Para ver un ejemplo, consulte Technical Q&A QA1704, "Vista de OpenGL ES View Snapshot".

+1

Hola Jonah, gracias por tu sugerencia. Resultó que intenté usar el método renderInContext: de CALayer. Es aún más lento. AVFoundation tampoco me va a ayudar en este caso, ya que no estoy capturando desde una cámara u otra fuente de AV. Estoy intentando capturar la pantalla en sí. Apple recomienda alternativas a UIGetScreenImage porque ya no lo permiten, pero este código no es para el envío de App Store, es solo para una demostración. –

0

No tengo la solución que desea (simulación de reflejo de video) pero puede mover sus vistas a la pantalla externa.Esto es lo que hago y no hay un impacto apreciable en la velocidad de fotogramas. Sin embargo, obviamente dado que la vista ya no está en la pantalla del dispositivo, ya no puede interactuar directamente con él ni verlo. Si tienes algo como un juego controlado con el acelerómetro, esto no debería ser un problema, sin embargo, algo basado en el tacto requerirá algo de trabajo. Lo que hago es tener una vista alternativa en el dispositivo cuando la vista principal es externa. Para mí, esta es una vista de control 2D para "ordenar" la vista 3D normal. Si tienes un juego, tal vez puedas crear una vista de entrada alternativa para controlar el juego con (botones virtuales/joystick, etc.) realmente depende de lo que tengas y de cómo evitarlo.

No me he liberado de jail, no puedo decirlo con certeza, pero estoy bajo la impresión de que un dispositivo con jailbreak puede esencialmente habilitar el reflejo de video (como lo usan en las demostraciones de Apple ...). Si es cierto, esa es probablemente la ruta más fácil si lo único que quieres es una demostración.

1

No sé qué tan rápido es esto, pero vale la pena intentarlo;)

CGImageRef screenshot = [[UIApplication sharedApplication] _createDefaultImageSnapshot]; 
[myVGAView.layer setContents:(id)screenshot]; 

donde _createDefaultImageSnapshot es una API privada. (Dado que es para demostración ... está bien, supongo) y myVGAView es una UIView normal. Si obtiene CGImageRefs, simplemente páselos al contenido de una capa, es más ligero y debe ser un poco más rápido (pero solo un poco)

2

Nueva solución: ¡obtenga un iPad 2 y duplique la salida! :)

Cuestiones relacionadas