OLD | NEW |
---|---|
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 21 matching lines...) Expand all Loading... | |
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() { |
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() { | |
97 public void onCameraError(CameraSession session, String error) { | |
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) { | |
sakal
2016/09/15 14:20:56
I am not sure what we should do here.
| |
121 Logging.d(TAG, "onCameraClosed from another session."); | |
122 return; | |
123 } | |
124 eventsHandler.onCameraClosed(); | |
125 // This is just for safety. It should not be necessary. | |
126 stopCapture(); | |
127 } | |
128 } | |
129 | |
130 public void onByteBufferFrameCaptured( | |
131 CameraSession session, byte[] data, int width, int height, int rotat ion, | |
132 long timestamp) { | |
133 synchronized (stateLock) { | |
134 if (session != currentSession) { | |
135 Logging.w(TAG, "onByteBufferFrameCaptured from another session."); | |
136 return; | |
137 } | |
138 if (!firstFrameObserved) { | |
139 eventsHandler.onFirstFrameAvailable(); | |
140 firstFrameObserved = true; | |
141 } | |
142 cameraStatistics.addFrame(); | |
143 capturerObserver.onByteBufferFrameCaptured(data, width, height, rota tion, timestamp); | |
144 } | |
145 } | |
146 | |
147 public void onTextureFrameCaptured( | |
148 CameraSession session, int width, int height, int oesTextureId, floa t[] transformMatrix, | |
149 int rotation, long timestamp) { | |
150 synchronized (stateLock) { | |
151 if (session != currentSession) { | |
152 Logging.w(TAG, "onTextureFrameCaptured from another session."); | |
153 return; | |
154 } | |
155 if (!firstFrameObserved) { | |
156 eventsHandler.onFirstFrameAvailable(); | |
157 firstFrameObserved = true; | |
158 } | |
159 cameraStatistics.addFrame(); | |
160 capturerObserver.onTextureFrameCaptured( | |
161 width, height, oesTextureId, transformMatrix, rotation, timestam p); | |
162 } | |
163 } | |
164 }; | |
165 | |
90 private final Runnable openCameraTimeoutRunnable = new Runnable() { | 166 private final Runnable openCameraTimeoutRunnable = new Runnable() { |
91 @Override | 167 @Override |
92 public void run() { | 168 public void run() { |
93 eventsHandler.onCameraError("Camera failed to start within timeout."); | 169 eventsHandler.onCameraError("Camera failed to start within timeout."); |
94 } | 170 } |
95 }; | 171 }; |
96 | 172 |
97 // Initialized on initialize | 173 // Initialized on initialize |
98 // ------------------------- | 174 // ------------------------- |
99 private Handler cameraThreadHandler; | 175 private Handler cameraThreadHandler; |
100 private Context applicationContext; | 176 private Context applicationContext; |
101 private CapturerObserver capturerObserver; | 177 private CapturerObserver capturerObserver; |
102 private SurfaceTextureHelper surfaceHelper; | 178 private SurfaceTextureHelper surfaceHelper; |
103 | 179 |
104 private final Object stateLock = new Object(); | 180 private final Object stateLock = new Object(); |
105 private boolean sessionOpening; /* guarded by stateLock */ | 181 private boolean sessionOpening; /* guarded by stateLock */ |
106 private CameraSession currentSession; /* guarded by stateLock */ | 182 private CameraSession currentSession; /* guarded by stateLock */ |
107 private String cameraName; /* guarded by stateLock */ | 183 private String cameraName; /* guarded by stateLock */ |
108 private int width; /* guarded by stateLock */ | 184 private int width; /* guarded by stateLock */ |
109 private int height; /* guarded by stateLock */ | 185 private int height; /* guarded by stateLock */ |
110 private int framerate; /* guarded by stateLock */ | 186 private int framerate; /* guarded by stateLock */ |
111 private int openAttemptsRemaining; /* guarded by stateLock */ | 187 private int openAttemptsRemaining; /* guarded by stateLock */ |
112 private SwitchState switchState = SwitchState.IDLE; /* guarded by stateLock */ | 188 private SwitchState switchState = SwitchState.IDLE; /* guarded by stateLock */ |
113 private CameraSwitchHandler switchEventsHandler; /* guarded by stateLock */ | 189 private CameraSwitchHandler switchEventsHandler; /* guarded by stateLock */ |
190 // Valid from onDone call until stopCapture, otherwise null. | |
191 private CameraStatistics cameraStatistics; /* guarded by stateLock */ | |
192 private boolean firstFrameObserved; /* guarded by stateLock */ | |
114 | 193 |
115 public CameraCapturer( | 194 public CameraCapturer( |
116 String cameraName, CameraEventsHandler eventsHandler, CameraEnumerator cam eraEnumerator) { | 195 String cameraName, CameraEventsHandler eventsHandler, CameraEnumerator cam eraEnumerator) { |
117 if (eventsHandler == null) { | 196 if (eventsHandler == null) { |
118 eventsHandler = new CameraEventsHandler() { | 197 eventsHandler = new CameraEventsHandler() { |
119 @Override | 198 @Override |
120 public void onCameraError(String errorDescription) {} | 199 public void onCameraError(String errorDescription) {} |
121 @Override | 200 @Override |
122 public void onCameraFreezed(String errorDescription) {} | 201 public void onCameraFreezed(String errorDescription) {} |
123 @Override | 202 @Override |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
174 createSessionInternal(0); | 253 createSessionInternal(0); |
175 } | 254 } |
176 } | 255 } |
177 | 256 |
178 private void createSessionInternal(int delayMs) { | 257 private void createSessionInternal(int delayMs) { |
179 uiThreadHandler.postDelayed(openCameraTimeoutRunnable, delayMs + OPEN_CAMERA _TIMEOUT); | 258 uiThreadHandler.postDelayed(openCameraTimeoutRunnable, delayMs + OPEN_CAMERA _TIMEOUT); |
180 cameraThreadHandler.postDelayed(new Runnable() { | 259 cameraThreadHandler.postDelayed(new Runnable() { |
181 @Override | 260 @Override |
182 public void run() { | 261 public void run() { |
183 createCameraSession( | 262 createCameraSession( |
184 createSessionCallback, | 263 createSessionCallback, cameraSessionEventsHandler, applicationContex t, surfaceHelper, |
185 eventsHandler, applicationContext, capturerObserver, surfaceHelper, | |
186 cameraName, width, height, framerate); | 264 cameraName, width, height, framerate); |
187 } | 265 } |
188 }, delayMs); | 266 }, delayMs); |
189 } | 267 } |
190 | 268 |
191 @Override | 269 @Override |
192 public void stopCapture() { | 270 public void stopCapture() { |
193 Logging.d(TAG, "Stop capture"); | 271 Logging.d(TAG, "Stop capture"); |
194 | 272 |
195 synchronized (stateLock) { | 273 synchronized (stateLock) { |
196 while (sessionOpening) { | 274 while (sessionOpening) { |
197 Logging.d(TAG, "Stop capture: Waiting for session to open"); | 275 Logging.d(TAG, "Stop capture: Waiting for session to open"); |
198 ThreadUtils.waitUninterruptibly(stateLock); | 276 ThreadUtils.waitUninterruptibly(stateLock); |
199 } | 277 } |
200 | 278 |
201 if (currentSession != null) { | 279 if (currentSession != null) { |
202 Logging.d(TAG, "Stop capture: Stopping session"); | 280 cameraStatistics.release(); |
281 cameraStatistics = null; | |
203 currentSession.stop(); | 282 currentSession.stop(); |
204 currentSession = null; | 283 currentSession = null; |
284 capturerObserver.onCapturerStopped(); | |
205 } else { | 285 } else { |
206 Logging.d(TAG, "Stop capture: No session open"); | 286 Logging.d(TAG, "Stop capture: No session open"); |
207 } | 287 } |
208 } | 288 } |
209 | 289 |
210 Logging.d(TAG, "Stop capture done"); | 290 Logging.d(TAG, "Stop capture done"); |
211 } | 291 } |
212 | 292 |
213 @Override | 293 @Override |
214 public void onOutputFormatRequest(final int width, final int height, final int framerate) { | 294 public void onOutputFormatRequest(final int width, final int height, final int framerate) { |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
319 Logging.d(TAG, "switchCamera done"); | 399 Logging.d(TAG, "switchCamera done"); |
320 } | 400 } |
321 | 401 |
322 protected String getCameraName() { | 402 protected String getCameraName() { |
323 synchronized (stateLock) { | 403 synchronized (stateLock) { |
324 return cameraName; | 404 return cameraName; |
325 } | 405 } |
326 } | 406 } |
327 | 407 |
328 abstract protected void createCameraSession( | 408 abstract protected void createCameraSession( |
329 CameraSession.CreateSessionCallback createSessionCallback, | 409 CameraSession.CreateSessionCallback createSessionCallback, CameraSession.E vents events, |
330 CameraEventsHandler eventsHandler, Context applicationContext, | 410 Context applicationContext, SurfaceTextureHelper surfaceTextureHelper, |
331 CameraVideoCapturer.CapturerObserver capturerObserver, | |
332 SurfaceTextureHelper surfaceTextureHelper, | |
333 String cameraName, int width, int height, int framerate); | 411 String cameraName, int width, int height, int framerate); |
334 } | 412 } |
OLD | NEW |