Aperture: Move video quality setting to top bar
Change-Id: Ieb37d8f85294cb50dc2a365bc3298d40106fc7ce
diff --git a/app/src/main/java/org/lineageos/aperture/MainActivity.kt b/app/src/main/java/org/lineageos/aperture/MainActivity.kt
index 1280e9d..b619f8d 100644
--- a/app/src/main/java/org/lineageos/aperture/MainActivity.kt
+++ b/app/src/main/java/org/lineageos/aperture/MainActivity.kt
@@ -45,6 +45,7 @@
import androidx.camera.extensions.ExtensionMode
import androidx.camera.extensions.ExtensionsManager
import androidx.camera.lifecycle.ProcessCameraProvider
+import androidx.camera.video.Quality
import androidx.camera.video.Recording
import androidx.camera.video.VideoRecordEvent
import androidx.camera.view.CameraController
@@ -103,6 +104,7 @@
private val timerChip by lazy { findViewById<Chip>(R.id.timerChip) }
private val torchButton by lazy { findViewById<ImageButton>(R.id.torchButton) }
private val videoModeButton by lazy { findViewById<MaterialButton>(R.id.videoModeButton) }
+ private val videoQualityButton by lazy { findViewById<ToggleButton>(R.id.videoQualityButton) }
private val viewFinder by lazy { findViewById<PreviewView>(R.id.viewFinder) }
private val viewFinderFocus by lazy { findViewById<ImageView>(R.id.viewFinderFocus) }
private val zoomLevel by lazy { findViewById<Slider>(R.id.zoomLevel) }
@@ -136,6 +138,8 @@
private var viewFinderTouchEvent: MotionEvent? = null
+ private val videoQuality: Quality
+ get() = sharedPreferences.videoQuality
private var recording: Recording? = null
private val recordingLock = Mutex()
private var recordingTime = 0L
@@ -224,6 +228,7 @@
// Set top bar button callbacks
aspectRatioButton.setOnClickListener { cycleAspectRatio() }
+ videoQualityButton.setOnClickListener { cycleVideoQuality() }
effectButton.setOnClickListener { cyclePhotoEffects() }
gridButton.setOnClickListener { cycleGridMode() }
timerButton.setOnClickListener { toggleTimerMode() }
@@ -558,6 +563,10 @@
}
}
+ // Get a stable reference to CameraInfo
+ // We can hardcode the first one in the filter as long as we use DEFAULT_*_CAMERA
+ camera = PhysicalCamera(cameraSelector.filter(cameraProvider.availableCameraInfos).first())
+
// Get the supported vendor extensions for the given camera selector
supportedExtensionModes = extensionsManager.getSupportedModes(cameraSelector)
@@ -571,6 +580,11 @@
aspectRatio = sharedPreferences.aspectRatio
val outputSize = CameraController.OutputSize(aspectRatio)
+ // Fallback to highest supported video quality
+ if (!camera.supportedVideoQualities.contains(sharedPreferences.videoQuality)) {
+ sharedPreferences.videoQuality = camera.supportedVideoQualities.first()
+ }
+
// Initialize the use case we want and set its properties
val cameraUseCases = when (cameraMode) {
CameraMode.QR -> {
@@ -584,7 +598,7 @@
}
CameraMode.VIDEO -> {
cameraController.videoCaptureTargetQuality = null // FIXME: video preview restart
- cameraController.videoCaptureTargetQuality = sharedPreferences.videoQuality
+ cameraController.videoCaptureTargetQuality = videoQuality
CameraController.VIDEO_CAPTURE
}
}
@@ -622,10 +636,6 @@
// Bind camera controller to lifecycle
cameraController.bindToLifecycle(this)
- // Get a stable reference to CameraInfo
- // We can hardcode the first one in the filter as long as we use DEFAULT_*_CAMERA
- camera = PhysicalCamera(cameraSelector.filter(cameraProvider.availableCameraInfos)[0])
-
// Restore settings that can be set on the fly
setGridMode(sharedPreferences.lastGridMode)
setFlashMode(sharedPreferences.photoFlashMode)
@@ -635,6 +645,7 @@
updateCameraModeButtons()
updateTimerModeIcon()
updateAspectRatioIcon()
+ updateVideoQualityIcon()
updatePhotoEffectIcon()
updateGridIcon()
updateTorchModeIcon()
@@ -717,6 +728,27 @@
bindCameraUseCases()
}
+ private fun cycleVideoQuality() {
+ if (!canRestartCamera()) {
+ return
+ }
+
+ val newVideoQuality = if (videoQuality == camera.supportedVideoQualities.first()) {
+ camera.supportedVideoQualities.last()
+ } else {
+ val index = camera.supportedVideoQualities.indexOf(videoQuality)
+ camera.supportedVideoQualities[maxOf(0, index - 1)]
+ }
+
+ if (newVideoQuality == videoQuality) {
+ return
+ }
+
+ sharedPreferences.videoQuality = newVideoQuality
+
+ bindCameraUseCases()
+ }
+
/**
* Update the grid button icon based on the value set in grid view
*/
@@ -789,6 +821,17 @@
}
}
+ private fun updateVideoQualityIcon() {
+ videoQualityButton.isVisible = cameraMode == CameraMode.VIDEO
+ videoQualityButton.text = when (videoQuality) {
+ Quality.SD -> "SD"
+ Quality.HD -> "HD"
+ Quality.FHD -> "FHD"
+ Quality.UHD -> "UHD"
+ else -> throw Exception("Unknown video quality $videoQuality")
+ }
+ }
+
/**
* Update the torch mode button icon based on the value set in camera
*/
diff --git a/app/src/main/java/org/lineageos/aperture/SharedPreferencesExt.kt b/app/src/main/java/org/lineageos/aperture/SharedPreferencesExt.kt
index 2a0bcb6..14de37b 100644
--- a/app/src/main/java/org/lineageos/aperture/SharedPreferencesExt.kt
+++ b/app/src/main/java/org/lineageos/aperture/SharedPreferencesExt.kt
@@ -188,29 +188,25 @@
// Video prefs
private const val VIDEO_QUALITY_KEY = "video_quality"
-private const val VIDEO_QUALITY_DEFAULT = "highest"
+private const val VIDEO_QUALITY_DEFAULT = "fhd"
internal var SharedPreferences.videoQuality: Quality
get() = when (getString(VIDEO_QUALITY_KEY, VIDEO_QUALITY_DEFAULT)) {
- "lowest" -> Quality.LOWEST
"sd" -> Quality.SD
"hd" -> Quality.HD
"fhd" -> Quality.FHD
"uhd" -> Quality.UHD
- "highest" -> Quality.HIGHEST
- // Default to highest
- else -> Quality.HIGHEST
+ // Default to fhd
+ else -> Quality.FHD
}
set(value) = edit {
putString(
VIDEO_QUALITY_KEY, when (value) {
- Quality.LOWEST -> "lowest"
Quality.SD -> "sd"
Quality.HD -> "hd"
Quality.FHD -> "fhd"
Quality.UHD -> "uhd"
- Quality.HIGHEST -> "highest"
- // Default to highest
+ // Default to fhd
else -> VIDEO_QUALITY_DEFAULT
}
)
diff --git a/app/src/main/java/org/lineageos/aperture/utils/PhysicalCamera.kt b/app/src/main/java/org/lineageos/aperture/utils/PhysicalCamera.kt
index f493a1a..f100a41 100644
--- a/app/src/main/java/org/lineageos/aperture/utils/PhysicalCamera.kt
+++ b/app/src/main/java/org/lineageos/aperture/utils/PhysicalCamera.kt
@@ -9,6 +9,7 @@
import android.hardware.camera2.CameraCharacteristics
import androidx.camera.camera2.interop.Camera2CameraInfo
import androidx.camera.core.CameraInfo
+import androidx.camera.video.QualitySelector
/**
* Class representing a physical device camera
@@ -40,4 +41,9 @@
* Flash is available or not
*/
val hasFlashUnit = cameraInfo.hasFlashUnit()
+
+ /**
+ * Supported video qualities
+ */
+ val supportedVideoQualities = QualitySelector.getSupportedQualities(cameraInfo)
}
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 83800ff..287d1a4 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -42,11 +42,24 @@
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/aspect_ratio_button_description"
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toStartOf="@+id/effectButton"
+ app:layout_constraintEnd_toStartOf="@+id/videoQualityButton"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/timerButton"
app:layout_constraintTop_toTopOf="parent" />
+ <ToggleButton
+ android:id="@+id/videoQualityButton"
+ style="@style/ApertureTopBarButton"
+ android:layout_width="@dimen/top_view_buttons_size"
+ android:layout_height="@dimen/top_view_buttons_size"
+ android:background="?attr/selectableItemBackgroundBorderless"
+ android:contentDescription="@string/video_quality_button_description"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toStartOf="@+id/effectButton"
+ app:layout_constraintHorizontal_bias="0.5"
+ app:layout_constraintStart_toEndOf="@+id/aspectRatioButton"
+ app:layout_constraintTop_toTopOf="parent" />
+
<ImageButton
android:id="@+id/effectButton"
style="@style/ApertureTopBarButton"
@@ -58,7 +71,7 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/gridButton"
app:layout_constraintHorizontal_bias="0.5"
- app:layout_constraintStart_toEndOf="@+id/aspectRatioButton"
+ app:layout_constraintStart_toEndOf="@+id/videoQualityButton"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
index c2a47b1..f80a8f7 100644
--- a/app/src/main/res/values/arrays.xml
+++ b/app/src/main/res/values/arrays.xml
@@ -12,25 +12,6 @@
<item>zero_shutter_lag</item>
</string-array>
- <!-- Video quality Preference -->
- <string-array name="video_quality_entries">
- <item>@string/video_quality_lowest</item>
- <item>SD</item>
- <item>HD</item>
- <item>FHD</item>
- <item>UHD</item>
- <item>@string/video_quality_highest</item>
- </string-array>
-
- <string-array name="video_quality_values">
- <item>lowest</item>
- <item>sd</item>
- <item>hd</item>
- <item>fhd</item>
- <item>uhd</item>
- <item>highest</item>
- </string-array>
-
<string-array name="qr_bottom_sheet_dialog_types">
<item>@string/qr_type_bytes</item>
<item>@string/qr_type_text</item>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index d1c2d64..31cb759 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -4,6 +4,7 @@
<!-- Button descriptions -->
<string name="timer_button_description">Timer</string>
<string name="aspect_ratio_button_description">Aspect ratio</string>
+ <string name="video_quality_button_description">Video quality</string>
<string name="effect_button_description">Effect</string>
<string name="grid_button_description">Grid</string>
<string name="torch_button_description">Torch</string>
@@ -46,7 +47,6 @@
<!-- Preference Titles -->
<string name="general_header">General</string>
<string name="photos_header">Photos</string>
- <string name="videos_header">Videos</string>
<!-- General Preferences -->
<string name="bright_screen_title">Bright screen</string>
@@ -62,9 +62,4 @@
<string name="photo_capture_mode_maximize_quality">Maximize quality</string>
<string name="photo_capture_mode_minimize_latency">Minimize latency</string>
<string name="photo_capture_mode_zsl">Zero shutter lag (experimental)</string>
-
- <!-- Videos Preferences -->
- <string name="video_quality_title">Video quality</string>
- <string name="video_quality_lowest">Lowest</string>
- <string name="video_quality_highest">Highest</string>
</resources>
\ No newline at end of file
diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml
index f1cec37..e5bbbc9 100644
--- a/app/src/main/res/xml/root_preferences.xml
+++ b/app/src/main/res/xml/root_preferences.xml
@@ -42,19 +42,4 @@
</PreferenceCategory>
- <PreferenceCategory
- app:iconSpaceReserved="false"
- app:title="@string/videos_header">
-
- <ListPreference
- app:defaultValue="highest"
- app:entries="@array/video_quality_entries"
- app:entryValues="@array/video_quality_values"
- app:iconSpaceReserved="false"
- app:key="video_quality"
- app:title="@string/video_quality_title"
- app:useSimpleSummaryProvider="true" />
-
- </PreferenceCategory>
-
</PreferenceScreen>
\ No newline at end of file