¿Cómo obtengo el búfer de cámara de Android sin procesar en C usando JNI?

4 minutos de lectura

¿Como obtengo el bufer de camara de Android sin procesar
Mella

He estado buscando exhaustivamente en Google y StackOverflow y no puedo encontrar esto. Tal vez me estoy perdiendo algo obvio. ¡Gracias!

(Esto se debe a que la implementación de Java de la devolución de llamada de vista previa [even with buffer] es demasiado ineficiente.)

  • ¿Tiene solo privilegios habituales o adicionales (tal vez root)?

    – Andrei Ermakov

    27 mayo 2012 a las 19:05

  • ¿Alguna vez encontraste una manera de hacer esto? Porque estoy buscando lo mismo.

    – timemanx

    18 de septiembre de 2013 a las 13:04

¿Como obtengo el bufer de camara de Android sin procesar
Andrei Ermakov

Hice una pequeña investigación sobre el tema. Esta presentación (de la p.277, chino) ayudó mucho.

Cadena de llamadas de vista previa de la cámara

Como otros mencionaron, puede obtener un búfer usando un Camera.setPreviewCallback método.
Así es como sucede allí (una versión detallada):

  1. Llamadas de usuario Camera.startPreview() que es una función nativa.
  2. android_hardware_Camera_startPreview llamadas startPreview método de C++ Camera clase.
  3. Camera llama un startPreview método de ICamera interfaz
  4. ICamera hace un IPC llamada a cliente remoto.
  5. llama un setCameraMode método de CameraService clase.
  6. CameraService establece una ventana para mostrar una vista previa y llama a un startPreview método de CameraHardwareInterface clase.
  7. Este último trata de llamar a un start_preview método en particular camera_device_t dispositivo.
    No miré más hacia arriba, pero debería realizar una llamada al conductor.
  8. Cuando llega la imagen, dataCallback de CameraService es invocado.
  9. Pasa datos a handlePreviewData método de cliente.
  10. El cliente copia el búfer o lo envía directamente al ICameraClient.
  11. ICameraClient lo envía IPC al Camera.
  12. Camera llama a un oyente registrado y pasa el búfer a JNI.
  13. Invoca una devolución de llamada en la clase Java. Si el usuario proporcionó un búfer con Camera.addCallbackBuffer luego se copia primero en el búfer.
  14. Finalmente clase Java Camera maneja el mensaje e invoca un onPreviewFrame método de Camera.PreviewCallback.

Como puedes ver 2 IPC se invocaron llamadas y el búfer se copió al menos dos veces en los pasos 10, 11. Primera instancia de búfer sin procesar que devuelve camera_device_t está alojado en otro proceso y no puede acceder a él debido a controles de seguridad en CameraService.

Superficie de vista previa

Sin embargo, cuando configura una superficie de vista previa utilizando Camera.setPreviewTexture o Camera.setPreviewDisplay se pasa directamente al dispositivo de la cámara y se actualiza en tiempo real sin la participación de toda la cadena anterior. Como dice su documentación:

Manejar en un búfer sin procesar que está siendo administrado por el compositor de pantalla.

clase Java Surface tiene un método para recuperar su contenido:

public static native Bitmap screenshot(int width, int height, int minLayer, int maxLayer);

Pero esta API está oculta. Ver es decir, esta pregunta para una forma de usarlo.

  • Dos comentarios a este excelente resumen. 1. Pasos 10-11 mayo involucrar memcpypero lo más probable es que solo pasen el búfer sin copiar, mediante el uso compartido de memoria entre procesos. 2. los screenshot método para Superficie copia píxeles, también involucra IPC y posiblemente conversión de color, por lo que sería un error usarlo para un mejor rendimiento. 2a. Esta screenshot El método produce un mapa de bits RGB, mientras que la mayoría de la codificación de video necesita YUV.

    – Alex Cohn

    18 de febrero de 2014 a las 8:44


No hay una API pública para hacer lo que quieras; el único método oficial (es decir, garantizado para funcionar) son las devoluciones de llamada de vista previa de nivel Java configuradas a través de llamadas Cámara.setPreviewCallback(). En Android > 3.0, también puedes usar Cámara.setPreviewTexture() para enrutar los datos de vista previa a la GPU y procesarlos allí usando GLES (o volver a leerlos en la CPU). La ruta de GPU es lo que usa la aplicación de cámara ICS AOSP para sus efectos de video.

Presumiblemente, OpenCV y otros han revisado el código nativo del marco de trabajo de Android y han pasado por alto la API de la cámara Java, hablando directamente con los servicios a continuación.

Esto es bastante peligroso, porque no hay absolutamente ninguna garantía de que esas interfaces no cambien entre las versiones de Android, ya que no son parte de la API pública. Usarlos puede estar bien ahora, y luego, cuando un usuario actualice su dispositivo, su aplicación dejará de funcionar.

¿Has echado un vistazo a OpenCV para Android. Sus tutoriales avanzados muestra cómo usar JNI y hay un objeto NativeProcessor en su paquete de cámara.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad