OLD | NEW |
---|---|
1 /* | 1 /* |
2 * libjingle | 2 * libjingle |
3 * Copyright 2015 Google Inc. | 3 * Copyright 2015 Google Inc. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
(...skipping 20 matching lines...) Expand all Loading... | |
31 import android.test.suitebuilder.annotation.SmallTest; | 31 import android.test.suitebuilder.annotation.SmallTest; |
32 import android.util.Size; | 32 import android.util.Size; |
33 | 33 |
34 import org.webrtc.CameraEnumerationAndroid.CaptureFormat; | 34 import org.webrtc.CameraEnumerationAndroid.CaptureFormat; |
35 import org.webrtc.VideoRenderer.I420Frame; | 35 import org.webrtc.VideoRenderer.I420Frame; |
36 | 36 |
37 import java.util.ArrayList; | 37 import java.util.ArrayList; |
38 import java.util.HashSet; | 38 import java.util.HashSet; |
39 import java.util.List; | 39 import java.util.List; |
40 import java.util.Set; | 40 import java.util.Set; |
41 import java.util.concurrent.CountDownLatch; | |
41 | 42 |
42 @SuppressWarnings("deprecation") | 43 @SuppressWarnings("deprecation") |
43 public class VideoCapturerAndroidTest extends ActivityTestCase { | 44 public class VideoCapturerAndroidTest extends ActivityTestCase { |
44 static class RendererCallbacks implements VideoRenderer.Callbacks { | 45 static class RendererCallbacks implements VideoRenderer.Callbacks { |
45 private int framesRendered = 0; | 46 private int framesRendered = 0; |
46 private Object frameLock = 0; | 47 private Object frameLock = 0; |
47 | 48 |
48 @Override | 49 @Override |
49 public void renderFrame(I420Frame frame) { | 50 public void renderFrame(I420Frame frame) { |
50 synchronized (frameLock) { | 51 synchronized (frameLock) { |
51 ++framesRendered; | 52 ++framesRendered; |
52 frameLock.notify(); | 53 frameLock.notify(); |
53 } | 54 } |
54 VideoRenderer.renderFrameDone(frame); | 55 VideoRenderer.renderFrameDone(frame); |
55 } | 56 } |
56 | 57 |
57 public int WaitForNextFrameToRender() throws InterruptedException { | 58 public int WaitForNextFrameToRender() throws InterruptedException { |
58 synchronized (frameLock) { | 59 synchronized (frameLock) { |
59 frameLock.wait(); | 60 frameLock.wait(); |
60 return framesRendered; | 61 return framesRendered; |
61 } | 62 } |
62 } | 63 } |
63 } | 64 } |
64 | 65 |
65 static class AsyncRenderer implements VideoRenderer.Callbacks { | |
66 private final List<I420Frame> pendingFrames = new ArrayList<I420Frame>(); | |
67 | |
68 @Override | |
69 public void renderFrame(I420Frame frame) { | |
70 synchronized (pendingFrames) { | |
71 pendingFrames.add(frame); | |
72 pendingFrames.notifyAll(); | |
73 } | |
74 } | |
75 | |
76 // Wait until at least one frame have been received, before returning them. | |
77 public List<I420Frame> WaitForFrames() { | |
78 synchronized (pendingFrames) { | |
79 while (pendingFrames.isEmpty()) { | |
80 try { | |
81 pendingFrames.wait(); | |
82 } catch (InterruptedException e) { | |
83 // Ignore. | |
84 } | |
85 } | |
86 final List<I420Frame> frames = new ArrayList<I420Frame>(pendingFrames); | |
87 pendingFrames.clear(); | |
88 return frames; | |
89 } | |
90 } | |
91 } | |
92 | |
93 static class FakeCapturerObserver implements | 66 static class FakeCapturerObserver implements |
94 VideoCapturerAndroid.CapturerObserver { | 67 VideoCapturerAndroid.CapturerObserver { |
95 private int framesCaptured = 0; | 68 private int framesCaptured = 0; |
96 private int frameSize = 0; | 69 private int frameSize = 0; |
97 private Object frameLock = 0; | 70 private Object frameLock = 0; |
98 private Object capturerStartLock = 0; | 71 private Object capturerStartLock = 0; |
99 private boolean captureStartResult = false; | 72 private boolean captureStartResult = false; |
100 private List<Long> timestamps = new ArrayList<Long>(); | 73 private List<Long> timestamps = new ArrayList<Long>(); |
101 | 74 |
102 @Override | 75 @Override |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
243 // to a Java video renderer using the back facing video capturer. | 216 // to a Java video renderer using the back facing video capturer. |
244 // It tests both the Java and the C++ layer. | 217 // It tests both the Java and the C++ layer. |
245 public void testStartBackFacingVideoCapturer() throws Exception { | 218 public void testStartBackFacingVideoCapturer() throws Exception { |
246 if (!HaveTwoCameras()) { | 219 if (!HaveTwoCameras()) { |
247 return; | 220 return; |
248 } | 221 } |
249 startCapturerAndRender(CameraEnumerationAndroid.getNameOfBackFacingDevice()) ; | 222 startCapturerAndRender(CameraEnumerationAndroid.getNameOfBackFacingDevice()) ; |
250 } | 223 } |
251 | 224 |
252 @SmallTest | 225 @SmallTest |
253 // This test that the default camera can be started and but the camera can | 226 // This test that the default camera can be started and that the camera can |
254 // later be switched to another camera. | 227 // later be switched to another camera. |
255 // It tests both the Java and the C++ layer. | 228 // It tests both the Java and the C++ layer. |
256 public void testSwitchVideoCapturer() throws Exception { | 229 public void testSwitchVideoCapturer() throws Exception { |
257 PeerConnectionFactory factory = new PeerConnectionFactory(); | 230 PeerConnectionFactory factory = new PeerConnectionFactory(); |
258 VideoCapturerAndroid capturer = VideoCapturerAndroid.create("", null); | 231 VideoCapturerAndroid capturer = VideoCapturerAndroid.create("", null); |
259 VideoSource source = | 232 VideoSource source = |
260 factory.createVideoSource(capturer, new MediaConstraints()); | 233 factory.createVideoSource(capturer, new MediaConstraints()); |
261 VideoTrack track = factory.createVideoTrack("dummy", source); | 234 VideoTrack track = factory.createVideoTrack("dummy", source); |
262 | 235 |
263 if (HaveTwoCameras()) | 236 // Array with one element to avoid final problem in nested classes. |
264 assertTrue(capturer.switchCamera(null)); | 237 final boolean[] cameraSwitchSuccessful = new boolean[1]; |
265 else | 238 final CountDownLatch barrier = new CountDownLatch(1); |
266 assertFalse(capturer.switchCamera(null)); | 239 capturer.switchCamera(new VideoCapturerAndroid.CameraSwitchHandler() { |
240 @Override | |
241 public void onCameraSwitchDone(boolean isFrontCamera) { | |
242 cameraSwitchSuccessful[0] = true; | |
243 barrier.countDown(); | |
244 } | |
245 @Override | |
246 public void onCameraSwitchError(String errorDescription) { | |
247 cameraSwitchSuccessful[0] = false; | |
248 barrier.countDown(); | |
249 } | |
250 }); | |
251 // Wait until the camera has been switched. | |
252 barrier.await(); | |
267 | 253 |
268 // Wait until the camera have been switched. | 254 // Check result. |
269 capturer.runCameraThreadUntilIdle(); | 255 if (HaveTwoCameras()) { |
270 | 256 assertTrue(cameraSwitchSuccessful[0]); |
257 } else { | |
258 assertFalse(cameraSwitchSuccessful[0]); | |
259 } | |
271 // Ensure that frames are received. | 260 // Ensure that frames are received. |
272 RendererCallbacks callbacks = new RendererCallbacks(); | 261 RendererCallbacks callbacks = new RendererCallbacks(); |
273 track.addRenderer(new VideoRenderer(callbacks)); | 262 track.addRenderer(new VideoRenderer(callbacks)); |
274 assertTrue(callbacks.WaitForNextFrameToRender() > 0); | 263 assertTrue(callbacks.WaitForNextFrameToRender() > 0); |
275 track.dispose(); | 264 track.dispose(); |
276 source.dispose(); | 265 source.dispose(); |
277 factory.dispose(); | 266 factory.dispose(); |
278 } | 267 } |
279 | 268 |
280 @SmallTest | 269 @SmallTest |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
359 | 348 |
360 observer.WaitForNextCapturedFrame(); | 349 observer.WaitForNextCapturedFrame(); |
361 capturer.stopCapture(); | 350 capturer.stopCapture(); |
362 | 351 |
363 listOftimestamps = observer.getCopyAndResetListOftimeStamps(); | 352 listOftimestamps = observer.getCopyAndResetListOftimeStamps(); |
364 assertTrue(listOftimestamps.size() >= 2); | 353 assertTrue(listOftimestamps.size() >= 2); |
365 for (Long timeStamp : listOftimestamps) { | 354 for (Long timeStamp : listOftimestamps) { |
366 capturer.returnBuffer(timeStamp); | 355 capturer.returnBuffer(timeStamp); |
367 } | 356 } |
368 } | 357 } |
369 | |
370 @SmallTest | |
371 // This test that we can capture frames, stop capturing, keep the frames for r endering, and then | |
372 // return the frames. It tests both the Java and the C++ layer. | |
373 public void testCaptureAndAsyncRender() { | |
374 final VideoCapturerAndroid capturer = VideoCapturerAndroid.create("", null); | |
375 // Helper class that sets everything up, captures at least one frame, and th en shuts | |
376 // everything down. | |
377 class CaptureFramesRunnable implements Runnable { | |
378 public List<I420Frame> frames; | |
379 | |
380 @Override | |
381 public void run() { | |
382 PeerConnectionFactory factory = new PeerConnectionFactory(); | |
383 VideoSource source = factory.createVideoSource(capturer, new MediaConstr aints()); | |
384 VideoTrack track = factory.createVideoTrack("dummy", source); | |
385 AsyncRenderer renderer = new AsyncRenderer(); | |
386 track.addRenderer(new VideoRenderer(renderer)); | |
387 | |
388 // Wait until we get at least one frame. | |
389 frames = renderer.WaitForFrames(); | |
390 | |
391 // Stop everything. | |
392 track.dispose(); | |
393 source.dispose(); | |
394 factory.dispose(); | |
395 } | |
396 } | |
397 | |
398 // Capture frames on a separate thread. | |
399 CaptureFramesRunnable captureFramesRunnable = new CaptureFramesRunnable(); | |
400 Thread captureThread = new Thread(captureFramesRunnable); | |
401 captureThread.start(); | |
402 | |
403 // Wait until frames are captured, and then kill the thread. | |
404 try { | |
405 captureThread.join(); | |
406 } catch (InterruptedException e) { | |
407 fail("Capture thread was interrupted"); | |
408 } | |
409 captureThread = null; | |
410 | |
411 // Assert that we have frames that have not been returned. | |
412 assertTrue(!captureFramesRunnable.frames.isEmpty()); | |
413 // Return the frame(s). | |
414 for (I420Frame frame : captureFramesRunnable.frames) { | |
415 VideoRenderer.renderFrameDone(frame); | |
416 } | |
417 assertEquals(capturer.pendingFramesTimeStamps(), "[]"); | |
418 } | |
hbos
2015/09/18 11:10:52
I'm thinking it might be worth to tweak this test
magjed_webrtc
2015/09/21 08:19:57
Probably true. We have a similar test in testRetur
| |
419 } | 358 } |
OLD | NEW |