diff options
author | Magnus Jedvert <magjed@webrtc.org> | 2015-08-20 14:03:07 +0200 |
---|---|---|
committer | Magnus Jedvert <magjed@webrtc.org> | 2015-08-20 12:03:17 +0000 |
commit | ff020c01ca8ad72e513700315ebb6ff16afffd22 (patch) | |
tree | bc3c68d3784f02c3b1a4d06cfb0dc8b360388aeb | |
parent | 41b3a384f446985bdd7e2b9a8830aa90264fef29 (diff) | |
download | webrtc-ff020c01ca8ad72e513700315ebb6ff16afffd22.tar.gz |
Android: Move common functions from VideoRendererGui to new RendererCommon file
This is primarily done to prepare for a new renderer implementation.
BUG=webrtc:4742
R=glaznev@webrtc.org
Review URL: https://codereview.webrtc.org/1298673002 .
Cr-Commit-Position: refs/heads/master@{#9742}
5 files changed, 156 insertions, 95 deletions
diff --git a/talk/app/webrtc/java/android/org/webrtc/RendererCommon.java b/talk/app/webrtc/java/android/org/webrtc/RendererCommon.java new file mode 100644 index 0000000000..f54d5edca6 --- /dev/null +++ b/talk/app/webrtc/java/android/org/webrtc/RendererCommon.java @@ -0,0 +1,139 @@ +/* + * libjingle + * Copyright 2015 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.webrtc; + +import android.graphics.Point; +import android.opengl.Matrix; + +/** + * Static helper functions for renderer implementations. + */ +public class RendererCommon { + /** Interface for reporting rendering events. */ + public static interface RendererEvents { + /** + * Callback fired once first frame is rendered. + */ + public void onFirstFrameRendered(); + + /** + * Callback fired when rendered frame resolution or rotation has changed. + */ + public void onFrameResolutionChanged(int videoWidth, int videoHeight, int rotation); + } + + // Types of video scaling: + // SCALE_ASPECT_FIT - video frame is scaled to fit the size of the view by + // maintaining the aspect ratio (black borders may be displayed). + // SCALE_ASPECT_FILL - video frame is scaled to fill the size of the view by + // maintaining the aspect ratio. Some portion of the video frame may be + // clipped. + // SCALE_ASPECT_BALANCED - Compromise between FIT and FILL. Video frame will fill as much as + // possible of the view while maintaining aspect ratio, under the constraint that at least + // |BALANCED_VISIBLE_FRACTION| of the frame content will be shown. + public static enum ScalingType { SCALE_ASPECT_FIT, SCALE_ASPECT_FILL, SCALE_ASPECT_BALANCED } + // The minimum fraction of the frame content that will be shown for |SCALE_ASPECT_BALANCED|. + // This limits excessive cropping when adjusting display size. + private static float BALANCED_VISIBLE_FRACTION = 0.56f; + + /** + * Calculates a texture transformation matrix based on rotation, mirror, and video vs display + * aspect ratio. + */ + public static void getTextureMatrix(float[] outputTextureMatrix, float rotationDegree, + boolean mirror, float videoAspectRatio, float displayAspectRatio) { + // The matrix stack is using post-multiplication, which means that matrix operations: + // A; B; C; will end up as A * B * C. When you apply this to a vertex, it will result in: + // v' = A * B * C * v, i.e. the last matrix operation is the first thing that affects the + // vertex. This is the opposite of what you might expect. + Matrix.setIdentityM(outputTextureMatrix, 0); + // Move coordinates back to [0,1]x[0,1]. + Matrix.translateM(outputTextureMatrix, 0, 0.5f, 0.5f, 0.0f); + // Rotate frame clockwise in the XY-plane (around the Z-axis). + Matrix.rotateM(outputTextureMatrix, 0, -rotationDegree, 0, 0, 1); + // Scale one dimension until video and display size have same aspect ratio. + if (displayAspectRatio > videoAspectRatio) { + Matrix.scaleM(outputTextureMatrix, 0, 1, videoAspectRatio / displayAspectRatio, 1); + } else { + Matrix.scaleM(outputTextureMatrix, 0, displayAspectRatio / videoAspectRatio, 1, 1); + } + // TODO(magjed): We currently ignore the texture transform matrix from the SurfaceTexture. + // It contains a vertical flip that is hardcoded here instead. + Matrix.scaleM(outputTextureMatrix, 0, 1, -1, 1); + // Apply optional horizontal flip. + if (mirror) { + Matrix.scaleM(outputTextureMatrix, 0, -1, 1, 1); + } + // Center coordinates around origin. + Matrix.translateM(outputTextureMatrix, 0, -0.5f, -0.5f, 0.0f); + } + + /** + * Calculate display size based on scaling type, video aspect ratio, and maximum display size. + */ + public static Point getDisplaySize(ScalingType scalingType, float videoAspectRatio, + int maxDisplayWidth, int maxDisplayHeight) { + return getDisplaySize(convertScalingTypeToVisibleFraction(scalingType), videoAspectRatio, + maxDisplayWidth, maxDisplayHeight); + } + + /** + * Each scaling type has a one-to-one correspondence to a numeric minimum fraction of the video + * that must remain visible. + */ + private static float convertScalingTypeToVisibleFraction(ScalingType scalingType) { + switch (scalingType) { + case SCALE_ASPECT_FIT: + return 1.0f; + case SCALE_ASPECT_FILL: + return 0.0f; + case SCALE_ASPECT_BALANCED: + return BALANCED_VISIBLE_FRACTION; + default: + throw new IllegalArgumentException(); + } + } + + /** + * Calculate display size based on minimum fraction of the video that must remain visible, + * video aspect ratio, and maximum display size. + */ + private static Point getDisplaySize(float minVisibleFraction, float videoAspectRatio, + int maxDisplayWidth, int maxDisplayHeight) { + // If there is no constraint on the amount of cropping, fill the allowed display area. + if (minVisibleFraction == 0 || videoAspectRatio == 0) { + return new Point(maxDisplayWidth, maxDisplayHeight); + } + // Each dimension is constrained on max display size and how much we are allowed to crop. + final int width = Math.min(maxDisplayWidth, + (int) (maxDisplayHeight / minVisibleFraction * videoAspectRatio)); + final int height = Math.min(maxDisplayHeight, + (int) (maxDisplayWidth / minVisibleFraction / videoAspectRatio)); + return new Point(width, height); + } +} diff --git a/talk/app/webrtc/java/android/org/webrtc/VideoRendererGui.java b/talk/app/webrtc/java/android/org/webrtc/VideoRendererGui.java index 8246e8bd17..a685c397c8 100644 --- a/talk/app/webrtc/java/android/org/webrtc/VideoRendererGui.java +++ b/talk/app/webrtc/java/android/org/webrtc/VideoRendererGui.java @@ -42,7 +42,6 @@ import android.opengl.EGL14; import android.opengl.EGLContext; import android.opengl.GLES20; import android.opengl.GLSurfaceView; -import android.opengl.Matrix; import android.util.Log; import org.webrtc.VideoRenderer.I420Frame; @@ -73,20 +72,6 @@ public class VideoRendererGui implements GLSurfaceView.Renderer { private final ArrayList<YuvImageRenderer> yuvImageRenderers; // |drawer| is synchronized on |yuvImageRenderers|. private GlRectDrawer drawer; - // The minimum fraction of the frame content that will be shown for |SCALE_ASPECT_BALANCED|. - // This limits excessive cropping when adjusting display size. - private static float BALANCED_VISIBLE_FRACTION = 0.56f; - // Types of video scaling: - // SCALE_ASPECT_FIT - video frame is scaled to fit the size of the view by - // maintaining the aspect ratio (black borders may be displayed). - // SCALE_ASPECT_FILL - video frame is scaled to fill the size of the view by - // maintaining the aspect ratio. Some portion of the video frame may be - // clipped. - // SCALE_ASPECT_BALANCED - Compromise between FIT and FILL. Video frame will fill as much as - // possible of the view while maintaining aspect ratio, under the constraint that at least - // |BALANCED_VISIBLE_FRACTION| of the frame content will be shown. - public static enum ScalingType - { SCALE_ASPECT_FIT, SCALE_ASPECT_FILL, SCALE_ASPECT_BALANCED } private static final int EGL14_SDK_VERSION = android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; // Current SDK version. @@ -146,9 +131,9 @@ public class VideoRendererGui implements GLSurfaceView.Renderer { // Type of video frame used for recent frame rendering. private static enum RendererType { RENDERER_YUV, RENDERER_TEXTURE }; private RendererType rendererType; - private ScalingType scalingType; + private RendererCommon.ScalingType scalingType; private boolean mirror; - private RendererEvents rendererEvents; + private RendererCommon.RendererEvents rendererEvents; // Flag if renderFrame() was ever called. boolean seenFrame; // Total number of video frames received in renderFrame() call. @@ -190,7 +175,7 @@ public class VideoRendererGui implements GLSurfaceView.Renderer { private YuvImageRenderer( GLSurfaceView surface, int id, int x, int y, int width, int height, - ScalingType scalingType, boolean mirror) { + RendererCommon.ScalingType scalingType, boolean mirror) { Log.d(TAG, "YuvImageRenderer.Create id: " + id); this.surface = surface; this.id = id; @@ -232,33 +217,6 @@ public class VideoRendererGui implements GLSurfaceView.Renderer { GlUtil.checkNoGLES2Error("y/u/v glGenTextures"); } - private static float convertScalingTypeToVisibleFraction(ScalingType scalingType) { - switch (scalingType) { - case SCALE_ASPECT_FIT: - return 1.0f; - case SCALE_ASPECT_FILL: - return 0.0f; - case SCALE_ASPECT_BALANCED: - return BALANCED_VISIBLE_FRACTION; - default: - throw new IllegalArgumentException(); - } - } - - private static Point getDisplaySize(float minVisibleFraction, float videoAspectRatio, - int maxDisplayWidth, int maxDisplayHeight) { - // If there is no constraint on the amount of cropping, fill the allowed display area. - if (minVisibleFraction == 0) { - return new Point(maxDisplayWidth, maxDisplayHeight); - } - // Each dimension is constrained on max display size and how much we are allowed to crop. - final int width = Math.min(maxDisplayWidth, - (int) (maxDisplayHeight / minVisibleFraction * videoAspectRatio)); - final int height = Math.min(maxDisplayHeight, - (int) (maxDisplayWidth / minVisibleFraction / videoAspectRatio)); - return new Point(width, height); - } - private void checkAdjustTextureCoords() { synchronized(updateTextureLock) { if (!updateTextureProperties) { @@ -278,38 +236,14 @@ public class VideoRendererGui implements GLSurfaceView.Renderer { ? (float) videoWidth / videoHeight : (float) videoHeight / videoWidth; // Adjust display size based on |scalingType|. - final float minVisibleFraction = convertScalingTypeToVisibleFraction(scalingType); - final Point displaySize = getDisplaySize(minVisibleFraction, videoAspectRatio, - displayLayout.width(), displayLayout.height()); + final Point displaySize = RendererCommon.getDisplaySize(scalingType, + videoAspectRatio, displayLayout.width(), displayLayout.height()); displayLayout.inset((displayLayout.width() - displaySize.x) / 2, (displayLayout.height() - displaySize.y) / 2); Log.d(TAG, " Adjusted display size: " + displayLayout.width() + " x " + displayLayout.height()); - // The matrix stack is using post-multiplication, which means that matrix operations: - // A; B; C; will end up as A * B * C. When you apply this to a vertex, it will result in: - // v' = A * B * C * v, i.e. the last matrix operation is the first thing that affects the - // vertex. This is the opposite of what you might expect. - Matrix.setIdentityM(texMatrix, 0); - // Move coordinates back to [0,1]x[0,1]. - Matrix.translateM(texMatrix, 0, 0.5f, 0.5f, 0.0f); - // Rotate frame clockwise in the XY-plane (around the Z-axis). - Matrix.rotateM(texMatrix, 0, -rotationDegree, 0, 0, 1); - // Scale one dimension until video and display size have same aspect ratio. - final float displayAspectRatio = (float) displayLayout.width() / displayLayout.height(); - if (displayAspectRatio > videoAspectRatio) { - Matrix.scaleM(texMatrix, 0, 1, videoAspectRatio / displayAspectRatio, 1); - } else { - Matrix.scaleM(texMatrix, 0, displayAspectRatio / videoAspectRatio, 1, 1); - } - // TODO(magjed): We currently ignore the texture transform matrix from the SurfaceTexture. - // It contains a vertical flip that is hardcoded here instead. - Matrix.scaleM(texMatrix, 0, 1, -1, 1); - // Apply optional horizontal flip. - if (mirror) { - Matrix.scaleM(texMatrix, 0, -1, 1, 1); - } - // Center coordinates around origin. - Matrix.translateM(texMatrix, 0, -0.5f, -0.5f, 0.0f); + RendererCommon.getTextureMatrix(texMatrix, rotationDegree, mirror, videoAspectRatio, + (float) displayLayout.width() / displayLayout.height()); updateTextureProperties = false; Log.d(TAG, " AdjustTextureCoords done"); } @@ -408,7 +342,7 @@ public class VideoRendererGui implements GLSurfaceView.Renderer { } public void setPosition(int x, int y, int width, int height, - ScalingType scalingType, boolean mirror) { + RendererCommon.ScalingType scalingType, boolean mirror) { final Rect layoutInPercentage = new Rect(x, y, Math.min(100, x + width), Math.min(100, y + height)); synchronized(updateTextureLock) { @@ -528,19 +462,6 @@ public class VideoRendererGui implements GLSurfaceView.Renderer { } } - /** Interface for reporting rendering events. */ - public static interface RendererEvents { - /** - * Callback fired once first frame is rendered. - */ - public void onFirstFrameRendered(); - - /** - * Callback fired when rendered frame resolution or rotation has changed. - */ - public void onFrameResolutionChanged(int videoWidth, int videoHeight, int rotation); - } - /** Passes GLSurfaceView to video renderer. */ public static synchronized void setView(GLSurfaceView surface, Runnable eglContextReadyCallback) { @@ -558,7 +479,7 @@ public class VideoRendererGui implements GLSurfaceView.Renderer { * (width, height). All parameters are in percentage of screen resolution. */ public static VideoRenderer createGui(int x, int y, int width, int height, - ScalingType scalingType, boolean mirror) throws Exception { + RendererCommon.ScalingType scalingType, boolean mirror) throws Exception { YuvImageRenderer javaGuiRenderer = create( x, y, width, height, scalingType, mirror); return new VideoRenderer(javaGuiRenderer); @@ -566,7 +487,7 @@ public class VideoRendererGui implements GLSurfaceView.Renderer { public static VideoRenderer.Callbacks createGuiRenderer( int x, int y, int width, int height, - ScalingType scalingType, boolean mirror) { + RendererCommon.ScalingType scalingType, boolean mirror) { return create(x, y, width, height, scalingType, mirror); } @@ -576,7 +497,7 @@ public class VideoRendererGui implements GLSurfaceView.Renderer { * screen resolution. */ public static synchronized YuvImageRenderer create(int x, int y, int width, int height, - ScalingType scalingType, boolean mirror) { + RendererCommon.ScalingType scalingType, boolean mirror) { // Check display region parameters. if (x < 0 || x > 100 || y < 0 || y > 100 || width < 0 || width > 100 || height < 0 || height > 100 || @@ -619,8 +540,8 @@ public class VideoRendererGui implements GLSurfaceView.Renderer { } public static synchronized void update( - VideoRenderer.Callbacks renderer, - int x, int y, int width, int height, ScalingType scalingType, boolean mirror) { + VideoRenderer.Callbacks renderer, int x, int y, int width, int height, + RendererCommon.ScalingType scalingType, boolean mirror) { Log.d(TAG, "VideoRendererGui.update"); if (instance == null) { throw new RuntimeException( @@ -636,7 +557,7 @@ public class VideoRendererGui implements GLSurfaceView.Renderer { } public static synchronized void setRendererEvents( - VideoRenderer.Callbacks renderer, RendererEvents rendererEvents) { + VideoRenderer.Callbacks renderer, RendererCommon.RendererEvents rendererEvents) { Log.d(TAG, "VideoRendererGui.setRendererEvents"); if (instance == null) { throw new RuntimeException( diff --git a/talk/libjingle.gyp b/talk/libjingle.gyp index 15272519a2..8ae81fa084 100755 --- a/talk/libjingle.gyp +++ b/talk/libjingle.gyp @@ -144,6 +144,7 @@ 'app/webrtc/java/android/org/webrtc/GlRectDrawer.java', 'app/webrtc/java/android/org/webrtc/GlShader.java', 'app/webrtc/java/android/org/webrtc/GlUtil.java', + 'app/webrtc/java/android/org/webrtc/RendererCommon.java', 'app/webrtc/java/android/org/webrtc/VideoRendererGui.java', 'app/webrtc/java/src/org/webrtc/MediaCodecVideoEncoder.java', 'app/webrtc/java/src/org/webrtc/MediaCodecVideoDecoder.java', diff --git a/webrtc/examples/androidapp/src/org/appspot/apprtc/CallActivity.java b/webrtc/examples/androidapp/src/org/appspot/apprtc/CallActivity.java index a033c2f1ce..e2fa7d1e09 100644 --- a/webrtc/examples/androidapp/src/org/appspot/apprtc/CallActivity.java +++ b/webrtc/examples/androidapp/src/org/appspot/apprtc/CallActivity.java @@ -33,9 +33,9 @@ import android.widget.Toast; import org.webrtc.IceCandidate; import org.webrtc.SessionDescription; import org.webrtc.StatsReport; +import org.webrtc.RendererCommon.ScalingType; import org.webrtc.VideoRenderer; import org.webrtc.VideoRendererGui; -import org.webrtc.VideoRendererGui.ScalingType; /** * Activity for peer connection call setup, call waiting diff --git a/webrtc/examples/androidapp/src/org/appspot/apprtc/CallFragment.java b/webrtc/examples/androidapp/src/org/appspot/apprtc/CallFragment.java index 3d445d4f90..35013f7948 100644 --- a/webrtc/examples/androidapp/src/org/appspot/apprtc/CallFragment.java +++ b/webrtc/examples/androidapp/src/org/appspot/apprtc/CallFragment.java @@ -19,7 +19,7 @@ import android.view.ViewGroup; import android.widget.ImageButton; import android.widget.TextView; -import org.webrtc.VideoRendererGui.ScalingType; +import org.webrtc.RendererCommon.ScalingType; /** * Fragment for call control. |