Taking picture with flash on camera2 gives picture “after” flash occured (i.e without flash)

久未见 提交于 2019-12-23 15:43:46

问题


I based my code on the sample from Google Camera2-Basic and added flash always support. But It looks like the picture is taken right after the flash has occur. I (almost) always get non flashed picture, even though the flash is triggered.

The modified preview request builder :

mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH);

And I also added this control mode to captureStillPicture()

captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH);

and modified the process() switch with :

       case STATE_WAITING_PRECAPTURE: {
          // CONTROL_AE_STATE can be null on some devices
          Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
          Log.i(TAG, "aeState = " + aeState);
          if (aeState == null ||
              aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE ||
              aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED ||
              aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {
            mState = STATE_WAITING_NON_PRECAPTURE;
          }
          break;
        }

回答1:


I had this exact same problem, also on a Nexus 5. I worked around it by checking CaptureResult.FLASH_STATE and triggering a capture immediately if it is equal to CaptureResult.FLASH_STATE_FIRED. Basically, if the flash fires, then you need to do a capture right then and there, regardless of what state you are in, because it's only going to fire once. If the auto-focus/exposure etc hasn't properly converged at that point there's nothing you can do about it.

You can do a check at the start of onCaptureCompleted like this:

if(mFlashAvailable && mWaitingForFlash)
{
     Integer flashState = result.get(CaptureResult.FLASH_STATE);
     if(flashState != null && flashState==CaptureResult.FLASH_STATE_FIRED)
     {
         mWaitingForFlash = false;

         // do the capture...
         mState = STATE_PICTURE_TAKEN;
         captureStillPicture();

         return;  // don't call process()
     }
}

mFlashAvailable is set from the CameraCharacteristics when opening the camera like this:

mFlashAvailable = characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);

mWaitingForFlash is just a flag you can set when you start the precapture, so that you don't capture more than one frame. This might not be necessary in your particular case however.

That will take care of when the flash fires before the state converges (i.e. the picture is after the flash), as you describe in your question. However you also need to handle the case when the flash is firing late (I've never seen this actually happen but just in case). You can do that by setting a flag like mExpectingFlash = true; when setting the CONTROL_AE_MODE to CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH, and not capturing the usual way if it is true (since you will capture when you detect the flash firing state instead). You can also set this flag when you get aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED if you are using CONTROL_AE_MODE_ON_AUTO_FLASH. As a safety net I have a timeout so I don't end up waiting for a flash that never comes in case CONTROL_AE_STATE_FLASH_REQUIRED is detected but the flash doesn't fire.

If you capture multiple frames, you can read the timestamp when you detect the flash firing, like this:

 long timestamp = result.get(CaptureResult.SENSOR_TIMESTAMP);

and then cross check it against the timestamp of the image in onImageAvailable

 Image image = reader.acquireLatestImage();
 if (image != null)
 {
     long timestamp = image.getTimestamp();
     // ....
 }


来源:https://stackoverflow.com/questions/33894917/taking-picture-with-flash-on-camera2-gives-picture-after-flash-occured-i-e-wi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!