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();
}
}
}
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.
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()
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)
withimageReader.acquireLatestImage()
Of if your use-case is different (e.g. batch/background processing), use e.g.:
ImageReader.newInstance(..., maxImages = 1)
withimageReader.acquireNextImage()
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().
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With