Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(237)

Side by Side Diff: webrtc/api/java/android/org/webrtc/VideoCapturerAndroid.java

Issue 2003973003: Reorder actions on stopCapturer, to avoid crashing on camera timeout. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Add comment on boolean literals. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 10
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 } 365 }
366 366
367 // Start camera observer. 367 // Start camera observer.
368 cameraStatistics = new CameraStatistics(surfaceHelper, eventsHandler); 368 cameraStatistics = new CameraStatistics(surfaceHelper, eventsHandler);
369 return; 369 return;
370 } catch (RuntimeException e) { 370 } catch (RuntimeException e) {
371 error = e; 371 error = e;
372 } 372 }
373 Logging.e(TAG, "startCapture failed", error); 373 Logging.e(TAG, "startCapture failed", error);
374 // Make sure the camera is released. 374 // Make sure the camera is released.
375 stopCaptureOnCameraThread(); 375 stopCaptureOnCameraThread(true /* stopHandler */);
376 synchronized (handlerLock) {
377 // Remove all pending Runnables posted from |this|.
378 cameraThreadHandler.removeCallbacksAndMessages(this /* token */);
379 cameraThreadHandler = null;
380 }
381 frameObserver.onCapturerStarted(false); 376 frameObserver.onCapturerStarted(false);
382 if (eventsHandler != null) { 377 if (eventsHandler != null) {
383 eventsHandler.onCameraError("Camera can not be started."); 378 eventsHandler.onCameraError("Camera can not be started.");
384 } 379 }
385 return; 380 return;
386 } 381 }
387 382
388 // (Re)start preview with the closest supported format to |width| x |height| @ |framerate|. 383 // (Re)start preview with the closest supported format to |width| x |height| @ |framerate|.
389 private void startPreviewOnCameraThread(int width, int height, int framerate) { 384 private void startPreviewOnCameraThread(int width, int height, int framerate) {
390 checkIsOnCameraThread(); 385 checkIsOnCameraThread();
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 camera.startPreview(); 471 camera.startPreview();
477 } 472 }
478 473
479 // Blocks until camera is known to be stopped. 474 // Blocks until camera is known to be stopped.
480 @Override 475 @Override
481 public void stopCapture() throws InterruptedException { 476 public void stopCapture() throws InterruptedException {
482 Logging.d(TAG, "stopCapture"); 477 Logging.d(TAG, "stopCapture");
483 final CountDownLatch barrier = new CountDownLatch(1); 478 final CountDownLatch barrier = new CountDownLatch(1);
484 final boolean didPost = maybePostOnCameraThread(new Runnable() { 479 final boolean didPost = maybePostOnCameraThread(new Runnable() {
485 @Override public void run() { 480 @Override public void run() {
486 stopCaptureOnCameraThread(); 481 stopCaptureOnCameraThread(true /* stopHandler */);
487 synchronized (handlerLock) {
488 // Remove all pending Runnables posted from |this|.
489 cameraThreadHandler.removeCallbacksAndMessages(this /* token */);
490 cameraThreadHandler = null;
491 surfaceHelper = null;
492 }
493 barrier.countDown(); 482 barrier.countDown();
494 } 483 }
495 }); 484 });
496 if (!didPost) { 485 if (!didPost) {
497 Logging.e(TAG, "Calling stopCapture() for already stopped camera."); 486 Logging.e(TAG, "Calling stopCapture() for already stopped camera.");
498 return; 487 return;
499 } 488 }
500 if (!barrier.await(CAMERA_STOP_TIMEOUT_MS, TimeUnit.MILLISECONDS)) { 489 if (!barrier.await(CAMERA_STOP_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
501 Logging.e(TAG, "Camera stop timeout"); 490 Logging.e(TAG, "Camera stop timeout");
502 printStackTrace(); 491 printStackTrace();
503 if (eventsHandler != null) { 492 if (eventsHandler != null) {
504 eventsHandler.onCameraError("Camera stop timeout"); 493 eventsHandler.onCameraError("Camera stop timeout");
505 } 494 }
506 } 495 }
507 Logging.d(TAG, "stopCapture done"); 496 Logging.d(TAG, "stopCapture done");
508 } 497 }
509 498
510 private void stopCaptureOnCameraThread() { 499 private void stopCaptureOnCameraThread(boolean stopHandler) {
511 checkIsOnCameraThread(); 500 checkIsOnCameraThread();
512 Logging.d(TAG, "stopCaptureOnCameraThread"); 501 Logging.d(TAG, "stopCaptureOnCameraThread");
513 // Note that the camera might still not be started here if startCaptureOnCam eraThread failed 502 // Note that the camera might still not be started here if startCaptureOnCam eraThread failed
514 // and we posted a retry. 503 // and we posted a retry.
515 504
516 // Make sure onTextureFrameAvailable() is not called anymore. 505 // Make sure onTextureFrameAvailable() is not called anymore.
517 if (surfaceHelper != null) { 506 if (surfaceHelper != null) {
518 surfaceHelper.stopListening(); 507 surfaceHelper.stopListening();
519 } 508 }
509 if (stopHandler) {
510 synchronized (handlerLock) {
511 // Clear the cameraThreadHandler first, in case stopPreview or
512 // other driver code deadlocks. Deadlock in
513 // android.hardware.Camera._stopPreview(Native Method) has
514 // been observed on Nexus 5 (hammerhead), OS version LMY48I.
515 // The camera might post another one or two preview frames
516 // before stopped, so we have to check for a null
517 // cameraThreadHandler in our handler. Remove all pending
518 // Runnables posted from |this|.
519 cameraThreadHandler.removeCallbacksAndMessages(this /* token */);
520 cameraThreadHandler = null;
521 surfaceHelper = null;
522 }
523 }
520 if (cameraStatistics != null) { 524 if (cameraStatistics != null) {
521 cameraStatistics.release(); 525 cameraStatistics.release();
522 cameraStatistics = null; 526 cameraStatistics = null;
523 } 527 }
524 Logging.d(TAG, "Stop preview."); 528 Logging.d(TAG, "Stop preview.");
525 if (camera != null) { 529 if (camera != null) {
526 camera.stopPreview(); 530 camera.stopPreview();
527 camera.setPreviewCallbackWithBuffer(null); 531 camera.setPreviewCallbackWithBuffer(null);
528 } 532 }
529 queuedBuffers.clear(); 533 queuedBuffers.clear();
530 captureFormat = null; 534 captureFormat = null;
531 535
532 Logging.d(TAG, "Release camera."); 536 Logging.d(TAG, "Release camera.");
533 if (camera != null) { 537 if (camera != null) {
534 camera.release(); 538 camera.release();
535 camera = null; 539 camera = null;
536 } 540 }
537 if (eventsHandler != null) { 541 if (eventsHandler != null) {
538 eventsHandler.onCameraClosed(); 542 eventsHandler.onCameraClosed();
539 } 543 }
540 Logging.d(TAG, "stopCaptureOnCameraThread done"); 544 Logging.d(TAG, "stopCaptureOnCameraThread done");
541 } 545 }
542 546
543 private void switchCameraOnCameraThread() { 547 private void switchCameraOnCameraThread() {
544 checkIsOnCameraThread(); 548 checkIsOnCameraThread();
545 Logging.d(TAG, "switchCameraOnCameraThread"); 549 Logging.d(TAG, "switchCameraOnCameraThread");
546 stopCaptureOnCameraThread(); 550 stopCaptureOnCameraThread(false /* stopHandler */);
547 synchronized (cameraIdLock) { 551 synchronized (cameraIdLock) {
548 id = (id + 1) % android.hardware.Camera.getNumberOfCameras(); 552 id = (id + 1) % android.hardware.Camera.getNumberOfCameras();
549 } 553 }
550 startCaptureOnCameraThread(requestedWidth, requestedHeight, requestedFramera te, frameObserver, 554 startCaptureOnCameraThread(requestedWidth, requestedHeight, requestedFramera te, frameObserver,
551 applicationContext); 555 applicationContext);
552 Logging.d(TAG, "switchCameraOnCameraThread done"); 556 Logging.d(TAG, "switchCameraOnCameraThread done");
553 } 557 }
554 558
555 private void onOutputFormatRequestOnCameraThread(int width, int height, int fr amerate) { 559 private void onOutputFormatRequestOnCameraThread(int width, int height, int fr amerate) {
556 checkIsOnCameraThread(); 560 checkIsOnCameraThread();
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
625 629
626 cameraStatistics.addFrame(); 630 cameraStatistics.addFrame();
627 frameObserver.onByteBufferFrameCaptured(data, captureFormat.width, captureFo rmat.height, 631 frameObserver.onByteBufferFrameCaptured(data, captureFormat.width, captureFo rmat.height,
628 getFrameOrientation(), captureTimeNs); 632 getFrameOrientation(), captureTimeNs);
629 camera.addCallbackBuffer(data); 633 camera.addCallbackBuffer(data);
630 } 634 }
631 635
632 @Override 636 @Override
633 public void onTextureFrameAvailable( 637 public void onTextureFrameAvailable(
634 int oesTextureId, float[] transformMatrix, long timestampNs) { 638 int oesTextureId, float[] transformMatrix, long timestampNs) {
635 if (cameraThreadHandler == null) { 639
636 throw new RuntimeException("onTextureFrameAvailable() called after stopCap ture().");
637 }
638 checkIsOnCameraThread(); 640 checkIsOnCameraThread();
639 if (eventsHandler != null && !firstFrameReported) { 641 if (eventsHandler != null && !firstFrameReported) {
640 eventsHandler.onFirstFrameAvailable(); 642 eventsHandler.onFirstFrameAvailable();
641 firstFrameReported = true; 643 firstFrameReported = true;
642 } 644 }
643 645
644 int rotation = getFrameOrientation(); 646 int rotation = getFrameOrientation();
645 if (info.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT) { 647 if (info.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT) {
646 // Undo the mirror that the OS "helps" us with. 648 // Undo the mirror that the OS "helps" us with.
647 // http://developer.android.com/reference/android/hardware/Camera.html#set DisplayOrientation(int) 649 // http://developer.android.com/reference/android/hardware/Camera.html#set DisplayOrientation(int)
648 transformMatrix = 650 transformMatrix =
649 RendererCommon.multiplyMatrices(transformMatrix, RendererCommon.horizo ntalFlipMatrix()); 651 RendererCommon.multiplyMatrices(transformMatrix, RendererCommon.horizo ntalFlipMatrix());
650 } 652 }
651 cameraStatistics.addFrame(); 653 cameraStatistics.addFrame();
652 frameObserver.onTextureFrameCaptured(captureFormat.width, captureFormat.heig ht, oesTextureId, 654 frameObserver.onTextureFrameCaptured(captureFormat.width, captureFormat.heig ht, oesTextureId,
653 transformMatrix, rotation, timestampNs); 655 transformMatrix, rotation, timestampNs);
654 } 656 }
655 } 657 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698