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