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

Side by Side Diff: webrtc/api/android/java/src/org/webrtc/CameraCapturer.java

Issue 2331343010: Events refactor in Android session based capturing. (Closed)
Patch Set: Safety breaks switchCamera. Remove safety. Created 4 years, 3 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
OLDNEW
1 /* 1 /*
2 * Copyright 2016 The WebRTC project authors. All Rights Reserved. 2 * Copyright 2016 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 16 matching lines...) Expand all
27 private static final String TAG = "CameraCapturer"; 27 private static final String TAG = "CameraCapturer";
28 private final static int MAX_OPEN_CAMERA_ATTEMPTS = 3; 28 private final static int MAX_OPEN_CAMERA_ATTEMPTS = 3;
29 private final static int OPEN_CAMERA_DELAY_MS = 500; 29 private final static int OPEN_CAMERA_DELAY_MS = 500;
30 private final static int OPEN_CAMERA_TIMEOUT = 10000; 30 private final static int OPEN_CAMERA_TIMEOUT = 10000;
31 31
32 private final CameraEnumerator cameraEnumerator; 32 private final CameraEnumerator cameraEnumerator;
33 private final CameraEventsHandler eventsHandler; 33 private final CameraEventsHandler eventsHandler;
34 private final Handler uiThreadHandler; 34 private final Handler uiThreadHandler;
35 35
36 private final CameraSession.CreateSessionCallback createSessionCallback = 36 private final CameraSession.CreateSessionCallback createSessionCallback =
37 new CameraSession.CreateSessionCallback() { 37 new CameraSession.CreateSessionCallback() {
magjed_webrtc 2016/09/16 09:00:37 It would be nice with checkIsOnCameraThread for on
sakal 2016/09/16 12:38:58 Done.
38 @Override 38 @Override
39 public void onDone(CameraSession session) { 39 public void onDone(CameraSession session) {
40 Logging.d(TAG, "Create session done"); 40 Logging.d(TAG, "Create session done");
41 uiThreadHandler.removeCallbacks(openCameraTimeoutRunnable); 41 uiThreadHandler.removeCallbacks(openCameraTimeoutRunnable);
42 capturerObserver.onCapturerStarted(true /* success */);
42 synchronized (stateLock) { 43 synchronized (stateLock) {
43 sessionOpening = false; 44 sessionOpening = false;
44 currentSession = session; 45 currentSession = session;
45 stateLock.notifyAll(); 46 stateLock.notifyAll();
46 47
47 if (switchState == SwitchState.IN_PROGRESS) { 48 if (switchState == SwitchState.IN_PROGRESS) {
48 if (switchEventsHandler != null) { 49 if (switchEventsHandler != null) {
49 switchEventsHandler.onCameraSwitchDone( 50 switchEventsHandler.onCameraSwitchDone(
50 cameraEnumerator.isFrontFacing(cameraName)); 51 cameraEnumerator.isFrontFacing(cameraName));
51 switchEventsHandler = null; 52 switchEventsHandler = null;
52 } 53 }
53 switchState = SwitchState.IDLE; 54 switchState = SwitchState.IDLE;
54 } else if (switchState == SwitchState.PENDING) { 55 } else if (switchState == SwitchState.PENDING) {
55 switchState = SwitchState.IDLE; 56 switchState = SwitchState.IDLE;
56 switchCameraInternal(switchEventsHandler); 57 switchCameraInternal(switchEventsHandler);
57 } 58 }
59
60 cameraStatistics = new CameraStatistics(surfaceHelper, eventsHandler );
61 firstFrameObserved = false;
58 } 62 }
59 } 63 }
60 64
61 @Override 65 @Override
62 public void onFailure(String error) { 66 public void onFailure(String error) {
63 uiThreadHandler.removeCallbacks(openCameraTimeoutRunnable); 67 uiThreadHandler.removeCallbacks(openCameraTimeoutRunnable);
68 capturerObserver.onCapturerStarted(false /* success */);
64 synchronized (stateLock) { 69 synchronized (stateLock) {
65 openAttemptsRemaining--; 70 openAttemptsRemaining--;
66 71
67 if (openAttemptsRemaining <= 0) { 72 if (openAttemptsRemaining <= 0) {
68 Logging.w(TAG, "Opening camera failed, passing: " + error); 73 Logging.w(TAG, "Opening camera failed, passing: " + error);
69 sessionOpening = false; 74 sessionOpening = false;
70 stateLock.notifyAll(); 75 stateLock.notifyAll();
71 76
72 if (switchState != SwitchState.IDLE) { 77 if (switchState != SwitchState.IDLE) {
73 if (switchEventsHandler != null) { 78 if (switchEventsHandler != null) {
74 switchEventsHandler.onCameraSwitchError(error); 79 switchEventsHandler.onCameraSwitchError(error);
75 switchEventsHandler = null; 80 switchEventsHandler = null;
76 } 81 }
77 switchState = SwitchState.IDLE; 82 switchState = SwitchState.IDLE;
78 } 83 }
79 84
80 eventsHandler.onCameraError(error); 85 eventsHandler.onCameraError(error);
81 } else { 86 } else {
82 Logging.w(TAG, "Opening camera failed, retry: " + error); 87 Logging.w(TAG, "Opening camera failed, retry: " + error);
83 88
84 createSessionInternal(OPEN_CAMERA_DELAY_MS); 89 createSessionInternal(OPEN_CAMERA_DELAY_MS);
85 } 90 }
86 } 91 }
87 } 92 }
88 }; 93 };
89 94
95 private final CameraSession.Events cameraSessionEventsHandler =
96 new CameraSession.Events() {
magjed_webrtc 2016/09/16 09:00:37 nit: Can you move 'new CameraSession.Events() {' u
sakal 2016/09/16 12:38:58 Done.
97 public void onCameraError(CameraSession session, String error) {
magjed_webrtc 2016/09/16 09:00:37 It would be nice with checkIsOnCameraThread checks
sakal 2016/09/16 12:38:59 Done.
98 synchronized (stateLock) {
99 if (session != currentSession) {
100 Logging.w(TAG, "onCameraError from another session: " + error);
101 return;
102 }
103 eventsHandler.onCameraError(error);
104 stopCapture();
105 }
106 }
107
108 public void onCameraOpening(CameraSession session) {
109 synchronized (stateLock) {
110 if (currentSession != null) {
111 Logging.w(TAG, "onCameraOpening while session was open.");
112 return;
113 }
114 eventsHandler.onCameraOpening(cameraName);
115 }
116 }
117
118 public void onCameraClosed(CameraSession session) {
119 synchronized (stateLock) {
120 if (session != currentSession && currentSession != null) {
121 Logging.d(TAG, "onCameraClosed from another session.");
122 return;
123 }
124 eventsHandler.onCameraClosed();
magjed_webrtc 2016/09/15 14:58:06 Now we hold stateLock while making the callbacks.
sakal 2016/09/15 15:08:18 If the callbacks invoke method on other threads, d
125 }
126 }
127
128 public void onByteBufferFrameCaptured(
129 CameraSession session, byte[] data, int width, int height, int rotat ion,
130 long timestamp) {
131 synchronized (stateLock) {
132 if (session != currentSession) {
magjed_webrtc 2016/09/15 14:58:06 Can we drop frames if we are in an incorrect state
sakal 2016/09/15 15:08:18 I am not sure what you mean. The stopping state is
magjed_webrtc 2016/09/16 09:00:37 I was thinking if the frame dropping in the sessio
sakal 2016/09/16 12:38:58 It is already redundant since we don't keep closed
magjed_webrtc 2016/09/16 12:59:19 Good, no keep it.
133 Logging.w(TAG, "onByteBufferFrameCaptured from another session.");
134 return;
135 }
136 if (!firstFrameObserved) {
137 eventsHandler.onFirstFrameAvailable();
138 firstFrameObserved = true;
139 }
140 cameraStatistics.addFrame();
141 capturerObserver.onByteBufferFrameCaptured(data, width, height, rota tion, timestamp);
142 }
143 }
144
145 public void onTextureFrameCaptured(
146 CameraSession session, int width, int height, int oesTextureId, floa t[] transformMatrix,
147 int rotation, long timestamp) {
148 synchronized (stateLock) {
149 if (session != currentSession) {
150 Logging.w(TAG, "onTextureFrameCaptured from another session.");
151 return;
152 }
153 if (!firstFrameObserved) {
154 eventsHandler.onFirstFrameAvailable();
155 firstFrameObserved = true;
156 }
157 cameraStatistics.addFrame();
158 capturerObserver.onTextureFrameCaptured(
159 width, height, oesTextureId, transformMatrix, rotation, timestam p);
160 }
161 }
162 };
163
90 private final Runnable openCameraTimeoutRunnable = new Runnable() { 164 private final Runnable openCameraTimeoutRunnable = new Runnable() {
91 @Override 165 @Override
92 public void run() { 166 public void run() {
93 eventsHandler.onCameraError("Camera failed to start within timeout."); 167 eventsHandler.onCameraError("Camera failed to start within timeout.");
94 } 168 }
95 }; 169 };
96 170
97 // Initialized on initialize 171 // Initialized on initialize
98 // ------------------------- 172 // -------------------------
99 private Handler cameraThreadHandler; 173 private Handler cameraThreadHandler;
100 private Context applicationContext; 174 private Context applicationContext;
101 private CapturerObserver capturerObserver; 175 private CapturerObserver capturerObserver;
102 private SurfaceTextureHelper surfaceHelper; 176 private SurfaceTextureHelper surfaceHelper;
103 177
104 private final Object stateLock = new Object(); 178 private final Object stateLock = new Object();
105 private boolean sessionOpening; /* guarded by stateLock */ 179 private boolean sessionOpening; /* guarded by stateLock */
106 private CameraSession currentSession; /* guarded by stateLock */ 180 private CameraSession currentSession; /* guarded by stateLock */
107 private String cameraName; /* guarded by stateLock */ 181 private String cameraName; /* guarded by stateLock */
108 private int width; /* guarded by stateLock */ 182 private int width; /* guarded by stateLock */
109 private int height; /* guarded by stateLock */ 183 private int height; /* guarded by stateLock */
110 private int framerate; /* guarded by stateLock */ 184 private int framerate; /* guarded by stateLock */
111 private int openAttemptsRemaining; /* guarded by stateLock */ 185 private int openAttemptsRemaining; /* guarded by stateLock */
112 private SwitchState switchState = SwitchState.IDLE; /* guarded by stateLock */ 186 private SwitchState switchState = SwitchState.IDLE; /* guarded by stateLock */
113 private CameraSwitchHandler switchEventsHandler; /* guarded by stateLock */ 187 private CameraSwitchHandler switchEventsHandler; /* guarded by stateLock */
188 // Valid from onDone call until stopCapture, otherwise null.
189 private CameraStatistics cameraStatistics; /* guarded by stateLock */
190 private boolean firstFrameObserved; /* guarded by stateLock */
114 191
115 public CameraCapturer( 192 public CameraCapturer(
116 String cameraName, CameraEventsHandler eventsHandler, CameraEnumerator cam eraEnumerator) { 193 String cameraName, CameraEventsHandler eventsHandler, CameraEnumerator cam eraEnumerator) {
117 if (eventsHandler == null) { 194 if (eventsHandler == null) {
118 eventsHandler = new CameraEventsHandler() { 195 eventsHandler = new CameraEventsHandler() {
119 @Override 196 @Override
120 public void onCameraError(String errorDescription) {} 197 public void onCameraError(String errorDescription) {}
121 @Override 198 @Override
122 public void onCameraFreezed(String errorDescription) {} 199 public void onCameraFreezed(String errorDescription) {}
123 @Override 200 @Override
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 createSessionInternal(0); 251 createSessionInternal(0);
175 } 252 }
176 } 253 }
177 254
178 private void createSessionInternal(int delayMs) { 255 private void createSessionInternal(int delayMs) {
179 uiThreadHandler.postDelayed(openCameraTimeoutRunnable, delayMs + OPEN_CAMERA _TIMEOUT); 256 uiThreadHandler.postDelayed(openCameraTimeoutRunnable, delayMs + OPEN_CAMERA _TIMEOUT);
180 cameraThreadHandler.postDelayed(new Runnable() { 257 cameraThreadHandler.postDelayed(new Runnable() {
181 @Override 258 @Override
182 public void run() { 259 public void run() {
183 createCameraSession( 260 createCameraSession(
184 createSessionCallback, 261 createSessionCallback, cameraSessionEventsHandler, applicationContex t, surfaceHelper,
185 eventsHandler, applicationContext, capturerObserver, surfaceHelper,
186 cameraName, width, height, framerate); 262 cameraName, width, height, framerate);
187 } 263 }
188 }, delayMs); 264 }, delayMs);
189 } 265 }
190 266
191 @Override 267 @Override
192 public void stopCapture() { 268 public void stopCapture() {
193 Logging.d(TAG, "Stop capture"); 269 Logging.d(TAG, "Stop capture");
194 270
195 synchronized (stateLock) { 271 synchronized (stateLock) {
196 while (sessionOpening) { 272 while (sessionOpening) {
197 Logging.d(TAG, "Stop capture: Waiting for session to open"); 273 Logging.d(TAG, "Stop capture: Waiting for session to open");
198 ThreadUtils.waitUninterruptibly(stateLock); 274 ThreadUtils.waitUninterruptibly(stateLock);
199 } 275 }
200 276
201 if (currentSession != null) { 277 if (currentSession != null) {
202 Logging.d(TAG, "Stop capture: Stopping session"); 278 cameraStatistics.release();
279 cameraStatistics = null;
203 currentSession.stop(); 280 currentSession.stop();
204 currentSession = null; 281 currentSession = null;
282 capturerObserver.onCapturerStopped();
205 } else { 283 } else {
206 Logging.d(TAG, "Stop capture: No session open"); 284 Logging.d(TAG, "Stop capture: No session open");
207 } 285 }
208 } 286 }
209 287
210 Logging.d(TAG, "Stop capture done"); 288 Logging.d(TAG, "Stop capture done");
211 } 289 }
212 290
213 @Override 291 @Override
214 public void onOutputFormatRequest(final int width, final int height, final int framerate) { 292 public void onOutputFormatRequest(final int width, final int height, final int framerate) {
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 Logging.d(TAG, "switchCamera done"); 397 Logging.d(TAG, "switchCamera done");
320 } 398 }
321 399
322 protected String getCameraName() { 400 protected String getCameraName() {
323 synchronized (stateLock) { 401 synchronized (stateLock) {
324 return cameraName; 402 return cameraName;
325 } 403 }
326 } 404 }
327 405
328 abstract protected void createCameraSession( 406 abstract protected void createCameraSession(
329 CameraSession.CreateSessionCallback createSessionCallback, 407 CameraSession.CreateSessionCallback createSessionCallback, CameraSession.E vents events,
330 CameraEventsHandler eventsHandler, Context applicationContext, 408 Context applicationContext, SurfaceTextureHelper surfaceTextureHelper,
331 CameraVideoCapturer.CapturerObserver capturerObserver,
332 SurfaceTextureHelper surfaceTextureHelper,
333 String cameraName, int width, int height, int framerate); 409 String cameraName, int width, int height, int framerate);
334 } 410 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698