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.SurfaceTexture; 20feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.Camera; 21df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkinimport android.hardware.camera2.CameraCharacteristics; 22feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.CaptureRequest; 23e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunkimport android.hardware.camera2.impl.CameraDeviceImpl; 245d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvalaimport android.hardware.camera2.utils.SubmitInfo; 25df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkinimport android.hardware.camera2.utils.SizeAreaComparator; 26feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.impl.CameraMetadataNative; 27feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.ConditionVariable; 28feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.Handler; 29feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.Message; 30feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.SystemClock; 31feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.util.Log; 3283d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkinimport android.util.MutableLong; 33feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.util.Pair; 34d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunkimport android.util.Size; 35feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.view.Surface; 36feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 37feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.io.IOException; 38feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.ArrayList; 39feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.Collection; 40d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunkimport java.util.Collections; 41f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunkimport java.util.Iterator; 42feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.List; 4391838ded36131525312739c0929913b215519c2aRuben Brunkimport java.util.concurrent.TimeUnit; 44e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunkimport java.util.concurrent.atomic.AtomicBoolean; 45feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 46df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkinimport static com.android.internal.util.Preconditions.*; 47df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin 48feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/** 49feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * This class executes requests to the {@link Camera}. 50feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 51feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p> 52feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * The main components of this class are: 53feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * - A message queue of requests to the {@link Camera}. 54feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * - A thread that consumes requests to the {@link Camera} and executes them. 55feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * - A {@link GLThreadManager} that draws to the configured output {@link Surface}s. 56feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * - An {@link CameraDeviceState} state machine that manages the callbacks for various operations. 57feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p> 58feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 590a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin@SuppressWarnings("deprecation") 60feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkpublic class RequestThreadManager { 61feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final String TAG; 62feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final int mCameraId; 63feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final RequestHandlerThread mRequestThread; 64feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 65a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala private static final boolean DEBUG = false; 660a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin // For slightly more spammy messages that will get repeated every frame 67a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala private static final boolean VERBOSE = false; 68e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk private Camera mCamera; 69df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin private final CameraCharacteristics mCharacteristics; 70feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 71feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final CameraDeviceState mDeviceState; 7291838ded36131525312739c0929913b215519c2aRuben Brunk private final CaptureCollector mCaptureCollector; 7383d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin private final LegacyFocusStateMapper mFocusStateMapper; 740a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin private final LegacyFaceDetectMapper mFaceDetectMapper; 75feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 76feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private static final int MSG_CONFIGURE_OUTPUTS = 1; 77feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private static final int MSG_SUBMIT_CAPTURE_REQUEST = 2; 78feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private static final int MSG_CLEANUP = 3; 79feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 8091838ded36131525312739c0929913b215519c2aRuben Brunk private static final int MAX_IN_FLIGHT_REQUESTS = 2; 8191838ded36131525312739c0929913b215519c2aRuben Brunk 823e2c14f3d64b66e155e623c6cda22848eb3f5314Igor Murashkin private static final int PREVIEW_FRAME_TIMEOUT = 1000; // ms 83e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk private static final int JPEG_FRAME_TIMEOUT = 4000; // ms (same as CTS for API2) 8445441f3a7cf6ba5175d971cc2d8ea4f16bac771bRuben Brunk private static final int REQUEST_COMPLETE_TIMEOUT = JPEG_FRAME_TIMEOUT; 85feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 86d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk private static final float ASPECT_RATIO_TOLERANCE = 0.01f; 87feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private boolean mPreviewRunning = false; 88feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 897f2372bd85445967ac6cb8c9519ebd1405aaa233Ruben Brunk private final List<Surface> mPreviewOutputs = new ArrayList<>(); 907f2372bd85445967ac6cb8c9519ebd1405aaa233Ruben Brunk private final List<Surface> mCallbackOutputs = new ArrayList<>(); 91feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private GLThreadManager mGLThreadManager; 92feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private SurfaceTexture mPreviewTexture; 933e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk private Camera.Parameters mParams; 94feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 950fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk private final List<Long> mJpegSurfaceIds = new ArrayList<>(); 960fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk 97d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk private Size mIntermediateBufferSize; 98d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 990fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk private final RequestQueue mRequestQueue = new RequestQueue(mJpegSurfaceIds); 100df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin private LegacyRequest mLastRequest = null; 101feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private SurfaceTexture mDummyTexture; 102feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private Surface mDummySurface; 103feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 1044aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk private final Object mIdleLock = new Object(); 105feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final FpsCounter mPrevCounter = new FpsCounter("Incoming Preview"); 1063e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk private final FpsCounter mRequestCounter = new FpsCounter("Incoming Requests"); 107feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 108e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk private final AtomicBoolean mQuit = new AtomicBoolean(false); 109e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk 1100fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk // Stuff JPEGs into HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers to get around SW write 1110fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk // limitations for (b/17379185). 1120fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk private static final boolean USE_BLOB_FORMAT_OVERRIDE = true; 1130fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk 114feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 115feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Container object for Configure messages. 116feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 117feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private static class ConfigureHolder { 118feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public final ConditionVariable condition; 119f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk public final Collection<Pair<Surface, Size>> surfaces; 120feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 121f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk public ConfigureHolder(ConditionVariable condition, Collection<Pair<Surface, 122f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk Size>> surfaces) { 123feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk this.condition = condition; 124feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk this.surfaces = surfaces; 125feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 126feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 127feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 128feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 129feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Counter class used to calculate and log the current FPS of frame production. 130feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 131feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public static class FpsCounter { 132feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk //TODO: Hook this up to SystTrace? 133feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private static final String TAG = "FpsCounter"; 134feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private int mFrameCount = 0; 135feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private long mLastTime = 0; 136feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private long mLastPrintTime = 0; 137feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private double mLastFps = 0; 138feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final String mStreamType; 139feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private static final long NANO_PER_SECOND = 1000000000; //ns 140feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 141feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public FpsCounter(String streamType) { 142feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mStreamType = streamType; 143feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 144feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 145feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public synchronized void countFrame() { 146feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mFrameCount++; 147feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk long nextTime = SystemClock.elapsedRealtimeNanos(); 148feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (mLastTime == 0) { 149feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mLastTime = nextTime; 150feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 151feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (nextTime > mLastTime + NANO_PER_SECOND) { 152feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk long elapsed = nextTime - mLastTime; 153feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mLastFps = mFrameCount * (NANO_PER_SECOND / (double) elapsed); 154feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mFrameCount = 0; 155feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mLastTime = nextTime; 156feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 157feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 158feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 159feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public synchronized double checkFps() { 160feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return mLastFps; 161feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 162feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 163feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public synchronized void staggeredLog() { 164feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (mLastTime > mLastPrintTime + 5 * NANO_PER_SECOND) { 165feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mLastPrintTime = mLastTime; 166feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk Log.d(TAG, "FPS for " + mStreamType + " stream: " + mLastFps ); 167feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 168feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 169feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 170feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public synchronized void countAndLog() { 171feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk countFrame(); 172feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk staggeredLog(); 173feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 174feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 175feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 176feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Fake preview for jpeg captures when there is no active preview 177feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 178feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private void createDummySurface() { 179feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (mDummyTexture == null || mDummySurface == null) { 180feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mDummyTexture = new SurfaceTexture(/*ignored*/0); 181feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk // TODO: use smallest default sizes 182feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mDummyTexture.setDefaultBufferSize(640, 480); 183feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mDummySurface = new Surface(mDummyTexture); 184feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 185feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 186feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 1874aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk private final Camera.ErrorCallback mErrorCallback = new Camera.ErrorCallback() { 1884aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk @Override 1894aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk public void onError(int i, Camera camera) { 190b44864e76b56006298e574f8ce5539a1c9e1750fRuben Brunk switch(i) { 191b44864e76b56006298e574f8ce5539a1c9e1750fRuben Brunk case Camera.CAMERA_ERROR_EVICTED: { 192b44864e76b56006298e574f8ce5539a1c9e1750fRuben Brunk flush(); 193b44864e76b56006298e574f8ce5539a1c9e1750fRuben Brunk mDeviceState.setError( 194b44864e76b56006298e574f8ce5539a1c9e1750fRuben Brunk CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DISCONNECTED); 195b44864e76b56006298e574f8ce5539a1c9e1750fRuben Brunk } break; 196b44864e76b56006298e574f8ce5539a1c9e1750fRuben Brunk default: { 197b44864e76b56006298e574f8ce5539a1c9e1750fRuben Brunk Log.e(TAG, "Received error " + i + " from the Camera1 ErrorCallback"); 198b44864e76b56006298e574f8ce5539a1c9e1750fRuben Brunk mDeviceState.setError( 199b44864e76b56006298e574f8ce5539a1c9e1750fRuben Brunk CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); 200b44864e76b56006298e574f8ce5539a1c9e1750fRuben Brunk } break; 201b44864e76b56006298e574f8ce5539a1c9e1750fRuben Brunk } 2024aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk } 2034aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk }; 2044aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk 205feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final ConditionVariable mReceivedJpeg = new ConditionVariable(false); 206feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 207feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final Camera.PictureCallback mJpegCallback = new Camera.PictureCallback() { 208feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 209feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void onPictureTaken(byte[] data, Camera camera) { 210feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk Log.i(TAG, "Received jpeg."); 21191838ded36131525312739c0929913b215519c2aRuben Brunk Pair<RequestHolder, Long> captureInfo = mCaptureCollector.jpegProduced(); 2122c3d7c5f68993531a4f5f91c1335cac8ca448e17Ruben Brunk if (captureInfo == null || captureInfo.first == null) { 21391838ded36131525312739c0929913b215519c2aRuben Brunk Log.e(TAG, "Dropping jpeg frame."); 214feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return; 215feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 2162c3d7c5f68993531a4f5f91c1335cac8ca448e17Ruben Brunk RequestHolder holder = captureInfo.first; 2172c3d7c5f68993531a4f5f91c1335cac8ca448e17Ruben Brunk long timestamp = captureInfo.second; 218feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk for (Surface s : holder.getHolderTargets()) { 219ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk try { 2200fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk if (LegacyCameraDevice.containsSurfaceId(s, mJpegSurfaceIds)) { 221ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk Log.i(TAG, "Producing jpeg buffer..."); 2220fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk 2230fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk int totalSize = data.length + LegacyCameraDevice.nativeGetJpegFooterSize(); 22431798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk totalSize = (totalSize + 3) & ~0x3; // round up to nearest octonibble 2250c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk LegacyCameraDevice.setNextTimestamp(s, timestamp); 22631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk 22731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk if (USE_BLOB_FORMAT_OVERRIDE) { 22831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk // Override to RGBA_8888 format. 22931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk LegacyCameraDevice.setSurfaceFormat(s, 23031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk LegacyMetadataMapper.HAL_PIXEL_FORMAT_RGBA_8888); 2310c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk 2320c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk int dimen = (int) Math.ceil(Math.sqrt(totalSize)); 2330c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk dimen = (dimen + 0xf) & ~0xf; // round up to nearest multiple of 16 2340c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk LegacyCameraDevice.setSurfaceDimens(s, dimen, dimen); 2350c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk LegacyCameraDevice.produceFrame(s, data, dimen, dimen, 2360c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk CameraMetadataNative.NATIVE_JPEG_FORMAT); 2370c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk } else { 2380c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk LegacyCameraDevice.setSurfaceDimens(s, totalSize, /*height*/1); 2390c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk LegacyCameraDevice.produceFrame(s, data, totalSize, /*height*/1, 2400c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk CameraMetadataNative.NATIVE_JPEG_FORMAT); 24131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk } 242ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 243ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) { 244ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk Log.w(TAG, "Surface abandoned, dropping frame. ", e); 245feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 246feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 24791838ded36131525312739c0929913b215519c2aRuben Brunk 248feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mReceivedJpeg.open(); 249feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 250feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk }; 251feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 2523e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk private final Camera.ShutterCallback mJpegShutterCallback = new Camera.ShutterCallback() { 2533e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk @Override 2543e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk public void onShutter() { 25591838ded36131525312739c0929913b215519c2aRuben Brunk mCaptureCollector.jpegCaptured(SystemClock.elapsedRealtimeNanos()); 2563e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 2573e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk }; 2583e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk 259feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final SurfaceTexture.OnFrameAvailableListener mPreviewCallback = 260feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk new SurfaceTexture.OnFrameAvailableListener() { 261feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 262feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void onFrameAvailable(SurfaceTexture surfaceTexture) { 263d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk if (DEBUG) { 264d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk mPrevCounter.countAndLog(); 265d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk } 26691838ded36131525312739c0929913b215519c2aRuben Brunk mGLThreadManager.queueNewFrame(); 267feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 268feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk }; 269feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 270feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private void stopPreview() { 2710a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin if (VERBOSE) { 2720a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin Log.v(TAG, "stopPreview - preview running? " + mPreviewRunning); 2730a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 274feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (mPreviewRunning) { 275feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCamera.stopPreview(); 276feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mPreviewRunning = false; 277feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 278feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 279feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 280feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private void startPreview() { 2810a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin if (VERBOSE) { 2820a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin Log.v(TAG, "startPreview - preview running? " + mPreviewRunning); 2830a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 284feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (!mPreviewRunning) { 2850a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin // XX: CameraClient:;startPreview is not getting called after a stop 286feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCamera.startPreview(); 287feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mPreviewRunning = true; 288feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 289feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 290feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 2910a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin private void doJpegCapturePrepare(RequestHolder request) throws IOException { 2920a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin if (DEBUG) Log.d(TAG, "doJpegCapturePrepare - preview running? " + mPreviewRunning); 293a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 294feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (!mPreviewRunning) { 295a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin if (DEBUG) Log.d(TAG, "doJpegCapture - create fake surface"); 296a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 297feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk createDummySurface(); 298feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCamera.setPreviewTexture(mDummyTexture); 299feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk startPreview(); 300feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 3010a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 3020a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 3030a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin private void doJpegCapture(RequestHolder request) { 3040a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin if (DEBUG) Log.d(TAG, "doJpegCapturePrepare"); 3050a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 3063e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk mCamera.takePicture(mJpegShutterCallback, /*raw*/null, mJpegCallback); 307feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mPreviewRunning = false; 308feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 309feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 310feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private void doPreviewCapture(RequestHolder request) throws IOException { 3110a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin if (VERBOSE) { 3120a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin Log.v(TAG, "doPreviewCapture - preview running? " + mPreviewRunning); 3130a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 3140a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 315feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (mPreviewRunning) { 316feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return; // Already running 317feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 318feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 319d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk if (mPreviewTexture == null) { 320d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk throw new IllegalStateException( 321d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk "Preview capture called with no preview surfaces configured."); 322d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 323d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 324d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mPreviewTexture.setDefaultBufferSize(mIntermediateBufferSize.getWidth(), 325d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mIntermediateBufferSize.getHeight()); 326feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCamera.setPreviewTexture(mPreviewTexture); 327feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 328feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk startPreview(); 329feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 330feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 331f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk private void configureOutputs(Collection<Pair<Surface, Size>> outputs) { 3320a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin if (DEBUG) { 3330a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin String outputsStr = outputs == null ? "null" : (outputs.size() + " surfaces"); 3340a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin Log.d(TAG, "configureOutputs with " + outputsStr); 3350a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 3360a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 337e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk try { 338e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk stopPreview(); 339e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk } catch (RuntimeException e) { 340e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk Log.e(TAG, "Received device exception in configure call: ", e); 341e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk mDeviceState.setError( 342e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); 343e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk return; 344e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk } 345e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk 3460a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin /* 3470a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * Try to release the previous preview's surface texture earlier if we end up 3480a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * using a different one; this also reduces the likelihood of getting into a deadlock 3490a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * when disconnecting from the old previous texture at a later time. 3500a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin */ 351e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk try { 352e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mCamera.setPreviewTexture(/*surfaceTexture*/null); 353e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } catch (IOException e) { 354e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.w(TAG, "Failed to clear prior SurfaceTexture, may cause GL deadlock: ", e); 355e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk } catch (RuntimeException e) { 356e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk Log.e(TAG, "Received device exception in configure call: ", e); 357e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk mDeviceState.setError( 358e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); 359e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk return; 360e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 3610a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 362feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (mGLThreadManager != null) { 363feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mGLThreadManager.waitUntilStarted(); 364feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mGLThreadManager.ignoreNewFrames(); 365feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mGLThreadManager.waitUntilIdle(); 366feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 3670fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk resetJpegSurfaceFormats(mCallbackOutputs); 36829c3630563452c9635f0510d071839c112d3017dChien-Yu Chen 36929c3630563452c9635f0510d071839c112d3017dChien-Yu Chen for (Surface s : mCallbackOutputs) { 37029c3630563452c9635f0510d071839c112d3017dChien-Yu Chen try { 37129c3630563452c9635f0510d071839c112d3017dChien-Yu Chen LegacyCameraDevice.disconnectSurface(s); 37229c3630563452c9635f0510d071839c112d3017dChien-Yu Chen } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) { 37329c3630563452c9635f0510d071839c112d3017dChien-Yu Chen Log.w(TAG, "Surface abandoned, skipping...", e); 37429c3630563452c9635f0510d071839c112d3017dChien-Yu Chen } 37529c3630563452c9635f0510d071839c112d3017dChien-Yu Chen } 376feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mPreviewOutputs.clear(); 377feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCallbackOutputs.clear(); 37852571b9032fedb90ca1fabbda90d0313d44adfb9Eino-Ville Talvala mJpegSurfaceIds.clear(); 379feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mPreviewTexture = null; 380feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 381f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk List<Size> previewOutputSizes = new ArrayList<>(); 382f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk List<Size> callbackOutputSizes = new ArrayList<>(); 383f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk 38428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk int facing = mCharacteristics.get(CameraCharacteristics.LENS_FACING); 38528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk int orientation = mCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION); 38649b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin if (outputs != null) { 387f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk for (Pair<Surface, Size> outPair : outputs) { 388f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk Surface s = outPair.first; 389f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk Size outSize = outPair.second; 390ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk try { 391ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk int format = LegacyCameraDevice.detectSurfaceType(s); 39228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk LegacyCameraDevice.setSurfaceOrientation(s, facing, orientation); 393ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk switch (format) { 394ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk case CameraMetadataNative.NATIVE_JPEG_FORMAT: 3950fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk if (USE_BLOB_FORMAT_OVERRIDE) { 3960fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk // Override to RGBA_8888 format. 3970fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk LegacyCameraDevice.setSurfaceFormat(s, 3980fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk LegacyMetadataMapper.HAL_PIXEL_FORMAT_RGBA_8888); 3990fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk } 4000fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk mJpegSurfaceIds.add(LegacyCameraDevice.getSurfaceId(s)); 401ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk mCallbackOutputs.add(s); 402f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk callbackOutputSizes.add(outSize); 40329c3630563452c9635f0510d071839c112d3017dChien-Yu Chen 40429c3630563452c9635f0510d071839c112d3017dChien-Yu Chen // LegacyCameraDevice is the producer of JPEG output surfaces 40529c3630563452c9635f0510d071839c112d3017dChien-Yu Chen // so LegacyCameraDevice needs to connect to the surfaces. 40629c3630563452c9635f0510d071839c112d3017dChien-Yu Chen LegacyCameraDevice.connectSurface(s); 407ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk break; 408ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk default: 409a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk LegacyCameraDevice.setScalingMode(s, LegacyCameraDevice. 410a94c6033452b465a28d6bd76015d4a1de6b1bd29Ruben Brunk NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); 411ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk mPreviewOutputs.add(s); 412f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk previewOutputSizes.add(outSize); 413ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk break; 414ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 415ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) { 416ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk Log.w(TAG, "Surface abandoned, skipping...", e); 41749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin } 418feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 419feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 420eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala try { 421eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala mParams = mCamera.getParameters(); 422eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala } catch (RuntimeException e) { 423eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala Log.e(TAG, "Received device exception: ", e); 424eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala mDeviceState.setError( 425eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); 426eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala return; 427eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala } 4287f2372bd85445967ac6cb8c9519ebd1405aaa233Ruben Brunk 4297f2372bd85445967ac6cb8c9519ebd1405aaa233Ruben Brunk List<int[]> supportedFpsRanges = mParams.getSupportedPreviewFpsRange(); 4307f2372bd85445967ac6cb8c9519ebd1405aaa233Ruben Brunk int[] bestRange = getPhotoPreviewFpsRange(supportedFpsRanges); 4317f2372bd85445967ac6cb8c9519ebd1405aaa233Ruben Brunk if (DEBUG) { 4327f2372bd85445967ac6cb8c9519ebd1405aaa233Ruben Brunk Log.d(TAG, "doPreviewCapture - Selected range [" + 4337f2372bd85445967ac6cb8c9519ebd1405aaa233Ruben Brunk bestRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX] + "," + 4347f2372bd85445967ac6cb8c9519ebd1405aaa233Ruben Brunk bestRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX] + "]"); 4357f2372bd85445967ac6cb8c9519ebd1405aaa233Ruben Brunk } 4367f2372bd85445967ac6cb8c9519ebd1405aaa233Ruben Brunk mParams.setPreviewFpsRange(bestRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX], 4377f2372bd85445967ac6cb8c9519ebd1405aaa233Ruben Brunk bestRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]); 4387f2372bd85445967ac6cb8c9519ebd1405aaa233Ruben Brunk 439c64e80ddda5516ceabdbbe9da41ae5e7165157b4Ruben Brunk Size smallestSupportedJpegSize = calculatePictureSize(mCallbackOutputs, 440c64e80ddda5516ceabdbbe9da41ae5e7165157b4Ruben Brunk callbackOutputSizes, mParams); 441c64e80ddda5516ceabdbbe9da41ae5e7165157b4Ruben Brunk 442f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk if (previewOutputSizes.size() > 0) { 443d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 444f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk Size largestOutput = SizeAreaComparator.findLargestByArea(previewOutputSizes); 445d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 446d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk // Find largest jpeg dimension - assume to have the same aspect ratio as sensor. 447df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin Size largestJpegDimen = ParameterUtils.getLargestSupportedJpegSizeByArea(mParams); 448d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 449c64e80ddda5516ceabdbbe9da41ae5e7165157b4Ruben Brunk Size chosenJpegDimen = (smallestSupportedJpegSize != null) ? smallestSupportedJpegSize 450c64e80ddda5516ceabdbbe9da41ae5e7165157b4Ruben Brunk : largestJpegDimen; 451c64e80ddda5516ceabdbbe9da41ae5e7165157b4Ruben Brunk 452df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin List<Size> supportedPreviewSizes = ParameterUtils.convertSizeList( 453df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin mParams.getSupportedPreviewSizes()); 454d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 455d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk // Use smallest preview dimension with same aspect ratio as sensor that is >= than all 456d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk // of the configured output dimensions. If none exists, fall back to using the largest 457d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk // supported preview size. 458d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk long largestOutputArea = largestOutput.getHeight() * (long) largestOutput.getWidth(); 459df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin Size bestPreviewDimen = SizeAreaComparator.findLargestByArea(supportedPreviewSizes); 460d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk for (Size s : supportedPreviewSizes) { 461d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk long currArea = s.getWidth() * s.getHeight(); 462d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk long bestArea = bestPreviewDimen.getWidth() * bestPreviewDimen.getHeight(); 463c64e80ddda5516ceabdbbe9da41ae5e7165157b4Ruben Brunk if (checkAspectRatiosMatch(chosenJpegDimen, s) && (currArea < bestArea && 464d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk currArea >= largestOutputArea)) { 465d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk bestPreviewDimen = s; 466d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 467d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 468d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 469d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mIntermediateBufferSize = bestPreviewDimen; 470059d766e1450eede014076957cda6300e75f84b5Ruben Brunk mParams.setPreviewSize(mIntermediateBufferSize.getWidth(), 471059d766e1450eede014076957cda6300e75f84b5Ruben Brunk mIntermediateBufferSize.getHeight()); 472059d766e1450eede014076957cda6300e75f84b5Ruben Brunk 473d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk if (DEBUG) { 474d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk Log.d(TAG, "Intermediate buffer selected with dimens: " + 475d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk bestPreviewDimen.toString()); 476d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 477d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } else { 478d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mIntermediateBufferSize = null; 479d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk if (DEBUG) { 480d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk Log.d(TAG, "No Intermediate buffer selected, no preview outputs were configured"); 481d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 482d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 483d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 484a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin if (smallestSupportedJpegSize != null) { 485a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin /* 486a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * Set takePicture size to the smallest supported JPEG size large enough 487a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * to scale/crop out of for the bounding rectangle of the configured JPEG sizes. 488a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin */ 489a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 490a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin Log.i(TAG, "configureOutputs - set take picture size to " + smallestSupportedJpegSize); 491a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin mParams.setPictureSize( 492a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin smallestSupportedJpegSize.getWidth(), smallestSupportedJpegSize.getHeight()); 493a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin } 494a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 495feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk // TODO: Detect and optimize single-output paths here to skip stream teeing. 496feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (mGLThreadManager == null) { 4974aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk mGLThreadManager = new GLThreadManager(mCameraId, facing, mDeviceState); 498feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mGLThreadManager.start(); 499feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 500feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mGLThreadManager.waitUntilStarted(); 501f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk List<Pair<Surface, Size>> previews = new ArrayList<>(); 502f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk Iterator<Size> previewSizeIter = previewOutputSizes.iterator(); 503f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk for (Surface p : mPreviewOutputs) { 504f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk previews.add(new Pair<>(p, previewSizeIter.next())); 505f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk } 506f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk mGLThreadManager.setConfigurationAndWait(previews, mCaptureCollector); 507feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mGLThreadManager.allowNewFrames(); 508feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mPreviewTexture = mGLThreadManager.getCurrentSurfaceTexture(); 509d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk if (mPreviewTexture != null) { 510d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk mPreviewTexture.setOnFrameAvailableListener(mPreviewCallback); 511d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 5125096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin 513e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk try { 514e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk mCamera.setParameters(mParams); 515e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk } catch (RuntimeException e) { 516e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk Log.e(TAG, "Received device exception while configuring: ", e); 517e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk mDeviceState.setError( 518e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); 519e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk 520e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk } 5210fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk } 5220fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk 5230fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk private void resetJpegSurfaceFormats(Collection<Surface> surfaces) { 5240fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk if (!USE_BLOB_FORMAT_OVERRIDE || surfaces == null) { 5250fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk return; 5260fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk } 5270fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk for(Surface s : surfaces) { 528443ab2c7dbe2a3a482892f3171882572f10eab9aRuben Brunk if (s == null || !s.isValid()) { 529443ab2c7dbe2a3a482892f3171882572f10eab9aRuben Brunk Log.w(TAG, "Jpeg surface is invalid, skipping..."); 530443ab2c7dbe2a3a482892f3171882572f10eab9aRuben Brunk continue; 531443ab2c7dbe2a3a482892f3171882572f10eab9aRuben Brunk } 5320fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk try { 5330fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk LegacyCameraDevice.setSurfaceFormat(s, LegacyMetadataMapper.HAL_PIXEL_FORMAT_BLOB); 5340fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) { 5350fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk Log.w(TAG, "Surface abandoned, skipping...", e); 5360fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk } 5370fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk } 538d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 539d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 540a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin /** 541a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * Find a JPEG size (that is supported by the legacy camera device) which is equal to or larger 542a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * than all of the configured {@code JPEG} outputs (by both width and height). 543a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * 544a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * <p>If multiple supported JPEG sizes are larger, select the smallest of them which 545a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * still satisfies the above constraint.</p> 546a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * 547a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * <p>As a result, the returned size is guaranteed to be usable without needing 548a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * to upscale any of the outputs. If only one {@code JPEG} surface is used, 549a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * then no scaling/cropping is necessary between the taken picture and 550a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * the {@code JPEG} output surface.</p> 551a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * 552a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * @param callbackOutputs a non-{@code null} list of {@code Surface}s with any image formats 553a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * @param params api1 parameters (used for reading only) 554a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * 555a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * @return a size large enough to fit all of the configured {@code JPEG} outputs, or 556a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * {@code null} if the {@code callbackOutputs} did not have any {@code JPEG} 557a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * surfaces. 558a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin */ 559f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk private Size calculatePictureSize( List<Surface> callbackOutputs, 560f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk List<Size> callbackSizes, Camera.Parameters params) { 561a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin /* 562a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * Find the largest JPEG size (if any), from the configured outputs: 563a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * - the api1 picture size should be set to the smallest legal size that's at least as large 564a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * as the largest configured JPEG size 565a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin */ 566f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk if (callbackOutputs.size() != callbackSizes.size()) { 567f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk throw new IllegalStateException("Input collections must be same length"); 568f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk } 569f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk List<Size> configuredJpegSizes = new ArrayList<>(); 570f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk Iterator<Size> sizeIterator = callbackSizes.iterator(); 571a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin for (Surface callbackSurface : callbackOutputs) { 572f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk Size jpegSize = sizeIterator.next(); 5730fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk if (!LegacyCameraDevice.containsSurfaceId(callbackSurface, mJpegSurfaceIds)) { 574ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk continue; // Ignore non-JPEG callback formats 575ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk } 576a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 577ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk configuredJpegSizes.add(jpegSize); 578a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin } 579a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin if (!configuredJpegSizes.isEmpty()) { 580a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin /* 581a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * Find the largest configured JPEG width, and height, independently 582a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * of the rest. 583a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * 584a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * The rest of the JPEG streams can be cropped out of this smallest bounding 585a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * rectangle. 586a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin */ 587a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin int maxConfiguredJpegWidth = -1; 588a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin int maxConfiguredJpegHeight = -1; 589a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin for (Size jpegSize : configuredJpegSizes) { 590a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin maxConfiguredJpegWidth = jpegSize.getWidth() > maxConfiguredJpegWidth ? 591a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin jpegSize.getWidth() : maxConfiguredJpegWidth; 592a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin maxConfiguredJpegHeight = jpegSize.getHeight() > maxConfiguredJpegHeight ? 593a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin jpegSize.getHeight() : maxConfiguredJpegHeight; 594a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin } 595a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin Size smallestBoundJpegSize = new Size(maxConfiguredJpegWidth, maxConfiguredJpegHeight); 596a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 597df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin List<Size> supportedJpegSizes = ParameterUtils.convertSizeList( 598df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin params.getSupportedPictureSizes()); 599a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 600a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin /* 601a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * Find the smallest supported JPEG size that can fit the smallest bounding 602a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin * rectangle for the configured JPEG sizes. 603a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin */ 604a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin List<Size> candidateSupportedJpegSizes = new ArrayList<>(); 605a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin for (Size supportedJpegSize : supportedJpegSizes) { 606a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin if (supportedJpegSize.getWidth() >= maxConfiguredJpegWidth && 607a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin supportedJpegSize.getHeight() >= maxConfiguredJpegHeight) { 608a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin candidateSupportedJpegSizes.add(supportedJpegSize); 609a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin } 610a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin } 611a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 612a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin if (candidateSupportedJpegSizes.isEmpty()) { 613a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin throw new AssertionError( 614a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin "Could not find any supported JPEG sizes large enough to fit " + 615a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin smallestBoundJpegSize); 616a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin } 617a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 618a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin Size smallestSupportedJpegSize = Collections.min(candidateSupportedJpegSizes, 619a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin new SizeAreaComparator()); 620a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 621a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin if (!smallestSupportedJpegSize.equals(smallestBoundJpegSize)) { 622a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin Log.w(TAG, 623a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin String.format( 624a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin "configureOutputs - Will need to crop picture %s into " 625a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin + "smallest bound size %s", 626a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin smallestSupportedJpegSize, smallestBoundJpegSize)); 627a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin } 628a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 629a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin return smallestSupportedJpegSize; 630a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin } 631a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 632a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin return null; 633a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin } 634a296fece2b974a11bc624fd67b275863f17df867Igor Murashkin 635d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk private static boolean checkAspectRatiosMatch(Size a, Size b) { 636d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk float aAspect = a.getWidth() / (float) a.getHeight(); 637d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk float bAspect = b.getWidth() / (float) b.getHeight(); 638d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 639d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk return Math.abs(aAspect - bAspect) < ASPECT_RATIO_TOLERANCE; 640d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 641d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk 642feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk // Calculate the highest FPS range supported 643feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private int[] getPhotoPreviewFpsRange(List<int[]> frameRates) { 644feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (frameRates.size() == 0) { 645feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk Log.e(TAG, "No supported frame rates returned!"); 646feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return null; 647feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 648feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 649feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk int bestMin = 0; 650feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk int bestMax = 0; 651feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk int bestIndex = 0; 652feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk int index = 0; 653feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk for (int[] rate : frameRates) { 654feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk int minFps = rate[Camera.Parameters.PREVIEW_FPS_MIN_INDEX]; 655feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk int maxFps = rate[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]; 656feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (maxFps > bestMax || (maxFps == bestMax && minFps > bestMin)) { 657feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk bestMin = minFps; 658feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk bestMax = maxFps; 659feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk bestIndex = index; 660feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 661feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk index++; 662feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 663feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 664feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return frameRates.get(bestIndex); 665feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 666feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 667feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private final Handler.Callback mRequestHandlerCb = new Handler.Callback() { 668feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk private boolean mCleanup = false; 66983d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin private final LegacyResultMapper mMapper = new LegacyResultMapper(); 670feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 671feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk @Override 672feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public boolean handleMessage(Message msg) { 673feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (mCleanup) { 674feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return true; 675feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 676feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 6773e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 6783e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk Log.d(TAG, "Request thread handling message:" + msg.what); 6793e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 680d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk long startTime = 0; 681d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk if (DEBUG) { 682d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk startTime = SystemClock.elapsedRealtimeNanos(); 683d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk } 684feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk switch (msg.what) { 685feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk case MSG_CONFIGURE_OUTPUTS: 686feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk ConfigureHolder config = (ConfigureHolder) msg.obj; 68749b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin int sizes = config.surfaces != null ? config.surfaces.size() : 0; 688e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.i(TAG, "Configure outputs: " + sizes + " surfaces configured."); 68991838ded36131525312739c0929913b215519c2aRuben Brunk 69091838ded36131525312739c0929913b215519c2aRuben Brunk try { 69191838ded36131525312739c0929913b215519c2aRuben Brunk boolean success = mCaptureCollector.waitForEmpty(JPEG_FRAME_TIMEOUT, 69291838ded36131525312739c0929913b215519c2aRuben Brunk TimeUnit.MILLISECONDS); 69391838ded36131525312739c0929913b215519c2aRuben Brunk if (!success) { 69491838ded36131525312739c0929913b215519c2aRuben Brunk Log.e(TAG, "Timed out while queueing configure request."); 695e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mCaptureCollector.failAll(); 69691838ded36131525312739c0929913b215519c2aRuben Brunk } 69791838ded36131525312739c0929913b215519c2aRuben Brunk } catch (InterruptedException e) { 69891838ded36131525312739c0929913b215519c2aRuben Brunk Log.e(TAG, "Interrupted while waiting for requests to complete."); 699e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mDeviceState.setError( 700e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); 701e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk break; 70291838ded36131525312739c0929913b215519c2aRuben Brunk } 70391838ded36131525312739c0929913b215519c2aRuben Brunk 704e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk configureOutputs(config.surfaces); 705feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk config.condition.open(); 706d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk if (DEBUG) { 707d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk long totalTime = SystemClock.elapsedRealtimeNanos() - startTime; 708d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk Log.d(TAG, "Configure took " + totalTime + " ns"); 709d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk } 710feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk break; 711feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk case MSG_SUBMIT_CAPTURE_REQUEST: 712feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk Handler handler = RequestThreadManager.this.mRequestThread.getHandler(); 7132da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen boolean anyRequestOutputAbandoned = false; 714feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 715feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk // Get the next burst from the request queue. 716feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk Pair<BurstHolder, Long> nextBurst = mRequestQueue.getNext(); 717e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 718feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (nextBurst == null) { 719e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // If there are no further requests queued, wait for any currently executing 720e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // requests to complete, then switch to idle state. 72191838ded36131525312739c0929913b215519c2aRuben Brunk try { 72291838ded36131525312739c0929913b215519c2aRuben Brunk boolean success = mCaptureCollector.waitForEmpty(JPEG_FRAME_TIMEOUT, 72391838ded36131525312739c0929913b215519c2aRuben Brunk TimeUnit.MILLISECONDS); 72491838ded36131525312739c0929913b215519c2aRuben Brunk if (!success) { 725e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.e(TAG, 726e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk "Timed out while waiting for prior requests to complete."); 727e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mCaptureCollector.failAll(); 72891838ded36131525312739c0929913b215519c2aRuben Brunk } 72991838ded36131525312739c0929913b215519c2aRuben Brunk } catch (InterruptedException e) { 730e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.e(TAG, "Interrupted while waiting for requests to complete: ", e); 731e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mDeviceState.setError( 732e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); 733e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk break; 73491838ded36131525312739c0929913b215519c2aRuben Brunk } 7354aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk 7364aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk synchronized (mIdleLock) { 7374aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk // Retry the the request queue. 7384aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk nextBurst = mRequestQueue.getNext(); 7394aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk 7404aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk // If we still have no queued requests, go idle. 7414aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk if (nextBurst == null) { 7424aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk mDeviceState.setIdle(); 7434aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk break; 7444aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk } 7454aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk } 7464aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk } 7474aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk 7484aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk if (nextBurst != null) { 749feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk // Queue another capture if we did not get the last burst. 750feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk handler.sendEmptyMessage(MSG_SUBMIT_CAPTURE_REQUEST); 751feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 752feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 753feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk // Complete each request in the burst 754feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk List<RequestHolder> requests = 755feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk nextBurst.first.produceRequestHolders(nextBurst.second); 756feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk for (RequestHolder holder : requests) { 7575776aafc7e70c0b79c4bee2bc50f44121b37c962Ruben Brunk CaptureRequest request = holder.getRequest(); 758d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk 759d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk boolean paramsChanged = false; 76083d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin 761e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // Only update parameters if the request has changed 762df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin if (mLastRequest == null || mLastRequest.captureRequest != request) { 763df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin 764df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin // The intermediate buffer is sometimes null, but we always need 765e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // the Camera1 API configured preview size 766df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin Size previewSize = ParameterUtils.convertSize(mParams.getPreviewSize()); 767df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin 768e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk LegacyRequest legacyRequest = new LegacyRequest(mCharacteristics, 769e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk request, previewSize, mParams); // params are copied 770e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 771df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin 772df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin // Parameters are mutated as a side-effect 773df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin LegacyMetadataMapper.convertRequestMetadata(/*inout*/legacyRequest); 774df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin 775e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // If the parameters have changed, set them in the Camera1 API. 776d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk if (!mParams.same(legacyRequest.parameters)) { 777e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk try { 778e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mCamera.setParameters(legacyRequest.parameters); 779e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } catch (RuntimeException e) { 780e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // If setting the parameters failed, report a request error to 781e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // the camera client, and skip any further work for this request 782e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.e(TAG, "Exception while setting camera parameters: ", e); 783e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk holder.failRequest(); 784e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mDeviceState.setCaptureStart(holder, /*timestamp*/0, 785e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CameraDeviceImpl.CameraDeviceCallbacks. 786e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk ERROR_CAMERA_REQUEST); 787e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk continue; 788e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 789d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk paramsChanged = true; 790e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mParams = legacyRequest.parameters; 791d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk } 792e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 793e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mLastRequest = legacyRequest; 7945776aafc7e70c0b79c4bee2bc50f44121b37c962Ruben Brunk } 795d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk 796feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk try { 79791838ded36131525312739c0929913b215519c2aRuben Brunk boolean success = mCaptureCollector.queueRequest(holder, 79891838ded36131525312739c0929913b215519c2aRuben Brunk mLastRequest, JPEG_FRAME_TIMEOUT, TimeUnit.MILLISECONDS); 79991838ded36131525312739c0929913b215519c2aRuben Brunk 80091838ded36131525312739c0929913b215519c2aRuben Brunk if (!success) { 801e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // Report a request error if we timed out while queuing this. 80291838ded36131525312739c0929913b215519c2aRuben Brunk Log.e(TAG, "Timed out while queueing capture request."); 803e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk holder.failRequest(); 804e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mDeviceState.setCaptureStart(holder, /*timestamp*/0, 805e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CameraDeviceImpl.CameraDeviceCallbacks. 806e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk ERROR_CAMERA_REQUEST); 807e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk continue; 80891838ded36131525312739c0929913b215519c2aRuben Brunk } 809e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 8100a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin // Starting the preview needs to happen before enabling 8110a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin // face detection or auto focus 812feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (holder.hasPreviewTargets()) { 813feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk doPreviewCapture(holder); 814feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 815feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (holder.hasJpegTargets()) { 816e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk while(!mCaptureCollector.waitForPreviewsEmpty(PREVIEW_FRAME_TIMEOUT, 817e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk TimeUnit.MILLISECONDS)) { 818e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // Fail preview requests until the queue is empty. 819e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.e(TAG, "Timed out while waiting for preview requests to " + 820e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk "complete."); 821e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mCaptureCollector.failNextPreview(); 82291838ded36131525312739c0929913b215519c2aRuben Brunk } 823feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mReceivedJpeg.close(); 8240a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin doJpegCapturePrepare(holder); 8250a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin } 8260a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 8270a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin /* 8280a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin * Do all the actions that require a preview to have been started 8290a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin */ 8300a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 8310a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin // Toggle face detection on/off 8320a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin // - do this before AF to give AF a chance to use faces 8330a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin mFaceDetectMapper.processFaceDetectMode(request, /*in*/mParams); 8340a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 8350a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin // Unconditionally process AF triggers, since they're non-idempotent 8360a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin // - must be done after setting the most-up-to-date AF mode 8370a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin mFocusStateMapper.processRequestTriggers(request, mParams); 8380a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 8390a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin if (holder.hasJpegTargets()) { 840feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk doJpegCapture(holder); 841feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (!mReceivedJpeg.block(JPEG_FRAME_TIMEOUT)) { 842feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk Log.e(TAG, "Hit timeout for jpeg callback!"); 843e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mCaptureCollector.failNextJpeg(); 844feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 845feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 8460a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin 847feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } catch (IOException e) { 848e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk Log.e(TAG, "Received device exception during capture call: ", e); 849e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mDeviceState.setError( 850e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); 851e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk break; 85291838ded36131525312739c0929913b215519c2aRuben Brunk } catch (InterruptedException e) { 853e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.e(TAG, "Interrupted during capture: ", e); 854e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mDeviceState.setError( 855e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); 856e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk break; 857e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk } catch (RuntimeException e) { 858e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk Log.e(TAG, "Received device exception during capture call: ", e); 859e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk mDeviceState.setError( 860e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); 861e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk break; 86291b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk } 863d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk 864d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk if (paramsChanged) { 865d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk if (DEBUG) { 866d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk Log.d(TAG, "Params changed -- getting new Parameters from HAL."); 867d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk } 868eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala try { 869eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala mParams = mCamera.getParameters(); 870eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala } catch (RuntimeException e) { 871eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala Log.e(TAG, "Received device exception: ", e); 872eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala mDeviceState.setError( 873eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); 874eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala break; 875eecc904f13e7a105f5548c953e4caa306fe06f0dEino-Ville Talvala } 876d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk 877d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk // Update parameters to the latest that we think the camera is using 878d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk mLastRequest.setParameters(mParams); 879d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk } 88083d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin 88183d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin MutableLong timestampMutable = new MutableLong(/*value*/0L); 88283d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin try { 88383d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin boolean success = mCaptureCollector.waitForRequestCompleted(holder, 88483d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin REQUEST_COMPLETE_TIMEOUT, TimeUnit.MILLISECONDS, 88583d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin /*out*/timestampMutable); 88683d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin 88783d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin if (!success) { 88883d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin Log.e(TAG, "Timed out while waiting for request to complete."); 889e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mCaptureCollector.failAll(); 89083d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin } 89183d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin } catch (InterruptedException e) { 892e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.e(TAG, "Interrupted waiting for request completion: ", e); 893e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mDeviceState.setError( 894e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); 895e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk break; 89683d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin } 89783d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin 89883d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin CameraMetadataNative result = mMapper.cachedConvertResultMetadata( 89956678d87782ddeca7956d5f48cf214a396166f0eIgor Murashkin mLastRequest, timestampMutable.value); 9008c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin /* 9018c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin * Order matters: The default result mapper is state-less; the 9028c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin * other mappers carry state and may override keys set by the default 9038c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin * mapper with their own values. 9048c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin */ 9058c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin 90683d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin // Update AF state 90783d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin mFocusStateMapper.mapResultTriggers(result); 9088c4486c14134e81999c8e732fcee3bd7e89ffb69Igor Murashkin // Update face-related results 9090a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin mFaceDetectMapper.mapResultFaces(result, mLastRequest); 91083d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin 911e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if (!holder.requestFailed()) { 912385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala mDeviceState.setCaptureResult(holder, result); 913e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 9142da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen 9152da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen if (holder.isOutputAbandoned()) { 9162da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen anyRequestOutputAbandoned = true; 9172da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } 9182da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } 9192da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen 9202da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen // Stop the repeating request if any of its output surfaces is abandoned. 9212da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen if (anyRequestOutputAbandoned && nextBurst.first.isRepeating()) { 9222da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen long lastFrameNumber = cancelRepeating(nextBurst.first.getRequestId()); 9232da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen if (DEBUG) { 9242da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen Log.d(TAG, "Stopped repeating request. Last frame number is " + 9252da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen lastFrameNumber); 9262da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen } 9272da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen mDeviceState.setRepeatingRequestError(lastFrameNumber); 928feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 9292da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen 9303e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk if (DEBUG) { 931d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk long totalTime = SystemClock.elapsedRealtimeNanos() - startTime; 932d1f113d0f0ce5099f8efba40a88398f7945bb5e0Ruben Brunk Log.d(TAG, "Capture request took " + totalTime + " ns"); 9333e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk mRequestCounter.countAndLog(); 9343e4fed203fe7c945c53c6d6bb9f160932a1d15b3Ruben Brunk } 935feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk break; 936feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk case MSG_CLEANUP: 937feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCleanup = true; 93891838ded36131525312739c0929913b215519c2aRuben Brunk try { 93991838ded36131525312739c0929913b215519c2aRuben Brunk boolean success = mCaptureCollector.waitForEmpty(JPEG_FRAME_TIMEOUT, 94091838ded36131525312739c0929913b215519c2aRuben Brunk TimeUnit.MILLISECONDS); 94191838ded36131525312739c0929913b215519c2aRuben Brunk if (!success) { 94291838ded36131525312739c0929913b215519c2aRuben Brunk Log.e(TAG, "Timed out while queueing cleanup request."); 943e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mCaptureCollector.failAll(); 94491838ded36131525312739c0929913b215519c2aRuben Brunk } 94591838ded36131525312739c0929913b215519c2aRuben Brunk } catch (InterruptedException e) { 946e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.e(TAG, "Interrupted while waiting for requests to complete: ", e); 947e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mDeviceState.setError( 948e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE); 94991838ded36131525312739c0929913b215519c2aRuben Brunk } 950feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (mGLThreadManager != null) { 951feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mGLThreadManager.quit(); 952e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk mGLThreadManager = null; 953feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 954feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk if (mCamera != null) { 955feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCamera.release(); 956e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk mCamera = null; 957feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 9580fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk resetJpegSurfaceFormats(mCallbackOutputs); 959feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk break; 96051dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin case RequestHandlerThread.MSG_POKE_IDLE_HANDLER: 96151dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin // OK: Ignore message. 96251dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin break; 963feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk default: 964feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk throw new AssertionError("Unhandled message " + msg.what + 965feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk " on RequestThread."); 966feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 967feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return true; 968feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 969feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk }; 970feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 971feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 972feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Create a new RequestThreadManager. 973feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 974feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param cameraId the id of the camera to use. 975feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param camera an open camera object. The RequestThreadManager takes ownership of this camera 976feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * object, and is responsible for closing it. 977df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * @param characteristics the static camera characteristics corresponding to this camera device 978feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param deviceState a {@link CameraDeviceState} state machine. 979feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 980df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin public RequestThreadManager(int cameraId, Camera camera, CameraCharacteristics characteristics, 981feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk CameraDeviceState deviceState) { 982df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin mCamera = checkNotNull(camera, "camera must not be null"); 983feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mCameraId = cameraId; 984df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin mCharacteristics = checkNotNull(characteristics, "characteristics must not be null"); 985feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk String name = String.format("RequestThread-%d", cameraId); 986feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk TAG = name; 987df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin mDeviceState = checkNotNull(deviceState, "deviceState must not be null"); 98883d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin mFocusStateMapper = new LegacyFocusStateMapper(mCamera); 9890a1ef4dbf39aa3dfae1a91daf972ae3457ce27feIgor Murashkin mFaceDetectMapper = new LegacyFaceDetectMapper(mCamera, mCharacteristics); 99091838ded36131525312739c0929913b215519c2aRuben Brunk mCaptureCollector = new CaptureCollector(MAX_IN_FLIGHT_REQUESTS, mDeviceState); 991feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThread = new RequestHandlerThread(name, mRequestHandlerCb); 9924aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk mCamera.setErrorCallback(mErrorCallback); 993feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 994feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 995feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 996feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Start the request thread. 997feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 998feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void start() { 999feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk mRequestThread.start(); 1000feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 1001feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 1002feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 1003e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk * Flush any pending requests. 1004e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk * 1005e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk * @return the last frame number. 1006feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 1007e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public long flush() { 1008e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.i(TAG, "Flushing all pending requests."); 1009e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk long lastFrame = mRequestQueue.stopRepeating(); 1010e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mCaptureCollector.failAll(); 1011e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk return lastFrame; 1012feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 1013feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 1014feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 1015feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Quit the request thread, and clean up everything. 1016feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 1017feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public void quit() { 1018e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk if (!mQuit.getAndSet(true)) { // Avoid sending messages on dead thread's handler. 1019e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk Handler handler = mRequestThread.waitAndGetHandler(); 1020e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk handler.sendMessageAtFrontOfQueue(handler.obtainMessage(MSG_CLEANUP)); 1021e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk mRequestThread.quitSafely(); 1022e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk try { 1023e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk mRequestThread.join(); 1024e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk } catch (InterruptedException e) { 1025e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk Log.e(TAG, String.format("Thread %s (%d) interrupted while quitting.", 1026e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk mRequestThread.getName(), mRequestThread.getId())); 1027e3c0434d9741c78ef0405de3e9f4d16b6a8ef360Ruben Brunk } 1028d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk } 1029feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 1030feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 1031feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 1032feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Submit the given burst of requests to be captured. 1033feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 1034feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p>If the burst is repeating, replace the current repeating burst.</p> 1035feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 1036feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param requests the burst of requests to add to the queue. 1037feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param repeating true if the burst is repeating. 10385d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * @return the submission info, including the new request id, and the last frame number, which 10395d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * contains either the frame number of the last frame that will be returned for this request, 10405d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * or the frame number of the last frame that will be returned for the current repeating 10415d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala * request if this burst is set to be repeating. 1042feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 10435d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala public SubmitInfo submitCaptureRequests(CaptureRequest[] requests, boolean repeating) { 1044feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk Handler handler = mRequestThread.waitAndGetHandler(); 10455d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala SubmitInfo info; 10464aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk synchronized (mIdleLock) { 10475d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala info = mRequestQueue.submit(requests, repeating); 10484aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk handler.sendEmptyMessage(MSG_SUBMIT_CAPTURE_REQUEST); 10494aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk } 10505d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala return info; 1051feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 1052feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 1053feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 1054feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Cancel a repeating request. 1055feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 1056feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param requestId the id of the repeating request to cancel. 1057feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @return the last frame to be returned from the HAL for the given repeating request, or 1058feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * {@code INVALID_FRAME} if none exists. 1059feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 1060feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public long cancelRepeating(int requestId) { 1061feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk return mRequestQueue.stopRepeating(requestId); 1062feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 1063feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 1064feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk /** 106549b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * Configure with the current list of output Surfaces. 1066feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 1067feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p> 1068feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * This operation blocks until the configuration is complete. 1069feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p> 1070feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * 107149b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * <p>Using a {@code null} or empty {@code outputs} list is the equivalent of unconfiguring.</p> 107249b2b135105e5ca5dc9547f4c6de473bebad647dIgor Murashkin * 1073feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * @param outputs a {@link java.util.Collection} of outputs to configure. 1074feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */ 1075f4a637d0be2e028d1e78c8bf90ad17ec3f84b5f3Ruben Brunk public void configure(Collection<Pair<Surface, Size>> outputs) { 1076feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk Handler handler = mRequestThread.waitAndGetHandler(); 1077feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk final ConditionVariable condition = new ConditionVariable(/*closed*/false); 1078feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk ConfigureHolder holder = new ConfigureHolder(condition, outputs); 1079feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk handler.sendMessage(handler.obtainMessage(MSG_CONFIGURE_OUTPUTS, 0, 0, holder)); 1080feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk condition.block(); 1081feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk } 1082feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk} 1083