Reputation: 141
I want to take 1fps still captures using Camera 2 API's setRepeatingRequest()
mode.
I set the CONTROL_AE_MODE
to CONTROL_AE_MODE_OFF
and SENSOR_FRAME_DURATION
to 1
. However I still receive a very high frame rate of 20fps with the below code.
I tried changing the capture request template from TEMPLATE_PREVIEW
to TEMPLATE_STILL_CAPTURE
without any luck. How do I achieve 1fps using setRepeatingRequest()?
CaptureRequest.Builder requestBuilder
= cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
requestBuilder.addTarget(imageReader.getSurface());
cameraDevice.createCaptureSession(Collections.singletonList(imageReader.getSurface()),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
// The camera is already closed
if (cameraDevice == null) {
return;
}
captureSession = cameraCaptureSession;
try {
requestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
requestBuilder.set(CaptureRequest.SENSOR_FRAME_DURATION, 1L);
CameraCaptureSession.CaptureCallback captureCallback
= new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request,
@NonNull TotalCaptureResult result) {
}
};
captureSession.setRepeatingRequest(
requestBuilder.build(), captureCallback, callbackHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(
@NonNull CameraCaptureSession cameraCaptureSession) {
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
Upvotes: 5
Views: 2469
Reputation: 57163
Your control over how often will onCaptureCompleted() be invoked is limited. But you have full control over what you do in that callback.
If your camera produces 20 fps, you can skip 19 callbacks and capture the twentieth. If you are not sure that the frame rate is stable enough, you can keep the timestamp (using SystemClock.elapsedRealtime()) for the last picture you used, and ignore all callbacks until one second after that. You can even play with sleep() to improve precision if you really need it.
Upvotes: 0
Reputation: 3393
First of all, the unit in SENSOR_FRAME_DURATION is in nanoseconds, according to the docs
So try with requestBuilder.set(CaptureRequest.SENSOR_FRAME_DURATION, 1000000L);
In addition, you can do it less elegantly using a CountDownTimer
, and taking a photo each 1 sec. I know this is bad, because you are initializing all the camera stuff each seconds, but it's a solution that just works. An example would be:
new CountDownTimer(5000,1000){
@Override
public void onFinish() { (...) }
@Override
public void onTick(long millisUntilFinished) {
// TODO take picture
}
}.start();
Another third solution would be using Camera.Parameters [setPreviewFpsRange](https://developer.android.com/reference/android/hardware/Camera.Parameters.html#setPreviewFpsRange(int, int)), but it would require Camera API instead of Camera2. But it's just another possibility
Upvotes: 1