¿Cómo obtengo el búfer de la cámara Android en bruto en C con JNI?

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

(Esto es porque la implementación de Java de la devolución de llamada de vista previa [incluso con búfer] es demasiado ineficiente.)

3 Solutions collect form web for “¿Cómo obtengo el búfer de la cámara Android en bruto en C con JNI?”

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

Cadena de llamada de vista previa de la cámara

Como otros mencionados, puede obtener un búfer utilizando un método Camera.setPreviewCallback .
Aquí es cómo sucede allí (una versión detallada):

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

Como se puede ver, se invocó 2 llamadas IPC y se copió el búfer por lo menos dos veces en los pasos 10 y 11. La primera instancia del búfer sin camera_device_t devuelto por camera_device_t se hospeda en otro proceso y no se puede acceder a él debido a las comprobaciones de seguridad en CameraService .

Vista previa de la superficie

Sin embargo, cuando se establece 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 la documentación:

Manejar en un buffer bruto que está siendo gestionado por el compositor de pantalla.

La 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. Vea esta pregunta para una manera de usarla.

No hay API pública para hacer lo que desea; El único método oficial (es decir, garantizado para trabajar) es las devoluciones de llamada de vista previa a nivel Java configuradas a través de la llamada a Camera.setPreviewCallback () . En Android> 3.0, también puede usar Camera.setPreviewTexture () para enrutar datos de vista previa a la GPU y procesarlos allí usando GLES (o volver a leerlos en la CPU). La ruta de la GPU es lo que utiliza la aplicación de cámara ICS AOSP para sus efectos de vídeo.

Presumiblemente, OpenCV y otros han mirado a través del código nativo de framework de Android, y han pasado por alto el Java Camera API, hablando directamente con los servicios de abajo.

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 forman parte de la API pública. Usarlos puede estar bien ahora, y luego cuando un usuario actualiza su dispositivo, su aplicación dejará de funcionar.

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

  • Redireccionamiento de STDIN y STDOUT del programa C en Android
  • Cómo conectar una biblioteca C a la aplicación de iOS
  • JNI: Pasar varios parámetros en la firma de función para GetMethodID
  • Ciclo de vida de actividad de Android y ciclo de código nativo de JNI
  • Función nativa no se ha encontrado ninguna implementación
  • Generación de archivos .so en Android Studio 1.0.2 con NDK
  • C ++ y JNI - Cómo pasar una matriz en un jfloatArray
  • Cómo conectar Kinect a Android
  • Uso de bibliotecas pre-construidas y jni en Android Studio
  • Definir macro para registrar error con archivo y línea en android
  • Extraer código de archivo .aar Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.