androidkotlinandroid-camera2camera-flash

Unable to trigger flash when capturing still image using camera2 API


I am trying to automatically trigger flash when capturing an image using the Camera2 API. I tried to use both CONTROL_AE_MODE_ON_ALWAYS_FLASH and CONTROL_AE_MODE_ON_AUTO_FLASH but both did not work.

What I tried:
Setting CONTROL_AE_MODE to CONTROL_AE_MODE_ON_ALWAYS_FLASH for the still capture builder

val captureRequestBuilder = cameraDevice
            .createCaptureRequest(AndroidCameraDevice.TEMPLATE_STILL_CAPTURE)
 
captureRequestBuilder.apply {
set(CaptureRequest.CONTROL_AE_MODE,
     CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH)
}

I have also done the same for the preview builder (TEMPLATE_PREVIEW) but I was not successful in triggering the flash

Similar was done using CONTROL_AE_MODE_ON_AUTO_FLASH but it did not work too, I need both to work.

Referring to the camera samples provided by Google lead to nothing
camera samples

Is a precapture phase required to be able to setup flash?

Camera2 basic repository that uses precapture and flash before being archived

https://stackoverflow.com/a/37149446/25778714

https://developer.android.com/reference/android/hardware/camera2/CaptureResult#CONTROL_AE_PRECAPTURE_TRIGGER


Solution

  • The documentation for CONTROL_AE_MODE_ON_ALWAYS_FLASH mentions the following.

    The flash may be fired during a precapture sequence (triggered by android.control.aePrecaptureTrigger) and will always be fired for captures for which the android.control.captureIntent field is set to STILL_CAPTURE

    So, as per the docs, it should work even without AE precapture trigger in case of ON_ALWAYS_FLASH.

    However, there is always the chance that the camera HAL implementation in that device is just buggy. Furthermore, the CTS tests also don't seem to have the case of flash image capture without AE precapture trigger, which increases the chance of such a bug. What devices have you experienced this problem? Is it from a single brand or happens in various kinds of devices?

    In such a case, I recommend simply adding an AE precapture trigger before your still image capture like the CTS test does. If you don't really need the precapture, then you can just not wait for any 3A convergence to reduce image capture latency. Not 100% sure, but you may even be able to add precapture trigger to your TEMPLATE_STILL_CAPTURE request as well. For example, just modify your code to the following.

    val captureRequestBuilder = cameraDevice
                .createCaptureRequest(AndroidCameraDevice.TEMPLATE_STILL_CAPTURE)
     
    captureRequestBuilder.apply {
      set(CaptureRequest.CONTROL_AE_MODE,
         CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH)
      set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
         CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START)
    }
    

    If this doesn't work, try submit AE precapture trigger separately first with Preview template like in the CTS test. Note that precapture trigger should never be submitted with the repeating request, it should be a single capture request like the still image capture.

    Also, you can use the watch command for further checking if the capture request key/value pairs are really submitted properly or not, to eliminate any implementation mistake in your side. For example, run the adb shell cmd media.camera watch start -m android.control.captureIntent,3a && adb shell cmd media.camera watch live command and then capture an image. (may not work in all/old devices)