summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--assets/dependency.json8
-rw-r--r--src/com/android/camera/CaptureModule.java70
-rw-r--r--src/com/android/camera/CaptureUI.java1
-rw-r--r--src/com/android/camera/SettingsActivity.java11
-rw-r--r--src/com/android/camera/imageprocessor/PostProcessor.java274
-rw-r--r--src/com/android/camera/imageprocessor/ZSLQueue.java74
-rw-r--r--src/com/android/camera/util/CameraUtil.java28
7 files changed, 322 insertions, 144 deletions
diff --git a/assets/dependency.json b/assets/dependency.json
index e415a1cec..b8c396895 100644
--- a/assets/dependency.json
+++ b/assets/dependency.json
@@ -70,6 +70,12 @@
"0":{},
"default":
{"pref_camera2_facedetection_key":"on",
- "pref_camera2_video_quality_key":"720x480"}
+ "pref_camera2_video_quality_key":"720x480",
+ "pref_camera2_longshot_key":"off"}
+ },
+ "pref_camera2_selfiemirror_key":
+ {
+ "on":{"pref_camera2_longshot_key":"off"},
+ "off":{}
}
}
diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java
index acd9de91a..7e7b60414 100644
--- a/src/com/android/camera/CaptureModule.java
+++ b/src/com/android/camera/CaptureModule.java
@@ -178,7 +178,7 @@ public class CaptureModule implements CameraModule, PhotoController,
CaptureRequest.Key<Integer> BayerMonoLinkSessionIdKey =
new CaptureRequest.Key<>("org.codeaurora.qcamera3.dualcam_link_meta_data" +
".related_camera_id", Integer.class);
- CaptureRequest.Key<Integer> CdsModeKey =
+ public static CaptureRequest.Key<Integer> CdsModeKey =
new CaptureRequest.Key<>("org.codeaurora.qcamera3.CDS.cds_mode", Integer.class);
public static CaptureRequest.Key<Byte> JpegCropEnableKey =
new CaptureRequest.Key<>("org.codeaurora.qcamera3.jpeg_encode_crop.enable",
@@ -729,6 +729,10 @@ public class CaptureModule implements CameraModule, PhotoController,
return CameraProfile.getJpegEncodingQualityParameter(value);
}
+ public LocationManager getLocationManager() {
+ return mLocationManager;
+ }
+
private void initializeFirstTime() {
if (mFirstTimeInitialized || mPaused) {
return;
@@ -849,7 +853,7 @@ public class CaptureModule implements CameraModule, PhotoController,
}
if (isClearSightOn()) {
ClearSightImageProcessor.getInstance().onCaptureSessionConfigured(id == BAYER_ID, cameraCaptureSession);
- } else if (mChosenImageFormat == ImageFormat.YUV_420_888 && id == getMainCameraId()) {
+ } else if (mChosenImageFormat == ImageFormat.PRIVATE && id == getMainCameraId()) {
mPostProcessor.onSessionConfigured(mCameraDevice[id], mCaptureSession[id]);
}
} catch (CameraAccessException e) {
@@ -903,7 +907,7 @@ public class CaptureModule implements CameraModule, PhotoController,
list.add(surs);
}
list.add(mImageReader[id].getSurface());
- if(mChosenImageFormat == ImageFormat.YUV_420_888) {
+ if(mChosenImageFormat == ImageFormat.YUV_420_888 || mChosenImageFormat == ImageFormat.PRIVATE) {
if (mPostProcessor.isZSLEnabled()) {
mPreviewRequestBuilder[id].addTarget(mImageReader[id].getSurface());
list.add(mPostProcessor.getZSLReprocessImageReader().getSurface());
@@ -1053,13 +1057,17 @@ public class CaptureModule implements CameraModule, PhotoController,
private boolean takeZSLPicture(int cameraId) {
if(mPostProcessor.isZSLEnabled() && mPostProcessor.takeZSLPicture()) {
- checkAndPlayShutterSound(cameraId);
+ checkAndPlayShutterSound(getMainCameraId());
mUI.enableShutter(true);
return true;
}
return false;
}
+ public boolean isLongShotActive() {
+ return mLongshotActive;
+ }
+
/**
* Lock the focus as the first step for a still image capture.
*/
@@ -1297,7 +1305,7 @@ public class CaptureModule implements CameraModule, PhotoController,
mMpoSaveHandler.obtainMessage(MpoSaveHandler.MSG_CONFIGURE,
Long.valueOf(mCaptureStartTime)).sendToTarget();
}
- if(mChosenImageFormat == ImageFormat.YUV_420_888) { // Case of ZSL, FrameFilter, SelfieMirror
+ if(mChosenImageFormat == ImageFormat.YUV_420_888 || mChosenImageFormat == ImageFormat.PRIVATE) { // Case of ZSL, FrameFilter, SelfieMirror
mPostProcessor.onStartCapturing();
mCaptureSession[id].capture(captureBuilder.build(), mPostProcessor.getCaptureCallback(), mCaptureCallbackHandler);
} else {
@@ -1419,19 +1427,20 @@ public class CaptureModule implements CameraModule, PhotoController,
ClearSightImageProcessor.getInstance().setCallback(this);
}
} else {
- if (imageFormat == ImageFormat.YUV_420_888 && i == getMainCameraId()) {
+ if ((imageFormat == ImageFormat.YUV_420_888 || imageFormat == ImageFormat.PRIVATE)
+ && i == getMainCameraId()) {
if(mPostProcessor.isZSLEnabled()) {
mImageReader[i] = ImageReader.newInstance(mSupportedMaxPictureSize.getWidth(),
- mSupportedMaxPictureSize.getHeight(), imageFormat, PostProcessor.MAX_REQUIRED_IMAGE_NUM);
+ mSupportedMaxPictureSize.getHeight(), imageFormat, mPostProcessor.getMaxRequiredImageNum());
} else {
mImageReader[i] = ImageReader.newInstance(mPictureSize.getWidth(),
- mPictureSize.getHeight(), imageFormat, PostProcessor.MAX_REQUIRED_IMAGE_NUM);
+ mPictureSize.getHeight(), imageFormat, mPostProcessor.getMaxRequiredImageNum());
}
mImageReader[i].setOnImageAvailableListener(mPostProcessor.getImageHandler(), mImageAvailableHandler);
mPostProcessor.onImageReaderReady(mImageReader[i], mSupportedMaxPictureSize, mPictureSize);
} else {
mImageReader[i] = ImageReader.newInstance(mPictureSize.getWidth(),
- mPictureSize.getHeight(), imageFormat, PostProcessor.MAX_REQUIRED_IMAGE_NUM);
+ mPictureSize.getHeight(), imageFormat, PersistUtil.getLongshotShotLimit());
mImageReader[i].setOnImageAvailableListener(new ImageAvailableListener(i) {
@Override
@@ -1483,7 +1492,7 @@ public class CaptureModule implements CameraModule, PhotoController,
mVideoSnapshotImageReader.close();
}
mVideoSnapshotImageReader = ImageReader.newInstance(mVideoSnapshotSize.getWidth(),
- mVideoSnapshotSize.getHeight(), ImageFormat.JPEG, mPostProcessor.MAX_REQUIRED_IMAGE_NUM);
+ mVideoSnapshotSize.getHeight(), ImageFormat.JPEG, 2);
mVideoSnapshotImageReader.setOnImageAvailableListener(
new ImageReader.OnImageAvailableListener() {
@Override
@@ -1959,13 +1968,18 @@ public class CaptureModule implements CameraModule, PhotoController,
private void openProcessors() {
String scene = mSettingsManager.getValue(SettingsManager.KEY_SCENE_MODE);
- boolean isLongShotOn = false;
boolean isFlashOn = false;
boolean isTrackingFocusOn = false;
+ boolean isMakeupOn = false;
+ boolean isSelfieMirrorOn = false;
if(mPostProcessor != null) {
- String longshot = mSettingsManager.getValue(SettingsManager.KEY_LONGSHOT);
- if(longshot != null && longshot.equalsIgnoreCase("on")) {
- isLongShotOn = true;
+ String selfieMirror = mSettingsManager.getValue(SettingsManager.KEY_SELFIEMIRROR);
+ if(selfieMirror != null && selfieMirror.equalsIgnoreCase("on")) {
+ isSelfieMirrorOn = true;
+ }
+ String makeup = mSettingsManager.getValue(SettingsManager.KEY_MAKEUP);
+ if(makeup != null && !makeup.equals("0")) {
+ isMakeupOn = true;
}
String flashMode = mSettingsManager.getValue(SettingsManager.KEY_FLASH_MODE);
if(flashMode != null && flashMode.equalsIgnoreCase("on")) {
@@ -1978,17 +1992,18 @@ public class CaptureModule implements CameraModule, PhotoController,
if (scene != null) {
int mode = Integer.parseInt(scene);
Log.d(TAG, "Chosen postproc filter id : " + getPostProcFilterId(mode));
- mPostProcessor.onOpen(getPostProcFilterId(mode), isLongShotOn, isFlashOn, isTrackingFocusOn);
+ mPostProcessor.onOpen(getPostProcFilterId(mode), isFlashOn, isTrackingFocusOn, isMakeupOn, isSelfieMirrorOn);
} else {
- mPostProcessor.onOpen(PostProcessor.FILTER_NONE, isLongShotOn, isFlashOn, isTrackingFocusOn);
+ mPostProcessor.onOpen(PostProcessor.FILTER_NONE, isFlashOn, isTrackingFocusOn, isMakeupOn, isSelfieMirrorOn);
}
}
if(mFrameProcessor != null) {
mFrameProcessor.onOpen(getFrameProcFilterId(), mPreviewSize);
}
- if(!isLongShotOn &&
- (mPostProcessor.isFilterOn() || getFrameFilters().size() != 0 || mPostProcessor.isZSLEnabled() || mPostProcessor.isSelfieMirrorOn())) {
+ if(mPostProcessor.isZSLEnabled()) {
+ mChosenImageFormat = ImageFormat.PRIVATE;
+ } else if(mPostProcessor.isFilterOn() || getFrameFilters().size() != 0 || mPostProcessor.isSelfieMirrorOn()) {
mChosenImageFormat = ImageFormat.YUV_420_888;
} else {
mChosenImageFormat = ImageFormat.JPEG;
@@ -2400,6 +2415,8 @@ public class CaptureModule implements CameraModule, PhotoController,
public void onShutterButtonFocus(boolean pressed) {
if (!pressed && mLongshotActive) {
Log.d(TAG, "Longshot button up");
+ mLongshotActive = false;
+ mPostProcessor.stopLongShot();
}
}
@@ -2416,6 +2433,10 @@ public class CaptureModule implements CameraModule, PhotoController,
mPictureThumbSize = getOptimalPreviewSize(mPictureSize, thumbSizes, 0, 0); // get largest thumb size
}
+ public Size getThumbSize() {
+ return mPictureThumbSize;
+ }
+
public boolean isRecordingVideo() {
return mIsRecordingVideo;
}
@@ -2993,12 +3014,19 @@ public class CaptureModule implements CameraModule, PhotoController,
}
+ public boolean isLongShotSettingEnabled() {
+ String longshot = mSettingsManager.getValue(SettingsManager.KEY_LONGSHOT);
+ if(longshot.equals("on")) {
+ return true;
+ }
+ return false;
+ }
+
@Override
public void onShutterButtonLongClick() {
if (isBackCamera() && getCameraMode() == DUAL_MODE) return;
- String longshot = mSettingsManager.getValue(SettingsManager.KEY_LONGSHOT);
- if (longshot.equals("on")) {
+ if (isLongShotSettingEnabled()) {
//Cancel the previous countdown when long press shutter button for longshot.
if (mUI.isCountingDown()) {
mUI.cancelCountDown();
@@ -3313,7 +3341,7 @@ public class CaptureModule implements CameraModule, PhotoController,
}
}
- private void checkAndPlayShutterSound(int id) {
+ public void checkAndPlayShutterSound(int id) {
if (id == getMainCameraId()) {
String value = mSettingsManager.getValue(SettingsManager.KEY_SHUTTER_SOUND);
if (value != null && value.equals("on") && mSound != null) {
diff --git a/src/com/android/camera/CaptureUI.java b/src/com/android/camera/CaptureUI.java
index 6c4254cb6..b980bf7ef 100644
--- a/src/com/android/camera/CaptureUI.java
+++ b/src/com/android/camera/CaptureUI.java
@@ -392,6 +392,7 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
mMakeupSeekBarLayout.setVisibility(View.VISIBLE);
} else {
mMakeupButton.setImageResource(R.drawable.beautify);
+ mMakeupSeekBarLayout.setVisibility(View.GONE);
}
}
});
diff --git a/src/com/android/camera/SettingsActivity.java b/src/com/android/camera/SettingsActivity.java
index 8482750ec..86d74b079 100644
--- a/src/com/android/camera/SettingsActivity.java
+++ b/src/com/android/camera/SettingsActivity.java
@@ -194,12 +194,13 @@ public class SettingsActivity extends PreferenceActivity {
}
private void updatePreferenceButton(String key) {
- ListPreference pref = (ListPreference) findPreference(key);
- if (pref != null) {
- if (pref.getEntryValues().length == 1) {
- pref.setEnabled(false);
+ Preference pref = findPreference(key);
+ if (pref != null && pref instanceof ListPreference) {
+ ListPreference pref2 = (ListPreference) pref;
+ if (pref2.getEntryValues().length == 1) {
+ pref2.setEnabled(false);
} else {
- pref.setEnabled(true);
+ pref2.setEnabled(true);
}
}
}
diff --git a/src/com/android/camera/imageprocessor/PostProcessor.java b/src/com/android/camera/imageprocessor/PostProcessor.java
index 82467acaa..8e6caa953 100644
--- a/src/com/android/camera/imageprocessor/PostProcessor.java
+++ b/src/com/android/camera/imageprocessor/PostProcessor.java
@@ -43,6 +43,7 @@ import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
+import android.location.Location;
import android.media.Image;
import android.media.ImageReader;
import android.media.ImageWriter;
@@ -81,6 +82,8 @@ import java.util.concurrent.Semaphore;
import com.android.camera.imageprocessor.filter.ImageFilter;
import com.android.camera.util.CameraUtil;
+import com.android.camera.util.PersistUtil;
+
import android.util.Size;
public class PostProcessor{
@@ -99,7 +102,7 @@ public class PostProcessor{
public static final int FILTER_MAX = 8;
//BestPicture requires 10 which is the biggest among filters
- public static final int MAX_REQUIRED_IMAGE_NUM = 11;
+ private static final int MAX_REQUIRED_IMAGE_NUM = 11;
private int mCurrentNumImage = 0;
private ImageFilter mFilter;
private int mFilterIndex;
@@ -117,10 +120,10 @@ public class PostProcessor{
private int mOrientation = 0;
private ImageWriter mImageWriter;
- //This is for the debug feature.
private static boolean DEBUG_FILTER = false;
- private static boolean DEBUG_ZSL = true;
+ private static boolean DEBUG_ZSL = false;
private ImageFilter.ResultImage mDebugResultImage;
+
private ZSLQueue mZSLQueue;
private CameraDevice mCameraDevice;
private CameraCaptureSession mCaptureSession;
@@ -129,10 +132,20 @@ public class PostProcessor{
private boolean mUseZSL = true;
private Handler mZSLHandler;
private HandlerThread mZSLHandlerThread;
+ private Handler mSavingHander;
+ private HandlerThread mSavingHandlerThread;
private ImageHandlerTask mImageHandlerTask;
private LinkedList<TotalCaptureResult> mTotalCaptureResultList = new LinkedList<TotalCaptureResult>();
private TotalCaptureResult mZSLFallOffResult = null;
- private boolean mIsZSLFallOffForFlash = false;
+ private boolean mIsZSLFallOff = false;
+ private TotalCaptureResult mLatestResultForLongShot = null;
+ private LinkedList<Image> mFallOffImages = new LinkedList<Image>();
+ private int mPendingContinuousRequestCount = 0;
+ public int mMaxRequiredImageNum;
+
+ public int getMaxRequiredImageNum() {
+ return mMaxRequiredImageNum;
+ }
public boolean isZSLEnabled() {
return mUseZSL;
@@ -169,6 +182,42 @@ public class PostProcessor{
}
}
+ private void clearFallOffImage() {
+ for(Image im: mFallOffImages ) {
+ try {
+ im.close();
+ } catch(Exception e) {
+ }
+ }
+ mFallOffImages.clear();
+ }
+
+ private Image findFallOffImage(long timestamp) {
+ Image foundImage = null;
+ for(Image im: mFallOffImages ) {
+ if(im.getTimestamp() == timestamp) {
+ foundImage = im;
+ break;
+ }
+ }
+ if(foundImage != null) {
+ mFallOffImages.remove(foundImage);
+ }
+ return foundImage;
+ }
+
+ private void addFallOffImage(Image image) {
+ mFallOffImages.add(image);
+ if(mFallOffImages.size() >= MAX_REQUIRED_IMAGE_NUM - 1) {
+ Image im = mFallOffImages.getFirst();
+ try {
+ im.close();
+ } catch(Exception e) {
+ }
+ mFallOffImages.removeFirst();
+ }
+ }
+
class ImageHandlerTask implements Runnable, ImageReader.OnImageAvailableListener {
private ImageWrapper mImageWrapper = null;
Semaphore mMutureLock = new Semaphore(1);
@@ -177,15 +226,31 @@ public class PostProcessor{
public void onImageAvailable(ImageReader reader) {
try {
if(mUseZSL) {
- if(mIsZSLFallOffForFlash && mZSLFallOffResult != null) {
+ if(mController.isLongShotActive() && mPendingContinuousRequestCount > 0) {
+ Image image = reader.acquireNextImage();
+ ZSLQueue.ImageItem item = new ZSLQueue.ImageItem();
+ item.setImage(image);
+ if(onContinuousZSLImage(item, true)) {
+ image.close();
+ }
+ return;
+ }
+ if(mIsZSLFallOff) {
Image image = reader.acquireNextImage();
- if((mZSLFallOffResult.get(CaptureResult.SENSOR_TIMESTAMP)).longValue() <= image.getTimestamp()) {
- Log.d(TAG,"ZSL fall off for flash image");
- mIsZSLFallOffForFlash = false;
- reprocessImage(image, mZSLFallOffResult);
+ if(mZSLFallOffResult == null) {
+ addFallOffImage(image);
+ return;
+ }
+ addFallOffImage(image);
+ Image foundImage = findFallOffImage(mZSLFallOffResult.get(CaptureResult.SENSOR_TIMESTAMP).longValue());
+ if(foundImage != null) {
+ Log.d(TAG,"ZSL fall off image is found");
+ reprocessImage(foundImage, mZSLFallOffResult);
+ mIsZSLFallOff = false;
+ clearFallOffImage();
mZSLFallOffResult = null;
} else {
- image.close();
+ clearFallOffImage();
}
return;
}
@@ -217,8 +282,9 @@ public class PostProcessor{
}
} catch (IllegalStateException e) {
Log.e(TAG, "Max images has been already acquired. ");
- mIsZSLFallOffForFlash = false;
+ mIsZSLFallOff = false;
mZSLFallOffResult = null;
+ clearFallOffImage();
}
}
@@ -242,6 +308,7 @@ public class PostProcessor{
if(mUseZSL && mZSLQueue != null) {
mZSLQueue.add(metadata);
}
+ mLatestResultForLongShot = metadata;
}
CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession.CaptureCallback() {
@@ -253,7 +320,7 @@ public class PostProcessor{
if(mTotalCaptureResultList.size() <= PostProcessor.MAX_REQUIRED_IMAGE_NUM) {
mTotalCaptureResultList.add(result);
}
- if(mIsZSLFallOffForFlash) {
+ if(mIsZSLFallOff) {
mZSLFallOffResult = result;
} else {
onMetaAvailable(result);
@@ -283,14 +350,14 @@ public class PostProcessor{
mCameraDevice = cameraDevice;
mCaptureSession = captureSession;
if(mUseZSL) {
- mImageWriter = ImageWriter.newInstance(captureSession.getInputSurface(), 2);
+ mImageWriter = ImageWriter.newInstance(captureSession.getInputSurface(), mMaxRequiredImageNum);
}
}
public void onImageReaderReady(ImageReader imageReader, Size maxSize, Size pictureSize) {
mImageReader = imageReader;
if(mUseZSL) {
- mZSLReprocessImageReader = ImageReader.newInstance(pictureSize.getWidth(), pictureSize.getHeight(), ImageFormat.YUV_420_888, 2);
+ mZSLReprocessImageReader = ImageReader.newInstance(pictureSize.getWidth(), pictureSize.getHeight(), ImageFormat.JPEG, mMaxRequiredImageNum);
mZSLReprocessImageReader.setOnImageAvailableListener(processedImageAvailableListener, mHandler);
}
}
@@ -300,53 +367,131 @@ public class PostProcessor{
if(mController.getPreviewCaptureResult() == null ||
mController.getPreviewCaptureResult().get(CaptureResult.CONTROL_AE_STATE) == CameraMetadata.CONTROL_AE_STATE_FLASH_REQUIRED) {
if(DEBUG_ZSL) Log.d(TAG, "Flash required image");
- mIsZSLFallOffForFlash = true;
imageItem = null;
}
if (mController.isSelfieFlash()) {
imageItem = null;
}
+ if (mController.isLongShotActive()) {
+ imageItem = null;
+ }
if (imageItem != null) {
if(DEBUG_ZSL) Log.d(TAG,"Got the item from the queue");
reprocessImage(imageItem.getImage(), imageItem.getMetadata());
return true;
} else {
if(DEBUG_ZSL) Log.d(TAG, "No good item in queue, register the request for the future");
- if(!mIsZSLFallOffForFlash) {
- mZSLQueue.addPictureRequest();
+ if(mController.isLongShotActive()) {
+ if(DEBUG_ZSL) Log.d(TAG, "Long shot active in ZSL");
+ mPendingContinuousRequestCount = PersistUtil.getLongshotShotLimit();
+ return true;
+ } else {
+ mIsZSLFallOff = true;
}
return false;
}
}
- public void onMatchingZSLPictureAvailable(ZSLQueue.ImageItem imageItem) {
- reprocessImage(imageItem.getImage(), imageItem.getMetadata());
+ public boolean onContinuousZSLImage(ZSLQueue.ImageItem imageItem, boolean isLongShotRequest) {
+ if(isLongShotRequest) {
+ if(mLatestResultForLongShot != null) {
+ reprocessImage(imageItem.getImage(), mLatestResultForLongShot);
+ mPendingContinuousRequestCount--;
+ return true;
+ }
+ } else {
+ reprocessImage(imageItem.getImage(), imageItem.getMetadata());
+ return true;
+ }
+
+ return false;
+ }
+
+ public void stopLongShot() {
+ mPendingContinuousRequestCount = 0;
}
private void reprocessImage(Image image, TotalCaptureResult metadata) {
- if(mCameraDevice == null || mCaptureSession == null || mImageReader == null) {
- Log.e(TAG, "Reprocess request is called even before taking picture");
- new Throwable().printStackTrace();
- return;
+ if(mController.isLongShotActive()) {
+ mController.checkAndPlayShutterSound(mController.getMainCameraId());
}
- Log.d(TAG, "reprocess Image request");
- CaptureRequest.Builder builder = null;
- try {
- builder = mCameraDevice.createReprocessCaptureRequest(metadata);
- builder.addTarget(mZSLReprocessImageReader.getSurface());
- builder.set(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE,
- CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY);
- builder.set(CaptureRequest.EDGE_MODE,
- CaptureRequest.EDGE_MODE_HIGH_QUALITY);
- builder.set(CaptureRequest.NOISE_REDUCTION_MODE,
- CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY);
+ synchronized (lock) {
+ if(mCameraDevice == null || mCaptureSession == null || mImageReader == null) {
+ Log.e(TAG, "Reprocess request is called even before taking picture");
+ image.close();
+ return;
+ }
+ if (mZSLReprocessImageReader == null) {
+ image.close();
+ return;
+ }
+ if (DEBUG_ZSL) Log.d(TAG, "reprocess Image request " + image.getTimestamp());
+ CaptureRequest.Builder builder = null;
try {
- mImageWriter.queueInputImage(image);
- } catch(IllegalStateException e) {
- Log.e(TAG, "Queueing more than it can have");
+ builder = mCameraDevice.createReprocessCaptureRequest(metadata);
+ builder.set(CaptureRequest.JPEG_ORIENTATION,
+ CameraUtil.getJpegRotation(mController.getMainCameraId(), mController.getDisplayOrientation()));
+ builder.set(CaptureRequest.JPEG_THUMBNAIL_SIZE, mController.getThumbSize());
+ builder.set(CaptureRequest.JPEG_THUMBNAIL_QUALITY, (byte)80);
+ builder.set(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE,
+ CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY);
+ builder.set(CaptureRequest.EDGE_MODE,
+ CaptureRequest.EDGE_MODE_HIGH_QUALITY);
+ builder.set(CaptureRequest.NOISE_REDUCTION_MODE,
+ CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY);
+ builder.set(CaptureModule.CdsModeKey, 2); // CDS 0-OFF, 1-ON, 2-AUTO
+ builder.set(CaptureModule.JpegCropEnableKey, (byte)1);
+ Rect cropRect = image.getCropRect();
+ if(cropRect == null ||
+ cropRect.isEmpty()) {
+ cropRect = new Rect(0, 0, image.getWidth(), image.getHeight());
+ }
+
+ int targetWidth = mZSLReprocessImageReader.getWidth();
+ int targetHeight = mZSLReprocessImageReader.getHeight();
+ float targetRatio = (float)targetWidth / (float)targetHeight;
+ cropRect = CameraUtil.getFinalCropRect(cropRect, targetRatio);
+ // has crop rect. apply to jpeg request
+ builder.set(CaptureModule.JpegCropRectKey,
+ new int[] {cropRect.left, cropRect.top, cropRect.width(), cropRect.height()});
+ builder.set(CaptureModule.JpegRoiRectKey,
+ new int[] {0, 0, targetWidth, targetHeight});
+
+ Location location = mController.getLocationManager().getCurrentLocation();
+ if(location != null) {
+ location = new Location(location);
+ Log.d(TAG, "sendReprocessRequest gps: " + location.toString());
+ // workaround for Google bug. Need to convert timestamp from ms -> sec
+ location.setTime(location.getTime()/1000);
+ builder.set(CaptureRequest.JPEG_GPS_LOCATION, location);
+ }
+
+ builder.addTarget(mZSLReprocessImageReader.getSurface());
+ try {
+ mImageWriter.queueInputImage(image);
+ } catch (IllegalStateException e) {
+ Log.e(TAG, "Queueing more than it can have");
+ }
+ mCaptureSession.capture(builder.build(), new CameraCaptureSession.CaptureCallback(){
+ @Override
+ public void onCaptureCompleted(CameraCaptureSession session,
+ CaptureRequest request,
+ TotalCaptureResult result) {
+ }
+
+ @Override
+ public void onCaptureFailed(CameraCaptureSession session,
+ CaptureRequest request,
+ CaptureFailure result) {
+ }
+
+ @Override
+ public void onCaptureSequenceCompleted(CameraCaptureSession session, int
+ sequenceId, long frameNumber) {
+ }
+ }, mHandler);
+ } catch (CameraAccessException e) {
}
- mCaptureSession.capture(builder.build(), mCaptureCallback, mHandler);
- } catch (CameraAccessException e) {
}
}
@@ -428,10 +573,11 @@ public class PostProcessor{
return false;
}
- public void onOpen(int postFilterId, boolean isLongShotOn, boolean isFlashModeOn, boolean isTrackingFocusOn) {
+ public void onOpen(int postFilterId, boolean isFlashModeOn, boolean isTrackingFocusOn, boolean isMakeupOn, boolean isSelfieMirrorOn) {
mImageHandlerTask = new ImageHandlerTask();
- if(setFilter(postFilterId) || isLongShotOn || isFlashModeOn || isTrackingFocusOn) {
+ if(setFilter(postFilterId) || isFlashModeOn || isTrackingFocusOn || isMakeupOn || isSelfieMirrorOn
+ || PersistUtil.getCameraZSLDisabled()) {
mUseZSL = false;
} else {
mUseZSL = true;
@@ -441,6 +587,11 @@ public class PostProcessor{
if(mUseZSL) {
mZSLQueue = new ZSLQueue(mController);
}
+ mMaxRequiredImageNum = MAX_REQUIRED_IMAGE_NUM;
+ if(mController.isLongShotSettingEnabled()) {
+ mMaxRequiredImageNum = Math.max(MAX_REQUIRED_IMAGE_NUM, PersistUtil.getLongshotShotLimit()+2);
+ }
+ mPendingContinuousRequestCount = 0;
}
public int getFilterIndex() {
@@ -470,6 +621,7 @@ public class PostProcessor{
mCameraDevice = null;
mCaptureSession = null;
mImageReader = null;
+ mPendingContinuousRequestCount = 0;
}
private void startBackgroundThread() {
@@ -481,6 +633,10 @@ public class PostProcessor{
mZSLHandlerThread.start();
mZSLHandler = new ProcessorHandler(mZSLHandlerThread.getLooper());
+ mSavingHandlerThread = new HandlerThread("SavingHandlerThread");
+ mSavingHandlerThread.start();
+ mSavingHander = new ProcessorHandler(mSavingHandlerThread.getLooper());
+
mWatchdog = new WatchdogThread();
mWatchdog.start();
}
@@ -557,6 +713,15 @@ public class PostProcessor{
mZSLHandlerThread = null;
mZSLHandler = null;
}
+ if (mSavingHandlerThread != null) {
+ mSavingHandlerThread.quitSafely();
+ try {
+ mSavingHandlerThread.join();
+ } catch (InterruptedException e) {
+ }
+ mSavingHandlerThread = null;
+ mSavingHander = null;
+ }
if(mWatchdog != null) {
mWatchdog.kill();
mWatchdog = null;
@@ -851,11 +1016,28 @@ public class PostProcessor{
ImageReader.OnImageAvailableListener processedImageAvailableListener = new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
- Log.d(TAG, "ZSL image Reprocess is done");
- Image image = reader.acquireNextImage();
- if(image != null) {
- onImageToProcess(image);
- }
+ final Image image = reader.acquireNextImage();
+ if(DEBUG_ZSL) Log.d(TAG, "ZSL image Reprocess is done "+image.getTimestamp());
+ mSavingHander.post(new Runnable() {
+ public void run() {
+ long captureStartTime = System.currentTimeMillis();
+ mNamedImages.nameNewImage(captureStartTime);
+ PhotoModule.NamedImages.NamedEntity name = mNamedImages.getNextNameEntity();
+ String title = (name == null) ? null : name.title;
+ long date = (name == null) ? -1 : name.date;
+ image.getPlanes()[0].getBuffer().rewind();
+ int size = image.getPlanes()[0].getBuffer().remaining();
+ byte[] bytes = new byte[size];
+ image.getPlanes()[0].getBuffer().get(bytes, 0, size);
+ ExifInterface exif = Exif.getExif(bytes);
+ int orientation = Exif.getOrientation(exif);
+ mActivity.getMediaSaveService().addImage(
+ bytes, title, date, null, image.getCropRect().width(), image.getCropRect().height(),
+ orientation, null, mController.getMediaSavedListener(), mActivity.getContentResolver(), "jpeg");
+ mController.updateThumbnailJpegData(bytes);
+ image.close();
+ }
+ });
}
};
diff --git a/src/com/android/camera/imageprocessor/ZSLQueue.java b/src/com/android/camera/imageprocessor/ZSLQueue.java
index 792489cbc..f50858a35 100644
--- a/src/com/android/camera/imageprocessor/ZSLQueue.java
+++ b/src/com/android/camera/imageprocessor/ZSLQueue.java
@@ -36,7 +36,9 @@ import android.util.Log;
import com.android.camera.CaptureModule;
import android.os.SystemProperties;
+import java.util.Iterator;
import java.util.LinkedList;
+import java.util.NoSuchElementException;
public class ZSLQueue {
private static final String CIRCULAR_BUFFER_SIZE_PERSIST = "persist.camera.zsl.buffer.size";
@@ -46,28 +48,10 @@ public class ZSLQueue {
private int mImageHead;
private int mMetaHead;
private Object mLock = new Object();
- private LinkedList<PendingRequest> mPendingRequestList = new LinkedList<PendingRequest>();
private CaptureModule mModule;
private static final boolean DEBUG = false;
private static final boolean DEBUG_QUEUE = false;
private static final String TAG = "ZSLQueue";
- private static final int REQUEST_LIFESPAN = 5; //This is in frame count.
-
- class PendingRequest {
- private int mLifeTimeInFrame;
-
- public PendingRequest(){
- mLifeTimeInFrame = 0;
- }
-
- public int getLifeTime() {
- return mLifeTimeInFrame;
- }
-
- public void incLifeTime() {
- mLifeTimeInFrame++;
- }
- }
public ZSLQueue(CaptureModule module) {
mCircularBufferSize = SystemProperties.getInt(CIRCULAR_BUFFER_SIZE_PERSIST, CIRCULAR_BUFFER_SIZE_DEFAULT);
@@ -75,7 +59,6 @@ public class ZSLQueue {
mBuffer = new ImageItem[mCircularBufferSize];
mImageHead = 0;
mMetaHead = 0;
- mPendingRequestList.clear();
mModule = module;
}
}
@@ -141,40 +124,6 @@ public class ZSLQueue {
}
if(DEBUG_QUEUE) Log.d(TAG, "imageIndex: " + lastIndex + " " + image.getTimestamp());
-
- if(mPendingRequestList.size() != 0) {
- if(lastIndex != -1) {
- processPendingRequest(lastIndex);
- }
- for(int i=0; i < mPendingRequestList.size(); i++) {
- mPendingRequestList.get(i).incLifeTime();
- }
- }
- }
-
- private void processPendingRequest(int index) {
- ImageItem item;
- synchronized (mLock) {
- if(mBuffer == null)
- return;
- item = mBuffer[index];
- if (item != null && item.isValid() && checkImageRequirement(item.getMetadata())) {
- if(DEBUG && (mBuffer[index].getMetadata().get(CaptureResult.SENSOR_TIMESTAMP)).longValue() !=
- mBuffer[index].getImage().getTimestamp()) {
- Log.e(TAG,"Not matching image coming through");
- }
- mBuffer[index] = null;
- mPendingRequestList.removeFirst();
- for(PendingRequest request : mPendingRequestList) {
- if(request.getLifeTime() >= REQUEST_LIFESPAN) {
- mPendingRequestList.remove(request);
- }
- }
- } else {
- return;
- }
- }
- mModule.getPostProcessor().onMatchingZSLPictureAvailable(item);
}
public void add(TotalCaptureResult metadata) {
@@ -224,15 +173,6 @@ public class ZSLQueue {
}
if(DEBUG_QUEUE) Log.d(TAG, "Meta: " + lastIndex + " " + metadata.get(CaptureResult.SENSOR_TIMESTAMP));
-
- if(mPendingRequestList.size() != 0) {
- if(lastIndex != -1) {
- processPendingRequest(lastIndex);
- }
- for(int i=0; i < mPendingRequestList.size(); i++) {
- mPendingRequestList.get(i).incLifeTime();
- }
- }
}
public ImageItem tryToGetMatchingItem() {
@@ -252,13 +192,6 @@ public class ZSLQueue {
return null;
}
- public void addPictureRequest() {
- if(DEBUG) Log.d(TAG, "RequsetPendingCount: "+mPendingRequestList.size());
- synchronized (mLock) {
- mPendingRequestList.addLast(new PendingRequest());
- }
- }
-
public void onClose() {
synchronized (mLock) {
for (int i = 0; i < mBuffer.length; i++) {
@@ -271,7 +204,6 @@ public class ZSLQueue {
mBuffer = null;
mImageHead = 0;
mMetaHead = 0;
- mPendingRequestList.clear();
}
}
@@ -304,7 +236,7 @@ public class ZSLQueue {
return true;
}
- class ImageItem {
+ static class ImageItem {
private Image mImage = null;
private TotalCaptureResult mMetadata = null;
diff --git a/src/com/android/camera/util/CameraUtil.java b/src/com/android/camera/util/CameraUtil.java
index 1cdfd285a..1dc5e558b 100644
--- a/src/com/android/camera/util/CameraUtil.java
+++ b/src/com/android/camera/util/CameraUtil.java
@@ -842,6 +842,34 @@ public class CameraUtil {
view.setVisibility(View.GONE);
}
+ public static Rect getFinalCropRect(Rect rect, float targetRatio) {
+ Rect finalRect = new Rect(rect);
+ float rectRatio = (float) rect.width()/(float) rect.height();
+
+ // if ratios are different, adjust crop rect to fit ratio
+ // if ratios are same, no need to adjust crop
+ Log.d(TAG, "getFinalCropRect - rect: " + rect.toString());
+ Log.d(TAG, "getFinalCropRect - ratios: " + rectRatio + ", " + targetRatio);
+ if(rectRatio > targetRatio) {
+ // ratio indicates need for horizontal crop
+ // add .5 to round up if necessary
+ int newWidth = (int)(((float)rect.height() * targetRatio) + .5f);
+ int newXoffset = (rect.width() - newWidth)/2 + rect.left;
+ finalRect.left = newXoffset;
+ finalRect.right = newXoffset + newWidth;
+ } else if(rectRatio < targetRatio) {
+ // ratio indicates need for vertical crop
+ // add .5 to round up if necessary
+ int newHeight = (int)(((float)rect.width() / targetRatio) + .5f);
+ int newYoffset = (rect.height() - newHeight)/2 + rect.top;
+ finalRect.top = newYoffset;
+ finalRect.bottom = newYoffset + newHeight;
+ }
+
+ Log.d(TAG, "getFinalCropRect - final rect: " + finalRect.toString());
+ return finalRect;
+ }
+
public static int getJpegRotation(int cameraId, int orientation) {
// See android.hardware.Camera.Parameters.setRotation for
// documentation.