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

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

Issue 1979583002: Revert of Android: Make base interface for camera1 and camera2 (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 7 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 | « webrtc/api/java/android/org/webrtc/CameraVideoCapturer.java ('k') | 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 20 matching lines...) Expand all
31 // An instance of this class can be created by an application using 31 // An instance of this class can be created by an application using
32 // VideoCapturerAndroid.create(); 32 // VideoCapturerAndroid.create();
33 // This class extends VideoCapturer with a method to easily switch between the 33 // This class extends VideoCapturer with a method to easily switch between the
34 // front and back camera. It also provides methods for enumerating valid device 34 // front and back camera. It also provides methods for enumerating valid device
35 // names. 35 // names.
36 // 36 //
37 // Threading notes: this class is called from C++ code, Android Camera callbacks , and possibly 37 // Threading notes: this class is called from C++ code, Android Camera callbacks , and possibly
38 // arbitrary Java threads. All public entry points are thread safe, and delegate the work to the 38 // arbitrary Java threads. All public entry points are thread safe, and delegate the work to the
39 // camera thread. The internal *OnCameraThread() methods must check |camera| for null to check if 39 // camera thread. The internal *OnCameraThread() methods must check |camera| for null to check if
40 // the camera has been stopped. 40 // the camera has been stopped.
41 // TODO(magjed): This class name is now confusing - rename to Camera1VideoCaptur er.
42 @SuppressWarnings("deprecation") 41 @SuppressWarnings("deprecation")
43 public class VideoCapturerAndroid implements 42 public class VideoCapturerAndroid implements
44 CameraVideoCapturer, 43 VideoCapturer,
45 android.hardware.Camera.PreviewCallback, 44 android.hardware.Camera.PreviewCallback,
46 SurfaceTextureHelper.OnTextureFrameAvailableListener { 45 SurfaceTextureHelper.OnTextureFrameAvailableListener {
47 private final static String TAG = "VideoCapturerAndroid"; 46 private final static String TAG = "VideoCapturerAndroid";
47 private final static int CAMERA_OBSERVER_PERIOD_MS = 2000;
48 private final static int CAMERA_FREEZE_REPORT_TIMOUT_MS = 4000;
48 private static final int CAMERA_STOP_TIMEOUT_MS = 7000; 49 private static final int CAMERA_STOP_TIMEOUT_MS = 7000;
49 50
50 private boolean isDisposed = false; 51 private boolean isDisposed = false;
51 private android.hardware.Camera camera; // Only non-null while capturing. 52 private android.hardware.Camera camera; // Only non-null while capturing.
52 private final Object handlerLock = new Object(); 53 private final Object handlerLock = new Object();
53 // |cameraThreadHandler| must be synchronized on |handlerLock| when not on the camera thread, 54 // |cameraThreadHandler| must be synchronized on |handlerLock| when not on the camera thread,
54 // or when modifying the reference. Use maybePostOnCameraThread() instead of p osting directly to 55 // or when modifying the reference. Use maybePostOnCameraThread() instead of p osting directly to
55 // the handler - this way all callbacks with a specifed token can be removed a t once. 56 // the handler - this way all callbacks with a specifed token can be removed a t once.
56 private Handler cameraThreadHandler; 57 private Handler cameraThreadHandler;
57 private Context applicationContext; 58 private Context applicationContext;
58 // Synchronization lock for |id|. 59 // Synchronization lock for |id|.
59 private final Object cameraIdLock = new Object(); 60 private final Object cameraIdLock = new Object();
60 private int id; 61 private int id;
61 private android.hardware.Camera.CameraInfo info; 62 private android.hardware.Camera.CameraInfo info;
62 private CameraStatistics cameraStatistics; 63 private final CameraStatistics cameraStatistics;
63 // Remember the requested format in case we want to switch cameras. 64 // Remember the requested format in case we want to switch cameras.
64 private int requestedWidth; 65 private int requestedWidth;
65 private int requestedHeight; 66 private int requestedHeight;
66 private int requestedFramerate; 67 private int requestedFramerate;
67 // The capture format will be the closest supported format to the requested fo rmat. 68 // The capture format will be the closest supported format to the requested fo rmat.
68 private CaptureFormat captureFormat; 69 private CaptureFormat captureFormat;
69 private final Object pendingCameraSwitchLock = new Object(); 70 private final Object pendingCameraSwitchLock = new Object();
70 private volatile boolean pendingCameraSwitch; 71 private volatile boolean pendingCameraSwitch;
71 private CapturerObserver frameObserver = null; 72 private CapturerObserver frameObserver = null;
72 private final CameraEventsHandler eventsHandler; 73 private final CameraEventsHandler eventsHandler;
(...skipping 23 matching lines...) Expand all
96 } else { 97 } else {
97 errorMessage = "Camera error: " + error; 98 errorMessage = "Camera error: " + error;
98 } 99 }
99 Logging.e(TAG, errorMessage); 100 Logging.e(TAG, errorMessage);
100 if (eventsHandler != null) { 101 if (eventsHandler != null) {
101 eventsHandler.onCameraError(errorMessage); 102 eventsHandler.onCameraError(errorMessage);
102 } 103 }
103 } 104 }
104 }; 105 };
105 106
107 // Camera observer - monitors camera framerate. Observer is executed on camera thread.
108 private final Runnable cameraObserver = new Runnable() {
109 private int freezePeriodCount;
110 @Override
111 public void run() {
112 int cameraFramesCount = cameraStatistics.getAndResetFrameCount();
113 int cameraFps = (cameraFramesCount * 1000 + CAMERA_OBSERVER_PERIOD_MS / 2)
114 / CAMERA_OBSERVER_PERIOD_MS;
115
116 Logging.d(TAG, "Camera fps: " + cameraFps +".");
117 if (cameraFramesCount == 0) {
118 ++freezePeriodCount;
119 if (CAMERA_OBSERVER_PERIOD_MS * freezePeriodCount >= CAMERA_FREEZE_REPOR T_TIMOUT_MS
120 && eventsHandler != null) {
121 Logging.e(TAG, "Camera freezed.");
122 if (surfaceHelper.isTextureInUse()) {
123 // This can only happen if we are capturing to textures.
124 eventsHandler.onCameraFreezed("Camera failure. Client must return vi deo buffers.");
125 } else {
126 eventsHandler.onCameraFreezed("Camera failure.");
127 }
128 return;
129 }
130 } else {
131 freezePeriodCount = 0;
132 }
133 maybePostDelayedOnCameraThread(CAMERA_OBSERVER_PERIOD_MS, this);
134 }
135 };
136
137 private static class CameraStatistics {
138 private int frameCount = 0;
139 private final ThreadUtils.ThreadChecker threadChecker = new ThreadUtils.Thre adChecker();
140
141 CameraStatistics() {
142 threadChecker.detachThread();
143 }
144
145 public void addFrame() {
146 threadChecker.checkIsOnValidThread();
147 ++frameCount;
148 }
149
150 public int getAndResetFrameCount() {
151 threadChecker.checkIsOnValidThread();
152 int count = frameCount;
153 frameCount = 0;
154 return count;
155 }
156 }
157
158 public static interface CameraEventsHandler {
159 // Camera error handler - invoked when camera can not be opened
160 // or any camera exception happens on camera thread.
161 void onCameraError(String errorDescription);
162
163 // Invoked when camera stops receiving frames
164 void onCameraFreezed(String errorDescription);
165
166 // Callback invoked when camera is opening.
167 void onCameraOpening(int cameraId);
168
169 // Callback invoked when first camera frame is available after camera is ope ned.
170 void onFirstFrameAvailable();
171
172 // Callback invoked when camera closed.
173 void onCameraClosed();
174 }
175
176 // Camera switch handler - one of these functions are invoked with the result of switchCamera().
177 // The callback may be called on an arbitrary thread.
178 public interface CameraSwitchHandler {
179 // Invoked on success. |isFrontCamera| is true if the new camera is front fa cing.
180 void onCameraSwitchDone(boolean isFrontCamera);
181 // Invoked on failure, e.g. camera is stopped or only one camera available.
182 void onCameraSwitchError(String errorDescription);
183 }
184
106 public static VideoCapturerAndroid create(String name, 185 public static VideoCapturerAndroid create(String name,
107 CameraEventsHandler eventsHandler) { 186 CameraEventsHandler eventsHandler) {
108 return VideoCapturerAndroid.create(name, eventsHandler, false /* captureToTe xture */); 187 return VideoCapturerAndroid.create(name, eventsHandler, false /* captureToTe xture */);
109 } 188 }
110 189
111 public static VideoCapturerAndroid create(String name, 190 public static VideoCapturerAndroid create(String name,
112 CameraEventsHandler eventsHandler, boolean captureToTexture) { 191 CameraEventsHandler eventsHandler, boolean captureToTexture) {
113 final int cameraId = lookupDeviceName(name); 192 final int cameraId = lookupDeviceName(name);
114 if (cameraId == -1) { 193 if (cameraId == -1) {
115 return null; 194 return null;
(...skipping 14 matching lines...) Expand all
130 Logging.d(TAG, "VideoCapturerAndroid stacks trace:"); 209 Logging.d(TAG, "VideoCapturerAndroid stacks trace:");
131 for (StackTraceElement stackTrace : cameraStackTraces) { 210 for (StackTraceElement stackTrace : cameraStackTraces) {
132 Logging.d(TAG, stackTrace.toString()); 211 Logging.d(TAG, stackTrace.toString());
133 } 212 }
134 } 213 }
135 } 214 }
136 } 215 }
137 216
138 // Switch camera to the next valid camera id. This can only be called while 217 // Switch camera to the next valid camera id. This can only be called while
139 // the camera is running. 218 // the camera is running.
140 @Override
141 public void switchCamera(final CameraSwitchHandler switchEventsHandler) { 219 public void switchCamera(final CameraSwitchHandler switchEventsHandler) {
142 if (android.hardware.Camera.getNumberOfCameras() < 2) { 220 if (android.hardware.Camera.getNumberOfCameras() < 2) {
143 if (switchEventsHandler != null) { 221 if (switchEventsHandler != null) {
144 switchEventsHandler.onCameraSwitchError("No camera to switch to."); 222 switchEventsHandler.onCameraSwitchError("No camera to switch to.");
145 } 223 }
146 return; 224 return;
147 } 225 }
148 synchronized (pendingCameraSwitchLock) { 226 synchronized (pendingCameraSwitchLock) {
149 if (pendingCameraSwitch) { 227 if (pendingCameraSwitch) {
150 // Do not handle multiple camera switch request to avoid blocking 228 // Do not handle multiple camera switch request to avoid blocking
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 // Returns true if this VideoCapturer is setup to capture video frames to a Su rfaceTexture. 292 // Returns true if this VideoCapturer is setup to capture video frames to a Su rfaceTexture.
215 public boolean isCapturingToTexture() { 293 public boolean isCapturingToTexture() {
216 return isCapturingToTexture; 294 return isCapturingToTexture;
217 } 295 }
218 296
219 private VideoCapturerAndroid(int cameraId, CameraEventsHandler eventsHandler, 297 private VideoCapturerAndroid(int cameraId, CameraEventsHandler eventsHandler,
220 boolean captureToTexture) { 298 boolean captureToTexture) {
221 this.id = cameraId; 299 this.id = cameraId;
222 this.eventsHandler = eventsHandler; 300 this.eventsHandler = eventsHandler;
223 isCapturingToTexture = captureToTexture; 301 isCapturingToTexture = captureToTexture;
302 cameraStatistics = new CameraStatistics();
224 Logging.d(TAG, "VideoCapturerAndroid isCapturingToTexture : " + isCapturingT oTexture); 303 Logging.d(TAG, "VideoCapturerAndroid isCapturingToTexture : " + isCapturingT oTexture);
225 } 304 }
226 305
227 private void checkIsOnCameraThread() { 306 private void checkIsOnCameraThread() {
228 if (Thread.currentThread() != cameraThreadHandler.getLooper().getThread()) { 307 if (Thread.currentThread() != cameraThreadHandler.getLooper().getThread()) {
229 throw new IllegalStateException("Wrong thread"); 308 throw new IllegalStateException("Wrong thread");
230 } 309 }
231 } 310 }
232 311
233 // Returns the camera index for camera with name |deviceName|, or -1 if no suc h camera can be 312 // Returns the camera index for camera with name |deviceName|, or -1 if no suc h camera can be
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 Logging.d(TAG, "Camera orientation: " + info.orientation + 453 Logging.d(TAG, "Camera orientation: " + info.orientation +
375 " .Device orientation: " + getDeviceOrientation()); 454 " .Device orientation: " + getDeviceOrientation());
376 camera.setErrorCallback(cameraErrorCallback); 455 camera.setErrorCallback(cameraErrorCallback);
377 startPreviewOnCameraThread(width, height, framerate); 456 startPreviewOnCameraThread(width, height, framerate);
378 frameObserver.onCapturerStarted(true); 457 frameObserver.onCapturerStarted(true);
379 if (isCapturingToTexture) { 458 if (isCapturingToTexture) {
380 surfaceHelper.startListening(this); 459 surfaceHelper.startListening(this);
381 } 460 }
382 461
383 // Start camera observer. 462 // Start camera observer.
384 cameraStatistics = new CameraStatistics(surfaceHelper, eventsHandler); 463 maybePostDelayedOnCameraThread(CAMERA_OBSERVER_PERIOD_MS, cameraObserver);
385 return; 464 return;
386 } catch (RuntimeException e) { 465 } catch (RuntimeException e) {
387 error = e; 466 error = e;
388 } 467 }
389 Logging.e(TAG, "startCapture failed", error); 468 Logging.e(TAG, "startCapture failed", error);
390 // Make sure the camera is released. 469 // Make sure the camera is released.
391 stopCaptureOnCameraThread(); 470 stopCaptureOnCameraThread();
392 synchronized (handlerLock) { 471 synchronized (handlerLock) {
393 // Remove all pending Runnables posted from |this|. 472 // Remove all pending Runnables posted from |this|.
394 cameraThreadHandler.removeCallbacksAndMessages(this /* token */); 473 cameraThreadHandler.removeCallbacksAndMessages(this /* token */);
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
527 private void stopCaptureOnCameraThread() { 606 private void stopCaptureOnCameraThread() {
528 checkIsOnCameraThread(); 607 checkIsOnCameraThread();
529 Logging.d(TAG, "stopCaptureOnCameraThread"); 608 Logging.d(TAG, "stopCaptureOnCameraThread");
530 // Note that the camera might still not be started here if startCaptureOnCam eraThread failed 609 // Note that the camera might still not be started here if startCaptureOnCam eraThread failed
531 // and we posted a retry. 610 // and we posted a retry.
532 611
533 // Make sure onTextureFrameAvailable() is not called anymore. 612 // Make sure onTextureFrameAvailable() is not called anymore.
534 if (surfaceHelper != null) { 613 if (surfaceHelper != null) {
535 surfaceHelper.stopListening(); 614 surfaceHelper.stopListening();
536 } 615 }
537 if (cameraStatistics != null) { 616 cameraThreadHandler.removeCallbacks(cameraObserver);
538 cameraStatistics.release(); 617 cameraStatistics.getAndResetFrameCount();
539 cameraStatistics = null;
540 }
541 Logging.d(TAG, "Stop preview."); 618 Logging.d(TAG, "Stop preview.");
542 if (camera != null) { 619 if (camera != null) {
543 camera.stopPreview(); 620 camera.stopPreview();
544 camera.setPreviewCallbackWithBuffer(null); 621 camera.setPreviewCallbackWithBuffer(null);
545 } 622 }
546 queuedBuffers.clear(); 623 queuedBuffers.clear();
547 captureFormat = null; 624 captureFormat = null;
548 625
549 Logging.d(TAG, "Release camera."); 626 Logging.d(TAG, "Release camera.");
550 if (camera != null) { 627 if (camera != null) {
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
669 // Undo the mirror that the OS "helps" us with. 746 // Undo the mirror that the OS "helps" us with.
670 // http://developer.android.com/reference/android/hardware/Camera.html#set DisplayOrientation(int) 747 // http://developer.android.com/reference/android/hardware/Camera.html#set DisplayOrientation(int)
671 transformMatrix = 748 transformMatrix =
672 RendererCommon.multiplyMatrices(transformMatrix, RendererCommon.horizo ntalFlipMatrix()); 749 RendererCommon.multiplyMatrices(transformMatrix, RendererCommon.horizo ntalFlipMatrix());
673 } 750 }
674 cameraStatistics.addFrame(); 751 cameraStatistics.addFrame();
675 frameObserver.onTextureFrameCaptured(captureFormat.width, captureFormat.heig ht, oesTextureId, 752 frameObserver.onTextureFrameCaptured(captureFormat.width, captureFormat.heig ht, oesTextureId,
676 transformMatrix, rotation, timestampNs); 753 transformMatrix, rotation, timestampNs);
677 } 754 }
678 } 755 }
OLDNEW
« no previous file with comments | « webrtc/api/java/android/org/webrtc/CameraVideoCapturer.java ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698