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; 2451dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkinimport android.hardware.camera2.impl.CameraDeviceImpl; 25feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.impl.CaptureResultExtras; 26feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.ICameraDeviceCallbacks; 27e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunkimport android.hardware.camera2.params.StreamConfigurationMap; 28e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunkimport android.hardware.camera2.utils.ArrayUtils; 295d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvalaimport android.hardware.camera2.utils.SubmitInfo; 30feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.impl.CameraMetadataNative; 31feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.ConditionVariable; 32feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.Handler; 33feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.HandlerThread; 34feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.RemoteException; 355d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvalaimport android.os.ServiceSpecificException; 36feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.util.Log; 37f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunkimport android.util.Pair; 38a296fece2b974a11bc624fd67b275863f17df867Igor Murashkinimport android.util.Size; 39385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvalaimport android.util.SparseArray; 40feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.view.Surface; 41feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 42feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.ArrayList; 43e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunkimport java.util.Arrays; 443c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunkimport java.util.Collection; 45feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.List; 4649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 47ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkimport static android.hardware.camera2.legacy.LegacyExceptionUtils.*; 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 private final String TAG; 62feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 63a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala private static final boolean DEBUG = false; 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(); 68385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala private SparseArray<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 79f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk // Keep up to date with values in hardware/libhardware/include/hardware/gralloc.h 80f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk private static final int GRALLOC_USAGE_RENDERSCRIPT = 0x00100000; 81f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk private static final int GRALLOC_USAGE_SW_READ_OFTEN = 0x00000003; 82f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk private static final int GRALLOC_USAGE_HW_TEXTURE = 0x00000100; 83f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk private static final int GRALLOC_USAGE_HW_COMPOSER = 0x00000800; 84a7677722304670dc07feef242156b97e6bb51bcdZhijun He private static final int GRALLOC_USAGE_HW_RENDER = 0x00000200; 85f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk private static final int GRALLOC_USAGE_HW_VIDEO_ENCODER = 0x00010000; 86f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk 8768e4fc8ca9b923bc6d053589329eab8509d625abRuben Brunk public static final int MAX_DIMEN_FOR_ROUNDING = 1920; // maximum allowed width for rounding 88f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk 89a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk // Keep up to date with values in system/core/include/system/window.h 90a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk public static final int NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW = 1; 91a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk 92feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private CaptureResultExtras getExtrasFromRequest(RequestHolder holder) { 93385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala return getExtrasFromRequest(holder, 94385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala /*errorCode*/CameraDeviceState.NO_CAPTURE_ERROR, /*errorArg*/null); 95385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala } 96385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala 97385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala private CaptureResultExtras getExtrasFromRequest(RequestHolder holder, 98385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala int errorCode, Object errorArg) { 99385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala int errorStreamId = -1; 100385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala if (errorCode == CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_BUFFER) { 101385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala Surface errorTarget = (Surface) errorArg; 102385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala int indexOfTarget = mConfiguredSurfaces.indexOfValue(errorTarget); 103385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala if (indexOfTarget < 0) { 104385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala Log.e(TAG, "Buffer drop error reported for unknown Surface"); 105385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala } else { 106385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala errorStreamId = mConfiguredSurfaces.keyAt(indexOfTarget); 107385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala } 108385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala } 109feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (holder == null) { 110feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return new CaptureResultExtras(ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE, 1113e0023ae89895f215791a8472f22b213f5a9ae93Eino-Ville Talvala ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE); 112feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 113feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return new CaptureResultExtras(holder.getRequestId(), holder.getSubsequeceId(), 11483159151f618c79040a2e800de8cc78f22bf760bZhijun He /*afTriggerId*/0, /*precaptureTriggerId*/0, holder.getFrameNumber(), 115385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala /*partialResultCount*/1, errorStreamId); 116feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 117feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 118feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 119feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Listener for the camera device state machine. Calls the appropriate 120feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * {@link ICameraDeviceCallbacks} for each state transition. 121feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 122feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final CameraDeviceState.CameraDeviceStateListener mStateListener = 123feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk new CameraDeviceState.CameraDeviceStateListener() { 124feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 125385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala public void onError(final int errorCode, final Object errorArg, final RequestHolder holder) { 12651dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin if (DEBUG) { 127385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala Log.d(TAG, "onError called, errorCode = " + errorCode + ", errorArg = " + errorArg); 12851dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin } 12951dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin switch (errorCode) { 13051dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin /* 13151dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin * Only be considered idle if we hit a fatal error 13251dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin * and no further requests can be processed. 13351dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin */ 13451dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin case CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DISCONNECTED: 13551dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin case CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_SERVICE: 13651dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin case CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE: { 13751dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin mIdle.open(); 13851dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin 13951dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin if (DEBUG) { 14051dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin Log.d(TAG, "onError - opening idle"); 14151dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin } 14251dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin } 14351dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin } 14451dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin 145385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala final CaptureResultExtras extras = getExtrasFromRequest(holder, errorCode, errorArg); 146d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 147d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 148d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 1493e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 150e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.d(TAG, "doing onError callback for request " + holder.getRequestId() + 151e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk ", with error code " + errorCode); 1523e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 153d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 154acc0095bc84914d3ce41ad8298f698c37935b8a8Eino-Ville Talvala mDeviceCallbacks.onDeviceError(errorCode, extras); 155d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 156d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 157d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraError callback: ", e); 158d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 159d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 160d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 161feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 162feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 163feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 164feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void onConfiguring() { 165feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk // Do nothing 1663e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 1673e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk Log.d(TAG, "doing onConfiguring callback."); 1683e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 169feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 170feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 171feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 172feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void onIdle() { 17351dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin if (DEBUG) { 17451dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin Log.d(TAG, "onIdle called"); 17551dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin } 17651dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin 177feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mIdle.open(); 178feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 179d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 180d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 181d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 1823e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 1833e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk Log.d(TAG, "doing onIdle callback."); 1843e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 185d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 186acc0095bc84914d3ce41ad8298f698c37935b8a8Eino-Ville Talvala mDeviceCallbacks.onDeviceIdle(); 187d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 188d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 189d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraIdle callback: ", e); 190d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 191d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 192d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 193feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 194feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 195feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 19651dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin public void onBusy() { 19751dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin mIdle.close(); 19851dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin 19951dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin if (DEBUG) { 20051dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin Log.d(TAG, "onBusy called"); 20151dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin } 20251dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin } 20351dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin 20451dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin @Override 205e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public void onCaptureStarted(final RequestHolder holder, final long timestamp) { 206feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk final CaptureResultExtras extras = getExtrasFromRequest(holder); 207feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 208d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 209d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 210d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 2113e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 212e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.d(TAG, "doing onCaptureStarted callback for request " + 213e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk holder.getRequestId()); 2143e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 215d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 216d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mDeviceCallbacks.onCaptureStarted(extras, timestamp); 217d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 218d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 219d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraError callback: ", e); 220d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 221d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 222d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 223feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 224feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 225feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 226e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public void onCaptureResult(final CameraMetadataNative result, final RequestHolder holder) { 227feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk final CaptureResultExtras extras = getExtrasFromRequest(holder); 228feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 229d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler.post(new Runnable() { 230d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk @Override 231d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk public void run() { 2323e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 233e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.d(TAG, "doing onCaptureResult callback for request " + 234e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk holder.getRequestId()); 2353e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 236d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 237d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mDeviceCallbacks.onResultReceived(result, extras); 238d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (RemoteException e) { 239d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 240d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Received remote exception during onCameraError callback: ", e); 241d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 242d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 243d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk }); 244feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 2452da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen 2462da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen @Override 2472da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen public void onRepeatingRequestError(final long lastFrameNumber) { 2482da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen mResultHandler.post(new Runnable() { 2492da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen @Override 2502da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen public void run() { 2512da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen if (DEBUG) { 2522da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen Log.d(TAG, "doing onRepeatingRequestError callback."); 2532da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } 2542da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen try { 2552da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen mDeviceCallbacks.onRepeatingRequestError(lastFrameNumber); 2562da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } catch (RemoteException e) { 2572da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen throw new IllegalStateException( 2582da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen "Received remote exception during onRepeatingRequestError " + 2592da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen "callback: ", e); 2602da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } 2612da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } 2622da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen }); 2632da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } 264feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk }; 265feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 266feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final RequestThreadManager mRequestThreadManager; 267feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 268feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 26991b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk * Check if a given surface uses {@link ImageFormat#YUV_420_888} or format that can be readily 27091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk * converted to this; YV12 and NV21 are the two currently supported formats. 271feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 272feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param s the surface to check. 27391b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk * @return {@code true} if the surfaces uses {@link ImageFormat#YUV_420_888} or a compatible 27491b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk * format. 275feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 276ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static boolean needsConversion(Surface s) throws BufferQueueAbandonedException { 277ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk int nativeType = detectSurfaceType(s); 27891b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk return nativeType == ImageFormat.YUV_420_888 || nativeType == ImageFormat.YV12 || 27991b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk nativeType == ImageFormat.NV21; 280feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 281feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 282feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 283feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Create a new emulated camera device from a given Camera 1 API camera. 284feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 285feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p> 286feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * The {@link Camera} provided to this constructor must already have been successfully opened, 287feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * and ownership of the provided camera is passed to this object. No further calls to the 288feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * camera methods should be made following this constructor. 289feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p> 290feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 291feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param cameraId the id of the camera. 292feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param camera an open {@link Camera} device. 293df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * @param characteristics the static camera characteristics for this camera device 294feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param callbacks {@link ICameraDeviceCallbacks} callbacks to call for Camera2 API operations. 295feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 296df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin public LegacyCameraDevice(int cameraId, Camera camera, CameraCharacteristics characteristics, 297df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin ICameraDeviceCallbacks callbacks) { 298feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCameraId = cameraId; 299feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mDeviceCallbacks = callbacks; 300feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk TAG = String.format("CameraDevice-%d-LE", mCameraId); 301feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 302d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.start(); 303d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultHandler = new Handler(mResultThread.getLooper()); 304feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCallbackHandlerThread.start(); 305feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCallbackHandler = new Handler(mCallbackHandlerThread.getLooper()); 306feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mDeviceState.setCameraDeviceCallbacks(mCallbackHandler, mStateListener); 307e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mStaticCharacteristics = characteristics; 308feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThreadManager = 309df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin new RequestThreadManager(cameraId, camera, characteristics, mDeviceState); 310feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThreadManager.start(); 311feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 312feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 313feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 314feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Configure the device with a set of output surfaces. 315feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 31649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * <p>Using empty or {@code null} {@code outputs} is the same as unconfiguring.</p> 31749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * 31849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * <p>Every surface in {@code outputs} must be non-{@code null}.</p> 31949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * 320385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala * @param outputs a list of surfaces to set. LegacyCameraDevice will take ownership of this 321385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala * list; it must not be modified by the caller once it's passed in. 32249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * @return an error code for this binder operation, or {@link NO_ERROR} 323feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * on success. 324feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 325385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala public int configureOutputs(SparseArray<Surface> outputs) { 326f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk List<Pair<Surface, Size>> sizedSurfaces = new ArrayList<>(); 32749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (outputs != null) { 328385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala int count = outputs.size(); 329385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala for (int i = 0; i < count; i++) { 330385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala Surface output = outputs.valueAt(i); 33149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (output == null) { 33249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "configureOutputs - null outputs are not allowed"); 33349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin return BAD_VALUE; 33449b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 335443ab2c7dbe2a3a482892f3171882572f10eab9aRuben Brunk if (!output.isValid()) { 336443ab2c7dbe2a3a482892f3171882572f10eab9aRuben Brunk Log.e(TAG, "configureOutputs - invalid output surfaces are not allowed"); 337443ab2c7dbe2a3a482892f3171882572f10eab9aRuben Brunk return BAD_VALUE; 338443ab2c7dbe2a3a482892f3171882572f10eab9aRuben Brunk } 339e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk StreamConfigurationMap streamConfigurations = mStaticCharacteristics. 340e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 341e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 342e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // Validate surface size and format. 343e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk try { 344e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Size s = getSurfaceSize(output); 345e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk int surfaceType = detectSurfaceType(output); 346e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 347fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala boolean flexibleConsumer = isFlexibleConsumer(output); 348f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk 349f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk Size[] sizes = streamConfigurations.getOutputSizes(surfaceType); 350e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if (sizes == null) { 351e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // WAR: Override default format to IMPLEMENTATION_DEFINED for b/9487482 352e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if ((surfaceType >= LegacyMetadataMapper.HAL_PIXEL_FORMAT_RGBA_8888 && 353e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk surfaceType <= LegacyMetadataMapper.HAL_PIXEL_FORMAT_BGRA_8888)) { 354e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 355f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk // YUV_420_888 is always present in LEGACY for all 356f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk // IMPLEMENTATION_DEFINED output sizes, and is publicly visible in the 357f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk // API (i.e. {@code #getOutputSizes} works here). 358e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk sizes = streamConfigurations.getOutputSizes(ImageFormat.YUV_420_888); 359e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } else if (surfaceType == LegacyMetadataMapper.HAL_PIXEL_FORMAT_BLOB) { 360e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk sizes = streamConfigurations.getOutputSizes(ImageFormat.JPEG); 361e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 362e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 363e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 364e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if (!ArrayUtils.contains(sizes, s)) { 365f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk if (flexibleConsumer && (s = findClosestSize(s, sizes)) != null) { 366f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk sizedSurfaces.add(new Pair<>(output, s)); 367f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk } else { 368f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk String reason = (sizes == null) ? "format is invalid." : 369f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk ("size not in valid set: " + Arrays.toString(sizes)); 370f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk Log.e(TAG, String.format("Surface with size (w=%d, h=%d) and format " + 371f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk "0x%x is not valid, %s", s.getWidth(), s.getHeight(), 372f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk surfaceType, reason)); 373f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk return BAD_VALUE; 374f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk } 375f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk } else { 376f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk sizedSurfaces.add(new Pair<>(output, s)); 377e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 378315bc0971539f97aaf424c6b21b789a7c8ca9e04Eino-Ville Talvala // Lock down the size before configuration 379315bc0971539f97aaf424c6b21b789a7c8ca9e04Eino-Ville Talvala setSurfaceDimens(output, s.getWidth(), s.getHeight()); 380e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } catch (BufferQueueAbandonedException e) { 381e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.e(TAG, "Surface bufferqueue is abandoned, cannot configure as output: ", e); 382e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk return BAD_VALUE; 383e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 384e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 38549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 38649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 38749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 3884aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk boolean success = false; 3894aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk if (mDeviceState.setConfiguring()) { 390f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk mRequestThreadManager.configure(sizedSurfaces); 3914aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk success = mDeviceState.setIdle(); 392feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 39349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 3944aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk if (success) { 395385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala mConfiguredSurfaces = outputs; 3964aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk } else { 3975d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala return LegacyExceptionUtils.INVALID_OPERATION; 39849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 3995d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala return LegacyExceptionUtils.NO_ERROR; 400feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 401feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 402feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 403feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Submit a burst of capture requests. 404feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 405feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param requestList a list of capture requests to execute. 406feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param repeating {@code true} if this burst is repeating. 4075d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * @return the submission info, including the new request id, and the last frame number, which 4085d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * contains either the frame number of the last frame that will be returned for this request, 4095d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * or the frame number of the last frame that will be returned for the current repeating 4105d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * request if this burst is set to be repeating. 411feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 4125d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala public SubmitInfo submitRequestList(CaptureRequest[] requestList, boolean repeating) { 4135d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala if (requestList == null || requestList.length == 0) { 41449b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - Empty/null requests are not allowed"); 4155d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throw new ServiceSpecificException(BAD_VALUE, 4165d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala "submitRequestList - Empty/null requests are not allowed"); 41749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 41849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 4192da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen List<Long> surfaceIds; 4202da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen 4212da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen try { 4222da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen surfaceIds = (mConfiguredSurfaces == null) ? new ArrayList<Long>() : 4232da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen getSurfaceIds(mConfiguredSurfaces); 4242da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } catch (BufferQueueAbandonedException e) { 4252da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen throw new ServiceSpecificException(BAD_VALUE, 4262da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen "submitRequestList - configured surface is abandoned."); 4272da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } 4283c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk 42949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin // Make sure that there all requests have at least 1 surface; all surfaces are non-null 43049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin for (CaptureRequest request : requestList) { 43149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (request.getTargets().isEmpty()) { 43249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - " 43349b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin + "Each request must have at least one Surface target"); 4345d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throw new ServiceSpecificException(BAD_VALUE, 4355d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala "submitRequestList - " 4365d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala + "Each request must have at least one Surface target"); 43749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 43849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 43949b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin for (Surface surface : request.getTargets()) { 44049b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (surface == null) { 44149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - Null Surface targets are not allowed"); 4425d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throw new ServiceSpecificException(BAD_VALUE, 4435d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala "submitRequestList - Null Surface targets are not allowed"); 44449b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } else if (mConfiguredSurfaces == null) { 44549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - must configure " + 44649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin " device with valid surfaces before submitting requests"); 4475d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throw new ServiceSpecificException(INVALID_OPERATION, 4485d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala "submitRequestList - must configure " + 4495d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala " device with valid surfaces before submitting requests"); 4503c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } else if (!containsSurfaceId(surface, surfaceIds)) { 45149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin Log.e(TAG, "submitRequestList - cannot use a surface that wasn't configured"); 4525d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala throw new ServiceSpecificException(BAD_VALUE, 4535d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala "submitRequestList - cannot use a surface that wasn't configured"); 45449b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 45549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 45649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 45749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin 45849b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin // TODO: further validation of request here 459feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mIdle.close(); 4605d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala return mRequestThreadManager.submitCaptureRequests(requestList, repeating); 461feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 462feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 463feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 464feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Submit a single capture request. 465feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 466feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param request the capture request to execute. 467feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param repeating {@code true} if this request is repeating. 4685d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * @return the submission info, including the new request id, and the last frame number, which 4695d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * contains either the frame number of the last frame that will be returned for this request, 4705d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * or the frame number of the last frame that will be returned for the current repeating 4715d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * request if this burst is set to be repeating. 472feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 4735d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala public SubmitInfo submitRequest(CaptureRequest request, boolean repeating) { 4745d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala CaptureRequest[] requestList = { request }; 4755d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala return submitRequestList(requestList, repeating); 476feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 477feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 478feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 479feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Cancel the repeating request with the given request id. 480feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 481feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param requestId the request id of the request to cancel. 482feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @return the last frame number to be returned from the HAL for the given repeating request, or 483feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * {@code INVALID_FRAME} if none exists. 484feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 485feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public long cancelRequest(int requestId) { 486feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return mRequestThreadManager.cancelRepeating(requestId); 487feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 488feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 489feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 490feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Block until the {@link ICameraDeviceCallbacks#onCameraIdle()} callback is received. 491feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 492feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void waitUntilIdle() { 493feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mIdle.block(); 494feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 495feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 496e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk /** 497e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk * Flush any pending requests. 498e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk * 499e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk * @return the last frame number. 500e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk */ 501e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public long flush() { 502e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk long lastFrame = mRequestThreadManager.flush(); 503e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk waitUntilIdle(); 504e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk return lastFrame; 505e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 506e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 507e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk /** 508e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk * Return {@code true} if the device has been closed. 509e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk */ 510e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public boolean isClosed() { 511e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk return mClosed; 512e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 513e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 514feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 515feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void close() { 516feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThreadManager.quit(); 517feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCallbackHandlerThread.quitSafely(); 518d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.quitSafely(); 519d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 520d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 521d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mCallbackHandlerThread.join(); 522d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (InterruptedException e) { 523d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk Log.e(TAG, String.format("Thread %s (%d) interrupted while quitting.", 524d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mCallbackHandlerThread.getName(), mCallbackHandlerThread.getId())); 525d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 526d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 527d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk try { 528d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.join(); 529d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } catch (InterruptedException e) { 530d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk Log.e(TAG, String.format("Thread %s (%d) interrupted while quitting.", 531d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mResultThread.getName(), mResultThread.getId())); 532d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 533d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 534e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mClosed = true; 535feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 536feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 537feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 538feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk protected void finalize() throws Throwable { 539feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk try { 540feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk close(); 5415d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala } catch (ServiceSpecificException e) { 542feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk Log.e(TAG, "Got error while trying to finalize, ignoring: " + e.getMessage()); 543feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } finally { 544feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk super.finalize(); 545feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 546feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 547feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 548f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk static long findEuclidDistSquare(Size a, Size b) { 549f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk long d0 = a.getWidth() - b.getWidth(); 550f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk long d1 = a.getHeight() - b.getHeight(); 551f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk return d0 * d0 + d1 * d1; 552f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk } 553f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk 554f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk // Keep up to date with rounding behavior in 555f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk // frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp 556f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk static Size findClosestSize(Size size, Size[] supportedSizes) { 557f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk if (size == null || supportedSizes == null) { 558f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk return null; 559f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk } 560f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk Size bestSize = null; 561f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk for (Size s : supportedSizes) { 562f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk if (s.equals(size)) { 563f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk return size; 564f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk } else if (s.getWidth() <= MAX_DIMEN_FOR_ROUNDING && (bestSize == null || 565f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk LegacyCameraDevice.findEuclidDistSquare(size, s) < 566f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk LegacyCameraDevice.findEuclidDistSquare(bestSize, s))) { 567f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk bestSize = s; 568f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk } 569f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk } 570f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk return bestSize; 571f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk } 572f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk 573a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin /** 574a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * Query the surface for its currently configured default buffer size. 575a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * @param surface a non-{@code null} {@code Surface} 576a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * @return the width and height of the surface 577a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * 578a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * @throws NullPointerException if the {@code surface} was {@code null} 579443ab2c7dbe2a3a482892f3171882572f10eab9aRuben Brunk * @throws BufferQueueAbandonedException if the {@code surface} was invalid 580a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin */ 581fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala public static Size getSurfaceSize(Surface surface) throws BufferQueueAbandonedException { 582a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin checkNotNull(surface); 583a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 584a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin int[] dimens = new int[2]; 585ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeDetectSurfaceDimens(surface, /*out*/dimens)); 586a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 587a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin return new Size(dimens[0], dimens[1]); 588a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin } 589a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 590fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala public static boolean isFlexibleConsumer(Surface output) { 591fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala int usageFlags = detectSurfaceUsageFlags(output); 592fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala 593fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala // Keep up to date with allowed consumer types in 594fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala // frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp 595fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala int disallowedFlags = GRALLOC_USAGE_HW_VIDEO_ENCODER | GRALLOC_USAGE_RENDERSCRIPT; 596fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala int allowedFlags = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_OFTEN | 597fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala GRALLOC_USAGE_HW_COMPOSER; 598fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala boolean flexibleConsumer = ((usageFlags & disallowedFlags) == 0 && 599fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala (usageFlags & allowedFlags) != 0); 600fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala return flexibleConsumer; 601fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala } 602fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala 603a7677722304670dc07feef242156b97e6bb51bcdZhijun He public static boolean isPreviewConsumer(Surface output) { 604a7677722304670dc07feef242156b97e6bb51bcdZhijun He int usageFlags = detectSurfaceUsageFlags(output); 605a7677722304670dc07feef242156b97e6bb51bcdZhijun He int disallowedFlags = GRALLOC_USAGE_HW_VIDEO_ENCODER | GRALLOC_USAGE_RENDERSCRIPT | 606a7677722304670dc07feef242156b97e6bb51bcdZhijun He GRALLOC_USAGE_SW_READ_OFTEN; 607a7677722304670dc07feef242156b97e6bb51bcdZhijun He int allowedFlags = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER | 608a7677722304670dc07feef242156b97e6bb51bcdZhijun He GRALLOC_USAGE_HW_RENDER; 609a7677722304670dc07feef242156b97e6bb51bcdZhijun He boolean previewConsumer = ((usageFlags & disallowedFlags) == 0 && 610a7677722304670dc07feef242156b97e6bb51bcdZhijun He (usageFlags & allowedFlags) != 0); 611a7677722304670dc07feef242156b97e6bb51bcdZhijun He int surfaceFormat = ImageFormat.UNKNOWN; 612a7677722304670dc07feef242156b97e6bb51bcdZhijun He try { 613a7677722304670dc07feef242156b97e6bb51bcdZhijun He surfaceFormat = detectSurfaceType(output); 614a7677722304670dc07feef242156b97e6bb51bcdZhijun He } catch(BufferQueueAbandonedException e) { 615a7677722304670dc07feef242156b97e6bb51bcdZhijun He throw new IllegalArgumentException("Surface was abandoned", e); 616a7677722304670dc07feef242156b97e6bb51bcdZhijun He } 617a7677722304670dc07feef242156b97e6bb51bcdZhijun He 61847ac34997b34002a81cfaac3fdf429fdf329220cZhijun He return previewConsumer; 619a7677722304670dc07feef242156b97e6bb51bcdZhijun He } 620a7677722304670dc07feef242156b97e6bb51bcdZhijun He 621a7677722304670dc07feef242156b97e6bb51bcdZhijun He public static boolean isVideoEncoderConsumer(Surface output) { 622a7677722304670dc07feef242156b97e6bb51bcdZhijun He int usageFlags = detectSurfaceUsageFlags(output); 623a7677722304670dc07feef242156b97e6bb51bcdZhijun He int disallowedFlags = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER | 624a7677722304670dc07feef242156b97e6bb51bcdZhijun He GRALLOC_USAGE_RENDERSCRIPT | GRALLOC_USAGE_SW_READ_OFTEN; 625a7677722304670dc07feef242156b97e6bb51bcdZhijun He int allowedFlags = GRALLOC_USAGE_HW_VIDEO_ENCODER; 626a7677722304670dc07feef242156b97e6bb51bcdZhijun He boolean videoEncoderConsumer = ((usageFlags & disallowedFlags) == 0 && 627a7677722304670dc07feef242156b97e6bb51bcdZhijun He (usageFlags & allowedFlags) != 0); 628a7677722304670dc07feef242156b97e6bb51bcdZhijun He 629a7677722304670dc07feef242156b97e6bb51bcdZhijun He int surfaceFormat = ImageFormat.UNKNOWN; 630a7677722304670dc07feef242156b97e6bb51bcdZhijun He try { 631a7677722304670dc07feef242156b97e6bb51bcdZhijun He surfaceFormat = detectSurfaceType(output); 632a7677722304670dc07feef242156b97e6bb51bcdZhijun He } catch(BufferQueueAbandonedException e) { 633a7677722304670dc07feef242156b97e6bb51bcdZhijun He throw new IllegalArgumentException("Surface was abandoned", e); 634a7677722304670dc07feef242156b97e6bb51bcdZhijun He } 635a7677722304670dc07feef242156b97e6bb51bcdZhijun He 63647ac34997b34002a81cfaac3fdf429fdf329220cZhijun He return videoEncoderConsumer; 637a7677722304670dc07feef242156b97e6bb51bcdZhijun He } 638a7677722304670dc07feef242156b97e6bb51bcdZhijun He 639fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala /** 640fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala * Query the surface for its currently configured usage flags 641fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala */ 642f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk static int detectSurfaceUsageFlags(Surface surface) { 643f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk checkNotNull(surface); 644f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk return nativeDetectSurfaceUsageFlags(surface); 645f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk } 646f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk 647fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala /** 648fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala * Query the surface for its currently configured format 649fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala */ 650fa0b9a00b48394bd9b7e5d54b2b4a5a33d7bd186Eino-Ville Talvala public static int detectSurfaceType(Surface surface) throws BufferQueueAbandonedException { 651ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 652ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk return LegacyExceptionUtils.throwOnError(nativeDetectSurfaceType(surface)); 653ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 654ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 655e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala /** 656e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala * Query the surface for its currently configured dataspace 657e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala */ 658e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala public static int detectSurfaceDataspace(Surface surface) throws BufferQueueAbandonedException { 659e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala checkNotNull(surface); 660e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala return LegacyExceptionUtils.throwOnError(nativeDetectSurfaceDataspace(surface)); 661e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala } 662e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala 66329c3630563452c9635f0510d071839c112d3017dChien-Yu Chen static void connectSurface(Surface surface) throws BufferQueueAbandonedException { 664ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 665ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 66629c3630563452c9635f0510d071839c112d3017dChien-Yu Chen LegacyExceptionUtils.throwOnError(nativeConnectSurface(surface)); 66729c3630563452c9635f0510d071839c112d3017dChien-Yu Chen } 66829c3630563452c9635f0510d071839c112d3017dChien-Yu Chen 66929c3630563452c9635f0510d071839c112d3017dChien-Yu Chen static void disconnectSurface(Surface surface) throws BufferQueueAbandonedException { 67029c3630563452c9635f0510d071839c112d3017dChien-Yu Chen if (surface == null) return; 67129c3630563452c9635f0510d071839c112d3017dChien-Yu Chen 67229c3630563452c9635f0510d071839c112d3017dChien-Yu Chen LegacyExceptionUtils.throwOnError(nativeDisconnectSurface(surface)); 673ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 674ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 675ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static void produceFrame(Surface surface, byte[] pixelBuffer, int width, 676ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk int height, int pixelFormat) 677ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk throws BufferQueueAbandonedException { 678ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 679ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(pixelBuffer); 680ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(width, "width must be positive."); 681ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(height, "height must be positive."); 682ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 683ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeProduceFrame(surface, pixelBuffer, width, height, 684ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk pixelFormat)); 685ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 686ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 687ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static void setSurfaceFormat(Surface surface, int pixelFormat) 688ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk throws BufferQueueAbandonedException { 689ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 690ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 691ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeSetSurfaceFormat(surface, pixelFormat)); 692ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 693ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 694ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk static void setSurfaceDimens(Surface surface, int width, int height) 695ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk throws BufferQueueAbandonedException { 696ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkNotNull(surface); 697ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(width, "width must be positive."); 698ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk checkArgumentPositive(height, "height must be positive."); 699ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 700ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk LegacyExceptionUtils.throwOnError(nativeSetSurfaceDimens(surface, width, height)); 701ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 702ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk 7032da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen static long getSurfaceId(Surface surface) throws BufferQueueAbandonedException { 7043c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk checkNotNull(surface); 7052da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen try { 7062da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen return nativeGetSurfaceId(surface); 7072da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } catch (IllegalArgumentException e) { 7082da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen throw new BufferQueueAbandonedException(); 7092da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } 7103c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 7113c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk 7122da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen static List<Long> getSurfaceIds(SparseArray<Surface> surfaces) 7132da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen throws BufferQueueAbandonedException { 714385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala if (surfaces == null) { 715385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala throw new NullPointerException("Null argument surfaces"); 716385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala } 717385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala List<Long> surfaceIds = new ArrayList<>(); 718385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala int count = surfaces.size(); 719385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala for (int i = 0; i < count; i++) { 720385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala long id = getSurfaceId(surfaces.valueAt(i)); 721385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala if (id == 0) { 722385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala throw new IllegalStateException( 723385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala "Configured surface had null native GraphicBufferProducer pointer!"); 724385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala } 725385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala surfaceIds.add(id); 726385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala } 727385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala return surfaceIds; 728385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala } 729385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala 7302da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen static List<Long> getSurfaceIds(Collection<Surface> surfaces) 7312da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen throws BufferQueueAbandonedException { 7323c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk if (surfaces == null) { 7333c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk throw new NullPointerException("Null argument surfaces"); 7343c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 7353c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk List<Long> surfaceIds = new ArrayList<>(); 7363c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk for (Surface s : surfaces) { 7373c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk long id = getSurfaceId(s); 7383c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk if (id == 0) { 7393c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk throw new IllegalStateException( 7403c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk "Configured surface had null native GraphicBufferProducer pointer!"); 7413c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 7423c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk surfaceIds.add(id); 7433c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 7443c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk return surfaceIds; 7453c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 7463c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk 7470fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk static boolean containsSurfaceId(Surface s, Collection<Long> ids) { 7482da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen long id = 0; 7492da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen try { 7502da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen id = getSurfaceId(s); 7512da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } catch (BufferQueueAbandonedException e) { 7522da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen // If surface is abandoned, return false. 7532da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen return false; 7542da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } 7553c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk return ids.contains(id); 7563c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk } 7573c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk 75828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk static void setSurfaceOrientation(Surface surface, int facing, int sensorOrientation) 75928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk throws BufferQueueAbandonedException { 76028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk checkNotNull(surface); 76128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk LegacyExceptionUtils.throwOnError(nativeSetSurfaceOrientation(surface, facing, 76228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk sensorOrientation)); 76328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk } 76428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 76528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk static Size getTextureSize(SurfaceTexture surfaceTexture) 76628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk throws BufferQueueAbandonedException { 76728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk checkNotNull(surfaceTexture); 76828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 76928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk int[] dimens = new int[2]; 77028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk LegacyExceptionUtils.throwOnError(nativeDetectTextureDimens(surfaceTexture, 77128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk /*out*/dimens)); 77228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 77328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk return new Size(dimens[0], dimens[1]); 77428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk } 77528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 77691838ded36131525312739c0929913b215519c2aRuben Brunk static void setNextTimestamp(Surface surface, long timestamp) 77791838ded36131525312739c0929913b215519c2aRuben Brunk throws BufferQueueAbandonedException { 77891838ded36131525312739c0929913b215519c2aRuben Brunk checkNotNull(surface); 77991838ded36131525312739c0929913b215519c2aRuben Brunk LegacyExceptionUtils.throwOnError(nativeSetNextTimestamp(surface, timestamp)); 78091838ded36131525312739c0929913b215519c2aRuben Brunk } 78191838ded36131525312739c0929913b215519c2aRuben Brunk 782a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk static void setScalingMode(Surface surface, int mode) 783a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk throws BufferQueueAbandonedException { 784a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk checkNotNull(surface); 785a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk LegacyExceptionUtils.throwOnError(nativeSetScalingMode(surface, mode)); 786a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk } 787a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk 788a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk 789ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeDetectSurfaceType(Surface surface); 790feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 791e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala private static native int nativeDetectSurfaceDataspace(Surface surface); 792e365120aaead97567bdfbc53d3bfc2699bd2f886Eino-Ville Talvala 793ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeDetectSurfaceDimens(Surface surface, 794a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin /*out*/int[/*2*/] dimens); 795feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 79629c3630563452c9635f0510d071839c112d3017dChien-Yu Chen private static native int nativeConnectSurface(Surface surface); 797feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 798ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeProduceFrame(Surface surface, byte[] pixelBuffer, int width, 799feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk int height, int pixelFormat); 800feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 801ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeSetSurfaceFormat(Surface surface, int pixelFormat); 802feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 803ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk private static native int nativeSetSurfaceDimens(Surface surface, int width, int height); 804feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 8053c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk private static native long nativeGetSurfaceId(Surface surface); 80628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 80728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk private static native int nativeSetSurfaceOrientation(Surface surface, int facing, 80828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk int sensorOrientation); 80928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 81028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk private static native int nativeDetectTextureDimens(SurfaceTexture surfaceTexture, 81128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk /*out*/int[/*2*/] dimens); 81228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk 81391838ded36131525312739c0929913b215519c2aRuben Brunk private static native int nativeSetNextTimestamp(Surface surface, long timestamp); 8141dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk 815f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk private static native int nativeDetectSurfaceUsageFlags(Surface surface); 816f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk 817a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk private static native int nativeSetScalingMode(Surface surface, int scalingMode); 818a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk 81929c3630563452c9635f0510d071839c112d3017dChien-Yu Chen private static native int nativeDisconnectSurface(Surface surface); 82029c3630563452c9635f0510d071839c112d3017dChien-Yu Chen 8211dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk static native int nativeGetJpegFooterSize(); 822feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk} 823