diff options
| author | Shuzhen Wang <shuzhenwang@google.com> | 2017-03-01 12:58:04 -0800 |
|---|---|---|
| committer | Shuzhen Wang <shuzhenwang@google.com> | 2017-03-14 12:32:56 -0700 |
| commit | ae10eb9f7d60ab530ad586e7c11c896ed6f3ee2d (patch) | |
| tree | e6551f0606039f0486cf5e864f239159043258ec /core/java | |
| parent | 7986b529f7c8acaf3a7822cc04daf8da761cd04e (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.java | 133 |
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; } |
