191838ded36131525312739c0929913b215519c2aRuben Brunk/* 291838ded36131525312739c0929913b215519c2aRuben Brunk * Copyright (C) 2014 The Android Open Source Project 391838ded36131525312739c0929913b215519c2aRuben Brunk * 491838ded36131525312739c0929913b215519c2aRuben Brunk * Licensed under the Apache License, Version 2.0 (the "License"); 591838ded36131525312739c0929913b215519c2aRuben Brunk * you may not use this file except in compliance with the License. 691838ded36131525312739c0929913b215519c2aRuben Brunk * You may obtain a copy of the License at 791838ded36131525312739c0929913b215519c2aRuben Brunk * 891838ded36131525312739c0929913b215519c2aRuben Brunk * http://www.apache.org/licenses/LICENSE-2.0 991838ded36131525312739c0929913b215519c2aRuben Brunk * 1091838ded36131525312739c0929913b215519c2aRuben Brunk * Unless required by applicable law or agreed to in writing, software 1191838ded36131525312739c0929913b215519c2aRuben Brunk * distributed under the License is distributed on an "AS IS" BASIS, 1291838ded36131525312739c0929913b215519c2aRuben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1391838ded36131525312739c0929913b215519c2aRuben Brunk * See the License for the specific language governing permissions and 1491838ded36131525312739c0929913b215519c2aRuben Brunk * limitations under the License. 1591838ded36131525312739c0929913b215519c2aRuben Brunk */ 1691838ded36131525312739c0929913b215519c2aRuben Brunkpackage android.hardware.camera2.legacy; 1791838ded36131525312739c0929913b215519c2aRuben Brunk 18e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunkimport android.hardware.camera2.impl.CameraDeviceImpl; 1991838ded36131525312739c0929913b215519c2aRuben Brunkimport android.util.Log; 2083d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkinimport android.util.MutableLong; 2191838ded36131525312739c0929913b215519c2aRuben Brunkimport android.util.Pair; 2291838ded36131525312739c0929913b215519c2aRuben Brunk 2391838ded36131525312739c0929913b215519c2aRuben Brunkimport java.util.ArrayDeque; 2483d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkinimport java.util.ArrayList; 25e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunkimport java.util.TreeSet; 2691838ded36131525312739c0929913b215519c2aRuben Brunkimport java.util.concurrent.TimeUnit; 2791838ded36131525312739c0929913b215519c2aRuben Brunkimport java.util.concurrent.locks.Condition; 2891838ded36131525312739c0929913b215519c2aRuben Brunkimport java.util.concurrent.locks.ReentrantLock; 2991838ded36131525312739c0929913b215519c2aRuben Brunk 3091838ded36131525312739c0929913b215519c2aRuben Brunk/** 3191838ded36131525312739c0929913b215519c2aRuben Brunk * Collect timestamps and state for each {@link CaptureRequest} as it passes through 3291838ded36131525312739c0929913b215519c2aRuben Brunk * the Legacy camera pipeline. 3391838ded36131525312739c0929913b215519c2aRuben Brunk */ 3491838ded36131525312739c0929913b215519c2aRuben Brunkpublic class CaptureCollector { 3591838ded36131525312739c0929913b215519c2aRuben Brunk private static final String TAG = "CaptureCollector"; 3691838ded36131525312739c0929913b215519c2aRuben Brunk 3791838ded36131525312739c0929913b215519c2aRuben Brunk private static final boolean DEBUG = Log.isLoggable(LegacyCameraDevice.DEBUG_PROP, Log.DEBUG); 3891838ded36131525312739c0929913b215519c2aRuben Brunk 3991838ded36131525312739c0929913b215519c2aRuben Brunk private static final int FLAG_RECEIVED_JPEG = 1; 4091838ded36131525312739c0929913b215519c2aRuben Brunk private static final int FLAG_RECEIVED_JPEG_TS = 2; 4191838ded36131525312739c0929913b215519c2aRuben Brunk private static final int FLAG_RECEIVED_PREVIEW = 4; 4291838ded36131525312739c0929913b215519c2aRuben Brunk private static final int FLAG_RECEIVED_PREVIEW_TS = 8; 4391838ded36131525312739c0929913b215519c2aRuben Brunk private static final int FLAG_RECEIVED_ALL_JPEG = FLAG_RECEIVED_JPEG | FLAG_RECEIVED_JPEG_TS; 4491838ded36131525312739c0929913b215519c2aRuben Brunk private static final int FLAG_RECEIVED_ALL_PREVIEW = FLAG_RECEIVED_PREVIEW | 4591838ded36131525312739c0929913b215519c2aRuben Brunk FLAG_RECEIVED_PREVIEW_TS; 4691838ded36131525312739c0929913b215519c2aRuben Brunk 4791838ded36131525312739c0929913b215519c2aRuben Brunk private static final int MAX_JPEGS_IN_FLIGHT = 1; 4891838ded36131525312739c0929913b215519c2aRuben Brunk 49e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk private class CaptureHolder implements Comparable<CaptureHolder>{ 5091838ded36131525312739c0929913b215519c2aRuben Brunk private final RequestHolder mRequest; 5191838ded36131525312739c0929913b215519c2aRuben Brunk private final LegacyRequest mLegacy; 5291838ded36131525312739c0929913b215519c2aRuben Brunk public final boolean needsJpeg; 5391838ded36131525312739c0929913b215519c2aRuben Brunk public final boolean needsPreview; 5491838ded36131525312739c0929913b215519c2aRuben Brunk 5591838ded36131525312739c0929913b215519c2aRuben Brunk private long mTimestamp = 0; 5691838ded36131525312739c0929913b215519c2aRuben Brunk private int mReceivedFlags = 0; 5791838ded36131525312739c0929913b215519c2aRuben Brunk private boolean mHasStarted = false; 58e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk private boolean mFailedJpeg = false; 59e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk private boolean mFailedPreview = false; 60e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk private boolean mCompleted = false; 61e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk private boolean mPreviewCompleted = false; 6291838ded36131525312739c0929913b215519c2aRuben Brunk 6391838ded36131525312739c0929913b215519c2aRuben Brunk public CaptureHolder(RequestHolder request, LegacyRequest legacyHolder) { 6491838ded36131525312739c0929913b215519c2aRuben Brunk mRequest = request; 6591838ded36131525312739c0929913b215519c2aRuben Brunk mLegacy = legacyHolder; 6691838ded36131525312739c0929913b215519c2aRuben Brunk needsJpeg = request.hasJpegTargets(); 6791838ded36131525312739c0929913b215519c2aRuben Brunk needsPreview = request.hasPreviewTargets(); 6891838ded36131525312739c0929913b215519c2aRuben Brunk } 6991838ded36131525312739c0929913b215519c2aRuben Brunk 7091838ded36131525312739c0929913b215519c2aRuben Brunk public boolean isPreviewCompleted() { 7191838ded36131525312739c0929913b215519c2aRuben Brunk return (mReceivedFlags & FLAG_RECEIVED_ALL_PREVIEW) == FLAG_RECEIVED_ALL_PREVIEW; 7291838ded36131525312739c0929913b215519c2aRuben Brunk } 7391838ded36131525312739c0929913b215519c2aRuben Brunk 7491838ded36131525312739c0929913b215519c2aRuben Brunk public boolean isJpegCompleted() { 7591838ded36131525312739c0929913b215519c2aRuben Brunk return (mReceivedFlags & FLAG_RECEIVED_ALL_JPEG) == FLAG_RECEIVED_ALL_JPEG; 7691838ded36131525312739c0929913b215519c2aRuben Brunk } 7791838ded36131525312739c0929913b215519c2aRuben Brunk 7891838ded36131525312739c0929913b215519c2aRuben Brunk public boolean isCompleted() { 7991838ded36131525312739c0929913b215519c2aRuben Brunk return (needsJpeg == isJpegCompleted()) && (needsPreview == isPreviewCompleted()); 8091838ded36131525312739c0929913b215519c2aRuben Brunk } 8191838ded36131525312739c0929913b215519c2aRuben Brunk 8291838ded36131525312739c0929913b215519c2aRuben Brunk public void tryComplete() { 83e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if (!mPreviewCompleted && needsPreview && isPreviewCompleted()) { 84e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CaptureCollector.this.onPreviewCompleted(); 85e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mPreviewCompleted = true; 86e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 87e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 88e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if (isCompleted() && !mCompleted) { 89e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if (mFailedPreview || mFailedJpeg) { 90e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if (!mHasStarted) { 91e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // Send a request error if the capture has not yet started. 92e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mRequest.failRequest(); 93e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CaptureCollector.this.mDeviceState.setCaptureStart(mRequest, mTimestamp, 94e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_REQUEST); 95e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } else { 96e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // Send buffer dropped errors for each pending buffer if the request has 97e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // started. 98e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if (mFailedPreview) { 99e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.w(TAG, "Preview buffers dropped for request: " + 100e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mRequest.getRequestId()); 101e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk for (int i = 0; i < mRequest.numPreviewTargets(); i++) { 102e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CaptureCollector.this.mDeviceState.setCaptureResult(mRequest, 103e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk /*result*/null, 104e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_BUFFER); 105e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 106e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 107e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if (mFailedJpeg) { 108e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.w(TAG, "Jpeg buffers dropped for request: " + 109e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mRequest.getRequestId()); 110e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk for (int i = 0; i < mRequest.numJpegTargets(); i++) { 111e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CaptureCollector.this.mDeviceState.setCaptureResult(mRequest, 112e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk /*result*/null, 113e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_BUFFER); 114e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 115e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 116e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 117971251f362410caebe8eeb5b6c13d8912f72d50eRuben Brunk } 118e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CaptureCollector.this.onRequestCompleted(CaptureHolder.this); 119e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mCompleted = true; 12091838ded36131525312739c0929913b215519c2aRuben Brunk } 12191838ded36131525312739c0929913b215519c2aRuben Brunk } 12291838ded36131525312739c0929913b215519c2aRuben Brunk 12391838ded36131525312739c0929913b215519c2aRuben Brunk public void setJpegTimestamp(long timestamp) { 12491838ded36131525312739c0929913b215519c2aRuben Brunk if (DEBUG) { 12591838ded36131525312739c0929913b215519c2aRuben Brunk Log.d(TAG, "setJpegTimestamp - called for request " + mRequest.getRequestId()); 12691838ded36131525312739c0929913b215519c2aRuben Brunk } 12791838ded36131525312739c0929913b215519c2aRuben Brunk if (!needsJpeg) { 12891838ded36131525312739c0929913b215519c2aRuben Brunk throw new IllegalStateException( 12991838ded36131525312739c0929913b215519c2aRuben Brunk "setJpegTimestamp called for capture with no jpeg targets."); 13091838ded36131525312739c0929913b215519c2aRuben Brunk } 13191838ded36131525312739c0929913b215519c2aRuben Brunk if (isCompleted()) { 13291838ded36131525312739c0929913b215519c2aRuben Brunk throw new IllegalStateException( 13391838ded36131525312739c0929913b215519c2aRuben Brunk "setJpegTimestamp called on already completed request."); 13491838ded36131525312739c0929913b215519c2aRuben Brunk } 13591838ded36131525312739c0929913b215519c2aRuben Brunk 13691838ded36131525312739c0929913b215519c2aRuben Brunk mReceivedFlags |= FLAG_RECEIVED_JPEG_TS; 13791838ded36131525312739c0929913b215519c2aRuben Brunk 13891838ded36131525312739c0929913b215519c2aRuben Brunk if (mTimestamp == 0) { 13991838ded36131525312739c0929913b215519c2aRuben Brunk mTimestamp = timestamp; 14091838ded36131525312739c0929913b215519c2aRuben Brunk } 14191838ded36131525312739c0929913b215519c2aRuben Brunk 14291838ded36131525312739c0929913b215519c2aRuben Brunk if (!mHasStarted) { 14391838ded36131525312739c0929913b215519c2aRuben Brunk mHasStarted = true; 144e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CaptureCollector.this.mDeviceState.setCaptureStart(mRequest, mTimestamp, 145e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CameraDeviceState.NO_CAPTURE_ERROR); 14691838ded36131525312739c0929913b215519c2aRuben Brunk } 14791838ded36131525312739c0929913b215519c2aRuben Brunk 14891838ded36131525312739c0929913b215519c2aRuben Brunk tryComplete(); 14991838ded36131525312739c0929913b215519c2aRuben Brunk } 15091838ded36131525312739c0929913b215519c2aRuben Brunk 15191838ded36131525312739c0929913b215519c2aRuben Brunk public void setJpegProduced() { 15291838ded36131525312739c0929913b215519c2aRuben Brunk if (DEBUG) { 15391838ded36131525312739c0929913b215519c2aRuben Brunk Log.d(TAG, "setJpegProduced - called for request " + mRequest.getRequestId()); 15491838ded36131525312739c0929913b215519c2aRuben Brunk } 15591838ded36131525312739c0929913b215519c2aRuben Brunk if (!needsJpeg) { 15691838ded36131525312739c0929913b215519c2aRuben Brunk throw new IllegalStateException( 15791838ded36131525312739c0929913b215519c2aRuben Brunk "setJpegProduced called for capture with no jpeg targets."); 15891838ded36131525312739c0929913b215519c2aRuben Brunk } 15991838ded36131525312739c0929913b215519c2aRuben Brunk if (isCompleted()) { 16091838ded36131525312739c0929913b215519c2aRuben Brunk throw new IllegalStateException( 16191838ded36131525312739c0929913b215519c2aRuben Brunk "setJpegProduced called on already completed request."); 16291838ded36131525312739c0929913b215519c2aRuben Brunk } 16391838ded36131525312739c0929913b215519c2aRuben Brunk 16491838ded36131525312739c0929913b215519c2aRuben Brunk mReceivedFlags |= FLAG_RECEIVED_JPEG; 16591838ded36131525312739c0929913b215519c2aRuben Brunk tryComplete(); 16691838ded36131525312739c0929913b215519c2aRuben Brunk } 16791838ded36131525312739c0929913b215519c2aRuben Brunk 168e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public void setJpegFailed() { 169e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if (DEBUG) { 170e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.d(TAG, "setJpegFailed - called for request " + mRequest.getRequestId()); 171e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 172e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if (!needsJpeg || isJpegCompleted()) { 173e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk return; 174e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 175e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mFailedJpeg = true; 176e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 177e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mReceivedFlags |= FLAG_RECEIVED_JPEG; 178e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mReceivedFlags |= FLAG_RECEIVED_JPEG_TS; 179e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk tryComplete(); 180e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 181e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 18291838ded36131525312739c0929913b215519c2aRuben Brunk public void setPreviewTimestamp(long timestamp) { 18391838ded36131525312739c0929913b215519c2aRuben Brunk if (DEBUG) { 18491838ded36131525312739c0929913b215519c2aRuben Brunk Log.d(TAG, "setPreviewTimestamp - called for request " + mRequest.getRequestId()); 18591838ded36131525312739c0929913b215519c2aRuben Brunk } 18691838ded36131525312739c0929913b215519c2aRuben Brunk if (!needsPreview) { 18791838ded36131525312739c0929913b215519c2aRuben Brunk throw new IllegalStateException( 18891838ded36131525312739c0929913b215519c2aRuben Brunk "setPreviewTimestamp called for capture with no preview targets."); 18991838ded36131525312739c0929913b215519c2aRuben Brunk } 19091838ded36131525312739c0929913b215519c2aRuben Brunk if (isCompleted()) { 19191838ded36131525312739c0929913b215519c2aRuben Brunk throw new IllegalStateException( 19291838ded36131525312739c0929913b215519c2aRuben Brunk "setPreviewTimestamp called on already completed request."); 19391838ded36131525312739c0929913b215519c2aRuben Brunk } 19491838ded36131525312739c0929913b215519c2aRuben Brunk 19591838ded36131525312739c0929913b215519c2aRuben Brunk mReceivedFlags |= FLAG_RECEIVED_PREVIEW_TS; 19691838ded36131525312739c0929913b215519c2aRuben Brunk 19791838ded36131525312739c0929913b215519c2aRuben Brunk if (mTimestamp == 0) { 19891838ded36131525312739c0929913b215519c2aRuben Brunk mTimestamp = timestamp; 19991838ded36131525312739c0929913b215519c2aRuben Brunk } 20091838ded36131525312739c0929913b215519c2aRuben Brunk 20191838ded36131525312739c0929913b215519c2aRuben Brunk if (!needsJpeg) { 20291838ded36131525312739c0929913b215519c2aRuben Brunk if (!mHasStarted) { 20391838ded36131525312739c0929913b215519c2aRuben Brunk mHasStarted = true; 204e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CaptureCollector.this.mDeviceState.setCaptureStart(mRequest, mTimestamp, 205e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CameraDeviceState.NO_CAPTURE_ERROR); 20691838ded36131525312739c0929913b215519c2aRuben Brunk } 20791838ded36131525312739c0929913b215519c2aRuben Brunk } 20891838ded36131525312739c0929913b215519c2aRuben Brunk 20991838ded36131525312739c0929913b215519c2aRuben Brunk tryComplete(); 21091838ded36131525312739c0929913b215519c2aRuben Brunk } 21191838ded36131525312739c0929913b215519c2aRuben Brunk 21291838ded36131525312739c0929913b215519c2aRuben Brunk public void setPreviewProduced() { 21391838ded36131525312739c0929913b215519c2aRuben Brunk if (DEBUG) { 21491838ded36131525312739c0929913b215519c2aRuben Brunk Log.d(TAG, "setPreviewProduced - called for request " + mRequest.getRequestId()); 21591838ded36131525312739c0929913b215519c2aRuben Brunk } 21691838ded36131525312739c0929913b215519c2aRuben Brunk if (!needsPreview) { 21791838ded36131525312739c0929913b215519c2aRuben Brunk throw new IllegalStateException( 21891838ded36131525312739c0929913b215519c2aRuben Brunk "setPreviewProduced called for capture with no preview targets."); 21991838ded36131525312739c0929913b215519c2aRuben Brunk } 22091838ded36131525312739c0929913b215519c2aRuben Brunk if (isCompleted()) { 22191838ded36131525312739c0929913b215519c2aRuben Brunk throw new IllegalStateException( 22291838ded36131525312739c0929913b215519c2aRuben Brunk "setPreviewProduced called on already completed request."); 22391838ded36131525312739c0929913b215519c2aRuben Brunk } 22491838ded36131525312739c0929913b215519c2aRuben Brunk 22591838ded36131525312739c0929913b215519c2aRuben Brunk mReceivedFlags |= FLAG_RECEIVED_PREVIEW; 22691838ded36131525312739c0929913b215519c2aRuben Brunk tryComplete(); 22791838ded36131525312739c0929913b215519c2aRuben Brunk } 228e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 229e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public void setPreviewFailed() { 230e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if (DEBUG) { 231e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.d(TAG, "setPreviewFailed - called for request " + mRequest.getRequestId()); 232e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 233e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if (!needsPreview || isPreviewCompleted()) { 234e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk return; 235e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 236e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mFailedPreview = true; 237e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 238e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mReceivedFlags |= FLAG_RECEIVED_PREVIEW; 239e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mReceivedFlags |= FLAG_RECEIVED_PREVIEW_TS; 240e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk tryComplete(); 241e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 242e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 243e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // Comparison and equals based on frame number. 244e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk @Override 245e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public int compareTo(CaptureHolder captureHolder) { 246e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk return (mRequest.getFrameNumber() > captureHolder.mRequest.getFrameNumber()) ? 1 : 247e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk ((mRequest.getFrameNumber() == captureHolder.mRequest.getFrameNumber()) ? 0 : 248e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk -1); 249e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 250e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 251e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // Comparison and equals based on frame number. 252e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk @Override 253e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public boolean equals(Object o) { 254e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk return o instanceof CaptureHolder && compareTo((CaptureHolder) o) == 0; 255e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 25691838ded36131525312739c0929913b215519c2aRuben Brunk } 25791838ded36131525312739c0929913b215519c2aRuben Brunk 258e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk private final TreeSet<CaptureHolder> mActiveRequests; 25991838ded36131525312739c0929913b215519c2aRuben Brunk private final ArrayDeque<CaptureHolder> mJpegCaptureQueue; 26091838ded36131525312739c0929913b215519c2aRuben Brunk private final ArrayDeque<CaptureHolder> mJpegProduceQueue; 26191838ded36131525312739c0929913b215519c2aRuben Brunk private final ArrayDeque<CaptureHolder> mPreviewCaptureQueue; 26291838ded36131525312739c0929913b215519c2aRuben Brunk private final ArrayDeque<CaptureHolder> mPreviewProduceQueue; 26383d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin private final ArrayList<CaptureHolder> mCompletedRequests = new ArrayList<>(); 26491838ded36131525312739c0929913b215519c2aRuben Brunk 26591838ded36131525312739c0929913b215519c2aRuben Brunk private final ReentrantLock mLock = new ReentrantLock(); 26691838ded36131525312739c0929913b215519c2aRuben Brunk private final Condition mIsEmpty; 26791838ded36131525312739c0929913b215519c2aRuben Brunk private final Condition mPreviewsEmpty; 26891838ded36131525312739c0929913b215519c2aRuben Brunk private final Condition mNotFull; 26991838ded36131525312739c0929913b215519c2aRuben Brunk private final CameraDeviceState mDeviceState; 27091838ded36131525312739c0929913b215519c2aRuben Brunk private int mInFlight = 0; 27191838ded36131525312739c0929913b215519c2aRuben Brunk private int mInFlightPreviews = 0; 27291838ded36131525312739c0929913b215519c2aRuben Brunk private final int mMaxInFlight; 27391838ded36131525312739c0929913b215519c2aRuben Brunk 27491838ded36131525312739c0929913b215519c2aRuben Brunk /** 27591838ded36131525312739c0929913b215519c2aRuben Brunk * Create a new {@link CaptureCollector} that can modify the given {@link CameraDeviceState}. 27691838ded36131525312739c0929913b215519c2aRuben Brunk * 27791838ded36131525312739c0929913b215519c2aRuben Brunk * @param maxInFlight max allowed in-flight requests. 27891838ded36131525312739c0929913b215519c2aRuben Brunk * @param deviceState the {@link CameraDeviceState} to update as requests are processed. 27991838ded36131525312739c0929913b215519c2aRuben Brunk */ 28091838ded36131525312739c0929913b215519c2aRuben Brunk public CaptureCollector(int maxInFlight, CameraDeviceState deviceState) { 28191838ded36131525312739c0929913b215519c2aRuben Brunk mMaxInFlight = maxInFlight; 28291838ded36131525312739c0929913b215519c2aRuben Brunk mJpegCaptureQueue = new ArrayDeque<>(MAX_JPEGS_IN_FLIGHT); 28391838ded36131525312739c0929913b215519c2aRuben Brunk mJpegProduceQueue = new ArrayDeque<>(MAX_JPEGS_IN_FLIGHT); 28491838ded36131525312739c0929913b215519c2aRuben Brunk mPreviewCaptureQueue = new ArrayDeque<>(mMaxInFlight); 28591838ded36131525312739c0929913b215519c2aRuben Brunk mPreviewProduceQueue = new ArrayDeque<>(mMaxInFlight); 286e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mActiveRequests = new TreeSet<>(); 28791838ded36131525312739c0929913b215519c2aRuben Brunk mIsEmpty = mLock.newCondition(); 28891838ded36131525312739c0929913b215519c2aRuben Brunk mNotFull = mLock.newCondition(); 28991838ded36131525312739c0929913b215519c2aRuben Brunk mPreviewsEmpty = mLock.newCondition(); 29091838ded36131525312739c0929913b215519c2aRuben Brunk mDeviceState = deviceState; 29191838ded36131525312739c0929913b215519c2aRuben Brunk } 29291838ded36131525312739c0929913b215519c2aRuben Brunk 29391838ded36131525312739c0929913b215519c2aRuben Brunk /** 29491838ded36131525312739c0929913b215519c2aRuben Brunk * Queue a new request. 29591838ded36131525312739c0929913b215519c2aRuben Brunk * 29691838ded36131525312739c0929913b215519c2aRuben Brunk * <p> 29791838ded36131525312739c0929913b215519c2aRuben Brunk * For requests that use the Camera1 API preview output stream, this will block if there are 29891838ded36131525312739c0929913b215519c2aRuben Brunk * already {@code maxInFlight} requests in progress (until at least one prior request has 29991838ded36131525312739c0929913b215519c2aRuben Brunk * completed). For requests that use the Camera1 API jpeg callbacks, this will block until 30091838ded36131525312739c0929913b215519c2aRuben Brunk * all prior requests have been completed to avoid stopping preview for 30191838ded36131525312739c0929913b215519c2aRuben Brunk * {@link android.hardware.Camera#takePicture} before prior preview requests have been 30291838ded36131525312739c0929913b215519c2aRuben Brunk * completed. 30391838ded36131525312739c0929913b215519c2aRuben Brunk * </p> 30491838ded36131525312739c0929913b215519c2aRuben Brunk * @param holder the {@link RequestHolder} for this request. 30591838ded36131525312739c0929913b215519c2aRuben Brunk * @param legacy the {@link LegacyRequest} for this request; this will not be mutated. 30691838ded36131525312739c0929913b215519c2aRuben Brunk * @param timeout a timeout to use for this call. 30791838ded36131525312739c0929913b215519c2aRuben Brunk * @param unit the units to use for the timeout. 30891838ded36131525312739c0929913b215519c2aRuben Brunk * @return {@code false} if this method timed out. 30991838ded36131525312739c0929913b215519c2aRuben Brunk * @throws InterruptedException if this thread is interrupted. 31091838ded36131525312739c0929913b215519c2aRuben Brunk */ 31191838ded36131525312739c0929913b215519c2aRuben Brunk public boolean queueRequest(RequestHolder holder, LegacyRequest legacy, long timeout, 31291838ded36131525312739c0929913b215519c2aRuben Brunk TimeUnit unit) 31391838ded36131525312739c0929913b215519c2aRuben Brunk throws InterruptedException { 31491838ded36131525312739c0929913b215519c2aRuben Brunk CaptureHolder h = new CaptureHolder(holder, legacy); 31591838ded36131525312739c0929913b215519c2aRuben Brunk long nanos = unit.toNanos(timeout); 31691838ded36131525312739c0929913b215519c2aRuben Brunk final ReentrantLock lock = this.mLock; 31791838ded36131525312739c0929913b215519c2aRuben Brunk lock.lock(); 31891838ded36131525312739c0929913b215519c2aRuben Brunk try { 31991838ded36131525312739c0929913b215519c2aRuben Brunk if (DEBUG) { 32091838ded36131525312739c0929913b215519c2aRuben Brunk Log.d(TAG, "queueRequest for request " + holder.getRequestId() + 32191838ded36131525312739c0929913b215519c2aRuben Brunk " - " + mInFlight + " requests remain in flight."); 32291838ded36131525312739c0929913b215519c2aRuben Brunk } 3233fe9eba9044c0b20ed349a4b9094bf1fa7942cdfRuben Brunk 3243fe9eba9044c0b20ed349a4b9094bf1fa7942cdfRuben Brunk if (!(h.needsJpeg || h.needsPreview)) { 3253fe9eba9044c0b20ed349a4b9094bf1fa7942cdfRuben Brunk throw new IllegalStateException("Request must target at least one output surface!"); 3263fe9eba9044c0b20ed349a4b9094bf1fa7942cdfRuben Brunk } 3273fe9eba9044c0b20ed349a4b9094bf1fa7942cdfRuben Brunk 32891838ded36131525312739c0929913b215519c2aRuben Brunk if (h.needsJpeg) { 32991838ded36131525312739c0929913b215519c2aRuben Brunk // Wait for all current requests to finish before queueing jpeg. 33091838ded36131525312739c0929913b215519c2aRuben Brunk while (mInFlight > 0) { 33191838ded36131525312739c0929913b215519c2aRuben Brunk if (nanos <= 0) { 33291838ded36131525312739c0929913b215519c2aRuben Brunk return false; 33391838ded36131525312739c0929913b215519c2aRuben Brunk } 33491838ded36131525312739c0929913b215519c2aRuben Brunk nanos = mIsEmpty.awaitNanos(nanos); 33591838ded36131525312739c0929913b215519c2aRuben Brunk } 33691838ded36131525312739c0929913b215519c2aRuben Brunk mJpegCaptureQueue.add(h); 33791838ded36131525312739c0929913b215519c2aRuben Brunk mJpegProduceQueue.add(h); 33891838ded36131525312739c0929913b215519c2aRuben Brunk } 33991838ded36131525312739c0929913b215519c2aRuben Brunk if (h.needsPreview) { 34091838ded36131525312739c0929913b215519c2aRuben Brunk while (mInFlight >= mMaxInFlight) { 34191838ded36131525312739c0929913b215519c2aRuben Brunk if (nanos <= 0) { 34291838ded36131525312739c0929913b215519c2aRuben Brunk return false; 34391838ded36131525312739c0929913b215519c2aRuben Brunk } 34491838ded36131525312739c0929913b215519c2aRuben Brunk nanos = mNotFull.awaitNanos(nanos); 34591838ded36131525312739c0929913b215519c2aRuben Brunk } 34691838ded36131525312739c0929913b215519c2aRuben Brunk mPreviewCaptureQueue.add(h); 34791838ded36131525312739c0929913b215519c2aRuben Brunk mPreviewProduceQueue.add(h); 34891838ded36131525312739c0929913b215519c2aRuben Brunk mInFlightPreviews++; 34991838ded36131525312739c0929913b215519c2aRuben Brunk } 350e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mActiveRequests.add(h); 35191838ded36131525312739c0929913b215519c2aRuben Brunk 35291838ded36131525312739c0929913b215519c2aRuben Brunk mInFlight++; 35391838ded36131525312739c0929913b215519c2aRuben Brunk return true; 35491838ded36131525312739c0929913b215519c2aRuben Brunk } finally { 35591838ded36131525312739c0929913b215519c2aRuben Brunk lock.unlock(); 35691838ded36131525312739c0929913b215519c2aRuben Brunk } 35791838ded36131525312739c0929913b215519c2aRuben Brunk } 35891838ded36131525312739c0929913b215519c2aRuben Brunk 35991838ded36131525312739c0929913b215519c2aRuben Brunk /** 36091838ded36131525312739c0929913b215519c2aRuben Brunk * Wait all queued requests to complete. 36191838ded36131525312739c0929913b215519c2aRuben Brunk * 36291838ded36131525312739c0929913b215519c2aRuben Brunk * @param timeout a timeout to use for this call. 36391838ded36131525312739c0929913b215519c2aRuben Brunk * @param unit the units to use for the timeout. 36491838ded36131525312739c0929913b215519c2aRuben Brunk * @return {@code false} if this method timed out. 36591838ded36131525312739c0929913b215519c2aRuben Brunk * @throws InterruptedException if this thread is interrupted. 36691838ded36131525312739c0929913b215519c2aRuben Brunk */ 36791838ded36131525312739c0929913b215519c2aRuben Brunk public boolean waitForEmpty(long timeout, TimeUnit unit) throws InterruptedException { 36891838ded36131525312739c0929913b215519c2aRuben Brunk long nanos = unit.toNanos(timeout); 36991838ded36131525312739c0929913b215519c2aRuben Brunk final ReentrantLock lock = this.mLock; 37091838ded36131525312739c0929913b215519c2aRuben Brunk lock.lock(); 37191838ded36131525312739c0929913b215519c2aRuben Brunk try { 37291838ded36131525312739c0929913b215519c2aRuben Brunk while (mInFlight > 0) { 37391838ded36131525312739c0929913b215519c2aRuben Brunk if (nanos <= 0) { 37491838ded36131525312739c0929913b215519c2aRuben Brunk return false; 37591838ded36131525312739c0929913b215519c2aRuben Brunk } 37691838ded36131525312739c0929913b215519c2aRuben Brunk nanos = mIsEmpty.awaitNanos(nanos); 37791838ded36131525312739c0929913b215519c2aRuben Brunk } 37891838ded36131525312739c0929913b215519c2aRuben Brunk return true; 37991838ded36131525312739c0929913b215519c2aRuben Brunk } finally { 38091838ded36131525312739c0929913b215519c2aRuben Brunk lock.unlock(); 38191838ded36131525312739c0929913b215519c2aRuben Brunk } 38291838ded36131525312739c0929913b215519c2aRuben Brunk } 38391838ded36131525312739c0929913b215519c2aRuben Brunk 38491838ded36131525312739c0929913b215519c2aRuben Brunk /** 38591838ded36131525312739c0929913b215519c2aRuben Brunk * Wait all queued requests that use the Camera1 API preview output to complete. 38691838ded36131525312739c0929913b215519c2aRuben Brunk * 38791838ded36131525312739c0929913b215519c2aRuben Brunk * @param timeout a timeout to use for this call. 38891838ded36131525312739c0929913b215519c2aRuben Brunk * @param unit the units to use for the timeout. 38991838ded36131525312739c0929913b215519c2aRuben Brunk * @return {@code false} if this method timed out. 39091838ded36131525312739c0929913b215519c2aRuben Brunk * @throws InterruptedException if this thread is interrupted. 39191838ded36131525312739c0929913b215519c2aRuben Brunk */ 39291838ded36131525312739c0929913b215519c2aRuben Brunk public boolean waitForPreviewsEmpty(long timeout, TimeUnit unit) throws InterruptedException { 39391838ded36131525312739c0929913b215519c2aRuben Brunk long nanos = unit.toNanos(timeout); 39491838ded36131525312739c0929913b215519c2aRuben Brunk final ReentrantLock lock = this.mLock; 39591838ded36131525312739c0929913b215519c2aRuben Brunk lock.lock(); 39691838ded36131525312739c0929913b215519c2aRuben Brunk try { 39791838ded36131525312739c0929913b215519c2aRuben Brunk while (mInFlightPreviews > 0) { 39891838ded36131525312739c0929913b215519c2aRuben Brunk if (nanos <= 0) { 39991838ded36131525312739c0929913b215519c2aRuben Brunk return false; 40091838ded36131525312739c0929913b215519c2aRuben Brunk } 40191838ded36131525312739c0929913b215519c2aRuben Brunk nanos = mPreviewsEmpty.awaitNanos(nanos); 40291838ded36131525312739c0929913b215519c2aRuben Brunk } 40391838ded36131525312739c0929913b215519c2aRuben Brunk return true; 40491838ded36131525312739c0929913b215519c2aRuben Brunk } finally { 40591838ded36131525312739c0929913b215519c2aRuben Brunk lock.unlock(); 40691838ded36131525312739c0929913b215519c2aRuben Brunk } 40791838ded36131525312739c0929913b215519c2aRuben Brunk } 40891838ded36131525312739c0929913b215519c2aRuben Brunk 40991838ded36131525312739c0929913b215519c2aRuben Brunk /** 41083d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin * Wait for the specified request to be completed (all buffers available). 41183d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin * 41283d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin * <p>May not wait for the same request more than once, since a successful wait 41383d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin * will erase the history of that request.</p> 41483d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin * 41583d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin * @param holder the {@link RequestHolder} for this request. 41683d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin * @param timeout a timeout to use for this call. 41783d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin * @param unit the units to use for the timeout. 41883d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin * @param timestamp the timestamp of the request will be written out to here, in ns 41983d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin * 42083d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin * @return {@code false} if this method timed out. 42183d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin * 42283d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin * @throws InterruptedException if this thread is interrupted. 42383d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin */ 42483d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin public boolean waitForRequestCompleted(RequestHolder holder, long timeout, TimeUnit unit, 42583d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin MutableLong timestamp) 42683d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin throws InterruptedException { 42783d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin long nanos = unit.toNanos(timeout); 42883d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin final ReentrantLock lock = this.mLock; 42983d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin lock.lock(); 43083d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin try { 43183d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin while (!removeRequestIfCompleted(holder, /*out*/timestamp)) { 43283d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin if (nanos <= 0) { 43383d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin return false; 43483d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin } 43583d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin nanos = mNotFull.awaitNanos(nanos); 43683d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin } 43783d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin return true; 43883d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin } finally { 43983d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin lock.unlock(); 44083d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin } 44183d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin } 44283d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin 44383d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin private boolean removeRequestIfCompleted(RequestHolder holder, MutableLong timestamp) { 44483d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin int i = 0; 44583d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin for (CaptureHolder h : mCompletedRequests) { 44683d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin if (h.mRequest.equals(holder)) { 44783d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin timestamp.value = h.mTimestamp; 44883d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin mCompletedRequests.remove(i); 44983d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin return true; 45083d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin } 45183d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin i++; 45283d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin } 45383d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin 45483d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin return false; 45583d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin } 45683d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin 45783d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin /** 45891838ded36131525312739c0929913b215519c2aRuben Brunk * Called to alert the {@link CaptureCollector} that the jpeg capture has begun. 45991838ded36131525312739c0929913b215519c2aRuben Brunk * 46091838ded36131525312739c0929913b215519c2aRuben Brunk * @param timestamp the time of the jpeg capture. 46191838ded36131525312739c0929913b215519c2aRuben Brunk * @return the {@link RequestHolder} for the request associated with this capture. 46291838ded36131525312739c0929913b215519c2aRuben Brunk */ 46391838ded36131525312739c0929913b215519c2aRuben Brunk public RequestHolder jpegCaptured(long timestamp) { 46491838ded36131525312739c0929913b215519c2aRuben Brunk final ReentrantLock lock = this.mLock; 46591838ded36131525312739c0929913b215519c2aRuben Brunk lock.lock(); 46691838ded36131525312739c0929913b215519c2aRuben Brunk try { 46791838ded36131525312739c0929913b215519c2aRuben Brunk CaptureHolder h = mJpegCaptureQueue.poll(); 46891838ded36131525312739c0929913b215519c2aRuben Brunk if (h == null) { 46991838ded36131525312739c0929913b215519c2aRuben Brunk Log.w(TAG, "jpegCaptured called with no jpeg request on queue!"); 47091838ded36131525312739c0929913b215519c2aRuben Brunk return null; 47191838ded36131525312739c0929913b215519c2aRuben Brunk } 47291838ded36131525312739c0929913b215519c2aRuben Brunk h.setJpegTimestamp(timestamp); 47391838ded36131525312739c0929913b215519c2aRuben Brunk return h.mRequest; 47491838ded36131525312739c0929913b215519c2aRuben Brunk } finally { 47591838ded36131525312739c0929913b215519c2aRuben Brunk lock.unlock(); 47691838ded36131525312739c0929913b215519c2aRuben Brunk } 47791838ded36131525312739c0929913b215519c2aRuben Brunk } 47891838ded36131525312739c0929913b215519c2aRuben Brunk 47991838ded36131525312739c0929913b215519c2aRuben Brunk /** 48091838ded36131525312739c0929913b215519c2aRuben Brunk * Called to alert the {@link CaptureCollector} that the jpeg capture has completed. 48191838ded36131525312739c0929913b215519c2aRuben Brunk * 48291838ded36131525312739c0929913b215519c2aRuben Brunk * @return a pair containing the {@link RequestHolder} and the timestamp of the capture. 48391838ded36131525312739c0929913b215519c2aRuben Brunk */ 48491838ded36131525312739c0929913b215519c2aRuben Brunk public Pair<RequestHolder, Long> jpegProduced() { 48591838ded36131525312739c0929913b215519c2aRuben Brunk final ReentrantLock lock = this.mLock; 48691838ded36131525312739c0929913b215519c2aRuben Brunk lock.lock(); 48791838ded36131525312739c0929913b215519c2aRuben Brunk try { 48891838ded36131525312739c0929913b215519c2aRuben Brunk CaptureHolder h = mJpegProduceQueue.poll(); 48991838ded36131525312739c0929913b215519c2aRuben Brunk if (h == null) { 49091838ded36131525312739c0929913b215519c2aRuben Brunk Log.w(TAG, "jpegProduced called with no jpeg request on queue!"); 49191838ded36131525312739c0929913b215519c2aRuben Brunk return null; 49291838ded36131525312739c0929913b215519c2aRuben Brunk } 49391838ded36131525312739c0929913b215519c2aRuben Brunk h.setJpegProduced(); 49491838ded36131525312739c0929913b215519c2aRuben Brunk return new Pair<>(h.mRequest, h.mTimestamp); 49591838ded36131525312739c0929913b215519c2aRuben Brunk } finally { 49691838ded36131525312739c0929913b215519c2aRuben Brunk lock.unlock(); 49791838ded36131525312739c0929913b215519c2aRuben Brunk } 49891838ded36131525312739c0929913b215519c2aRuben Brunk } 49991838ded36131525312739c0929913b215519c2aRuben Brunk 50091838ded36131525312739c0929913b215519c2aRuben Brunk /** 50191838ded36131525312739c0929913b215519c2aRuben Brunk * Check if there are any pending capture requests that use the Camera1 API preview output. 50291838ded36131525312739c0929913b215519c2aRuben Brunk * 50391838ded36131525312739c0929913b215519c2aRuben Brunk * @return {@code true} if there are pending preview requests. 50491838ded36131525312739c0929913b215519c2aRuben Brunk */ 50591838ded36131525312739c0929913b215519c2aRuben Brunk public boolean hasPendingPreviewCaptures() { 50691838ded36131525312739c0929913b215519c2aRuben Brunk final ReentrantLock lock = this.mLock; 50791838ded36131525312739c0929913b215519c2aRuben Brunk lock.lock(); 50891838ded36131525312739c0929913b215519c2aRuben Brunk try { 50991838ded36131525312739c0929913b215519c2aRuben Brunk return !mPreviewCaptureQueue.isEmpty(); 51091838ded36131525312739c0929913b215519c2aRuben Brunk } finally { 51191838ded36131525312739c0929913b215519c2aRuben Brunk lock.unlock(); 51291838ded36131525312739c0929913b215519c2aRuben Brunk } 51391838ded36131525312739c0929913b215519c2aRuben Brunk } 51491838ded36131525312739c0929913b215519c2aRuben Brunk 51591838ded36131525312739c0929913b215519c2aRuben Brunk /** 51691838ded36131525312739c0929913b215519c2aRuben Brunk * Called to alert the {@link CaptureCollector} that the preview capture has begun. 51791838ded36131525312739c0929913b215519c2aRuben Brunk * 51891838ded36131525312739c0929913b215519c2aRuben Brunk * @param timestamp the time of the preview capture. 51991838ded36131525312739c0929913b215519c2aRuben Brunk * @return a pair containing the {@link RequestHolder} and the timestamp of the capture. 52091838ded36131525312739c0929913b215519c2aRuben Brunk */ 52191838ded36131525312739c0929913b215519c2aRuben Brunk public Pair<RequestHolder, Long> previewCaptured(long timestamp) { 52291838ded36131525312739c0929913b215519c2aRuben Brunk final ReentrantLock lock = this.mLock; 52391838ded36131525312739c0929913b215519c2aRuben Brunk lock.lock(); 52491838ded36131525312739c0929913b215519c2aRuben Brunk try { 52591838ded36131525312739c0929913b215519c2aRuben Brunk CaptureHolder h = mPreviewCaptureQueue.poll(); 52691838ded36131525312739c0929913b215519c2aRuben Brunk if (h == null) { 527e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if (DEBUG) { 528e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk Log.d(TAG, "previewCaptured called with no preview request on queue!"); 529e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 53091838ded36131525312739c0929913b215519c2aRuben Brunk return null; 53191838ded36131525312739c0929913b215519c2aRuben Brunk } 53291838ded36131525312739c0929913b215519c2aRuben Brunk h.setPreviewTimestamp(timestamp); 53391838ded36131525312739c0929913b215519c2aRuben Brunk return new Pair<>(h.mRequest, h.mTimestamp); 53491838ded36131525312739c0929913b215519c2aRuben Brunk } finally { 53591838ded36131525312739c0929913b215519c2aRuben Brunk lock.unlock(); 53691838ded36131525312739c0929913b215519c2aRuben Brunk } 53791838ded36131525312739c0929913b215519c2aRuben Brunk } 53891838ded36131525312739c0929913b215519c2aRuben Brunk 53991838ded36131525312739c0929913b215519c2aRuben Brunk /** 54091838ded36131525312739c0929913b215519c2aRuben Brunk * Called to alert the {@link CaptureCollector} that the preview capture has completed. 54191838ded36131525312739c0929913b215519c2aRuben Brunk * 54291838ded36131525312739c0929913b215519c2aRuben Brunk * @return the {@link RequestHolder} for the request associated with this capture. 54391838ded36131525312739c0929913b215519c2aRuben Brunk */ 54491838ded36131525312739c0929913b215519c2aRuben Brunk public RequestHolder previewProduced() { 54591838ded36131525312739c0929913b215519c2aRuben Brunk final ReentrantLock lock = this.mLock; 54691838ded36131525312739c0929913b215519c2aRuben Brunk lock.lock(); 54791838ded36131525312739c0929913b215519c2aRuben Brunk try { 54891838ded36131525312739c0929913b215519c2aRuben Brunk CaptureHolder h = mPreviewProduceQueue.poll(); 54991838ded36131525312739c0929913b215519c2aRuben Brunk if (h == null) { 55091838ded36131525312739c0929913b215519c2aRuben Brunk Log.w(TAG, "previewProduced called with no preview request on queue!"); 55191838ded36131525312739c0929913b215519c2aRuben Brunk return null; 55291838ded36131525312739c0929913b215519c2aRuben Brunk } 55391838ded36131525312739c0929913b215519c2aRuben Brunk h.setPreviewProduced(); 55491838ded36131525312739c0929913b215519c2aRuben Brunk return h.mRequest; 55591838ded36131525312739c0929913b215519c2aRuben Brunk } finally { 55691838ded36131525312739c0929913b215519c2aRuben Brunk lock.unlock(); 55791838ded36131525312739c0929913b215519c2aRuben Brunk } 55891838ded36131525312739c0929913b215519c2aRuben Brunk } 55991838ded36131525312739c0929913b215519c2aRuben Brunk 560e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk /** 561e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk * Called to alert the {@link CaptureCollector} that the next pending preview capture has failed. 562e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk */ 563e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public void failNextPreview() { 564e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk final ReentrantLock lock = this.mLock; 565e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk lock.lock(); 566e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk try { 567e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CaptureHolder h1 = mPreviewCaptureQueue.peek(); 568e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CaptureHolder h2 = mPreviewProduceQueue.peek(); 569e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 570e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // Find the request with the lowest frame number. 571e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CaptureHolder h = (h1 == null) ? h2 : 572e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk ((h2 == null) ? h1 : 573e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk ((h1.compareTo(h2) <= 0) ? h1 : 574e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk h2)); 575e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 576e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if (h != null) { 577e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mPreviewCaptureQueue.remove(h); 578e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mPreviewProduceQueue.remove(h); 579e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mActiveRequests.remove(h); 580e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk h.setPreviewFailed(); 581e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 582e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } finally { 583e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk lock.unlock(); 584e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 585e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 586e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 587e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk /** 588e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk * Called to alert the {@link CaptureCollector} that the next pending jpeg capture has failed. 589e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk */ 590e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public void failNextJpeg() { 591e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk final ReentrantLock lock = this.mLock; 592e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk lock.lock(); 593e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk try { 594e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CaptureHolder h1 = mJpegCaptureQueue.peek(); 595e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CaptureHolder h2 = mJpegProduceQueue.peek(); 596e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 597e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk // Find the request with the lowest frame number. 598e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CaptureHolder h = (h1 == null) ? h2 : 599e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk ((h2 == null) ? h1 : 600e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk ((h1.compareTo(h2) <= 0) ? h1 : 601e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk h2)); 602e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 603e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk if (h != null) { 604e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mJpegCaptureQueue.remove(h); 605e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mJpegProduceQueue.remove(h); 606e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mActiveRequests.remove(h); 607e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk h.setJpegFailed(); 608e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 609e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } finally { 610e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk lock.unlock(); 611e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 612e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 613e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 614e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk /** 615e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk * Called to alert the {@link CaptureCollector} all pending captures have failed. 616e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk */ 617e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk public void failAll() { 618e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk final ReentrantLock lock = this.mLock; 619e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk lock.lock(); 620e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk try { 621e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk CaptureHolder h; 622e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk while ((h = mActiveRequests.pollFirst()) != null) { 623e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk h.setPreviewFailed(); 624e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk h.setJpegFailed(); 625e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 626e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mPreviewCaptureQueue.clear(); 627e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mPreviewProduceQueue.clear(); 628e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mJpegCaptureQueue.clear(); 629e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mJpegProduceQueue.clear(); 630e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } finally { 631e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk lock.unlock(); 632e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 633e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk } 634e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk 63591838ded36131525312739c0929913b215519c2aRuben Brunk private void onPreviewCompleted() { 63691838ded36131525312739c0929913b215519c2aRuben Brunk mInFlightPreviews--; 63791838ded36131525312739c0929913b215519c2aRuben Brunk if (mInFlightPreviews < 0) { 63891838ded36131525312739c0929913b215519c2aRuben Brunk throw new IllegalStateException( 63991838ded36131525312739c0929913b215519c2aRuben Brunk "More preview captures completed than requests queued."); 64091838ded36131525312739c0929913b215519c2aRuben Brunk } 64191838ded36131525312739c0929913b215519c2aRuben Brunk if (mInFlightPreviews == 0) { 64291838ded36131525312739c0929913b215519c2aRuben Brunk mPreviewsEmpty.signalAll(); 64391838ded36131525312739c0929913b215519c2aRuben Brunk } 64491838ded36131525312739c0929913b215519c2aRuben Brunk } 64591838ded36131525312739c0929913b215519c2aRuben Brunk 64683d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin private void onRequestCompleted(CaptureHolder capture) { 64783d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin RequestHolder request = capture.mRequest; 64883d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin 64991838ded36131525312739c0929913b215519c2aRuben Brunk mInFlight--; 65091838ded36131525312739c0929913b215519c2aRuben Brunk if (DEBUG) { 65191838ded36131525312739c0929913b215519c2aRuben Brunk Log.d(TAG, "Completed request " + request.getRequestId() + 65291838ded36131525312739c0929913b215519c2aRuben Brunk ", " + mInFlight + " requests remain in flight."); 65391838ded36131525312739c0929913b215519c2aRuben Brunk } 65491838ded36131525312739c0929913b215519c2aRuben Brunk if (mInFlight < 0) { 65591838ded36131525312739c0929913b215519c2aRuben Brunk throw new IllegalStateException( 65691838ded36131525312739c0929913b215519c2aRuben Brunk "More captures completed than requests queued."); 65791838ded36131525312739c0929913b215519c2aRuben Brunk } 65883d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin 65983d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin mCompletedRequests.add(capture); 660e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk mActiveRequests.remove(capture); 66183d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin 66291838ded36131525312739c0929913b215519c2aRuben Brunk mNotFull.signalAll(); 66391838ded36131525312739c0929913b215519c2aRuben Brunk if (mInFlight == 0) { 66491838ded36131525312739c0929913b215519c2aRuben Brunk mIsEmpty.signalAll(); 66591838ded36131525312739c0929913b215519c2aRuben Brunk } 66691838ded36131525312739c0929913b215519c2aRuben Brunk } 66791838ded36131525312739c0929913b215519c2aRuben Brunk} 668