I've been searching Google and StackOverflow exhaustively and cannot find this. Maybe I'm missing something obvious. Thanks!
(This is because the Java implementation of the preview callback [even with buffer] is too inefficient.)
I've been searching Google and StackOverflow exhaustively and cannot find this. Maybe I'm missing something obvious. Thanks!
(This is because the Java implementation of the preview callback [even with buffer] is too inefficient.)
I made a little investigation on topic. This presentation (from p.277, Chinese) helped a lot.
As others mentioned, you can get a buffer using a Camera.setPreviewCallback
method.
Here's how it happens there (a verbose version):
Camera.startPreview()
which is a native function.android_hardware_Camera_startPreview
calls startPreview
method of C++ Camera
class.Camera
calls a startPreview
method of ICamera
interfaceICamera
makes an IPC
call to remote client.setCameraMode
method of CameraService
class.CameraService
sets a window to display a preview and calls a startPreview
method of CameraHardwareInterface
class.start_preview
method on particular camera_device_t
device. dataCallback
of CameraService
is invoked.handlePreviewData
method of client.ICameraClient
.ICameraClient
sends it over IPC
to the Camera
.Camera
calls a registered listener and passes buffer to JNI
.Camera.addCallbackBuffer
then it copies to the buffer first.Camera
handles the message and invokes a onPreviewFrame
method of Camera.PreviewCallback
.As you can see 2 IPC
calls were invoked and buffer was copied at least twice on steps 10, 11. First instance of raw buffer which is returned by camera_device_t
is hosted in another process and you cannot access it due to security checks in CameraService
.
However, when you set a preview surface using either Camera.setPreviewTexture
or Camera.setPreviewDisplay
it is be passed directly to the camera device and refreshed in realtime without participation of all the chain above. As it's documentation says:
Handle onto a raw buffer that is being managed by the screen compositor.
Java class Surface
has a method to retrieve it's contents:
public static native Bitmap screenshot(int width, int height, int minLayer, int maxLayer);
But this API is hidden. See i.e. this question for a way to use it.
There is no public API to do what you want; the only official (that is, guaranteed to work) method is the Java-level preview callbacks set up through calling Camera.setPreviewCallback(). In Android > 3.0, you can also use Camera.setPreviewTexture() to route preview data to the GPU, and process it there using GLES (or read it back to the CPU). The GPU path is what the ICS AOSP camera application uses for its video effects.
Presumably, OpenCV and others have looked through the Android framework native code, and have bypassed the Java Camera API, talking to the services below directly.
This is fairly dangerous, because there is absolutely no guarantee that those interfaces won't change between Android versions, since they are not part of the public API. Using them may be fine now, and then when a user upgrades their device, your app will stop working.
Have you taken a look at OpenCV for Android. Their advanced tutorials show how to use JNI and there is a NativeProcessor object in their camera package.