Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

error :Unable to acquire a lockedBuffer, very likely client tries to lock more than maxImages buffers

I am using camera2 api for capturing image and displaying in thumnail .Everything is working fine in all devices but when using Micromax Q382 device then in thumnail preview its displaying black image.I am getting below Issue

Unable to acquire a lockedBuffer, very likely client tries to lock more than maxImages buffers

i am using below code for capture listerner callback

final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback()
        {

            @Override
            public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
                                           TotalCaptureResult result)
            {

                super.onCaptureCompleted(session, request, result);

                startPreview();
            }

        };

        mCameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback()
        {

            @Override
            public void onConfigured(CameraCaptureSession session)
            {

                try {
                    session.capture(captureBuilder.build(), captureListener, backgroudHandler);
                } catch (CameraAccessException e) {
                    AppLogger.exception(myContext, getClass().getSimpleName(), e);
                    // e.printStackTrace();
                }
            }

            @Override
            public void onConfigureFailed(CameraCaptureSession session)
            {

            }
        }, backgroudHandler);

    } catch (CameraAccessException e) {
        AppLogger.exception(myContext, getClass().getSimpleName(), e);
        // e.printStackTrace();
    }

and below code using for OnImageAvailableListener

ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener()
        {

            @Override
            public void onImageAvailable(ImageReader reader)
            {

                Image image = null;
                try {
                    image = reader.acquireLatestImage();
                    // ByteBuffer buffer = image.getPlanes()[0].getBuffer();
                    // final byte[] bytes = new byte[buffer.capacity()];

                    ByteBuffer buffer = image.getPlanes()[0].getBuffer();
                    final byte[] bytes = new byte[buffer.remaining()];

                    buffer.get(bytes);
                    save(bytes);
                    buffer.clear();
                    runOnUiThread(new Runnable()
                    {

                        @Override
                        public void run()
                        {
                            mThumbnail.setVisibility(View.VISIBLE);
                            filePathLabel.setVisibility(View.VISIBLE);
                            filePathValue.setText(file.getAbsolutePath());

                            Bitmap bmp =
                                    UtilityMethods.getScaledBitmap(CameraImageTestActivityLoliipop.this, bytes);
                            mThumbnail.setImageBitmap(bmp);
                        }
                    });

                } catch (FileNotFoundException e) {
                    AppLogger.exception(myContext, getClass().getSimpleName(), e);
                    // e.printStackTrace();
                } catch (IOException e) {
                    AppLogger.exception(myContext, getClass().getSimpleName(), e);
                    // e.printStackTrace();
                } finally {
                    if (image != null) {
                        image.close();
                    }
                }
            }
like image 432
Android dev Avatar asked Apr 05 '16 07:04

Android dev


3 Answers

You may provide parameter maxImages as 1 for method ImageReader.newInstance. acquireLatestImage calls acquireNextSurfaceImage before close the only one image buffer, which lead to this warning.

Use acquireNextImage in this case. If maxImages is bigger than 1, acquireLatestImage don't have this problem.

like image 106
bitlixi Avatar answered Oct 10 '22 04:10

bitlixi


After setting maxImages to 2 and using acquireLatestImage, if you are still getting into issue where you stopped getting onImageAvailable callback then most likely you are not releasing the Image buffer you got from acquireLatestImage(), buffer will not be available unless you call Image.close() on that image and allow the same buffer for reuse.

    Image raw = imageReader.acquireLatestImage();
    raw.close();

Here is the link for documentation: https://developer.android.com/reference/android/media/Image.html#close()

like image 24
Tarun Chawla Avatar answered Oct 10 '22 04:10

Tarun Chawla


From the documentation of ImageReader.acquireLatestImage():

Acquire the latest Image from the ImageReader's queue, dropping older images. Returns null if no new image is available. This operation will acquire all the images possible from the ImageReader, but close() all images that aren't the latest.

This function is recommended to use over acquireNextImage() for most use-cases, as it's more suited for real-time processing. Note that maxImages should be at least 2 for acquireLatestImage() to be any different than acquireNextImage() - discarding all-but-the-newest Image requires temporarily acquiring two Images at once.

Thus, for real-time processing use:

  • ImageReader.newInstance(..., maxImages = 2) with
  • imageReader.acquireLatestImage()

Of if your use-case is different (e.g. batch/background processing), use e.g.:

  • ImageReader.newInstance(..., maxImages = 1) with
  • imageReader.acquireNextImage()
  • Be aware, that (from documentation of acquireNextImage():

This operation will fail by throwing an IllegalStateException if maxImages have been acquired with acquireNextImage() or acquireLatestImage(). In particular a sequence of acquireNextImage() or acquireLatestImage() calls greater than maxImages without calling close() in-between will exhaust the underlying queue. At such a time, IllegalStateException will be thrown until more images are released with close().

like image 43
hb0 Avatar answered Oct 10 '22 04:10

hb0