Skip to content

Commit 31129a8

Browse files
committed
Handle cases when 30 fps is unavailable
(and prevent crash when video mode is directly turned on)
1 parent 07339a2 commit 31129a8

2 files changed

Lines changed: 55 additions & 16 deletions

File tree

app/src/main/java/app/grapheneos/camera/CamConfig.kt

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import androidx.annotation.StringRes
2222
import androidx.camera.camera2.interop.Camera2Interop
2323
import androidx.camera.core.AspectRatio
2424
import androidx.camera.core.Camera
25+
import androidx.camera.core.CameraInfo
2526
import androidx.camera.core.CameraSelector
2627
import androidx.camera.core.ImageAnalysis
2728
import androidx.camera.core.ImageCapture
@@ -227,6 +228,10 @@ class CamConfig(private val mActivity: MainActivity) {
227228

228229
var lastCapturedItem: CapturedItem? = null
229230

231+
private var frontCameraInfo : CameraInfo? = null
232+
233+
private var rearCameraInfo : CameraInfo? = null
234+
230235
init {
231236
if (mActivity !is SecureActivity) {
232237
CapturedItems.init(mActivity, this)
@@ -359,7 +364,7 @@ class CamConfig(private val mActivity: MainActivity) {
359364
modePref.getString(videoFrameRateKey, "")!!
360365
)
361366
} else {
362-
SettingValues.Default.VIDEO_FRAME_RATE
367+
defaultVideoFrameRate
363368
}
364369
}
365370
set(value) {
@@ -381,6 +386,14 @@ class CamConfig(private val mActivity: MainActivity) {
381386
return "${SettingValues.Key.VIDEO_FRAME_RATE}_$pf"
382387
}
383388

389+
val defaultVideoFrameRate : Range<Int>
390+
get() {
391+
val availableFrameRates = getAvailableVideoFrameRates()
392+
if (availableFrameRates.contains(SettingValues.Default.VIDEO_FRAME_RATE))
393+
return SettingValues.Default.VIDEO_FRAME_RATE
394+
return availableFrameRates[0]
395+
}
396+
384397
var flashMode: Int
385398
get() = if (imageCapture != null) imageCapture!!.flashMode else
386399
SettingValues.Default.FLASH_MODE
@@ -945,6 +958,24 @@ class CamConfig(private val mActivity: MainActivity) {
945958
startCamera(true)
946959
}
947960

961+
fun getCurrentCameraInfo() : CameraInfo {
962+
return if (lensFacing == CameraSelector.LENS_FACING_BACK) rearCameraInfo!!
963+
else frontCameraInfo!!
964+
}
965+
966+
fun getAvailableVideoFrameRates(): List<Range<Int>> {
967+
val resSet = getCurrentCameraInfo().supportedFrameRateRanges
968+
969+
// Individual fps -> Ranged fps (sorted by lower value of range and then upper for each lower value)
970+
val resList = resSet.sortedWith(compareBy<Range<Int>> { it.lower != it.upper }.thenBy { it.lower }.thenBy { it.upper })
971+
972+
// If the supportedFrameRateRange list is somehow empty due to device/library implementation
973+
// go with the most likely default rate
974+
if (resList.isEmpty()) return listOf(SettingValues.Default.VIDEO_FRAME_RATE)
975+
976+
return resList
977+
}
978+
948979
fun toggleCameraSelector() {
949980

950981
// Manually switch to the opposite lens facing
@@ -988,6 +1019,12 @@ class CamConfig(private val mActivity: MainActivity) {
9881019
return
9891020
}
9901021

1022+
// Select a single camera for front/rear facing
1023+
for (cameraInfo in cameraProvider!!.availableCameraInfos) {
1024+
if (cameraInfo.lensFacing == CameraSelector.LENS_FACING_FRONT) frontCameraInfo = cameraInfo
1025+
else if (cameraInfo.lensFacing == CameraSelector.LENS_FACING_BACK) rearCameraInfo = cameraInfo
1026+
}
1027+
9911028
// Manually switch to the other lens facing (if the default lens facing isn't
9921029
// supported for the current device)
9931030
if (!isLensFacingSupported(lensFacing)) {
@@ -1014,11 +1051,11 @@ class CamConfig(private val mActivity: MainActivity) {
10141051
}
10151052

10161053
private fun isLensFacingSupported(lensFacing : Int) : Boolean {
1017-
val tCameraSelector = CameraSelector.Builder()
1018-
.requireLensFacing(lensFacing)
1019-
.build()
1020-
1021-
return cameraProvider?.hasCamera(tCameraSelector) ?: false
1054+
return when(lensFacing) {
1055+
CameraSelector.LENS_FACING_FRONT -> frontCameraInfo != null
1056+
CameraSelector.LENS_FACING_BACK -> rearCameraInfo != null
1057+
else -> false
1058+
}
10221059
}
10231060

10241061
// Start the camera with latest hard configuration
@@ -1043,7 +1080,15 @@ class CamConfig(private val mActivity: MainActivity) {
10431080
if (mActivity.isDestroyed || mActivity.isFinishing) return
10441081

10451082
cameraSelector = CameraSelector.Builder()
1046-
.requireLensFacing(lensFacing)
1083+
.addCameraFilter {
1084+
return@addCameraFilter listOf(
1085+
if (lensFacing == CameraSelector.LENS_FACING_BACK) {
1086+
rearCameraInfo
1087+
} else {
1088+
frontCameraInfo
1089+
}
1090+
)
1091+
}
10471092
.build()
10481093

10491094
val builder = ImageCapture.Builder()

app/src/main/java/app/grapheneos/camera/ui/SettingsDialog.kt

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -674,12 +674,6 @@ class SettingsDialog(val mActivity: MainActivity) :
674674
return Recorder.getVideoCapabilities(cameraInfo).getSupportedQualities(DynamicRange.SDR)
675675
}
676676

677-
private fun getAvailableVideoFrameRates(): List<Range<Int>> {
678-
val resSet = camConfig.camera?.cameraInfo?.supportedFrameRateRanges ?: Collections.emptySet()
679-
// Individual fps -> Ranged fps (sorted by lower value of range and then upper for each lower value)
680-
val resList = resSet.sortedWith(compareBy<Range<Int>> { it.lower != it.upper }.thenBy { it.lower }.thenBy { it.upper })
681-
return resList
682-
}
683677

684678
private fun getAvailableQualityTitles(): List<String> {
685679
val titles = arrayListOf<String>()
@@ -691,10 +685,10 @@ class SettingsDialog(val mActivity: MainActivity) :
691685
return titles
692686
}
693687

694-
private fun getAvailableFRTitles(): List<String> {
688+
private fun getAvailableFrameRateTitles(): List<String> {
695689
val titles = arrayListOf<String>()
696690

697-
getAvailableVideoFrameRates().forEach {
691+
camConfig.getAvailableVideoFrameRates().forEach {
698692
titles.add(getTitleForFrameRateRange(it))
699693
}
700694

@@ -752,7 +746,7 @@ class SettingsDialog(val mActivity: MainActivity) :
752746
fun reloadVideoSettings() {
753747

754748
val qualityTitles = getAvailableQualityTitles()
755-
val frameRateTitles = getAvailableFRTitles()
749+
val frameRateTitles = getAvailableFrameRateTitles()
756750

757751
videoQualityAdapter = ArrayAdapter<String>(
758752
mActivity,

0 commit comments

Comments
 (0)