diff options
3 files changed, 137 insertions, 57 deletions
diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java index aeddf032a176..ef71c42a9ba5 100644 --- a/core/java/android/hardware/camera2/CameraCaptureSession.java +++ b/core/java/android/hardware/camera2/CameraCaptureSession.java @@ -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 diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java index 3c195298b759..dff62270b05a 100644 --- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java @@ -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"); - } - - 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"); + throw new IllegalArgumentException("Requests must have at least one element"); } - 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"); + } } } diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index ff4ad79f120f..e84b46abf13a 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -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()); } } }; |