Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@
import androidx.camera.core.ImageAnalysis
import androidx.camera.core.ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888
import androidx.camera.core.Preview
import androidx.camera.core.resolutionselector.ResolutionSelector
import androidx.camera.core.resolutionselector.ResolutionStrategy
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.lifecycle.awaitInstance
import androidx.core.content.ContextCompat
import androidx.core.net.toUri
import androidx.core.view.doOnLayout
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
Expand Down Expand Up @@ -141,42 +144,55 @@
}

/** Initialize CameraX, and prepare to bind the camera use cases */
private fun setUpCamera() = viewLifecycleOwner.lifecycleScope.launch {
if (::cameraExecutor.isInitialized && !cameraExecutor.isShutdown) {
return@launch
}
// Initialize our background executor
cameraExecutor = Executors.newSingleThreadExecutor()
// ImageAnalysis
// Todo choose accurate output image resolution that respects quality,performance and face analysis SDKs https://simprints.atlassian.net/browse/CORE-2569
if (!::targetResolution.isInitialized) {
targetResolution = Size(binding.captureOverlay.width, binding.captureOverlay.height)
private fun setUpCamera() = binding.captureOverlay.doOnLayout {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this approach risking multiple listener registrations when setUpCamera() is called from different places?
I think it would be safer and more straight-forward if we simply await the view to be laid out inside the coroutine.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a great point. I’ve refactored setUpCamera() to use a suspending awaitLayout() extension instead. Thanks for the catch!

viewLifecycleOwner.lifecycleScope.launch {
if (::cameraExecutor.isInitialized && !cameraExecutor.isShutdown) {
return@launch
}
// Initialize our background executor
cameraExecutor = Executors.newSingleThreadExecutor()
// ImageAnalysis
// Todo choose accurate output image resolution that respects quality,performance and face analysis SDKs https://simprints.atlassian.net/browse/CORE-2569

Check warning on line 155 in face/capture/src/main/java/com/simprints/face/capture/screens/livefeedback/LiveFeedbackFragment.kt

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Complete the task associated to this TODO comment.

See more on https://sonarcloud.io/project/issues?id=Simprints_Android-Simprints-ID&issues=AZ0CftwjuLbE7AhQL_Pa&open=AZ0CftwjuLbE7AhQL_Pa&pullRequest=1621
if (!::targetResolution.isInitialized) {
targetResolution = Size(binding.captureOverlay.width, binding.captureOverlay.height)
}
val resolutionSelector = ResolutionSelector
.Builder()
.setResolutionStrategy(
ResolutionStrategy(
targetResolution,
ResolutionStrategy.FALLBACK_RULE_CLOSEST_HIGHER_THEN_LOWER,
),
).build()

val imageAnalyzer = ImageAnalysis
.Builder()
.setResolutionSelector(resolutionSelector)
.setOutputImageRotationEnabled(true)
.setOutputImageFormat(OUTPUT_IMAGE_FORMAT_RGBA_8888)
.build()
val cropAnalyzer = CropToTargetOverlayAnalyzer(binding.captureOverlay, ::analyze)

imageAnalyzer.setAnalyzer(cameraExecutor, cropAnalyzer)

// Preview
val preview = Preview
.Builder()
.setResolutionSelector(resolutionSelector)
.build()
val cameraProvider = ProcessCameraProvider.awaitInstance(requireContext())
cameraProvider.unbindAll()
val camera = cameraProvider.bindToLifecycle(
this@LiveFeedbackFragment,
DEFAULT_BACK_CAMERA,
preview,
imageAnalyzer,
)
cameraControl = camera.cameraControl
// Attach the view's surface provider to preview use case
preview.surfaceProvider = binding.faceCaptureCamera.surfaceProvider
Simber.i("Camera setup finished", tag = FACE_CAPTURE)
}

val imageAnalyzer = ImageAnalysis
.Builder()
.setTargetResolution(targetResolution)
.setOutputImageRotationEnabled(true)
.setOutputImageFormat(OUTPUT_IMAGE_FORMAT_RGBA_8888)
.build()
val cropAnalyzer = CropToTargetOverlayAnalyzer(binding.captureOverlay, ::analyze)

imageAnalyzer.setAnalyzer(cameraExecutor, cropAnalyzer)

// Preview
val preview = Preview.Builder().setTargetResolution(targetResolution).build()
val cameraProvider = ProcessCameraProvider.awaitInstance(requireContext())
cameraProvider.unbindAll()
val camera = cameraProvider.bindToLifecycle(
this@LiveFeedbackFragment,
DEFAULT_BACK_CAMERA,
preview,
imageAnalyzer,
)
cameraControl = camera.cameraControl
// Attach the view's surface provider to preview use case
preview.surfaceProvider = binding.faceCaptureCamera.surfaceProvider
Simber.i("Camera setup finished", tag = FACE_CAPTURE)
}

override fun onResume() {
Expand Down
Loading