blob: 15dbf2620608ee97db9f537da3525e7028633cae [file] [log] [blame]
Eino-Ville Talvala639fffe2015-06-30 10:34:48 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package android.hardware.camera2.impl;
17
18import android.hardware.camera2.CameraAccessException;
19import android.hardware.camera2.CameraCaptureSession;
20import android.hardware.camera2.CameraCharacteristics;
21import android.hardware.camera2.CameraConstrainedHighSpeedCaptureSession;
22import android.hardware.camera2.CameraDevice;
23import android.hardware.camera2.CaptureRequest;
Zhijun Hec8b181e2016-05-30 14:54:39 -070024import android.hardware.camera2.params.OutputConfiguration;
Eino-Ville Talvala639fffe2015-06-30 10:34:48 -070025import android.hardware.camera2.params.StreamConfigurationMap;
26import android.hardware.camera2.utils.SurfaceUtils;
27import android.os.Handler;
28import android.util.Range;
29import android.view.Surface;
30
31import java.util.ArrayList;
32import java.util.Collection;
33import java.util.Collections;
34import java.util.Iterator;
35import java.util.List;
36
37import static com.android.internal.util.Preconditions.*;
38
39/**
40 * Standard implementation of CameraConstrainedHighSpeedCaptureSession.
41 *
42 * <p>
43 * Mostly just forwards calls to an instance of CameraCaptureSessionImpl,
44 * but implements the few necessary behavior changes and additional methods required
45 * for the constrained high speed speed mode.
46 * </p>
47 */
48
49public class CameraConstrainedHighSpeedCaptureSessionImpl
50 extends CameraConstrainedHighSpeedCaptureSession implements CameraCaptureSessionCore {
51 private final CameraCharacteristics mCharacteristics;
52 private final CameraCaptureSessionImpl mSessionImpl;
53
54 /**
55 * Create a new CameraCaptureSession.
56 *
57 * <p>The camera device must already be in the {@code IDLE} state when this is invoked.
58 * There must be no pending actions
59 * (e.g. no pending captures, no repeating requests, no flush).</p>
60 */
Shuzhen Wang9c663d42016-10-28 23:25:02 -070061 CameraConstrainedHighSpeedCaptureSessionImpl(int id,
Eino-Ville Talvala639fffe2015-06-30 10:34:48 -070062 CameraCaptureSession.StateCallback callback, Handler stateHandler,
63 android.hardware.camera2.impl.CameraDeviceImpl deviceImpl,
64 Handler deviceStateHandler, boolean configureSuccess,
65 CameraCharacteristics characteristics) {
66 mCharacteristics = characteristics;
67 CameraCaptureSession.StateCallback wrapperCallback = new WrapperCallback(callback);
Shuzhen Wang9c663d42016-10-28 23:25:02 -070068 mSessionImpl = new CameraCaptureSessionImpl(id, /*input*/null, wrapperCallback,
Eino-Ville Talvala639fffe2015-06-30 10:34:48 -070069 stateHandler, deviceImpl, deviceStateHandler, configureSuccess);
70 }
71
72 @Override
73 public List<CaptureRequest> createHighSpeedRequestList(CaptureRequest request)
74 throws CameraAccessException {
75 if (request == null) {
76 throw new IllegalArgumentException("Input capture request must not be null");
77 }
78 Collection<Surface> outputSurfaces = request.getTargets();
79 Range<Integer> fpsRange = request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE);
80
81 StreamConfigurationMap config =
82 mCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
83 SurfaceUtils.checkConstrainedHighSpeedSurfaces(outputSurfaces, fpsRange, config);
84
85 // Request list size: to limit the preview to 30fps, need use maxFps/30; to maximize
86 // the preview frame rate, should use maxBatch size for that high speed stream
87 // configuration. We choose the former for now.
88 int requestListSize = fpsRange.getUpper() / 30;
89 List<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
90
91 // Prepare the Request builders: need carry over the request controls.
92 // First, create a request builder that will only include preview or recording target.
93 CameraMetadataNative requestMetadata = new CameraMetadataNative(request.getNativeCopy());
94 // Note that after this step, the requestMetadata is mutated (swapped) and can not be used
95 // for next request builder creation.
96 CaptureRequest.Builder singleTargetRequestBuilder = new CaptureRequest.Builder(
97 requestMetadata, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE);
98
99 // Overwrite the capture intent to make sure a good value is set.
100 Iterator<Surface> iterator = outputSurfaces.iterator();
101 Surface firstSurface = iterator.next();
102 Surface secondSurface = null;
103 if (outputSurfaces.size() == 1 && SurfaceUtils.isSurfaceForHwVideoEncoder(firstSurface)) {
104 singleTargetRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT,
105 CaptureRequest.CONTROL_CAPTURE_INTENT_PREVIEW);
106 } else {
107 // Video only, or preview + video
108 singleTargetRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT,
109 CaptureRequest.CONTROL_CAPTURE_INTENT_VIDEO_RECORD);
110 }
111 singleTargetRequestBuilder.setPartOfCHSRequestList(/*partOfCHSList*/true);
112
113 // Second, Create a request builder that will include both preview and recording targets.
114 CaptureRequest.Builder doubleTargetRequestBuilder = null;
115 if (outputSurfaces.size() == 2) {
116 // Have to create a new copy, the original one was mutated after a new
117 // CaptureRequest.Builder creation.
118 requestMetadata = new CameraMetadataNative(request.getNativeCopy());
119 doubleTargetRequestBuilder = new CaptureRequest.Builder(
120 requestMetadata, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE);
121 doubleTargetRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT,
122 CaptureRequest.CONTROL_CAPTURE_INTENT_VIDEO_RECORD);
123 doubleTargetRequestBuilder.addTarget(firstSurface);
124 secondSurface = iterator.next();
125 doubleTargetRequestBuilder.addTarget(secondSurface);
126 doubleTargetRequestBuilder.setPartOfCHSRequestList(/*partOfCHSList*/true);
127 // Make sure singleTargetRequestBuilder contains only recording surface for
128 // preview + recording case.
129 Surface recordingSurface = firstSurface;
130 if (!SurfaceUtils.isSurfaceForHwVideoEncoder(recordingSurface)) {
131 recordingSurface = secondSurface;
132 }
133 singleTargetRequestBuilder.addTarget(recordingSurface);
134 } else {
135 // Single output case: either recording or preview.
136 singleTargetRequestBuilder.addTarget(firstSurface);
137 }
138
139 // Generate the final request list.
140 for (int i = 0; i < requestListSize; i++) {
141 if (i == 0 && doubleTargetRequestBuilder != null) {
142 // First request should be recording + preview request
143 requestList.add(doubleTargetRequestBuilder.build());
144 } else {
145 requestList.add(singleTargetRequestBuilder.build());
146 }
147 }
148
149 return Collections.unmodifiableList(requestList);
150 }
151
152 private boolean isConstrainedHighSpeedRequestList(List<CaptureRequest> requestList) {
153 checkCollectionNotEmpty(requestList, "High speed request list");
154 for (CaptureRequest request : requestList) {
155 if (!request.isPartOfCRequestList()) {
156 return false;
157 }
158 }
159 return true;
160 }
161
162 @Override
163 public CameraDevice getDevice() {
164 return mSessionImpl.getDevice();
165 }
166
167 @Override
168 public void prepare(Surface surface) throws CameraAccessException {
169 mSessionImpl.prepare(surface);
170 }
171
172 @Override
Ruben Brunk7ed1aaa2015-08-13 17:57:14 -0700173 public void prepare(int maxCount, Surface surface) throws CameraAccessException {
174 mSessionImpl.prepare(maxCount, surface);
175 }
176
177 @Override
Eino-Ville Talvala14c09fa2015-07-15 16:04:04 -0700178 public void tearDown(Surface surface) throws CameraAccessException {
179 mSessionImpl.tearDown(surface);
180 }
181
182 @Override
Eino-Ville Talvala639fffe2015-06-30 10:34:48 -0700183 public int capture(CaptureRequest request, CaptureCallback listener, Handler handler)
184 throws CameraAccessException {
185 throw new UnsupportedOperationException("Constrained high speed session doesn't support"
186 + " this method");
187 }
188
189 @Override
190 public int captureBurst(List<CaptureRequest> requests, CaptureCallback listener,
191 Handler handler) throws CameraAccessException {
192 if (!isConstrainedHighSpeedRequestList(requests)) {
193 throw new IllegalArgumentException(
194 "Only request lists created by createHighSpeedRequestList() can be submitted to " +
195 "a constrained high speed capture session");
196 }
197 return mSessionImpl.captureBurst(requests, listener, handler);
198 }
199
200 @Override
201 public int setRepeatingRequest(CaptureRequest request, CaptureCallback listener,
202 Handler handler) throws CameraAccessException {
203 throw new UnsupportedOperationException("Constrained high speed session doesn't support"
204 + " this method");
205 }
206
207 @Override
208 public int setRepeatingBurst(List<CaptureRequest> requests, CaptureCallback listener,
209 Handler handler) throws CameraAccessException {
210 if (!isConstrainedHighSpeedRequestList(requests)) {
211 throw new IllegalArgumentException(
212 "Only request lists created by createHighSpeedRequestList() can be submitted to " +
213 "a constrained high speed capture session");
214 }
215 return mSessionImpl.setRepeatingBurst(requests, listener, handler);
216 }
217
218 @Override
219 public void stopRepeating() throws CameraAccessException {
220 mSessionImpl.stopRepeating();
221 }
222
223 @Override
224 public void abortCaptures() throws CameraAccessException {
225 mSessionImpl.abortCaptures();
226 }
227
228 @Override
229 public Surface getInputSurface() {
230 return null;
231 }
232
233 @Override
234 public void close() {
235 mSessionImpl.close();
236 }
237
238 @Override
239 public boolean isReprocessable() {
240 return false;
241 }
242
243 // Implementation of CameraCaptureSessionCore methods
244
245 @Override
246 public void replaceSessionClose() {
247 mSessionImpl.replaceSessionClose();
248 }
249
250 @Override
251 public CameraDeviceImpl.StateCallbackKK getDeviceStateCallback() {
252 return mSessionImpl.getDeviceStateCallback();
253 }
254
255 @Override
256 public boolean isAborting() {
257 return mSessionImpl.isAborting();
258 }
259
Zhijun Hec8b181e2016-05-30 14:54:39 -0700260 @Override
Shuzhen Wang4bd7abe2017-01-11 09:58:58 -0800261 public void finalizeOutputConfigurations(List<OutputConfiguration> deferredOutputConfigs)
Zhijun Hec8b181e2016-05-30 14:54:39 -0700262 throws CameraAccessException {
Shuzhen Wang4bd7abe2017-01-11 09:58:58 -0800263 mSessionImpl.finalizeOutputConfigurations(deferredOutputConfigs);
Zhijun Hec8b181e2016-05-30 14:54:39 -0700264 }
265
Eino-Ville Talvala639fffe2015-06-30 10:34:48 -0700266 private class WrapperCallback extends StateCallback {
267 private final StateCallback mCallback;
268
269 public WrapperCallback(StateCallback callback) {
270 mCallback = callback;
271 }
272
Zhijun Hec8b181e2016-05-30 14:54:39 -0700273 @Override
Eino-Ville Talvala639fffe2015-06-30 10:34:48 -0700274 public void onConfigured(CameraCaptureSession session) {
275 mCallback.onConfigured(CameraConstrainedHighSpeedCaptureSessionImpl.this);
276 }
277
Zhijun Hec8b181e2016-05-30 14:54:39 -0700278 @Override
Eino-Ville Talvala639fffe2015-06-30 10:34:48 -0700279 public void onConfigureFailed(CameraCaptureSession session) {
280 mCallback.onConfigureFailed(CameraConstrainedHighSpeedCaptureSessionImpl.this);
281 }
282
Zhijun Hec8b181e2016-05-30 14:54:39 -0700283 @Override
Eino-Ville Talvala639fffe2015-06-30 10:34:48 -0700284 public void onReady(CameraCaptureSession session) {
285 mCallback.onReady(CameraConstrainedHighSpeedCaptureSessionImpl.this);
286 }
287
Zhijun Hec8b181e2016-05-30 14:54:39 -0700288 @Override
Eino-Ville Talvala639fffe2015-06-30 10:34:48 -0700289 public void onActive(CameraCaptureSession session) {
290 mCallback.onActive(CameraConstrainedHighSpeedCaptureSessionImpl.this);
291 }
292
Zhijun Hec8b181e2016-05-30 14:54:39 -0700293 @Override
Shuzhen Wang88f1af22016-09-30 10:29:28 -0700294 public void onCaptureQueueEmpty(CameraCaptureSession session) {
295 mCallback.onCaptureQueueEmpty(CameraConstrainedHighSpeedCaptureSessionImpl.this);
296 }
297
298 @Override
Eino-Ville Talvala639fffe2015-06-30 10:34:48 -0700299 public void onClosed(CameraCaptureSession session) {
300 mCallback.onClosed(CameraConstrainedHighSpeedCaptureSessionImpl.this);
301 }
302
Zhijun Hec8b181e2016-05-30 14:54:39 -0700303 @Override
Eino-Ville Talvala639fffe2015-06-30 10:34:48 -0700304 public void onSurfacePrepared(CameraCaptureSession session, Surface surface) {
305 mCallback.onSurfacePrepared(CameraConstrainedHighSpeedCaptureSessionImpl.this,
306 surface);
307 }
Eino-Ville Talvala639fffe2015-06-30 10:34:48 -0700308 }
309}