Skip to content

Commit dec95ff

Browse files
committed
Add code to support UI of fps setting
(show appropriate options in dropdown and selection of default fps)
1 parent c274590 commit dec95ff

3 files changed

Lines changed: 144 additions & 42 deletions

File tree

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import androidx.core.content.ContextCompat
4242
import app.grapheneos.camera.analyzer.QRAnalyzer
4343
import app.grapheneos.camera.ktx.markAs16by9Layout
4444
import app.grapheneos.camera.ktx.markAs4by3Layout
45+
import app.grapheneos.camera.ui.SettingsDialog
4546
import app.grapheneos.camera.ui.activities.CaptureActivity
4647
import app.grapheneos.camera.ui.activities.MainActivity
4748
import app.grapheneos.camera.ui.activities.MoreSettings
@@ -318,7 +319,7 @@ class CamConfig(private val mActivity: MainActivity) {
318319
var videoQuality: Quality = SettingValues.Default.VIDEO_QUALITY
319320
get() {
320321
return if (modePref.contains(videoQualityKey)) {
321-
mActivity.settingsDialog.titleToQuality(
322+
SettingsDialog.titleToQuality(
322323
modePref.getString(videoQualityKey, "")!!
323324
)
324325
} else {
@@ -350,10 +351,9 @@ class CamConfig(private val mActivity: MainActivity) {
350351
var videoFrameRate: Range<Int> = SettingValues.Default.VIDEO_FRAME_RATE
351352
get() {
352353
return if (modePref.contains(videoFrameRateKey)) {
353-
mActivity.settingsDialog.titleToFrameRateRange(
354+
SettingsDialog.titleToFrameRateRange(
354355
modePref.getString(videoFrameRateKey, "")!!
355356
)
356-
357357
} else {
358358
SettingValues.Default.VIDEO_FRAME_RATE
359359
}

app/src/main/java/app/grapheneos/camera/capturer/VideoCapturer.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ class VideoCapturer(private val mActivity: MainActivity) {
285285

286286
mActivity.settingsDialog.includeAudioToggle.isEnabled = false
287287
mActivity.settingsDialog.videoQualitySpinner.isEnabled = false
288+
mActivity.settingsDialog.videoFrameRateSpinner.isEnabled = false
288289
mActivity.settingsDialog.enableEISToggle.isEnabled = false
289290

290291
mActivity.flipCamIcon.setImageResource(R.drawable.pause)
@@ -323,6 +324,7 @@ class VideoCapturer(private val mActivity: MainActivity) {
323324

324325
mActivity.settingsDialog.includeAudioToggle.isEnabled = true
325326
mActivity.settingsDialog.videoQualitySpinner.isEnabled = true
327+
mActivity.settingsDialog.videoFrameRateSpinner.isEnabled = true
326328
mActivity.settingsDialog.enableEISToggle.isEnabled = true
327329

328330
if (mActivity !is VideoCaptureActivity) {

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

Lines changed: 139 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import android.os.Handler
1010
import android.os.Looper
1111
import android.provider.Settings
1212
import android.util.Log
13+
import android.util.Range
1314
import android.view.MotionEvent
1415
import android.view.View
1516
import android.view.ViewGroup
@@ -54,8 +55,13 @@ class SettingsDialog(val mActivity: MainActivity) :
5455
private var aRToggle: ToggleButton
5556
var torchToggle: ToggleButton
5657
private var gridToggle: ImageView
58+
5759
var videoQualitySpinner: Spinner
58-
private lateinit var vQAdapter: ArrayAdapter<String>
60+
var videoFrameRateSpinner: Spinner
61+
62+
private lateinit var videoQualityAdapter: ArrayAdapter<String>
63+
private lateinit var videoFrameRateAdapter: ArrayAdapter<String>
64+
5965
private var focusTimeoutSpinner: Spinner
6066
private var timerSpinner: Spinner
6167

@@ -77,6 +83,7 @@ class SettingsDialog(val mActivity: MainActivity) :
7783
private var enableEISSetting: View
7884
private var selfIlluminationSetting: View
7985
private var videoQualitySetting: View
86+
private var videoFrameRateSetting: LinearLayout
8087
private var timerSetting: View
8188

8289
var settingsFrame: View
@@ -218,19 +225,35 @@ class SettingsDialog(val mActivity: MainActivity) :
218225
videoQualitySpinner.onItemSelectedListener =
219226
object : AdapterView.OnItemSelectedListener {
220227
override fun onItemSelected(
221-
p0: AdapterView<*>?,
222-
p1: View?,
228+
parent: AdapterView<*>?,
229+
view: View?,
223230
position: Int,
224-
p3: Long
231+
id: Long
225232
) {
226-
227-
val choice = vQAdapter.getItem(position) as String
233+
val choice = videoQualityAdapter.getItem(position) as String
228234
updateVideoQuality(choice)
229235
}
230236

231-
override fun onNothingSelected(p0: AdapterView<*>?) {}
237+
override fun onNothingSelected(parent: AdapterView<*>?) {}
238+
}
239+
240+
videoFrameRateSpinner = binding.videoFrameRateSpinner
241+
242+
videoFrameRateSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
243+
override fun onItemSelected(
244+
parent: AdapterView<*>?,
245+
view: View?,
246+
position: Int,
247+
id: Long
248+
) {
249+
val choice = videoFrameRateAdapter.getItem(position) as String
250+
updateVideoFrameRate(choice)
232251
}
233252

253+
override fun onNothingSelected(parent: AdapterView<*>?) {}
254+
255+
}
256+
234257
qRadio = binding.qualityRadio
235258
lRadio = binding.latencyRadio
236259

@@ -320,6 +343,7 @@ class SettingsDialog(val mActivity: MainActivity) :
320343
enableEISSetting = binding.enableEisSetting
321344
selfIlluminationSetting = binding.selfIlluminationSetting
322345
videoQualitySetting = binding.videoQualitySetting
346+
videoFrameRateSetting = binding.videoFrameRateSetting
323347
timerSetting = binding.timerSetting
324348

325349
includeAudioToggle = binding.includeAudioSwitch
@@ -369,19 +393,22 @@ class SettingsDialog(val mActivity: MainActivity) :
369393
fun showOnlyRelevantSettings() {
370394
@androidx.camera.camera2.interop.ExperimentalCamera2Interop
371395
if (camConfig.isVideoMode) {
372-
includeAudioSetting.visibility = View.VISIBLE
373396
enableEISSetting.visibility = View.GONE
374397
for (mode in Camera2CameraInfo.from(camConfig.camera!!.cameraInfo)
375398
.getCameraCharacteristic(CameraCharacteristics
376399
.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES)!!){
377400
if (mode == CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_ON)
378401
enableEISSetting.visibility = View.VISIBLE
379402
}
403+
includeAudioSetting.visibility = View.VISIBLE
380404
videoQualitySetting.visibility = View.VISIBLE
405+
videoFrameRateSpinner.visibility = View.VISIBLE
406+
videoFrameRateSetting.visibility = View.VISIBLE
381407
} else {
382408
includeAudioSetting.visibility = View.GONE
383409
enableEISSetting.visibility = View.GONE
384410
videoQualitySetting.visibility = View.GONE
411+
videoFrameRateSetting.visibility = View.GONE
385412
}
386413

387414
selfIlluminationSetting.visibility =
@@ -434,21 +461,23 @@ class SettingsDialog(val mActivity: MainActivity) :
434461
if (resCam) {
435462
camConfig.startCamera(true)
436463
} else {
437-
videoQualitySpinner.setSelection(getAvailableQTitles().indexOf(choice))
464+
videoQualitySpinner.setSelection(getAvailableQualityTitles().indexOf(choice))
438465

439466
}
440467
}
441468

442-
fun titleToQuality(title: String): Quality {
443-
return when (title) {
444-
"2160p (UHD)" -> Quality.UHD
445-
"1080p (FHD)" -> Quality.FHD
446-
"720p (HD)" -> Quality.HD
447-
"480p (SD)" -> Quality.SD
448-
else -> {
449-
Log.e("TAG", "Unknown quality: $title")
450-
Quality.SD
451-
}
469+
fun updateVideoFrameRate(choice: String, restartCamera: Boolean = true) {
470+
471+
val videoFrameRate = titleToFrameRateRange(choice)
472+
473+
if (videoFrameRate == camConfig.videoFrameRate) return
474+
475+
camConfig.videoFrameRate = videoFrameRate
476+
477+
if (restartCamera) {
478+
camConfig.startCamera(true)
479+
} else {
480+
videoFrameRateSpinner.setSelection(videoFrameRateAdapter.getPosition(choice))
452481
}
453482
}
454483

@@ -620,27 +649,31 @@ class SettingsDialog(val mActivity: MainActivity) :
620649
return Recorder.getVideoCapabilities(cameraInfo).getSupportedQualities(DynamicRange.SDR)
621650
}
622651

623-
private fun getAvailableQTitles(): List<String> {
652+
private fun getAvailableVideoFrameRates(): List<Range<Int>> {
653+
val resSet = camConfig.camera?.cameraInfo?.supportedFrameRateRanges ?: Collections.emptySet()
654+
// Individual fps -> Ranged fps (sorted by lower value of range and then upper for each lower value)
655+
val resList = resSet.sortedWith(compareBy<Range<Int>> { it.lower != it.upper }.thenBy { it.lower }.thenBy { it.upper })
656+
return resList
657+
}
658+
659+
private fun getAvailableQualityTitles(): List<String> {
624660
val titles = arrayListOf<String>()
625661

626662
getAvailableQualities().forEach {
627-
titles.add(getTitleFor(it))
663+
titles.add(getTitleForQuality(it))
628664
}
629665

630666
return titles
631667
}
632668

633-
private fun getTitleFor(quality: Quality): String {
634-
return when (quality) {
635-
Quality.UHD -> "2160p (UHD)"
636-
Quality.FHD -> "1080p (FHD)"
637-
Quality.HD -> "720p (HD)"
638-
Quality.SD -> "480p (SD)"
639-
else -> {
640-
Log.i("TAG", "Unknown constant: $quality")
641-
"Unknown"
642-
}
669+
private fun getAvailableFRTitles(): List<String> {
670+
val titles = arrayListOf<String>()
671+
672+
getAvailableVideoFrameRates().forEach {
673+
titles.add(getTitleForFrameRateRange(it))
643674
}
675+
676+
return titles
644677
}
645678

646679
fun updateGridToggleUI() {
@@ -691,24 +724,91 @@ class SettingsDialog(val mActivity: MainActivity) :
691724
slideDialogDown()
692725
}
693726

694-
fun reloadQualities() {
727+
fun reloadVideoSettings() {
695728

696-
val titles = getAvailableQTitles()
729+
val qualityTitles = getAvailableQualityTitles()
730+
val frameRateTitles = getAvailableFRTitles()
697731

698-
vQAdapter = ArrayAdapter<String>(
732+
videoQualityAdapter = ArrayAdapter<String>(
699733
mActivity,
700734
android.R.layout.simple_spinner_item,
701-
titles
735+
qualityTitles
702736
)
703737

704-
vQAdapter.setDropDownViewResource(
738+
videoQualityAdapter.setDropDownViewResource(
705739
android.R.layout.simple_spinner_dropdown_item
706740
)
707741

708-
videoQualitySpinner.adapter = vQAdapter
742+
videoQualitySpinner.adapter = videoQualityAdapter
709743

710-
if (camConfig.videoQuality != Quality.HIGHEST) {
711-
videoQualitySpinner.setSelection(titles.indexOf(getTitleFor(camConfig.videoQuality)))
744+
videoFrameRateAdapter = ArrayAdapter<String>(
745+
mActivity,
746+
android.R.layout.simple_spinner_item,
747+
frameRateTitles
748+
)
749+
750+
videoFrameRateAdapter.setDropDownViewResource(
751+
android.R.layout.simple_spinner_dropdown_item
752+
)
753+
754+
videoFrameRateSpinner.adapter = videoFrameRateAdapter
755+
756+
videoFrameRateSpinner.setSelection(videoFrameRateAdapter.getPosition(getTitleForFrameRateRange(camConfig.videoFrameRate)))
757+
758+
if (camConfig.videoQuality != CamConfig.SettingValues.Default.VIDEO_QUALITY) {
759+
videoQualitySpinner.setSelection(videoQualityAdapter.getPosition(getTitleForQuality(camConfig.videoQuality)))
760+
}
761+
}
762+
763+
companion object {
764+
fun titleToQuality(title: String): Quality {
765+
return when (title) {
766+
"2160p (UHD)" -> Quality.UHD
767+
"1080p (FHD)" -> Quality.FHD
768+
"720p (HD)" -> Quality.HD
769+
"480p (SD)" -> Quality.SD
770+
else -> {
771+
Log.e("TAG", "Unknown quality: $title")
772+
Quality.SD
773+
}
774+
}
775+
}
776+
777+
fun titleToFrameRateRange(title: String): Range<Int> {
778+
val titleWithoutFps = title.dropLast(4)
779+
780+
if (titleWithoutFps.contains("-")) {
781+
val lUArr = titleWithoutFps.split("-")
782+
783+
val lower = lUArr[0].dropLast(1).toInt()
784+
val upper = lUArr[1].drop(1).toInt()
785+
786+
return Range(lower, upper)
787+
} else {
788+
val fps = titleWithoutFps.toInt()
789+
return Range(fps, fps)
790+
}
791+
}
792+
}
793+
794+
fun getTitleForFrameRateRange(range: Range<Int>) : String {
795+
if (range.lower == range.upper) {
796+
return "${range.lower} fps"
797+
} else {
798+
return "${range.lower} - ${range.upper} fps"
799+
}
800+
}
801+
802+
private fun getTitleForQuality(quality: Quality): String {
803+
return when (quality) {
804+
Quality.UHD -> "2160p (UHD)"
805+
Quality.FHD -> "1080p (FHD)"
806+
Quality.HD -> "720p (HD)"
807+
Quality.SD -> "480p (SD)"
808+
else -> {
809+
Log.i("TAG", "Unknown constant: $quality")
810+
"Unknown"
811+
}
712812
}
713813
}
714814
}

0 commit comments

Comments
 (0)