ser requiere procesador premiere overclock nucleos los frecuencia forzar este elegir efecto bajar activar acelerar aceleracion android opengl-es android-ndk android-camera

requiere - La cámara más baja entre CPU y GPU se acerca en Android



overclock android root (1)

Mi aplicación necesita procesar algo en marcos de cámara en vivo en la CPU, antes de renderizarlos en la GPU. También hay otras cosas que se representan en la GPU, que dependen de los resultados del procesamiento de la CPU; por lo tanto, es importante mantener todo sincronizado para que no generemos el marco en la GPU hasta que los resultados del procesamiento de la CPU para ese cuadro también estén disponibles.

La pregunta es ¿cuál es el enfoque más bajo para esto en Android?

El procesamiento de la CPU en mi caso solo necesita una imagen en escala de grises, por lo que un formato YUV donde el plano Y está empaquetado es ideal (y tiende a ser una buena combinación con el formato nativo de los dispositivos de la cámara también). NVTV, NV21 o YUV totalmente planar proporcionarían acceso ideal a bajo nivel de carga a la escala de grises, por lo que sería preferible en el lado de la CPU.

En la API original de la cámara, setPreviewCallbackWithBuffer () era la única forma sensata de obtener datos en la CPU para su procesamiento. Esto tenía el plano Y separado, por lo que era ideal para el procesamiento de la CPU. Conseguir que este marco esté disponible para OpenGL para su renderizado de una manera muy baja fue el aspecto más desafiante. Al final, escribí una rutina de conversión de colores NEON para generar RGB565 y simplemente uso glTexSubImage2d para que esté disponible en la GPU. Esto se implementó por primera vez en el marco de tiempo del Nexus 1, donde incluso una llamada glTexSubImage2d de 320x240 tardó 50 ms de tiempo de CPU (supongo que los controladores deficientes intentan crear texturas swizzling; esto se mejoró significativamente en una actualización del sistema más adelante).

En el pasado, investigué cosas como las extensiones de eglImage, pero no parecen estar disponibles ni suficientemente documentadas para las aplicaciones de los usuarios. He echado un vistazo a las clases internas de Android GraphicsBuffer pero, idealmente, quiero permanecer en el mundo de las API públicas compatibles.

La API android.hardware.camera2 tenía la promesa de poder adjuntar un ImageReader y una SurfaceTexture a una sesión de captura. Desafortunadamente, no veo ninguna manera de garantizar la secuencia secuencial correcta aquí, detener la llamada a updateTexImage () hasta que la CPU haya sido procesada sea lo suficientemente fácil, pero si ha llegado otro marco durante ese procesamiento, updateTexImage () se saltará directamente a la última marco. También parece que con múltiples salidas habrá copias independientes de los marcos en cada una de las colas que idealmente quisiera evitar.

Idealmente esto es lo que me gustaría:

  1. El controlador de la cámara llena algo de memoria con el último fotograma
  2. La CPU obtiene un puntero a los datos en la memoria, puede leer los datos Y sin que se realice una copia
  3. La CPU procesa datos y establece un indicador en mi código cuando el marco está listo
  4. Cuando comiences a renderizar un marco, verifica si un nuevo marco está listo
  5. Llame a una API para enlazar la misma memoria que una textura GL
  6. Cuando un marco más nuevo está listo, libere el búfer que retiene el marco anterior en el grupo

No veo una manera de hacer exactamente ese estilo de copia cero con la API pública en Android, pero ¿qué es lo más cercano que se puede obtener?

Una locura que probé parece funcionar, pero no está documentada: la API ANativeWindow NDK puede aceptar el formato de datos NV12, aunque la constante de formato adecuada no es una de las que están en los encabezados públicos. Eso permite que SurfaceTexture se llene con datos NV12 mediante memcpy () para evitar la conversión de color del lado de la CPU y cualquier swizzling que ocurra en el lado del conductor en glTexImage2d. Sin embargo, esa es una copia adicional de los datos que parece innecesaria, y una vez más, dado que no está documentada, podría no funcionar en todos los dispositivos. Una cámara de copia cero secuencial admitida -> ImageReader -> SurfaceTexture o equivalente sería perfecta.


La forma más eficiente de procesar video es evitar la CPU por completo, pero parece que no es una opción para ti. Las API públicas generalmente están orientadas a hacer todo en hardware, ya que eso es lo que necesita el framework en sí, aunque hay algunas rutas para RenderScript. (Supongo que has visto la demostración del filtro Grafika que usa sombreadores de fragmentos).

El acceso a los datos en la CPU solía significar que las API de cámara eran lentas o que funcionaba con GraphicBuffer y funciones EGL relativamente oscuras (por ejemplo, esta pregunta ). El objetivo de ImageReader era proporcionar acceso de copia cero a los datos YUV de la cámara.

Realmente no se puede serializar Camera -> ImageReader -> SurfaceTexture ya que ImageReader no tiene una API de "reenviar el buffer". Lo cual es desafortunado, ya que eso haría que esto sea trivial. Podrías tratar de replicar lo que hace SurfaceTexture, usando las funciones EGL para empaquetar el buffer como una textura externa, pero de nuevo estás en un GraphicBuffer-land no público, y me preocupan los problemas de propiedad / duración del buffer.

No estoy seguro de cómo las rutas paralelas lo ayudan (Camera2 -> ImageReader, Camera2 -> SurfaceTexture), ya que lo que se envía a SurfaceTexture no tendrá sus modificaciones. FWIW, no implica una copia adicional: en Lollipop, BufferQueue se actualizó para permitir que los buffers individuales se muevan a través de múltiples colas.

Es muy posible que haya algunas nuevas API que aún no he visto, pero por lo que sé, su enfoque ANativeWindow es probablemente el ganador. Sospecho que estarías mejor con uno de los formatos de cámara (YV12 o NV21) que NV12, pero no estoy seguro.

FWIW, soltará los marcos si el procesamiento lleva demasiado tiempo, pero a menos que su procesamiento sea desigual (algunos cuadros tardan mucho más que otros), tendrá que soltar los marcos sin importar nada. Al entrar de nuevo en el ámbito de las API no públicas, puede cambiar SurfaceTexture al modo "síncrono", pero si sus buffers se llenan, todavía está eliminando fotogramas.