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 package org.webrtc; 28 29 import android.test.ActivityTestCase; 30 import android.test.suitebuilder.annotation.MediumTest; 31 import android.test.suitebuilder.annotation.SmallTest; 32 import android.util.Size; 33 34 import org.webrtc.CameraEnumerationAndroid.CaptureFormat; 35 36 import java.util.HashSet; 37 import java.util.Set; 38 39 @SuppressWarnings("deprecation") 40 public class VideoCapturerAndroidTest extends ActivityTestCase { 41 static final String TAG = "VideoCapturerAndroidTest"; 42 43 @Override 44 protected void setUp() { 45 assertTrue(PeerConnectionFactory.initializeAndroidGlobals( 46 getInstrumentation().getContext(), true, true, true)); 47 } 48 49 @SmallTest 50 // Test that enumerating formats using android.hardware.camera2 will give the same formats as 51 // android.hardware.camera in the range 320x240 to 1280x720. Often the camera2 API may contain 52 // some high resolutions that are not supported in camera1, but it may also be the other way 53 // around in some cases. Supported framerates may also differ, so don't compare those. 54 public void testCamera2Enumerator() { 55 if (!Camera2Enumerator.isSupported()) { 56 return; 57 } 58 final CameraEnumerationAndroid.Enumerator camera1Enumerator = new CameraEnumerator(); 59 final CameraEnumerationAndroid.Enumerator camera2Enumerator = 60 new Camera2Enumerator(getInstrumentation().getContext()); 61 62 for (int i = 0; i < CameraEnumerationAndroid.getDeviceCount(); ++i) { 63 final Set<Size> resolutions1 = new HashSet<Size>(); 64 for (CaptureFormat format : camera1Enumerator.getSupportedFormats(i)) { 65 resolutions1.add(new Size(format.width, format.height)); 66 } 67 final Set<Size> resolutions2 = new HashSet<Size>(); 68 for (CaptureFormat format : camera2Enumerator.getSupportedFormats(i)) { 69 resolutions2.add(new Size(format.width, format.height)); 70 } 71 for (Size size : resolutions1) { 72 if (size.getWidth() >= 320 && size.getHeight() >= 240 73 && size.getWidth() <= 1280 && size.getHeight() <= 720) { 74 assertTrue(resolutions2.contains(size)); 75 } 76 } 77 } 78 } 79 80 @SmallTest 81 public void testCreateAndRelease() { 82 VideoCapturerAndroidTestFixtures.release(VideoCapturerAndroid.create("", null)); 83 } 84 85 @SmallTest 86 public void testCreateAndReleaseUsingTextures() { 87 EglBase eglBase = EglBase.create(); 88 VideoCapturerAndroidTestFixtures.release( 89 VideoCapturerAndroid.create("", null, eglBase.getEglBaseContext())); 90 eglBase.release(); 91 } 92 93 @SmallTest 94 public void testCreateNonExistingCamera() { 95 VideoCapturerAndroid capturer = VideoCapturerAndroid.create( 96 "non-existing camera", null); 97 assertNull(capturer); 98 } 99 100 @SmallTest 101 // This test that the camera can be started and that the frames are forwarded 102 // to a Java video renderer using a "default" capturer. 103 // It tests both the Java and the C++ layer. 104 public void testStartVideoCapturer() throws InterruptedException { 105 VideoCapturerAndroid capturer = 106 VideoCapturerAndroid.create("", null); 107 VideoCapturerAndroidTestFixtures.startCapturerAndRender(capturer); 108 } 109 110 @SmallTest 111 public void testStartVideoCapturerUsingTextures() throws InterruptedException { 112 EglBase eglBase = EglBase.create(); 113 VideoCapturerAndroid capturer = 114 VideoCapturerAndroid.create("", null, eglBase.getEglBaseContext()); 115 VideoCapturerAndroidTestFixtures.startCapturerAndRender(capturer); 116 eglBase.release(); 117 } 118 119 @SmallTest 120 // This test that the camera can be started and that the frames are forwarded 121 // to a Java video renderer using the front facing video capturer. 122 // It tests both the Java and the C++ layer. 123 public void testStartFrontFacingVideoCapturer() throws InterruptedException { 124 String deviceName = CameraEnumerationAndroid.getNameOfFrontFacingDevice(); 125 VideoCapturerAndroid capturer = 126 VideoCapturerAndroid.create(deviceName, null); 127 VideoCapturerAndroidTestFixtures.startCapturerAndRender(capturer); 128 } 129 130 @SmallTest 131 // This test that the camera can be started and that the frames are forwarded 132 // to a Java video renderer using the back facing video capturer. 133 // It tests both the Java and the C++ layer. 134 public void testStartBackFacingVideoCapturer() throws InterruptedException { 135 if (!VideoCapturerAndroidTestFixtures.HaveTwoCameras()) { 136 return; 137 } 138 139 String deviceName = CameraEnumerationAndroid.getNameOfBackFacingDevice(); 140 VideoCapturerAndroid capturer = 141 VideoCapturerAndroid.create(deviceName, null); 142 VideoCapturerAndroidTestFixtures.startCapturerAndRender(capturer); 143 } 144 145 @SmallTest 146 // This test that the default camera can be started and that the camera can 147 // later be switched to another camera. 148 // It tests both the Java and the C++ layer. 149 public void testSwitchVideoCapturer() throws InterruptedException { 150 VideoCapturerAndroid capturer = VideoCapturerAndroid.create("", null); 151 VideoCapturerAndroidTestFixtures.switchCamera(capturer); 152 } 153 154 @SmallTest 155 public void testSwitchVideoCapturerUsingTextures() throws InterruptedException { 156 EglBase eglBase = EglBase.create(); 157 VideoCapturerAndroid capturer = 158 VideoCapturerAndroid.create("", null, eglBase.getEglBaseContext()); 159 VideoCapturerAndroidTestFixtures.switchCamera(capturer); 160 eglBase.release(); 161 } 162 163 @MediumTest 164 public void testCameraEvents() throws InterruptedException { 165 VideoCapturerAndroidTestFixtures.CameraEvents cameraEvents = 166 VideoCapturerAndroidTestFixtures.createCameraEvents(); 167 VideoCapturerAndroid capturer = VideoCapturerAndroid.create("", cameraEvents); 168 VideoCapturerAndroidTestFixtures.cameraEventsInvoked( 169 capturer, cameraEvents, getInstrumentation().getContext()); 170 } 171 172 @MediumTest 173 // Test what happens when attempting to call e.g. switchCamera() after camera has been stopped. 174 public void testCameraCallsAfterStop() throws InterruptedException { 175 final String deviceName = CameraEnumerationAndroid.getDeviceName(0); 176 final VideoCapturerAndroid capturer = VideoCapturerAndroid.create(deviceName, null); 177 178 VideoCapturerAndroidTestFixtures.cameraCallsAfterStop(capturer, 179 getInstrumentation().getContext()); 180 } 181 182 @MediumTest 183 public void testCameraCallsAfterStopUsingTextures() throws InterruptedException { 184 EglBase eglBase = EglBase.create(); 185 final String deviceName = CameraEnumerationAndroid.getDeviceName(0); 186 final VideoCapturerAndroid capturer = VideoCapturerAndroid.create(deviceName, null, 187 eglBase.getEglBaseContext()); 188 189 VideoCapturerAndroidTestFixtures.cameraCallsAfterStop(capturer, 190 getInstrumentation().getContext()); 191 eglBase.release(); 192 } 193 194 @SmallTest 195 // This test that the VideoSource that the VideoCapturer is connected to can 196 // be stopped and restarted. It tests both the Java and the C++ layer. 197 public void testStopRestartVideoSource() throws InterruptedException { 198 VideoCapturerAndroid capturer = VideoCapturerAndroid.create("", null); 199 VideoCapturerAndroidTestFixtures.stopRestartVideoSource(capturer); 200 } 201 202 @SmallTest 203 public void testStopRestartVideoSourceUsingTextures() throws InterruptedException { 204 EglBase eglBase = EglBase.create(); 205 VideoCapturerAndroid capturer = 206 VideoCapturerAndroid.create("", null, eglBase.getEglBaseContext()); 207 VideoCapturerAndroidTestFixtures.stopRestartVideoSource(capturer); 208 eglBase.release(); 209 } 210 211 @SmallTest 212 // This test that the camera can be started at different resolutions. 213 // It does not test or use the C++ layer. 214 public void testStartStopWithDifferentResolutions() throws InterruptedException { 215 String deviceName = CameraEnumerationAndroid.getDeviceName(0); 216 VideoCapturerAndroid capturer = 217 VideoCapturerAndroid.create(deviceName, null); 218 VideoCapturerAndroidTestFixtures.startStopWithDifferentResolutions(capturer, 219 getInstrumentation().getContext()); 220 } 221 222 @SmallTest 223 public void testStartStopWithDifferentResolutionsUsingTextures() throws InterruptedException { 224 EglBase eglBase = EglBase.create(); 225 String deviceName = CameraEnumerationAndroid.getDeviceName(0); 226 VideoCapturerAndroid capturer = 227 VideoCapturerAndroid.create(deviceName, null, eglBase.getEglBaseContext()); 228 VideoCapturerAndroidTestFixtures.startStopWithDifferentResolutions(capturer, 229 getInstrumentation().getContext()); 230 eglBase.release(); 231 } 232 233 @SmallTest 234 // This test that an error is reported if the camera is already opened 235 // when VideoCapturerAndroid is started. 236 public void testStartWhileCameraAlreadyOpened() throws InterruptedException { 237 String deviceName = CameraEnumerationAndroid.getDeviceName(0); 238 VideoCapturerAndroid capturer = 239 VideoCapturerAndroid.create(deviceName, null); 240 VideoCapturerAndroidTestFixtures.startWhileCameraIsAlreadyOpen( 241 capturer, getInstrumentation().getContext()); 242 } 243 244 @SmallTest 245 // This test that VideoCapturerAndroid can be started, even if the camera is already opened 246 // if the camera is closed while VideoCapturerAndroid is re-trying to start. 247 public void testStartWhileCameraIsAlreadyOpenAndCloseCamera() throws InterruptedException { 248 String deviceName = CameraEnumerationAndroid.getDeviceName(0); 249 VideoCapturerAndroid capturer = 250 VideoCapturerAndroid.create(deviceName, null); 251 VideoCapturerAndroidTestFixtures.startWhileCameraIsAlreadyOpenAndCloseCamera( 252 capturer, getInstrumentation().getContext()); 253 } 254 255 @SmallTest 256 // This test that VideoCapturerAndroid.stop can be called while VideoCapturerAndroid is 257 // re-trying to start. 258 public void startWhileCameraIsAlreadyOpenAndStop() throws InterruptedException { 259 String deviceName = CameraEnumerationAndroid.getDeviceName(0); 260 VideoCapturerAndroid capturer = 261 VideoCapturerAndroid.create(deviceName, null); 262 VideoCapturerAndroidTestFixtures.startWhileCameraIsAlreadyOpenAndStop( 263 capturer, getInstrumentation().getContext()); 264 } 265 266 267 268 @SmallTest 269 // This test what happens if buffers are returned after the capturer have 270 // been stopped and restarted. It does not test or use the C++ layer. 271 public void testReturnBufferLate() throws InterruptedException { 272 String deviceName = CameraEnumerationAndroid.getDeviceName(0); 273 VideoCapturerAndroid capturer = 274 VideoCapturerAndroid.create(deviceName, null); 275 VideoCapturerAndroidTestFixtures.returnBufferLate(capturer, 276 getInstrumentation().getContext()); 277 } 278 279 @SmallTest 280 public void testReturnBufferLateUsingTextures() throws InterruptedException { 281 EglBase eglBase = EglBase.create(); 282 String deviceName = CameraEnumerationAndroid.getDeviceName(0); 283 VideoCapturerAndroid capturer = 284 VideoCapturerAndroid.create(deviceName, null, eglBase.getEglBaseContext()); 285 VideoCapturerAndroidTestFixtures.returnBufferLate(capturer, 286 getInstrumentation().getContext()); 287 eglBase.release(); 288 } 289 290 @MediumTest 291 // This test that we can capture frames, keep the frames in a local renderer, stop capturing, 292 // and then return the frames. The difference between the test testReturnBufferLate() is that we 293 // also test the JNI and C++ AndroidVideoCapturer parts. 294 public void testReturnBufferLateEndToEnd() throws InterruptedException { 295 final VideoCapturerAndroid capturer = VideoCapturerAndroid.create("", null); 296 VideoCapturerAndroidTestFixtures.returnBufferLateEndToEnd(capturer); 297 } 298 299 @MediumTest 300 public void testReturnBufferLateEndToEndUsingTextures() throws InterruptedException { 301 EglBase eglBase = EglBase.create(); 302 final VideoCapturerAndroid capturer = 303 VideoCapturerAndroid.create("", null, eglBase.getEglBaseContext()); 304 VideoCapturerAndroidTestFixtures.returnBufferLateEndToEnd(capturer); 305 eglBase.release(); 306 } 307 308 @MediumTest 309 // This test that CameraEventsHandler.onError is triggered if video buffers are not returned to 310 // the capturer. 311 public void testCameraFreezedEventOnBufferStarvationUsingTextures() throws InterruptedException { 312 EglBase eglBase = EglBase.create(); 313 VideoCapturerAndroidTestFixtures.CameraEvents cameraEvents = 314 VideoCapturerAndroidTestFixtures.createCameraEvents(); 315 VideoCapturerAndroid capturer = VideoCapturerAndroid.create("", cameraEvents, 316 eglBase.getEglBaseContext()); 317 VideoCapturerAndroidTestFixtures.cameraFreezedEventOnBufferStarvationUsingTextures(capturer, 318 cameraEvents, getInstrumentation().getContext()); 319 eglBase.release(); 320 } 321 322 @MediumTest 323 // This test that frames forwarded to a renderer is scaled if onOutputFormatRequest is 324 // called. This test both Java and C++ parts of of the stack. 325 public void testScaleCameraOutput() throws InterruptedException { 326 VideoCapturerAndroid capturer = VideoCapturerAndroid.create("", null); 327 VideoCapturerAndroidTestFixtures.scaleCameraOutput(capturer); 328 } 329 330 @MediumTest 331 // This test that frames forwarded to a renderer is scaled if onOutputFormatRequest is 332 // called. This test both Java and C++ parts of of the stack. 333 public void testScaleCameraOutputUsingTextures() throws InterruptedException { 334 EglBase eglBase = EglBase.create(); 335 VideoCapturerAndroid capturer = 336 VideoCapturerAndroid.create("", null, eglBase.getEglBaseContext()); 337 VideoCapturerAndroidTestFixtures.scaleCameraOutput(capturer); 338 eglBase.release(); 339 } 340 } 341