summaryrefslogtreecommitdiffstats
path: root/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java')
-rw-r--r--[-rwxr-xr-x]src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java329
1 files changed, 287 insertions, 42 deletions
diff --git a/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java b/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java
index bfd58db28..8a6e7667f 100755..100644
--- a/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java
+++ b/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -30,6 +30,10 @@
package org.codeaurora.snapcam.filter;
import java.io.ByteArrayOutputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.ArrayDeque;
import java.util.ArrayList;
@@ -38,8 +42,11 @@ import java.util.List;
import org.codeaurora.snapcam.filter.ClearSightNativeEngine.CamSystemCalibrationData;
import org.codeaurora.snapcam.filter.ClearSightNativeEngine.ClearsightImage;
+import org.codeaurora.snapcam.filter.DDMNativeEngine;
import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Color;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
@@ -80,6 +87,7 @@ import com.android.camera.PhotoModule.NamedImages.NamedEntity;
import com.android.camera.Storage;
import com.android.camera.util.CameraUtil;
+
public class ClearSightImageProcessor {
private static final String TAG = "ClearSightImageProcessor";
private static final String PERSIST_TIMESTAMP_LIMIT_KEY = "persist.camera.cs.threshold";
@@ -87,6 +95,7 @@ public class ClearSightImageProcessor {
private static final String PERSIST_DUMP_FRAMES_KEY = "persist.camera.cs.dumpframes";
private static final String PERSIST_DUMP_YUV_KEY = "persist.camera.cs.dumpyuv";
private static final String PERSIST_CS_TIMEOUT_KEY = "persist.camera.cs.timeout";
+ private static final String PERSIST_DUMP_DEPTH_KEY = "persist.camera.cs.dumpdepth";
private static final long DEFAULT_TIMESTAMP_THRESHOLD_MS = 10;
private static final int DEFAULT_IMAGES_TO_BURST = 4;
@@ -106,6 +115,9 @@ public class ClearSightImageProcessor {
private static final int MSG_NEW_REPROC_RESULT = 4;
private static final int MSG_NEW_REPROC_FAIL = 5;
private static final int MSG_END_CAPTURE = 6;
+ private static final int MSG_CALIBRATION_DATA = 7;
+ private static final int MSG_NEW_LENS_FOCUS_DISTANCE_BAYER = 8;
+ private static final int MSG_NEW_DEPTH = 9;
private static final int CAM_TYPE_BAYER = 0;
private static final int CAM_TYPE_MONO = 1;
@@ -115,6 +127,10 @@ public class ClearSightImageProcessor {
new CameraCharacteristics.Key<>(
"org.codeaurora.qcamera3.dualcam_calib_meta_data.dualcam_calib_meta_data_blob",
byte[].class);
+ private CaptureResult.Key<byte[]> SCALE_CROP_ROTATION_REPROCESS_BLOB =
+ new CaptureResult.Key<byte[]>(
+ "org.codeaurora.qcamera3.hal_private_data.reprocess_data_blob",
+ byte[].class);
private NamedImages mNamedImages;
private ImageReader[] mImageReader = new ImageReader[NUM_CAM];
@@ -128,10 +144,13 @@ public class ClearSightImageProcessor {
private ClearsightRegisterHandler mClearsightRegisterHandler;
private ClearsightProcessHandler mClearsightProcessHandler;
private ImageEncodeHandler mImageEncodeHandler;
+ private DepthProcessHandler mDepthProcessHandler;
+
private HandlerThread mImageProcessThread;
private HandlerThread mClearsightRegisterThread;
private HandlerThread mClearsightProcessThread;
private HandlerThread mImageEncodeThread;
+ private HandlerThread mDepthProcessThread;
private Callback mCallback;
private CameraCaptureSession[] mCaptureSessions = new CameraCaptureSession[NUM_CAM];
@@ -144,6 +163,7 @@ public class ClearSightImageProcessor {
private int mCsTimeout;
private boolean mDumpImages;
private boolean mDumpYUV;
+ private boolean mDumpDepth;
private boolean mIsClosing;
private int mFinishReprocessNum;
@@ -167,8 +187,12 @@ public class ClearSightImageProcessor {
mDumpYUV = SystemProperties.getBoolean(PERSIST_DUMP_YUV_KEY, false);
Log.d(TAG, "mDumpYUV: " + mDumpYUV);
+ mDumpDepth = SystemProperties.getBoolean(PERSIST_DUMP_DEPTH_KEY, false);
+ Log.d(TAG, "mDumpDepth: " + mDumpDepth);
+
mCsTimeout = SystemProperties.getInt(PERSIST_CS_TIMEOUT_KEY, DEFAULT_CS_TIMEOUT_MS);
Log.d(TAG, "mCsTimeout: " + mCsTimeout);
+
}
public static void createInstance() {
@@ -197,11 +221,14 @@ public class ClearSightImageProcessor {
mClearsightProcessThread.start();
mImageEncodeThread = new HandlerThread("CameraImageEncode");
mImageEncodeThread.start();
+ mDepthProcessThread = new HandlerThread("DepthProcess");
+ mDepthProcessThread.start();
mImageProcessHandler = new ImageProcessHandler(mImageProcessThread.getLooper());
mClearsightRegisterHandler = new ClearsightRegisterHandler(mClearsightRegisterThread.getLooper());
mClearsightProcessHandler = new ClearsightProcessHandler(mClearsightProcessThread.getLooper());
mImageEncodeHandler = new ImageEncodeHandler(mImageEncodeThread.getLooper());
+ mDepthProcessHandler = new DepthProcessHandler(mImageEncodeThread.getLooper());
mFinalPictureSize = new Size(width, height);
mFinalPictureRatio = (float)width / (float)height;
@@ -219,8 +246,11 @@ public class ClearSightImageProcessor {
try {
CameraCharacteristics cc = cm.getCameraCharacteristics("0");
byte[] blob = cc.get(OTP_CALIB_BLOB);
+ CamSystemCalibrationData calibrationData = CamSystemCalibrationData.createFromBytes(blob);
ClearSightNativeEngine.getInstance().init(mNumFrameCount*2,
- maxWidth, maxHeight, CamSystemCalibrationData.createFromBytes(blob));
+ maxWidth, maxHeight, calibrationData);
+ mDepthProcessHandler.obtainMessage(MSG_CALIBRATION_DATA,0, 0,
+ calibrationData).sendToTarget();
} catch (CameraAccessException e) {
e.printStackTrace();
}
@@ -281,6 +311,17 @@ public class ClearSightImageProcessor {
}
}
+ if ( mDepthProcessThread != null ) {
+ mDepthProcessThread.quit();
+ try{
+ mDepthProcessThread.join();
+ mDepthProcessThread = null;
+ mDepthProcessHandler = null;
+ }catch (InterruptedException e){
+ e.printStackTrace();
+ }
+ }
+
for(int i=0; i<mImageReader.length; i++) {
if (null != mImageReader[i]) {
mImageReader[i].close();
@@ -356,9 +397,16 @@ public class ClearSightImageProcessor {
Log.d(TAG, "capture - onCaptureCompleted: " + cam);
if(isClosing())
Log.d(TAG, "capture - onCaptureCompleted - closing");
- else
+ else {
mImageProcessHandler.obtainMessage(MSG_NEW_CAPTURE_RESULT,
cam, 0, result).sendToTarget();
+ if (cam == CAM_TYPE_BAYER) {
+ float lensFocusDistance = result.get(CaptureResult.LENS_FOCUS_DISTANCE);
+ Log.d(TAG, "lensFocusDistance=" + lensFocusDistance);
+ mDepthProcessHandler.obtainMessage(MSG_NEW_LENS_FOCUS_DISTANCE_BAYER,
+ 0, 0, lensFocusDistance).sendToTarget();
+ }
+ }
}
@Override
@@ -492,6 +540,7 @@ public class ClearSightImageProcessor {
mNamedEntity = mNamedImages.getNextNameEntity();
mClearsightRegisterHandler.obtainMessage(MSG_START_CAPTURE,
0, 0, mNamedEntity).sendToTarget();
+ mDepthProcessHandler.obtainMessage(MSG_START_CAPTURE).sendToTarget();
break;
case MSG_END_CAPTURE:
// TIMED OUT WAITING FOR FRAME
@@ -832,6 +881,8 @@ public class ClearSightImageProcessor {
// reference not yet set
Log.d(TAG, "reprocess - setReferenceResult: " + msg.obj);
ClearSightNativeEngine.getInstance().setReferenceResult(isBayer, result);
+ mDepthProcessHandler.obtainMessage(MSG_NEW_REPROC_RESULT, msg.arg1, 0, msg.obj)
+ .sendToTarget();
}
mFinishReprocessNum++;
checkReprocessDone();
@@ -912,6 +963,7 @@ public class ClearSightImageProcessor {
.hasReferenceImage(isBayer)) {
// reference not yet set
ClearSightNativeEngine.getInstance().setReferenceImage(isBayer, image);
+ mDepthProcessHandler.obtainMessage(MSG_NEW_IMG, msg.arg1, 0, msg.obj).sendToTarget();
} else {
// if ref images set, register this image
if(ClearSightNativeEngine.getInstance().registerImage(
@@ -960,9 +1012,6 @@ public class ClearSightImageProcessor {
ClearSightNativeEngine.getInstance().reset();
if(processInit) {
- if(mCallback != null)
- mCallback.onReleaseShutterLock();
-
Image encodeImage = mImageWriter[CAM_TYPE_BAYER].dequeueInputImage();
ClearSightNativeEngine.ClearsightImage csImage = new ClearsightImage(encodeImage);
encodeImage.setTimestamp(csTs);
@@ -1086,13 +1135,19 @@ public class ClearSightImageProcessor {
private short mEncodeRequest;
private short mEncodeResults;
- private boolean mReadyToSave;
private boolean mHasFailure;
private Image mMonoImage;
private Image mBayerImage;
private Image mClearSightImage;
private NamedEntity mNamedEntity;
+ private GDepth.DepthMap mDepthMap;
+ private GImage mGImage;
+ private boolean mDepthMapReady;
+ private boolean mClearSightReady;
+
+ private long CLEAR_SIGHT_IMAGE_SAVE_DELAY = 1*500;
+
public ImageEncodeHandler(Looper looper) {
super(looper);
}
@@ -1110,15 +1165,19 @@ public class ClearSightImageProcessor {
Log.d(TAG, "ImageEncodeEvent - END_CAPTURE");
mNamedEntity = (NamedEntity) msg.obj;
mEncodeRequest = (short)msg.arg1;
- mReadyToSave = true;
- saveMpoImage();
+ mClearSightReady = true;
+ saveClearSightImage();
break;
case MSG_NEW_IMG:
case MSG_NEW_CAPTURE_RESULT:
case MSG_NEW_CAPTURE_FAIL:
processNewEvent(msg);
- saveMpoImage();
+ saveClearSightImage();
break;
+ case MSG_NEW_DEPTH:
+ processNewGDepth(msg);
+ saveClearSightImage();
+ break;
}
}
@@ -1128,12 +1187,20 @@ public class ClearSightImageProcessor {
if(msg.arg1 == CAM_TYPE_MONO) {
mMonoImage = (Image)msg.obj;
mEncodeResults |= MASK_MONO_ENCODE;
+ if ( mDumpDepth ) {
+ saveToFile(getJpegData(mMonoImage), "mono", "jpg");
+ }
} else if(mBayerImage == null){
mBayerImage = (Image)msg.obj;
mEncodeResults |= MASK_BAYER_ENCODE;
+ mGImage = new GImage(getJpegData(mBayerImage), "image/jpeg");
+ if ( mDumpDepth ) {
+ saveToFile(getJpegData(mBayerImage), "bayer", "jpg");
+ }
} else {
mClearSightImage = (Image)msg.obj;
mEncodeResults |= MASK_CS_ENCODE;
+
}
} else if (msg.what == MSG_NEW_CAPTURE_RESULT) {
Log.d(TAG, "processNewEncodeEvent - newResult: " + msg.arg1);
@@ -1152,63 +1219,69 @@ public class ClearSightImageProcessor {
}
}
- private void saveMpoImage() {
- if(!mReadyToSave || mEncodeRequest != mEncodeResults) {
- Log.d(TAG, "saveMpoImage - not yet ready to save");
+ private void processNewGDepth(Message msg) {
+ mDepthMap = (GDepth.DepthMap)msg.obj;
+ mDepthMapReady = true;
+ }
+
+ private void saveClearSightImage() {
+ if ( !isReadyToSave() || mEncodeRequest != mEncodeResults) {
+ Log.d(TAG, "saveClearSightImage - not yet ready to save");
return;
}
- Log.d(TAG, "saveMpoImage");
if(mHasFailure) {
// don't save anything and fail
- Log.d(TAG, "saveMpoImage has failure - aborting.");
+ Log.d(TAG, "saveClearSightImage has failure - aborting.");
if(mCallback != null) mCallback.onClearSightFailure(null);
resetParams();
return;
}
+ Log.d(TAG, "saveClearSightImage");
+ byte[] clearSightBytes = getJpegData(mClearSightImage);
+
String title = (mNamedEntity == null) ? null : mNamedEntity.title;
long date = (mNamedEntity == null) ? -1 : mNamedEntity.date;
- int width = mBayerImage.getWidth();
- int height = mBayerImage.getHeight();
- if(mClearSightImage != null) {
+ int width = 0;
+ int height = 0;
+ if ( mBayerImage != null ) {
+ mBayerImage.getWidth();
+ mBayerImage.getHeight();
+ }
+ if ( mClearSightImage != null ) {
width = mClearSightImage.getWidth();
height = mClearSightImage.getHeight();
}
- byte[] clearSightBytes = getJpegData(mClearSightImage);
byte[] bayerBytes = getJpegData(mBayerImage);
- byte[] monoBytes = getJpegData(mMonoImage);
- ExifInterface exif = Exif.getExif(bayerBytes);
- int orientation = Exif.getOrientation(exif);
-
- if(clearSightBytes != null) {
- if(mCallback != null) mCallback.onClearSightSuccess(clearSightBytes);
- } else if (bayerBytes != null) {
- if(mCallback != null) mCallback.onClearSightFailure(bayerBytes);
- } else {
- if(mCallback != null) mCallback.onClearSightFailure(null);
- }
+ if ( bayerBytes != null ) {
+ ExifInterface exif = Exif.getExif(bayerBytes);
+ int orientation = Exif.getOrientation(exif);
+
+ if(clearSightBytes != null) {
+ if(mCallback != null) mCallback.onClearSightSuccess(clearSightBytes);
+ } else if (bayerBytes != null) {
+ if(mCallback != null) mCallback.onClearSightFailure(bayerBytes);
+ } else {
+ if(mCallback != null) mCallback.onClearSightFailure(null);
+ }
- if(monoBytes == null) {
- mMediaSaveService.addImage(
- clearSightBytes!=null?clearSightBytes:bayerBytes, title, date, null,
+ mMediaSaveService.addClearsightImage(
+ clearSightBytes != null ? clearSightBytes : bayerBytes,
+ mGImage, mDepthMap,title, date, null,
width, height, orientation, exif,
mMediaSavedListener,
mMediaSaveService.getContentResolver(), "jpeg");
- } else if (bayerBytes != null) {
- mMediaSaveService.addMpoImage(
- clearSightBytes,
- bayerBytes,
- monoBytes, width, height, title,
- date, null, orientation, mMediaSavedListener,
- mMediaSaveService.getContentResolver(), "jpeg");
}
-
resetParams();
}
+ private boolean isReadyToSave() {
+ return (mDepthMapReady &&mClearSightReady);
+ }
+
void resetParams() {
if(mBayerImage != null) {
mBayerImage.close();
@@ -1223,10 +1296,182 @@ public class ClearSightImageProcessor {
mClearSightImage = null;
}
mNamedEntity = null;
- mReadyToSave = false;
mHasFailure = false;
mEncodeRequest = 0;
mEncodeResults = 0;
+ mGImage = null;
+ mDepthMapReady = false;
+ mClearSightReady = false;
+ }
+ }
+
+ private class DepthProcessHandler extends Handler{
+ private TotalCaptureResult mReprocessCaptureResult;
+ private DDMNativeEngine mDDMNativeEngine;
+ public DepthProcessHandler(Looper looper) {
+ super(looper);
+ mDDMNativeEngine = new DDMNativeEngine();
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch( msg.what ) {
+ case MSG_CALIBRATION_DATA:
+ setCalibrationdata(msg);
+ break;
+
+ case MSG_NEW_LENS_FOCUS_DISTANCE_BAYER:
+ setBayerLensFocusDistance(msg);
+ break;
+
+ case MSG_START_CAPTURE:
+ resetParams();
+ break;
+
+ case MSG_NEW_IMG:
+ registerImage(msg);
+ break;
+
+ case MSG_NEW_REPROC_RESULT:
+ registerReprocessResult(msg);
+ break;
+ }
+ }
+
+ private void setCalibrationdata(Message msg) {
+ mDDMNativeEngine.setCamSystemCalibrationData((CamSystemCalibrationData)msg.obj);
+ }
+ private void resetParams(){
+ Log.d(TAG, "resetParams");
+ mDDMNativeEngine.reset();
+ }
+
+ private void setBayerLensFocusDistance(Message msg) {
+ mDDMNativeEngine.setBayerLensFocusDistance((float)msg.obj);
+ }
+
+ private void registerImage(Message msg) {
+ boolean isBayer = (msg.arg1 == CAM_TYPE_BAYER);
+ Image image = (Image) msg.obj;
+ if ( isBayer ) {
+ mDDMNativeEngine.setBayerImage(image);
+ }else{
+ mDDMNativeEngine.setMonoImage(image);
+ }
+
+ if ( mDDMNativeEngine.isReadyForGenerateDepth() ) {
+ generateDepthmap();
+ }
+ }
+
+ private void registerReprocessResult(Message msg) {
+
+ boolean isBayer = (msg.arg1 == CAM_TYPE_BAYER);
+ Log.d(TAG, "registerReprocessResult bayer=" + isBayer);
+ TotalCaptureResult result = (TotalCaptureResult)msg.obj;
+ if ( isBayer ) {
+ mDDMNativeEngine.setBayerReprocessResult(result);
+ }else{
+ mDDMNativeEngine.setMonoReprocessResult(result);
+ }
+
+ if ( mDDMNativeEngine.isReadyForGenerateDepth() ) {
+ generateDepthmap();
+ }
+
+ }
+
+ private void generateDepthmap() {
+ GDepth.DepthMap depthMap = null;
+ int[] size = new int[2];
+ if ( mDDMNativeEngine.getDepthMapSize(size) ) {
+ int width = size[0];
+ int height = size[1];
+ Bitmap bmp = Bitmap.createBitmap(width, height,
+ Bitmap.Config.ALPHA_8);
+ int stride = bmp.getRowBytes();
+ byte[] depthBuffer = new byte[stride*height];
+ Log.d(TAG, "depthMapWidth=" + width + " depthMapHeight="
+ + height + " stride=" + stride);
+ Rect roiRect = new Rect();
+
+ if ( mDDMNativeEngine.dualCameraGenerateDDM(depthBuffer, stride, roiRect) ) {
+ if ( mDumpDepth ) {
+ saveAsRGB(depthBuffer, width, height);
+ }
+ depthMap = new GDepth.DepthMap(width, height);
+ depthMap.roi = roiRect;
+ depthMap.rawDepth = depthBuffer;
+ }else{
+ Log.e(TAG, "dualCameraGenerateDDM failure");
+ }
+ }else{
+ Log.e(TAG, "getDepthMapSize failure");
+ }
+ if ( mDumpDepth ) {
+ dumpCameraParam();
+ }
+ mImageEncodeHandler.obtainMessage(MSG_NEW_DEPTH, 0, 0, depthMap).sendToTarget();
+ }
+
+ private void dumpCameraParam() {
+ saveToFile(mDDMNativeEngine.getOTPCalibration().getBytes(), "OTPdata", "txt");
+ saveToFile(mDDMNativeEngine.getBayerScaleCrop().getBytes(), "BayerScaleCrop", "txt");
+ saveToFile(mDDMNativeEngine.getMonoScaleCrop().getBytes(), "MonoScaleCrop", "txt");
+ }
+ }
+
+ private void saveAsRGB(byte[] depth, int width, int height) {
+ int[] colors = new int[depth.length];
+ for(int i=0; i < colors.length; ++i) {
+ colors[i] = (256+depth[i])%256;
+ }
+
+ Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ for( int y=0; y < height; ++y ) {
+ for( int x=0; x < width; ++x) {
+ int c = colors[y*width+x];
+ bitmap.setPixel(x, y, Color.rgb(c, c, c));
+ }
+ }
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
+ File file = new File("sdcard/depthmap_rgb.jpg");
+ byte[] jpeg = baos.toByteArray();
+ Log.d(TAG, "jpeg.size=" + jpeg.length);
+ OutputStream out = null;
+ try {
+ out = new BufferedOutputStream(new FileOutputStream(file));
+ out.write(jpeg, 0, jpeg.length);
+ }catch(Exception e) {
+ Log.d(TAG, e.toString());
+ }finally {
+ if (out != null) {
+ try {
+ out.close();
+ }catch(Exception e){
+ Log.d(TAG, e.toString());
+ }
+ }
+ }
+ }
+
+ private void saveToFile(byte[] bytes, String name, String format){
+ File file = new File("sdcard/"+ name + "." + format);
+ OutputStream out = null;
+ try {
+ out = new BufferedOutputStream(new FileOutputStream(file));
+ out.write(bytes, 0, bytes.length);
+ }catch(Exception e) {
+ Log.d(TAG, e.toString());
+ }finally {
+ if (out != null) {
+ try {
+ out.close();
+ }catch(Exception e){
+ Log.d(TAG, e.toString());
+ }
+ }
}
}