Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(re) add support for 4:3 video #433

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 57 additions & 21 deletions app/src/main/java/app/grapheneos/camera/CamConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class CamConfig(private val mActivity: MainActivity) {
const val FOCUS_TIMEOUT = "focus_timeout"
const val VIDEO_QUALITY = "video_quality"
const val ASPECT_RATIO = "aspect_ratio"
const val VIDEO_ASPECT_RATIO = "video_aspect_ratio"
const val INCLUDE_AUDIO = "include_audio"
const val ENABLE_EIS = "enable_eis"
const val SCAN = "scan"
Expand Down Expand Up @@ -119,6 +120,7 @@ class CamConfig(private val mActivity: MainActivity) {
const val GRID_TYPE_INDEX = 0

const val ASPECT_RATIO = AspectRatio.RATIO_4_3
const val VIDEO_ASPECT_RATIO = AspectRatio.RATIO_16_9

val VIDEO_QUALITY = Quality.HIGHEST

Expand Down Expand Up @@ -275,29 +277,32 @@ class CamConfig(private val mActivity: MainActivity) {

private var currentMode: CameraMode = DEFAULT_CAMERA_MODE

var aspectRatio: Int
private var photoAspectRatio: Int
get() {
return when {
isVideoMode -> {
AspectRatio.RATIO_16_9
}
isQRMode -> {
AspectRatio.RATIO_4_3
}
else -> {
commonPref.getInt(
SettingValues.Key.ASPECT_RATIO,
SettingValues.Default.ASPECT_RATIO
)
}
}
return commonPref.getInt(
SettingValues.Key.ASPECT_RATIO,
SettingValues.Default.ASPECT_RATIO
)
}
set(value) {
val editor = commonPref.edit()
editor.putInt(SettingValues.Key.ASPECT_RATIO, value)
editor.apply()
}

private var videoAspectRatio: Int
get() {
return commonPref.getInt(
SettingValues.Key.VIDEO_ASPECT_RATIO,
SettingValues.Default.VIDEO_ASPECT_RATIO
)
}
set(value) {
val editor = commonPref.edit()
editor.putInt(SettingValues.Key.VIDEO_ASPECT_RATIO, value)
editor.apply()
}

var lensFacing = DEFAULT_LENS_FACING

private lateinit var cameraSelector: CameraSelector
Expand Down Expand Up @@ -801,11 +806,16 @@ class CamConfig(private val mActivity: MainActivity) {
mActivity.settingsDialog.cmRadioGroup.check(R.id.latency_radio)
}

aspectRatio = commonPref.getInt(
photoAspectRatio = commonPref.getInt(
SettingValues.Key.ASPECT_RATIO,
SettingValues.Default.ASPECT_RATIO
)

videoAspectRatio = commonPref.getInt(
SettingValues.Key.VIDEO_ASPECT_RATIO,
SettingValues.Default.VIDEO_ASPECT_RATIO
)

includeAudio = commonPref.getBoolean(
SettingValues.Key.INCLUDE_AUDIO,
SettingValues.Default.INCLUDE_AUDIO
Expand Down Expand Up @@ -886,10 +896,18 @@ class CamConfig(private val mActivity: MainActivity) {
}

fun toggleAspectRatio() {
aspectRatio = if (aspectRatio == AspectRatio.RATIO_16_9) {
AspectRatio.RATIO_4_3
if (isVideoMode) {
videoAspectRatio = if (videoAspectRatio == AspectRatio.RATIO_16_9) {
AspectRatio.RATIO_4_3
} else {
AspectRatio.RATIO_16_9
}
} else {
AspectRatio.RATIO_16_9
photoAspectRatio = if (photoAspectRatio == AspectRatio.RATIO_16_9) {
AspectRatio.RATIO_4_3
} else {
AspectRatio.RATIO_16_9
}
}
startCamera(true)
}
Expand Down Expand Up @@ -970,10 +988,19 @@ class CamConfig(private val mActivity: MainActivity) {
return cameraProvider?.hasCamera(tCameraSelector) ?: false
}

fun getCurrentModeAspectRatio(): Int {
return when {
isQRMode -> AspectRatio.RATIO_4_3
isVideoMode -> videoAspectRatio
else -> photoAspectRatio
}
}

// Start the camera with latest hard configuration
fun startCamera(forced: Boolean = false) {
if ((!forced && camera != null) || cameraProvider == null) return

val currentAspectRatio = getCurrentModeAspectRatio()
mActivity.exposureBar.hidePanel()
modePref = mActivity.getSharedPreferences(currentMode.name, Context.MODE_PRIVATE)

Expand Down Expand Up @@ -1016,7 +1043,7 @@ class CamConfig(private val mActivity: MainActivity) {

val useCaseGroupBuilder = UseCaseGroup.Builder()
val aspectRatioStrategy = AspectRatioStrategy(
aspectRatio, AspectRatioStrategy.FALLBACK_RULE_AUTO
currentAspectRatio, AspectRatioStrategy.FALLBACK_RULE_AUTO
)

if (isQRMode) {
Expand Down Expand Up @@ -1056,6 +1083,7 @@ class CamConfig(private val mActivity: MainActivity) {
videoCapture =
VideoCapture.withOutput(
Recorder.Builder()
.setAspectRatio(currentAspectRatio)
.setQualitySelector(QualitySelector.from(videoQuality))
.build()
)
Expand Down Expand Up @@ -1147,6 +1175,14 @@ class CamConfig(private val mActivity: MainActivity) {
}
imageCapture = null

if (videoAspectRatio == AspectRatio.RATIO_4_3) {
videoAspectRatio = AspectRatio.RATIO_16_9
mActivity.showMessage(mActivity.getString(R.string.aspect_ratio_unsupported_by_selected_resolution))
startCamera(true)
mActivity.settingsDialog.showOnlyRelevantSettings()
return
}

camera = cameraProvider!!.bindToLifecycle(
mActivity, cameraSelector,
newUseCaseGroupBuilder.build()
Expand Down Expand Up @@ -1177,7 +1213,7 @@ class CamConfig(private val mActivity: MainActivity) {
// Focus camera on touch/tap
mActivity.previewView.setOnTouchListener(mActivity)
mActivity.previewView.apply {
when (aspectRatio) {
when (currentAspectRatio) {
AspectRatio.RATIO_16_9 -> {
markAs16by9Layout()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class CountDownTimerUI @JvmOverloads constructor(
private fun beforeTimeStarts() {

val params: ViewGroup.LayoutParams = layoutParams
params.height = if (camConfig.aspectRatio == AspectRatio.RATIO_4_3) {
params.height = if (camConfig.getCurrentModeAspectRatio() == AspectRatio.RATIO_4_3) {
mActivity.previewView.width * 4 / 3
} else {
mActivity.previewView.height
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/app/grapheneos/camera/ui/CustomGrid.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class CustomGrid @JvmOverloads constructor(
return
}

val previewHeight = if (camConfig.aspectRatio == AspectRatio.RATIO_16_9) {
val previewHeight = if (camConfig.getCurrentModeAspectRatio() == AspectRatio.RATIO_16_9) {
mActivity.previewView.width * 16 / 9
} else {
mActivity.previewView.width * 4 / 3
Expand Down
64 changes: 51 additions & 13 deletions app/src/main/java/app/grapheneos/camera/ui/SettingsDialog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package app.grapheneos.camera.ui

import android.animation.ArgbEvaluator
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.app.Dialog
import android.graphics.Color
import android.hardware.camera2.CameraCharacteristics
Expand Down Expand Up @@ -31,11 +32,15 @@ import androidx.annotation.StringRes
import androidx.appcompat.widget.SwitchCompat
import androidx.camera.camera2.interop.Camera2CameraInfo
import androidx.camera.core.AspectRatio
import androidx.camera.core.Camera
import androidx.camera.core.CameraSelector
import androidx.camera.core.DynamicRange
import androidx.camera.core.ImageCapture
import androidx.camera.core.Preview
import androidx.camera.video.Quality
import androidx.camera.video.QualitySelector
import androidx.camera.video.Recorder
import androidx.camera.video.VideoCapture
import app.grapheneos.camera.CamConfig
import app.grapheneos.camera.R
import app.grapheneos.camera.databinding.SettingsBinding
Expand Down Expand Up @@ -180,14 +185,7 @@ class SettingsDialog(val mActivity: MainActivity) :

aRToggle = binding.aspectRatioToggle
aRToggle.setOnClickListener {
if (camConfig.isVideoMode) {
aRToggle.isChecked = true
mActivity.showMessage(
getString(R.string.four_by_three_unsupported_in_video)
)
} else {
camConfig.toggleAspectRatio()
}
camConfig.toggleAspectRatio()
}

torchToggle = binding.torchToggleOption
Expand Down Expand Up @@ -344,6 +342,49 @@ class SettingsDialog(val mActivity: MainActivity) :
)
}

@SuppressLint("RestrictedApi")
fun isVideoAspectRatioSupported(
camera: Camera,
quality: Quality,
@AspectRatio.Ratio aspectRatio: Int
): Boolean {

val preview = Preview.Builder()
.build()

val video = VideoCapture.Builder(
Recorder.Builder()
.setQualitySelector(QualitySelector.from(quality))
.setAspectRatio(aspectRatio)
.build()
).build()

return camera.isUseCasesCombinationSupported(preview, video)
}

private fun updateAspectRatioToggle() {

aRToggle.isChecked = camConfig.getCurrentModeAspectRatio() == AspectRatio.RATIO_16_9
if (!camConfig.isVideoMode) {
aRToggle.isEnabled = true
return
}
val camera = camConfig.camera ?: return

val currentAspectRatio = camConfig.getCurrentModeAspectRatio()
val newAspectRatio =
if (currentAspectRatio == AspectRatio.RATIO_16_9) {
AspectRatio.RATIO_4_3
} else {
AspectRatio.RATIO_16_9
}

val isDifferentAspectRatioSupported =
isVideoAspectRatioSupported(camera, camConfig.videoQuality, newAspectRatio)

aRToggle.isEnabled = isDifferentAspectRatioSupported
}

private fun resize() {
mScrollViewContent.viewTreeObserver.addOnGlobalLayoutListener(object :
ViewTreeObserver.OnGlobalLayoutListener {
Expand Down Expand Up @@ -396,6 +437,7 @@ class SettingsDialog(val mActivity: MainActivity) :
} else {
View.VISIBLE
}
updateAspectRatioToggle()
}


Expand Down Expand Up @@ -675,11 +717,7 @@ class SettingsDialog(val mActivity: MainActivity) :

updateFlashMode()

if (camConfig.isVideoMode) {
aRToggle.isChecked = true
} else {
aRToggle.isChecked = camConfig.aspectRatio == AspectRatio.RATIO_16_9
}
aRToggle.isChecked = camConfig.getCurrentModeAspectRatio() == AspectRatio.RATIO_16_9

torchToggle.isChecked = camConfig.isTorchOn

Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@
<string name="unable_to_access_output_file">Unable to access output file</string>
<string name="please_wait_for_image_to_get_captured_before_opening">Please wait for the image to get captured before trying to open the gallery.</string>
<string name="please_wait_for_image_to_get_captured_before_sharing">Please wait for the image to get captured before attempting to share via long tap</string>
<string name="aspect_ratio_unsupported_by_selected_resolution">This aspect ratio is not supported by selected resolution (Video quality)</string>

<string name="file_details">File Details</string>
<string name="file_name_generic">File Name: </string>
Expand Down