I'm working on a project where I need to constantly take pictures with some defined resolution, quality and waiting period. The user is able to start/stop the capturing of pictures, the user can also run it with a preview or without a preview (as to do other things with his phone).
I have everything working fine most of the time for most devices but in some strange cases I see bad/blurred pictures. It is worth mentioning that the device is on the move.
Here is my current request:
private fun setRequestParams(builder: CaptureRequest.Builder) {
builder.set(CaptureRequest.BLACK_LEVEL_LOCK, false)
builder.set(CaptureRequest.CONTROL_AWB_LOCK, false)
builder.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_AUTO)
builder.set(CaptureRequest.CONTROL_AE_LOCK, false)
builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON)
builder.set(CaptureRequest.CONTROL_AE_ANTIBANDING_MODE, CaptureRequest.CONTROL_AE_ANTIBANDING_MODE_AUTO)
builder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 0)
builder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, 0)
builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO)
builder.set(CaptureRequest.COLOR_CORRECTION_MODE, CaptureRequest.CONTROL_MODE_AUTO)
builder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, CaptureRequest.CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG)
builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)
builder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE,getRange())
builder.set(CaptureRequest.JPEG_QUALITY,pictureConfig.quality.toByte())
val capabilities = cameraCharacteristics?.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)
val isManualFocusSupported : Boolean? = capabilities?.contains(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)
if (isManualFocusSupported != null && isManualFocusSupported ) {
builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF)
builder.set(CaptureRequest.LENS_FOCUS_DISTANCE, 0.0f)
}
}
As I mentioned above, The user can either capture photos on foreground or background, for that I create 3 requests, I realized in some phones if there is no linked Surface the camera automatically closes, that's why I use the dummyView.
private val previewRequest: CaptureRequest by lazy {
captureSession!!.device.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW).apply {
addTarget(preview!!)
setRequestParams(this)
}.build()
}
private val backgroundPreviewRequest : CaptureRequest by lazy {
captureSession!!.device.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW).apply {
addTarget(dummyPreview!!)
}.build()
}
private val captureRequest: CaptureRequest by lazy {
captureSession!!.device.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE).apply {
addTarget(imageReader!!.surface)
setRequestParams(this)
}.build()
}
When everything is ready I capture a photo :
captureSession?.setRepeatingRequest(previewRequest, null, cameraPreviewHandler)
captureSession?.capture(captureRequest,null, cameraHandler)
When the onImageAvailable
is called I capture again. Sometimes I save the image, but if the capture is during the waiting period I just let it continue. Usually the waiting period is of 400ms.
My questions are:
- My pictures are sometimes blurred and sometimes not (on the same capturing session) is there something to improve on the request ?
- Phones of similar model (SM-A705FN) give inconsistent results. Same phone give partially blurred images when another phone gives good results. Is it possible that the camera's hardware was overused ?
- In some phones the camera stops taking pictures without ever calling the camera error callback. Is there a way to know that my picture was lost somewhere ?
- In some phones my code doesn't work at all for example Samsung A7 but it works on the Samsung A10 (which is less powerful)
PS: I was using repeatingRequest with almost identical request params but find out that even though the output was slightly higher (pictures were taken faster) the quality was poorer.