Index: talk/app/webrtc/java/android/org/webrtc/SurfaceViewRenderer.java |
diff --git a/talk/app/webrtc/java/android/org/webrtc/SurfaceViewRenderer.java b/talk/app/webrtc/java/android/org/webrtc/SurfaceViewRenderer.java |
index 170827efc11acd34726b9fe12ca688d6aa6162a1..86c1481eec7579a8a548c70b071fa214d33442d1 100644 |
--- a/talk/app/webrtc/java/android/org/webrtc/SurfaceViewRenderer.java |
+++ b/talk/app/webrtc/java/android/org/webrtc/SurfaceViewRenderer.java |
@@ -83,14 +83,13 @@ public class SurfaceViewRenderer extends SurfaceView |
// traversal of the View tree, followed by an onLayout() pass that is also top-down. During the |
// onLayout() pass, each parent is responsible for positioning its children using the sizes |
// computed in the measure pass. |
- // |desiredLayoutsize| is the layout size we have requested in onMeasure() and are waiting for to |
- // take effect. |
+ // |desiredLayoutsize|/|desiredSurfaceSize| is the layout/surface size we have requested in |
+ // onMeasure() and are waiting for to take effect. |
private Point desiredLayoutSize = new Point(); |
+ private final Point desiredSurfaceSize = new Point(); |
// |layoutSize|/|surfaceSize| is the actual current layout/surface size. They are updated in |
// onLayout() and surfaceChanged() respectively. |
private final Point layoutSize = new Point(); |
- // TODO(magjed): Enable hardware scaler with SurfaceHolder.setFixedSize(). This will decouple |
- // layout and surface size. |
private final Point surfaceSize = new Point(); |
// |isSurfaceCreated| keeps track of the current status in surfaceCreated()/surfaceDestroyed(). |
private boolean isSurfaceCreated; |
@@ -324,7 +323,23 @@ public class SurfaceViewRenderer extends SurfaceView |
return; |
} |
desiredLayoutSize = getDesiredLayoutSize(widthSpec, heightSpec); |
- if (desiredLayoutSize.x != getMeasuredWidth() || desiredLayoutSize.y != getMeasuredHeight()) { |
+ // Calculate at what scale we are rendering the frame. |
+ final int rotatedFrameWidth = (frameRotation % 180 == 0) ? frameWidth : frameHeight; |
+ final int rotatedFrameHeight = (frameRotation % 180 == 0) ? frameHeight : frameWidth; |
+ final float displayScale = Math.max((float) desiredLayoutSize.x / rotatedFrameWidth, |
+ (float) desiredLayoutSize.y / rotatedFrameHeight); |
+ if (displayScale > 1) { |
+ // Upscaling - decrease surface size and let the HW scaler take care of the upscaling |
+ // instead of the GPU. |
+ desiredSurfaceSize.x = Math.round(desiredLayoutSize.x / displayScale); |
+ desiredSurfaceSize.y = Math.round(desiredLayoutSize.y / displayScale); |
+ } else { |
+ // Downscaling - render at layout resolution. |
+ desiredSurfaceSize.x = desiredLayoutSize.x; |
+ desiredSurfaceSize.y = desiredLayoutSize.y; |
+ } |
+ if (desiredLayoutSize.x != getMeasuredWidth() || desiredLayoutSize.y != getMeasuredHeight() |
+ || !desiredSurfaceSize.equals(surfaceSize)) { |
// Clear the surface asap before the layout change to avoid stretched video and other |
// render artifacs. Don't wait for it to finish because the IO thread should never be |
// blocked, so it's a best-effort attempt. |
@@ -334,6 +349,7 @@ public class SurfaceViewRenderer extends SurfaceView |
} |
} |
} |
+ getHolder().setFixedSize(desiredSurfaceSize.x, desiredSurfaceSize.y); |
setMeasuredDimension(desiredLayoutSize.x, desiredLayoutSize.y); |
} |
} |
@@ -423,7 +439,7 @@ public class SurfaceViewRenderer extends SurfaceView |
} |
synchronized (layoutLock) { |
// Return false while we are in the middle of a layout change. |
- return layoutSize.equals(desiredLayoutSize) && surfaceSize.equals(layoutSize); |
+ return layoutSize.equals(desiredLayoutSize) && surfaceSize.equals(desiredSurfaceSize); |
} |
} |