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); |
+ } |
} |