Home | History | Annotate | Download | only in webrtc
      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