CameraActivity: only bind 2 use cases at most + some other fixes

This commit is contained in:
Matéo Duparc 2022-04-12 16:09:56 +02:00
parent c521c7f998
commit ab48f9219b
Signed by: hardcoresushi
GPG Key ID: AFE384344A45E13A
3 changed files with 61 additions and 37 deletions

View File

@ -76,7 +76,7 @@ dependencies {
implementation "androidx.concurrent:concurrent-futures:1.1.0" implementation "androidx.concurrent:concurrent-futures:1.1.0"
def camerax_version = "1.1.0-beta02" def camerax_version = "1.1.0-beta03"
implementation "androidx.camera:camera-camera2:$camerax_version" implementation "androidx.camera:camera-camera2:$camerax_version"
implementation "androidx.camera:camera-lifecycle:$camerax_version" implementation "androidx.camera:camera-lifecycle:$camerax_version"
implementation "androidx.camera:camera-view:$camerax_version" implementation "androidx.camera:camera-view:$camerax_version"

View File

@ -78,6 +78,7 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
private var camera: Camera? = null private var camera: Camera? = null
private var resolutions: List<Size>? = null private var resolutions: List<Size>? = null
private var currentResolutionIndex: Int = 0 private var currentResolutionIndex: Int = 0
private var currentResolution: Size? = null
private var captureMode = ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY private var captureMode = ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY
private var isBackCamera = true private var isBackCamera = true
private var isInVideoMode = false private var isInVideoMode = false
@ -139,7 +140,11 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
if (newCaptureMode != captureMode) { if (newCaptureMode != captureMode) {
captureMode = newCaptureMode captureMode = newCaptureMode
binding.imageCaptureMode.setImageResource(resId) binding.imageCaptureMode.setImageResource(resId)
setupCamera() if (!isInVideoMode) {
cameraProvider.unbind(imageCapture)
refreshImageCapture()
cameraProvider.bindToLifecycle(this, cameraSelector, imageCapture)
}
} }
dialog.dismiss() dialog.dismiss()
} }
@ -151,9 +156,10 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, themeValue)
.setTitle(R.string.choose_resolution) .setTitle(R.string.choose_resolution)
.setSingleChoiceItems(it.map { size -> size.toString() }.toTypedArray(), currentResolutionIndex) { dialog, which -> .setSingleChoiceItems(it.map { size -> size.toString() }.toTypedArray(), currentResolutionIndex) { dialog, which ->
setupCamera(resolutions!![which]) currentResolution = resolutions!![which]
dialog.dismiss()
currentResolutionIndex = which currentResolutionIndex = which
setupCamera()
dialog.dismiss()
} }
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)
.show() .show()
@ -204,6 +210,7 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
} }
binding.imageModeSwitch.setOnClickListener { binding.imageModeSwitch.setOnClickListener {
isInVideoMode = !isInVideoMode isInVideoMode = !isInVideoMode
setupCamera()
binding.imageFlash.setImageResource(if (isInVideoMode) { binding.imageFlash.setImageResource(if (isInVideoMode) {
binding.recordVideoButton.visibility = View.VISIBLE binding.recordVideoButton.visibility = View.VISIBLE
binding.takePhotoButton.visibility = View.GONE binding.takePhotoButton.visibility = View.GONE
@ -239,6 +246,7 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
} }
true true
} }
resolutions = null
setupCamera() setupCamera()
} }
binding.takePhotoButton.onClick = ::onClickTakePhoto binding.takePhotoButton.onClick = ::onClickTakePhoto
@ -301,52 +309,67 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
private fun adaptPreviewSize(resolution: Size) { private fun adaptPreviewSize(resolution: Size) {
val screenWidth = resources.displayMetrics.widthPixels val screenWidth = resources.displayMetrics.widthPixels
binding.cameraPreview.layoutParams = if (screenWidth < resolution.width) { val screenHeight = resources.displayMetrics.heightPixels
RelativeLayout.LayoutParams(
screenWidth, var height = (resolution.height * (screenWidth.toFloat() / resolution.width)).toInt()
(resolution.height * (screenWidth.toFloat() / resolution.width)).toInt() var width = screenWidth
) if (height > screenHeight) {
} else { width = (width * (screenHeight.toFloat() / height)).toInt()
RelativeLayout.LayoutParams(resolution.width, resolution.height) height = screenHeight
} }
(binding.cameraPreview.layoutParams as RelativeLayout.LayoutParams).addRule(RelativeLayout.CENTER_IN_PARENT) binding.cameraPreview.layoutParams = RelativeLayout.LayoutParams(width, height).apply {
addRule(RelativeLayout.CENTER_IN_PARENT)
}
}
private fun refreshImageCapture() {
imageCapture = ImageCapture.Builder()
.setCaptureMode(captureMode)
.setFlashMode(imageCapture?.flashMode ?: ImageCapture.FLASH_MODE_AUTO)
.apply {
currentResolution?.let {
setTargetResolution(it)
}
}
.build()
}
private fun refreshVideoCapture() {
videoCapture = VideoCapture.Builder().apply {
currentResolution?.let {
setTargetResolution(it)
}
}.build()
} }
@SuppressLint("RestrictedApi") @SuppressLint("RestrictedApi")
private fun setupCamera(resolution: Size? = null){ private fun setupCamera() {
if (permissionsGranted && ::extensionsManager.isInitialized && ::cameraProvider.isInitialized) { if (permissionsGranted && ::extensionsManager.isInitialized && ::cameraProvider.isInitialized) {
imageCapture = ImageCapture.Builder()
.setCaptureMode(captureMode)
.setFlashMode(imageCapture?.flashMode ?: ImageCapture.FLASH_MODE_AUTO)
.apply {
resolution?.let {
setTargetResolution(it)
}
}
.build()
videoCapture = VideoCapture.Builder().apply {
resolution?.let {
setTargetResolution(it)
}
}.build()
cameraSelector = if (isBackCamera){ CameraSelector.DEFAULT_BACK_CAMERA } else { CameraSelector.DEFAULT_FRONT_CAMERA } cameraSelector = if (isBackCamera){ CameraSelector.DEFAULT_BACK_CAMERA } else { CameraSelector.DEFAULT_FRONT_CAMERA }
if (extensionsManager.isExtensionAvailable(cameraSelector, ExtensionMode.HDR)) { if (extensionsManager.isExtensionAvailable(cameraSelector, ExtensionMode.AUTO)) {
cameraSelector = extensionsManager.getExtensionEnabledCameraSelector(cameraSelector, ExtensionMode.HDR) cameraSelector = extensionsManager.getExtensionEnabledCameraSelector(cameraSelector, ExtensionMode.AUTO)
} }
cameraProvider.unbindAll() cameraProvider.unbindAll()
camera = cameraProvider.bindToLifecycle(this, cameraSelector, cameraPreview, imageCapture, videoCapture)
adaptPreviewSize(resolution ?: imageCapture!!.attachedSurfaceResolution!!.swap()) val currentUseCase = (if (isInVideoMode) {
refreshVideoCapture()
camera = cameraProvider.bindToLifecycle(this, cameraSelector, cameraPreview, videoCapture)
videoCapture
} else {
refreshImageCapture()
camera = cameraProvider.bindToLifecycle(this, cameraSelector, cameraPreview, imageCapture)
imageCapture
})!!
adaptPreviewSize(currentResolution ?: currentUseCase.attachedSurfaceResolution!!.swap())
if (resolutions == null) { if (resolutions == null) {
val info = Camera2CameraInfo.from(camera!!.cameraInfo) val info = Camera2CameraInfo.from(camera!!.cameraInfo)
val cameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager val cameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager
val characteristics = cameraManager.getCameraCharacteristics(info.cameraId) val characteristics = cameraManager.getCameraCharacteristics(info.cameraId)
characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)?.let { streamConfigurationMap -> characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)?.let { streamConfigurationMap ->
resolutions = streamConfigurationMap.getOutputSizes(imageCapture!!.imageFormat).map { it.swap() } resolutions = streamConfigurationMap.getOutputSizes(currentUseCase.imageFormat).map { it.swap() }
} }
} }
} }

View File

@ -41,7 +41,6 @@ import static androidx.camera.core.internal.ThreadConfig.OPTION_BACKGROUND_EXECU
import static androidx.camera.core.internal.UseCaseEventConfig.OPTION_USE_CASE_EVENT_CALLBACK; import static androidx.camera.core.internal.UseCaseEventConfig.OPTION_USE_CASE_EVENT_CALLBACK;
import android.Manifest; import android.Manifest;
import android.annotation.SuppressLint;
import android.media.AudioFormat; import android.media.AudioFormat;
import android.media.AudioRecord; import android.media.AudioRecord;
import android.media.CamcorderProfile; import android.media.CamcorderProfile;
@ -76,6 +75,7 @@ import androidx.annotation.VisibleForTesting;
import androidx.camera.core.AspectRatio; import androidx.camera.core.AspectRatio;
import androidx.camera.core.CameraSelector; import androidx.camera.core.CameraSelector;
import androidx.camera.core.CameraXThreads; import androidx.camera.core.CameraXThreads;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.Logger; import androidx.camera.core.Logger;
import androidx.camera.core.UseCase; import androidx.camera.core.UseCase;
import androidx.camera.core.impl.CameraInternal; import androidx.camera.core.impl.CameraInternal;
@ -121,7 +121,6 @@ import java.util.concurrent.atomic.AtomicReference;
* @hide * @hide
*/ */
@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
@SuppressLint("RestrictedApi")
public final class VideoCapture extends UseCase { public final class VideoCapture extends UseCase {
//////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////
@ -280,7 +279,9 @@ public final class VideoCapture extends UseCase {
@Nullable @Nullable
public UseCaseConfig<?> getDefaultConfig(boolean applyDefaultConfig, public UseCaseConfig<?> getDefaultConfig(boolean applyDefaultConfig,
@NonNull UseCaseConfigFactory factory) { @NonNull UseCaseConfigFactory factory) {
Config captureConfig = factory.getConfig(UseCaseConfigFactory.CaptureType.VIDEO_CAPTURE); Config captureConfig = factory.getConfig(
UseCaseConfigFactory.CaptureType.VIDEO_CAPTURE,
ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY);
if (applyDefaultConfig) { if (applyDefaultConfig) {
captureConfig = Config.mergeConfigs(captureConfig, DEFAULT_CONFIG.getConfig()); captureConfig = Config.mergeConfigs(captureConfig, DEFAULT_CONFIG.getConfig());