OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * libjingle | |
3 * Copyright 2015 Google Inc. | |
4 * | |
5 * Redistribution and use in source and binary forms, with or without | |
6 * modification, are permitted provided that the following conditions are met: | |
7 * | |
8 * 1. Redistributions of source code must retain the above copyright notice, | |
9 * this list of conditions and the following disclaimer. | |
10 * 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 * this list of conditions and the following disclaimer in the documentation | |
12 * and/or other materials provided with the distribution. | |
13 * 3. The name of the author may not be used to endorse or promote products | |
14 * derived from this software without specific prior written permission. | |
15 * | |
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | |
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
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, | |
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 | |
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
26 */ | |
27 | |
28 package org.webrtc; | |
29 | |
30 import android.opengl.EGL14; | |
31 import android.test.ActivityTestCase; | |
32 import android.test.suitebuilder.annotation.MediumTest; | |
33 import android.view.View.MeasureSpec; | |
34 | |
35 import java.nio.ByteBuffer; | |
36 import java.util.Arrays; | |
37 import java.util.List; | |
38 | |
39 public final class SurfaceViewRendererOnMeasureTest extends ActivityTestCase { | |
40 /** | |
41 * List with all possible scaling types. | |
42 */ | |
43 private static final List<RendererCommon.ScalingType> scalingTypes = Arrays.as List( | |
44 RendererCommon.ScalingType.SCALE_ASPECT_FIT, | |
45 RendererCommon.ScalingType.SCALE_ASPECT_FILL, | |
46 RendererCommon.ScalingType.SCALE_ASPECT_BALANCED); | |
47 | |
48 /** | |
49 * List with MeasureSpec modes. | |
50 */ | |
51 private static final List<Integer> measureSpecModes = | |
52 Arrays.asList(MeasureSpec.EXACTLY, MeasureSpec.AT_MOST); | |
hbos
2015/10/06 08:15:16
In the below tests, why do we expect the AT_MOST m
magjed_webrtc
2015/10/07 08:43:52
After a frame is delivered we know exactly how big
hbos
2015/10/07 09:47:09
Acknowledged.
| |
53 | |
54 /** | |
55 * Returns a dummy YUV frame. | |
56 */ | |
57 static VideoRenderer.I420Frame createFrame(int width, int height, int rotation Degree) { | |
58 final int[] yuvStrides = new int[] {width, (width + 1) / 2, (width + 1) / 2} ; | |
59 final int[] yuvHeights = new int[] {height, (height + 1) / 2, (height + 1) / 2}; | |
60 final ByteBuffer[] yuvPlanes = new ByteBuffer[3]; | |
61 for (int i = 0; i < 3; ++i) { | |
62 yuvPlanes[i] = ByteBuffer.allocateDirect(yuvStrides[i] * yuvHeights[i]); | |
63 } | |
64 return new VideoRenderer.I420Frame(width, height, rotationDegree, yuvStrides , yuvPlanes, 0); | |
65 } | |
hbos
2015/10/06 08:15:16
Remember multiple of 16 stride alignments and Vide
magjed_webrtc
2015/10/07 08:43:53
Yeah, that's specific to the camera. We can use wh
hbos
2015/10/07 09:47:09
Acknowledged.
| |
66 | |
67 /** | |
68 * Assert onMeasure() with given parameters will result in expected measured s ize. | |
69 */ | |
70 private static void assertMeasuredSize( | |
71 SurfaceViewRenderer surfaceViewRenderer, RendererCommon.ScalingType scalin gType, | |
72 String frameDimensions, | |
73 int expectedWidth, int expectedHeight, | |
74 int widthSpec, int heightSpec) { | |
75 surfaceViewRenderer.setScalingType(scalingType); | |
76 surfaceViewRenderer.onMeasure(widthSpec, heightSpec); | |
hbos
2015/10/06 08:15:16
I looked at onMeasure. The way it obtains and rele
magjed_webrtc
2015/10/07 08:43:52
Hmm. onMeasure() is only called from UI thread in
hbos
2015/10/07 09:47:09
Acknowledged.
| |
77 final int measuredWidth = surfaceViewRenderer.getMeasuredWidth(); | |
78 final int measuredHeight = surfaceViewRenderer.getMeasuredHeight(); | |
79 if (measuredWidth != expectedWidth || measuredHeight != expectedHeight) { | |
80 fail("onMeasure(" | |
81 + MeasureSpec.toString(widthSpec) + ", " + MeasureSpec.toString(height Spec) + ")" | |
82 + " with scaling type " + scalingType | |
83 + " and frame: " + frameDimensions | |
84 + " expected measured size " + expectedWidth + "x" + expectedHeight | |
85 + ", but was " + measuredWidth + "x" + measuredHeight); | |
86 } | |
87 } | |
88 | |
89 /** | |
90 * Test how SurfaceViewRenderer.onMeasure() behaves when no frame has been del ivered. | |
91 */ | |
92 @MediumTest | |
93 public void testNoFrame() { | |
94 final SurfaceViewRenderer surfaceViewRenderer = | |
95 new SurfaceViewRenderer(getInstrumentation().getContext()); | |
96 final String frameDimensions = "null"; | |
97 | |
98 // Test behaviour before SurfaceViewRenderer.init() is called. | |
99 for (RendererCommon.ScalingType scalingType : scalingTypes) { | |
100 for (int measureSpecMode : measureSpecModes) { | |
101 final int zeroMeasureSize = MeasureSpec.makeMeasureSpec(0, measureSpecMo de); | |
102 assertMeasuredSize(surfaceViewRenderer, scalingType, frameDimensions, | |
103 0, 0, zeroMeasureSize, zeroMeasureSize); | |
104 assertMeasuredSize(surfaceViewRenderer, scalingType, frameDimensions, | |
105 1280, 720, | |
106 MeasureSpec.makeMeasureSpec(1280, measureSpecMode), | |
107 MeasureSpec.makeMeasureSpec(720, measureSpecMode)); | |
108 } | |
109 } | |
110 | |
111 // Test behaviour after SurfaceViewRenderer.init() is called, but still no fr ame. | |
112 surfaceViewRenderer.init(EGL14.EGL_NO_CONTEXT, null); | |
113 for (RendererCommon.ScalingType scalingType : scalingTypes) { | |
114 for (int measureSpecMode : measureSpecModes) { | |
115 final int zeroMeasureSize = MeasureSpec.makeMeasureSpec(0, measureSpecMo de); | |
116 assertMeasuredSize(surfaceViewRenderer, scalingType, frameDimensions, | |
117 0, 0, zeroMeasureSize, zeroMeasureSize); | |
118 assertMeasuredSize(surfaceViewRenderer, scalingType, frameDimensions, | |
119 1280, 720, | |
120 MeasureSpec.makeMeasureSpec(1280, measureSpecMode), | |
121 MeasureSpec.makeMeasureSpec(720, measureSpecMode)); | |
122 } | |
123 } | |
124 | |
125 surfaceViewRenderer.release(); | |
126 } | |
127 | |
128 /** | |
129 * Test how SurfaceViewRenderer.onMeasure() behaves with a 1280x720 frame. | |
130 */ | |
131 @MediumTest | |
132 public void testFrame1280x720() { | |
133 final SurfaceViewRenderer surfaceViewRenderer = | |
134 new SurfaceViewRenderer(getInstrumentation().getContext()); | |
135 surfaceViewRenderer.init(EGL14.EGL_NO_CONTEXT, null); | |
136 | |
137 // Test different rotation degress, but same rotated size. | |
138 for (int rotationDegree : new int[] {0, 90, 180, 270}) { | |
139 final int rotatedWidth = 1280; | |
140 final int rotatedHeight = 720; | |
141 final int unrotatedWidth = (rotationDegree % 180 == 0 ? rotatedWidth : rot atedHeight); | |
142 final int unrotatedHeight = (rotationDegree % 180 == 0 ? rotatedHeight : r otatedWidth); | |
143 final VideoRenderer.I420Frame frame = | |
144 createFrame(unrotatedWidth, unrotatedHeight, rotationDegree); | |
145 assertEquals(rotatedWidth, frame.rotatedWidth()); | |
146 assertEquals(rotatedHeight, frame.rotatedHeight()); | |
147 final String frameDimensions = | |
148 unrotatedWidth + "x" + unrotatedHeight + " with rotation " + rotationD egree; | |
149 surfaceViewRenderer.renderFrame(frame); | |
150 | |
151 // Test forcing to zero size. | |
152 for (RendererCommon.ScalingType scalingType : scalingTypes) { | |
153 for (int measureSpecMode : measureSpecModes) { | |
154 final int zeroMeasureSize = MeasureSpec.makeMeasureSpec(0, measureSpec Mode); | |
155 assertMeasuredSize(surfaceViewRenderer, scalingType, frameDimensions, | |
156 0, 0, zeroMeasureSize, zeroMeasureSize); | |
157 } | |
158 } | |
159 | |
160 // Test perfect fit. | |
161 for (RendererCommon.ScalingType scalingType : scalingTypes) { | |
162 for (int measureSpecMode : measureSpecModes) { | |
163 assertMeasuredSize(surfaceViewRenderer, scalingType, frameDimensions, | |
164 rotatedWidth, rotatedHeight, | |
165 MeasureSpec.makeMeasureSpec(rotatedWidth, measureSpecMode), | |
166 MeasureSpec.makeMeasureSpec(rotatedHeight, measureSpecMode)); | |
167 } | |
168 } | |
169 | |
170 // Force spec size with different aspect ratio than frame aspect ratio. | |
171 for (RendererCommon.ScalingType scalingType : scalingTypes) { | |
172 assertMeasuredSize(surfaceViewRenderer, scalingType, frameDimensions, | |
173 720, 1280, | |
174 MeasureSpec.makeMeasureSpec(720, MeasureSpec.EXACTLY), | |
175 MeasureSpec.makeMeasureSpec(1280, MeasureSpec.EXACTLY)); | |
176 } | |
177 | |
178 // Note about expected sizes: | |
179 // * SCALE_ASPECT_FIT will try to show the whole frame, which means keepin g the same | |
180 // layout aspect ratio as the frame. For a 1280x720 frame (16:9) and at most 720 spec | |
181 // width, this means a layout size of 720x405 (16:9). | |
182 // * SCALE_ASPECT_FILL will simply maximize the layout size given the meas ure constraints. | |
183 // * SCALE_ASPECT_BALANCED allows showing only a part of the frame. The la yout size will be | |
184 // 720x720 because 720x720 / 1280x720 = 9/16 = RendererCommon.BALANCED_V ISIBLE_FRACTION. | |
185 { | |
186 // Relax both width and height constraints. | |
187 final int widthSpec = MeasureSpec.makeMeasureSpec(720, MeasureSpec.AT_MO ST); | |
188 final int heightSpec = MeasureSpec.makeMeasureSpec(1280, MeasureSpec.AT_ MOST); | |
189 assertMeasuredSize(surfaceViewRenderer, RendererCommon.ScalingType.SCALE _ASPECT_FIT, | |
190 frameDimensions, 720, 405, widthSpec, heightSpec); | |
191 assertMeasuredSize(surfaceViewRenderer, RendererCommon.ScalingType.SCALE _ASPECT_FILL, | |
192 frameDimensions, 720, 1280, widthSpec, heightSpec); | |
193 assertMeasuredSize(surfaceViewRenderer, RendererCommon.ScalingType.SCALE _ASPECT_BALANCED, | |
194 frameDimensions, 720, 720, widthSpec, heightSpec); | |
195 } | |
196 { | |
197 // Force width to 720, but relax height constraint. This will give the s ame result as above. | |
198 final int widthSpec = MeasureSpec.makeMeasureSpec(720, MeasureSpec.EXACT LY); | |
199 final int heightSpec = MeasureSpec.makeMeasureSpec(1280, MeasureSpec.AT_ MOST); | |
200 assertMeasuredSize(surfaceViewRenderer, RendererCommon.ScalingType.SCALE _ASPECT_FIT, | |
201 frameDimensions, 720, 405, widthSpec, heightSpec); | |
202 assertMeasuredSize(surfaceViewRenderer, RendererCommon.ScalingType.SCALE _ASPECT_FILL, | |
203 frameDimensions, 720, 1280, widthSpec, heightSpec); | |
204 assertMeasuredSize(surfaceViewRenderer, RendererCommon.ScalingType.SCALE _ASPECT_BALANCED, | |
205 frameDimensions, 720, 720, widthSpec, heightSpec); | |
206 } | |
207 { | |
208 // Force height, but relax width constraint. This will force a bad layou t size. | |
209 final int widthSpec = MeasureSpec.makeMeasureSpec(720, MeasureSpec.AT_MO ST); | |
210 final int heightSpec = MeasureSpec.makeMeasureSpec(1280, MeasureSpec.EXA CTLY); | |
211 assertMeasuredSize(surfaceViewRenderer, RendererCommon.ScalingType.SCALE _ASPECT_FIT, | |
212 frameDimensions, 720, 1280, widthSpec, heightSpec); | |
213 assertMeasuredSize(surfaceViewRenderer, RendererCommon.ScalingType.SCALE _ASPECT_FILL, | |
214 frameDimensions, 720, 1280, widthSpec, heightSpec); | |
215 assertMeasuredSize(surfaceViewRenderer, RendererCommon.ScalingType.SCALE _ASPECT_BALANCED, | |
216 frameDimensions, 720, 1280, widthSpec, heightSpec); | |
217 } | |
218 } | |
219 | |
220 surfaceViewRenderer.release(); | |
221 } | |
222 } | |
OLD | NEW |