OSDN Git Service

Merge "Camera2: add deferred output config support" into nyc-mr1-dev
[android-x86/frameworks-base.git] / core / java / android / hardware / camera2 / impl / CameraConstrainedHighSpeedCaptureSessionImpl.java
1 /*
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  */
16 package android.hardware.camera2.impl;
17
18 import android.hardware.camera2.CameraAccessException;
19 import android.hardware.camera2.CameraCaptureSession;
20 import android.hardware.camera2.CameraCharacteristics;
21 import android.hardware.camera2.CameraConstrainedHighSpeedCaptureSession;
22 import android.hardware.camera2.CameraDevice;
23 import android.hardware.camera2.CaptureRequest;
24 import android.hardware.camera2.params.OutputConfiguration;
25 import android.hardware.camera2.params.StreamConfigurationMap;
26 import android.hardware.camera2.utils.SurfaceUtils;
27 import android.os.Handler;
28 import android.util.Range;
29 import android.view.Surface;
30
31 import java.util.ArrayList;
32 import java.util.Collection;
33 import java.util.Collections;
34 import java.util.Iterator;
35 import java.util.List;
36
37 import 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
49 public 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      */
61     CameraConstrainedHighSpeedCaptureSessionImpl(int id, List<Surface> outputs,
62             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);
68         mSessionImpl = new CameraCaptureSessionImpl(id, /*input*/null, outputs, wrapperCallback,
69                 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
173     public void prepare(int maxCount, Surface surface) throws CameraAccessException {
174         mSessionImpl.prepare(maxCount, surface);
175     }
176
177     @Override
178     public void tearDown(Surface surface) throws CameraAccessException {
179         mSessionImpl.tearDown(surface);
180     }
181
182     @Override
183     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
260     @Override
261     public void finishDeferredConfiguration(List<OutputConfiguration> deferredOutputConfigs)
262             throws CameraAccessException {
263         mSessionImpl.finishDeferredConfiguration(deferredOutputConfigs);
264     }
265
266     private class WrapperCallback extends StateCallback {
267         private final StateCallback mCallback;
268
269         public WrapperCallback(StateCallback callback) {
270             mCallback = callback;
271         }
272
273         @Override
274         public void onConfigured(CameraCaptureSession session) {
275             mCallback.onConfigured(CameraConstrainedHighSpeedCaptureSessionImpl.this);
276         }
277
278         @Override
279         public void onConfigureFailed(CameraCaptureSession session) {
280             mCallback.onConfigureFailed(CameraConstrainedHighSpeedCaptureSessionImpl.this);
281         }
282
283         @Override
284         public void onReady(CameraCaptureSession session) {
285             mCallback.onReady(CameraConstrainedHighSpeedCaptureSessionImpl.this);
286         }
287
288         @Override
289         public void onActive(CameraCaptureSession session) {
290             mCallback.onActive(CameraConstrainedHighSpeedCaptureSessionImpl.this);
291         }
292
293         @Override
294         public void onClosed(CameraCaptureSession session) {
295             mCallback.onClosed(CameraConstrainedHighSpeedCaptureSessionImpl.this);
296         }
297
298         @Override
299         public void onSurfacePrepared(CameraCaptureSession session, Surface surface) {
300             mCallback.onSurfacePrepared(CameraConstrainedHighSpeedCaptureSessionImpl.this,
301                     surface);
302         }
303
304
305     }
306 }