summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/hardware/camera2/impl/CameraDeviceImpl.java133
1 files changed, 116 insertions, 17 deletions
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 8bc65af65ef1..e3b97e82f6c8 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -100,6 +100,8 @@ public class CameraDeviceImpl extends CameraDevice
private final CameraCharacteristics mCharacteristics;
private final int mTotalPartialCount;
+ private static final long NANO_PER_SECOND = 1000000000; //ns
+
/**
* A list tracking request and its expected last regular frame number and last reprocess frame
* number. Updated when calling ICameraDeviceUser methods.
@@ -1239,6 +1241,14 @@ public class CameraDeviceImpl extends CameraDevice
private final List<CaptureRequest> mRequestList;
private final Handler mHandler;
private final int mSessionId;
+ /**
+ * <p>Determine if the callback holder is for a constrained high speed request list that
+ * expects batched capture results. Capture results will be batched if the request list
+ * is interleaved with preview and video requests. Capture results won't be batched if the
+ * request list only contains preview requests, or if the request doesn't belong to a
+ * constrained high speed list.
+ */
+ private final boolean mHasBatchedOutputs;
CaptureCallbackHolder(CaptureCallback callback, List<CaptureRequest> requestList,
Handler handler, boolean repeating, int sessionId) {
@@ -1251,6 +1261,25 @@ public class CameraDeviceImpl extends CameraDevice
mRequestList = new ArrayList<CaptureRequest>(requestList);
mCallback = callback;
mSessionId = sessionId;
+
+ // Check whether this callback holder is for batched outputs.
+ // The logic here should match createHighSpeedRequestList.
+ boolean hasBatchedOutputs = true;
+ for (int i = 0; i < requestList.size(); i++) {
+ CaptureRequest request = requestList.get(i);
+ if (!request.isPartOfCRequestList()) {
+ hasBatchedOutputs = false;
+ break;
+ }
+ if (i == 0) {
+ Collection<Surface> targets = request.getTargets();
+ if (targets.size() != 2) {
+ hasBatchedOutputs = false;
+ break;
+ }
+ }
+ }
+ mHasBatchedOutputs = hasBatchedOutputs;
}
public boolean isRepeating() {
@@ -1288,6 +1317,14 @@ public class CameraDeviceImpl extends CameraDevice
public int getSessionId() {
return mSessionId;
}
+
+ public int getRequestCount() {
+ return mRequestList.size();
+ }
+
+ public boolean hasBatchedOutputs() {
+ return mHasBatchedOutputs;
+ }
}
/**
@@ -1777,10 +1814,27 @@ public class CameraDeviceImpl extends CameraDevice
@Override
public void run() {
if (!CameraDeviceImpl.this.isClosed()) {
- holder.getCallback().onCaptureStarted(
- CameraDeviceImpl.this,
- holder.getRequest(resultExtras.getSubsequenceId()),
- timestamp, frameNumber);
+ final int subsequenceId = resultExtras.getSubsequenceId();
+ final CaptureRequest request = holder.getRequest(subsequenceId);
+
+ if (holder.hasBatchedOutputs()) {
+ // Send derived onCaptureStarted for requests within the batch
+ final Range<Integer> fpsRange =
+ request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE);
+ for (int i = 0; i < holder.getRequestCount(); i++) {
+ holder.getCallback().onCaptureStarted(
+ CameraDeviceImpl.this,
+ holder.getRequest(i),
+ timestamp - (subsequenceId - i) *
+ NANO_PER_SECOND/fpsRange.getUpper(),
+ frameNumber - (subsequenceId - i));
+ }
+ } else {
+ holder.getCallback().onCaptureStarted(
+ CameraDeviceImpl.this,
+ holder.getRequest(resultExtras.getSubsequenceId()),
+ timestamp, frameNumber);
+ }
}
}
});
@@ -1845,46 +1899,91 @@ public class CameraDeviceImpl extends CameraDevice
Runnable resultDispatch = null;
CaptureResult finalResult;
+ // Make a copy of the native metadata before it gets moved to a CaptureResult
+ // object.
+ final CameraMetadataNative resultCopy;
+ if (holder.hasBatchedOutputs()) {
+ resultCopy = new CameraMetadataNative(result);
+ } else {
+ resultCopy = null;
+ }
// Either send a partial result or the final capture completed result
if (isPartialResult) {
final CaptureResult resultAsCapture =
new CaptureResult(result, request, resultExtras);
-
// Partial result
resultDispatch = new Runnable() {
@Override
public void run() {
- if (!CameraDeviceImpl.this.isClosed()){
- holder.getCallback().onCaptureProgressed(
- CameraDeviceImpl.this,
- request,
- resultAsCapture);
+ if (!CameraDeviceImpl.this.isClosed()) {
+ if (holder.hasBatchedOutputs()) {
+ // Send derived onCaptureProgressed for requests within
+ // the batch.
+ for (int i = 0; i < holder.getRequestCount(); i++) {
+ CameraMetadataNative resultLocal =
+ new CameraMetadataNative(resultCopy);
+ CaptureResult resultInBatch = new CaptureResult(
+ resultLocal, holder.getRequest(i), resultExtras);
+
+ holder.getCallback().onCaptureProgressed(
+ CameraDeviceImpl.this,
+ holder.getRequest(i),
+ resultInBatch);
+ }
+ } else {
+ holder.getCallback().onCaptureProgressed(
+ CameraDeviceImpl.this,
+ request,
+ resultAsCapture);
+ }
}
}
};
-
finalResult = resultAsCapture;
} else {
List<CaptureResult> partialResults =
mFrameNumberTracker.popPartialResults(frameNumber);
+ final long sensorTimestamp =
+ result.get(CaptureResult.SENSOR_TIMESTAMP);
+ final Range<Integer> fpsRange =
+ request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE);
+ final int subsequenceId = resultExtras.getSubsequenceId();
final TotalCaptureResult resultAsCapture = new TotalCaptureResult(result,
request, resultExtras, partialResults, holder.getSessionId());
-
// Final capture result
resultDispatch = new Runnable() {
@Override
public void run() {
if (!CameraDeviceImpl.this.isClosed()){
- holder.getCallback().onCaptureCompleted(
- CameraDeviceImpl.this,
- request,
- resultAsCapture);
+ if (holder.hasBatchedOutputs()) {
+ // Send derived onCaptureCompleted for requests within
+ // the batch.
+ for (int i = 0; i < holder.getRequestCount(); i++) {
+ resultCopy.set(CaptureResult.SENSOR_TIMESTAMP,
+ sensorTimestamp - (subsequenceId - i) *
+ NANO_PER_SECOND/fpsRange.getUpper());
+ CameraMetadataNative resultLocal =
+ new CameraMetadataNative(resultCopy);
+ TotalCaptureResult resultInBatch = new TotalCaptureResult(
+ resultLocal, holder.getRequest(i), resultExtras,
+ partialResults, holder.getSessionId());
+
+ holder.getCallback().onCaptureCompleted(
+ CameraDeviceImpl.this,
+ holder.getRequest(i),
+ resultInBatch);
+ }
+ } else {
+ holder.getCallback().onCaptureCompleted(
+ CameraDeviceImpl.this,
+ request,
+ resultAsCapture);
+ }
}
}
};
-
finalResult = resultAsCapture;
}