summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJay Wang <jaywang@codeaurora.org>2016-05-09 18:35:53 -0700
committerSteve Kondik <steve@cyngn.com>2016-08-21 18:45:51 -0700
commit1fea7d5bb3dd45caf29e90be2e9eae2646567a10 (patch)
treebd3059bba91264f649251456ce06789e38667818 /src
parent67f8bccf87818e7ea124fa733c56894030ee5951 (diff)
downloadandroid_packages_apps_Snap-1fea7d5bb3dd45caf29e90be2e9eae2646567a10.tar.gz
android_packages_apps_Snap-1fea7d5bb3dd45caf29e90be2e9eae2646567a10.tar.bz2
android_packages_apps_Snap-1fea7d5bb3dd45caf29e90be2e9eae2646567a10.zip
SnapdragonCamera: Enable jpeg encoding via reprocess
Enable JPEG encoding via reprocess request for ClearSight routine. Add support for dumping images in NV21 format using persist.camera.cs.dumpyuv CRs-Fixed: 993611 Change-Id: I51ff59ec45bb37059a16197186a9f90bc52554f1
Diffstat (limited to 'src')
-rw-r--r--src/com/android/camera/CaptureModule.java55
-rw-r--r--src/com/android/camera/MediaSaveService.java59
-rw-r--r--src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java418
-rw-r--r--src/org/codeaurora/snapcam/filter/ClearSightNativeEngine.java66
4 files changed, 387 insertions, 211 deletions
diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java
index 6bb16950f..90e1794ac 100644
--- a/src/com/android/camera/CaptureModule.java
+++ b/src/com/android/camera/CaptureModule.java
@@ -750,12 +750,11 @@ public class CaptureModule implements CameraModule, PhotoController,
} else {
// No Clearsight
captureBuilder = mCameraDevice[id].createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
-
- // Orientation
- int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
- captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
}
+ // Orientation
+ int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
+ captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
captureBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
captureBuilder.addTarget(getPreviewSurface(id));
captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, mControlAFMode);
@@ -855,7 +854,8 @@ public class CaptureModule implements CameraModule, PhotoController,
Size largest = Collections.max(
Arrays.asList(map.getOutputSizes(ImageFormat.YUV_420_888)),
new CompareSizesByArea());
- ClearSightImageProcessor.getInstance().init(largest.getWidth(), largest.getHeight(), mActivity);
+ ClearSightImageProcessor.getInstance().init(
+ largest.getWidth(), largest.getHeight(), mActivity, mOnMediaSavedListener);
ClearSightImageProcessor.getInstance().setCallback(this);
} else {
// No Clearsight
@@ -1345,6 +1345,10 @@ public class CaptureModule implements CameraModule, PhotoController,
public void onMediaSaveServiceConnected(MediaSaveService s) {
if (mFirstTimeInitialized) {
s.setListener(this);
+ ListPreference pref = mPreferenceGroup.findPreference(CameraSettings.KEY_CLEARSIGHT);
+ if(pref.getValue().equals(mActivity.getString(R.string.pref_camera_clearsight_value_on))) {
+ ClearSightImageProcessor.getInstance().setMediaSaveService(s);
+ }
}
}
@@ -1655,18 +1659,8 @@ public class CaptureModule implements CameraModule, PhotoController,
}
@Override
- public void onClearSightSuccess(ClearsightImage csImage, YuvImage bayer, YuvImage mono) {
- Log.d(TAG, "reprocess - processClearSight success");
- mNamedImages.nameNewImage(System.currentTimeMillis());
- NamedEntity name = mNamedImages.getNextNameEntity();
- String title = (name == null) ? null : name.title;
- long date = (name == null) ? -1 : name.date;
-
- mActivity.getMediaSaveService().addMpoImage(
- csImage, bayer, mono, null, null, title,
- date, null, 0, mOnMediaSavedListener, mContentResolver,
- "jpeg");
-
+ public void onClearSightSuccess() {
+ Log.d(TAG, "onClearSightSuccess");
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
@@ -1680,21 +1674,8 @@ public class CaptureModule implements CameraModule, PhotoController,
}
@Override
- public void onClearSightFailure(YuvImage bayer, YuvImage mono) {
- if(bayer != null && mono != null) {
- Log.d(TAG, "reprocess - processClearSight fail");
- mNamedImages.nameNewImage(System.currentTimeMillis());
- NamedEntity name = mNamedImages.getNextNameEntity();
- String title = (name == null) ? null : name.title;
- long date = (name == null) ? -1 : name.date;
-
- Log.d(TAG, "reprocess - saving with bayer + mono mpo");
-
- mActivity.getMediaSaveService().addMpoImage(null,
- bayer, mono, null, null, title, date, null, 0,
- mOnMediaSavedListener, mContentResolver, "jpeg");
- }
-
+ public void onClearSightFailure() {
+ Log.d(TAG, "onClearSightFailure");
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
@@ -1706,14 +1687,4 @@ public class CaptureModule implements CameraModule, PhotoController,
unlockFocus(BAYER_ID);
unlockFocus(MONO_ID);
}
-
- @Override
- public CameraCaptureSession onReprocess(boolean bayer) {
- return mCaptureSession[bayer?BAYER_ID:MONO_ID];
- }
-
- @Override
- public MediaSaveService getMediaSaveService() {
- return mActivity.getMediaSaveService();
- }
}
diff --git a/src/com/android/camera/MediaSaveService.java b/src/com/android/camera/MediaSaveService.java
index 3c5dbe586..58ebc11b4 100644
--- a/src/com/android/camera/MediaSaveService.java
+++ b/src/com/android/camera/MediaSaveService.java
@@ -16,7 +16,6 @@
package com.android.camera;
-import java.io.ByteArrayOutputStream;
import java.io.File;
import java.nio.ByteOrder;
@@ -25,9 +24,6 @@ import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.graphics.BitmapFactory;
-import android.graphics.Rect;
-import android.graphics.YuvImage;
-import android.hardware.camera2.TotalCaptureResult;
import android.location.Location;
import android.net.Uri;
import android.os.AsyncTask;
@@ -36,13 +32,7 @@ import android.os.IBinder;
import android.provider.MediaStore.Video;
import android.util.Log;
-import com.android.camera.PhotoModule;
import com.android.camera.exif.ExifInterface;
-
-import java.io.File;
-
-import org.codeaurora.snapcam.filter.ClearSightNativeEngine.ClearsightImage;
-
import com.android.camera.mpo.MpoData;
import com.android.camera.mpo.MpoImageData;
import com.android.camera.mpo.MpoInterface;
@@ -99,9 +89,9 @@ public class MediaSaveService extends Service {
return (mMemoryUse >= SAVE_TASK_MEMORY_LIMIT);
}
- public void addMpoImage(final ClearsightImage csImage,
- final YuvImage bayerImg, final YuvImage monoImg,
- TotalCaptureResult bayerResult, TotalCaptureResult monoResult,
+ public void addMpoImage(final byte[] csImage,
+ final byte[] bayerImg, final byte[] monoImg,
+ int width, int height,
String title, long date, Location loc, int orientation,
OnMediaSavedListener l, ContentResolver resolver,
String pictureFormat) {
@@ -111,12 +101,12 @@ public class MediaSaveService extends Service {
}
MpoSaveTask t = new MpoSaveTask(csImage, bayerImg, monoImg,
- bayerResult, monoResult, title, date, loc, orientation, l,
+ width, height, title, date, loc, orientation, l,
resolver, pictureFormat);
long size = (csImage == null ? 0
- : csImage.getDataLength())
- + bayerImg.getYuvData().length + monoImg.getYuvData().length;
+ : csImage.length)
+ + bayerImg.length + monoImg.length;
mMemoryUse += size;
if (isQueueFull()) {
onQueueFull();
@@ -179,23 +169,20 @@ public class MediaSaveService extends Service {
}
private class MpoSaveTask extends AsyncTask<Void, Void, Uri> {
- private ClearsightImage csImage;
- private YuvImage bayerImage;
- private YuvImage monoImage;
+ private byte[] csImage;
+ private byte[] bayerImage;
+ private byte[] monoImage;
private String title;
private long date;
private Location loc;
private int width, height;
private int orientation;
- private TotalCaptureResult bayerResult;
- private TotalCaptureResult monoResult;
private ContentResolver resolver;
private OnMediaSavedListener listener;
private String pictureFormat;
- public MpoSaveTask(ClearsightImage csImage, YuvImage bayerImg,
- YuvImage monoImg, TotalCaptureResult bayerResult,
- TotalCaptureResult monoResult, String title, long date,
+ public MpoSaveTask(byte[] csImage, byte[] bayerImg,
+ byte[] monoImg, int width, int height, String title, long date,
Location loc, int orientation, OnMediaSavedListener listener,
ContentResolver resolver, String pictureFormat) {
this.csImage = csImage;
@@ -204,11 +191,9 @@ public class MediaSaveService extends Service {
this.title = title;
this.date = date;
this.loc = loc;
- this.width = bayerImg.getWidth();
- this.height = bayerImg.getHeight();
+ this.width = width;
+ this.height = height;
this.orientation = orientation;
- this.bayerResult = bayerResult;
- this.monoResult = monoResult;
this.resolver = resolver;
this.listener = listener;
this.pictureFormat = pictureFormat;
@@ -218,23 +203,17 @@ public class MediaSaveService extends Service {
protected Uri doInBackground(Void... v) {
// encode jpeg and add exif for all images
MpoData mpo = new MpoData();
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- bayerImage.compressToJpeg(new Rect(0, 0, bayerImage.getWidth(),
- bayerImage.getHeight()), 100, baos);
- MpoImageData bayer = new MpoImageData(baos.toByteArray(),
+ MpoImageData bayer = new MpoImageData(bayerImage,
ByteOrder.BIG_ENDIAN);
- baos.reset();
- monoImage.compressToJpeg(new Rect(0, 0, monoImage.getWidth(),
- monoImage.getHeight()), 100, baos);
- MpoImageData mono = new MpoImageData(baos.toByteArray(),
+ MpoImageData mono = new MpoImageData(monoImage,
ByteOrder.BIG_ENDIAN);
if (csImage == null) {
mpo.addAuxiliaryMpoImage(mono);
mpo.setPrimaryMpoImage(bayer);
} else {
- MpoImageData cs = new MpoImageData(csImage.compressToJpeg(),
+ MpoImageData cs = new MpoImageData(csImage,
ByteOrder.BIG_ENDIAN);
mpo.addAuxiliaryMpoImage(bayer);
@@ -260,9 +239,9 @@ public class MediaSaveService extends Service {
listener.onMediaSaved(uri);
boolean previouslyFull = isQueueFull();
long size = (csImage == null ? 0
- : csImage.getDataLength())
- + bayerImage.getYuvData().length
- + monoImage.getYuvData().length;
+ : csImage.length)
+ + bayerImage.length
+ + monoImage.length;
mMemoryUse -= size;
if (isQueueFull() != previouslyFull)
onQueueAvailable();
diff --git a/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java b/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java
index 141d8e412..c33726322 100644
--- a/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java
+++ b/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java
@@ -30,13 +30,13 @@
package org.codeaurora.snapcam.filter;
import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.nio.ByteBuffer;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import org.codeaurora.snapcam.filter.ClearSightNativeEngine.CamSystemCalibrationData;
-import org.codeaurora.snapcam.filter.ClearSightNativeEngine.ClearsightImage;
import android.content.Context;
import android.graphics.ImageFormat;
@@ -66,14 +66,18 @@ import android.util.Log;
import android.view.Surface;
import com.android.camera.MediaSaveService;
+import com.android.camera.MediaSaveService.OnMediaSavedListener;
import com.android.camera.PhotoModule.NamedImages;
import com.android.camera.PhotoModule.NamedImages.NamedEntity;
+import com.android.camera.SDCard;
+import com.android.camera.Storage;
public class ClearSightImageProcessor {
private static final String TAG = "ClearSightImageProcessor";
private static final String PERSIST_TIMESTAMP_LIMIT_KEY = "persist.camera.cs.threshold";
private static final String PERSIST_BURST_COUNT_KEY = "persist.camera.cs.burstcount";
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 long DEFAULT_TIMESTAMP_THRESHOLD_MS = 10;
private static final int DEFAULT_IMAGES_TO_BURST = 5;
@@ -93,18 +97,23 @@ public class ClearSightImageProcessor {
private NamedImages mNamedImages;
private ImageReader[] mImageReader = new ImageReader[NUM_CAM];
- private ImageReader[] mReprocessImageReader = new ImageReader[NUM_CAM];
+ private ImageReader[] mEncodeImageReader = new ImageReader[NUM_CAM];
private ImageWriter[] mImageWriter = new ImageWriter[NUM_CAM];
private ImageProcessHandler mImageProcessHandler;
- private ImageReprocessHandler mImageReprocessHandler;
+ private ImageEncodeHandler mImageEncodeHandler;
private HandlerThread mImageProcessThread;
- private HandlerThread mImageReprocessThread;
+ private HandlerThread mImageEncodeThread;
private Callback mCallback;
+ private CameraCaptureSession[] mCaptureSessions = new CameraCaptureSession[NUM_CAM];
+ private MediaSaveService mMediaSaveService;
+ private OnMediaSavedListener mMediaSavedListener;
+
private long mTimestampThresholdNs;
private int mNumBurstCount;
private boolean mDumpImages;
+ private boolean mDumpYUV;
private static ClearSightImageProcessor mInstance;
@@ -119,6 +128,9 @@ public class ClearSightImageProcessor {
mDumpImages = SystemProperties.getBoolean(PERSIST_DUMP_FRAMES_KEY, false);
Log.d(TAG, "mDumpImages: " + mDumpImages);
+
+ mDumpYUV = SystemProperties.getBoolean(PERSIST_DUMP_YUV_KEY, false);
+ Log.d(TAG, "mDumpYUV: " + mDumpYUV);
}
public static void createInstance() {
@@ -135,20 +147,21 @@ public class ClearSightImageProcessor {
return mInstance;
}
- public void init(int width, int height, Context context) {
+ public void init(int width, int height, Context context, OnMediaSavedListener mediaListener) {
mImageProcessThread = new HandlerThread("CameraImageProcess");
mImageProcessThread.start();
- mImageReprocessThread = new HandlerThread("CameraImageReprocess");
- mImageReprocessThread.start();
+ mImageEncodeThread = new HandlerThread("CameraImageEncode");
+ mImageEncodeThread.start();
mImageProcessHandler = new ImageProcessHandler(mImageProcessThread.getLooper());
- mImageReprocessHandler = new ImageReprocessHandler(mImageReprocessThread.getLooper());
+ mImageEncodeHandler = new ImageEncodeHandler(mImageEncodeThread.getLooper());
mImageReader[CAM_TYPE_BAYER] = createImageReader(CAM_TYPE_BAYER, width, height);
mImageReader[CAM_TYPE_MONO] = createImageReader(CAM_TYPE_MONO, width, height);
- mReprocessImageReader[CAM_TYPE_BAYER] = createReprocImageReader(CAM_TYPE_BAYER, width, height);
- mReprocessImageReader[CAM_TYPE_MONO] = createReprocImageReader(CAM_TYPE_MONO, width, height);
+ mEncodeImageReader[CAM_TYPE_BAYER] = createEncodeImageReader(CAM_TYPE_BAYER, width, height);
+ mEncodeImageReader[CAM_TYPE_MONO] = createEncodeImageReader(CAM_TYPE_MONO, width, height);
+ mMediaSavedListener = mediaListener;
CameraManager cm = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
try {
CameraCharacteristics cc = cm.getCameraCharacteristics("0");
@@ -165,9 +178,9 @@ public class ClearSightImageProcessor {
mImageReader[i].close();
mImageReader[i] = null;
}
- if (null != mReprocessImageReader[i]) {
- mReprocessImageReader[i].close();
- mReprocessImageReader[i] = null;
+ if (null != mEncodeImageReader[i]) {
+ mEncodeImageReader[i].close();
+ mEncodeImageReader[i] = null;
}
if (null != mImageWriter[i]) {
mImageWriter[i].close();
@@ -187,23 +200,20 @@ public class ClearSightImageProcessor {
}
}
- if(mImageReprocessThread != null) {
- mImageReprocessThread.quitSafely();
-
- try {
- mImageReprocessThread.join();
- mImageReprocessThread = null;
- mImageReprocessHandler = null;
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
+ mCaptureSessions[CAM_TYPE_MONO] = null;
+ mCaptureSessions[CAM_TYPE_BAYER] = null;
+ mMediaSaveService = null;
+ mMediaSavedListener = null;
}
public void setCallback(Callback callback) {
mCallback = callback;
}
+ public void setMediaSaveService(MediaSaveService service) {
+ mMediaSaveService = service;
+ }
+
public void createCaptureSession(boolean bayer, CameraDevice device, List<Surface> surfaces,
CameraCaptureSession.StateCallback captureSessionCallback) throws CameraAccessException {
@@ -211,7 +221,7 @@ public class ClearSightImageProcessor {
int cam = bayer?CAM_TYPE_BAYER:CAM_TYPE_MONO;
surfaces.add(mImageReader[cam].getSurface());
- surfaces.add(mReprocessImageReader[cam].getSurface());
+ surfaces.add(mEncodeImageReader[cam].getSurface());
// Here, we create a CameraCaptureSession for camera preview.
device.createReprocessableCaptureSession(
new InputConfiguration(mImageReader[cam].getWidth(),
@@ -222,6 +232,7 @@ public class ClearSightImageProcessor {
public void onCaptureSessionConfigured(boolean bayer, CameraCaptureSession session) {
Log.d(TAG, "onCaptureSessionConfigured: " + bayer);
+ mCaptureSessions[bayer?CAM_TYPE_BAYER:CAM_TYPE_MONO] = session;
mImageWriter[bayer?CAM_TYPE_BAYER:CAM_TYPE_MONO] =
ImageWriter.newInstance(session.getInputSurface(), mNumBurstCount);
}
@@ -230,9 +241,6 @@ public class ClearSightImageProcessor {
Log.d(TAG, "createCaptureRequest");
CaptureRequest.Builder builder = device.createCaptureRequest(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG);
- // Orientation
- // int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
- // captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
return builder;
}
@@ -276,7 +284,7 @@ public class ClearSightImageProcessor {
burstList.add(request);
}
- mImageProcessHandler.obtainMessage(MSG_START_CAPTURE, cam, burstList.size()).sendToTarget();
+ mImageProcessHandler.obtainMessage(MSG_START_CAPTURE, cam, burstList.size(), ProcessState.CAPTURE).sendToTarget();
session.captureBurst(burstList, captureCallback, captureCallbackHandler);
}
@@ -295,14 +303,14 @@ public class ClearSightImageProcessor {
return reader;
}
- private ImageReader createReprocImageReader(final int cam, int width, int height) {
+ private ImageReader createEncodeImageReader(final int cam, int width, int height) {
ImageReader reader = ImageReader.newInstance(width, height,
- ImageFormat.YUV_420_888, mNumBurstCount);
+ ImageFormat.JPEG, mNumBurstCount);
reader.setOnImageAvailableListener(new OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
- Log.d(TAG, "reprocessed image available for cam: " + cam);
- mImageReprocessHandler.obtainMessage(
+ Log.d(TAG, "jpeg image available for cam: " + cam);
+ mImageEncodeHandler.obtainMessage(
MSG_NEW_IMG, cam, 0, reader.acquireNextImage()).sendToTarget();
}
}, null);
@@ -311,10 +319,8 @@ public class ClearSightImageProcessor {
}
public interface Callback {
- public void onClearSightSuccess(ClearsightImage csImage, YuvImage bayer, YuvImage mono);
- public void onClearSightFailure(YuvImage bayer, YuvImage mono);
- public CameraCaptureSession onReprocess(boolean bayer);
- public MediaSaveService getMediaSaveService();
+ public void onClearSightSuccess();
+ public void onClearSightFailure();
}
private static class ReprocessableImage {
@@ -327,6 +333,12 @@ public class ClearSightImageProcessor {
}
}
+ private enum ProcessState {
+ IDLE,
+ CAPTURE,
+ REPROCESS
+ };
+
private class ImageProcessHandler extends Handler {
private ArrayDeque<ReprocessableImage> mBayerFrames = new ArrayDeque<ReprocessableImage>(
mNumBurstCount);
@@ -340,9 +352,11 @@ public class ClearSightImageProcessor {
mNumBurstCount);
private ArrayDeque<Image> mMonoImages = new ArrayDeque<Image>(
mNumBurstCount);
+ private ReprocessableImage mClearSightFrame;
private int[] mNumImagesToProcess = new int[NUM_CAM];
+ private ProcessState mState = ProcessState.IDLE;
- public ImageProcessHandler(Looper looper) {
+ ImageProcessHandler(Looper looper) {
super(looper);
}
@@ -351,27 +365,31 @@ public class ClearSightImageProcessor {
switch (msg.what) {
case MSG_START_CAPTURE:
mNumImagesToProcess[msg.arg1] = msg.arg2;
+ mState = (ProcessState)msg.obj;
break;
case MSG_NEW_IMG:
case MSG_NEW_RESULT:
- processNewEvent(msg);
+ if(mState == ProcessState.CAPTURE)
+ processNewCaptureEvent(msg);
+ else
+ processNewReprocessEvent(msg);
break;
}
}
- private void processNewEvent(Message msg) {
+ private void processNewCaptureEvent(Message msg) {
ArrayDeque<Image> imageQueue;
ArrayDeque<TotalCaptureResult> resultQueue;
- ArrayDeque<ReprocessableImage> reprocQueue;
+ ArrayDeque<ReprocessableImage> frameQueue;
// push image onto queue
if (msg.arg1 == CAM_TYPE_BAYER) {
imageQueue = mBayerImages;
resultQueue = mBayerCaptureResults;
- reprocQueue = mBayerFrames;
+ frameQueue = mBayerFrames;
} else {
imageQueue = mMonoImages;
resultQueue = mMonoCaptureResults;
- reprocQueue = mMonoFrames;
+ frameQueue = mMonoFrames;
}
if(msg.what == MSG_NEW_IMG) {
@@ -393,7 +411,7 @@ public class ClearSightImageProcessor {
if (!imageQueue.isEmpty() && !resultQueue.isEmpty()) {
Image headImage = imageQueue.poll();
TotalCaptureResult headResult = resultQueue.poll();
- reprocQueue.add(new ReprocessableImage(headImage, headResult));
+ frameQueue.add(new ReprocessableImage(headImage, headResult));
mNumImagesToProcess[msg.arg1]--;
checkForValidFramePair();
}
@@ -470,7 +488,7 @@ public class ClearSightImageProcessor {
Log.d(TAG, "processReprocess - frames are empty");
releaseBayerFrames();
releaseMonoFrames();
- mCallback.onClearSightFailure(null, null);
+ mCallback.onClearSightFailure();
return;
} else {
int frameCount = Math.min(mMonoFrames.size(), mBayerFrames.size());
@@ -484,7 +502,7 @@ public class ClearSightImageProcessor {
}
private void sendReprocessRequests(final int camId, int frameCount) {
- CameraCaptureSession session = mCallback.onReprocess(camId == CAM_TYPE_BAYER);
+ CameraCaptureSession session = mCaptureSessions[camId];
CameraDevice device = session.getDevice();
try {
@@ -505,8 +523,11 @@ public class ClearSightImageProcessor {
CaptureRequest.Builder reprocRequest = device
.createReprocessCaptureRequest(reprocImg.mCaptureResult);
- reprocRequest.addTarget(mReprocessImageReader[camId]
+ reprocRequest.addTarget(mImageReader[camId]
.getSurface());
+ if(reprocRequests.size() == 0) {
+ reprocRequest.setTag(new Object());
+ }
reprocRequests.add(reprocRequest.build());
mImageWriter[camId].queueInputImage(reprocImg.mImage);
@@ -521,8 +542,8 @@ public class ClearSightImageProcessor {
}
}
- mImageReprocessHandler.obtainMessage(MSG_START_CAPTURE, camId,
- reprocRequests.size()).sendToTarget();
+ mImageProcessHandler.obtainMessage(MSG_START_CAPTURE, camId,
+ reprocRequests.size(), ProcessState.REPROCESS).sendToTarget();
session.captureBurst(reprocRequests,
new CaptureCallback() {
@Override
@@ -533,6 +554,11 @@ public class ClearSightImageProcessor {
super.onCaptureCompleted(session, request, result);
Log.d(TAG, "reprocess - onCaptureCompleted: "
+ camId);
+ if(request.getTag() != null) {
+ mImageProcessHandler.obtainMessage(
+ MSG_NEW_RESULT, camId, 0, result)
+ .sendToTarget();
+ }
}
@Override
@@ -543,7 +569,7 @@ public class ClearSightImageProcessor {
super.onCaptureFailed(session, request, failure);
Log.d(TAG, "reprocess - onCaptureFailed: "
+ camId);
- mImageReprocessHandler.obtainMessage(
+ mImageProcessHandler.obtainMessage(
MSG_NEW_RESULT, camId, 1)
.sendToTarget();
}
@@ -552,29 +578,8 @@ public class ClearSightImageProcessor {
e.printStackTrace();
}
}
- };
-
- private class ImageReprocessHandler extends Handler {
- private int[] mNumImagesToProcess = new int[NUM_CAM];
-
- public ImageReprocessHandler(Looper looper) {
- super(looper);
- }
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_START_CAPTURE:
- mNumImagesToProcess[msg.arg1] = msg.arg2;
- break;
- case MSG_NEW_IMG:
- case MSG_NEW_RESULT:
- processNewEvent(msg);
- break;
- }
- }
-
- private void processNewEvent(Message msg) {
+ private void processNewReprocessEvent(Message msg) {
boolean isBayer = (msg.arg1 == CAM_TYPE_BAYER);
if(msg.what == MSG_NEW_IMG) {
@@ -582,7 +587,10 @@ public class ClearSightImageProcessor {
Log.d(TAG, "reprocess - processNewImg");
if(mDumpImages) {
- saveDebugImage(mCallback.getMediaSaveService(), image, true);
+ saveDebugImageAsJpeg(mMediaSaveService, image, isBayer);
+ if(mDumpYUV) {
+ saveDebugImageAsNV21(image, isBayer);
+ }
}
if (!ClearSightNativeEngine.getInstance()
@@ -601,13 +609,24 @@ public class ClearSightImageProcessor {
} else if (msg.arg2 == 1) {
// capture failed
mNumImagesToProcess[msg.arg1]--;
+ } else {
+ Log.d(TAG, "reprocess - processNewResult: " + msg.arg1);
+ if (ClearSightNativeEngine.getInstance()
+ .getReferenceResult(isBayer) == null) {
+ // reference not yet set
+ Log.d(TAG, "reprocess - setReferenceResult: " + msg.obj);
+ ClearSightNativeEngine.getInstance().setReferenceResult(isBayer,
+ (TotalCaptureResult)msg.obj);
+ }
}
Log.d(TAG, "reprocess - processNewEvent, cam: " + msg.arg1
+ " count: " + mNumImagesToProcess[msg.arg1]);
if (mNumImagesToProcess[CAM_TYPE_BAYER] == 0
- && mNumImagesToProcess[CAM_TYPE_MONO] == 0) {
+ && mNumImagesToProcess[CAM_TYPE_MONO] == 0
+ && ClearSightNativeEngine.getInstance().getReferenceResult(true) != null
+ && ClearSightNativeEngine.getInstance().getReferenceResult(false) != null) {
processClearSight();
}
}
@@ -617,35 +636,197 @@ public class ClearSightImageProcessor {
+ mNumImagesToProcess[CAM_TYPE_BAYER] + " mono count: "
+ mNumImagesToProcess[CAM_TYPE_MONO]);
- if(mCallback != null) {
- ClearSightNativeEngine.ClearsightImage csImage = ClearSightNativeEngine
- .getInstance().processImage();
-
- if(csImage != null) {
- Log.d(TAG, "reprocess - processClearSight, roiRect: "
- + csImage.getRoiRect().toString());
- mCallback.onClearSightSuccess(csImage,
- createYuvImage(ClearSightNativeEngine.getInstance().getReferenceImage(true)),
- createYuvImage(ClearSightNativeEngine.getInstance().getReferenceImage(false)));
- } else {
- mCallback.onClearSightFailure(
- createYuvImage(ClearSightNativeEngine.getInstance().getReferenceImage(true)),
- createYuvImage(ClearSightNativeEngine.getInstance().getReferenceImage(false)));
- }
+ ClearSightNativeEngine.ClearsightImage csImage = ClearSightNativeEngine
+ .getInstance().processImage();
+
+ if(csImage != null) {
+ Log.d(TAG, "reprocess - processClearSight, roiRect: "
+ + csImage.getRoiRect().toString());
+
+ Image encodeImage = mImageWriter[CAM_TYPE_BAYER].dequeueInputImage();
+ encodeImage.setCropRect(csImage.getRoiRect());
+ encodeImage.setTimestamp(
+ ClearSightNativeEngine.getInstance().getReferenceImage(true).getTimestamp());
+ Plane[] planes = encodeImage.getPlanes();
+ planes[0].getBuffer().put(csImage.mYplane);
+ planes[2].getBuffer().put(csImage.mVUplane);
+
+ mClearSightFrame = new ReprocessableImage(encodeImage,
+ ClearSightNativeEngine.getInstance().getReferenceResult(true));
+ if(mCallback != null)
+ mCallback.onClearSightSuccess();
+ } else {
+ mClearSightFrame = null;
+ if(mCallback != null)
+ mCallback.onClearSightFailure();
}
+ sendEncodeRequests();
ClearSightNativeEngine.getInstance().reset();
+ mClearSightFrame = null;
+ mState = ProcessState.IDLE;
+ }
+
+ private void sendEncodeRequests() {
+ mImageEncodeHandler.obtainMessage(
+ MSG_START_CAPTURE, (mClearSightFrame != null)?1:0, 0).sendToTarget();
+
+ // First Mono
+ CameraCaptureSession session = mCaptureSessions[CAM_TYPE_MONO];
+ sendReprocessRequest(session,
+ new ReprocessableImage(
+ ClearSightNativeEngine.getInstance().getReferenceImage(false),
+ ClearSightNativeEngine.getInstance().getReferenceResult(false)),
+ CAM_TYPE_MONO);
+
+ // bayer
+ session = mCaptureSessions[CAM_TYPE_BAYER];
+ sendReprocessRequest(session,
+ new ReprocessableImage(
+ ClearSightNativeEngine.getInstance().getReferenceImage(true),
+ ClearSightNativeEngine.getInstance().getReferenceResult(true)),
+ CAM_TYPE_BAYER);
+
+ // clearsight
+ if(mClearSightFrame != null)
+ sendReprocessRequest(session, mClearSightFrame, CAM_TYPE_BAYER);
+ }
+
+ private void sendReprocessRequest(CameraCaptureSession session, ReprocessableImage image, final int camType) {
+ CameraDevice device = session.getDevice();
+
+ try {
+ CaptureRequest.Builder reprocRequest = device
+ .createReprocessCaptureRequest(image.mCaptureResult);
+ reprocRequest.addTarget(mEncodeImageReader[camType]
+ .getSurface());
+ reprocRequest.set(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE,
+ CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE_OFF);
+ reprocRequest.set(CaptureRequest.EDGE_MODE,
+ CaptureRequest.EDGE_MODE_OFF);
+ reprocRequest.set(CaptureRequest.NOISE_REDUCTION_MODE,
+ CaptureRequest.NOISE_REDUCTION_MODE_OFF);
+
+ mImageWriter[camType].queueInputImage(image.mImage);
+
+ session.capture(reprocRequest.build(),
+ new CaptureCallback() {
+ @Override
+ public void onCaptureCompleted(
+ CameraCaptureSession session,
+ CaptureRequest request,
+ TotalCaptureResult result) {
+ super.onCaptureCompleted(session, request, result);
+ Log.d(TAG, "encode - onCaptureCompleted: " + camType);
+ mImageEncodeHandler.obtainMessage(
+ MSG_NEW_RESULT, camType, 0, result)
+ .sendToTarget();
+ }
+
+ @Override
+ public void onCaptureFailed(
+ CameraCaptureSession session,
+ CaptureRequest request,
+ CaptureFailure failure) {
+ super.onCaptureFailed(session, request, failure);
+ Log.d(TAG, "encode - onCaptureFailed: " + camType);
+ mImageEncodeHandler.obtainMessage(
+ MSG_NEW_RESULT, camType, 1)
+ .sendToTarget();
+ }
+ }, null);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
}
};
- public void saveDebugImage(MediaSaveService service, byte[] data,
- int width, int height, boolean isReproc) {
+ private class ImageEncodeHandler extends Handler {
+ private boolean mClearsightEncode;
+ private Image mMonoImage;
+ private Image mBayerImage;
+ private Image mClearSightImage;
+
+ public ImageEncodeHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_START_CAPTURE:
+ mClearsightEncode = (msg.arg1 == 1);
+ break;
+ case MSG_NEW_IMG:
+ case MSG_NEW_RESULT:
+ processNewEvent(msg);
+ break;
+ }
+ }
+
+ private void processNewEvent(Message msg) {
+ if(msg.what == MSG_NEW_IMG) {
+ Log.d(TAG, "processNewEncodeEvent - newImg: " + msg.arg1);
+ if(msg.arg1 == CAM_TYPE_MONO) {
+ mMonoImage = (Image)msg.obj;
+ } else if(mBayerImage == null){
+ mBayerImage = (Image)msg.obj;
+ } else {
+ mClearSightImage = (Image)msg.obj;
+ }
+ } else if (msg.arg2 == 0) {
+ Log.d(TAG, "processNewEncodeEvent - newResult: " + msg.arg1);
+ } else {
+ Log.d(TAG, "processNewEncodeEvent - newFailure: " + msg.arg1);
+ }
+ if(mMonoImage != null && mBayerImage != null
+ && (!mClearsightEncode ||
+ (mClearsightEncode && mClearSightImage != null))) {
+ saveMpoImage();
+ }
+ }
+
+ private void saveMpoImage() {
+ mNamedImages.nameNewImage(System.currentTimeMillis());
+ NamedEntity name = mNamedImages.getNextNameEntity();
+ String title = (name == null) ? null : name.title;
+ long date = (name == null) ? -1 : name.date;
+ int width = mBayerImage.getWidth();
+ int height = mBayerImage.getHeight();
+
+ if(mClearsightEncode) {
+ width = mClearSightImage.getWidth();
+ height = mClearSightImage.getHeight();
+ }
+
+ mMediaSaveService.addMpoImage(
+ getJpegData(mClearSightImage),
+ getJpegData(mBayerImage),
+ getJpegData(mMonoImage), width, height, title,
+ date, null, 0, mMediaSavedListener,
+ mMediaSaveService.getContentResolver(), "jpeg");
+
+ mBayerImage.close();
+ mBayerImage = null;
+ mMonoImage.close();
+ mMonoImage = null;
+ if(mClearSightImage != null) {
+ mClearSightImage.close();
+ mClearSightImage = null;
+ }
+ }
+ }
+
+ public void saveDebugImageAsJpeg(MediaSaveService service, byte[] data,
+ int width, int height, boolean isBayer) {
mNamedImages.nameNewImage(System.currentTimeMillis());
NamedEntity name = mNamedImages.getNextNameEntity();
String title = (name == null) ? null : name.title;
long date = (name == null) ? -1 : name.date;
- if (isReproc) {
- title += "_reproc";
+ if (isBayer) {
+ title += "_bayer";
+ } else {
+ title += "_mono";
}
service.addImage(data, title, date, null,
@@ -653,17 +834,43 @@ public class ClearSightImageProcessor {
service.getContentResolver(), "jpeg");
}
- public void saveDebugImage(MediaSaveService service, YuvImage image, boolean isReproc) {
+ public void saveDebugImageAsJpeg(MediaSaveService service, YuvImage image, boolean isBayer) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compressToJpeg(
new Rect(0, 0, image.getWidth(), image.getHeight()), 100, baos);
- saveDebugImage(service, baos.toByteArray(), image.getWidth(), image.getHeight(),
- isReproc);
+ saveDebugImageAsJpeg(service, baos.toByteArray(), image.getWidth(), image.getHeight(),
+ isBayer);
+ }
+
+ public void saveDebugImageAsJpeg(MediaSaveService service, Image image, boolean isBayer) {
+ if(image.getFormat() == ImageFormat.YUV_420_888)
+ saveDebugImageAsJpeg(service, createYuvImage(image), isBayer);
+ else if (image.getFormat() == ImageFormat.JPEG) {
+ saveDebugImageAsJpeg(service, getJpegData(image), image.getWidth(), image.getHeight(), isBayer);
+ }
}
- public void saveDebugImage(MediaSaveService service, Image image, boolean isReproc) {
- saveDebugImage(service, createYuvImage(image), isReproc);
+ public void saveDebugImageAsNV21(Image image, boolean isBayer) {
+ if(image.getFormat() != ImageFormat.YUV_420_888) {
+ Log.d(TAG, "saveDebugImageAsNV21 - invalid param");
+ }
+
+ mNamedImages.nameNewImage(System.currentTimeMillis());
+ NamedEntity name = mNamedImages.getNextNameEntity();
+ StringBuilder pathSB = (name == null) ? new StringBuilder() : new StringBuilder(name.title);
+ pathSB.append("_" + image.getWidth() + "x" + image.getHeight());
+ pathSB.append("_NV21");
+
+ if (isBayer) {
+ pathSB.append("_bayer");
+ } else {
+ pathSB.append("_mono");
+ }
+
+ YuvImage yuv = createYuvImage(image);
+ String path = Storage.generateFilepath(pathSB.toString(), "yuv");
+ Storage.writeFile(path, yuv.getYuvData(), null, "yuv");
}
public YuvImage createYuvImage(Image image) {
@@ -687,4 +894,19 @@ public class ClearSightImageProcessor {
return new YuvImage(data, ImageFormat.NV21, image.getWidth(),
image.getHeight(), strides);
}
+
+ public byte[] getJpegData(Image image) {
+ if (image == null) {
+ Log.d(TAG, "getJpegData - invalid param");
+ return null;
+ }
+ Plane[] planes = image.getPlanes();
+ ByteBuffer buffer = planes[0].getBuffer();
+ int size = buffer.capacity();
+ byte[] data = new byte[size];
+ buffer.rewind();
+ buffer.get(data, 0, size);
+
+ return data;
+ }
}
diff --git a/src/org/codeaurora/snapcam/filter/ClearSightNativeEngine.java b/src/org/codeaurora/snapcam/filter/ClearSightNativeEngine.java
index c79d15a84..0fc23f1bf 100644
--- a/src/org/codeaurora/snapcam/filter/ClearSightNativeEngine.java
+++ b/src/org/codeaurora/snapcam/filter/ClearSightNativeEngine.java
@@ -29,15 +29,13 @@
package org.codeaurora.snapcam.filter;
-import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
-import android.graphics.ImageFormat;
import android.graphics.Rect;
-import android.graphics.YuvImage;
+import android.hardware.camera2.TotalCaptureResult;
import android.media.Image;
import android.media.Image.Plane;
import android.util.Log;
@@ -62,11 +60,13 @@ public class ClearSightNativeEngine {
private static final int VU_PLANE = 2;
private static boolean mLibLoaded;
- private static CamSystemCalibrationData mOtpCalibData;
+ private static byte[] mOtpCalibData;
private static ClearSightNativeEngine mInstance;
private Image mRefColorImage;
private Image mRefMonoImage;
+ private TotalCaptureResult mRefColorResult;
+ private TotalCaptureResult mRefMonoResult;
private ArrayList<SourceImage> mSrcColor = new ArrayList<SourceImage>();
private ArrayList<SourceImage> mSrcMono = new ArrayList<SourceImage>();
@@ -85,7 +85,9 @@ public class ClearSightNativeEngine {
}
public static void setOtpCalibData(CamSystemCalibrationData calibData) {
- mOtpCalibData = calibData;
+ String calibStr = calibData.toString();
+ Log.d(TAG, "OTP calibration data: \n" + calibStr);
+ mOtpCalibData = calibStr.getBytes();
}
public boolean isLibLoaded() {
@@ -97,6 +99,23 @@ public class ClearSightNativeEngine {
mSrcMono.clear();
setReferenceColorImage(null);
setReferenceMonoImage(null);
+ setReferenceColorResult(null);
+ setReferenceMonoResult(null);
+ }
+
+ public void setReferenceResult(boolean color, TotalCaptureResult result) {
+ if (color)
+ setReferenceColorResult(result);
+ else
+ setReferenceMonoResult(result);
+ }
+
+ private void setReferenceColorResult(TotalCaptureResult result) {
+ mRefColorResult = result;
+ }
+
+ private void setReferenceMonoResult(TotalCaptureResult result) {
+ mRefMonoResult = result;
}
public void setReferenceImage(boolean color, Image image) {
@@ -145,6 +164,10 @@ public class ClearSightNativeEngine {
return color ? mRefColorImage : mRefMonoImage;
}
+ public TotalCaptureResult getReferenceResult(boolean color) {
+ return color ? mRefColorResult : mRefMonoResult;
+ }
+
public boolean registerImage(boolean color, Image image) {
List<SourceImage> sourceImages = color?mSrcColor:mSrcMono;
if (sourceImages.isEmpty()) {
@@ -229,30 +252,20 @@ public class ClearSightNativeEngine {
Log.d(TAG, "processImage - dst size - y: "
+ dstY.capacity() + " vu: " + dstVU.capacity());
- String otp_string = mOtpCalibData.toString();
- Log.d(TAG, "processImage - otp_calib: " + otp_string);
-
boolean result = nativeClearSightProcess(numImages, srcColorY, srcColorVU,
metadataColor, mRefColorImage.getWidth(),
mRefColorImage.getHeight(),
colorPlanes[Y_PLANE].getRowStride(),
colorPlanes[VU_PLANE].getRowStride(), srcMonoY, metadataMono,
mRefMonoImage.getWidth(), mRefMonoImage.getHeight(),
- monoPlanes[Y_PLANE].getRowStride(), otp_string.getBytes(), dstY, dstVU,
+ monoPlanes[Y_PLANE].getRowStride(), mOtpCalibData, dstY, dstVU,
colorPlanes[Y_PLANE].getRowStride(),
colorPlanes[VU_PLANE].getRowStride(), roiRect);
if (result) {
dstY.rewind();
dstVU.rewind();
- byte[] data = new byte[dstY.capacity() + dstVU.capacity()];
- int[] strides = new int[] { colorPlanes[Y_PLANE].getRowStride(),
- colorPlanes[VU_PLANE].getRowStride() };
- dstY.get(data, 0, dstY.capacity());
- dstVU.get(data, dstY.capacity(), dstVU.capacity());
- return new ClearsightImage(new YuvImage(data, ImageFormat.NV21,
- mRefColorImage.getWidth(), mRefColorImage.getHeight(),
- strides), roiRect);
+ return new ClearsightImage(dstY, dstVU, roiRect);
} else {
return null;
}
@@ -286,11 +299,13 @@ public class ClearSightNativeEngine {
}
public static class ClearsightImage {
- private YuvImage mImage;
+ public final ByteBuffer mYplane;
+ public final ByteBuffer mVUplane;
private Rect mRoiRect;
- ClearsightImage(YuvImage image, int[] rect) {
- mImage = image;
+ ClearsightImage(ByteBuffer yPlane, ByteBuffer vuPlane, int[] rect) {
+ mYplane = yPlane;
+ mVUplane = vuPlane;
mRoiRect = new Rect(rect[0], rect[1], rect[0] + rect[2], rect[1]
+ rect[3]);
}
@@ -299,10 +314,6 @@ public class ClearSightNativeEngine {
return mRoiRect;
}
- public long getDataLength() {
- return (mImage==null?0:mImage.getYuvData().length);
- }
-
public int getWidth() {
return (mRoiRect.right - mRoiRect.left);
}
@@ -310,13 +321,6 @@ public class ClearSightNativeEngine {
public int getHeight() {
return (mRoiRect.bottom - mRoiRect.top);
}
-
- public byte[] compressToJpeg() {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
- mImage.compressToJpeg(mRoiRect, 100, baos);
- return baos.toByteArray();
- }
}
public static class CamSensorCalibrationData {