diff options
-rwxr-xr-x | src/com/android/camera/CaptureModule.java | 94 | ||||
-rwxr-xr-x | src/com/android/camera/SettingsManager.java | 5 | ||||
-rwxr-xr-x | src/com/android/camera/util/CameraUtil.java | 147 |
3 files changed, 185 insertions, 61 deletions
diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java index de2735090..d2efbdab5 100755 --- a/src/com/android/camera/CaptureModule.java +++ b/src/com/android/camera/CaptureModule.java @@ -1412,8 +1412,7 @@ public class CaptureModule implements CameraModule, PhotoController, if (mCaptureSession[id] instanceof CameraConstrainedHighSpeedCaptureSession) { CameraConstrainedHighSpeedCaptureSession session = (CameraConstrainedHighSpeedCaptureSession) mCaptureSession[id]; - List requestList = session.createHighSpeedRequestList( - mPreviewRequestBuilder[id].build()); + List requestList = CameraUtil.createHighSpeedRequestList(mVideoRequestBuilder.build()); session.setRepeatingBurst(requestList, mCaptureCallback, mCameraHandler); } else { mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id] @@ -3743,7 +3742,7 @@ public class CaptureModule implements CameraModule, PhotoController, CameraConstrainedHighSpeedCaptureSession session = (CameraConstrainedHighSpeedCaptureSession) mCurrentSession; try { - List list = session + List list = CameraUtil .createHighSpeedRequestList(mVideoRequestBuilder.build()); session.setRepeatingBurst(list, mCaptureCallback, mCameraHandler); } catch (CameraAccessException e) { @@ -3896,7 +3895,7 @@ public class CaptureModule implements CameraModule, PhotoController, mVideoPausePreviewRequestBuilder.addTarget(surface); mVideoPausePreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, mControlAFMode); if (mHighSpeedCapture) { - mVideoRequestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, + mVideoPausePreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, mHighSpeedFPSRange); } if (!mHighSpeedCapture || !((int)mHighSpeedFPSRange.getUpper() > NORMAL_SESSION_MAX_FPS)) { @@ -4100,17 +4099,14 @@ public class CaptureModule implements CameraModule, PhotoController, } private void setEndOfStream(boolean isResume, boolean isStopRecord) { + CaptureRequest.Builder captureRequestBuilder = null; try { if (isResume) { - mVideoRequestBuilder.set(CaptureModule.recording_end_stream, (byte) 0x00); - if (mCurrentSession instanceof CameraConstrainedHighSpeedCaptureSession) { - List requestList = ((CameraConstrainedHighSpeedCaptureSession)mCurrentSession) - .createHighSpeedRequestList(mVideoRequestBuilder.build()); - mCurrentSession.setRepeatingBurst(requestList, - mCaptureCallback, mCameraHandler); - } else { - mCurrentSession.setRepeatingRequest(mVideoRequestBuilder.build(), - mCaptureCallback, mCameraHandler); + captureRequestBuilder = mVideoRequestBuilder; + try { + captureRequestBuilder.set(CaptureModule.recording_end_stream, (byte) 0x00); + } catch(IllegalArgumentException illegalArgumentException) { + Log.w(TAG, "can not find vendor tag: org.quic.camera.recording.endOfStream"); } } else { // is pause or stopRecord @@ -4119,11 +4115,17 @@ public class CaptureModule implements CameraModule, PhotoController, CaptureRequest.Builder builder = mCameraDevice[getMainCameraId()].createCaptureRequest(CameraDevice.TEMPLATE_RECORD); builder.setTag(getMainCameraId()); + if (mHighSpeedCapture) { + builder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, mHighSpeedFPSRange); + } addPreviewSurface(builder, null, getMainCameraId()); - builder.set(CaptureModule.recording_end_stream, (byte) 0x01); + try { + builder.set(CaptureModule.recording_end_stream, (byte) 0x01); + } catch (IllegalArgumentException illegalArgumentException) { + Log.w(TAG, "can not find vendor tag: org.quic.camera.recording.endOfStream"); + } if (mCurrentSession instanceof CameraConstrainedHighSpeedCaptureSession) { - List requestList = ((CameraConstrainedHighSpeedCaptureSession)mCurrentSession). - createHighSpeedRequestList(builder.build()); + List requestList = CameraUtil.createHighSpeedRequestList(builder.build()); mCurrentSession.captureBurst(requestList, mCaptureCallback, mCameraHandler); } else { mCurrentSession.capture(builder.build(), mCaptureCallback, mCameraHandler); @@ -4132,54 +4134,24 @@ public class CaptureModule implements CameraModule, PhotoController, if (!isStopRecord) { //is pause record mMediaRecorder.pause(); - if (mVideoPausePreviewRequestBuilder != null) { - if (mCurrentSession instanceof CameraConstrainedHighSpeedCaptureSession) { - List requestList = ((CameraConstrainedHighSpeedCaptureSession)mCurrentSession) - .createHighSpeedRequestList(mVideoPausePreviewRequestBuilder.build()); - mCurrentSession.setRepeatingBurst(requestList, - mCaptureCallback, mCameraHandler); - } else { - mCurrentSession.setRepeatingRequest( - mVideoPausePreviewRequestBuilder.build(), - mCaptureCallback, mCameraHandler); - } - } else { - //if failed to set up preview builder, stop recording - stopRecordingVideo(getMainCameraId()); - } + captureRequestBuilder = mVideoPausePreviewRequestBuilder; } } - } catch (CameraAccessException | IllegalArgumentException | IllegalStateException e) { - if (e instanceof CameraAccessException) { - Log.w(TAG, "setEndOfStream, Camera access failed"); - } - if (e instanceof IllegalArgumentException) { - Log.w(TAG, "can not find vendor tag: org.quic.camera.recording.endOfStream"); - } - if (e instanceof IllegalStateException) { - Log.w(TAG, "setEndOfStream, CameraDevice was already closed"); - } - if (!isStopRecord && !isResume) { - mMediaRecorder.pause(); - try { - if (mVideoPausePreviewRequestBuilder != null) { - if (mCurrentSession instanceof CameraConstrainedHighSpeedCaptureSession) { - List requestList = ((CameraConstrainedHighSpeedCaptureSession)mCurrentSession) - .createHighSpeedRequestList(mVideoPausePreviewRequestBuilder.build()); - mCurrentSession.setRepeatingBurst(requestList, - mCaptureCallback, mCameraHandler); - } else { - mCurrentSession.setRepeatingRequest(mVideoPausePreviewRequestBuilder - .build(), mCaptureCallback, mCameraHandler); - } - } else { - //if failed to set up preview builder, stop recording - stopRecordingVideo(getMainCameraId()); - } - } catch (CameraAccessException exception) { - Log.w(TAG, "setEndOfStream, Camera access failed"); + + // set preview + if (captureRequestBuilder != null) { + if (mCurrentSession instanceof CameraConstrainedHighSpeedCaptureSession) { + List requestList = CameraUtil.createHighSpeedRequestList(captureRequestBuilder.build()); + mCurrentSession.setRepeatingBurst(requestList, + mCaptureCallback, mCameraHandler); + } else { + mCurrentSession.setRepeatingRequest(captureRequestBuilder.build(), + mCaptureCallback, mCameraHandler); } } + } catch (CameraAccessException e) { + stopRecordingVideo(getMainCameraId()); + e.printStackTrace(); } } @@ -4912,7 +4884,7 @@ public class CaptureModule implements CameraModule, PhotoController, } else { CameraCaptureSession session = mCaptureSession[id]; if (session instanceof CameraConstrainedHighSpeedCaptureSession) { - List list = ((CameraConstrainedHighSpeedCaptureSession)session) + List list = CameraUtil .createHighSpeedRequestList(mPreviewRequestBuilder[id].build()); ((CameraConstrainedHighSpeedCaptureSession) session).setRepeatingBurst(list , mCaptureCallback, mCameraHandler); diff --git a/src/com/android/camera/SettingsManager.java b/src/com/android/camera/SettingsManager.java index ebc9a697a..6cb5ea484 100755 --- a/src/com/android/camera/SettingsManager.java +++ b/src/com/android/camera/SettingsManager.java @@ -1387,6 +1387,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<String> 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 d30885d29..6075c8c4e 100755 --- a/src/com/android/camera/util/CameraUtil.java +++ b/src/com/android/camera/util/CameraUtil.java @@ -72,8 +72,24 @@ 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 java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; + +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; +import java.util.Set; import static android.content.Context.MODE_PRIVATE; @@ -125,6 +141,9 @@ public class CameraUtil { public static final String TRUE = "true"; public static final String FALSE = "false"; + private static final Class<?>[] CTOR_SIGNATURE = + new Class[] {CaptureRequest.class, CameraMetadataNative.class, boolean.class, int.class}; + // Fields for the show-on-maps-functionality private static final String MAPS_PACKAGE_NAME = "com.google.android.apps.maps"; private static final String MAPS_CLASS_NAME = "com.google.android.maps.MapsActivity"; @@ -1363,6 +1382,134 @@ public class CameraUtil { } } + public static List<CaptureRequest> createHighSpeedRequestList(final CaptureRequest request) + throws CameraAccessException { + if (request == null) { + throw new IllegalArgumentException("Input capture request must not be null"); + } + Set<String> physicalCameraIdSet = null; + Collection<Surface> outputSurfaces = request.getTargets(); + Range<Integer> fpsRange = request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE); + + StreamConfigurationMap config = + SettingsManager.getInstance().getStreamConfigurationMap((int)request.getTag()); + 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<CaptureRequest> requestList = new ArrayList<CaptureRequest>(); + + // 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 = constructorCaptureRequestBuilder( + requestMetadata, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE, + request, physicalCameraIdSet); + singleTargetRequestBuilder.setTag(request.getTag()); + + // Overwrite the capture intent to make sure a good value is set. + Iterator<Surface> 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 = constructorCaptureRequestBuilder(requestMetadata, + /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE, + request, physicalCameraIdSet); + doubleTargetRequestBuilder.setTag(request.getTag()); + 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); + } + + private static CaptureRequest.Builder constructorCaptureRequestBuilder ( + CameraMetadataNative requestMetadata, boolean reprocess, int SESSION_ID_NONE, + CaptureRequest request, Set<String> physicalCameraIdSet) { + CaptureRequest.Builder builder = null; + try { + Class clazz = Class.forName("android.hardware.camera2.CaptureRequest$Builder"); + // for Android O, has 3 parameters + builder = (CaptureRequest.Builder) clazz.getConstructors()[0].newInstance( + requestMetadata, reprocess, SESSION_ID_NONE); + } catch (ClassNotFoundException e) { + Log.v(TAG, "constructorCaptureRequestBuilder for AndroidO ClassNotFoundException " + + e.toString()); + } catch (Exception e) { + Log.v(TAG, "constructorCaptureRequestBuilder for AndroidO Exception " + e.toString()); + } + + if (builder == null) { + // for Android P has 5 parameters + String logicalCameraId = "-1"; + try { + Method getLogicalCameraId = Class.forName("android.hardware.camera2.CaptureRequest") + .getMethod("getLogicalCameraId"); + logicalCameraId = (String) getLogicalCameraId.invoke(request); + } catch (NoSuchMethodException e) { + Log.v(TAG, "constructorCaptureRequestBuilder NoSuchMethodException"+ e.toString()); + } catch (Exception e) { + Log.v(TAG, "constructorCaptureRequestBuilder logicalCameraId Exception" + + e.toString()); + } + try { + Class clazz = Class.forName("android.hardware.camera2.CaptureRequest$Builder"); + Log.v(TAG, "logicalCameraId :" + logicalCameraId); + builder = (CaptureRequest.Builder) clazz.getConstructors()[0].newInstance( + requestMetadata, reprocess, SESSION_ID_NONE, + logicalCameraId, physicalCameraIdSet); + } catch (ClassNotFoundException e) { + Log.v(TAG, "constructorCaptureRequestBuilder ClassNotFoundException"+e.toString()); + } catch (Exception e) { + Log.v(TAG, "constructorCaptureRequestBuilder Exception"+e.toString()); + } + } + return builder; + } + public static int dip2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); |