Loading core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +116 −17 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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) { Loading @@ -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() { Loading Loading @@ -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; } } /** Loading Loading @@ -1777,12 +1814,29 @@ public class CameraDeviceImpl extends CameraDevice @Override public void run() { if (!CameraDeviceImpl.this.isClosed()) { 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); } } } }); } Loading Loading @@ -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()) { 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()){ 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; } Loading Loading
core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +116 −17 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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) { Loading @@ -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() { Loading Loading @@ -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; } } /** Loading Loading @@ -1777,12 +1814,29 @@ public class CameraDeviceImpl extends CameraDevice @Override public void run() { if (!CameraDeviceImpl.this.isClosed()) { 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); } } } }); } Loading Loading @@ -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()) { 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()){ 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; } Loading