¿Cómo obtengo el búfer de cámara raw de Android en C usando JNI?
He estado buscando en Google y StackOverflow exhaustivamente y no puedo encontrar esto. Tal vez me estoy perdiendo algo obvio. ¡Gracias!
(Esto se debe a que la implementación Java de la devolución de llamada de vista previa [incluso con buffer] es demasiado ineficiente.)
3 answers
Hice una pequeña investigación sobre el tema. Estapresentación (de 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 método Camera.setPreviewCallback
.
Así es como sucede allí (una versión detallada):
- El usuario llama a
Camera.startPreview()
que es una función nativa. -
android_hardware_Camera_startPreview
llama al métodostartPreview
de la clase C++Camera
. -
Camera
llama a un métodostartPreview
de la interfazICamera
-
ICamera
hace unIPC
llamada al cliente remoto. - Llama a un método
setCameraMode
de la claseCameraService
. -
CameraService
establece una ventana para mostrar una vista previa y llama a un métodostartPreview
de la claseCameraHardwareInterface
. - Este último intenta llamar a un método
start_preview
en un dispositivocamera_device_t
particular.
No miré más, pero debería realizar una llamada al conductor. - Cuando llega la imagen, se invoca
dataCallback
deCameraService
. - Pasa datos al método
handlePreviewData
del cliente. - Cliente copia el buffer o lo envía directamente al
ICameraClient
. -
ICameraClient
lo envía aIPC
alCamera
. -
Camera
llama a un oyente registrado y pasa buffer aJNI
. - Invoca una devolución de llamada en la clase Java. Si el usuario proporciona un búfer con
Camera.addCallbackBuffer
entonces se copia al búfer primero. - Finalmente la clase Java
Camera
maneja el mensaje e invoca un métodoonPreviewFrame
deCamera.PreviewCallback
.
Como puede ver, se invocaron 2 IPC
llamadas y se copió buffer al menos dos veces en los escalones 10, 11. La primera instancia de raw buffer que devuelve camera_device_t
está alojada en otro proceso y no puede acceder a ella 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 búfer sin procesar que está siendo administrado por el compositor de pantalla.
Java class 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 i.e. esta pregunta para una forma de usarla.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:33:44
No hay una API pública para hacer lo que quieras; el único método oficial (es decir, garantizado para funcionar) es la vista previa de llamadas a nivel Java configurada a través de calling Camera.setPreviewCallback () . En Android > 3.0, también puede utilizar Cámara.setPreviewTexture () para enrutar los datos de vista previa a la GPU, y procesarlos allí usando GLES (o leerlos de nuevo a la CPU). La ruta de la GPU es lo que la aplicación de cámara ICS AOSP utiliza para sus efectos de vídeo.
Presumiblemente, OpenCV y otros han mirado a través del código nativo del marco de trabajo de Android y han omitido la API de Java Camera, 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 forman parte de la API pública. Usarlas puede estar bien ahora, y luego, cuando un usuario actualice su dispositivo, su aplicación dejará de funcionar.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-27 18:23:51
¿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.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-22 19:48:45