LegacyCameraDevice.java revision 0fd198ad89ec9c600bb1761b10d938146c28bb98
1feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/* 2feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Copyright (C) 2014 The Android Open Source Project 3feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 4feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Licensed under the Apache License, Version 2.0 (the "License"); 5feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * you may not use this file except in compliance with the License. 6feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * You may obtain a copy of the License at 7feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 8feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * http://www.apache.org/licenses/LICENSE-2.0 9feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 10feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Unless required by applicable law or agreed to in writing, software 11feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * distributed under the License is distributed on an "AS IS" BASIS, 12feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * See the License for the specific language governing permissions and 14feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * limitations under the License. 15feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 16feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 17feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkpackage android.hardware.camera2.legacy; 18feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 19feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.graphics.ImageFormat; 2028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunkimport android.graphics.SurfaceTexture; 21feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.Camera; 22df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkinimport android.hardware.camera2.CameraCharacteristics; 23feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.CaptureRequest; 24feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.impl.CaptureResultExtras; 25feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.ICameraDeviceCallbacks; 26e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunkimport android.hardware.camera2.params.StreamConfiguration; 27e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunkimport android.hardware.camera2.params.StreamConfigurationMap; 28e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunkimport android.hardware.camera2.utils.ArrayUtils; 294aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunkimport android.hardware.camera2.utils.CameraBinderDecorator; 30feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.utils.LongParcelable; 31feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.impl.CameraMetadataNative; 32feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.utils.CameraRuntimeException; 33feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.ConditionVariable; 34feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.Handler; 35feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.HandlerThread; 36feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.RemoteException; 37feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.util.Log; 38a296fece2b974a11bc624fd67b275863f17df867Igor Murashkinimport android.util.Size; 39feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.view.Surface; 40feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 41feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.ArrayList; 42e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunkimport java.util.Arrays; 433c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunkimport java.util.Collection; 44feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.List; 4549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 46ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkimport static android.hardware.camera2.legacy.LegacyExceptionUtils.*; 4749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkinimport static android.hardware.camera2.utils.CameraBinderDecorator.*; 48a296fece2b974a11bc624fd67b275863f17df867Igor Murashkinimport static com.android.internal.util.Preconditions.*; 49feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 50feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/** 51feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * This class emulates the functionality of a Camera2 device using a the old Camera class. 52feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 53feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p> 54feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * There are two main components that are used to implement this: 55feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * - A state machine containing valid Camera2 device states ({@link CameraDeviceState}). 56feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * - A message-queue based pipeline that manages an old Camera class, and executes capture and 57feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * configuration requests. 58feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p> 59feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 60feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkpublic class LegacyCameraDevice implements AutoCloseable { 61feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public static final String DEBUG_PROP = "HAL1ShimLogging"; 62feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final String TAG; 63feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 64e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk private static final boolean DEBUG = Log.isLoggable(LegacyCameraDevice.DEBUG_PROP, Log.DEBUG); 65feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final int mCameraId; 66e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk private final CameraCharacteristics mStaticCharacteristics; 67feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final ICameraDeviceCallbacks mDeviceCallbacks; 68feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final CameraDeviceState mDeviceState = new CameraDeviceState(); 6949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin private List<Surface> mConfiguredSurfaces; 70e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk private boolean mClosed = false; 71feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 72feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final ConditionVariable mIdle = new ConditionVariable(/*open*/true); 73feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 74d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk private final HandlerThread mResultThread = new HandlerThread("ResultThread"); 75d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk private final HandlerThread mCallbackHandlerThread = new HandlerThread("CallbackThread"); 76feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final Handler mCallbackHandler; 77d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk private final Handler mResultHandler; 78feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private static final int ILLEGAL_VALUE = -1; 79feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 80feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private CaptureResultExtras getExtrasFromRequest(RequestHolder holder) { 81feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (holder == null) { 82feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return new CaptureResultExtras(ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE, 8383159151f618c79040a2e800de8cc78f22bf760bZhijun He ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE); 84feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 85feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return new CaptureResultExtras(holder.getRequestId(), holder.getSubsequeceId(), 8683159151f618c79040a2e800de8cc78f22bf760bZhijun He /*afTriggerId*/0, /*precaptureTriggerId*/0, holder.getFrameNumber(), 8783159151f618c79040a2e800de8cc78f22bf760bZhijun He /*partialResultCount*/1); 88feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 89feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 90feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 91feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Listener for the camera device state machine. Calls the appropriate 92feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * {@link ICameraDeviceCallbacks} for each state transition. 93feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 94feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final CameraDeviceState.CameraDeviceStateListener mStateListener = 95feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk new CameraDeviceState.CameraDeviceStateListener() { 96feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 97e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public void onError(final int errorCode, final RequestHolder holder) { 98feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mIdle.open(); 99feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk final CaptureResultExtras extras = getExtrasFromRequest(holder); 100d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 101d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 102d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 1033e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 104e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.d(TAG, "doing onError callback for request " + holder.getRequestId() + 105e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk ", with error code " + errorCode); 1063e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 107d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 108acc0095bc84914d3ce41ad8298f698c37935b8a8Eino-Ville Talvala mDeviceCallbacks.onDeviceError(errorCode, extras); 109d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 110d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 111d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraError callback: ", e); 112d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 113d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 114d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 115feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 116feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 117feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 118feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void onConfiguring() { 119feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk // Do nothing 1203e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 1213e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk Log.d(TAG, "doing onConfiguring callback."); 1223e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 123feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 124feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 125feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 126feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void onIdle() { 127feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mIdle.open(); 128feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 129d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 130d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 131d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 1323e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 1333e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk Log.d(TAG, "doing onIdle callback."); 1343e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 135d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 136acc0095bc84914d3ce41ad8298f698c37935b8a8Eino-Ville Talvala mDeviceCallbacks.onDeviceIdle(); 137d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 138d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 139d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraIdle callback: ", e); 140d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 141d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 142d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 143feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 144feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 145feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 146e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public void onCaptureStarted(final RequestHolder holder, final long timestamp) { 147feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk final CaptureResultExtras extras = getExtrasFromRequest(holder); 148feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 149d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 150d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 151d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 1523e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 153e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.d(TAG, "doing onCaptureStarted callback for request " + 154e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk holder.getRequestId()); 1553e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 156d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 157d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mDeviceCallbacks.onCaptureStarted(extras, timestamp); 158d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 159d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 160d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraError callback: ", e); 161d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 162d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 163d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 164feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 165feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 166feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 167e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public void onCaptureResult(final CameraMetadataNative result, final RequestHolder holder) { 168feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk final CaptureResultExtras extras = getExtrasFromRequest(holder); 169feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 170d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 171d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 172d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 1733e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 174e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.d(TAG, "doing onCaptureResult callback for request " + 175e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk holder.getRequestId()); 1763e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 177d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 178d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mDeviceCallbacks.onResultReceived(result, extras); 179d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 180d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 181d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraError callback: ", e); 182d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 183d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 184d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 185feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 186feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk }; 187feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 188feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final RequestThreadManager mRequestThreadManager; 189feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 190feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 19191b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk * Check if a given surface uses {@link ImageFormat#YUV_420_888} or format that can be readily 19291b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk * converted to this; YV12 and NV21 are the two currently supported formats. 193feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 194feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param s the surface to check. 19591b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk * @return {@code true} if the surfaces uses {@link ImageFormat#YUV_420_888} or a compatible 19691b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk * format. 197feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 198ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static boolean needsConversion(Surface s) throws BufferQueueAbandonedException { 199ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk int nativeType = detectSurfaceType(s); 20091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk return nativeType == ImageFormat.YUV_420_888 || nativeType == ImageFormat.YV12 || 20191b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk nativeType == ImageFormat.NV21; 202feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 203feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 204feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 205feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Create a new emulated camera device from a given Camera 1 API camera. 206feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 207feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p> 208feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * The {@link Camera} provided to this constructor must already have been successfully opened, 209feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * and ownership of the provided camera is passed to this object. No further calls to the 210feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * camera methods should be made following this constructor. 211feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p> 212feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 213feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param cameraId the id of the camera. 214feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param camera an open {@link Camera} device. 215df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * @param characteristics the static camera characteristics for this camera device 216feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param callbacks {@link ICameraDeviceCallbacks} callbacks to call for Camera2 API operations. 217feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 218df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin public LegacyCameraDevice(int cameraId, Camera camera, CameraCharacteristics characteristics, 219df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin ICameraDeviceCallbacks callbacks) { 220feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCameraId = cameraId; 221feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mDeviceCallbacks = callbacks; 222feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk TAG = String.format("CameraDevice-%d-LE", mCameraId); 223feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 224d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.start(); 225d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler = new Handler(mResultThread.getLooper()); 226feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCallbackHandlerThread.start(); 227feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCallbackHandler = new Handler(mCallbackHandlerThread.getLooper()); 228feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mDeviceState.setCameraDeviceCallbacks(mCallbackHandler, mStateListener); 229e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mStaticCharacteristics = characteristics; 230feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThreadManager = 231df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin new RequestThreadManager(cameraId, camera, characteristics, mDeviceState); 232feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThreadManager.start(); 233feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 234feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 235feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 236feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Configure the device with a set of output surfaces. 237feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 23849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * <p>Using empty or {@code null} {@code outputs} is the same as unconfiguring.</p> 23949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * 24049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * <p>Every surface in {@code outputs} must be non-{@code null}.</p> 24149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * 242feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param outputs a list of surfaces to set. 24349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * @return an error code for this binder operation, or {@link NO_ERROR} 244feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * on success. 245feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 246feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public int configureOutputs(List<Surface> outputs) { 24749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (outputs != null) { 24849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin for (Surface output : outputs) { 24949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (output == null) { 25049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "configureOutputs - null outputs are not allowed"); 25149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin return BAD_VALUE; 25249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 253e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk StreamConfigurationMap streamConfigurations = mStaticCharacteristics. 254e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 255e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 256e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // Validate surface size and format. 257e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk try { 258e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Size s = getSurfaceSize(output); 259e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk int surfaceType = detectSurfaceType(output); 260e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Size[] sizes = streamConfigurations.getOutputSizes(surfaceType); 261e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 262e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if (sizes == null) { 263e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // WAR: Override default format to IMPLEMENTATION_DEFINED for b/9487482 264e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if ((surfaceType >= LegacyMetadataMapper.HAL_PIXEL_FORMAT_RGBA_8888 && 265e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk surfaceType <= LegacyMetadataMapper.HAL_PIXEL_FORMAT_BGRA_8888)) { 266e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 267e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // YUV_420_888 is always present in LEGACY for all IMPLEMENTATION_DEFINED 268e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // output sizes, and is publicly visible in the API (i.e. 269e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // {@code #getOutputSizes} works here). 270e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk sizes = streamConfigurations.getOutputSizes(ImageFormat.YUV_420_888); 271e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } else if (surfaceType == LegacyMetadataMapper.HAL_PIXEL_FORMAT_BLOB) { 272e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk sizes = streamConfigurations.getOutputSizes(ImageFormat.JPEG); 273e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 274e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 275e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 276e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if (!ArrayUtils.contains(sizes, s)) { 277e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk String reason = (sizes == null) ? "format is invalid." : 278e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk ("size not in valid set: " + Arrays.toString(sizes)); 279e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.e(TAG, String.format("Surface with size (w=%d, h=%d) and format 0x%x is" 280e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk + " not valid, %s", s.getWidth(), s.getHeight(), surfaceType, 281e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk reason)); 282e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk return BAD_VALUE; 283e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 284e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } catch (BufferQueueAbandonedException e) { 285e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.e(TAG, "Surface bufferqueue is abandoned, cannot configure as output: ", e); 286e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk return BAD_VALUE; 287e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 288e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 28949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 29049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 29149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 2924aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk boolean success = false; 2934aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk if (mDeviceState.setConfiguring()) { 294feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThreadManager.configure(outputs); 2954aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk success = mDeviceState.setIdle(); 296feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 29749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 2984aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk if (success) { 29949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin mConfiguredSurfaces = outputs != null ? new ArrayList<>(outputs) : null; 3004aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk } else { 3014aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk return CameraBinderDecorator.INVALID_OPERATION; 30249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 3034aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk return CameraBinderDecorator.NO_ERROR; 304feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 305feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 306feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 307feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Submit a burst of capture requests. 308feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 309feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param requestList a list of capture requests to execute. 310feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param repeating {@code true} if this burst is repeating. 311feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param frameNumber an output argument that contains either the frame number of the last frame 312feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * that will be returned for this request, or the frame number of the last 313feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * frame that will be returned for the current repeating request if this 314feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * burst is set to be repeating. 315feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @return the request id. 316feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 317feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public int submitRequestList(List<CaptureRequest> requestList, boolean repeating, 318feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /*out*/LongParcelable frameNumber) { 31949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (requestList == null || requestList.isEmpty()) { 32049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - Empty/null requests are not allowed"); 32149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin return BAD_VALUE; 32249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 32349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 3243c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk List<Long> surfaceIds = (mConfiguredSurfaces == null) ? new ArrayList<Long>() : 3253c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk getSurfaceIds(mConfiguredSurfaces); 3263c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk 32749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin // Make sure that there all requests have at least 1 surface; all surfaces are non-null 32849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin for (CaptureRequest request : requestList) { 32949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (request.getTargets().isEmpty()) { 33049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - " 33149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin + "Each request must have at least one Surface target"); 33249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin return BAD_VALUE; 33349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 33449b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 33549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin for (Surface surface : request.getTargets()) { 33649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (surface == null) { 33749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - Null Surface targets are not allowed"); 33849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin return BAD_VALUE; 33949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } else if (mConfiguredSurfaces == null) { 34049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - must configure " + 34149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin " device with valid surfaces before submitting requests"); 34249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin return INVALID_OPERATION; 3433c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } else if (!containsSurfaceId(surface, surfaceIds)) { 34449b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - cannot use a surface that wasn't configured"); 34549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin return BAD_VALUE; 34649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 34749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 34849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 34949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 35049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin // TODO: further validation of request here 351feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mIdle.close(); 352feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return mRequestThreadManager.submitCaptureRequests(requestList, repeating, 353feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk frameNumber); 354feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 355feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 356feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 357feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Submit a single capture request. 358feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 359feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param request the capture request to execute. 360feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param repeating {@code true} if this request is repeating. 361feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param frameNumber an output argument that contains either the frame number of the last frame 362feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * that will be returned for this request, or the frame number of the last 363feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * frame that will be returned for the current repeating request if this 364feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * request is set to be repeating. 365feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @return the request id. 366feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 367feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public int submitRequest(CaptureRequest request, boolean repeating, 368feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /*out*/LongParcelable frameNumber) { 369feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk ArrayList<CaptureRequest> requestList = new ArrayList<CaptureRequest>(); 370feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk requestList.add(request); 371feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return submitRequestList(requestList, repeating, frameNumber); 372feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 373feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 374feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 375feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Cancel the repeating request with the given request id. 376feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 377feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param requestId the request id of the request to cancel. 378feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @return the last frame number to be returned from the HAL for the given repeating request, or 379feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * {@code INVALID_FRAME} if none exists. 380feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 381feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public long cancelRequest(int requestId) { 382feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return mRequestThreadManager.cancelRepeating(requestId); 383feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 384feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 385feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 386feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Block until the {@link ICameraDeviceCallbacks#onCameraIdle()} callback is received. 387feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 388feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void waitUntilIdle() { 389feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mIdle.block(); 390feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 391feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 392e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk /** 393e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk * Flush any pending requests. 394e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk * 395e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk * @return the last frame number. 396e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk */ 397e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public long flush() { 398e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk long lastFrame = mRequestThreadManager.flush(); 399e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk waitUntilIdle(); 400e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk return lastFrame; 401e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 402e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 403e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk /** 404e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk * Return {@code true} if the device has been closed. 405e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk */ 406e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public boolean isClosed() { 407e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk return mClosed; 408e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 409e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 410feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 411feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void close() { 412feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThreadManager.quit(); 413feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCallbackHandlerThread.quitSafely(); 414d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.quitSafely(); 415d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 416d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 417d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mCallbackHandlerThread.join(); 418d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (InterruptedException e) { 419d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk Log.e(TAG, String.format("Thread %s (%d) interrupted while quitting.", 420d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mCallbackHandlerThread.getName(), mCallbackHandlerThread.getId())); 421d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 422d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 423d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 424d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.join(); 425d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (InterruptedException e) { 426d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk Log.e(TAG, String.format("Thread %s (%d) interrupted while quitting.", 427d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.getName(), mResultThread.getId())); 428d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 429d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 430e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mClosed = true; 431feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 432feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 433feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 434feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk protected void finalize() throws Throwable { 435feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk try { 436feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk close(); 437feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } catch (CameraRuntimeException e) { 438feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk Log.e(TAG, "Got error while trying to finalize, ignoring: " + e.getMessage()); 439feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } finally { 440feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk super.finalize(); 441feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 442feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 443feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 444a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin /** 445a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * Query the surface for its currently configured default buffer size. 446a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * @param surface a non-{@code null} {@code Surface} 447a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * @return the width and height of the surface 448a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * 449a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * @throws NullPointerException if the {@code surface} was {@code null} 450a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * @throws IllegalStateException if the {@code surface} was invalid 451a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin */ 452ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static Size getSurfaceSize(Surface surface) throws BufferQueueAbandonedException { 453a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin checkNotNull(surface); 454a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 455a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin int[] dimens = new int[2]; 456ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeDetectSurfaceDimens(surface, /*out*/dimens)); 457a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 458a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin return new Size(dimens[0], dimens[1]); 459a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin } 460a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 461ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static int detectSurfaceType(Surface surface) throws BufferQueueAbandonedException { 462ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 463ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk return LegacyExceptionUtils.throwOnError(nativeDetectSurfaceType(surface)); 464ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 465ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 466ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static void configureSurface(Surface surface, int width, int height, 467ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk int pixelFormat) throws BufferQueueAbandonedException { 468ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 469ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(width, "width must be positive."); 470ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(height, "height must be positive."); 471ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 472ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeConfigureSurface(surface, width, height, 473ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk pixelFormat)); 474ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 475ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 476ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static void produceFrame(Surface surface, byte[] pixelBuffer, int width, 477ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk int height, int pixelFormat) 478ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk throws BufferQueueAbandonedException { 479ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 480ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(pixelBuffer); 481ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(width, "width must be positive."); 482ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(height, "height must be positive."); 483ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 484ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeProduceFrame(surface, pixelBuffer, width, height, 485ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk pixelFormat)); 486ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 487ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 488ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static void setSurfaceFormat(Surface surface, int pixelFormat) 489ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk throws BufferQueueAbandonedException { 490ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 491ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 492ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeSetSurfaceFormat(surface, pixelFormat)); 493ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 494ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 495ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static void setSurfaceDimens(Surface surface, int width, int height) 496ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk throws BufferQueueAbandonedException { 497ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 498ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(width, "width must be positive."); 499ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(height, "height must be positive."); 500ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 501ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeSetSurfaceDimens(surface, width, height)); 502ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 503ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 5043c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk static long getSurfaceId(Surface surface) { 5053c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk checkNotNull(surface); 5063c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk return nativeGetSurfaceId(surface); 5073c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 5083c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk 5093c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk static List<Long> getSurfaceIds(Collection<Surface> surfaces) { 5103c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk if (surfaces == null) { 5113c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk throw new NullPointerException("Null argument surfaces"); 5123c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 5133c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk List<Long> surfaceIds = new ArrayList<>(); 5143c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk for (Surface s : surfaces) { 5153c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk long id = getSurfaceId(s); 5163c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk if (id == 0) { 5173c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk throw new IllegalStateException( 5183c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk "Configured surface had null native GraphicBufferProducer pointer!"); 5193c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 5203c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk surfaceIds.add(id); 5213c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 5223c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk return surfaceIds; 5233c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 5243c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk 5250fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk static boolean containsSurfaceId(Surface s, Collection<Long> ids) { 5263c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk long id = getSurfaceId(s); 5273c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk return ids.contains(id); 5283c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 5293c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk 53028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk static void setSurfaceOrientation(Surface surface, int facing, int sensorOrientation) 53128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk throws BufferQueueAbandonedException { 53228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk checkNotNull(surface); 53328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk LegacyExceptionUtils.throwOnError(nativeSetSurfaceOrientation(surface, facing, 53428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk sensorOrientation)); 53528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk } 53628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 53728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk static Size getTextureSize(SurfaceTexture surfaceTexture) 53828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk throws BufferQueueAbandonedException { 53928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk checkNotNull(surfaceTexture); 54028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 54128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk int[] dimens = new int[2]; 54228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk LegacyExceptionUtils.throwOnError(nativeDetectTextureDimens(surfaceTexture, 54328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk /*out*/dimens)); 54428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 54528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk return new Size(dimens[0], dimens[1]); 54628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk } 54728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 54891838ded36131525312739c0929913b215519c2aRuben Brunk static void setNextTimestamp(Surface surface, long timestamp) 54991838ded36131525312739c0929913b215519c2aRuben Brunk throws BufferQueueAbandonedException { 55091838ded36131525312739c0929913b215519c2aRuben Brunk checkNotNull(surface); 55191838ded36131525312739c0929913b215519c2aRuben Brunk LegacyExceptionUtils.throwOnError(nativeSetNextTimestamp(surface, timestamp)); 55291838ded36131525312739c0929913b215519c2aRuben Brunk } 55391838ded36131525312739c0929913b215519c2aRuben Brunk 554ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeDetectSurfaceType(Surface surface); 555feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 556ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeDetectSurfaceDimens(Surface surface, 557a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin /*out*/int[/*2*/] dimens); 558feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 559ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeConfigureSurface(Surface surface, int width, int height, 560feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk int pixelFormat); 561feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 562ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeProduceFrame(Surface surface, byte[] pixelBuffer, int width, 563feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk int height, int pixelFormat); 564feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 565ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeSetSurfaceFormat(Surface surface, int pixelFormat); 566feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 567ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeSetSurfaceDimens(Surface surface, int width, int height); 568feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 5693c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk private static native long nativeGetSurfaceId(Surface surface); 57028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 57128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk private static native int nativeSetSurfaceOrientation(Surface surface, int facing, 57228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk int sensorOrientation); 57328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 57428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk private static native int nativeDetectTextureDimens(SurfaceTexture surfaceTexture, 57528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk /*out*/int[/*2*/] dimens); 57628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 57791838ded36131525312739c0929913b215519c2aRuben Brunk private static native int nativeSetNextTimestamp(Surface surface, long timestamp); 5781dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk 5791dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk static native int nativeGetJpegFooterSize(); 580feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk} 581