Merge pull request #4838 from nextcloud/feature/2052/moreFovByRatioSwitch

switch video capture between 4:3 and 16:9 ratio for portrait/landscape
This commit is contained in:
Sowjanya Kota 2025-04-11 16:43:29 +02:00 committed by GitHub
commit a27f95caeb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 84 additions and 41 deletions

View File

@ -38,6 +38,7 @@ import android.text.TextUtils
import android.text.format.DateUtils import android.text.format.DateUtils
import android.util.Log import android.util.Log
import android.view.MotionEvent import android.view.MotionEvent
import android.view.OrientationEventListener
import android.view.View import android.view.View
import android.view.View.OnTouchListener import android.view.View.OnTouchListener
import android.view.ViewGroup import android.view.ViewGroup
@ -51,7 +52,6 @@ import androidx.appcompat.app.AlertDialog
import androidx.core.graphics.drawable.DrawableCompat import androidx.core.graphics.drawable.DrawableCompat
import androidx.core.graphics.toColorInt import androidx.core.graphics.toColorInt
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.core.view.isVisible
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import autodagger.AutoInjector import autodagger.AutoInjector
import com.bluelinelabs.logansquare.LoganSquare import com.bluelinelabs.logansquare.LoganSquare
@ -1032,7 +1032,7 @@ class CallActivity : CallBaseActivity() {
private fun prepareCall() { private fun prepareCall() {
basicInitialization() basicInitialization()
initViews() initViews()
updateSelfVideoViewPosition() updateSelfVideoViewPosition(true)
checkRecordingConsentAndInitiateCall() checkRecordingConsentAndInitiateCall()
if (permissionUtil!!.isMicrophonePermissionGranted()) { if (permissionUtil!!.isMicrophonePermissionGranted()) {
@ -1326,7 +1326,10 @@ class CallActivity : CallBaseActivity() {
if (video) { if (video) {
if (enable) { if (enable) {
binding!!.cameraButton.alpha = OPACITY_ENABLED binding!!.cameraButton.alpha = OPACITY_ENABLED
startVideoCapture() startVideoCapture(
isPortrait = true
)
setupOrientationListener(context)
} else { } else {
binding!!.cameraButton.alpha = OPACITY_DISABLED binding!!.cameraButton.alpha = OPACITY_DISABLED
if (videoCapturer != null) { if (videoCapturer != null) {
@ -2158,10 +2161,44 @@ class CallActivity : CallBaseActivity() {
}) })
} }
private fun startVideoCapture() { private fun startVideoCapture(isPortrait: Boolean) {
if (videoCapturer != null) { val (width, height) = if (isPortrait) {
videoCapturer!!.startCapture(WIDTH, HEIGHT, FRAME_RATE) WIDTH_4_TO_3_RATIO to HEIGHT_4_TO_3_RATIO
} else {
WIDTH_16_TO_9_RATIO to HEIGHT_16_TO_9_RATIO
} }
videoCapturer?.let {
it.stopCapture()
it.startCapture(width, height, FRAME_RATE)
}
updateSelfVideoViewPosition(isPortrait)
}
private fun setupOrientationListener(context: Context) {
var lastAspectRatio = ""
val orientationEventListener = object : OrientationEventListener(context) {
override fun onOrientationChanged(orientation: Int) {
when (orientation) {
in ANGLE_0..ANGLE_PORTRAIT_RIGHT_THRESHOLD,
in ANGLE_PORTRAIT_LEFT_THRESHOLD..ANGLE_FULL -> {
if (lastAspectRatio != RATIO_4_TO_3) {
lastAspectRatio = RATIO_4_TO_3
startVideoCapture(true)
}
}
in ANGLE_LANDSCAPE_RIGHT_THRESHOLD_MIN..ANGLE_LANDSCAPE_RIGHT_THRESHOLD_MAX,
in ANGLE_LANDSCAPE_LEFT_THRESHOLD_MIN..ANGLE_LANDSCAPE_LEFT_THRESHOLD_MAX -> {
if (lastAspectRatio != RATIO_16_TO_9) {
lastAspectRatio = RATIO_16_TO_9
startVideoCapture(false)
}
}
}
}
}
orientationEventListener.enable()
} }
@Suppress("Detekt.ComplexMethod") @Suppress("Detekt.ComplexMethod")
@ -2515,7 +2552,6 @@ class CallActivity : CallBaseActivity() {
fun onMessageEvent(configurationChangeEvent: ConfigurationChangeEvent?) { fun onMessageEvent(configurationChangeEvent: ConfigurationChangeEvent?) {
powerManagerUtils!!.setOrientation(Objects.requireNonNull(resources).configuration.orientation) powerManagerUtils!!.setOrientation(Objects.requireNonNull(resources).configuration.orientation)
initGridAdapter() initGridAdapter()
updateSelfVideoViewPosition()
} }
private fun updateSelfVideoViewIceConnectionState(iceConnectionState: IceConnectionState) { private fun updateSelfVideoViewIceConnectionState(iceConnectionState: IceConnectionState) {
@ -2532,40 +2568,26 @@ class CallActivity : CallBaseActivity() {
} }
} }
private fun updateSelfVideoViewPosition() { private fun updateSelfVideoViewPosition(isPortrait: Boolean) {
Log.d(TAG, "updateSelfVideoViewPosition") Log.d(TAG, "updateSelfVideoViewPosition")
if (!isInPipMode) { if (!isInPipMode) {
val layoutParams = binding!!.selfVideoRenderer.layoutParams as FrameLayout.LayoutParams val layoutParams = binding!!.selfVideoRenderer.layoutParams as FrameLayout.LayoutParams
val displayMetrics = applicationContext.resources.displayMetrics if (!isPortrait) {
val screenWidthPx = displayMetrics.widthPixels layoutParams.height =
val screenWidthDp = DisplayUtils.convertPixelToDp(screenWidthPx.toFloat(), applicationContext).toInt() DisplayUtils.convertDpToPixel(SELFVIDEO_HEIGHT_16_TO_9_RATIO.toFloat(), applicationContext).toInt()
var newXafterRotate = 0f layoutParams.width =
val newYafterRotate: Float = if (binding!!.callInfosLinearLayout.isVisible) { DisplayUtils.convertDpToPixel(SELFVIDEO_WIDTH_16_TO_9_RATIO.toFloat(), applicationContext).toInt()
Y_POS_CALL_INFO binding!!.selfVideoViewWrapper.y = SELFVIDEO_POSITION_X_LANDSCAPE
binding!!.selfVideoViewWrapper.x = SELFVIDEO_POSITION_Y_LANDSCAPE
} else { } else {
Y_POS_NO_CALL_INFO layoutParams.height =
} DisplayUtils.convertDpToPixel(SELFVIDEO_HEIGHT_4_TO_3_RATIO.toFloat(), applicationContext).toInt()
if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) { layoutParams.width =
layoutParams.height = resources.getDimension(R.dimen.call_self_video_short_side_length).toInt() DisplayUtils.convertDpToPixel(SELFVIDEO_WIDTH_4_TO_3_RATIO.toFloat(), applicationContext).toInt()
layoutParams.width = resources.getDimension(R.dimen.call_self_video_long_side_length).toInt() binding!!.selfVideoViewWrapper.y = SELFVIDEO_POSITION_X_PORTRAIT
newXafterRotate = binding!!.selfVideoViewWrapper.x = SELFVIDEO_POSITION_Y_PORTRAIT
(
screenWidthDp - resources.getDimension(R.dimen.call_self_video_short_side_length) *
BY_80_PERCENT
).toFloat()
} else if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
layoutParams.height = resources.getDimension(R.dimen.call_self_video_long_side_length).toInt()
layoutParams.width = resources.getDimension(R.dimen.call_self_video_short_side_length).toInt()
newXafterRotate =
(
screenWidthDp - resources.getDimension(R.dimen.call_self_video_short_side_length) *
BY_50_PERCENT
).toFloat()
} }
binding!!.selfVideoRenderer.layoutParams = layoutParams binding!!.selfVideoRenderer.layoutParams = layoutParams
val newXafterRotatePx = DisplayUtils.convertDpToPixel(newXafterRotate, applicationContext).toInt()
binding!!.selfVideoViewWrapper.y = newYafterRotate
binding!!.selfVideoViewWrapper.x = newXafterRotatePx.toFloat()
} }
} }
@ -3276,8 +3298,31 @@ class CallActivity : CallBaseActivity() {
private const val MICROPHONE_VALUE_SLEEP: Long = 1000 private const val MICROPHONE_VALUE_SLEEP: Long = 1000
private const val FRAME_RATE: Int = 30 private const val FRAME_RATE: Int = 30
private const val WIDTH: Int = 1280 private const val WIDTH_16_TO_9_RATIO: Int = 1280
private const val HEIGHT: Int = 720 private const val HEIGHT_16_TO_9_RATIO: Int = 720
private const val WIDTH_4_TO_3_RATIO: Int = 640
private const val HEIGHT_4_TO_3_RATIO: Int = 480
private const val RATIO_4_TO_3 = "RATIO_4_TO_3"
private const val RATIO_16_TO_9 = "RATIO_16_TO_9"
private const val ANGLE_0 = 0
private const val ANGLE_FULL = 360
private const val ANGLE_PORTRAIT_RIGHT_THRESHOLD = 30
private const val ANGLE_PORTRAIT_LEFT_THRESHOLD = 330
private const val ANGLE_LANDSCAPE_RIGHT_THRESHOLD_MIN = 80
private const val ANGLE_LANDSCAPE_RIGHT_THRESHOLD_MAX = 100
private const val ANGLE_LANDSCAPE_LEFT_THRESHOLD_MIN = 260
private const val ANGLE_LANDSCAPE_LEFT_THRESHOLD_MAX = 280
private const val SELFVIDEO_WIDTH_4_TO_3_RATIO = 80
private const val SELFVIDEO_HEIGHT_4_TO_3_RATIO = 104
private const val SELFVIDEO_WIDTH_16_TO_9_RATIO = 136
private const val SELFVIDEO_HEIGHT_16_TO_9_RATIO = 80
private const val SELFVIDEO_POSITION_X_LANDSCAPE = 100F
private const val SELFVIDEO_POSITION_Y_LANDSCAPE = 100F
private const val SELFVIDEO_POSITION_X_PORTRAIT = 300F
private const val SELFVIDEO_POSITION_Y_PORTRAIT = 100F
private const val FIVE_SECONDS: Long = 5000 private const val FIVE_SECONDS: Long = 5000
private const val CALLING_TIMEOUT: Long = 45000 private const val CALLING_TIMEOUT: Long = 45000

View File

@ -52,8 +52,8 @@
<org.webrtc.SurfaceViewRenderer <org.webrtc.SurfaceViewRenderer
android:id="@+id/selfVideoRenderer" android:id="@+id/selfVideoRenderer"
android:layout_width="@dimen/call_self_video_short_side_length" android:layout_width="80dp"
android:layout_height="@dimen/call_self_video_long_side_length" android:layout_height="104dp"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_margin="16dp" android:layout_margin="16dp"
android:clickable="false" android:clickable="false"

View File

@ -54,8 +54,6 @@
<dimen name="dialog_padding">24dp</dimen> <dimen name="dialog_padding">24dp</dimen>
<dimen name="dialog_padding_top_bottom">18dp</dimen> <dimen name="dialog_padding_top_bottom">18dp</dimen>
<dimen name="call_self_video_long_side_length">150dp</dimen>
<dimen name="call_self_video_short_side_length">80dp</dimen>
<dimen name="call_grid_item_min_height">180dp</dimen> <dimen name="call_grid_item_min_height">180dp</dimen>
<dimen name="call_controls_height">110dp</dimen> <dimen name="call_controls_height">110dp</dimen>
<dimen name="call_participant_progress_bar_size">48dp</dimen> <dimen name="call_participant_progress_bar_size">48dp</dimen>