Android - Camera2 tap to focus not working

37 Views Asked by At

I am working on a Camera2 library that has a auto-focusing preview, and should support "tap to focus" to focus to a specific area.

I tried to follow tutorials in the internet, read Google's camera-samples code as well as browsing camerakit-android, CameraView and react-native-camera, but none of them showed a complete example or were simply not doing anything/no focusing, so I couldn't get it to work.

This is my code:

suspend fun focus(point: Point) {
  // prepare variables...

  // 1. stop repeating
  session.stopRepeating()

  // 2. submit repeating request to cancel any ongoing focus?
  val request1 = createBaseCaptureRequest(device, outputs)
  request1.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO)
  request1.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO)
  request1.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START)
  session.setRepeatingRequest(request1.build(), null, null)

  // 3. capture one request to start the trigger?
  val request2 = createBaseCaptureRequest(device, outputs)
  request2.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO)
  request2.set(CaptureRequest.CONTROL_AF_REGIONS, arrayOf(meteringRectangle))
  request2.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START)
  // this waits until onCaptureCompleted, coroutine helper func!
  session.capture(request2.build(), false)

  // 4. stop repeating again?
  session.stopRepeating()

  // 5. set it to idle
  val request3 = createBaseCaptureRequest(device, outputs)
  request3.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO)
  request3.set(CaptureRequest.CONTROL_AF_REGIONS, arrayOf(meteringRectangle))
  request3.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_IDLE)
  session.setRepeatingRequest(request3.build(), null, null)

  coroutineScope {
    launch {
      delay(FOCUS_RESET_TIMEOUT)
      Log.i(TAG, "Resetting focus to auto-focus...")
      // 6. stop repeating again?
      session.stopRepeating()

      // 7. set new repeating request without any AF options to go back
      val request4 = createBaseCaptureRequest(device, outputs)
      session.setRepeatingRequest(request4.build(), null, null)
    }
  }
}

As you might've noticed, I'm trying to do this without introducing a lot of callbacks as those are hard to follow - I'm trying to use Kotlin coroutines/suspend functions to make this as simple as possible, and possibly also cancelable.

Source code:

For some reason, it does auto-focus to the top of the screen, but not to the bottom of the screen. I tried to hardcode the point to eliminate my error:

val activeArea = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE)
// this should be the "bottom/center" point of the preview view,
// as camera sensor orientation is landscape
val point = Point(activeArea.width(), activeArea.centerY())

val meteringRectangle = MeteringRectangle(point,
                                          DEFAULT_METERING_SIZE,
                                          MeteringRectangle.METERING_WEIGHT_MAX - 1)

Is there any resource available for reliably focusing to a specific point of interest, without dropping too many preview frames? I simply can't get it to work now.

0

There are 0 best solutions below