summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
authorShuzhen Wang <shuzhenwang@google.com>2017-03-01 12:58:04 -0800
committerShuzhen Wang <shuzhenwang@google.com>2017-03-14 12:32:56 -0700
commitae10eb9f7d60ab530ad586e7c11c896ed6f3ee2d (patch)
treee6551f0606039f0486cf5e864f239159043258ec /core/java
parent7986b529f7c8acaf3a7822cc04daf8da761cd04e (diff)
Camera: Enable batching for constrained high speed recording
For each constrained high speed recording request list, only 1 shutter notify and 1 capture result are sent from cameraserver to application process as a power-saving measure. Once the shutter notify and capture result are passed into application process, derive individual shutter and result for other requests in the batch, and send them to application. Test: Manually test high speed recording with GCA and CTS. Bug: 35775704 Change-Id: Ie5fa1de6b3b87f1242d6c81770e40ae876991bc3
Diffstat (limited to 'core/java')
-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;
}