From e0982d3961d4a07ab1a9368b389b4b7240795db9 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Tue, 19 Apr 2016 18:40:45 -0400 Subject: [PATCH] Fix video stream aspect ratio scaling in multi-window mode on Android N --- app/src/main/java/com/limelight/Game.java | 34 ++---------- .../java/com/limelight/ui/StreamView.java | 55 +++++++++++++++++++ app/src/main/res/layout/activity_game.xml | 2 +- 3 files changed, 60 insertions(+), 31 deletions(-) create mode 100644 app/src/main/java/com/limelight/ui/StreamView.java diff --git a/app/src/main/java/com/limelight/Game.java b/app/src/main/java/com/limelight/Game.java index 71e61e46..0c7dee92 100644 --- a/app/src/main/java/com/limelight/Game.java +++ b/app/src/main/java/com/limelight/Game.java @@ -22,6 +22,7 @@ import com.limelight.nvstream.input.KeyboardPacket; import com.limelight.nvstream.input.MouseButtonPacket; import com.limelight.preferences.PreferenceConfiguration; import com.limelight.ui.GameGestures; +import com.limelight.ui.StreamView; import com.limelight.utils.Dialog; import com.limelight.utils.SpinnerDialog; @@ -91,7 +92,6 @@ public class Game extends Activity implements SurfaceHolder.Callback, private boolean displayedFailureDialog = false; private boolean connecting = false; private boolean connected = false; - private boolean deferredSurfaceResize = false; private EvdevHandler evdevHandler; private int modifierFlags = 0; @@ -179,7 +179,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, display.getSize(screenSize); // Listen for events on the game surface - SurfaceView sv = (SurfaceView) findViewById(R.id.surfaceView); + StreamView sv = (StreamView) findViewById(R.id.surfaceView); sv.setOnGenericMotionListener(this); sv.setOnTouchListener(this); @@ -272,7 +272,8 @@ public class Game extends Activity implements SurfaceHolder.Callback, sh.setFixedSize(prefConfig.width, prefConfig.height); } else { - deferredSurfaceResize = true; + // Set the surface to scale based on the aspect ratio of the stream + sv.setDesiredAspectRatio((double)prefConfig.width / (double)prefConfig.height); } // Initialize touch contexts @@ -306,26 +307,6 @@ public class Game extends Activity implements SurfaceHolder.Callback, sh.addCallback(this); } - private void resizeSurfaceWithAspectRatio(SurfaceView sv, double vidWidth, double vidHeight) - { - // Get the visible width of the activity - double visibleWidth = getWindow().getDecorView().getWidth(); - - ViewGroup.LayoutParams lp = sv.getLayoutParams(); - - // Calculate the new size of the SurfaceView - lp.width = (int) visibleWidth; - lp.height = (int) ((vidHeight / vidWidth) * visibleWidth); - - // Apply the size change - sv.setLayoutParams(lp); - - // refresh virtual controller layout - if (virtualController != null) { - virtualController.refreshLayout(); - } - } - private void checkDataConnection() { ConnectivityManager mgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); @@ -932,13 +913,6 @@ public class Game extends Activity implements SurfaceHolder.Callback, if (!connected && !connecting) { connecting = true; - // Resize the surface to match the aspect ratio of the video - // This must be done after the surface is created. - if (deferredSurfaceResize) { - resizeSurfaceWithAspectRatio((SurfaceView) findViewById(R.id.surfaceView), - prefConfig.width, prefConfig.height); - } - conn.start(PlatformBinding.getDeviceName(), holder, drFlags, PlatformBinding.getAudioRenderer(), decoderRenderer); } diff --git a/app/src/main/java/com/limelight/ui/StreamView.java b/app/src/main/java/com/limelight/ui/StreamView.java new file mode 100644 index 00000000..c6672ead --- /dev/null +++ b/app/src/main/java/com/limelight/ui/StreamView.java @@ -0,0 +1,55 @@ +package com.limelight.ui; + +import android.annotation.TargetApi; +import android.content.Context; +import android.util.AttributeSet; +import android.view.SurfaceView; + +public class StreamView extends SurfaceView { + private double desiredAspectRatio; + + public void setDesiredAspectRatio(double aspectRatio) { + this.desiredAspectRatio = aspectRatio; + } + + public StreamView(Context context) { + super(context); + } + + public StreamView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public StreamView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @TargetApi(21) + public StreamView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // If no fixed aspect ratio has been provided, simply use the default onMeasure() behavior + if (desiredAspectRatio == 0) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + return; + } + + // Based on code from: https://www.buzzingandroid.com/2012/11/easy-measuring-of-custom-views-with-specific-aspect-ratio/ + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + + int measuredHeight, measuredWidth; + if (widthSize > heightSize * desiredAspectRatio) { + measuredHeight = heightSize; + measuredWidth = (int)(measuredHeight * desiredAspectRatio); + } else { + measuredWidth = widthSize; + measuredHeight = (int)(measuredWidth / desiredAspectRatio); + } + + setMeasuredDimension(measuredWidth, measuredHeight); + } +} diff --git a/app/src/main/res/layout/activity_game.xml b/app/src/main/res/layout/activity_game.xml index 42617a76..5fbf87c4 100644 --- a/app/src/main/res/layout/activity_game.xml +++ b/app/src/main/res/layout/activity_game.xml @@ -4,7 +4,7 @@ android:layout_height="match_parent" tools:context=".Game" > -