Merge "Camera: Handle out-of-order frameNumber for ZSL requests" into qt-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
34bc57f738
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1549,11 +1611,20 @@ public class CameraDeviceImpl extends CameraDevice
|
||||
return mLastReprocessFrameNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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());
|
||||
}
|
||||
|
||||
// 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");
|
||||
}
|
||||
|
||||
// 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.
|
||||
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;
|
||||
// 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++) {
|
||||
mSkippedReprocessFrameNumbers.add(i);
|
||||
mSkippedOtherFrameNumbers[requestType].add(i);
|
||||
}
|
||||
}
|
||||
|
||||
mCompletedFrameNumber = frameNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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());
|
||||
}
|
||||
// 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;
|
||||
i < frameNumber; i++) {
|
||||
mSkippedRegularFrameNumbers.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
|
||||
|
||||
Reference in New Issue
Block a user