PIP aspect ratio should match video aspect ratio. fixes #4077
This commit is contained in:
parent
e6d8bee035
commit
88d7ddf124
|
@ -1,5 +1,8 @@
|
||||||
package eu.siacs.conversations.ui;
|
package eu.siacs.conversations.ui;
|
||||||
|
|
||||||
|
import static java.util.Arrays.asList;
|
||||||
|
import static eu.siacs.conversations.utils.PermissionUtils.getFirstDenied;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.PictureInPictureParams;
|
import android.app.PictureInPictureParams;
|
||||||
|
@ -55,6 +58,7 @@ import eu.siacs.conversations.services.AppRTCAudioManager;
|
||||||
import eu.siacs.conversations.services.XmppConnectionService;
|
import eu.siacs.conversations.services.XmppConnectionService;
|
||||||
import eu.siacs.conversations.ui.util.AvatarWorkerTask;
|
import eu.siacs.conversations.ui.util.AvatarWorkerTask;
|
||||||
import eu.siacs.conversations.ui.util.MainThreadExecutor;
|
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.PermissionUtils;
|
||||||
import eu.siacs.conversations.utils.TimeFrameUtils;
|
import eu.siacs.conversations.utils.TimeFrameUtils;
|
||||||
import eu.siacs.conversations.xml.Namespace;
|
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.Media;
|
||||||
import eu.siacs.conversations.xmpp.jingle.RtpEndUserState;
|
import eu.siacs.conversations.xmpp.jingle.RtpEndUserState;
|
||||||
|
|
||||||
import static eu.siacs.conversations.utils.PermissionUtils.getFirstDenied;
|
public class RtpSessionActivity extends XmppActivity implements XmppConnectionService.OnJingleRtpConnectionUpdate, eu.siacs.conversations.ui.widget.SurfaceViewRenderer.OnAspectRatioChanged {
|
||||||
import static java.util.Arrays.asList;
|
|
||||||
|
|
||||||
public class RtpSessionActivity extends XmppActivity implements XmppConnectionService.OnJingleRtpConnectionUpdate {
|
|
||||||
|
|
||||||
public static final String EXTRA_WITH = "with";
|
public static final String EXTRA_WITH = "with";
|
||||||
public static final String EXTRA_SESSION_ID = "session_id";
|
public static final String EXTRA_SESSION_ID = "session_id";
|
||||||
|
@ -446,12 +447,14 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
mHandler.postDelayed(mTickExecutor, CALL_DURATION_UPDATE_INTERVAL);
|
mHandler.postDelayed(mTickExecutor, CALL_DURATION_UPDATE_INTERVAL);
|
||||||
|
this.binding.remoteVideo.setOnAspectRatioChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStop() {
|
public void onStop() {
|
||||||
mHandler.removeCallbacks(mTickExecutor);
|
mHandler.removeCallbacks(mTickExecutor);
|
||||||
binding.remoteVideo.release();
|
binding.remoteVideo.release();
|
||||||
|
binding.remoteVideo.setOnAspectRatioChanged(null);
|
||||||
binding.localVideo.release();
|
binding.localVideo.release();
|
||||||
final WeakReference<JingleRtpConnection> weakReference = this.rtpConnectionReference;
|
final WeakReference<JingleRtpConnection> weakReference = this.rtpConnectionReference;
|
||||||
final JingleRtpConnection jingleRtpConnection = weakReference == null ? null : weakReference.get();
|
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)
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||||
private void startPictureInPicture() {
|
private void startPictureInPicture() {
|
||||||
try {
|
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(
|
enterPictureInPictureMode(
|
||||||
new PictureInPictureParams.Builder()
|
new PictureInPictureParams.Builder()
|
||||||
.setAspectRatio(new Rational(10, 16))
|
.setAspectRatio(clippedRational)
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
} catch (final IllegalStateException e) {
|
} 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() {
|
private boolean deviceSupportsPictureInPicture() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
return getPackageManager().hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE);
|
return getPackageManager().hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE);
|
||||||
|
|
26
src/main/java/eu/siacs/conversations/ui/util/Rationals.java
Normal file
26
src/main/java/eu/siacs/conversations/ui/util/Rationals.java
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -98,13 +98,13 @@
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:visibility="gone">
|
android:visibility="gone">
|
||||||
|
|
||||||
<org.webrtc.SurfaceViewRenderer
|
<eu.siacs.conversations.ui.widget.SurfaceViewRenderer
|
||||||
android:id="@+id/remote_video"
|
android:id="@+id/remote_video"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<org.webrtc.SurfaceViewRenderer
|
<eu.siacs.conversations.ui.widget.SurfaceViewRenderer
|
||||||
android:id="@+id/local_video"
|
android:id="@+id/local_video"
|
||||||
android:layout_width="@dimen/local_video_preview_width"
|
android:layout_width="@dimen/local_video_preview_width"
|
||||||
android:layout_height="@dimen/local_video_preview_height"
|
android:layout_height="@dimen/local_video_preview_height"
|
||||||
|
|
Loading…
Reference in a new issue