Merge "camera2: allow mixing regular/reprocess requests" into mnc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
0dfb7ba4a8
@@ -212,8 +212,7 @@ public abstract class CameraCaptureSession implements AutoCloseable {
|
||||
* <p>All capture sessions can be used for capturing images from the camera but only capture
|
||||
* sessions created by
|
||||
* {@link CameraDevice#createReprocessibleCaptureSession createReprocessibleCaptureSession}
|
||||
* can submit reprocess capture requests. The list of requests must all be capturing images from
|
||||
* the camera or all be reprocess capture requests. Submitting a reprocess request to a regular
|
||||
* can submit reprocess capture requests. Submitting a reprocess request to a regular
|
||||
* capture session will result in an {@link IllegalArgumentException}.</p>
|
||||
*
|
||||
* @param requests the list of settings for this burst capture
|
||||
@@ -236,9 +235,7 @@ public abstract class CameraCaptureSession implements AutoCloseable {
|
||||
* @throws IllegalArgumentException If the requests target no Surfaces, or the requests target
|
||||
* Surfaces not currently configured as outputs; or a reprocess
|
||||
* capture request is submitted in a non-reprocessible capture
|
||||
* session; or the list of requests contains both requests to
|
||||
* capture images from the camera and reprocess capture
|
||||
* requests; or one of the reprocess capture requests was
|
||||
* session; or one of the reprocess capture requests was
|
||||
* created with a {@link TotalCaptureResult} from a different
|
||||
* session; or one of the captures targets a Surface in the
|
||||
* middle of being {@link #prepare prepared}; or if the handler
|
||||
|
||||
@@ -177,26 +177,20 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {
|
||||
public synchronized int captureBurst(List<CaptureRequest> requests, CaptureCallback callback,
|
||||
Handler handler) throws CameraAccessException {
|
||||
if (requests == null) {
|
||||
throw new IllegalArgumentException("requests must not be null");
|
||||
throw new IllegalArgumentException("Requests must not be null");
|
||||
} else if (requests.isEmpty()) {
|
||||
throw new IllegalArgumentException("requests must have at least one element");
|
||||
throw new IllegalArgumentException("Requests must have at least one element");
|
||||
}
|
||||
|
||||
boolean reprocess = requests.get(0).isReprocess();
|
||||
if (reprocess && !isReprocessible()) {
|
||||
throw new IllegalArgumentException("this capture session cannot handle reprocess " +
|
||||
"requests");
|
||||
} else if (reprocess && requests.get(0).getReprocessibleSessionId() != mId) {
|
||||
throw new IllegalArgumentException("capture request was created for another session");
|
||||
}
|
||||
|
||||
for (int i = 1; i < requests.size(); i++) {
|
||||
if (requests.get(i).isReprocess() != reprocess) {
|
||||
throw new IllegalArgumentException("cannot mix regular and reprocess capture " +
|
||||
" requests");
|
||||
} else if (reprocess && requests.get(i).getReprocessibleSessionId() != mId) {
|
||||
throw new IllegalArgumentException("capture request was created for another " +
|
||||
"session");
|
||||
for (CaptureRequest request : requests) {
|
||||
if (request.isReprocess()) {
|
||||
if (!isReprocessible()) {
|
||||
throw new IllegalArgumentException("This capture session cannot handle " +
|
||||
"reprocess requests");
|
||||
} else if (request.getReprocessibleSessionId() != mId) {
|
||||
throw new IllegalArgumentException("Capture request was created for another " +
|
||||
"session");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -94,11 +94,11 @@ public class CameraDeviceImpl extends CameraDevice {
|
||||
private final int mTotalPartialCount;
|
||||
|
||||
/**
|
||||
* A list tracking request and its expected last frame.
|
||||
* Updated when calling ICameraDeviceUser methods.
|
||||
* A list tracking request and its expected last regular frame number and last reprocess frame
|
||||
* number. Updated when calling ICameraDeviceUser methods.
|
||||
*/
|
||||
private final List<SimpleEntry</*frameNumber*/Long, /*requestId*/Integer>>
|
||||
mFrameNumberRequestPairs = new ArrayList<SimpleEntry<Long, Integer>>();
|
||||
private final List<RequestLastFrameNumbersHolder> mRequestLastFrameNumbersList =
|
||||
new ArrayList<>();
|
||||
|
||||
/**
|
||||
* An object tracking received frame numbers.
|
||||
@@ -653,8 +653,8 @@ public class CameraDeviceImpl extends CameraDevice {
|
||||
*
|
||||
* <p>If lastFrameNumber is NO_FRAMES_CAPTURED, it means that the request was never
|
||||
* sent to HAL. Then onCaptureSequenceAborted is immediately triggered.
|
||||
* If lastFrameNumber is non-negative, then the requestId and lastFrameNumber pair
|
||||
* is added to the list mFrameNumberRequestPairs.</p>
|
||||
* If lastFrameNumber is non-negative, then the requestId and lastFrameNumber as the last
|
||||
* regular frame number will be added to the list mRequestLastFrameNumbersList.</p>
|
||||
*
|
||||
* @param requestId the request ID of the current repeating request.
|
||||
*
|
||||
@@ -693,10 +693,6 @@ public class CameraDeviceImpl extends CameraDevice {
|
||||
"early trigger sequence complete for request %d",
|
||||
requestId));
|
||||
}
|
||||
if (lastFrameNumber < Integer.MIN_VALUE
|
||||
|| lastFrameNumber > Integer.MAX_VALUE) {
|
||||
throw new AssertionError(lastFrameNumber + " cannot be cast to int");
|
||||
}
|
||||
holder.getCallback().onCaptureSequenceAborted(
|
||||
CameraDeviceImpl.this,
|
||||
requestId);
|
||||
@@ -710,9 +706,11 @@ public class CameraDeviceImpl extends CameraDevice {
|
||||
requestId));
|
||||
}
|
||||
} else {
|
||||
mFrameNumberRequestPairs.add(
|
||||
new SimpleEntry<Long, Integer>(lastFrameNumber,
|
||||
requestId));
|
||||
// This function is only called for regular request so lastFrameNumber is the last
|
||||
// regular frame number.
|
||||
mRequestLastFrameNumbersList.add(new RequestLastFrameNumbersHolder(requestId,
|
||||
lastFrameNumber));
|
||||
|
||||
// It is possible that the last frame has already arrived, so we need to check
|
||||
// for sequence completion right away
|
||||
checkAndFireSequenceComplete();
|
||||
@@ -779,8 +777,8 @@ public class CameraDeviceImpl extends CameraDevice {
|
||||
}
|
||||
mRepeatingRequestId = requestId;
|
||||
} else {
|
||||
mFrameNumberRequestPairs.add(
|
||||
new SimpleEntry<Long, Integer>(lastFrameNumber, requestId));
|
||||
mRequestLastFrameNumbersList.add(new RequestLastFrameNumbersHolder(requestList,
|
||||
requestId, lastFrameNumber));
|
||||
}
|
||||
|
||||
if (mIdle) {
|
||||
@@ -1146,7 +1144,101 @@ public class CameraDeviceImpl extends CameraDevice {
|
||||
public int getSessionId() {
|
||||
return mSessionId;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class holds a capture ID and its expected last regular frame number and last reprocess
|
||||
* frame number.
|
||||
*/
|
||||
static class RequestLastFrameNumbersHolder {
|
||||
// request ID
|
||||
private final int mRequestId;
|
||||
// The last regular frame number for this request ID. It's
|
||||
// CaptureCallback.NO_FRAMES_CAPTURED if the request ID has no regular request.
|
||||
private final long mLastRegularFrameNumber;
|
||||
// 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;
|
||||
|
||||
/**
|
||||
* Create a request-last-frame-numbers holder with a list of requests, request ID, and
|
||||
* the last frame number returned by camera service.
|
||||
*/
|
||||
public RequestLastFrameNumbersHolder(List<CaptureRequest> requestList, int requestId,
|
||||
long lastFrameNumber) {
|
||||
long lastRegularFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
|
||||
long lastReprocessFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
|
||||
long frameNumber = lastFrameNumber;
|
||||
|
||||
if (lastFrameNumber < requestList.size() - 1) {
|
||||
throw new IllegalArgumentException("lastFrameNumber: " + lastFrameNumber +
|
||||
" should be at least " + (requestList.size() - 1) + " for the number of " +
|
||||
" requests in the list: " + requestList.size());
|
||||
}
|
||||
|
||||
// find the last regular frame number and the last 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) {
|
||||
lastReprocessFrameNumber = frameNumber;
|
||||
} else if (!request.isReprocess() && lastRegularFrameNumber ==
|
||||
CaptureCallback.NO_FRAMES_CAPTURED) {
|
||||
lastRegularFrameNumber = frameNumber;
|
||||
}
|
||||
|
||||
if (lastReprocessFrameNumber != CaptureCallback.NO_FRAMES_CAPTURED &&
|
||||
lastRegularFrameNumber != CaptureCallback.NO_FRAMES_CAPTURED) {
|
||||
break;
|
||||
}
|
||||
|
||||
frameNumber--;
|
||||
}
|
||||
|
||||
mLastRegularFrameNumber = lastRegularFrameNumber;
|
||||
mLastReprocessFrameNumber = lastReprocessFrameNumber;
|
||||
mRequestId = requestId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a request-last-frame-numbers holder with a request ID and last regular frame
|
||||
* number.
|
||||
*/
|
||||
public RequestLastFrameNumbersHolder(int requestId, long lastRegularFrameNumber) {
|
||||
mLastRegularFrameNumber = lastRegularFrameNumber;
|
||||
mLastReprocessFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
|
||||
mRequestId = requestId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the last regular frame number. Return CaptureCallback.NO_FRAMES_CAPTURED if
|
||||
* it contains no regular request.
|
||||
*/
|
||||
public long getLastRegularFrameNumber() {
|
||||
return mLastRegularFrameNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the last reprocess frame number. Return CaptureCallback.NO_FRAMES_CAPTURED if
|
||||
* it contains no reprocess request.
|
||||
*/
|
||||
public long getLastReprocessFrameNumber() {
|
||||
return mLastReprocessFrameNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the last frame number overall.
|
||||
*/
|
||||
public long getLastFrameNumber() {
|
||||
return Math.max(mLastRegularFrameNumber, mLastReprocessFrameNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the request ID.
|
||||
*/
|
||||
public int getRequestId() {
|
||||
return mRequestId;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1154,8 +1246,8 @@ public class CameraDeviceImpl extends CameraDevice {
|
||||
*/
|
||||
public class FrameNumberTracker {
|
||||
|
||||
private long mCompletedFrameNumber = -1;
|
||||
private long mCompletedReprocessFrameNumber = -1;
|
||||
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 */
|
||||
@@ -1360,11 +1452,11 @@ public class CameraDeviceImpl extends CameraDevice {
|
||||
long completedFrameNumber = mFrameNumberTracker.getCompletedFrameNumber();
|
||||
long completedReprocessFrameNumber = mFrameNumberTracker.getCompletedReprocessFrameNumber();
|
||||
boolean isReprocess = false;
|
||||
Iterator<SimpleEntry<Long, Integer> > iter = mFrameNumberRequestPairs.iterator();
|
||||
Iterator<RequestLastFrameNumbersHolder> iter = mRequestLastFrameNumbersList.iterator();
|
||||
while (iter.hasNext()) {
|
||||
final SimpleEntry<Long, Integer> frameNumberRequestPair = iter.next();
|
||||
final RequestLastFrameNumbersHolder requestLastFrameNumbers = iter.next();
|
||||
boolean sequenceCompleted = false;
|
||||
final int requestId = frameNumberRequestPair.getValue();
|
||||
final int requestId = requestLastFrameNumbers.getRequestId();
|
||||
final CaptureCallbackHolder holder;
|
||||
synchronized(mInterfaceLock) {
|
||||
if (mRemoteDevice == null) {
|
||||
@@ -1376,19 +1468,22 @@ public class CameraDeviceImpl extends CameraDevice {
|
||||
holder = (index >= 0) ?
|
||||
mCaptureCallbackMap.valueAt(index) : null;
|
||||
if (holder != null) {
|
||||
isReprocess = holder.getRequest().isReprocess();
|
||||
long lastRegularFrameNumber =
|
||||
requestLastFrameNumbers.getLastRegularFrameNumber();
|
||||
long lastReprocessFrameNumber =
|
||||
requestLastFrameNumbers.getLastReprocessFrameNumber();
|
||||
|
||||
// check if it's okay to remove request from mCaptureCallbackMap
|
||||
if ((isReprocess && frameNumberRequestPair.getKey() <=
|
||||
completedReprocessFrameNumber) || (!isReprocess &&
|
||||
frameNumberRequestPair.getKey() <= completedFrameNumber)) {
|
||||
if (lastRegularFrameNumber <= completedFrameNumber &&
|
||||
lastReprocessFrameNumber <= completedReprocessFrameNumber) {
|
||||
sequenceCompleted = true;
|
||||
mCaptureCallbackMap.removeAt(index);
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, String.format(
|
||||
"remove holder for requestId %d, "
|
||||
+ "because lastFrame %d is <= %d",
|
||||
requestId, frameNumberRequestPair.getKey(),
|
||||
completedFrameNumber));
|
||||
"Remove holder for requestId %d, because lastRegularFrame %d " +
|
||||
"is <= %d and lastReprocessFrame %d is <= %d", requestId,
|
||||
lastRegularFrameNumber, completedFrameNumber,
|
||||
lastReprocessFrameNumber, completedReprocessFrameNumber));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1412,16 +1507,10 @@ public class CameraDeviceImpl extends CameraDevice {
|
||||
requestId));
|
||||
}
|
||||
|
||||
long lastFrameNumber = frameNumberRequestPair.getKey();
|
||||
if (lastFrameNumber < Integer.MIN_VALUE
|
||||
|| lastFrameNumber > Integer.MAX_VALUE) {
|
||||
throw new AssertionError(lastFrameNumber
|
||||
+ " cannot be cast to int");
|
||||
}
|
||||
holder.getCallback().onCaptureSequenceCompleted(
|
||||
CameraDeviceImpl.this,
|
||||
requestId,
|
||||
lastFrameNumber);
|
||||
requestLastFrameNumbers.getLastFrameNumber());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user