feat: Use new CameraX Recorder API (Upgrade CameraX to alpha12/32) (#543)
* chore(deps): Upgrade CameraX to alpha10/30 * chore(deps): Add first stable CameraX Video library * feat: Use new CameraX Video API * chore(deps): Upgrade CameraX from 10 -> 12 * fix: Replace deprecated APIs * Update CameraViewModule.kt * fix: Fix file creation
This commit is contained in:
@@ -16,6 +16,8 @@ import androidx.camera.core.*
|
||||
import androidx.camera.core.impl.*
|
||||
import androidx.camera.extensions.*
|
||||
import androidx.camera.lifecycle.ProcessCameraProvider
|
||||
import androidx.camera.video.*
|
||||
import androidx.camera.video.VideoCapture
|
||||
import androidx.camera.view.PreviewView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.*
|
||||
@@ -121,10 +123,12 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
|
||||
|
||||
internal var camera: Camera? = null
|
||||
internal var imageCapture: ImageCapture? = null
|
||||
internal var videoCapture: VideoCapture? = null
|
||||
internal var videoCapture: Recorder? = null
|
||||
private var imageAnalysis: ImageAnalysis? = null
|
||||
private var preview: Preview? = null
|
||||
|
||||
internal var activeVideoRecording: Recording? = null
|
||||
|
||||
private var lastFrameProcessorCall = System.currentTimeMillis()
|
||||
|
||||
private var extensionsManager: ExtensionsManager? = null
|
||||
@@ -234,7 +238,7 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
|
||||
preview?.targetRotation = rotation
|
||||
imageCapture?.targetRotation = rotation
|
||||
imageAnalysis?.targetRotation = rotation
|
||||
videoCapture?.setTargetRotation(rotation)
|
||||
// TODO: videoCapture?.setTargetRotation(rotation)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,11 +342,11 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
|
||||
val tryEnableExtension: (suspend (extension: Int) -> Unit) = lambda@ { extension ->
|
||||
if (extensionsManager == null) {
|
||||
Log.i(TAG, "Initializing ExtensionsManager...")
|
||||
extensionsManager = ExtensionsManager.getInstance(context).await()
|
||||
extensionsManager = ExtensionsManager.getInstanceAsync(context, cameraProvider).await()
|
||||
}
|
||||
if (extensionsManager!!.isExtensionAvailable(cameraProvider, cameraSelector, extension)) {
|
||||
if (extensionsManager!!.isExtensionAvailable(cameraSelector, extension)) {
|
||||
Log.i(TAG, "Enabling extension $extension...")
|
||||
cameraSelector = extensionsManager!!.getExtensionEnabledCameraSelector(cameraProvider, cameraSelector, extension)
|
||||
cameraSelector = extensionsManager!!.getExtensionEnabledCameraSelector(cameraSelector, extension)
|
||||
} else {
|
||||
Log.e(TAG, "Extension $extension is not available for the given Camera!")
|
||||
throw when (extension) {
|
||||
@@ -355,11 +359,14 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
|
||||
|
||||
val previewBuilder = Preview.Builder()
|
||||
.setTargetRotation(rotation)
|
||||
|
||||
val imageCaptureBuilder = ImageCapture.Builder()
|
||||
.setTargetRotation(rotation)
|
||||
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
|
||||
val videoCaptureBuilder = VideoCapture.Builder()
|
||||
.setTargetRotation(rotation)
|
||||
|
||||
val videoRecorderBuilder = Recorder.Builder()
|
||||
.setExecutor(cameraExecutor)
|
||||
|
||||
val imageAnalysisBuilder = ImageAnalysis.Builder()
|
||||
.setTargetRotation(rotation)
|
||||
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
|
||||
@@ -371,7 +378,7 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
|
||||
val aspectRatio = aspectRatio(previewView.height, previewView.width) // flipped because it's in sensor orientation.
|
||||
previewBuilder.setTargetAspectRatio(aspectRatio)
|
||||
imageCaptureBuilder.setTargetAspectRatio(aspectRatio)
|
||||
videoCaptureBuilder.setTargetAspectRatio(aspectRatio)
|
||||
// TODO: Aspect Ratio for Video Recorder?
|
||||
imageAnalysisBuilder.setTargetAspectRatio(aspectRatio)
|
||||
} else {
|
||||
// User has selected a custom format={}. Use that
|
||||
@@ -379,9 +386,16 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
|
||||
Log.i(TAG, "Using custom format - photo: ${format.photoSize}, video: ${format.videoSize} @ $fps FPS")
|
||||
previewBuilder.setTargetResolution(format.videoSize)
|
||||
imageCaptureBuilder.setTargetResolution(format.photoSize)
|
||||
videoCaptureBuilder.setTargetResolution(format.videoSize)
|
||||
imageAnalysisBuilder.setTargetResolution(format.videoSize)
|
||||
|
||||
// TODO: Ability to select resolution exactly depending on format? Just like on iOS...
|
||||
when (min(format.videoSize.height, format.videoSize.width)) {
|
||||
in 0..480 -> videoRecorderBuilder.setQualitySelector(QualitySelector.from(Quality.SD))
|
||||
in 480..720 -> videoRecorderBuilder.setQualitySelector(QualitySelector.from(Quality.HD))
|
||||
in 720..1080 -> videoRecorderBuilder.setQualitySelector(QualitySelector.from(Quality.FHD))
|
||||
in 1080..2160 -> videoRecorderBuilder.setQualitySelector(QualitySelector.from(Quality.UHD))
|
||||
}
|
||||
|
||||
fps?.let { fps ->
|
||||
if (format.frameRateRanges.any { it.contains(fps) }) {
|
||||
// Camera supports the given FPS (frame rate range)
|
||||
@@ -391,7 +405,7 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
|
||||
Camera2Interop.Extender(previewBuilder)
|
||||
.setCaptureRequestOption(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, Range(fps, fps))
|
||||
.setCaptureRequestOption(CaptureRequest.SENSOR_FRAME_DURATION, frameDuration)
|
||||
videoCaptureBuilder.setVideoFrameRate(fps)
|
||||
// TODO: Frame Rate/FPS for Video Recorder?
|
||||
} else {
|
||||
throw FpsNotContainedInFormatError(fps)
|
||||
}
|
||||
@@ -404,8 +418,12 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
|
||||
}
|
||||
}
|
||||
|
||||
val videoRecorder = videoRecorderBuilder.build()
|
||||
val videoCapture = VideoCapture.withOutput(videoRecorder)
|
||||
videoCapture.targetRotation = rotation
|
||||
|
||||
// Unbind use cases before rebinding
|
||||
videoCapture = null
|
||||
this.videoCapture = null
|
||||
imageCapture = null
|
||||
imageAnalysis = null
|
||||
cameraProvider.unbindAll()
|
||||
@@ -414,8 +432,8 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer
|
||||
val useCases = ArrayList<UseCase>()
|
||||
if (video == true) {
|
||||
Log.i(TAG, "Adding VideoCapture use-case...")
|
||||
videoCapture = videoCaptureBuilder.build()
|
||||
useCases.add(videoCapture!!)
|
||||
this.videoCapture = videoRecorder
|
||||
useCases.add(videoCapture)
|
||||
}
|
||||
if (photo == true) {
|
||||
if (fallbackToSnapshot) {
|
||||
|
||||
Reference in New Issue
Block a user