Chromium Code Reviews| Index: webrtc/api/androidtests/src/org/webrtc/CameraVideoCapturerTestFixtures.java |
| diff --git a/webrtc/api/androidtests/src/org/webrtc/VideoCapturerAndroidTestFixtures.java b/webrtc/api/androidtests/src/org/webrtc/CameraVideoCapturerTestFixtures.java |
| similarity index 31% |
| rename from webrtc/api/androidtests/src/org/webrtc/VideoCapturerAndroidTestFixtures.java |
| rename to webrtc/api/androidtests/src/org/webrtc/CameraVideoCapturerTestFixtures.java |
| index 4c96b8cff071fb54bdd666a9b769ba2463e97db1..965101bd8d4ebb07d604b113e11a326309f48241 100644 |
| --- a/webrtc/api/androidtests/src/org/webrtc/VideoCapturerAndroidTestFixtures.java |
| +++ b/webrtc/api/androidtests/src/org/webrtc/CameraVideoCapturerTestFixtures.java |
| @@ -9,21 +9,21 @@ |
| */ |
| package org.webrtc; |
| +import java.util.ArrayList; |
| +import java.util.List; |
| +import java.util.concurrent.CountDownLatch; |
| + |
| import android.content.Context; |
| -import org.webrtc.VideoCapturerAndroidTestFixtures; |
| import org.webrtc.CameraEnumerationAndroid.CaptureFormat; |
| import org.webrtc.VideoRenderer.I420Frame; |
| -import java.util.ArrayList; |
| -import java.util.List; |
| -import java.util.concurrent.CountDownLatch; |
| - |
| import static junit.framework.Assert.*; |
| -@SuppressWarnings("deprecation") |
| -public class VideoCapturerAndroidTestFixtures { |
| - static class RendererCallbacks implements VideoRenderer.Callbacks { |
| +class CameraVideoCapturerTestFixtures { |
| + static final String TAG = "CameraVideoCapturerTestFixtures"; |
| + |
| + static private class RendererCallbacks implements VideoRenderer.Callbacks { |
| private int framesRendered = 0; |
| private Object frameLock = 0; |
| private int width = 0; |
| @@ -52,7 +52,8 @@ public class VideoCapturerAndroidTestFixtures { |
| } |
| } |
| - public int WaitForNextFrameToRender() throws InterruptedException { |
| + public int waitForNextFrameToRender() throws InterruptedException { |
| + Logging.d(TAG, "Waiting for the next frame to render"); |
| synchronized (frameLock) { |
| frameLock.wait(); |
| return framesRendered; |
| @@ -60,7 +61,7 @@ public class VideoCapturerAndroidTestFixtures { |
| } |
| } |
| - static class FakeAsyncRenderer implements VideoRenderer.Callbacks { |
| + static private class FakeAsyncRenderer implements VideoRenderer.Callbacks { |
| private final List<I420Frame> pendingFrames = new ArrayList<I420Frame>(); |
| @Override |
| @@ -73,6 +74,7 @@ public class VideoCapturerAndroidTestFixtures { |
| // Wait until at least one frame have been received, before returning them. |
| public List<I420Frame> waitForPendingFrames() throws InterruptedException { |
| + Logging.d(TAG, "Waiting for pending frames"); |
| synchronized (pendingFrames) { |
| while (pendingFrames.isEmpty()) { |
| pendingFrames.wait(); |
| @@ -82,21 +84,23 @@ public class VideoCapturerAndroidTestFixtures { |
| } |
| } |
| - static class FakeCapturerObserver implements VideoCapturer.CapturerObserver { |
| + static private class FakeCapturerObserver implements CameraVideoCapturer.CapturerObserver { |
| private int framesCaptured = 0; |
| private int frameSize = 0; |
| private int frameWidth = 0; |
| private int frameHeight = 0; |
| - private Object frameLock = 0; |
| - private Object capturerStartLock = 0; |
| - private boolean captureStartResult = false; |
| - private List<Long> timestamps = new ArrayList<Long>(); |
| + final private Object frameLock = new Object(); |
| + final private Object capturerStartLock = new Object(); |
| + private boolean capturerStartResult = false; |
| + final private List<Long> timestamps = new ArrayList<Long>(); |
| @Override |
| public void onCapturerStarted(boolean success) { |
| + Logging.d(TAG, "onCapturerStarted: " + success); |
| + |
| synchronized (capturerStartLock) { |
| - captureStartResult = success; |
| - capturerStartLock.notify(); |
| + capturerStartResult = success; |
| + capturerStartLock.notifyAll(); |
| } |
| } |
| @@ -129,14 +133,16 @@ public class VideoCapturerAndroidTestFixtures { |
| @Override |
| public void onOutputFormatRequest(int width, int height, int fps) {} |
| - public boolean WaitForCapturerToStart() throws InterruptedException { |
| + public boolean waitForCapturerToStart() throws InterruptedException { |
| + Logging.d(TAG, "Waiting for the capturer to start"); |
| synchronized (capturerStartLock) { |
| capturerStartLock.wait(); |
| - return captureStartResult; |
| + return capturerStartResult; |
| } |
| } |
| - public int WaitForNextCapturedFrame() throws InterruptedException { |
| + public int waitForNextCapturedFrame() throws InterruptedException { |
| + Logging.d(TAG, "Waiting for the next captured frame"); |
| synchronized (frameLock) { |
| frameLock.wait(); |
| return framesCaptured; |
| @@ -171,7 +177,7 @@ public class VideoCapturerAndroidTestFixtures { |
| } |
| static class CameraEvents implements |
| - VideoCapturerAndroid.CameraEventsHandler { |
| + CameraVideoCapturer.CameraEventsHandler { |
| public boolean onCameraOpeningCalled; |
| public boolean onFirstFrameAvailableCalled; |
| public final Object onCameraFreezedLock = new Object(); |
| @@ -202,7 +208,8 @@ public class VideoCapturerAndroidTestFixtures { |
| @Override |
| public void onCameraClosed() { } |
| - public String WaitForCameraFreezed() throws InterruptedException { |
| + public String waitForCameraFreezed() throws InterruptedException { |
| + Logging.d(TAG, "Waiting for the camera to freeze"); |
| synchronized (onCameraFreezedLock) { |
| onCameraFreezedLock.wait(); |
| return onCameraFreezedDescription; |
| @@ -210,45 +217,193 @@ public class VideoCapturerAndroidTestFixtures { |
| } |
| } |
| - static public CameraEvents createCameraEvents() { |
| - return new CameraEvents(); |
| + /** |
| + * Class to collect all classes related to single capturer instance. |
| + */ |
| + static private class CapturerInstance { |
| + public CameraVideoCapturer capturer; |
| + public CameraEvents cameraEvents; |
| + public SurfaceTextureHelper surfaceTextureHelper; |
| + public FakeCapturerObserver observer; |
| + public List<CaptureFormat> supportedFormats; |
| + public CaptureFormat format; |
| } |
| - // Return true if the device under test have at least two cameras. |
| - @SuppressWarnings("deprecation") |
| - static public boolean HaveTwoCameras() { |
| - return (android.hardware.Camera.getNumberOfCameras() >= 2); |
| + /** |
| + * Class used for collecting a VideoSource, a VideoTrack and a renderer. The class |
| + * is used for testing local rendering from a capturer. |
| + */ |
| + static private class VideoTrackWithRenderer { |
| + public VideoSource source; |
| + public VideoTrack track; |
| + public RendererCallbacks rendererCallbacks; |
| + public FakeAsyncRenderer fakeAsyncRenderer; |
| } |
| - static public void release(VideoCapturerAndroid capturer) { |
| - assertNotNull(capturer); |
| - capturer.dispose(); |
| + public interface TestObjectFactory { |
| + CameraVideoCapturer createCapturer( |
| + String name, CameraVideoCapturer.CameraEventsHandler eventsHandler); |
| + String getNameOfFrontFacingDevice(); |
| + String getNameOfBackFacingDevice(); |
| + boolean haveTwoCameras(); |
| + boolean isCapturingToTexture(); |
| + Context getAppContext(); |
| + |
| + // CameraVideoCapturer API is too slow for some of our tests where we need to open a competing |
| + // camera. These methods are used instead. |
| + Object rawOpenCamera(String cameraId); |
| + void rawCloseCamera(Object camera); |
| } |
| - static public void startCapturerAndRender(VideoCapturerAndroid capturer) |
| - throws InterruptedException { |
| - PeerConnectionFactory factory = new PeerConnectionFactory(null /* options */); |
| - VideoSource source = |
| - factory.createVideoSource(capturer, new MediaConstraints()); |
| - VideoTrack track = factory.createVideoTrack("dummy", source); |
| - RendererCallbacks callbacks = new RendererCallbacks(); |
| - track.addRenderer(new VideoRenderer(callbacks)); |
| - assertTrue(callbacks.WaitForNextFrameToRender() > 0); |
| - track.dispose(); |
| - source.dispose(); |
| - factory.dispose(); |
| - } |
| - |
| - static public void switchCamera(VideoCapturerAndroid capturer) throws InterruptedException { |
| - PeerConnectionFactory factory = new PeerConnectionFactory(null /* options */); |
| - VideoSource source = |
| - factory.createVideoSource(capturer, new MediaConstraints()); |
| - VideoTrack track = factory.createVideoTrack("dummy", source); |
| + private PeerConnectionFactory peerConnectionFactory; |
| + private TestObjectFactory testObjectFactory; |
| + |
| + CameraVideoCapturerTestFixtures(TestObjectFactory testObjectFactory) { |
| + PeerConnectionFactory.initializeAndroidGlobals( |
| + testObjectFactory.getAppContext(), true, true, true); |
| + |
| + this.peerConnectionFactory = new PeerConnectionFactory(null /* options */); |
| + this.testObjectFactory = testObjectFactory; |
| + } |
| + |
| + public void dispose() { |
| + this.peerConnectionFactory.dispose(); |
| + } |
| + |
| + // Internal helper methods |
| + private CapturerInstance createCapturer(String name) { |
| + CapturerInstance instance = new CapturerInstance(); |
| + instance.cameraEvents = new CameraEvents(); |
| + instance.capturer = testObjectFactory.createCapturer(name, instance.cameraEvents); |
| + instance.surfaceTextureHelper = SurfaceTextureHelper.create( |
| + "SurfaceTextureHelper test" /* threadName */, null /* sharedContext */); |
| + instance.observer = new FakeCapturerObserver(); |
| + instance.supportedFormats = instance.capturer.getSupportedFormats(); |
| + return instance; |
| + } |
| + |
| + private CapturerInstance createCapturer() { |
| + return createCapturer(""); |
| + } |
| + |
| + private void startCapture(CapturerInstance instance) { |
| + startCapture(instance, 0); |
| + } |
| + |
| + private void startCapture(CapturerInstance instance, int formatIndex) { |
| + final CameraEnumerationAndroid.CaptureFormat format = |
| + instance.supportedFormats.get(formatIndex); |
| + |
| + instance.capturer.startCapture(format.width, format.height, format.framerate.max, |
| + instance.surfaceTextureHelper, testObjectFactory.getAppContext(), instance.observer); |
| + instance.format = format; |
| + } |
| + |
| + private void disposeCapturer(CapturerInstance instance) { |
| + instance.capturer.dispose(); |
| + instance.surfaceTextureHelper.returnTextureFrame(); |
| + instance.surfaceTextureHelper.dispose(); |
| + } |
| + |
| + private VideoTrackWithRenderer createVideoTrackWithRenderer(CameraVideoCapturer capturer, |
| + VideoRenderer.Callbacks rendererCallbacks) { |
| + VideoTrackWithRenderer videoTrackWithRenderer = new VideoTrackWithRenderer(); |
| + videoTrackWithRenderer.source = |
| + peerConnectionFactory.createVideoSource(capturer, new MediaConstraints()); |
| + videoTrackWithRenderer.track = |
| + peerConnectionFactory.createVideoTrack("dummy", videoTrackWithRenderer.source); |
| + videoTrackWithRenderer.track.addRenderer(new VideoRenderer(rendererCallbacks)); |
| + return videoTrackWithRenderer; |
| + } |
| + |
| + private VideoTrackWithRenderer createVideoTrackWithRenderer(CameraVideoCapturer capturer) { |
| + RendererCallbacks rendererCallbacks = new RendererCallbacks(); |
| + VideoTrackWithRenderer videoTrackWithRenderer = |
| + createVideoTrackWithRenderer(capturer, rendererCallbacks); |
| + videoTrackWithRenderer.rendererCallbacks = rendererCallbacks; |
| + return videoTrackWithRenderer; |
| + } |
| + |
| + private VideoTrackWithRenderer createVideoTrackWithFakeAsyncRenderer( |
| + CameraVideoCapturer capturer) { |
| + FakeAsyncRenderer fakeAsyncRenderer = new FakeAsyncRenderer(); |
| + VideoTrackWithRenderer videoTrackWithRenderer = |
| + createVideoTrackWithRenderer(capturer, fakeAsyncRenderer); |
| + videoTrackWithRenderer.fakeAsyncRenderer = fakeAsyncRenderer; |
| + return videoTrackWithRenderer; |
| + } |
| + |
| + private void disposeVideoTrackWithRenderer(VideoTrackWithRenderer videoTrackWithRenderer) { |
| + videoTrackWithRenderer.track.dispose(); |
| + videoTrackWithRenderer.source.dispose(); |
| + } |
| + |
| + private void waitUntilIdle(CapturerInstance capturerInstance) throws InterruptedException { |
| + final CountDownLatch barrier = new CountDownLatch(1); |
| + capturerInstance.surfaceTextureHelper.getHandler().post(new Runnable() { |
| + @Override public void run() { |
| + barrier.countDown(); |
| + } |
| + }); |
| + barrier.await(); |
| + } |
| + |
| + private void createCapturerAndRender(String name) throws InterruptedException { |
| + if (name == null) { |
| + Logging.w(TAG, "Skipping video capturer test because device name is null."); |
| + return; |
| + } |
| + |
| + final CapturerInstance capturerInstance = createCapturer(name); |
| + final VideoTrackWithRenderer videoTrackWithRenderer = |
| + createVideoTrackWithRenderer(capturerInstance.capturer); |
| + assertTrue(videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender() > 0); |
| + disposeVideoTrackWithRenderer(videoTrackWithRenderer); |
| + disposeCapturer(capturerInstance); |
| + } |
| + |
| + // Test methods |
| + public void createCapturerAndDispose() { |
| + disposeCapturer(createCapturer()); |
| + } |
| + |
| + public void createNonExistingCamera() { |
| + try { |
| + disposeCapturer(createCapturer("non-existing camera")); |
| + } catch (IllegalArgumentException e) { |
| + return; |
| + } |
| + |
| + fail("Expected illegal argument exception when creating non-existing camera."); |
| + } |
| + |
| + public void createCapturerAndRender() throws InterruptedException { |
| + createCapturerAndRender(""); |
| + } |
| + |
| + public void createFrontFacingCapturerAndRender() throws InterruptedException { |
| + createCapturerAndRender(testObjectFactory.getNameOfFrontFacingDevice()); |
| + } |
| + |
| + public void createBackFacingCapturerAndRender() throws InterruptedException { |
| + createCapturerAndRender(testObjectFactory.getNameOfBackFacingDevice()); |
| + } |
| + |
| + public void switchCamera() throws InterruptedException { |
| + if (!testObjectFactory.haveTwoCameras()) { |
| + Logging.w(TAG, |
| + "Skipping test switch video capturer because the device doesn't have two cameras."); |
| + return; |
| + } |
| + |
| + final CapturerInstance capturerInstance = createCapturer(); |
| + final VideoTrackWithRenderer videoTrackWithRenderer = |
| + createVideoTrackWithRenderer(capturerInstance.capturer); |
| // Array with one element to avoid final problem in nested classes. |
| final boolean[] cameraSwitchSuccessful = new boolean[1]; |
| final CountDownLatch barrier = new CountDownLatch(1); |
| - capturer.switchCamera(new VideoCapturerAndroid.CameraSwitchHandler() { |
| + capturerInstance.capturer.switchCamera(new CameraVideoCapturer.CameraSwitchHandler() { |
| @Override |
| public void onCameraSwitchDone(boolean isFrontCamera) { |
| cameraSwitchSuccessful[0] = true; |
| @@ -264,265 +419,134 @@ public class VideoCapturerAndroidTestFixtures { |
| barrier.await(); |
| // Check result. |
| - if (HaveTwoCameras()) { |
| - assertTrue(cameraSwitchSuccessful[0]); |
| - } else { |
| - assertFalse(cameraSwitchSuccessful[0]); |
| - } |
| + assertTrue(cameraSwitchSuccessful[0]); |
| // Ensure that frames are received. |
| - RendererCallbacks callbacks = new RendererCallbacks(); |
| - track.addRenderer(new VideoRenderer(callbacks)); |
| - assertTrue(callbacks.WaitForNextFrameToRender() > 0); |
| - track.dispose(); |
| - source.dispose(); |
| - factory.dispose(); |
| + assertTrue(videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender() > 0); |
| + disposeVideoTrackWithRenderer(videoTrackWithRenderer); |
| + disposeCapturer(capturerInstance); |
| } |
| - static public void cameraEventsInvoked(VideoCapturerAndroid capturer, CameraEvents events, |
| - Context appContext) throws InterruptedException { |
| - final List<CaptureFormat> formats = capturer.getSupportedFormats(); |
| - final CameraEnumerationAndroid.CaptureFormat format = formats.get(0); |
| - |
| - final SurfaceTextureHelper surfaceTextureHelper = SurfaceTextureHelper.create( |
| - "SurfaceTextureHelper test" /* threadName */, null /* sharedContext */); |
| - final FakeCapturerObserver observer = new FakeCapturerObserver(); |
| - capturer.startCapture(format.width, format.height, format.framerate.max, |
| - surfaceTextureHelper, appContext, observer); |
| + public void cameraEventsInvoked() throws InterruptedException { |
| + final CapturerInstance capturerInstance = createCapturer(); |
| + startCapture(capturerInstance); |
| // Make sure camera is started and first frame is received and then stop it. |
| - assertTrue(observer.WaitForCapturerToStart()); |
| - observer.WaitForNextCapturedFrame(); |
| - capturer.stopCapture(); |
| - if (capturer.isCapturingToTexture()) { |
| - surfaceTextureHelper.returnTextureFrame(); |
| - } |
| - release(capturer); |
| - surfaceTextureHelper.dispose(); |
| + assertTrue(capturerInstance.observer.waitForCapturerToStart()); |
| + capturerInstance.observer.waitForNextCapturedFrame(); |
| + capturerInstance.capturer.stopCapture(); |
| + disposeCapturer(capturerInstance); |
| - assertTrue(events.onCameraOpeningCalled); |
| - assertTrue(events.onFirstFrameAvailableCalled); |
| + assertTrue(capturerInstance.cameraEvents.onCameraOpeningCalled); |
| + assertTrue(capturerInstance.cameraEvents.onFirstFrameAvailableCalled); |
| } |
| - static public void cameraCallsAfterStop( |
| - VideoCapturerAndroid capturer, Context appContext) throws InterruptedException { |
| - final List<CaptureFormat> formats = capturer.getSupportedFormats(); |
| - final CameraEnumerationAndroid.CaptureFormat format = formats.get(0); |
| - |
| - final SurfaceTextureHelper surfaceTextureHelper = SurfaceTextureHelper.create( |
| - "SurfaceTextureHelper test" /* threadName */, null /* sharedContext */); |
| - final FakeCapturerObserver observer = new FakeCapturerObserver(); |
| - capturer.startCapture(format.width, format.height, format.framerate.max, |
| - surfaceTextureHelper, appContext, observer); |
| + public void cameraCallsAfterStop() throws InterruptedException { |
| + final CapturerInstance capturerInstance = createCapturer(); |
| + startCapture(capturerInstance); |
| // Make sure camera is started and then stop it. |
| - assertTrue(observer.WaitForCapturerToStart()); |
| - capturer.stopCapture(); |
| - if (capturer.isCapturingToTexture()) { |
| - surfaceTextureHelper.returnTextureFrame(); |
| - } |
| + assertTrue(capturerInstance.observer.waitForCapturerToStart()); |
| + capturerInstance.capturer.stopCapture(); |
| + capturerInstance.surfaceTextureHelper.returnTextureFrame(); |
| // We can't change |capturer| at this point, but we should not crash. |
| - capturer.switchCamera(null); |
| - capturer.onOutputFormatRequest(640, 480, 15); |
| - capturer.changeCaptureFormat(640, 480, 15); |
| + capturerInstance.capturer.switchCamera(null /* switchEventsHandler */); |
| + capturerInstance.capturer.onOutputFormatRequest(640, 480, 15); |
| + capturerInstance.capturer.changeCaptureFormat(640, 480, 15); |
| - release(capturer); |
| - surfaceTextureHelper.dispose(); |
| + disposeCapturer(capturerInstance); |
| } |
| - static public void stopRestartVideoSource(VideoCapturerAndroid capturer) |
| - throws InterruptedException { |
| - PeerConnectionFactory factory = new PeerConnectionFactory(null /* options */); |
| - VideoSource source = |
| - factory.createVideoSource(capturer, new MediaConstraints()); |
| - VideoTrack track = factory.createVideoTrack("dummy", source); |
| - RendererCallbacks callbacks = new RendererCallbacks(); |
| - track.addRenderer(new VideoRenderer(callbacks)); |
| - assertTrue(callbacks.WaitForNextFrameToRender() > 0); |
| - assertEquals(MediaSource.State.LIVE, source.state()); |
| - |
| - source.stop(); |
| - assertEquals(MediaSource.State.ENDED, source.state()); |
| - |
| - source.restart(); |
| - assertTrue(callbacks.WaitForNextFrameToRender() > 0); |
| - assertEquals(MediaSource.State.LIVE, source.state()); |
| - track.dispose(); |
| - source.dispose(); |
| - factory.dispose(); |
| - } |
| - |
| - static public void startStopWithDifferentResolutions(VideoCapturerAndroid capturer, |
| - Context appContext) throws InterruptedException { |
| - final SurfaceTextureHelper surfaceTextureHelper = SurfaceTextureHelper.create( |
| - "SurfaceTextureHelper test" /* threadName */, null /* sharedContext */); |
| - FakeCapturerObserver observer = new FakeCapturerObserver(); |
| - List<CaptureFormat> formats = capturer.getSupportedFormats(); |
| + public void stopRestartVideoSource() throws InterruptedException { |
| + final CapturerInstance capturerInstance = createCapturer(); |
| + final VideoTrackWithRenderer videoTrackWithRenderer = |
| + createVideoTrackWithRenderer(capturerInstance.capturer); |
| + |
| + assertTrue(videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender() > 0); |
| + assertEquals(MediaSource.State.LIVE, videoTrackWithRenderer.source.state()); |
| + |
| + videoTrackWithRenderer.source.stop(); |
| + assertEquals(MediaSource.State.ENDED, videoTrackWithRenderer.source.state()); |
| + |
| + videoTrackWithRenderer.source.restart(); |
| + assertTrue(videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender() > 0); |
| + assertEquals(MediaSource.State.LIVE, videoTrackWithRenderer.source.state()); |
| + |
| + disposeVideoTrackWithRenderer(videoTrackWithRenderer); |
| + disposeCapturer(capturerInstance); |
| + } |
| + |
| + public void startStopWithDifferentResolutions() throws InterruptedException { |
| + final CapturerInstance capturerInstance = createCapturer(); |
| for(int i = 0; i < 3 ; ++i) { |
| - CameraEnumerationAndroid.CaptureFormat format = formats.get(i); |
| - capturer.startCapture(format.width, format.height, format.framerate.max, |
| - surfaceTextureHelper, appContext, observer); |
| - assertTrue(observer.WaitForCapturerToStart()); |
| - observer.WaitForNextCapturedFrame(); |
| + startCapture(capturerInstance, i); |
| + assertTrue(capturerInstance.observer.waitForCapturerToStart()); |
| + capturerInstance.observer.waitForNextCapturedFrame(); |
| // Check the frame size. The actual width and height depend on how the capturer is mounted. |
| - final boolean identicalResolution = (observer.frameWidth() == format.width |
| - && observer.frameHeight() == format.height); |
| - final boolean flippedResolution = (observer.frameWidth() == format.height |
| - && observer.frameHeight() == format.width); |
| + final boolean identicalResolution = ( |
| + capturerInstance.observer.frameWidth() == capturerInstance.format.width |
| + && capturerInstance.observer.frameHeight() == capturerInstance.format.height); |
| + final boolean flippedResolution = ( |
| + capturerInstance.observer.frameWidth() == capturerInstance.format.height |
| + && capturerInstance.observer.frameHeight() == capturerInstance.format.width); |
| if (!identicalResolution && !flippedResolution) { |
| - fail("Wrong resolution, got: " + observer.frameWidth() + "x" + observer.frameHeight() |
| - + " expected: " + format.width + "x" + format.height + " or " + format.height + "x" |
| - + format.width); |
| + fail("Wrong resolution, got: " |
| + + capturerInstance.observer.frameWidth() + "x" + capturerInstance.observer.frameHeight() |
| + + " expected: "+ capturerInstance.format.width + "x" + capturerInstance.format.height |
| + + " or " + capturerInstance.format.height + "x" + capturerInstance.format.width); |
| } |
| - if (capturer.isCapturingToTexture()) { |
| - assertEquals(0, observer.frameSize()); |
| + if (testObjectFactory.isCapturingToTexture()) { |
| + assertEquals(0, capturerInstance.observer.frameSize()); |
| } else { |
| - assertTrue(format.frameSize() <= observer.frameSize()); |
| - } |
| - capturer.stopCapture(); |
| - if (capturer.isCapturingToTexture()) { |
| - surfaceTextureHelper.returnTextureFrame(); |
| + assertTrue(capturerInstance.format.frameSize() <= capturerInstance.observer.frameSize()); |
| } |
| + capturerInstance.capturer.stopCapture(); |
| + capturerInstance.surfaceTextureHelper.returnTextureFrame(); |
| } |
| - release(capturer); |
| - surfaceTextureHelper.dispose(); |
| + disposeCapturer(capturerInstance); |
| } |
| - static void waitUntilIdle(VideoCapturerAndroid capturer) throws InterruptedException { |
| - final CountDownLatch barrier = new CountDownLatch(1); |
| - capturer.getCameraThreadHandler().post(new Runnable() { |
| - @Override public void run() { |
| - barrier.countDown(); |
| - } |
| - }); |
| - barrier.await(); |
| - } |
| - |
| - static public void startWhileCameraIsAlreadyOpen( |
| - VideoCapturerAndroid capturer, Context appContext) throws InterruptedException { |
| - final List<CaptureFormat> formats = capturer.getSupportedFormats(); |
| - final CameraEnumerationAndroid.CaptureFormat format = formats.get(0); |
| - android.hardware.Camera camera = android.hardware.Camera.open(capturer.getCurrentCameraId()); |
| - |
| - final SurfaceTextureHelper surfaceTextureHelper = SurfaceTextureHelper.create( |
| - "SurfaceTextureHelper test" /* threadName */, null /* sharedContext */); |
| - final FakeCapturerObserver observer = new FakeCapturerObserver(); |
| - capturer.startCapture(format.width, format.height, format.framerate.max, |
| - surfaceTextureHelper, appContext, observer); |
| - |
| - if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.LOLLIPOP_MR1) { |
| - // The first opened camera client will be evicted. |
| - assertTrue(observer.WaitForCapturerToStart()); |
| - capturer.stopCapture(); |
| - } else { |
| - assertFalse(observer.WaitForCapturerToStart()); |
| - } |
| + public void returnBufferLate() throws InterruptedException { |
| + final CapturerInstance capturerInstance = createCapturer(); |
| + startCapture(capturerInstance); |
| + assertTrue(capturerInstance.observer.waitForCapturerToStart()); |
| - release(capturer); |
| - camera.release(); |
| - surfaceTextureHelper.dispose(); |
| - } |
| - |
| - static public void startWhileCameraIsAlreadyOpenAndCloseCamera( |
| - VideoCapturerAndroid capturer, Context appContext) throws InterruptedException { |
| - final PeerConnectionFactory factory = new PeerConnectionFactory(null /* options */); |
| - final List<CaptureFormat> formats = capturer.getSupportedFormats(); |
| - final CameraEnumerationAndroid.CaptureFormat format = formats.get(0); |
| - android.hardware.Camera camera = android.hardware.Camera.open(capturer.getCurrentCameraId()); |
| - |
| - final SurfaceTextureHelper surfaceTextureHelper = SurfaceTextureHelper.create( |
| - "SurfaceTextureHelper test" /* threadName */, null /* sharedContext */); |
| - final VideoSource source = factory.createVideoSource(capturer, new MediaConstraints()); |
| - final VideoTrack track = factory.createVideoTrack("dummy", source); |
| - final RendererCallbacks callbacks = new RendererCallbacks(); |
| - track.addRenderer(new VideoRenderer(callbacks)); |
| - waitUntilIdle(capturer); |
| - |
| - camera.release(); |
| - |
| - // Make sure camera is started and first frame is received and then stop it. |
| - callbacks.WaitForNextFrameToRender(); |
| - capturer.stopCapture(); |
| - release(capturer); |
| - surfaceTextureHelper.dispose(); |
| - } |
| - |
| - static public void startWhileCameraIsAlreadyOpenAndStop( |
| - VideoCapturerAndroid capturer, Context appContext) throws InterruptedException { |
| - final List<CaptureFormat> formats = capturer.getSupportedFormats(); |
| - final CameraEnumerationAndroid.CaptureFormat format = formats.get(0); |
| - android.hardware.Camera camera = android.hardware.Camera.open(capturer.getCurrentCameraId()); |
| - |
| - final SurfaceTextureHelper surfaceTextureHelper = SurfaceTextureHelper.create( |
| - "SurfaceTextureHelper test" /* threadName */, null /* sharedContext */); |
| - final FakeCapturerObserver observer = new FakeCapturerObserver(); |
| - capturer.startCapture(format.width, format.height, format.framerate.max, |
| - surfaceTextureHelper, appContext, observer); |
| - capturer.stopCapture(); |
| - release(capturer); |
| - camera.release(); |
| - surfaceTextureHelper.dispose(); |
| - } |
| - |
| - static public void returnBufferLate(VideoCapturerAndroid capturer, |
| - Context appContext) throws InterruptedException { |
| - final SurfaceTextureHelper surfaceTextureHelper = SurfaceTextureHelper.create( |
| - "SurfaceTextureHelper test" /* threadName */, null /* sharedContext */); |
| - FakeCapturerObserver observer = new FakeCapturerObserver(); |
| - |
| - List<CaptureFormat> formats = capturer.getSupportedFormats(); |
| - CameraEnumerationAndroid.CaptureFormat format = formats.get(0); |
| - capturer.startCapture(format.width, format.height, format.framerate.max, |
| - surfaceTextureHelper, appContext, observer); |
| - assertTrue(observer.WaitForCapturerToStart()); |
| - |
| - observer.WaitForNextCapturedFrame(); |
| - capturer.stopCapture(); |
| - List<Long> listOftimestamps = observer.getCopyAndResetListOftimeStamps(); |
| + capturerInstance.observer.waitForNextCapturedFrame(); |
| + capturerInstance.capturer.stopCapture(); |
| + List<Long> listOftimestamps = capturerInstance.observer.getCopyAndResetListOftimeStamps(); |
| assertTrue(listOftimestamps.size() >= 1); |
| - format = formats.get(1); |
| - capturer.startCapture(format.width, format.height, format.framerate.max, |
| - surfaceTextureHelper, appContext, observer); |
| - observer.WaitForCapturerToStart(); |
| - if (capturer.isCapturingToTexture()) { |
| - surfaceTextureHelper.returnTextureFrame(); |
| - } |
| + startCapture(capturerInstance, 1); |
| + capturerInstance.observer.waitForCapturerToStart(); |
| + capturerInstance.surfaceTextureHelper.returnTextureFrame(); |
| - observer.WaitForNextCapturedFrame(); |
| - capturer.stopCapture(); |
| + capturerInstance.observer.waitForNextCapturedFrame(); |
| + capturerInstance.capturer.stopCapture(); |
| - listOftimestamps = observer.getCopyAndResetListOftimeStamps(); |
| + listOftimestamps = capturerInstance.observer.getCopyAndResetListOftimeStamps(); |
| assertTrue(listOftimestamps.size() >= 1); |
| - if (capturer.isCapturingToTexture()) { |
| - surfaceTextureHelper.returnTextureFrame(); |
| - } |
| - release(capturer); |
| - surfaceTextureHelper.dispose(); |
| + disposeCapturer(capturerInstance); |
| } |
| - static public void returnBufferLateEndToEnd(VideoCapturerAndroid capturer) |
| + public void returnBufferLateEndToEnd() |
| throws InterruptedException { |
| - final PeerConnectionFactory factory = new PeerConnectionFactory(null /* options */); |
| - final VideoSource source = factory.createVideoSource(capturer, new MediaConstraints()); |
| - final VideoTrack track = factory.createVideoTrack("dummy", source); |
| - final FakeAsyncRenderer renderer = new FakeAsyncRenderer(); |
| - |
| - track.addRenderer(new VideoRenderer(renderer)); |
| + final CapturerInstance capturerInstance = createCapturer(); |
| + final VideoTrackWithRenderer videoTrackWithRenderer = |
| + createVideoTrackWithFakeAsyncRenderer(capturerInstance.capturer); |
| // Wait for at least one frame that has not been returned. |
| - assertFalse(renderer.waitForPendingFrames().isEmpty()); |
| + assertFalse(videoTrackWithRenderer.fakeAsyncRenderer.waitForPendingFrames().isEmpty()); |
| - capturer.stopCapture(); |
| + capturerInstance.capturer.stopCapture(); |
| // Dispose everything. |
| - track.dispose(); |
| - source.dispose(); |
| - factory.dispose(); |
| + disposeVideoTrackWithRenderer(videoTrackWithRenderer); |
| + disposeCapturer(capturerInstance); |
| // Return the frame(s), on a different thread out of spite. |
| - final List<I420Frame> pendingFrames = renderer.waitForPendingFrames(); |
| + final List<I420Frame> pendingFrames = |
| + videoTrackWithRenderer.fakeAsyncRenderer.waitForPendingFrames(); |
| final Thread returnThread = new Thread(new Runnable() { |
| @Override |
| public void run() { |
| @@ -535,70 +559,104 @@ public class VideoCapturerAndroidTestFixtures { |
| returnThread.join(); |
| } |
| - static public void cameraFreezedEventOnBufferStarvationUsingTextures( |
| - VideoCapturerAndroid capturer, |
| - CameraEvents events, Context appContext) throws InterruptedException { |
| - assertTrue("Not capturing to textures.", capturer.isCapturingToTexture()); |
| - |
| - final List<CaptureFormat> formats = capturer.getSupportedFormats(); |
| - final CameraEnumerationAndroid.CaptureFormat format = formats.get(0); |
| - |
| - final SurfaceTextureHelper surfaceTextureHelper = SurfaceTextureHelper.create( |
| - "SurfaceTextureHelper test" /* threadName */, null /* sharedContext */); |
| - final FakeCapturerObserver observer = new FakeCapturerObserver(); |
| - capturer.startCapture(format.width, format.height, format.framerate.max, |
| - surfaceTextureHelper, appContext, observer); |
| + public void cameraFreezedEventOnBufferStarvation() throws InterruptedException { |
| + final CapturerInstance capturerInstance = createCapturer(); |
| + startCapture(capturerInstance); |
| // Make sure camera is started. |
| - assertTrue(observer.WaitForCapturerToStart()); |
| + assertTrue(capturerInstance.observer.waitForCapturerToStart()); |
| // Since we don't return the buffer, we should get a starvation message if we are |
| // capturing to a texture. |
| assertEquals("Camera failure. Client must return video buffers.", |
| - events.WaitForCameraFreezed()); |
| - |
| - capturer.stopCapture(); |
| - if (capturer.isCapturingToTexture()) { |
| - surfaceTextureHelper.returnTextureFrame(); |
| - } |
| + capturerInstance.cameraEvents.waitForCameraFreezed()); |
| - release(capturer); |
| - surfaceTextureHelper.dispose(); |
| + capturerInstance.capturer.stopCapture(); |
| + disposeCapturer(capturerInstance); |
| } |
| - static public void scaleCameraOutput(VideoCapturerAndroid capturer) throws InterruptedException { |
| - PeerConnectionFactory factory = new PeerConnectionFactory(null /* options */); |
| - VideoSource source = |
| - factory.createVideoSource(capturer, new MediaConstraints()); |
| - VideoTrack track = factory.createVideoTrack("dummy", source); |
| - RendererCallbacks renderer = new RendererCallbacks(); |
| - track.addRenderer(new VideoRenderer(renderer)); |
| - assertTrue(renderer.WaitForNextFrameToRender() > 0); |
| + public void scaleCameraOutput() throws InterruptedException { |
| + final CapturerInstance capturerInstance = createCapturer(); |
| + final VideoTrackWithRenderer videoTrackWithRenderer = |
| + createVideoTrackWithRenderer(capturerInstance.capturer); |
| + assertTrue(videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender() > 0); |
| - final int startWidth = renderer.frameWidth(); |
| - final int startHeight = renderer.frameHeight(); |
| + final int startWidth = videoTrackWithRenderer.rendererCallbacks.frameWidth(); |
| + final int startHeight = videoTrackWithRenderer.rendererCallbacks.frameHeight(); |
| final int frameRate = 30; |
| final int scaledWidth = startWidth / 2; |
| final int scaledHeight = startHeight / 2; |
| // Request the captured frames to be scaled. |
| - capturer.onOutputFormatRequest(scaledWidth, scaledHeight, frameRate); |
| + capturerInstance.capturer.onOutputFormatRequest(scaledWidth, scaledHeight, frameRate); |
| boolean gotExpectedResolution = false; |
| int numberOfInspectedFrames = 0; |
| do { |
| - renderer.WaitForNextFrameToRender(); |
| + videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender(); |
| ++numberOfInspectedFrames; |
| - gotExpectedResolution = (renderer.frameWidth() == scaledWidth |
| - && renderer.frameHeight() == scaledHeight); |
| + gotExpectedResolution = (videoTrackWithRenderer.rendererCallbacks.frameWidth() == scaledWidth |
| + && videoTrackWithRenderer.rendererCallbacks.frameHeight() == scaledHeight); |
| } while (!gotExpectedResolution && numberOfInspectedFrames < 30); |
| - source.stop(); |
| - track.dispose(); |
| - source.dispose(); |
| - factory.dispose(); |
| + disposeVideoTrackWithRenderer(videoTrackWithRenderer); |
| + disposeCapturer(capturerInstance); |
| assertTrue(gotExpectedResolution); |
| } |
| + public void startWhileCameraIsAlreadyOpen() throws InterruptedException { |
| + final CapturerInstance capturerInstance = createCapturer(); |
| + final Object competingCamera = testObjectFactory.rawOpenCamera( |
|
perkj_webrtc
2016/06/14 06:02:35
I think this should be done in the other order. Th
sakal
2016/06/14 08:40:55
Camera is not actually opened on createCapturer. T
|
| + capturerInstance.capturer.getCurrentCameraId()); |
| + |
| + startCapture(capturerInstance); |
| + |
| + if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.LOLLIPOP_MR1) { |
| + // The first opened camera client will be evicted. |
| + assertTrue(capturerInstance.observer.waitForCapturerToStart()); |
| + capturerInstance.capturer.stopCapture(); |
| + } else { |
| + assertFalse(capturerInstance.observer.waitForCapturerToStart()); |
| + } |
| + |
| + testObjectFactory.rawCloseCamera(competingCamera); |
| + disposeCapturer(capturerInstance); |
| + } |
| + |
| + public void startWhileCameraIsAlreadyOpenAndCloseCamera() throws InterruptedException { |
| + final CapturerInstance capturerInstance = createCapturer(); |
| + |
| + Logging.d(TAG, "startWhileCameraIsAlreadyOpenAndCloseCamera: Opening competing camera."); |
| + final Object competingCamera = testObjectFactory.rawOpenCamera( |
| + capturerInstance.capturer.getCurrentCameraId()); |
| + |
| + Logging.d(TAG, "startWhileCameraIsAlreadyOpenAndCloseCamera: Opening camera."); |
| + final VideoTrackWithRenderer videoTrackWithRenderer = |
| + createVideoTrackWithRenderer(capturerInstance.capturer); |
| + waitUntilIdle(capturerInstance); |
| + |
| + Logging.d(TAG, "startWhileCameraIsAlreadyOpenAndCloseCamera: Closing competing camera."); |
| + testObjectFactory.rawCloseCamera(competingCamera); |
| + |
| + // Make sure camera is started and first frame is received and then stop it. |
| + Logging.d(TAG, "startWhileCameraIsAlreadyOpenAndCloseCamera: Waiting for capture to start."); |
| + videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender(); |
| + Logging.d(TAG, "startWhileCameraIsAlreadyOpenAndCloseCamera: Stopping capture."); |
| + capturerInstance.capturer.stopCapture(); |
| + disposeCapturer(capturerInstance); |
| + } |
| + |
| + public void startWhileCameraIsAlreadyOpenAndStop() throws InterruptedException { |
| + final CapturerInstance capturerInstance = createCapturer(); |
| + final Object competingCamera = testObjectFactory.rawOpenCamera( |
| + capturerInstance.capturer.getCurrentCameraId()); |
| + |
| + startCapture(capturerInstance); |
| + |
| + capturerInstance.capturer.stopCapture(); |
| + disposeCapturer(capturerInstance); |
| + |
| + testObjectFactory.rawCloseCamera(competingCamera); |
| + } |
| } |