summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2019-05-17 21:20:44 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2019-05-17 21:20:44 +0000
commit34bc57f73887bda3b362b90ede3f9a58f907e088 (patch)
treede9fc0482a25ec0cfbdd1791c83ce67b7d9c022f
parent4f09b09f62d48b291b77cf09c207b6570bd88535 (diff)
parentb45449b9bce8d9291b259879e7495cd94c6b28fd (diff)
Merge "Camera: Handle out-of-order frameNumber for ZSL requests" into qt-dev
-rw-r--r--core/java/android/hardware/camera2/CaptureRequest.java56
-rw-r--r--core/java/android/hardware/camera2/impl/CameraDeviceImpl.java368
2 files changed, 291 insertions, 133 deletions
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index eddfd7d0e8e6..6a2fc8a2ca34 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -235,6 +235,62 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
new HashMap<String, CameraMetadataNative>();
private boolean mIsReprocess;
+
+ //
+ // Enumeration values for types of CaptureRequest
+ //
+
+ /**
+ * @hide
+ */
+ public static final int REQUEST_TYPE_REGULAR = 0;
+
+ /**
+ * @hide
+ */
+ public static final int REQUEST_TYPE_REPROCESS = 1;
+
+ /**
+ * @hide
+ */
+ public static final int REQUEST_TYPE_ZSL_STILL = 2;
+
+ /**
+ * Note: To add another request type, the FrameNumberTracker in CameraDeviceImpl must be
+ * adjusted accordingly.
+ * @hide
+ */
+ public static final int REQUEST_TYPE_COUNT = 3;
+
+
+ private int mRequestType = -1;
+
+ /**
+ * Get the type of the capture request
+ *
+ * Return one of REGULAR, ZSL_STILL, or REPROCESS.
+ * @hide
+ */
+ public int getRequestType() {
+ if (mRequestType == -1) {
+ if (mIsReprocess) {
+ mRequestType = REQUEST_TYPE_REPROCESS;
+ } else {
+ Boolean enableZsl = mLogicalCameraSettings.get(CaptureRequest.CONTROL_ENABLE_ZSL);
+ boolean isZslStill = false;
+ if (enableZsl != null && enableZsl) {
+ int captureIntent = mLogicalCameraSettings.get(
+ CaptureRequest.CONTROL_CAPTURE_INTENT);
+ if (captureIntent == CameraMetadata.CONTROL_CAPTURE_INTENT_STILL_CAPTURE) {
+ isZslStill = true;
+ }
+ }
+ mRequestType = isZslStill ? REQUEST_TYPE_ZSL_STILL : REQUEST_TYPE_REGULAR;
+ }
+ }
+ return mRequestType;
+ }
+
// If this request is part of constrained high speed request list that was created by
// {@link android.hardware.camera2.CameraConstrainedHighSpeedCaptureSession#createHighSpeedRequestList}
private boolean mIsPartOfCHSRequestList = false;
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index fc12b090b2f3..cc8c182b867e 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -95,6 +95,8 @@ public class CameraDeviceImpl extends CameraDevice
new SparseArray<CaptureCallbackHolder>();
private int mRepeatingRequestId = REQUEST_ID_NONE;
+ // Latest repeating request list's types
+ private int[] mRepeatingRequestTypes;
// Map stream IDs to input/output configurations
private SimpleEntry<Integer, InputConfiguration> mConfiguredInput =
new SimpleEntry<>(REQUEST_ID_NONE, null);
@@ -108,7 +110,7 @@ public class CameraDeviceImpl extends CameraDevice
private static final long NANO_PER_SECOND = 1000000000; //ns
/**
- * A list tracking request and its expected last regular frame number and last reprocess frame
+ * A list tracking request and its expected last regular/reprocess/zslStill frame
* number. Updated when calling ICameraDeviceUser methods.
*/
private final List<RequestLastFrameNumbersHolder> mRequestLastFrameNumbersList =
@@ -943,11 +945,12 @@ public class CameraDeviceImpl extends CameraDevice
* regular frame number will be added to the list mRequestLastFrameNumbersList.</p>
*
* @param requestId the request ID of the current repeating request.
- *
* @param lastFrameNumber last frame number returned from binder.
+ * @param repeatingRequestTypes the repeating requests' types.
*/
private void checkEarlyTriggerSequenceComplete(
- final int requestId, final long lastFrameNumber) {
+ final int requestId, final long lastFrameNumber,
+ final int[] repeatingRequestTypes) {
// lastFrameNumber being equal to NO_FRAMES_CAPTURED means that the request
// was never sent to HAL. Should trigger onCaptureSequenceAborted immediately.
if (lastFrameNumber == CaptureCallback.NO_FRAMES_CAPTURED) {
@@ -997,10 +1000,10 @@ public class CameraDeviceImpl extends CameraDevice
requestId));
}
} else {
- // This function is only called for regular request so lastFrameNumber is the last
- // regular frame number.
+ // This function is only called for regular/ZslStill request so lastFrameNumber is the
+ // last regular/ZslStill frame number.
mRequestLastFrameNumbersList.add(new RequestLastFrameNumbersHolder(requestId,
- lastFrameNumber));
+ lastFrameNumber, repeatingRequestTypes));
// It is possible that the last frame has already arrived, so we need to check
// for sequence completion right away
@@ -1008,6 +1011,14 @@ public class CameraDeviceImpl extends CameraDevice
}
}
+ private int[] getRequestTypes(final CaptureRequest[] requestArray) {
+ int[] requestTypes = new int[requestArray.length];
+ for (int i = 0; i < requestArray.length; i++) {
+ requestTypes[i] = requestArray[i].getRequestType();
+ }
+ return requestTypes;
+ }
+
private int submitCaptureRequest(List<CaptureRequest> requestList, CaptureCallback callback,
Executor executor, boolean repeating) throws CameraAccessException {
@@ -1077,9 +1088,11 @@ public class CameraDeviceImpl extends CameraDevice
if (repeating) {
if (mRepeatingRequestId != REQUEST_ID_NONE) {
checkEarlyTriggerSequenceComplete(mRepeatingRequestId,
- requestInfo.getLastFrameNumber());
+ requestInfo.getLastFrameNumber(),
+ mRepeatingRequestTypes);
}
mRepeatingRequestId = requestInfo.getRequestId();
+ mRepeatingRequestTypes = getRequestTypes(requestArray);
} else {
mRequestLastFrameNumbersList.add(
new RequestLastFrameNumbersHolder(requestList, requestInfo));
@@ -1117,6 +1130,8 @@ public class CameraDeviceImpl extends CameraDevice
int requestId = mRepeatingRequestId;
mRepeatingRequestId = REQUEST_ID_NONE;
+ int[] requestTypes = mRepeatingRequestTypes;
+ mRepeatingRequestTypes = null;
long lastFrameNumber;
try {
@@ -1129,7 +1144,7 @@ public class CameraDeviceImpl extends CameraDevice
return;
}
- checkEarlyTriggerSequenceComplete(requestId, lastFrameNumber);
+ checkEarlyTriggerSequenceComplete(requestId, lastFrameNumber, requestTypes);
}
}
}
@@ -1162,8 +1177,10 @@ public class CameraDeviceImpl extends CameraDevice
long lastFrameNumber = mRemoteDevice.flush();
if (mRepeatingRequestId != REQUEST_ID_NONE) {
- checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber);
+ checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber,
+ mRepeatingRequestTypes);
mRepeatingRequestId = REQUEST_ID_NONE;
+ mRepeatingRequestTypes = null;
}
}
}
@@ -1470,7 +1487,7 @@ public class CameraDeviceImpl extends CameraDevice
}
/**
- * This class holds a capture ID and its expected last regular frame number and last reprocess
+ * This class holds a capture ID and its expected last regular, zslStill, and reprocess
* frame number.
*/
static class RequestLastFrameNumbersHolder {
@@ -1482,6 +1499,9 @@ public class CameraDeviceImpl extends CameraDevice
// The last reprocess frame number for this request ID. It's
// CaptureCallback.NO_FRAMES_CAPTURED if the request ID has no reprocess request.
private final long mLastReprocessFrameNumber;
+ // The last ZSL still capture frame number for this request ID. It's
+ // CaptureCallback.NO_FRAMES_CAPTURED if the request ID has no zsl request.
+ private final long mLastZslStillFrameNumber;
/**
* Create a request-last-frame-numbers holder with a list of requests, request ID, and
@@ -1490,6 +1510,7 @@ public class CameraDeviceImpl extends CameraDevice
public RequestLastFrameNumbersHolder(List<CaptureRequest> requestList, SubmitInfo requestInfo) {
long lastRegularFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
long lastReprocessFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
+ long lastZslStillFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
long frameNumber = requestInfo.getLastFrameNumber();
if (requestInfo.getLastFrameNumber() < requestList.size() - 1) {
@@ -1499,19 +1520,24 @@ public class CameraDeviceImpl extends CameraDevice
" requests in the list: " + requestList.size());
}
- // find the last regular frame number and the last reprocess frame number
+ // find the last regular, zslStill, and reprocess frame number
for (int i = requestList.size() - 1; i >= 0; i--) {
CaptureRequest request = requestList.get(i);
- if (request.isReprocess() && lastReprocessFrameNumber ==
- CaptureCallback.NO_FRAMES_CAPTURED) {
+ int requestType = request.getRequestType();
+ if (requestType == CaptureRequest.REQUEST_TYPE_REPROCESS
+ && lastReprocessFrameNumber == CaptureCallback.NO_FRAMES_CAPTURED) {
lastReprocessFrameNumber = frameNumber;
- } else if (!request.isReprocess() && lastRegularFrameNumber ==
- CaptureCallback.NO_FRAMES_CAPTURED) {
+ } else if (requestType == CaptureRequest.REQUEST_TYPE_ZSL_STILL
+ && lastZslStillFrameNumber == CaptureCallback.NO_FRAMES_CAPTURED) {
+ lastZslStillFrameNumber = frameNumber;
+ } else if (requestType == CaptureRequest.REQUEST_TYPE_REGULAR
+ && lastRegularFrameNumber == CaptureCallback.NO_FRAMES_CAPTURED) {
lastRegularFrameNumber = frameNumber;
}
- if (lastReprocessFrameNumber != CaptureCallback.NO_FRAMES_CAPTURED &&
- lastRegularFrameNumber != CaptureCallback.NO_FRAMES_CAPTURED) {
+ if (lastReprocessFrameNumber != CaptureCallback.NO_FRAMES_CAPTURED
+ && lastZslStillFrameNumber != CaptureCallback.NO_FRAMES_CAPTURED
+ && lastRegularFrameNumber != CaptureCallback.NO_FRAMES_CAPTURED) {
break;
}
@@ -1520,15 +1546,51 @@ public class CameraDeviceImpl extends CameraDevice
mLastRegularFrameNumber = lastRegularFrameNumber;
mLastReprocessFrameNumber = lastReprocessFrameNumber;
+ mLastZslStillFrameNumber = lastZslStillFrameNumber;
mRequestId = requestInfo.getRequestId();
}
/**
- * Create a request-last-frame-numbers holder with a request ID and last regular frame
- * number.
+ * Create a request-last-frame-numbers holder with a request ID and last regular/ZslStill
+ * frame number.
*/
- public RequestLastFrameNumbersHolder(int requestId, long lastRegularFrameNumber) {
+ RequestLastFrameNumbersHolder(int requestId, long lastFrameNumber,
+ int[] repeatingRequestTypes) {
+ long lastRegularFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
+ long lastZslStillFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
+
+ if (repeatingRequestTypes == null) {
+ throw new IllegalArgumentException(
+ "repeatingRequest list must not be null");
+ }
+ if (lastFrameNumber < repeatingRequestTypes.length - 1) {
+ throw new IllegalArgumentException(
+ "lastFrameNumber: " + lastFrameNumber + " should be at least "
+ + (repeatingRequestTypes.length - 1)
+ + " for the number of requests in the list: "
+ + repeatingRequestTypes.length);
+ }
+
+ long frameNumber = lastFrameNumber;
+ for (int i = repeatingRequestTypes.length - 1; i >= 0; i--) {
+ if (repeatingRequestTypes[i] == CaptureRequest.REQUEST_TYPE_ZSL_STILL
+ && lastZslStillFrameNumber == CaptureCallback.NO_FRAMES_CAPTURED) {
+ lastZslStillFrameNumber = frameNumber;
+ } else if (repeatingRequestTypes[i] == CaptureRequest.REQUEST_TYPE_REGULAR
+ && lastRegularFrameNumber == CaptureCallback.NO_FRAMES_CAPTURED) {
+ lastRegularFrameNumber = frameNumber;
+ }
+
+ if (lastZslStillFrameNumber != CaptureCallback.NO_FRAMES_CAPTURED
+ && lastRegularFrameNumber != CaptureCallback.NO_FRAMES_CAPTURED) {
+ break;
+ }
+
+ frameNumber--;
+ }
+
mLastRegularFrameNumber = lastRegularFrameNumber;
+ mLastZslStillFrameNumber = lastZslStillFrameNumber;
mLastReprocessFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
mRequestId = requestId;
}
@@ -1550,10 +1612,19 @@ public class CameraDeviceImpl extends CameraDevice
}
/**
+ * Return the last ZslStill frame number. Return CaptureCallback.NO_FRAMES_CAPTURED if
+ * it contains no Zsl request.
+ */
+ public long getLastZslStillFrameNumber() {
+ return mLastZslStillFrameNumber;
+ }
+
+ /**
* Return the last frame number overall.
*/
public long getLastFrameNumber() {
- return Math.max(mLastRegularFrameNumber, mLastReprocessFrameNumber);
+ return Math.max(mLastZslStillFrameNumber,
+ Math.max(mLastRegularFrameNumber, mLastReprocessFrameNumber));
}
/**
@@ -1569,43 +1640,58 @@ public class CameraDeviceImpl extends CameraDevice
*/
public class FrameNumberTracker {
- private long mCompletedFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
- private long mCompletedReprocessFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
- /** the skipped frame numbers that belong to regular results */
- private final LinkedList<Long> mSkippedRegularFrameNumbers = new LinkedList<Long>();
- /** the skipped frame numbers that belong to reprocess results */
- private final LinkedList<Long> mSkippedReprocessFrameNumbers = new LinkedList<Long>();
- /** frame number -> is reprocess */
- private final TreeMap<Long, Boolean> mFutureErrorMap = new TreeMap<Long, Boolean>();
+ /** the completed frame number for each type of capture results */
+ private long[] mCompletedFrameNumber = new long[CaptureRequest.REQUEST_TYPE_COUNT];
+
+ /** the skipped frame numbers that don't belong to each type of capture results */
+ private final LinkedList<Long>[] mSkippedOtherFrameNumbers =
+ new LinkedList[CaptureRequest.REQUEST_TYPE_COUNT];
+
+ /** the skipped frame numbers that belong to each type of capture results */
+ private final LinkedList<Long>[] mSkippedFrameNumbers =
+ new LinkedList[CaptureRequest.REQUEST_TYPE_COUNT];
+
+ /** frame number -> request type */
+ private final TreeMap<Long, Integer> mFutureErrorMap = new TreeMap<Long, Integer>();
/** Map frame numbers to list of partial results */
private final HashMap<Long, List<CaptureResult>> mPartialResults = new HashMap<>();
+ public FrameNumberTracker() {
+ for (int i = 0; i < CaptureRequest.REQUEST_TYPE_COUNT; i++) {
+ mCompletedFrameNumber[i] = CaptureCallback.NO_FRAMES_CAPTURED;
+ mSkippedOtherFrameNumbers[i] = new LinkedList<Long>();
+ mSkippedFrameNumbers[i] = new LinkedList<Long>();
+ }
+ }
+
private void update() {
Iterator iter = mFutureErrorMap.entrySet().iterator();
while (iter.hasNext()) {
TreeMap.Entry pair = (TreeMap.Entry)iter.next();
Long errorFrameNumber = (Long)pair.getKey();
- Boolean reprocess = (Boolean)pair.getValue();
- Boolean removeError = true;
- if (reprocess) {
- if (errorFrameNumber == mCompletedReprocessFrameNumber + 1) {
- mCompletedReprocessFrameNumber = errorFrameNumber;
- } else if (mSkippedReprocessFrameNumbers.isEmpty() != true &&
- errorFrameNumber == mSkippedReprocessFrameNumbers.element()) {
- mCompletedReprocessFrameNumber = errorFrameNumber;
- mSkippedReprocessFrameNumbers.remove();
- } else {
- removeError = false;
- }
+ int requestType = (int) pair.getValue();
+ Boolean removeError = false;
+ if (errorFrameNumber == mCompletedFrameNumber[requestType] + 1) {
+ mCompletedFrameNumber[requestType] = errorFrameNumber;
+ removeError = true;
} else {
- if (errorFrameNumber == mCompletedFrameNumber + 1) {
- mCompletedFrameNumber = errorFrameNumber;
- } else if (mSkippedRegularFrameNumbers.isEmpty() != true &&
- errorFrameNumber == mSkippedRegularFrameNumbers.element()) {
- mCompletedFrameNumber = errorFrameNumber;
- mSkippedRegularFrameNumbers.remove();
+ if (!mSkippedFrameNumbers[requestType].isEmpty()) {
+ if (errorFrameNumber == mSkippedFrameNumbers[requestType].element()) {
+ mCompletedFrameNumber[requestType] = errorFrameNumber;
+ mSkippedFrameNumbers[requestType].remove();
+ removeError = true;
+ }
} else {
- removeError = false;
+ for (int i = 1; i < CaptureRequest.REQUEST_TYPE_COUNT; i++) {
+ int otherType = (requestType + i) % CaptureRequest.REQUEST_TYPE_COUNT;
+ if (!mSkippedOtherFrameNumbers[otherType].isEmpty() && errorFrameNumber
+ == mSkippedOtherFrameNumbers[otherType].element()) {
+ mCompletedFrameNumber[requestType] = errorFrameNumber;
+ mSkippedOtherFrameNumbers[otherType].remove();
+ removeError = true;
+ break;
+ }
+ }
}
}
if (removeError) {
@@ -1618,18 +1704,14 @@ public class CameraDeviceImpl extends CameraDevice
* This function is called every time when a result or an error is received.
* @param frameNumber the frame number corresponding to the result or error
* @param isError true if it is an error, false if it is not an error
- * @param isReprocess true if it is a reprocess result, false if it is a regular result.
+ * @param requestType the type of capture request: Reprocess, ZslStill, or Regular.
*/
- public void updateTracker(long frameNumber, boolean isError, boolean isReprocess) {
+ public void updateTracker(long frameNumber, boolean isError, int requestType) {
if (isError) {
- mFutureErrorMap.put(frameNumber, isReprocess);
+ mFutureErrorMap.put(frameNumber, requestType);
} else {
try {
- if (isReprocess) {
- updateCompletedReprocessFrameNumber(frameNumber);
- } else {
- updateCompletedFrameNumber(frameNumber);
- }
+ updateCompletedFrameNumber(frameNumber, requestType);
} catch (IllegalArgumentException e) {
Log.e(TAG, e.getMessage());
}
@@ -1646,13 +1728,13 @@ public class CameraDeviceImpl extends CameraDevice
* @param frameNumber the frame number corresponding to the result
* @param result the total or partial result
* @param partial {@true} if the result is partial, {@code false} if total
- * @param isReprocess true if it is a reprocess result, false if it is a regular result.
+ * @param requestType the type of capture request: Reprocess, ZslStill, or Regular.
*/
public void updateTracker(long frameNumber, CaptureResult result, boolean partial,
- boolean isReprocess) {
+ int requestType) {
if (!partial) {
// Update the total result's frame status as being successful
- updateTracker(frameNumber, /*isError*/false, isReprocess);
+ updateTracker(frameNumber, /*isError*/false, requestType);
// Don't keep a list of total results, we don't need to track them
return;
}
@@ -1688,92 +1770,105 @@ public class CameraDeviceImpl extends CameraDevice
}
public long getCompletedFrameNumber() {
- return mCompletedFrameNumber;
+ return mCompletedFrameNumber[CaptureRequest.REQUEST_TYPE_REGULAR];
}
public long getCompletedReprocessFrameNumber() {
- return mCompletedReprocessFrameNumber;
+ return mCompletedFrameNumber[CaptureRequest.REQUEST_TYPE_REPROCESS];
+ }
+
+ public long getCompletedZslStillFrameNumber() {
+ return mCompletedFrameNumber[CaptureRequest.REQUEST_TYPE_ZSL_STILL];
}
/**
- * Update the completed frame number for regular results.
+ * Update the completed frame number for results of 3 categories
+ * (Regular/Reprocess/ZslStill).
*
- * It validates that all previous frames have arrived except for reprocess frames.
+ * It validates that all previous frames of the same category have arrived.
*
- * If there is a gap since previous regular frame number, assume the frames in the gap are
- * reprocess frames and store them in the skipped reprocess frame number queue to check
- * against when reprocess frames arrive.
+ * If there is a gap since previous frame number of the same category, assume the frames in
+ * the gap are other categories and store them in the skipped frame number queue to check
+ * against when frames of those categories arrive.
*/
- private void updateCompletedFrameNumber(long frameNumber) throws IllegalArgumentException {
- if (frameNumber <= mCompletedFrameNumber) {
+ private void updateCompletedFrameNumber(long frameNumber,
+ int requestType) throws IllegalArgumentException {
+ if (frameNumber <= mCompletedFrameNumber[requestType]) {
throw new IllegalArgumentException("frame number " + frameNumber + " is a repeat");
- } else if (frameNumber <= mCompletedReprocessFrameNumber) {
- // if frame number is smaller than completed reprocess frame number,
- // it must be the head of mSkippedRegularFrameNumbers
- if (mSkippedRegularFrameNumbers.isEmpty() == true ||
- frameNumber < mSkippedRegularFrameNumbers.element()) {
- throw new IllegalArgumentException("frame number " + frameNumber +
- " is a repeat");
- } else if (frameNumber > mSkippedRegularFrameNumbers.element()) {
- throw new IllegalArgumentException("frame number " + frameNumber +
- " comes out of order. Expecting " +
- mSkippedRegularFrameNumbers.element());
- }
- // frame number matches the head of the skipped frame number queue.
- mSkippedRegularFrameNumbers.remove();
- } else {
- // there is a gap of unseen frame numbers which should belong to reprocess result
- // put all the skipped frame numbers in the queue
- for (long i = Math.max(mCompletedFrameNumber, mCompletedReprocessFrameNumber) + 1;
- i < frameNumber; i++) {
- mSkippedReprocessFrameNumbers.add(i);
- }
}
- mCompletedFrameNumber = frameNumber;
- }
+ // Assume there are only 3 different types of capture requests.
+ int otherType1 = (requestType + 1) % CaptureRequest.REQUEST_TYPE_COUNT;
+ int otherType2 = (requestType + 2) % CaptureRequest.REQUEST_TYPE_COUNT;
+ long maxOtherFrameNumberSeen =
+ Math.max(mCompletedFrameNumber[otherType1], mCompletedFrameNumber[otherType2]);
+ if (frameNumber < maxOtherFrameNumberSeen) {
+ // if frame number is smaller than completed frame numbers of other categories,
+ // it must be:
+ // - the head of mSkippedFrameNumbers for this category, or
+ // - in one of other mSkippedOtherFrameNumbers
+ if (!mSkippedFrameNumbers[requestType].isEmpty()) {
+ // frame number must be head of current type of mSkippedFrameNumbers if
+ // mSkippedFrameNumbers isn't empty.
+ if (frameNumber < mSkippedFrameNumbers[requestType].element()) {
+ throw new IllegalArgumentException("frame number " + frameNumber
+ + " is a repeat");
+ } else if (frameNumber > mSkippedFrameNumbers[requestType].element()) {
+ throw new IllegalArgumentException("frame number " + frameNumber
+ + " comes out of order. Expecting "
+ + mSkippedFrameNumbers[requestType].element());
+ }
+ // frame number matches the head of the skipped frame number queue.
+ mSkippedFrameNumbers[requestType].remove();
+ } else {
+ // frame number must be in one of the other mSkippedOtherFrameNumbers.
+ int index1 = mSkippedOtherFrameNumbers[otherType1].indexOf(frameNumber);
+ int index2 = mSkippedOtherFrameNumbers[otherType2].indexOf(frameNumber);
+ boolean inSkippedOther1 = index1 != -1;
+ boolean inSkippedOther2 = index2 != -1;
+ if (!(inSkippedOther1 ^ inSkippedOther2)) {
+ throw new IllegalArgumentException("frame number " + frameNumber
+ + " is a repeat or invalid");
+ }
- /**
- * Update the completed frame number for reprocess results.
- *
- * It validates that all previous frames have arrived except for regular frames.
- *
- * If there is a gap since previous reprocess frame number, assume the frames in the gap are
- * regular frames and store them in the skipped regular frame number queue to check
- * against when regular frames arrive.
- */
- private void updateCompletedReprocessFrameNumber(long frameNumber)
- throws IllegalArgumentException {
- if (frameNumber < mCompletedReprocessFrameNumber) {
- throw new IllegalArgumentException("frame number " + frameNumber + " is a repeat");
- } else if (frameNumber < mCompletedFrameNumber) {
- // if reprocess frame number is smaller than completed regular frame number,
- // it must be the head of the skipped reprocess frame number queue.
- if (mSkippedReprocessFrameNumbers.isEmpty() == true ||
- frameNumber < mSkippedReprocessFrameNumbers.element()) {
- throw new IllegalArgumentException("frame number " + frameNumber +
- " is a repeat");
- } else if (frameNumber > mSkippedReprocessFrameNumbers.element()) {
- throw new IllegalArgumentException("frame number " + frameNumber +
- " comes out of order. Expecting " +
- mSkippedReprocessFrameNumbers.element());
+ // We know the category of frame numbers in skippedOtherFrameNumbers leading up
+ // to the current frame number. Move them into the correct skippedFrameNumbers.
+ LinkedList<Long> srcList, dstList;
+ int index;
+ if (inSkippedOther1) {
+ srcList = mSkippedOtherFrameNumbers[otherType1];
+ dstList = mSkippedFrameNumbers[otherType2];
+ index = index1;
+ } else {
+ srcList = mSkippedOtherFrameNumbers[otherType2];
+ dstList = mSkippedFrameNumbers[otherType1];
+ index = index2;
+ }
+ for (int i = 0; i < index; i++) {
+ dstList.add(srcList.removeFirst());
+ }
+
+ // Remove current frame number from skippedOtherFrameNumbers
+ srcList.remove();
}
- // frame number matches the head of the skipped frame number queue.
- mSkippedReprocessFrameNumbers.remove();
} else {
- // put all the skipped frame numbers in the queue
- for (long i = Math.max(mCompletedFrameNumber, mCompletedReprocessFrameNumber) + 1;
+ // there is a gap of unseen frame numbers which should belong to the other
+ // 2 categories. Put all the skipped frame numbers in the queue.
+ for (long i =
+ Math.max(maxOtherFrameNumberSeen, mCompletedFrameNumber[requestType]) + 1;
i < frameNumber; i++) {
- mSkippedRegularFrameNumbers.add(i);
+ mSkippedOtherFrameNumbers[requestType].add(i);
}
}
- mCompletedReprocessFrameNumber = frameNumber;
+
+ mCompletedFrameNumber[requestType] = frameNumber;
}
}
private void checkAndFireSequenceComplete() {
long completedFrameNumber = mFrameNumberTracker.getCompletedFrameNumber();
long completedReprocessFrameNumber = mFrameNumberTracker.getCompletedReprocessFrameNumber();
+ long completedZslStillFrameNumber = mFrameNumberTracker.getCompletedZslStillFrameNumber();
boolean isReprocess = false;
Iterator<RequestLastFrameNumbersHolder> iter = mRequestLastFrameNumbersList.iterator();
while (iter.hasNext()) {
@@ -1795,18 +1890,22 @@ public class CameraDeviceImpl extends CameraDevice
requestLastFrameNumbers.getLastRegularFrameNumber();
long lastReprocessFrameNumber =
requestLastFrameNumbers.getLastReprocessFrameNumber();
-
+ long lastZslStillFrameNumber =
+ requestLastFrameNumbers.getLastZslStillFrameNumber();
// check if it's okay to remove request from mCaptureCallbackMap
- if (lastRegularFrameNumber <= completedFrameNumber &&
- lastReprocessFrameNumber <= completedReprocessFrameNumber) {
+ if (lastRegularFrameNumber <= completedFrameNumber
+ && lastReprocessFrameNumber <= completedReprocessFrameNumber
+ && lastZslStillFrameNumber <= completedZslStillFrameNumber) {
sequenceCompleted = true;
mCaptureCallbackMap.removeAt(index);
if (DEBUG) {
Log.v(TAG, String.format(
- "Remove holder for requestId %d, because lastRegularFrame %d " +
- "is <= %d and lastReprocessFrame %d is <= %d", requestId,
+ "Remove holder for requestId %d, because lastRegularFrame %d "
+ + "is <= %d, lastReprocessFrame %d is <= %d, "
+ + "lastZslStillFrame %d is <= %d", requestId,
lastRegularFrameNumber, completedFrameNumber,
- lastReprocessFrameNumber, completedReprocessFrameNumber));
+ lastReprocessFrameNumber, completedReprocessFrameNumber,
+ lastZslStillFrameNumber, completedZslStillFrameNumber));
}
}
}
@@ -1925,10 +2024,12 @@ public class CameraDeviceImpl extends CameraDevice
return; // Camera already closed
}
- checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber);
+ checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber,
+ mRepeatingRequestTypes);
// Check if there is already a new repeating request
if (mRepeatingRequestId == repeatingRequestId) {
mRepeatingRequestId = REQUEST_ID_NONE;
+ mRepeatingRequestTypes = null;
}
}
}
@@ -2040,7 +2141,7 @@ public class CameraDeviceImpl extends CameraDevice
boolean isPartialResult =
(resultExtras.getPartialResultCount() < mTotalPartialCount);
- boolean isReprocess = request.isReprocess();
+ int requestType = request.getRequestType();
// Check if we have a callback for this
if (holder == null) {
@@ -2051,7 +2152,7 @@ public class CameraDeviceImpl extends CameraDevice
}
mFrameNumberTracker.updateTracker(frameNumber, /*result*/null, isPartialResult,
- isReprocess);
+ requestType);
return;
}
@@ -2064,7 +2165,7 @@ public class CameraDeviceImpl extends CameraDevice
}
mFrameNumberTracker.updateTracker(frameNumber, /*result*/null, isPartialResult,
- isReprocess);
+ requestType);
return;
}
@@ -2172,7 +2273,7 @@ public class CameraDeviceImpl extends CameraDevice
// Collect the partials for a total result; or mark the frame as totally completed
mFrameNumberTracker.updateTracker(frameNumber, finalResult, isPartialResult,
- isReprocess);
+ requestType);
// Fire onCaptureSequenceCompleted
if (!isPartialResult) {
@@ -2307,7 +2408,8 @@ public class CameraDeviceImpl extends CameraDevice
if (DEBUG) {
Log.v(TAG, String.format("got error frame %d", frameNumber));
}
- mFrameNumberTracker.updateTracker(frameNumber, /*error*/true, request.isReprocess());
+ mFrameNumberTracker.updateTracker(frameNumber,
+ /*error*/true, request.getRequestType());
checkAndFireSequenceComplete();
// Dispatch the failure callback