OLD | NEW |
1 /* | 1 /* |
2 * libjingle | 2 * libjingle |
3 * Copyright 2015 Google Inc. | 3 * Copyright 2015 Google Inc. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
(...skipping 10 matching lines...) Expand all Loading... |
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 */ | 26 */ |
27 | 27 |
28 package org.webrtc; | 28 package org.webrtc; |
29 | 29 |
30 import android.graphics.Point; | 30 import android.graphics.Point; |
| 31 import android.graphics.SurfaceTexture; |
31 import android.opengl.Matrix; | 32 import android.opengl.Matrix; |
32 | 33 |
33 /** | 34 /** |
34 * Static helper functions for renderer implementations. | 35 * Static helper functions for renderer implementations. |
35 */ | 36 */ |
36 public class RendererCommon { | 37 public class RendererCommon { |
37 /** Interface for reporting rendering events. */ | 38 /** Interface for reporting rendering events. */ |
38 public static interface RendererEvents { | 39 public static interface RendererEvents { |
39 /** | 40 /** |
40 * Callback fired once first frame is rendered. | 41 * Callback fired once first frame is rendered. |
(...skipping 12 matching lines...) Expand all Loading... |
53 // SCALE_ASPECT_FILL - video frame is scaled to fill the size of the view by | 54 // SCALE_ASPECT_FILL - video frame is scaled to fill the size of the view by |
54 // maintaining the aspect ratio. Some portion of the video frame may be | 55 // maintaining the aspect ratio. Some portion of the video frame may be |
55 // clipped. | 56 // clipped. |
56 // SCALE_ASPECT_BALANCED - Compromise between FIT and FILL. Video frame will f
ill as much as | 57 // SCALE_ASPECT_BALANCED - Compromise between FIT and FILL. Video frame will f
ill as much as |
57 // possible of the view while maintaining aspect ratio, under the constraint t
hat at least | 58 // possible of the view while maintaining aspect ratio, under the constraint t
hat at least |
58 // |BALANCED_VISIBLE_FRACTION| of the frame content will be shown. | 59 // |BALANCED_VISIBLE_FRACTION| of the frame content will be shown. |
59 public static enum ScalingType { SCALE_ASPECT_FIT, SCALE_ASPECT_FILL, SCALE_AS
PECT_BALANCED } | 60 public static enum ScalingType { SCALE_ASPECT_FIT, SCALE_ASPECT_FILL, SCALE_AS
PECT_BALANCED } |
60 // The minimum fraction of the frame content that will be shown for |SCALE_ASP
ECT_BALANCED|. | 61 // The minimum fraction of the frame content that will be shown for |SCALE_ASP
ECT_BALANCED|. |
61 // This limits excessive cropping when adjusting display size. | 62 // This limits excessive cropping when adjusting display size. |
62 private static float BALANCED_VISIBLE_FRACTION = 0.5625f; | 63 private static float BALANCED_VISIBLE_FRACTION = 0.5625f; |
| 64 // Matrix with transform y' = 1 - y. |
| 65 private static final float[] VERTICAL_FLIP = new float[] { |
| 66 1, 0, 0, 0, |
| 67 0, -1, 0, 0, |
| 68 0, 0, 1, 0, |
| 69 0, 1, 0, 1}; |
63 | 70 |
64 /** | 71 /** |
65 * Calculates a texture transformation matrix based on rotation, mirror, and v
ideo vs display | 72 * Returns matrix that transforms standard coordinates to their proper samplin
g locations in |
66 * aspect ratio. | 73 * the texture. This transform compensates for any properties of the video sou
rce that |
| 74 * cause it to appear different from a normalized texture. If the video source
is based on |
| 75 * ByteBuffers, pass null in |surfaceTexture|. |
67 */ | 76 */ |
68 public static void getTextureMatrix(float[] outputTextureMatrix, float rotatio
nDegree, | 77 public static float[] getSamplingMatrix(SurfaceTexture surfaceTexture, float r
otationDegree) { |
69 boolean mirror, float videoAspectRatio, float displayAspectRatio) { | 78 final float[] samplingMatrix; |
70 // The matrix stack is using post-multiplication, which means that matrix op
erations: | 79 if (surfaceTexture == null) { |
71 // A; B; C; will end up as A * B * C. When you apply this to a vertex, it wi
ll result in: | 80 // For ByteBuffers, row 0 specifies the top row, but for a texture, row 0
specifies the |
72 // v' = A * B * C * v, i.e. the last matrix operation is the first thing tha
t affects the | 81 // bottom row. Flip the image vertically to compensate for this. |
73 // vertex. This is the opposite of what you might expect. | 82 samplingMatrix = VERTICAL_FLIP; |
74 Matrix.setIdentityM(outputTextureMatrix, 0); | |
75 // Move coordinates back to [0,1]x[0,1]. | |
76 Matrix.translateM(outputTextureMatrix, 0, 0.5f, 0.5f, 0.0f); | |
77 // Rotate frame clockwise in the XY-plane (around the Z-axis). | |
78 Matrix.rotateM(outputTextureMatrix, 0, -rotationDegree, 0, 0, 1); | |
79 // Scale one dimension until video and display size have same aspect ratio. | |
80 if (displayAspectRatio > videoAspectRatio) { | |
81 Matrix.scaleM(outputTextureMatrix, 0, 1, videoAspectRatio / displayAspectR
atio, 1); | |
82 } else { | 83 } else { |
83 Matrix.scaleM(outputTextureMatrix, 0, displayAspectRatio / videoAspectRati
o, 1, 1); | 84 samplingMatrix = new float[16]; |
| 85 surfaceTexture.getTransformMatrix(samplingMatrix); |
84 } | 86 } |
85 // TODO(magjed): We currently ignore the texture transform matrix from the S
urfaceTexture. | 87 // Clockwise rotation matrix in the XY-plane (around the Z-axis). |
86 // It contains a vertical flip that is hardcoded here instead. | 88 final float[] rotationMatrix = new float[16]; |
87 Matrix.scaleM(outputTextureMatrix, 0, 1, -1, 1); | 89 Matrix.setRotateM(rotationMatrix, 0, -rotationDegree, 0, 0, 1); |
88 // Apply optional horizontal flip. | 90 adjustOrigin(rotationMatrix); |
89 if (mirror) { | 91 // Multiply matrices together. |
90 Matrix.scaleM(outputTextureMatrix, 0, -1, 1, 1); | 92 final float[] tmpMatrix = new float[16]; |
91 } | 93 Matrix.multiplyMM(tmpMatrix, 0, rotationMatrix, 0, samplingMatrix, 0); |
92 // Center coordinates around origin. | 94 return tmpMatrix; |
93 Matrix.translateM(outputTextureMatrix, 0, -0.5f, -0.5f, 0.0f); | |
94 } | 95 } |
95 | 96 |
96 /** | 97 /** |
| 98 * Returns layout transformation matrix that applies an optional mirror effect
and compensates |
| 99 * for video vs display aspect ratio. |
| 100 */ |
| 101 public static float[] getLayoutMatrix( |
| 102 boolean mirror, float videoAspectRatio, float displayAspectRatio) { |
| 103 float scaleX = 1; |
| 104 float scaleY = 1; |
| 105 // Scale X or Y dimension so that video and display size have same aspect ra
tio. |
| 106 if (displayAspectRatio > videoAspectRatio) { |
| 107 scaleY = videoAspectRatio / displayAspectRatio; |
| 108 } else { |
| 109 scaleX = displayAspectRatio / videoAspectRatio; |
| 110 } |
| 111 // Apply optional horizontal flip. |
| 112 if (mirror) { |
| 113 scaleX *= -1; |
| 114 } |
| 115 final float matrix[] = new float[16]; |
| 116 Matrix.setIdentityM(matrix, 0); |
| 117 Matrix.scaleM(matrix, 0, scaleX, scaleY, 1); |
| 118 adjustOrigin(matrix); |
| 119 return matrix; |
| 120 } |
| 121 |
| 122 /** |
97 * Calculate display size based on scaling type, video aspect ratio, and maxim
um display size. | 123 * Calculate display size based on scaling type, video aspect ratio, and maxim
um display size. |
98 */ | 124 */ |
99 public static Point getDisplaySize(ScalingType scalingType, float videoAspectR
atio, | 125 public static Point getDisplaySize(ScalingType scalingType, float videoAspectR
atio, |
100 int maxDisplayWidth, int maxDisplayHeight) { | 126 int maxDisplayWidth, int maxDisplayHeight) { |
101 return getDisplaySize(convertScalingTypeToVisibleFraction(scalingType), vide
oAspectRatio, | 127 return getDisplaySize(convertScalingTypeToVisibleFraction(scalingType), vide
oAspectRatio, |
102 maxDisplayWidth, maxDisplayHeight); | 128 maxDisplayWidth, maxDisplayHeight); |
103 } | 129 } |
104 | 130 |
105 /** | 131 /** |
| 132 * Move |matrix| transformation origin to (0.5, 0.5). This is the origin for t
exture coordinates |
| 133 * that are in the range 0 to 1. |
| 134 */ |
| 135 private static void adjustOrigin(float[] matrix) { |
| 136 // Note that OpenGL is using column-major order. |
| 137 // Pre translate with -0.5 to move coordinates to range [-0.5, 0.5]. |
| 138 matrix[12] -= 0.5f * (matrix[0] + matrix[4]); |
| 139 matrix[13] -= 0.5f * (matrix[1] + matrix[5]); |
| 140 // Post translate with 0.5 to move coordinates to range [0, 1]. |
| 141 matrix[12] += 0.5f; |
| 142 matrix[13] += 0.5f; |
| 143 } |
| 144 |
| 145 /** |
106 * Each scaling type has a one-to-one correspondence to a numeric minimum frac
tion of the video | 146 * Each scaling type has a one-to-one correspondence to a numeric minimum frac
tion of the video |
107 * that must remain visible. | 147 * that must remain visible. |
108 */ | 148 */ |
109 private static float convertScalingTypeToVisibleFraction(ScalingType scalingTy
pe) { | 149 private static float convertScalingTypeToVisibleFraction(ScalingType scalingTy
pe) { |
110 switch (scalingType) { | 150 switch (scalingType) { |
111 case SCALE_ASPECT_FIT: | 151 case SCALE_ASPECT_FIT: |
112 return 1.0f; | 152 return 1.0f; |
113 case SCALE_ASPECT_FILL: | 153 case SCALE_ASPECT_FILL: |
114 return 0.0f; | 154 return 0.0f; |
115 case SCALE_ASPECT_BALANCED: | 155 case SCALE_ASPECT_BALANCED: |
(...skipping 14 matching lines...) Expand all Loading... |
130 return new Point(maxDisplayWidth, maxDisplayHeight); | 170 return new Point(maxDisplayWidth, maxDisplayHeight); |
131 } | 171 } |
132 // Each dimension is constrained on max display size and how much we are all
owed to crop. | 172 // Each dimension is constrained on max display size and how much we are all
owed to crop. |
133 final int width = Math.min(maxDisplayWidth, | 173 final int width = Math.min(maxDisplayWidth, |
134 (int) (maxDisplayHeight / minVisibleFraction * videoAspectRatio)); | 174 (int) (maxDisplayHeight / minVisibleFraction * videoAspectRatio)); |
135 final int height = Math.min(maxDisplayHeight, | 175 final int height = Math.min(maxDisplayHeight, |
136 (int) (maxDisplayWidth / minVisibleFraction / videoAspectRatio)); | 176 (int) (maxDisplayWidth / minVisibleFraction / videoAspectRatio)); |
137 return new Point(width, height); | 177 return new Point(width, height); |
138 } | 178 } |
139 } | 179 } |
OLD | NEW |