From d0eb4c5e2cbd4b5af416e7150957d64b52edb04c Mon Sep 17 00:00:00 2001 From: yingrenw Date: Thu, 15 Dec 2016 17:42:28 +0800 Subject: SnapdragonCamera: HFR Crash on 720 120FPS with Camera 2 Description: Solve the HFR Crash on 720 120FPS with Camera 2 when recording. Nullpointer crash. CaptureRequest native data copy don't have the tag data. Confirm the tag data can be copied. Change-Id: I745a09b789864db9cdbbe5cfcc8bcbc941e01bf3 CRs-Fixed: 1099749 --- src/com/android/camera/CaptureModule.java | 4 +- src/com/android/camera/SettingsManager.java | 5 ++ src/com/android/camera/util/CameraUtil.java | 94 +++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 2 deletions(-) mode change 100755 => 100644 src/com/android/camera/CaptureModule.java diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java old mode 100755 new mode 100644 index 2b363dbfe..ae8676b50 --- a/src/com/android/camera/CaptureModule.java +++ b/src/com/android/camera/CaptureModule.java @@ -2660,8 +2660,8 @@ public class CaptureModule implements CameraModule, PhotoController, CameraConstrainedHighSpeedCaptureSession session = (CameraConstrainedHighSpeedCaptureSession) mCurrentSession; try { - List list = session - .createHighSpeedRequestList(mVideoRequestBuilder.build()); + List list = CameraUtil + .createHighSpeedRequestList(mVideoRequestBuilder.build(),cameraId); session.setRepeatingBurst(list, mCaptureCallback, mCameraHandler); } catch (CameraAccessException e) { Log.e(TAG, "Failed to start high speed video recording " diff --git a/src/com/android/camera/SettingsManager.java b/src/com/android/camera/SettingsManager.java index c1c6442dd..7d0f202e1 100644 --- a/src/com/android/camera/SettingsManager.java +++ b/src/com/android/camera/SettingsManager.java @@ -1076,6 +1076,11 @@ public class SettingsManager implements ListMenu.SettingsListener { return mCharacteristics.get(cameraId).get(CameraCharacteristics.FLASH_INFO_AVAILABLE); } + public StreamConfigurationMap getStreamConfigurationMap(int cameraId){ + return mCharacteristics.get(cameraId) + .get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); + } + public List getSupportedColorEffects(int cameraId) { int[] flashModes = mCharacteristics.get(cameraId).get(CameraCharacteristics .CONTROL_AVAILABLE_EFFECTS); diff --git a/src/com/android/camera/util/CameraUtil.java b/src/com/android/camera/util/CameraUtil.java index 838f8d950..cb414bac0 100644 --- a/src/com/android/camera/util/CameraUtil.java +++ b/src/com/android/camera/util/CameraUtil.java @@ -71,9 +71,22 @@ import java.text.SimpleDateFormat; import java.util.Comparator; import java.util.Date; import java.util.List; +import java.util.ArrayList; import java.util.Locale; +import android.util.Range; import java.util.StringTokenizer; +import com.android.camera.SettingsManager; +import android.hardware.camera2.CameraAccessException; +import android.hardware.camera2.CameraCaptureSession; +import android.hardware.camera2.params.StreamConfigurationMap; +import android.hardware.camera2.CaptureRequest; +import android.hardware.camera2.impl.CameraMetadataNative; +import android.hardware.camera2.utils.SurfaceUtils; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; + /** * Collection of utility functions used in this package. */ @@ -1275,4 +1288,85 @@ public class CameraUtil { (long) rhs.getWidth() * rhs.getHeight()); } } + + public static List createHighSpeedRequestList(CaptureRequest request + ,int cameraId) throws CameraAccessException { + if (request == null) { + throw new IllegalArgumentException("Input capture request must not be null"); + } + Collection outputSurfaces = request.getTargets(); + Range fpsRange = request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE); + + StreamConfigurationMap config = + SettingsManager.getInstance().getStreamConfigurationMap(cameraId); + SurfaceUtils.checkConstrainedHighSpeedSurfaces(outputSurfaces, fpsRange, config); + + // Request list size: to limit the preview to 30fps, need use maxFps/30; to maximize + // the preview frame rate, should use maxBatch size for that high speed stream + // configuration. We choose the former for now. + int requestListSize = fpsRange.getUpper() / 30; + List requestList = new ArrayList(); + + // Prepare the Request builders: need carry over the request controls. + // First, create a request builder that will only include preview or recording target. + CameraMetadataNative requestMetadata = new CameraMetadataNative(request.getNativeCopy()); + // Note that after this step, the requestMetadata is mutated (swapped) and can not be used + // for next request builder creation. + CaptureRequest.Builder singleTargetRequestBuilder = new CaptureRequest.Builder( + requestMetadata, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE); + singleTargetRequestBuilder.setTag(cameraId); + + // Overwrite the capture intent to make sure a good value is set. + Iterator iterator = outputSurfaces.iterator(); + Surface firstSurface = iterator.next(); + Surface secondSurface = null; + if (outputSurfaces.size() == 1 && SurfaceUtils.isSurfaceForHwVideoEncoder(firstSurface)) { + singleTargetRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, + CaptureRequest.CONTROL_CAPTURE_INTENT_PREVIEW); + } else { + // Video only, or preview + video + singleTargetRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, + CaptureRequest.CONTROL_CAPTURE_INTENT_VIDEO_RECORD); + } + singleTargetRequestBuilder.setPartOfCHSRequestList(/*partOfCHSList*/true); + + // Second, Create a request builder that will include both preview and recording targets. + CaptureRequest.Builder doubleTargetRequestBuilder = null; + if (outputSurfaces.size() == 2) { + // Have to create a new copy, the original one was mutated after a new + // CaptureRequest.Builder creation. + requestMetadata = new CameraMetadataNative(request.getNativeCopy()); + doubleTargetRequestBuilder = new CaptureRequest.Builder( + requestMetadata, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE); + doubleTargetRequestBuilder.setTag(cameraId); + doubleTargetRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, + CaptureRequest.CONTROL_CAPTURE_INTENT_VIDEO_RECORD); + doubleTargetRequestBuilder.addTarget(firstSurface); + secondSurface = iterator.next(); + doubleTargetRequestBuilder.addTarget(secondSurface); + doubleTargetRequestBuilder.setPartOfCHSRequestList(/*partOfCHSList*/true); + // Make sure singleTargetRequestBuilder contains only recording surface for + // preview + recording case. + Surface recordingSurface = firstSurface; + if (!SurfaceUtils.isSurfaceForHwVideoEncoder(recordingSurface)) { + recordingSurface = secondSurface; + } + singleTargetRequestBuilder.addTarget(recordingSurface); + } else { + // Single output case: either recording or preview. + singleTargetRequestBuilder.addTarget(firstSurface); + } + + // Generate the final request list. + for (int i = 0; i < requestListSize; i++) { + if (i == 0 && doubleTargetRequestBuilder != null) { + // First request should be recording + preview request + requestList.add(doubleTargetRequestBuilder.build()); + } else { + requestList.add(singleTargetRequestBuilder.build()); + } + } + + return Collections.unmodifiableList(requestList); + } } -- cgit v1.2.3