Home | History | Annotate | Download | only in impl
      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.StreamConfigurationMap;
     25 import android.hardware.camera2.utils.SurfaceUtils;
     26 import android.os.Handler;
     27 import android.util.Range;
     28 import android.view.Surface;
     29 
     30 import java.util.ArrayList;
     31 import java.util.Collection;
     32 import java.util.Collections;
     33 import java.util.Iterator;
     34 import java.util.List;
     35 
     36 import static com.android.internal.util.Preconditions.*;
     37 
     38 /**
     39  * Standard implementation of CameraConstrainedHighSpeedCaptureSession.
     40  *
     41  * <p>
     42  * Mostly just forwards calls to an instance of CameraCaptureSessionImpl,
     43  * but implements the few necessary behavior changes and additional methods required
     44  * for the constrained high speed speed mode.
     45  * </p>
     46  */
     47 
     48 public class CameraConstrainedHighSpeedCaptureSessionImpl
     49         extends CameraConstrainedHighSpeedCaptureSession implements CameraCaptureSessionCore {
     50     private final CameraCharacteristics mCharacteristics;
     51     private final CameraCaptureSessionImpl mSessionImpl;
     52 
     53     /**
     54      * Create a new CameraCaptureSession.
     55      *
     56      * <p>The camera device must already be in the {@code IDLE} state when this is invoked.
     57      * There must be no pending actions
     58      * (e.g. no pending captures, no repeating requests, no flush).</p>
     59      */
     60     CameraConstrainedHighSpeedCaptureSessionImpl(int id, List<Surface> outputs,
     61             CameraCaptureSession.StateCallback callback, Handler stateHandler,
     62             android.hardware.camera2.impl.CameraDeviceImpl deviceImpl,
     63             Handler deviceStateHandler, boolean configureSuccess,
     64             CameraCharacteristics characteristics) {
     65         mCharacteristics = characteristics;
     66         CameraCaptureSession.StateCallback wrapperCallback = new WrapperCallback(callback);
     67         mSessionImpl = new CameraCaptureSessionImpl(id, /*input*/null, outputs, wrapperCallback,
     68                 stateHandler, deviceImpl, deviceStateHandler, configureSuccess);
     69     }
     70 
     71     @Override
     72     public List<CaptureRequest> createHighSpeedRequestList(CaptureRequest request)
     73             throws CameraAccessException {
     74         if (request == null) {
     75             throw new IllegalArgumentException("Input capture request must not be null");
     76         }
     77         Collection<Surface> outputSurfaces = request.getTargets();
     78         Range<Integer> fpsRange = request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE);
     79 
     80         StreamConfigurationMap config =
     81                 mCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
     82         SurfaceUtils.checkConstrainedHighSpeedSurfaces(outputSurfaces, fpsRange, config);
     83 
     84         // Request list size: to limit the preview to 30fps, need use maxFps/30; to maximize
     85         // the preview frame rate, should use maxBatch size for that high speed stream
     86         // configuration. We choose the former for now.
     87         int requestListSize = fpsRange.getUpper() / 30;
     88         List<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
     89 
     90         // Prepare the Request builders: need carry over the request controls.
     91         // First, create a request builder that will only include preview or recording target.
     92         CameraMetadataNative requestMetadata = new CameraMetadataNative(request.getNativeCopy());
     93         // Note that after this step, the requestMetadata is mutated (swapped) and can not be used
     94         // for next request builder creation.
     95         CaptureRequest.Builder singleTargetRequestBuilder = new CaptureRequest.Builder(
     96                 requestMetadata, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE);
     97 
     98         // Overwrite the capture intent to make sure a good value is set.
     99         Iterator<Surface> iterator = outputSurfaces.iterator();
    100         Surface firstSurface = iterator.next();
    101         Surface secondSurface = null;
    102         if (outputSurfaces.size() == 1 && SurfaceUtils.isSurfaceForHwVideoEncoder(firstSurface)) {
    103             singleTargetRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT,
    104                     CaptureRequest.CONTROL_CAPTURE_INTENT_PREVIEW);
    105         } else {
    106             // Video only, or preview + video
    107             singleTargetRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT,
    108                     CaptureRequest.CONTROL_CAPTURE_INTENT_VIDEO_RECORD);
    109         }
    110         singleTargetRequestBuilder.setPartOfCHSRequestList(/*partOfCHSList*/true);
    111 
    112         // Second, Create a request builder that will include both preview and recording targets.
    113         CaptureRequest.Builder doubleTargetRequestBuilder = null;
    114         if (outputSurfaces.size() == 2) {
    115             // Have to create a new copy, the original one was mutated after a new
    116             // CaptureRequest.Builder creation.
    117             requestMetadata = new CameraMetadataNative(request.getNativeCopy());
    118             doubleTargetRequestBuilder = new CaptureRequest.Builder(
    119                     requestMetadata, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE);
    120             doubleTargetRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT,
    121                     CaptureRequest.CONTROL_CAPTURE_INTENT_VIDEO_RECORD);
    122             doubleTargetRequestBuilder.addTarget(firstSurface);
    123             secondSurface = iterator.next();
    124             doubleTargetRequestBuilder.addTarget(secondSurface);
    125             doubleTargetRequestBuilder.setPartOfCHSRequestList(/*partOfCHSList*/true);
    126             // Make sure singleTargetRequestBuilder contains only recording surface for
    127             // preview + recording case.
    128             Surface recordingSurface = firstSurface;
    129             if (!SurfaceUtils.isSurfaceForHwVideoEncoder(recordingSurface)) {
    130                 recordingSurface = secondSurface;
    131             }
    132             singleTargetRequestBuilder.addTarget(recordingSurface);
    133         } else {
    134             // Single output case: either recording or preview.
    135             singleTargetRequestBuilder.addTarget(firstSurface);
    136         }
    137 
    138         // Generate the final request list.
    139         for (int i = 0; i < requestListSize; i++) {
    140             if (i == 0 && doubleTargetRequestBuilder != null) {
    141                 // First request should be recording + preview request
    142                 requestList.add(doubleTargetRequestBuilder.build());
    143             } else {
    144                 requestList.add(singleTargetRequestBuilder.build());
    145             }
    146         }
    147 
    148         return Collections.unmodifiableList(requestList);
    149     }
    150 
    151     private boolean isConstrainedHighSpeedRequestList(List<CaptureRequest> requestList) {
    152         checkCollectionNotEmpty(requestList, "High speed request list");
    153         for (CaptureRequest request : requestList) {
    154             if (!request.isPartOfCRequestList()) {
    155                 return false;
    156             }
    157         }
    158         return true;
    159     }
    160 
    161     @Override
    162     public CameraDevice getDevice() {
    163         return mSessionImpl.getDevice();
    164     }
    165 
    166     @Override
    167     public void prepare(Surface surface) throws CameraAccessException {
    168         mSessionImpl.prepare(surface);
    169     }
    170 
    171     @Override
    172     public void prepare(int maxCount, Surface surface) throws CameraAccessException {
    173         mSessionImpl.prepare(maxCount, surface);
    174     }
    175 
    176     @Override
    177     public void tearDown(Surface surface) throws CameraAccessException {
    178         mSessionImpl.tearDown(surface);
    179     }
    180 
    181     @Override
    182     public int capture(CaptureRequest request, CaptureCallback listener, Handler handler)
    183             throws CameraAccessException {
    184         throw new UnsupportedOperationException("Constrained high speed session doesn't support"
    185                 + " this method");
    186     }
    187 
    188     @Override
    189     public int captureBurst(List<CaptureRequest> requests, CaptureCallback listener,
    190             Handler handler) throws CameraAccessException {
    191         if (!isConstrainedHighSpeedRequestList(requests)) {
    192             throw new IllegalArgumentException(
    193                 "Only request lists created by createHighSpeedRequestList() can be submitted to " +
    194                 "a constrained high speed capture session");
    195         }
    196         return mSessionImpl.captureBurst(requests, listener, handler);
    197     }
    198 
    199     @Override
    200     public int setRepeatingRequest(CaptureRequest request, CaptureCallback listener,
    201             Handler handler) throws CameraAccessException {
    202         throw new UnsupportedOperationException("Constrained high speed session doesn't support"
    203                 + " this method");
    204     }
    205 
    206     @Override
    207     public int setRepeatingBurst(List<CaptureRequest> requests, CaptureCallback listener,
    208             Handler handler) throws CameraAccessException {
    209         if (!isConstrainedHighSpeedRequestList(requests)) {
    210             throw new IllegalArgumentException(
    211                 "Only request lists created by createHighSpeedRequestList() can be submitted to " +
    212                 "a constrained high speed capture session");
    213         }
    214         return mSessionImpl.setRepeatingBurst(requests, listener, handler);
    215     }
    216 
    217     @Override
    218     public void stopRepeating() throws CameraAccessException {
    219         mSessionImpl.stopRepeating();
    220     }
    221 
    222     @Override
    223     public void abortCaptures() throws CameraAccessException {
    224         mSessionImpl.abortCaptures();
    225     }
    226 
    227     @Override
    228     public Surface getInputSurface() {
    229         return null;
    230     }
    231 
    232     @Override
    233     public void close() {
    234         mSessionImpl.close();
    235     }
    236 
    237     @Override
    238     public boolean isReprocessable() {
    239         return false;
    240     }
    241 
    242     // Implementation of CameraCaptureSessionCore methods
    243 
    244     @Override
    245     public void replaceSessionClose() {
    246         mSessionImpl.replaceSessionClose();
    247     }
    248 
    249     @Override
    250     public CameraDeviceImpl.StateCallbackKK getDeviceStateCallback() {
    251         return mSessionImpl.getDeviceStateCallback();
    252     }
    253 
    254     @Override
    255     public boolean isAborting() {
    256         return mSessionImpl.isAborting();
    257     }
    258 
    259     private class WrapperCallback extends StateCallback {
    260         private final StateCallback mCallback;
    261 
    262         public WrapperCallback(StateCallback callback) {
    263             mCallback = callback;
    264         }
    265 
    266         public void onConfigured(CameraCaptureSession session) {
    267             mCallback.onConfigured(CameraConstrainedHighSpeedCaptureSessionImpl.this);
    268         }
    269 
    270         public void onConfigureFailed(CameraCaptureSession session) {
    271             mCallback.onConfigureFailed(CameraConstrainedHighSpeedCaptureSessionImpl.this);
    272         }
    273 
    274         public void onReady(CameraCaptureSession session) {
    275             mCallback.onReady(CameraConstrainedHighSpeedCaptureSessionImpl.this);
    276         }
    277 
    278         public void onActive(CameraCaptureSession session) {
    279             mCallback.onActive(CameraConstrainedHighSpeedCaptureSessionImpl.this);
    280         }
    281 
    282         public void onClosed(CameraCaptureSession session) {
    283             mCallback.onClosed(CameraConstrainedHighSpeedCaptureSessionImpl.this);
    284         }
    285 
    286         public void onSurfacePrepared(CameraCaptureSession session, Surface surface) {
    287             mCallback.onSurfacePrepared(CameraConstrainedHighSpeedCaptureSessionImpl.this,
    288                     surface);
    289         }
    290 
    291 
    292     }
    293 }
    294