From 88d7ddf1248909f2b2dc940fee7f48342d650ae6 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 24 Aug 2021 14:40:12 +0200 Subject: [PATCH] PIP aspect ratio should match video aspect ratio. fixes #4077 --- .../conversations/ui/RtpSessionActivity.java | 27 +++++++++-- .../conversations/ui/util/Rationals.java | 26 ++++++++++ .../ui/widget/SurfaceViewRenderer.java | 48 +++++++++++++++++++ src/main/res/layout/activity_rtp_session.xml | 4 +- 4 files changed, 98 insertions(+), 7 deletions(-) create mode 100644 src/main/java/eu/siacs/conversations/ui/util/Rationals.java create mode 100644 src/main/java/eu/siacs/conversations/ui/widget/SurfaceViewRenderer.java diff --git a/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java b/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java index ad016a3b3..96aa00db0 100644 --- a/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java @@ -1,5 +1,8 @@ package eu.siacs.conversations.ui; +import static java.util.Arrays.asList; +import static eu.siacs.conversations.utils.PermissionUtils.getFirstDenied; + import android.Manifest; import android.annotation.SuppressLint; import android.app.PictureInPictureParams; @@ -55,6 +58,7 @@ import eu.siacs.conversations.services.AppRTCAudioManager; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.ui.util.AvatarWorkerTask; import eu.siacs.conversations.ui.util.MainThreadExecutor; +import eu.siacs.conversations.ui.util.Rationals; import eu.siacs.conversations.utils.PermissionUtils; import eu.siacs.conversations.utils.TimeFrameUtils; import eu.siacs.conversations.xml.Namespace; @@ -65,10 +69,7 @@ import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection; import eu.siacs.conversations.xmpp.jingle.Media; import eu.siacs.conversations.xmpp.jingle.RtpEndUserState; -import static eu.siacs.conversations.utils.PermissionUtils.getFirstDenied; -import static java.util.Arrays.asList; - -public class RtpSessionActivity extends XmppActivity implements XmppConnectionService.OnJingleRtpConnectionUpdate { +public class RtpSessionActivity extends XmppActivity implements XmppConnectionService.OnJingleRtpConnectionUpdate, eu.siacs.conversations.ui.widget.SurfaceViewRenderer.OnAspectRatioChanged { public static final String EXTRA_WITH = "with"; public static final String EXTRA_SESSION_ID = "session_id"; @@ -446,12 +447,14 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe public void onStart() { super.onStart(); mHandler.postDelayed(mTickExecutor, CALL_DURATION_UPDATE_INTERVAL); + this.binding.remoteVideo.setOnAspectRatioChanged(this); } @Override public void onStop() { mHandler.removeCallbacks(mTickExecutor); binding.remoteVideo.release(); + binding.remoteVideo.setOnAspectRatioChanged(null); binding.localVideo.release(); final WeakReference weakReference = this.rtpConnectionReference; final JingleRtpConnection jingleRtpConnection = weakReference == null ? null : weakReference.get(); @@ -515,9 +518,12 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe @RequiresApi(api = Build.VERSION_CODES.O) private void startPictureInPicture() { try { + final Rational rational = this.binding.remoteVideo.getAspectRatio(); + final Rational clippedRational = Rationals.clip(rational); + Log.d(Config.LOGTAG, "suggested rational " + rational + ". clipped to " + clippedRational); enterPictureInPictureMode( new PictureInPictureParams.Builder() - .setAspectRatio(new Rational(10, 16)) + .setAspectRatio(clippedRational) .build() ); } catch (final IllegalStateException e) { @@ -526,6 +532,17 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe } } + @Override + public void onAspectRatioChanged(final Rational rational) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && isPictureInPicture()) { + final Rational clippedRational = Rationals.clip(rational); + Log.d(Config.LOGTAG, "suggested rational after aspect ratio change " + rational + ". clipped to " + clippedRational); + setPictureInPictureParams(new PictureInPictureParams.Builder() + .setAspectRatio(clippedRational) + .build()); + } + } + private boolean deviceSupportsPictureInPicture() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { return getPackageManager().hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE); diff --git a/src/main/java/eu/siacs/conversations/ui/util/Rationals.java b/src/main/java/eu/siacs/conversations/ui/util/Rationals.java new file mode 100644 index 000000000..31155cd6e --- /dev/null +++ b/src/main/java/eu/siacs/conversations/ui/util/Rationals.java @@ -0,0 +1,26 @@ +package eu.siacs.conversations.ui.util; + +import android.util.Rational; + +public final class Rationals { + + //between 2.39:1 and 1:2.39 (inclusive). + private static final Rational MIN = new Rational(100,239); + private static final Rational MAX = new Rational(239,100); + + private Rationals() { + + } + + + public static Rational clip(final Rational input) { + if (input.compareTo(MIN) < 0) { + return MIN; + } + if (input.compareTo(MAX) > 0) { + return MAX; + } + return input; + } + +} diff --git a/src/main/java/eu/siacs/conversations/ui/widget/SurfaceViewRenderer.java b/src/main/java/eu/siacs/conversations/ui/widget/SurfaceViewRenderer.java new file mode 100644 index 000000000..06f604076 --- /dev/null +++ b/src/main/java/eu/siacs/conversations/ui/widget/SurfaceViewRenderer.java @@ -0,0 +1,48 @@ +package eu.siacs.conversations.ui.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.util.Log; +import android.util.Rational; + +import eu.siacs.conversations.Config; + +public class SurfaceViewRenderer extends org.webrtc.SurfaceViewRenderer { + + private Rational aspectRatio = new Rational(1,1); + + private OnAspectRatioChanged onAspectRatioChanged; + + public SurfaceViewRenderer(Context context) { + super(context); + } + + public SurfaceViewRenderer(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public void onFrameResolutionChanged(int videoWidth, int videoHeight, int rotation) { + super.onFrameResolutionChanged(videoWidth, videoHeight, rotation); + final int rotatedWidth = rotation != 0 && rotation != 180 ? videoHeight : videoWidth; + final int rotatedHeight = rotation != 0 && rotation != 180 ? videoWidth : videoHeight; + final Rational currentRational = this.aspectRatio; + this.aspectRatio = new Rational(rotatedWidth, rotatedHeight); + Log.d(Config.LOGTAG,"onFrameResolutionChanged("+rotatedWidth+","+rotatedHeight+","+aspectRatio+")"); + if (currentRational.equals(this.aspectRatio) || onAspectRatioChanged == null) { + return; + } + onAspectRatioChanged.onAspectRatioChanged(this.aspectRatio); + } + + public void setOnAspectRatioChanged(final OnAspectRatioChanged onAspectRatioChanged) { + this.onAspectRatioChanged = onAspectRatioChanged; + } + + public Rational getAspectRatio() { + return this.aspectRatio; + } + + public interface OnAspectRatioChanged { + void onAspectRatioChanged(final Rational rational); + } +} diff --git a/src/main/res/layout/activity_rtp_session.xml b/src/main/res/layout/activity_rtp_session.xml index 26fa4d496..0bdca4776 100644 --- a/src/main/res/layout/activity_rtp_session.xml +++ b/src/main/res/layout/activity_rtp_session.xml @@ -98,13 +98,13 @@ android:gravity="center" android:visibility="gone"> - -