LegacyCameraDevice.java revision e663cb77281c4c76241b820f6126543f1c2d859f
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; 29feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.utils.LongParcelable; 30feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.impl.CameraMetadataNative; 31feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.utils.CameraRuntimeException; 32feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.ConditionVariable; 33feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.Handler; 34feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.HandlerThread; 35feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.RemoteException; 36feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.util.Log; 37a296fece2b974a11bc624fd67b275863f17df867Igor Murashkinimport android.util.Size; 38feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.view.Surface; 39feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 40feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.ArrayList; 41e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunkimport java.util.Arrays; 423c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunkimport java.util.Collection; 43feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.List; 4449b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 45ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkimport static android.hardware.camera2.legacy.LegacyExceptionUtils.*; 4649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkinimport static android.hardware.camera2.utils.CameraBinderDecorator.*; 47a296fece2b974a11bc624fd67b275863f17df867Igor Murashkinimport static com.android.internal.util.Preconditions.*; 48feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 49feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/** 50feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * This class emulates the functionality of a Camera2 device using a the old Camera class. 51feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 52feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p> 53feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * There are two main components that are used to implement this: 54feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * - A state machine containing valid Camera2 device states ({@link CameraDeviceState}). 55feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * - A message-queue based pipeline that manages an old Camera class, and executes capture and 56feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * configuration requests. 57feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p> 58feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 59feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkpublic class LegacyCameraDevice implements AutoCloseable { 60feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public static final String DEBUG_PROP = "HAL1ShimLogging"; 61feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final String TAG; 62feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 63e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk private static final boolean DEBUG = Log.isLoggable(LegacyCameraDevice.DEBUG_PROP, Log.DEBUG); 64feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final int mCameraId; 65e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk private final CameraCharacteristics mStaticCharacteristics; 66feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final ICameraDeviceCallbacks mDeviceCallbacks; 67feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final CameraDeviceState mDeviceState = new CameraDeviceState(); 6849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin private List<Surface> mConfiguredSurfaces; 69e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk private boolean mClosed = false; 70feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 71feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final ConditionVariable mIdle = new ConditionVariable(/*open*/true); 72feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 73d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk private final HandlerThread mResultThread = new HandlerThread("ResultThread"); 74d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk private final HandlerThread mCallbackHandlerThread = new HandlerThread("CallbackThread"); 75feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final Handler mCallbackHandler; 76d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk private final Handler mResultHandler; 77feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private static final int ILLEGAL_VALUE = -1; 78feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 79feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private CaptureResultExtras getExtrasFromRequest(RequestHolder holder) { 80feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (holder == null) { 81feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return new CaptureResultExtras(ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE, 8283159151f618c79040a2e800de8cc78f22bf760bZhijun He ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE); 83feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 84feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return new CaptureResultExtras(holder.getRequestId(), holder.getSubsequeceId(), 8583159151f618c79040a2e800de8cc78f22bf760bZhijun He /*afTriggerId*/0, /*precaptureTriggerId*/0, holder.getFrameNumber(), 8683159151f618c79040a2e800de8cc78f22bf760bZhijun He /*partialResultCount*/1); 87feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 88feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 89feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 90feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Listener for the camera device state machine. Calls the appropriate 91feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * {@link ICameraDeviceCallbacks} for each state transition. 92feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 93feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final CameraDeviceState.CameraDeviceStateListener mStateListener = 94feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk new CameraDeviceState.CameraDeviceStateListener() { 95feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 96e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public void onError(final int errorCode, final RequestHolder holder) { 97feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mIdle.open(); 98feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk final CaptureResultExtras extras = getExtrasFromRequest(holder); 99d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 100d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 101d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 1023e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 103e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.d(TAG, "doing onError callback for request " + holder.getRequestId() + 104e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk ", with error code " + errorCode); 1053e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 106d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 107acc0095bc84914d3ce41ad8298f698c37935b8a8Eino-Ville Talvala mDeviceCallbacks.onDeviceError(errorCode, extras); 108d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 109d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 110d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraError callback: ", e); 111d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 112d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 113d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 114feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 115feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 116feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 117feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void onConfiguring() { 118feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk // Do nothing 1193e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 1203e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk Log.d(TAG, "doing onConfiguring callback."); 1213e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 122feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 123feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 124feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 125feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void onIdle() { 126feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mIdle.open(); 127feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 128d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 129d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 130d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 1313e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 1323e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk Log.d(TAG, "doing onIdle callback."); 1333e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 134d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 135acc0095bc84914d3ce41ad8298f698c37935b8a8Eino-Ville Talvala mDeviceCallbacks.onDeviceIdle(); 136d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 137d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 138d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraIdle callback: ", e); 139d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 140d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 141d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 142feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 143feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 144feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 145e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public void onCaptureStarted(final RequestHolder holder, final long timestamp) { 146feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk final CaptureResultExtras extras = getExtrasFromRequest(holder); 147feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 148d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 149d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 150d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 1513e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 152e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.d(TAG, "doing onCaptureStarted callback for request " + 153e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk holder.getRequestId()); 1543e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 155d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 156d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mDeviceCallbacks.onCaptureStarted(extras, timestamp); 157d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 158d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 159d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraError callback: ", e); 160d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 161d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 162d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 163feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 164feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 165feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 166e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public void onCaptureResult(final CameraMetadataNative result, final RequestHolder holder) { 167feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk final CaptureResultExtras extras = getExtrasFromRequest(holder); 168feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 169d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 170d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 171d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 1723e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 173e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.d(TAG, "doing onCaptureResult callback for request " + 174e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk holder.getRequestId()); 1753e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 176d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 177d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mDeviceCallbacks.onResultReceived(result, extras); 178d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 179d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 180d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraError callback: ", e); 181d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 182d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 183d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 184feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 185feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk }; 186feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 187feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final RequestThreadManager mRequestThreadManager; 188feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 189feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 19091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk * Check if a given surface uses {@link ImageFormat#YUV_420_888} or format that can be readily 19191b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk * converted to this; YV12 and NV21 are the two currently supported formats. 192feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 193feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param s the surface to check. 19491b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk * @return {@code true} if the surfaces uses {@link ImageFormat#YUV_420_888} or a compatible 19591b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk * format. 196feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 197ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static boolean needsConversion(Surface s) throws BufferQueueAbandonedException { 198ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk int nativeType = detectSurfaceType(s); 19991b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk return nativeType == ImageFormat.YUV_420_888 || nativeType == ImageFormat.YV12 || 20091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk nativeType == ImageFormat.NV21; 201feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 202feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 203feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 204feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Create a new emulated camera device from a given Camera 1 API camera. 205feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 206feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p> 207feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * The {@link Camera} provided to this constructor must already have been successfully opened, 208feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * and ownership of the provided camera is passed to this object. No further calls to the 209feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * camera methods should be made following this constructor. 210feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p> 211feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 212feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param cameraId the id of the camera. 213feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param camera an open {@link Camera} device. 214df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * @param characteristics the static camera characteristics for this camera device 215feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param callbacks {@link ICameraDeviceCallbacks} callbacks to call for Camera2 API operations. 216feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 217df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin public LegacyCameraDevice(int cameraId, Camera camera, CameraCharacteristics characteristics, 218df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin ICameraDeviceCallbacks callbacks) { 219feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCameraId = cameraId; 220feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mDeviceCallbacks = callbacks; 221feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk TAG = String.format("CameraDevice-%d-LE", mCameraId); 222feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 223d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.start(); 224d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler = new Handler(mResultThread.getLooper()); 225feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCallbackHandlerThread.start(); 226feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCallbackHandler = new Handler(mCallbackHandlerThread.getLooper()); 227feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mDeviceState.setCameraDeviceCallbacks(mCallbackHandler, mStateListener); 228e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mStaticCharacteristics = characteristics; 229feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThreadManager = 230df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin new RequestThreadManager(cameraId, camera, characteristics, mDeviceState); 231feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThreadManager.start(); 232feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 233feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 234feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 235feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Configure the device with a set of output surfaces. 236feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 23749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * <p>Using empty or {@code null} {@code outputs} is the same as unconfiguring.</p> 23849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * 23949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * <p>Every surface in {@code outputs} must be non-{@code null}.</p> 24049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * 241feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param outputs a list of surfaces to set. 24249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * @return an error code for this binder operation, or {@link NO_ERROR} 243feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * on success. 244feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 245feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public int configureOutputs(List<Surface> outputs) { 24649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (outputs != null) { 24749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin for (Surface output : outputs) { 24849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (output == null) { 24949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "configureOutputs - null outputs are not allowed"); 25049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin return BAD_VALUE; 25149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 252e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk StreamConfigurationMap streamConfigurations = mStaticCharacteristics. 253e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 254e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 255e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // Validate surface size and format. 256e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk try { 257e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Size s = getSurfaceSize(output); 258e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk int surfaceType = detectSurfaceType(output); 259e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Size[] sizes = streamConfigurations.getOutputSizes(surfaceType); 260e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 261e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if (sizes == null) { 262e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // WAR: Override default format to IMPLEMENTATION_DEFINED for b/9487482 263e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if ((surfaceType >= LegacyMetadataMapper.HAL_PIXEL_FORMAT_RGBA_8888 && 264e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk surfaceType <= LegacyMetadataMapper.HAL_PIXEL_FORMAT_BGRA_8888)) { 265e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 266e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // YUV_420_888 is always present in LEGACY for all IMPLEMENTATION_DEFINED 267e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // output sizes, and is publicly visible in the API (i.e. 268e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // {@code #getOutputSizes} works here). 269e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk sizes = streamConfigurations.getOutputSizes(ImageFormat.YUV_420_888); 270e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } else if (surfaceType == LegacyMetadataMapper.HAL_PIXEL_FORMAT_BLOB) { 271e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk sizes = streamConfigurations.getOutputSizes(ImageFormat.JPEG); 272e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 273e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 274e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 275e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if (!ArrayUtils.contains(sizes, s)) { 276e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk String reason = (sizes == null) ? "format is invalid." : 277e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk ("size not in valid set: " + Arrays.toString(sizes)); 278e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.e(TAG, String.format("Surface with size (w=%d, h=%d) and format 0x%x is" 279e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk + " not valid, %s", s.getWidth(), s.getHeight(), surfaceType, 280e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk reason)); 281e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk return BAD_VALUE; 282e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 283e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } catch (BufferQueueAbandonedException e) { 284e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.e(TAG, "Surface bufferqueue is abandoned, cannot configure as output: ", e); 285e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk return BAD_VALUE; 286e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 287e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 28849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 28949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 29049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 291feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk int error = mDeviceState.setConfiguring(); 29249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (error == NO_ERROR) { 293feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThreadManager.configure(outputs); 294feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk error = mDeviceState.setIdle(); 295feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 29649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 29749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (error == NO_ERROR) { 29849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin mConfiguredSurfaces = outputs != null ? new ArrayList<>(outputs) : null; 29949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 30049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 301feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return error; 302feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 303feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 304feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 305feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Submit a burst of capture requests. 306feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 307feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param requestList a list of capture requests to execute. 308feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param repeating {@code true} if this burst is repeating. 309feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param frameNumber an output argument that contains either the frame number of the last frame 310feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * that will be returned for this request, or the frame number of the last 311feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * frame that will be returned for the current repeating request if this 312feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * burst is set to be repeating. 313feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @return the request id. 314feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 315feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public int submitRequestList(List<CaptureRequest> requestList, boolean repeating, 316feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /*out*/LongParcelable frameNumber) { 31749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (requestList == null || requestList.isEmpty()) { 31849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - Empty/null requests are not allowed"); 31949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin return BAD_VALUE; 32049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 32149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 3223c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk List<Long> surfaceIds = (mConfiguredSurfaces == null) ? new ArrayList<Long>() : 3233c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk getSurfaceIds(mConfiguredSurfaces); 3243c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk 32549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin // Make sure that there all requests have at least 1 surface; all surfaces are non-null 32649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin for (CaptureRequest request : requestList) { 32749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (request.getTargets().isEmpty()) { 32849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - " 32949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin + "Each request must have at least one Surface target"); 33049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin return BAD_VALUE; 33149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 33249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 33349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin for (Surface surface : request.getTargets()) { 33449b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (surface == null) { 33549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - Null Surface targets are not allowed"); 33649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin return BAD_VALUE; 33749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } else if (mConfiguredSurfaces == null) { 33849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - must configure " + 33949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin " device with valid surfaces before submitting requests"); 34049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin return INVALID_OPERATION; 3413c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } else if (!containsSurfaceId(surface, surfaceIds)) { 34249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - cannot use a surface that wasn't configured"); 34349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin return BAD_VALUE; 34449b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 34549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 34649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 34749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 34849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin // TODO: further validation of request here 349feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mIdle.close(); 350feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return mRequestThreadManager.submitCaptureRequests(requestList, repeating, 351feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk frameNumber); 352feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 353feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 354feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 355feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Submit a single capture request. 356feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 357feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param request the capture request to execute. 358feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param repeating {@code true} if this request is repeating. 359feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param frameNumber an output argument that contains either the frame number of the last frame 360feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * that will be returned for this request, or the frame number of the last 361feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * frame that will be returned for the current repeating request if this 362feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * request is set to be repeating. 363feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @return the request id. 364feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 365feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public int submitRequest(CaptureRequest request, boolean repeating, 366feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /*out*/LongParcelable frameNumber) { 367feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk ArrayList<CaptureRequest> requestList = new ArrayList<CaptureRequest>(); 368feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk requestList.add(request); 369feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return submitRequestList(requestList, repeating, frameNumber); 370feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 371feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 372feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 373feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Cancel the repeating request with the given request id. 374feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 375feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param requestId the request id of the request to cancel. 376feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @return the last frame number to be returned from the HAL for the given repeating request, or 377feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * {@code INVALID_FRAME} if none exists. 378feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 379feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public long cancelRequest(int requestId) { 380feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return mRequestThreadManager.cancelRepeating(requestId); 381feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 382feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 383feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 384feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Block until the {@link ICameraDeviceCallbacks#onCameraIdle()} callback is received. 385feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 386feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void waitUntilIdle() { 387feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mIdle.block(); 388feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 389feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 390e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk /** 391e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk * Flush any pending requests. 392e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk * 393e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk * @return the last frame number. 394e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk */ 395e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public long flush() { 396e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk long lastFrame = mRequestThreadManager.flush(); 397e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk waitUntilIdle(); 398e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk return lastFrame; 399e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 400e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 401e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk /** 402e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk * Return {@code true} if the device has been closed. 403e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk */ 404e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public boolean isClosed() { 405e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk return mClosed; 406e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 407e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 408feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 409feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void close() { 410feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThreadManager.quit(); 411feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCallbackHandlerThread.quitSafely(); 412d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.quitSafely(); 413d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 414d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 415d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mCallbackHandlerThread.join(); 416d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (InterruptedException e) { 417d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk Log.e(TAG, String.format("Thread %s (%d) interrupted while quitting.", 418d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mCallbackHandlerThread.getName(), mCallbackHandlerThread.getId())); 419d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 420d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 421d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 422d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.join(); 423d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (InterruptedException e) { 424d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk Log.e(TAG, String.format("Thread %s (%d) interrupted while quitting.", 425d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.getName(), mResultThread.getId())); 426d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 427d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 428e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mClosed = true; 429feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 430feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 431feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 432feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk protected void finalize() throws Throwable { 433feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk try { 434feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk close(); 435feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } catch (CameraRuntimeException e) { 436feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk Log.e(TAG, "Got error while trying to finalize, ignoring: " + e.getMessage()); 437feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } finally { 438feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk super.finalize(); 439feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 440feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 441feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 442a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin /** 443a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * Query the surface for its currently configured default buffer size. 444a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * @param surface a non-{@code null} {@code Surface} 445a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * @return the width and height of the surface 446a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * 447a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * @throws NullPointerException if the {@code surface} was {@code null} 448a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * @throws IllegalStateException if the {@code surface} was invalid 449a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin */ 450ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static Size getSurfaceSize(Surface surface) throws BufferQueueAbandonedException { 451a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin checkNotNull(surface); 452a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 453a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin int[] dimens = new int[2]; 454ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeDetectSurfaceDimens(surface, /*out*/dimens)); 455a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 456a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin return new Size(dimens[0], dimens[1]); 457a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin } 458a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 459ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static int detectSurfaceType(Surface surface) throws BufferQueueAbandonedException { 460ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 461ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk return LegacyExceptionUtils.throwOnError(nativeDetectSurfaceType(surface)); 462ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 463ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 464ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static void configureSurface(Surface surface, int width, int height, 465ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk int pixelFormat) throws BufferQueueAbandonedException { 466ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 467ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(width, "width must be positive."); 468ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(height, "height must be positive."); 469ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 470ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeConfigureSurface(surface, width, height, 471ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk pixelFormat)); 472ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 473ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 474ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static void produceFrame(Surface surface, byte[] pixelBuffer, int width, 475ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk int height, int pixelFormat) 476ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk throws BufferQueueAbandonedException { 477ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 478ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(pixelBuffer); 479ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(width, "width must be positive."); 480ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(height, "height must be positive."); 481ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 482ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeProduceFrame(surface, pixelBuffer, width, height, 483ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk pixelFormat)); 484ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 485ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 486ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static void setSurfaceFormat(Surface surface, int pixelFormat) 487ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk throws BufferQueueAbandonedException { 488ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 489ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 490ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeSetSurfaceFormat(surface, pixelFormat)); 491ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 492ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 493ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static void setSurfaceDimens(Surface surface, int width, int height) 494ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk throws BufferQueueAbandonedException { 495ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 496ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(width, "width must be positive."); 497ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(height, "height must be positive."); 498ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 499ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeSetSurfaceDimens(surface, width, height)); 500ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 501ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 5023c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk static long getSurfaceId(Surface surface) { 5033c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk checkNotNull(surface); 5043c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk return nativeGetSurfaceId(surface); 5053c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 5063c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk 5073c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk static List<Long> getSurfaceIds(Collection<Surface> surfaces) { 5083c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk if (surfaces == null) { 5093c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk throw new NullPointerException("Null argument surfaces"); 5103c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 5113c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk List<Long> surfaceIds = new ArrayList<>(); 5123c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk for (Surface s : surfaces) { 5133c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk long id = getSurfaceId(s); 5143c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk if (id == 0) { 5153c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk throw new IllegalStateException( 5163c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk "Configured surface had null native GraphicBufferProducer pointer!"); 5173c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 5183c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk surfaceIds.add(id); 5193c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 5203c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk return surfaceIds; 5213c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 5223c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk 5233c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk static boolean containsSurfaceId(Surface s, List<Long> ids) { 5243c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk long id = getSurfaceId(s); 5253c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk return ids.contains(id); 5263c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 5273c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk 52828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk static void setSurfaceOrientation(Surface surface, int facing, int sensorOrientation) 52928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk throws BufferQueueAbandonedException { 53028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk checkNotNull(surface); 53128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk LegacyExceptionUtils.throwOnError(nativeSetSurfaceOrientation(surface, facing, 53228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk sensorOrientation)); 53328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk } 53428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 53528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk static Size getTextureSize(SurfaceTexture surfaceTexture) 53628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk throws BufferQueueAbandonedException { 53728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk checkNotNull(surfaceTexture); 53828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 53928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk int[] dimens = new int[2]; 54028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk LegacyExceptionUtils.throwOnError(nativeDetectTextureDimens(surfaceTexture, 54128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk /*out*/dimens)); 54228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 54328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk return new Size(dimens[0], dimens[1]); 54428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk } 54528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 54691838ded36131525312739c0929913b215519c2aRuben Brunk static void setNextTimestamp(Surface surface, long timestamp) 54791838ded36131525312739c0929913b215519c2aRuben Brunk throws BufferQueueAbandonedException { 54891838ded36131525312739c0929913b215519c2aRuben Brunk checkNotNull(surface); 54991838ded36131525312739c0929913b215519c2aRuben Brunk LegacyExceptionUtils.throwOnError(nativeSetNextTimestamp(surface, timestamp)); 55091838ded36131525312739c0929913b215519c2aRuben Brunk } 55191838ded36131525312739c0929913b215519c2aRuben Brunk 552ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeDetectSurfaceType(Surface surface); 553feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 554ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeDetectSurfaceDimens(Surface surface, 555a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin /*out*/int[/*2*/] dimens); 556feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 557ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeConfigureSurface(Surface surface, int width, int height, 558feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk int pixelFormat); 559feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 560ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeProduceFrame(Surface surface, byte[] pixelBuffer, int width, 561feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk int height, int pixelFormat); 562feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 563ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeSetSurfaceFormat(Surface surface, int pixelFormat); 564feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 565ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeSetSurfaceDimens(Surface surface, int width, int height); 566feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 5673c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk private static native long nativeGetSurfaceId(Surface surface); 56828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 56928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk private static native int nativeSetSurfaceOrientation(Surface surface, int facing, 57028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk int sensorOrientation); 57128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 57228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk private static native int nativeDetectTextureDimens(SurfaceTexture surfaceTexture, 57328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk /*out*/int[/*2*/] dimens); 57428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 57591838ded36131525312739c0929913b215519c2aRuben Brunk private static native int nativeSetNextTimestamp(Surface surface, long timestamp); 5761dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk 5771dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk static native int nativeGetJpegFooterSize(); 578feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk} 579