Getting android camera2 preview frames without screen preview

In the original (now obsolete) camera API, we were able to receive preview frames in Camera.PreviewCallback and be able to process it (possibly for a very long time) and release the buffer in order to be able to get another frame without delaying the screen preview, with some code as shown below:

public void onPreviewFrame(final byte[] data, Camera camera) { new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { (... do some slow processing ...) } @Override protected void onPostExecute(Void aVoid) { mCamera.addCallbackBuffer(data); // free the buffer to be able // to process another frame } }.execute(); } 

The API will only be a callback with a new frame, if there can be another buffer to receive it without delaying the screen preview.

I am trying to reproduce the same behavior in the new Camera2 API, but I cannot find a way to do this without delaying the screen preview. If I add a second target (same resolution as the screen image, YUV_420_888) in the preview request:

 mPreviewRequestBuilder.addTarget(surface); mPreviewRequestBuilder.addTarget(previewImageReader.getSurface()); mCameraDevice.createCaptureSession( Arrays.asList(surface, previewImageReader.getSurface()), ... 

the screen preview will lag even if I just close the image as soon as I get it:

 @Override public void onImageAvailable(ImageReader reader) { reader.acquireNextImage().close(); } 

What is the right way to use Camera2 to emulate the behavior of the API of the source camera (i.e. if you have a new buffer when it is free and does not slow down the screen)?

Update. If anyone is interested in what the rest of the code looks like, this is just a modified version of the standard sample android-camera2Basic, here is what I changed .

+9
source share
2 answers

If anyone else is interested.

Create a SurfaceTextureListener and call your asynchronous function from the onSurfaceTextureUpdated method. I have successfully used this when checking frames for barcodes using the BarcodeDetection API and Camera 2 API.

+2
source

Here is an example of an asynchronous function launched from the onSurfaceTextureUpdated method. If you want to run only one asynchronous task in the background at a time, you can use the flag to check if the previous task has completed.

 private final TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() { boolean processing; @Override public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) { openCamera(width, height); } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) { configureTransform(width, height); } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) { return true; } @Override public void onSurfaceTextureUpdated(SurfaceTexture texture) { if (processing) { return; } processing = true; Bitmap photo = mTextureView.getBitmap(); new ImageTask(photo, new ImageResponse() { @Override public void processFinished() { processing = false; } }).execute(); } }; private interface ImageResponse { void processFinished(); } private class ImageTask extends AsyncTask<Void, Void, Exception> { private Bitmap photo; private ImageResponse imageResponse; ImageTask(Bitmap photo, ImageResponse imageResponse) { this.photo = photo; this.imageResponse = imageResponse; } @Override protected Exception doInBackground(Void... params) { // do background work here imageResponse.processFinished(); return null; } @Override protected void onPostExecute(Exception result) { } } 
0
source

All Articles