I got an issue using Camera2 API and Google MLKit. What I try to do, for now, is just to log a message if a face is detected. But I have this issue:
It is spamming on console:
W/ImageReader_JNI: Unable to acquire a buffer item, very likely client tried to acquire more than maxImages buffers
And then crash my application with:
java.lang.IllegalStateException: maxImages (2) has already been acquired, call #close before acquiring more.
But as suggested by google for CameraX (I use Camera2 but I must do the same thing I think), I close the image I got with image.close() in the addOnCompleteListener.
Here is my code from the image reader:
val imageReader = ImageReader.newInstance(rotatedPreviewWidth, rotatedPreviewHeight,
ImageFormat.YUV_420_888, 2)
imageReader.setOnImageAvailableListener({
it.acquireLatestImage()?.let { image ->
val mlImage = InputImage.fromMediaImage(image, getRotationCompensation(cameraDevice.id, getInstance(), true))
val result = detector.process(mlImage)
.addOnSuccessListener {faces ->
if (faces.size > 0)
Log.d("photo", "Face found!")
else
Log.d("photo", "No face have been found")
}
.addOnFailureListener { e ->
Log.d("photo", "Error: $e")
}
.addOnCompleteListener {
image.close()
}
}
}, Handler { true })
What I think is happening is this:
Since the processing of google might be slow, the addOnCompleteListener is not called before the acquireLatestImage() is called to get a new image.
But I have no idea on how to prevent that :(, does anyone has an idea? Or maybe my asumptions about the problem are wrong?
And also to prevent the crash, I have increased the maxImages to 4, now it is just spamming "W/ImageReader_JNI: Unable to acquire a buffer item, very likely client tried to acquire more than maxImages buffers" for some time (and then stop) but no crash.
But I think this solution is a way to hide the problem instead of solving it.
EDIT: Increasing the maxImages amount just delay the crash which still happens later.
according to the best practice in MLKit developer guide: "If you use the Camera or camera2 API, throttle calls to the detector. If a new video frame becomes available while the detector is running, drop the frame. See the VisionProcessorBase class in the quickstart sample app for an example."
https://developers.google.com/ml-kit/vision/object-detection/android