I am using the Android Camera2 API to capture and process an image. The image processing happens in reponse to a successful capture. The problem I am having is that the camera captures 2 images, I have been unable to change the code in the Camera2Basic sample to ensure only a single image is captured. The issue can be demonstrated by adding logging code to the ImageSaver.run()
method in Camera2BasicFragment.java
public void run() {
Log.d("Camera2", "Saving image");
ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();
...
}
Edit - after further investigation the issue appears to be in the implementation of the sample, rather than anything fundamental to the API. In the sample, the following code tracks the state changes of the camera,
private void process(CaptureResult result) {
switch (mState) {
case STATE_PREVIEW: {
// We have nothing to do when the camera preview is working normally.
break;
}
case STATE_WAITING_LOCK: {
int afState = result.get(CaptureResult.CONTROL_AF_STATE);
if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
// CONTROL_AE_STATE can be null on some devices
Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
if (aeState == null ||
aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
mState = STATE_WAITING_NON_PRECAPTURE;
/** CAPTURE 1 */
captureStillPicture();
} else {
runPrecaptureSequence();
}
}
break;
}
case STATE_WAITING_PRECAPTURE: {
...
break;
}
case STATE_WAITING_NON_PRECAPTURE: {
// CONTROL_AE_STATE can be null on some devices
Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {
mState = STATE_PICTURE_TAKEN;
/** CAPTURE 2 **/
captureStillPicture();
}
break;
}
}
}
I have verified that both invocations of captureStillPicture
result in an image being generated, and hence processed. I'm not entirely sure what the correct state transitions should be.
I am using a Motorola Nexus 6
Both CameraX and Camera2 support Android 5.0 (API level 21) and higher. Camera2 is the latest low-level Android camera package and replaces the deprecated Camera class.
This is done as follows: Intent camera_intent = new Intent(MediaStore. ACTION_IMAGE_CAPTURE); startActivityForResult(camera_intent, pic_id); Now use the onActivityResult() method to get the result, here is the captured image.
The main purpose of Camera2API is to improve camera quality by controlling some important camera features such as shutter speed, RAW shooting, white balance. First of all, we need to understand whether the Camera2API feature is enabled on our phone.
There does indeed seem to be a redundancy/error in the sample code. The simple solution is to change the line just before you've written /** CAPTURE 1 */
to
mState = STATE_PICTURE_TAKEN;
This case is only entered when all the settings are already right/converged, and so might as well initiate the still capture, as it does. It just wasn't recording that it did so.
since your question I started reading and digging into it, and I believe that's the way it works. As per doc (link) says:
Each request will produce one CaptureResult and produce new frames for one or more target Surfaces
note that it says "frames". In plural.
Said that I believe you should only consider the last frame from inside onCaptureCompleted
callback.
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