am 0dfb7ba4: Merge "camera2: allow mixing regular/reprocess requests" into mnc-dev

* commit '0dfb7ba4a81e3af2e93732942d314a55c02f6ac1':
  camera2: allow mixing regular/reprocess requests
This commit is contained in:
Chien-Yu Chen
2015-05-07 20:31:40 +00:00
committed by Android Git Automerger
3 changed files with 137 additions and 57 deletions

View File

@@ -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

View File

@@ -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");
}
}
}

View File

@@ -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());
}
}
};