| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 2015 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 package org.webrtc; | 10 package org.webrtc; |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 } | 184 } |
| 185 } | 185 } |
| 186 } | 186 } |
| 187 | 187 |
| 188 static class CameraEvents implements | 188 static class CameraEvents implements |
| 189 CameraVideoCapturer.CameraEventsHandler { | 189 CameraVideoCapturer.CameraEventsHandler { |
| 190 public boolean onCameraOpeningCalled; | 190 public boolean onCameraOpeningCalled; |
| 191 public boolean onFirstFrameAvailableCalled; | 191 public boolean onFirstFrameAvailableCalled; |
| 192 public final Object onCameraFreezedLock = new Object(); | 192 public final Object onCameraFreezedLock = new Object(); |
| 193 private String onCameraFreezedDescription; | 193 private String onCameraFreezedDescription; |
| 194 public final Object cameraClosedLock = new Object(); |
| 195 private boolean cameraClosed = true; |
| 194 | 196 |
| 195 @Override | 197 @Override |
| 196 public void onCameraError(String errorDescription) { | 198 public void onCameraError(String errorDescription) { |
| 199 Logging.w(TAG, "Camera error: " + errorDescription); |
| 200 cameraClosed = true; |
| 197 } | 201 } |
| 198 | 202 |
| 199 @Override | 203 @Override |
| 200 public void onCameraFreezed(String errorDescription) { | 204 public void onCameraFreezed(String errorDescription) { |
| 201 synchronized (onCameraFreezedLock) { | 205 synchronized (onCameraFreezedLock) { |
| 202 onCameraFreezedDescription = errorDescription; | 206 onCameraFreezedDescription = errorDescription; |
| 203 onCameraFreezedLock.notifyAll(); | 207 onCameraFreezedLock.notifyAll(); |
| 204 } | 208 } |
| 205 } | 209 } |
| 206 | 210 |
| 207 @Override | 211 @Override |
| 208 public void onCameraOpening(int cameraId) { | 212 public void onCameraOpening(int cameraId) { |
| 209 onCameraOpeningCalled = true; | 213 onCameraOpeningCalled = true; |
| 214 synchronized (cameraClosedLock) { |
| 215 cameraClosed = false; |
| 216 } |
| 210 } | 217 } |
| 211 | 218 |
| 212 @Override | 219 @Override |
| 213 public void onFirstFrameAvailable() { | 220 public void onFirstFrameAvailable() { |
| 214 onFirstFrameAvailableCalled = true; | 221 onFirstFrameAvailableCalled = true; |
| 215 } | 222 } |
| 216 | 223 |
| 217 @Override | 224 @Override |
| 218 public void onCameraClosed() { } | 225 public void onCameraClosed() { |
| 226 synchronized (cameraClosedLock) { |
| 227 cameraClosed = true; |
| 228 cameraClosedLock.notifyAll(); |
| 229 } |
| 230 } |
| 219 | 231 |
| 220 public String waitForCameraFreezed() throws InterruptedException { | 232 public String waitForCameraFreezed() throws InterruptedException { |
| 221 Logging.d(TAG, "Waiting for the camera to freeze"); | 233 Logging.d(TAG, "Waiting for the camera to freeze"); |
| 222 synchronized (onCameraFreezedLock) { | 234 synchronized (onCameraFreezedLock) { |
| 223 onCameraFreezedLock.wait(); | 235 onCameraFreezedLock.wait(); |
| 224 return onCameraFreezedDescription; | 236 return onCameraFreezedDescription; |
| 225 } | 237 } |
| 226 } | 238 } |
| 239 |
| 240 public void waitForCameraClosed() throws InterruptedException { |
| 241 synchronized (cameraClosedLock) { |
| 242 while (!cameraClosed) { |
| 243 Logging.d(TAG, "Waiting for the camera to close."); |
| 244 cameraClosedLock.wait(); |
| 245 } |
| 246 } |
| 247 } |
| 227 } | 248 } |
| 228 | 249 |
| 229 /** | 250 /** |
| 230 * Class to collect all classes related to single capturer instance. | 251 * Class to collect all classes related to single capturer instance. |
| 231 */ | 252 */ |
| 232 static private class CapturerInstance { | 253 static private class CapturerInstance { |
| 233 public CameraVideoCapturer capturer; | 254 public CameraVideoCapturer capturer; |
| 234 public CameraEvents cameraEvents; | 255 public CameraEvents cameraEvents; |
| 235 public SurfaceTextureHelper surfaceTextureHelper; | 256 public SurfaceTextureHelper surfaceTextureHelper; |
| 236 public FakeCapturerObserver observer; | 257 public FakeCapturerObserver observer; |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 instance.observer = new FakeCapturerObserver(); | 346 instance.observer = new FakeCapturerObserver(); |
| 326 if (initialize) { | 347 if (initialize) { |
| 327 instance.capturer.initialize( | 348 instance.capturer.initialize( |
| 328 instance.surfaceTextureHelper, testObjectFactory.getAppContext(), inst
ance.observer); | 349 instance.surfaceTextureHelper, testObjectFactory.getAppContext(), inst
ance.observer); |
| 329 } | 350 } |
| 330 instance.supportedFormats = instance.capturer.getSupportedFormats(); | 351 instance.supportedFormats = instance.capturer.getSupportedFormats(); |
| 331 return instance; | 352 return instance; |
| 332 } | 353 } |
| 333 | 354 |
| 334 private CapturerInstance createCapturer(boolean initialize) { | 355 private CapturerInstance createCapturer(boolean initialize) { |
| 335 return createCapturer("", initialize); | 356 String name = testObjectFactory.cameraEnumerator.getDeviceNames()[0]; |
| 357 return createCapturer(name, initialize); |
| 336 } | 358 } |
| 337 | 359 |
| 338 private void startCapture(CapturerInstance instance) { | 360 private void startCapture(CapturerInstance instance) { |
| 339 startCapture(instance, 0); | 361 startCapture(instance, 0); |
| 340 } | 362 } |
| 341 | 363 |
| 342 private void startCapture(CapturerInstance instance, int formatIndex) { | 364 private void startCapture(CapturerInstance instance, int formatIndex) { |
| 343 final CameraEnumerationAndroid.CaptureFormat format = | 365 final CameraEnumerationAndroid.CaptureFormat format = |
| 344 instance.supportedFormats.get(formatIndex); | 366 instance.supportedFormats.get(formatIndex); |
| 345 | 367 |
| 346 instance.capturer.startCapture(format.width, format.height, format.framerate
.max); | 368 instance.capturer.startCapture(format.width, format.height, format.framerate
.max); |
| 347 instance.format = format; | 369 instance.format = format; |
| 348 } | 370 } |
| 349 | 371 |
| 350 private void disposeCapturer(CapturerInstance instance) { | 372 private void disposeCapturer(CapturerInstance instance) throws InterruptedExce
ption { |
| 351 try { | 373 instance.capturer.stopCapture(); |
| 352 instance.capturer.stopCapture(); | 374 instance.cameraEvents.waitForCameraClosed(); |
| 353 } catch (InterruptedException e) { | |
| 354 // TODO(sakal): Remove this once stopCapture no longer throws InterruptedE
xception | |
| 355 } | |
| 356 instance.capturer.dispose(); | 375 instance.capturer.dispose(); |
| 357 instance.surfaceTextureHelper.returnTextureFrame(); | 376 instance.surfaceTextureHelper.returnTextureFrame(); |
| 358 instance.surfaceTextureHelper.dispose(); | 377 instance.surfaceTextureHelper.dispose(); |
| 359 } | 378 } |
| 360 | 379 |
| 361 private VideoTrackWithRenderer createVideoTrackWithRenderer(CameraVideoCapture
r capturer, | 380 private VideoTrackWithRenderer createVideoTrackWithRenderer(CameraVideoCapture
r capturer, |
| 362 VideoRenderer.Callbacks rendererCallbacks) { | 381 VideoRenderer.Callbacks rendererCallbacks) { |
| 363 VideoTrackWithRenderer videoTrackWithRenderer = new VideoTrackWithRenderer()
; | 382 VideoTrackWithRenderer videoTrackWithRenderer = new VideoTrackWithRenderer()
; |
| 364 videoTrackWithRenderer.source = peerConnectionFactory.createVideoSource(capt
urer); | 383 videoTrackWithRenderer.source = peerConnectionFactory.createVideoSource(capt
urer); |
| 365 capturer.startCapture(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FPS); | 384 capturer.startCapture(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FPS); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 | 428 |
| 410 final CapturerInstance capturerInstance = createCapturer(name, false /* init
ialize */); | 429 final CapturerInstance capturerInstance = createCapturer(name, false /* init
ialize */); |
| 411 final VideoTrackWithRenderer videoTrackWithRenderer = | 430 final VideoTrackWithRenderer videoTrackWithRenderer = |
| 412 createVideoTrackWithRenderer(capturerInstance.capturer); | 431 createVideoTrackWithRenderer(capturerInstance.capturer); |
| 413 assertTrue(videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender
() > 0); | 432 assertTrue(videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender
() > 0); |
| 414 disposeCapturer(capturerInstance); | 433 disposeCapturer(capturerInstance); |
| 415 disposeVideoTrackWithRenderer(videoTrackWithRenderer); | 434 disposeVideoTrackWithRenderer(videoTrackWithRenderer); |
| 416 } | 435 } |
| 417 | 436 |
| 418 // Test methods | 437 // Test methods |
| 419 public void createCapturerAndDispose() { | 438 public void createCapturerAndDispose() throws InterruptedException { |
| 420 disposeCapturer(createCapturer(true /* initialize */)); | 439 disposeCapturer(createCapturer(true /* initialize */)); |
| 421 } | 440 } |
| 422 | 441 |
| 423 public void createNonExistingCamera() { | 442 public void createNonExistingCamera() throws InterruptedException { |
| 424 try { | 443 try { |
| 425 disposeCapturer(createCapturer("non-existing camera", false /* initialize
*/)); | 444 disposeCapturer(createCapturer("non-existing camera", false /* initialize
*/)); |
| 426 } catch (IllegalArgumentException e) { | 445 } catch (IllegalArgumentException e) { |
| 427 return; | 446 return; |
| 428 } | 447 } |
| 429 | 448 |
| 430 fail("Expected illegal argument exception when creating non-existing camera.
"); | 449 fail("Expected illegal argument exception when creating non-existing camera.
"); |
| 431 } | 450 } |
| 432 | 451 |
| 433 public void createCapturerAndRender() throws InterruptedException { | 452 public void createCapturerAndRender() throws InterruptedException { |
| 434 createCapturerAndRender(""); | 453 String name = testObjectFactory.cameraEnumerator.getDeviceNames()[0]; |
| 454 createCapturerAndRender(name); |
| 435 } | 455 } |
| 436 | 456 |
| 437 public void createFrontFacingCapturerAndRender() throws InterruptedException { | 457 public void createFrontFacingCapturerAndRender() throws InterruptedException { |
| 438 createCapturerAndRender(testObjectFactory.getNameOfFrontFacingDevice()); | 458 createCapturerAndRender(testObjectFactory.getNameOfFrontFacingDevice()); |
| 439 } | 459 } |
| 440 | 460 |
| 441 public void createBackFacingCapturerAndRender() throws InterruptedException { | 461 public void createBackFacingCapturerAndRender() throws InterruptedException { |
| 442 createCapturerAndRender(testObjectFactory.getNameOfBackFacingDevice()); | 462 createCapturerAndRender(testObjectFactory.getNameOfBackFacingDevice()); |
| 443 } | 463 } |
| 444 | 464 |
| 445 public void switchCamera() throws InterruptedException { | 465 public void switchCamera() throws InterruptedException { |
| 446 if (!testObjectFactory.haveTwoCameras()) { | 466 if (!testObjectFactory.haveTwoCameras()) { |
| 447 Logging.w(TAG, | 467 Logging.w(TAG, |
| 448 "Skipping test switch video capturer because the device doesn't have t
wo cameras."); | 468 "Skipping test switch video capturer because the device doesn't have t
wo cameras."); |
| 449 return; | 469 return; |
| 450 } | 470 } |
| 451 | 471 |
| 452 final CapturerInstance capturerInstance = createCapturer(false /* initialize
*/); | 472 final CapturerInstance capturerInstance = createCapturer(false /* initialize
*/); |
| 453 final VideoTrackWithRenderer videoTrackWithRenderer = | 473 final VideoTrackWithRenderer videoTrackWithRenderer = |
| 454 createVideoTrackWithRenderer(capturerInstance.capturer); | 474 createVideoTrackWithRenderer(capturerInstance.capturer); |
| 475 // Wait for the camera to start so we can switch it |
| 476 assertTrue(videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender
() > 0); |
| 455 | 477 |
| 456 // Array with one element to avoid final problem in nested classes. | 478 // Array with one element to avoid final problem in nested classes. |
| 457 final boolean[] cameraSwitchSuccessful = new boolean[1]; | 479 final boolean[] cameraSwitchSuccessful = new boolean[1]; |
| 458 final CountDownLatch barrier = new CountDownLatch(1); | 480 final CountDownLatch barrier = new CountDownLatch(1); |
| 459 capturerInstance.capturer.switchCamera(new CameraVideoCapturer.CameraSwitchH
andler() { | 481 capturerInstance.capturer.switchCamera(new CameraVideoCapturer.CameraSwitchH
andler() { |
| 460 @Override | 482 @Override |
| 461 public void onCameraSwitchDone(boolean isFrontCamera) { | 483 public void onCameraSwitchDone(boolean isFrontCamera) { |
| 462 cameraSwitchSuccessful[0] = true; | 484 cameraSwitchSuccessful[0] = true; |
| 463 barrier.countDown(); | 485 barrier.countDown(); |
| 464 } | 486 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 478 disposeCapturer(capturerInstance); | 500 disposeCapturer(capturerInstance); |
| 479 disposeVideoTrackWithRenderer(videoTrackWithRenderer); | 501 disposeVideoTrackWithRenderer(videoTrackWithRenderer); |
| 480 } | 502 } |
| 481 | 503 |
| 482 public void cameraEventsInvoked() throws InterruptedException { | 504 public void cameraEventsInvoked() throws InterruptedException { |
| 483 final CapturerInstance capturerInstance = createCapturer(true /* initialize
*/); | 505 final CapturerInstance capturerInstance = createCapturer(true /* initialize
*/); |
| 484 startCapture(capturerInstance); | 506 startCapture(capturerInstance); |
| 485 // Make sure camera is started and first frame is received and then stop it. | 507 // Make sure camera is started and first frame is received and then stop it. |
| 486 assertTrue(capturerInstance.observer.waitForCapturerToStart()); | 508 assertTrue(capturerInstance.observer.waitForCapturerToStart()); |
| 487 capturerInstance.observer.waitForNextCapturedFrame(); | 509 capturerInstance.observer.waitForNextCapturedFrame(); |
| 488 capturerInstance.capturer.stopCapture(); | |
| 489 disposeCapturer(capturerInstance); | 510 disposeCapturer(capturerInstance); |
| 490 | 511 |
| 491 assertTrue(capturerInstance.cameraEvents.onCameraOpeningCalled); | 512 assertTrue(capturerInstance.cameraEvents.onCameraOpeningCalled); |
| 492 assertTrue(capturerInstance.cameraEvents.onFirstFrameAvailableCalled); | 513 assertTrue(capturerInstance.cameraEvents.onFirstFrameAvailableCalled); |
| 493 } | 514 } |
| 494 | 515 |
| 495 public void cameraCallsAfterStop() throws InterruptedException { | 516 public void cameraCallsAfterStop() throws InterruptedException { |
| 496 final CapturerInstance capturerInstance = createCapturer(true /* initialize
*/); | 517 final CapturerInstance capturerInstance = createCapturer(true /* initialize
*/); |
| 497 startCapture(capturerInstance); | 518 startCapture(capturerInstance); |
| 498 // Make sure camera is started and then stop it. | 519 // Make sure camera is started and then stop it. |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 663 // At this point camera is not actually opened. | 684 // At this point camera is not actually opened. |
| 664 final CapturerInstance capturerInstance = createCapturer(cameraName, true /*
initialize */); | 685 final CapturerInstance capturerInstance = createCapturer(cameraName, true /*
initialize */); |
| 665 | 686 |
| 666 final Object competingCamera = testObjectFactory.rawOpenCamera(cameraName); | 687 final Object competingCamera = testObjectFactory.rawOpenCamera(cameraName); |
| 667 | 688 |
| 668 startCapture(capturerInstance); | 689 startCapture(capturerInstance); |
| 669 | 690 |
| 670 if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.LOLLIP
OP_MR1) { | 691 if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.LOLLIP
OP_MR1) { |
| 671 // The first opened camera client will be evicted. | 692 // The first opened camera client will be evicted. |
| 672 assertTrue(capturerInstance.observer.waitForCapturerToStart()); | 693 assertTrue(capturerInstance.observer.waitForCapturerToStart()); |
| 673 capturerInstance.capturer.stopCapture(); | |
| 674 } else { | 694 } else { |
| 675 assertFalse(capturerInstance.observer.waitForCapturerToStart()); | 695 assertFalse(capturerInstance.observer.waitForCapturerToStart()); |
| 676 } | 696 } |
| 677 | 697 |
| 678 testObjectFactory.rawCloseCamera(competingCamera); | 698 testObjectFactory.rawCloseCamera(competingCamera); |
| 679 disposeCapturer(capturerInstance); | 699 disposeCapturer(capturerInstance); |
| 680 } | 700 } |
| 681 | 701 |
| 682 public void startWhileCameraIsAlreadyOpenAndCloseCamera() throws InterruptedEx
ception { | 702 public void startWhileCameraIsAlreadyOpenAndCloseCamera() throws InterruptedEx
ception { |
| 683 final String cameraName = testObjectFactory.getNameOfBackFacingDevice(); | 703 final String cameraName = testObjectFactory.getNameOfBackFacingDevice(); |
| 684 // At this point camera is not actually opened. | 704 // At this point camera is not actually opened. |
| 685 final CapturerInstance capturerInstance = createCapturer(cameraName, false /
* initialize */); | 705 final CapturerInstance capturerInstance = createCapturer(cameraName, false /
* initialize */); |
| 686 | 706 |
| 687 Logging.d(TAG, "startWhileCameraIsAlreadyOpenAndCloseCamera: Opening competi
ng camera."); | 707 Logging.d(TAG, "startWhileCameraIsAlreadyOpenAndCloseCamera: Opening competi
ng camera."); |
| 688 final Object competingCamera = testObjectFactory.rawOpenCamera(cameraName); | 708 final Object competingCamera = testObjectFactory.rawOpenCamera(cameraName); |
| 689 | 709 |
| 690 Logging.d(TAG, "startWhileCameraIsAlreadyOpenAndCloseCamera: Opening camera.
"); | 710 Logging.d(TAG, "startWhileCameraIsAlreadyOpenAndCloseCamera: Opening camera.
"); |
| 691 final VideoTrackWithRenderer videoTrackWithRenderer = | 711 final VideoTrackWithRenderer videoTrackWithRenderer = |
| 692 createVideoTrackWithRenderer(capturerInstance.capturer); | 712 createVideoTrackWithRenderer(capturerInstance.capturer); |
| 693 waitUntilIdle(capturerInstance); | 713 waitUntilIdle(capturerInstance); |
| 694 | 714 |
| 695 Logging.d(TAG, "startWhileCameraIsAlreadyOpenAndCloseCamera: Closing competi
ng camera."); | 715 Logging.d(TAG, "startWhileCameraIsAlreadyOpenAndCloseCamera: Closing competi
ng camera."); |
| 696 testObjectFactory.rawCloseCamera(competingCamera); | 716 testObjectFactory.rawCloseCamera(competingCamera); |
| 697 | 717 |
| 698 // Make sure camera is started and first frame is received and then stop it. | 718 // Make sure camera is started and first frame is received and then stop it. |
| 699 Logging.d(TAG, "startWhileCameraIsAlreadyOpenAndCloseCamera: Waiting for cap
ture to start."); | 719 Logging.d(TAG, "startWhileCameraIsAlreadyOpenAndCloseCamera: Waiting for cap
ture to start."); |
| 700 videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender(); | 720 videoTrackWithRenderer.rendererCallbacks.waitForNextFrameToRender(); |
| 701 Logging.d(TAG, "startWhileCameraIsAlreadyOpenAndCloseCamera: Stopping captur
e."); | 721 Logging.d(TAG, "startWhileCameraIsAlreadyOpenAndCloseCamera: Stopping captur
e."); |
| 702 capturerInstance.capturer.stopCapture(); | |
| 703 disposeCapturer(capturerInstance); | 722 disposeCapturer(capturerInstance); |
| 704 } | 723 } |
| 705 | 724 |
| 706 public void startWhileCameraIsAlreadyOpenAndStop() throws InterruptedException
{ | 725 public void startWhileCameraIsAlreadyOpenAndStop() throws InterruptedException
{ |
| 707 final String cameraName = testObjectFactory.getNameOfBackFacingDevice(); | 726 final String cameraName = testObjectFactory.getNameOfBackFacingDevice(); |
| 708 // At this point camera is not actually opened. | 727 // At this point camera is not actually opened. |
| 709 final CapturerInstance capturerInstance = createCapturer(cameraName, true /*
initialize */); | 728 final CapturerInstance capturerInstance = createCapturer(cameraName, true /*
initialize */); |
| 710 | 729 |
| 711 final Object competingCamera = testObjectFactory.rawOpenCamera(cameraName); | 730 final Object competingCamera = testObjectFactory.rawOpenCamera(cameraName); |
| 712 | 731 |
| 713 startCapture(capturerInstance); | 732 startCapture(capturerInstance); |
| 714 | |
| 715 capturerInstance.capturer.stopCapture(); | |
| 716 disposeCapturer(capturerInstance); | 733 disposeCapturer(capturerInstance); |
| 717 | 734 |
| 718 testObjectFactory.rawCloseCamera(competingCamera); | 735 testObjectFactory.rawCloseCamera(competingCamera); |
| 719 } | 736 } |
| 720 } | 737 } |
| OLD | NEW |