1f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling/* 2f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * Copyright (C) 2014 The Android Open Source Project 3f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * 4f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * Licensed under the Apache License, Version 2.0 (the "License"); 5f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * you may not use this file except in compliance with the License. 6f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * You may obtain a copy of the License at 7f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * 8f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * http://www.apache.org/licenses/LICENSE-2.0 9f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * 10f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * Unless required by applicable law or agreed to in writing, software 11f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * distributed under the License is distributed on an "AS IS" BASIS, 12f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * See the License for the specific language governing permissions and 14f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * limitations under the License. 15f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling */ 16f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 17f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingpackage com.android.camera.one.v2; 18f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 19cbe861edcd0d094ee79d3eeaac48bb928017b600Sascha Haeberlingimport android.content.Context; 20f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.graphics.ImageFormat; 21f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.graphics.Rect; 22f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.hardware.camera2.CameraAccessException; 23f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.hardware.camera2.CameraCaptureSession; 24f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.hardware.camera2.CameraCharacteristics; 25f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.hardware.camera2.CameraDevice; 26f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.hardware.camera2.CameraMetadata; 27f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.hardware.camera2.CaptureRequest; 2830ffce08f511fbed4cf18daa743778b541583351Andy Huibersimport android.hardware.camera2.CaptureResult; 2930ffce08f511fbed4cf18daa743778b541583351Andy Huibersimport android.hardware.camera2.TotalCaptureResult; 3030ffce08f511fbed4cf18daa743778b541583351Andy Huibersimport android.hardware.camera2.params.MeteringRectangle; 31f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.hardware.camera2.params.StreamConfigurationMap; 32f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.media.Image; 33f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.media.ImageReader; 3457bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberlingimport android.net.Uri; 35f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.os.Handler; 36f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.os.HandlerThread; 3730ffce08f511fbed4cf18daa743778b541583351Andy Huibersimport android.os.SystemClock; 38f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport android.view.Surface; 39f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 40cbe861edcd0d094ee79d3eeaac48bb928017b600Sascha Haeberlingimport com.android.camera.CaptureModuleUtil; 4157bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberlingimport com.android.camera.Exif; 4257bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberlingimport com.android.camera.app.MediaSaver.OnMediaSavedListener; 4399a37d89f92cb0ad60cd57169c4845560ad0ffacAndy Huibersimport com.android.camera.debug.DebugPropertyHelper; 44f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport com.android.camera.debug.Log; 45f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport com.android.camera.debug.Log.Tag; 4657bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberlingimport com.android.camera.exif.ExifInterface; 4757bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberlingimport com.android.camera.exif.ExifTag; 4857bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberlingimport com.android.camera.exif.Rational; 49f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport com.android.camera.one.AbstractOneCamera; 50f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport com.android.camera.one.OneCamera; 51b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibersimport com.android.camera.one.Settings3A; 52f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport com.android.camera.session.CaptureSession; 5330ffce08f511fbed4cf18daa743778b541583351Andy Huibersimport com.android.camera.util.CameraUtil; 5451163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberlingimport com.android.camera.util.CaptureDataSerializer; 55967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lallimport com.android.camera.util.JpegUtilNative; 56967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lallimport com.android.camera.util.Size; 57f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 5851163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberlingimport java.io.File; 5957bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberlingimport java.io.IOException; 60f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport java.nio.ByteBuffer; 61f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport java.util.ArrayList; 62f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport java.util.LinkedList; 63f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingimport java.util.List; 64f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 65f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling/** 66f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * {@link OneCamera} implementation directly on top of the Camera2 API. 67f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling */ 68f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberlingpublic class OneCameraImpl extends AbstractOneCamera { 69f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 70f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** Captures that are requested but haven't completed yet. */ 71f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private static class InFlightCapture { 7257bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling final PhotoCaptureParameters parameters; 73f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling final CaptureSession session; 74f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 7557bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling public InFlightCapture(PhotoCaptureParameters parameters, 76f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling CaptureSession session) { 7757bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling this.parameters = parameters; 78f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling this.session = session; 79f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 80f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 81f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 82f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private static final Tag TAG = new Tag("OneCameraImpl2"); 8330ffce08f511fbed4cf18daa743778b541583351Andy Huibers 8499a37d89f92cb0ad60cd57169c4845560ad0ffacAndy Huibers /** If true, will write data about each capture request to disk. */ 8599a37d89f92cb0ad60cd57169c4845560ad0ffacAndy Huibers private static final boolean DEBUG_WRITE_CAPTURE_DATA = DebugPropertyHelper.writeCaptureData(); 8699a37d89f92cb0ad60cd57169c4845560ad0ffacAndy Huibers /** If true, will log per-frame AF info. */ 8762b4c3c0da3abd397b3790820359927784c50bc2Andy Huibers private static final boolean DEBUG_FOCUS_LOG = DebugPropertyHelper.showFrameDebugLog(); 8830ffce08f511fbed4cf18daa743778b541583351Andy Huibers 89f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** Default JPEG encoding quality. */ 90f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private static final Byte JPEG_QUALITY = 90; 91f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 92967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall /** 93967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall * Set to ImageFormat.JPEG, to use the hardware encoder, or 9451163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling * ImageFormat.YUV_420_888 to use the software encoder. No other image 9551163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling * formats are supported. 96967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall */ 97967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall private static final int sCaptureImageFormat = ImageFormat.YUV_420_888; 98967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall 9930ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** Duration to hold after manual focus tap. */ 100b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers private static final int FOCUS_HOLD_MILLIS = Settings3A.getFocusHoldMillis(); 10134ac0609e30601fe2ce9b2338a173d7740ab3f82Andy Huibers /** Zero weight 3A region, to reset regions per API. */ 102527706e2957fe26f301d991d86d4359ab433408dAndy Huibers MeteringRectangle[] ZERO_WEIGHT_3A_REGION = AutoFocusHelper.getZeroWeightRegion(); 10330ffce08f511fbed4cf18daa743778b541583351Andy Huibers 10430ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** 10530ffce08f511fbed4cf18daa743778b541583351Andy Huibers * CaptureRequest tags. 10630ffce08f511fbed4cf18daa743778b541583351Andy Huibers * <ul> 10730ffce08f511fbed4cf18daa743778b541583351Andy Huibers * <li>{@link #PRESHOT_TRIGGERED_AF}</li> 10830ffce08f511fbed4cf18daa743778b541583351Andy Huibers * <li>{@link #CAPTURE}</li> 10930ffce08f511fbed4cf18daa743778b541583351Andy Huibers * </ul> 11030ffce08f511fbed4cf18daa743778b541583351Andy Huibers */ 11130ffce08f511fbed4cf18daa743778b541583351Andy Huibers public static enum RequestTag { 11230ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** Request that is part of a pre shot trigger. */ 11330ffce08f511fbed4cf18daa743778b541583351Andy Huibers PRESHOT_TRIGGERED_AF, 11430ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** Capture request (purely for logging). */ 11526b3334755ffccc039249005435d5cc598d0689eAndy Huibers CAPTURE, 11626b3334755ffccc039249005435d5cc598d0689eAndy Huibers /** Tap to focus (purely for logging). */ 11726b3334755ffccc039249005435d5cc598d0689eAndy Huibers TAP_TO_FOCUS 11830ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 11930ffce08f511fbed4cf18daa743778b541583351Andy Huibers 12030ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** Current CONTROL_AF_MODE request to Camera2 API. */ 12126b3334755ffccc039249005435d5cc598d0689eAndy Huibers private int mControlAFMode = CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_PICTURE; 12230ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** Last OneCamera.AutoFocusState reported. */ 12330ffce08f511fbed4cf18daa743778b541583351Andy Huibers private AutoFocusState mLastResultAFState = AutoFocusState.INACTIVE; 12430ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** Flag to take a picture when the lens is stopped. */ 12530ffce08f511fbed4cf18daa743778b541583351Andy Huibers private boolean mTakePictureWhenLensIsStopped = false; 12630ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** Takes a (delayed) picture with appropriate parameters. */ 12730ffce08f511fbed4cf18daa743778b541583351Andy Huibers private Runnable mTakePictureRunnable; 12817d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers /** Keep PictureCallback for last requested capture. */ 12917d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers private PictureCallback mLastPictureCallback = null; 13030ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** Last time takePicture() was called in uptimeMillis. */ 13130ffce08f511fbed4cf18daa743778b541583351Andy Huibers private long mTakePictureStartMillis; 13230ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** Runnable that returns to CONTROL_AF_MODE = AF_CONTINUOUS_PICTURE. */ 13351163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling private final Runnable mReturnToContinuousAFRunnable = new Runnable() { 13430ffce08f511fbed4cf18daa743778b541583351Andy Huibers @Override 13530ffce08f511fbed4cf18daa743778b541583351Andy Huibers public void run() { 136b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers mAFRegions = ZERO_WEIGHT_3A_REGION; 137b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers mAERegions = ZERO_WEIGHT_3A_REGION; 13826b3334755ffccc039249005435d5cc598d0689eAndy Huibers mControlAFMode = CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_PICTURE; 13926b3334755ffccc039249005435d5cc598d0689eAndy Huibers repeatingPreview(null); 14030ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 14130ffce08f511fbed4cf18daa743778b541583351Andy Huibers }; 14230ffce08f511fbed4cf18daa743778b541583351Andy Huibers 14351163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling /** Current zoom value. 1.0 is no zoom. */ 14426b3334755ffccc039249005435d5cc598d0689eAndy Huibers private float mZoomValue = 1f; 14526b3334755ffccc039249005435d5cc598d0689eAndy Huibers /** Current crop region: set from mZoomValue. */ 14626b3334755ffccc039249005435d5cc598d0689eAndy Huibers private Rect mCropRegion; 147b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers /** Current AF and AE regions */ 148b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers private MeteringRectangle[] mAFRegions = ZERO_WEIGHT_3A_REGION; 149b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers private MeteringRectangle[] mAERegions = ZERO_WEIGHT_3A_REGION; 150b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers /** Last frame for which CONTROL_AF_STATE was received. */ 151b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers private long mLastControlAfStateFrameNumber = 0; 15230ffce08f511fbed4cf18daa743778b541583351Andy Huibers 15330ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** 15430ffce08f511fbed4cf18daa743778b541583351Andy Huibers * Common listener for preview frame metadata. 15530ffce08f511fbed4cf18daa743778b541583351Andy Huibers */ 15676215c98a9a11d87b5ce9d2b4198654c2b8bbddfAlan Newberger private final CameraCaptureSession.CaptureCallback mAutoFocusStateListener = new 15776215c98a9a11d87b5ce9d2b4198654c2b8bbddfAlan Newberger CameraCaptureSession.CaptureCallback() { 15817d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers @Override 15917d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, 160dd38b94c6f21b528f0de706a69d853f24a9c9561Eino-Ville Talvala long timestamp, long frameNumber) { 16117d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers if (request.getTag() == RequestTag.CAPTURE && mLastPictureCallback != null) { 16217d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers mLastPictureCallback.onQuickExpose(); 16317d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers } 16417d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers } 16517d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers 16630ffce08f511fbed4cf18daa743778b541583351Andy Huibers // AF state information is sometimes available 1 frame before 16730ffce08f511fbed4cf18daa743778b541583351Andy Huibers // onCaptureCompleted(), so we take advantage of that. 16830ffce08f511fbed4cf18daa743778b541583351Andy Huibers @Override 16951163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling public void onCaptureProgressed(CameraCaptureSession session, 17051163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling CaptureRequest request, 17151163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling CaptureResult partialResult) { 172b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers autofocusStateChangeDispatcher(partialResult); 17330ffce08f511fbed4cf18daa743778b541583351Andy Huibers super.onCaptureProgressed(session, request, partialResult); 17430ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 17551163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling 17630ffce08f511fbed4cf18daa743778b541583351Andy Huibers @Override 17751163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling public void onCaptureCompleted(CameraCaptureSession session, 17851163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling CaptureRequest request, 17951163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling TotalCaptureResult result) { 180b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers autofocusStateChangeDispatcher(result); 181b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers // This checks for a HAL implementation error where TotalCaptureResult 182b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers // is missing CONTROL_AF_STATE. This should not happen. 183b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers if (result.get(CaptureResult.CONTROL_AF_STATE) == null) { 184b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers AutoFocusHelper.checkControlAfState(result); 18530ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 18699a37d89f92cb0ad60cd57169c4845560ad0ffacAndy Huibers if (DEBUG_FOCUS_LOG) { 18703e17a62b43e58c8da5cd6ee23fd0809a82ee448Andy Huibers AutoFocusHelper.logExtraFocusInfo(result); 18899a37d89f92cb0ad60cd57169c4845560ad0ffacAndy Huibers } 18930ffce08f511fbed4cf18daa743778b541583351Andy Huibers super.onCaptureCompleted(session, request, result); 19030ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 19130ffce08f511fbed4cf18daa743778b541583351Andy Huibers }; 192f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** Thread on which the camera operations are running. */ 193f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private final HandlerThread mCameraThread; 194f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** Handler of the {@link #mCameraThread}. */ 195f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private final Handler mCameraHandler; 196f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** The characteristics of this camera. */ 197f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private final CameraCharacteristics mCharacteristics; 198f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** The underlying Camera2 API camera device. */ 199f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private final CameraDevice mDevice; 20057bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling 201f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** 202f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * The aspect ratio (width/height) of the full resolution for this camera. 203f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * Usually the native aspect ratio of this camera. 204f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling */ 2059cefdd495332719d987ffb942742ec602793d8d4Jiawen Chen private final float mFullSizeAspectRatio; 206f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** The Camera2 API capture session currently active. */ 207f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private CameraCaptureSession mCaptureSession; 208f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** The surface onto which to render the preview. */ 209f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private Surface mPreviewSurface; 210f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** 211f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * A queue of capture requests that have been requested but are not done 212f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * yet. 213f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling */ 21457bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling private final LinkedList<InFlightCapture> mCaptureQueue = 21557bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling new LinkedList<InFlightCapture>(); 216f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** Whether closing of this device has been requested. */ 217f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private volatile boolean mIsClosed = false; 218f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** A callback that is called when the device is fully closed. */ 219f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private CloseCallback mCloseCallback = null; 220f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 221967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall /** Receives the normal captured images. */ 222967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall private final ImageReader mCaptureImageReader; 223967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall ImageReader.OnImageAvailableListener mCaptureImageListener = 224f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling new ImageReader.OnImageAvailableListener() { 225f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 226f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling public void onImageAvailable(ImageReader reader) { 22757bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling InFlightCapture capture = mCaptureQueue.remove(); 22857bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling 22951163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling // Since this is not an HDR+ session, we will just save the 23051163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling // result. 23157bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling capture.session.startEmpty(); 232f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling byte[] imageBytes = acquireJpegBytesAndClose(reader); 23330ffce08f511fbed4cf18daa743778b541583351Andy Huibers // TODO: The savePicture call here seems to block UI thread. 23457bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling savePicture(imageBytes, capture.parameters, capture.session); 235e3ad4352a23ddb21350d356e0947905d1e635911Sascha Haeberling broadcastReadyState(true); 23657bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling capture.parameters.callback.onPictureTaken(capture.session); 237f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 238f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling }; 239f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 240f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** 241f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * Instantiates a new camera based on Camera 2 API. 242f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * 243f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * @param device The underlying Camera 2 device. 244f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * @param characteristics The device's characteristics. 24557bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling * @param pictureSize the size of the final image to be taken. 246f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling */ 247f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling OneCameraImpl(CameraDevice device, CameraCharacteristics characteristics, Size pictureSize) { 248f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mDevice = device; 249f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mCharacteristics = characteristics; 250f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mFullSizeAspectRatio = calculateFullSizeAspectRatio(characteristics); 251f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 252f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mCameraThread = new HandlerThread("OneCamera2"); 253f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mCameraThread.start(); 254f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mCameraHandler = new Handler(mCameraThread.getLooper()); 255f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 25651163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling mCaptureImageReader = ImageReader.newInstance(pictureSize.getWidth(), 25751163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling pictureSize.getHeight(), 258967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall sCaptureImageFormat, 2); 259967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall mCaptureImageReader.setOnImageAvailableListener(mCaptureImageListener, mCameraHandler); 260f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling Log.d(TAG, "New Camera2 based OneCameraImpl created."); 261f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 262f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 26330ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** 26430ffce08f511fbed4cf18daa743778b541583351Andy Huibers * Take picture, initiating an auto focus scan if needed. 26530ffce08f511fbed4cf18daa743778b541583351Andy Huibers */ 266f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 26730ffce08f511fbed4cf18daa743778b541583351Andy Huibers public void takePicture(final PhotoCaptureParameters params, final CaptureSession session) { 268b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers // Do not do anything when a picture is already requested. 269b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers if (mTakePictureWhenLensIsStopped) { 27030ffce08f511fbed4cf18daa743778b541583351Andy Huibers return; 27130ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 27230ffce08f511fbed4cf18daa743778b541583351Andy Huibers 273b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers // Not ready until the picture comes back. 274e3ad4352a23ddb21350d356e0947905d1e635911Sascha Haeberling broadcastReadyState(false); 275e3ad4352a23ddb21350d356e0947905d1e635911Sascha Haeberling 27630ffce08f511fbed4cf18daa743778b541583351Andy Huibers mTakePictureRunnable = new Runnable() { 27730ffce08f511fbed4cf18daa743778b541583351Andy Huibers @Override 27830ffce08f511fbed4cf18daa743778b541583351Andy Huibers public void run() { 27930ffce08f511fbed4cf18daa743778b541583351Andy Huibers takePictureNow(params, session); 28030ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 28130ffce08f511fbed4cf18daa743778b541583351Andy Huibers }; 28217d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers mLastPictureCallback = params.callback; 28330ffce08f511fbed4cf18daa743778b541583351Andy Huibers mTakePictureStartMillis = SystemClock.uptimeMillis(); 28430ffce08f511fbed4cf18daa743778b541583351Andy Huibers 285b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers // This class implements a very simple version of AF, which 286b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers // only delays capture if the lens is scanning. 287b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers if (mLastResultAFState == AutoFocusState.ACTIVE_SCAN) { 28830ffce08f511fbed4cf18daa743778b541583351Andy Huibers Log.v(TAG, "Waiting until scan is done before taking shot."); 28930ffce08f511fbed4cf18daa743778b541583351Andy Huibers mTakePictureWhenLensIsStopped = true; 29030ffce08f511fbed4cf18daa743778b541583351Andy Huibers } else { 291b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers // We could do CONTROL_AF_TRIGGER_START and wait until lens locks, 292b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers // but this would slow down the capture. 29330ffce08f511fbed4cf18daa743778b541583351Andy Huibers takePictureNow(params, session); 29430ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 29530ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 29630ffce08f511fbed4cf18daa743778b541583351Andy Huibers 29730ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** 29851163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling * Take picture immediately. Parameters passed through from takePicture(). 29930ffce08f511fbed4cf18daa743778b541583351Andy Huibers */ 30030ffce08f511fbed4cf18daa743778b541583351Andy Huibers public void takePictureNow(PhotoCaptureParameters params, CaptureSession session) { 30130ffce08f511fbed4cf18daa743778b541583351Andy Huibers long dt = SystemClock.uptimeMillis() - mTakePictureStartMillis; 30230ffce08f511fbed4cf18daa743778b541583351Andy Huibers Log.v(TAG, "Taking shot with extra AF delay of " + dt + " ms."); 30357bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling // This will throw a RuntimeException, if parameters are not sane. 30457bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling params.checkSanity(); 305f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling try { 30630ffce08f511fbed4cf18daa743778b541583351Andy Huibers // JPEG capture. 307f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling CaptureRequest.Builder builder = mDevice 308f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling .createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 30930ffce08f511fbed4cf18daa743778b541583351Andy Huibers builder.setTag(RequestTag.CAPTURE); 31026b3334755ffccc039249005435d5cc598d0689eAndy Huibers addBaselineCaptureKeysToRequest(builder); 311967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall 312967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall if (sCaptureImageFormat == ImageFormat.JPEG) { 313967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall builder.set(CaptureRequest.JPEG_QUALITY, JPEG_QUALITY); 314a2dd9ea5ba031128b9f0aa3852ff59991dd3008cSascha Haeberling builder.set(CaptureRequest.JPEG_ORIENTATION, 315a2dd9ea5ba031128b9f0aa3852ff59991dd3008cSascha Haeberling CameraUtil.getJpegRotation(params.orientation, mCharacteristics)); 316967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall } 317967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall 318f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling builder.addTarget(mPreviewSurface); 319967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall builder.addTarget(mCaptureImageReader.getSurface()); 3200cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling CaptureRequest request = builder.build(); 32151163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling 32251163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling if (DEBUG_WRITE_CAPTURE_DATA) { 32351163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling final String debugDataDir = makeDebugDir(params.debugDataFolder, 32451163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling "normal_capture_debug"); 32551163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling Log.i(TAG, "Writing capture data to: " + debugDataDir); 32651163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling CaptureDataSerializer.toFile("Normal Capture", request, new File(debugDataDir, 32751163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling "capture.txt")); 32851163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling } 32951163540604bcb1deabfde4d83c54a86114cefd0Sascha Haeberling 33030ffce08f511fbed4cf18daa743778b541583351Andy Huibers mCaptureSession.capture(request, mAutoFocusStateListener, mCameraHandler); 331f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } catch (CameraAccessException e) { 332967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall Log.e(TAG, "Could not access camera for still image capture."); 333e3ad4352a23ddb21350d356e0947905d1e635911Sascha Haeberling broadcastReadyState(true); 334f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling params.callback.onPictureTakenFailed(); 335f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling return; 336f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 33757bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling mCaptureQueue.add(new InFlightCapture(params, session)); 338f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 339f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 340f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 341f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling public void startPreview(Surface previewSurface, CaptureReadyCallback listener) { 342f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mPreviewSurface = previewSurface; 343f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling setupAsync(mPreviewSurface, listener); 344f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 345f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 346f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 3479cefdd495332719d987ffb942742ec602793d8d4Jiawen Chen public void setViewfinderSize(int width, int height) { 348f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling throw new RuntimeException("Not implemented yet."); 349f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 350f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 351f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 352f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling public boolean isFlashSupported(boolean enhanced) { 353f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling throw new RuntimeException("Not implemented yet."); 354f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 355f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 356f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 357f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling public boolean isSupportingEnhancedMode() { 358f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling throw new RuntimeException("Not implemented yet."); 359f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 360f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 361f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 362f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling public void close(CloseCallback closeCallback) { 363f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling if (mIsClosed) { 364f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling Log.w(TAG, "Camera is already closed."); 365f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling return; 366f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 36730ffce08f511fbed4cf18daa743778b541583351Andy Huibers try { 36830ffce08f511fbed4cf18daa743778b541583351Andy Huibers mCaptureSession.abortCaptures(); 36930ffce08f511fbed4cf18daa743778b541583351Andy Huibers } catch (CameraAccessException e) { 37030ffce08f511fbed4cf18daa743778b541583351Andy Huibers Log.e(TAG, "Could not abort captures in progress."); 37130ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 372f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mIsClosed = true; 373f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mCloseCallback = closeCallback; 374f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mCameraThread.quitSafely(); 375f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mDevice.close(); 376f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 377f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 378f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 379f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling public Size[] getSupportedSizes() { 380f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling StreamConfigurationMap config = mCharacteristics 381f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling .get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 382967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall return Size.convert(config.getOutputSizes(sCaptureImageFormat)); 383f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 384f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 385f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 3869cefdd495332719d987ffb942742ec602793d8d4Jiawen Chen public float getFullSizeAspectRatio() { 387f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling return mFullSizeAspectRatio; 388f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 389f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 39057bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling @Override 39157bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling public boolean isFrontFacing() { 39257bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling return mCharacteristics.get(CameraCharacteristics.LENS_FACING) 39357bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling == CameraMetadata.LENS_FACING_FRONT; 39457bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling } 39557bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling 39657bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling @Override 39757bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling public boolean isBackFacing() { 39857bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling return mCharacteristics.get(CameraCharacteristics.LENS_FACING) 39957bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling == CameraMetadata.LENS_FACING_BACK; 40057bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling } 40157bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling 40257bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling private void savePicture(byte[] jpegData, final PhotoCaptureParameters captureParams, 40357bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling CaptureSession session) { 40457bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling int heading = captureParams.heading; 40557bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling int width = 0; 40657bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling int height = 0; 40757bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling int rotation = 0; 40857bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling ExifInterface exif = null; 40957bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling try { 41057bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling exif = new ExifInterface(); 41157bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling exif.readExif(jpegData); 41257bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling 41357bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling Integer w = exif.getTagIntValue(ExifInterface.TAG_PIXEL_X_DIMENSION); 41457bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling width = (w == null) ? width : w; 41557bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling Integer h = exif.getTagIntValue(ExifInterface.TAG_PIXEL_Y_DIMENSION); 41657bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling height = (h == null) ? height : h; 41757bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling 41857bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling // Get image rotation from EXIF. 41957bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling rotation = Exif.getOrientation(exif); 42057bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling 42157bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling // Set GPS heading direction based on sensor, if location is on. 42257bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling if (heading >= 0) { 42357bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling ExifTag directionRefTag = exif.buildTag( 42457bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling ExifInterface.TAG_GPS_IMG_DIRECTION_REF, 42557bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling ExifInterface.GpsTrackRef.MAGNETIC_DIRECTION); 42657bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling ExifTag directionTag = exif.buildTag( 42757bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling ExifInterface.TAG_GPS_IMG_DIRECTION, 42857bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling new Rational(heading, 1)); 42957bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling exif.setTag(directionRefTag); 43057bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling exif.setTag(directionTag); 43157bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling } 43257bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling } catch (IOException e) { 43357bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling Log.w(TAG, "Could not read exif from gcam jpeg", e); 43457bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling exif = null; 43557bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling } 43657bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling session.saveAndFinish(jpegData, width, height, rotation, exif, new OnMediaSavedListener() { 43757bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling @Override 43857bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling public void onMediaSaved(Uri uri) { 43957bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling captureParams.callback.onPictureSaved(uri); 44057bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling } 44157bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling }); 44257bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling } 44357bcd92f39d85427102f30be2c749c4a7bd4be96Sascha Haeberling 444f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** 445f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * Asynchronously sets up the capture session. 446f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * 447f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * @param previewSurface the surface onto which the preview should be 448f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * rendered. 449f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * @param listener called when setup is completed. 450f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling */ 451f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private void setupAsync(final Surface previewSurface, final CaptureReadyCallback listener) { 452f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mCameraHandler.post(new Runnable() { 453f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 454f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling public void run() { 455f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling setup(previewSurface, listener); 456f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 457f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling }); 458f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 459f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 460f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** 461f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * Configures and attempts to create a capture session. 462f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * 463f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * @param previewSurface the surface onto which the preview should be 464f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * rendered. 465f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * @param listener called when the setup is completed. 466f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling */ 467f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private void setup(Surface previewSurface, final CaptureReadyCallback listener) { 468f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling try { 469f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling if (mCaptureSession != null) { 470f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mCaptureSession.abortCaptures(); 471f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mCaptureSession = null; 472f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 473f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling List<Surface> outputSurfaces = new ArrayList<Surface>(2); 474f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling outputSurfaces.add(previewSurface); 475967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall outputSurfaces.add(mCaptureImageReader.getSurface()); 476f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 47776215c98a9a11d87b5ce9d2b4198654c2b8bbddfAlan Newberger mDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() { 478f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 479f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 480f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling public void onConfigureFailed(CameraCaptureSession session) { 481f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling listener.onSetupFailed(); 482f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 483f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 484f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 485f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling public void onConfigured(CameraCaptureSession session) { 486f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mCaptureSession = session; 487b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers mAFRegions = ZERO_WEIGHT_3A_REGION; 488b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers mAERegions = ZERO_WEIGHT_3A_REGION; 48926b3334755ffccc039249005435d5cc598d0689eAndy Huibers mZoomValue = 1f; 49026b3334755ffccc039249005435d5cc598d0689eAndy Huibers mCropRegion = cropRegionForZoom(mZoomValue); 49126b3334755ffccc039249005435d5cc598d0689eAndy Huibers boolean success = repeatingPreview(null); 49226b3334755ffccc039249005435d5cc598d0689eAndy Huibers if (success) { 49326b3334755ffccc039249005435d5cc598d0689eAndy Huibers listener.onReadyForCapture(); 49426b3334755ffccc039249005435d5cc598d0689eAndy Huibers } else { 49526b3334755ffccc039249005435d5cc598d0689eAndy Huibers listener.onSetupFailed(); 49626b3334755ffccc039249005435d5cc598d0689eAndy Huibers } 497f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 498f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 499f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling @Override 500f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling public void onClosed(CameraCaptureSession session) { 501f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling super.onClosed(session); 502f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling if (mCloseCallback != null) { 503f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling mCloseCallback.onCameraClosed(); 504f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 505f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 506f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling }, mCameraHandler); 507f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } catch (CameraAccessException ex) { 508f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling Log.e(TAG, "Could not set up capture session", ex); 509f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling listener.onSetupFailed(); 510f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 511f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 512f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 513f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** 51426b3334755ffccc039249005435d5cc598d0689eAndy Huibers * Adds current regions to CaptureRequest and base AF mode + AF_TRIGGER_IDLE. 51526b3334755ffccc039249005435d5cc598d0689eAndy Huibers * 51626b3334755ffccc039249005435d5cc598d0689eAndy Huibers * @param builder Build for the CaptureRequest 51726b3334755ffccc039249005435d5cc598d0689eAndy Huibers */ 51826b3334755ffccc039249005435d5cc598d0689eAndy Huibers private void addBaselineCaptureKeysToRequest(CaptureRequest.Builder builder) { 519b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers builder.set(CaptureRequest.CONTROL_AF_REGIONS, mAFRegions); 520b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers builder.set(CaptureRequest.CONTROL_AE_REGIONS, mAERegions); 52126b3334755ffccc039249005435d5cc598d0689eAndy Huibers builder.set(CaptureRequest.SCALER_CROP_REGION, mCropRegion); 52226b3334755ffccc039249005435d5cc598d0689eAndy Huibers builder.set(CaptureRequest.CONTROL_AF_MODE, mControlAFMode); 52326b3334755ffccc039249005435d5cc598d0689eAndy Huibers builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_IDLE); 524b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers // Enable face detection 525b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers builder.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE, 526b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers CaptureRequest.STATISTICS_FACE_DETECT_MODE_FULL); 527b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers builder.set(CaptureRequest.CONTROL_SCENE_MODE, 528b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers CaptureRequest.CONTROL_SCENE_MODE_FACE_PRIORITY); 52926b3334755ffccc039249005435d5cc598d0689eAndy Huibers } 53026b3334755ffccc039249005435d5cc598d0689eAndy Huibers 53126b3334755ffccc039249005435d5cc598d0689eAndy Huibers /** 53230ffce08f511fbed4cf18daa743778b541583351Andy Huibers * Request preview capture stream with AF_MODE_CONTINUOUS_PICTURE. 533f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * 53426b3334755ffccc039249005435d5cc598d0689eAndy Huibers * @return true if request was build and sent successfully. 53526b3334755ffccc039249005435d5cc598d0689eAndy Huibers * @param tag 536f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling */ 53726b3334755ffccc039249005435d5cc598d0689eAndy Huibers private boolean repeatingPreview(Object tag) { 538f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling try { 53930ffce08f511fbed4cf18daa743778b541583351Andy Huibers CaptureRequest.Builder builder = mDevice. 54030ffce08f511fbed4cf18daa743778b541583351Andy Huibers createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 54130ffce08f511fbed4cf18daa743778b541583351Andy Huibers builder.addTarget(mPreviewSurface); 542f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling builder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); 54326b3334755ffccc039249005435d5cc598d0689eAndy Huibers addBaselineCaptureKeysToRequest(builder); 54430ffce08f511fbed4cf18daa743778b541583351Andy Huibers mCaptureSession.setRepeatingRequest(builder.build(), mAutoFocusStateListener, 54530ffce08f511fbed4cf18daa743778b541583351Andy Huibers mCameraHandler); 54626b3334755ffccc039249005435d5cc598d0689eAndy Huibers Log.v(TAG, String.format("Sent repeating Preview request, zoom = %.2f", mZoomValue)); 54726b3334755ffccc039249005435d5cc598d0689eAndy Huibers return true; 54830ffce08f511fbed4cf18daa743778b541583351Andy Huibers } catch (CameraAccessException ex) { 54930ffce08f511fbed4cf18daa743778b541583351Andy Huibers Log.e(TAG, "Could not access camera setting up preview.", ex); 55026b3334755ffccc039249005435d5cc598d0689eAndy Huibers return false; 55130ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 55230ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 55330ffce08f511fbed4cf18daa743778b541583351Andy Huibers 55430ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** 55526b3334755ffccc039249005435d5cc598d0689eAndy Huibers * Request preview capture stream with auto focus trigger cycle. 55630ffce08f511fbed4cf18daa743778b541583351Andy Huibers */ 55726b3334755ffccc039249005435d5cc598d0689eAndy Huibers private void sendAutoFocusTriggerCaptureRequest(Object tag) { 55830ffce08f511fbed4cf18daa743778b541583351Andy Huibers try { 55926b3334755ffccc039249005435d5cc598d0689eAndy Huibers // Step 1: Request single frame CONTROL_AF_TRIGGER_START. 56030ffce08f511fbed4cf18daa743778b541583351Andy Huibers CaptureRequest.Builder builder; 56130ffce08f511fbed4cf18daa743778b541583351Andy Huibers builder = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 562f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling builder.addTarget(mPreviewSurface); 56330ffce08f511fbed4cf18daa743778b541583351Andy Huibers builder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); 56426b3334755ffccc039249005435d5cc598d0689eAndy Huibers mControlAFMode = CameraMetadata.CONTROL_AF_MODE_AUTO; 56526b3334755ffccc039249005435d5cc598d0689eAndy Huibers addBaselineCaptureKeysToRequest(builder); 56630ffce08f511fbed4cf18daa743778b541583351Andy Huibers builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START); 56726b3334755ffccc039249005435d5cc598d0689eAndy Huibers builder.setTag(tag); 56830ffce08f511fbed4cf18daa743778b541583351Andy Huibers mCaptureSession.capture(builder.build(), mAutoFocusStateListener, mCameraHandler); 56930ffce08f511fbed4cf18daa743778b541583351Andy Huibers 57026b3334755ffccc039249005435d5cc598d0689eAndy Huibers // Step 2: Call repeatingPreview to update mControlAFMode. 57126b3334755ffccc039249005435d5cc598d0689eAndy Huibers repeatingPreview(tag); 57230ffce08f511fbed4cf18daa743778b541583351Andy Huibers resumeContinuousAFAfterDelay(FOCUS_HOLD_MILLIS); 57330ffce08f511fbed4cf18daa743778b541583351Andy Huibers } catch (CameraAccessException ex) { 57430ffce08f511fbed4cf18daa743778b541583351Andy Huibers Log.e(TAG, "Could not execute preview request.", ex); 57530ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 57630ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 57730ffce08f511fbed4cf18daa743778b541583351Andy Huibers 57830ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** 57930ffce08f511fbed4cf18daa743778b541583351Andy Huibers * Resume AF_MODE_CONTINUOUS_PICTURE after FOCUS_HOLD_MILLIS. 58030ffce08f511fbed4cf18daa743778b541583351Andy Huibers */ 58130ffce08f511fbed4cf18daa743778b541583351Andy Huibers private void resumeContinuousAFAfterDelay(int millis) { 58230ffce08f511fbed4cf18daa743778b541583351Andy Huibers mCameraHandler.removeCallbacks(mReturnToContinuousAFRunnable); 58330ffce08f511fbed4cf18daa743778b541583351Andy Huibers mCameraHandler.postDelayed(mReturnToContinuousAFRunnable, millis); 58430ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 58530ffce08f511fbed4cf18daa743778b541583351Andy Huibers 58630ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** 58730ffce08f511fbed4cf18daa743778b541583351Andy Huibers * This method takes appropriate action if camera2 AF state changes. 58830ffce08f511fbed4cf18daa743778b541583351Andy Huibers * <ol> 58930ffce08f511fbed4cf18daa743778b541583351Andy Huibers * <li>Reports changes in camera2 AF state to OneCamera.FocusStateListener.</li> 590b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers * <li>Take picture after AF scan if mTakePictureWhenLensIsStopped true.</li> 59130ffce08f511fbed4cf18daa743778b541583351Andy Huibers * </ol> 59230ffce08f511fbed4cf18daa743778b541583351Andy Huibers */ 59330ffce08f511fbed4cf18daa743778b541583351Andy Huibers private void autofocusStateChangeDispatcher(CaptureResult result) { 594b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers if (result.getFrameNumber() < mLastControlAfStateFrameNumber || 595b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers result.get(CaptureResult.CONTROL_AF_STATE) == null) { 596b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers return; 597b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers } 598b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers mLastControlAfStateFrameNumber = result.getFrameNumber(); 59930ffce08f511fbed4cf18daa743778b541583351Andy Huibers 60030ffce08f511fbed4cf18daa743778b541583351Andy Huibers // Convert to OneCamera mode and state. 601b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers AutoFocusState resultAFState = AutoFocusHelper. 602b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers stateFromCamera2State(result.get(CaptureResult.CONTROL_AF_STATE)); 603b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers 604b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers // TODO: Consider using LENS_STATE. 605b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers boolean lensIsStopped = resultAFState == AutoFocusState.ACTIVE_FOCUSED || 606b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers resultAFState == AutoFocusState.ACTIVE_UNFOCUSED || 607b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers resultAFState == AutoFocusState.PASSIVE_FOCUSED || 608b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers resultAFState == AutoFocusState.PASSIVE_UNFOCUSED; 60930ffce08f511fbed4cf18daa743778b541583351Andy Huibers 61030ffce08f511fbed4cf18daa743778b541583351Andy Huibers if (mTakePictureWhenLensIsStopped && lensIsStopped) { 61130ffce08f511fbed4cf18daa743778b541583351Andy Huibers // Take the shot. 61230ffce08f511fbed4cf18daa743778b541583351Andy Huibers mCameraHandler.post(mTakePictureRunnable); 61330ffce08f511fbed4cf18daa743778b541583351Andy Huibers mTakePictureWhenLensIsStopped = false; 61430ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 61530ffce08f511fbed4cf18daa743778b541583351Andy Huibers 616b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers // Report state change when AF state has changed. 617b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers if (resultAFState != mLastResultAFState && mFocusStateListener != null) { 618ca3c564536f154b83e380e37382bc7b9f6049302Andy Huibers mFocusStateListener.onFocusStatusUpdate(resultAFState, result.getFrameNumber()); 61930ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 62030ffce08f511fbed4cf18daa743778b541583351Andy Huibers mLastResultAFState = resultAFState; 62130ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 62230ffce08f511fbed4cf18daa743778b541583351Andy Huibers 62330ffce08f511fbed4cf18daa743778b541583351Andy Huibers @Override 62430ffce08f511fbed4cf18daa743778b541583351Andy Huibers public void triggerFocusAndMeterAtPoint(float nx, float ny) { 6250971376b0ddf12c8aa886ad9109f6a8929095154Jiawen Chen int sensorOrientation = mCharacteristics.get( 6260971376b0ddf12c8aa886ad9109f6a8929095154Jiawen Chen CameraCharacteristics.SENSOR_ORIENTATION); 6270971376b0ddf12c8aa886ad9109f6a8929095154Jiawen Chen mAERegions = AutoFocusHelper.aeRegionsForNormalizedCoord(nx, ny, mCropRegion, sensorOrientation); 6280971376b0ddf12c8aa886ad9109f6a8929095154Jiawen Chen mAFRegions = AutoFocusHelper.afRegionsForNormalizedCoord(nx, ny, mCropRegion, sensorOrientation); 62930ffce08f511fbed4cf18daa743778b541583351Andy Huibers 63026b3334755ffccc039249005435d5cc598d0689eAndy Huibers sendAutoFocusTriggerCaptureRequest(RequestTag.TAP_TO_FOCUS); 63126b3334755ffccc039249005435d5cc598d0689eAndy Huibers } 63226b3334755ffccc039249005435d5cc598d0689eAndy Huibers 63326b3334755ffccc039249005435d5cc598d0689eAndy Huibers @Override 63426b3334755ffccc039249005435d5cc598d0689eAndy Huibers public float getMaxZoom() { 63526b3334755ffccc039249005435d5cc598d0689eAndy Huibers return mCharacteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM); 63626b3334755ffccc039249005435d5cc598d0689eAndy Huibers } 63726b3334755ffccc039249005435d5cc598d0689eAndy Huibers 63826b3334755ffccc039249005435d5cc598d0689eAndy Huibers @Override 63926b3334755ffccc039249005435d5cc598d0689eAndy Huibers public void setZoom(float zoom) { 64026b3334755ffccc039249005435d5cc598d0689eAndy Huibers mZoomValue = zoom; 64126b3334755ffccc039249005435d5cc598d0689eAndy Huibers mCropRegion = cropRegionForZoom(zoom); 64226b3334755ffccc039249005435d5cc598d0689eAndy Huibers repeatingPreview(null); 64326b3334755ffccc039249005435d5cc598d0689eAndy Huibers } 64426b3334755ffccc039249005435d5cc598d0689eAndy Huibers 645cbe861edcd0d094ee79d3eeaac48bb928017b600Sascha Haeberling @Override 646cbe861edcd0d094ee79d3eeaac48bb928017b600Sascha Haeberling public Size pickPreviewSize(Size pictureSize, Context context) { 647cbe861edcd0d094ee79d3eeaac48bb928017b600Sascha Haeberling float pictureAspectRatio = pictureSize.getWidth() / (float) pictureSize.getHeight(); 648cbe861edcd0d094ee79d3eeaac48bb928017b600Sascha Haeberling return CaptureModuleUtil.getOptimalPreviewSize(context, getSupportedSizes(), 649cbe861edcd0d094ee79d3eeaac48bb928017b600Sascha Haeberling pictureAspectRatio); 650cbe861edcd0d094ee79d3eeaac48bb928017b600Sascha Haeberling } 651cbe861edcd0d094ee79d3eeaac48bb928017b600Sascha Haeberling 65226b3334755ffccc039249005435d5cc598d0689eAndy Huibers private Rect cropRegionForZoom(float zoom) { 653b868274c9dc8d9c772ec89fb5955215cc7911087Andy Huibers return AutoFocusHelper.cropRegionForZoom(mCharacteristics, zoom); 65430ffce08f511fbed4cf18daa743778b541583351Andy Huibers } 65530ffce08f511fbed4cf18daa743778b541583351Andy Huibers 65630ffce08f511fbed4cf18daa743778b541583351Andy Huibers /** 657f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * Calculate the aspect ratio of the full size capture on this device. 658f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * 659f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * @param characteristics the characteristics of the camera device. 660f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * @return The aspect ration, in terms of width/height of the full capture 661f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * size. 662f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling */ 6639cefdd495332719d987ffb942742ec602793d8d4Jiawen Chen private static float calculateFullSizeAspectRatio(CameraCharacteristics characteristics) { 664f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling Rect activeArraySize = 665f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE); 6669cefdd495332719d987ffb942742ec602793d8d4Jiawen Chen return ((float)(activeArraySize.width())) / activeArraySize.height(); 667f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 668f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 669f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling /** 670f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * Given an image reader, extracts the JPEG image bytes and then closes the 671f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * reader. 672f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * 673f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * @param reader the reader to read the JPEG data from. 674f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling * @return The bytes of the JPEG image. Newly allocated. 675f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling */ 676f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling private static byte[] acquireJpegBytesAndClose(ImageReader reader) { 677f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling Image img = reader.acquireLatestImage(); 678967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall 679967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall ByteBuffer buffer; 680967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall 681967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall if (img.getFormat() == ImageFormat.JPEG) { 682967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall Image.Plane plane0 = img.getPlanes()[0]; 683967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall buffer = plane0.getBuffer(); 684967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall } else if (img.getFormat() == ImageFormat.YUV_420_888) { 685967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall buffer = ByteBuffer.allocateDirect(img.getWidth() * img.getHeight() * 3); 686967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall 687967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall Log.v(TAG, "Compressing JPEG with software encoder."); 688967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall int numBytes = JpegUtilNative.compressJpegFromYUV420Image(img, buffer, JPEG_QUALITY); 689967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall 690967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall if (numBytes < 0) { 691967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall throw new RuntimeException("Error compressing jpeg."); 692967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall } 693967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall 694967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall buffer.limit(numBytes); 695967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall } else { 696967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall throw new RuntimeException("Unsupported image format."); 697967b782837a22974f565f5bbc71bef7bc05fc878Puneet Lall } 698f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling 699f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling byte[] imageBytes = new byte[buffer.remaining()]; 700f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling buffer.get(imageBytes); 701f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling buffer.rewind(); 702f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling img.close(); 703f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling return imageBytes; 704f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling } 705f5e51ec44934d6d687267d2aff6386f5b728dd9fSascha Haeberling} 706