diff options
Diffstat (limited to 'src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java')
-rw-r--r-- | src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java | 205 |
1 files changed, 160 insertions, 45 deletions
diff --git a/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java b/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java index 15240ca23..595df8122 100644 --- a/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java +++ b/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java @@ -86,9 +86,11 @@ public class ClearSightImageProcessor { 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 String PERSIST_CS_TIMEOUT_KEY = "persist.camera.cs.timeout"; private static final long DEFAULT_TIMESTAMP_THRESHOLD_MS = 10; private static final int DEFAULT_IMAGES_TO_BURST = 4; + private static final int DEFAULT_CS_TIMEOUT_MS = 300; private static final long MIN_MONO_AREA = 1900000; // ~1.9 MP private static final Size[] MONO_SIZES = { @@ -139,6 +141,7 @@ public class ClearSightImageProcessor { private long mTimestampThresholdNs; private int mNumBurstCount; private int mNumFrameCount; + private int mCsTimeout; private boolean mDumpImages; private boolean mDumpYUV; private boolean mIsClosing; @@ -162,6 +165,9 @@ public class ClearSightImageProcessor { mDumpYUV = SystemProperties.getBoolean(PERSIST_DUMP_YUV_KEY, false); Log.d(TAG, "mDumpYUV: " + mDumpYUV); + + mCsTimeout = SystemProperties.getInt(PERSIST_CS_TIMEOUT_KEY, DEFAULT_CS_TIMEOUT_MS); + Log.d(TAG, "mCsTimeout: " + mCsTimeout); } public static void createInstance() { @@ -346,9 +352,9 @@ public class ClearSightImageProcessor { public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) { - Log.d(TAG, "captureStillPicture onCaptureCompleted: " + cam); + Log.d(TAG, "capture - onCaptureCompleted: " + cam); if(isClosing()) - Log.d(TAG, "captureStillPicture onCaptureCompleted - closing"); + Log.d(TAG, "capture - onCaptureCompleted - closing"); else mImageProcessHandler.obtainMessage(MSG_NEW_CAPTURE_RESULT, cam, 0, result).sendToTarget(); @@ -358,9 +364,9 @@ public class ClearSightImageProcessor { public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request, CaptureFailure result) { - Log.d(TAG, "captureStillPicture onCaptureFailed: " + cam); + Log.d(TAG, "capture - onCaptureFailed: " + cam); if(isClosing()) - Log.d(TAG, "captureStillPicture onCaptureFailed - closing"); + Log.d(TAG, "capture - onCaptureFailed - closing"); else mImageProcessHandler.obtainMessage(MSG_NEW_CAPTURE_FAIL, cam, 0, result).sendToTarget(); @@ -369,7 +375,7 @@ public class ClearSightImageProcessor { @Override public void onCaptureSequenceCompleted(CameraCaptureSession session, int sequenceId, long frameNumber) { - Log.d(TAG, "captureStillPicture onCaptureSequenceCompleted: " + cam); + Log.d(TAG, "capture - onCaptureSequenceCompleted: " + cam); } }; @@ -453,12 +459,14 @@ public class ClearSightImageProcessor { mNumBurstCount); private SparseLongArray mReprocessingFrames = new SparseLongArray(); + private ArrayList<CaptureRequest> mReprocessingRequests = new ArrayList<CaptureRequest>(); private int mReprocessingPairCount; private int mReprocessedBayerCount; private int mReprocessedMonoCount; private NamedEntity mNamedEntity; private int[] mNumImagesToProcess = new int[NUM_CAM]; private boolean mCaptureDone; + private boolean mHasFailures; ImageProcessHandler(Looper looper) { super(looper); @@ -471,6 +479,7 @@ public class ClearSightImageProcessor { switch (msg.what) { case MSG_START_CAPTURE: mCaptureDone = false; + mHasFailures = false; mReprocessingPairCount = 0; mReprocessedBayerCount = 0; mReprocessedMonoCount = 0; @@ -480,6 +489,10 @@ public class ClearSightImageProcessor { mClearsightRegisterHandler.obtainMessage(MSG_START_CAPTURE, 0, 0, mNamedEntity).sendToTarget(); break; + case MSG_END_CAPTURE: + // TIMED OUT WAITING FOR FRAME + handleTimeout(); + break; case MSG_NEW_IMG: processImg(msg); break; @@ -498,6 +511,29 @@ public class ClearSightImageProcessor { } } + private void handleTimeout() { + Log.d(TAG, "handleTimeout"); + releaseBayerFrames(); + releaseMonoFrames(); + mReprocessingFrames.clear(); + mReprocessingRequests.clear(); + + removeMessages(MSG_NEW_CAPTURE_RESULT); + removeMessages(MSG_NEW_CAPTURE_FAIL); + removeMessages(MSG_NEW_REPROC_RESULT); + removeMessages(MSG_NEW_REPROC_FAIL); + removeMessages(MSG_END_CAPTURE); + + // set capture done so that any loose frames coming in will be closed + mCaptureDone = true; + mClearsightRegisterHandler.obtainMessage(MSG_END_CAPTURE, 0, 1).sendToTarget(); + } + + private void kickTimeout() { + removeMessages(MSG_END_CAPTURE); + sendEmptyMessageDelayed(MSG_END_CAPTURE, mCsTimeout); + } + private void processImg(Message msg) { Log.d(TAG, "processImg: " + msg.arg1); Image image = (Image) msg.obj; @@ -512,6 +548,8 @@ public class ClearSightImageProcessor { } private void processNewCaptureEvent(Message msg) { + kickTimeout(); + // Toss extra frames if(mCaptureDone) { Log.d(TAG, "processNewCaptureEvent - captureDone - we already have required frame pairs " + msg.arg1); @@ -541,7 +579,7 @@ public class ClearSightImageProcessor { Log.d(TAG, "processNewCaptureEvent - newImg: " + msg.arg1); Image image = (Image) msg.obj; imageQueue.add(image); - } else if(msg.arg2 == 1) { + } else if(msg.what == MSG_NEW_CAPTURE_FAIL) { Log.d(TAG, "processNewCaptureEvent - new failed result: " + msg.arg1); mNumImagesToProcess[msg.arg1]--; } else { @@ -641,7 +679,8 @@ public class ClearSightImageProcessor { mImageWriter[camId].queueInputImage(reprocImg.mImage); - session.capture(reprocRequest.build(), + CaptureRequest request = reprocRequest.build(); + session.capture(request, new CaptureCallback() { @Override public void onCaptureCompleted( @@ -671,6 +710,8 @@ public class ClearSightImageProcessor { .sendToTarget(); } }, null); + + mReprocessingRequests.add(request); } catch (CameraAccessException e) { e.printStackTrace(); } @@ -711,14 +752,15 @@ public class ClearSightImageProcessor { releaseBayerFrames(); releaseMonoFrames(); - mImageProcessHandler.removeMessages(MSG_NEW_CAPTURE_RESULT); - mImageProcessHandler.removeMessages(MSG_NEW_CAPTURE_FAIL); + removeMessages(MSG_NEW_CAPTURE_RESULT); + removeMessages(MSG_NEW_CAPTURE_FAIL); mCaptureDone = true; if(mReprocessingPairCount == 0) { - // No matching pairs + // No matching pairs = nothing registered, no need to reset engine Log.w(TAG, "processFinalPair - no matching pairs found"); + removeMessages(MSG_END_CAPTURE); if(mCallback != null) mCallback.onClearSightFailure(null); } } @@ -749,13 +791,14 @@ public class ClearSightImageProcessor { private void processNewReprocessResult(Message msg) { Log.d(TAG, "processNewReprocessResult: " + msg.arg1); boolean isBayer = (msg.arg1 == CAM_TYPE_BAYER); + TotalCaptureResult result = (TotalCaptureResult)msg.obj; + mReprocessingRequests.remove(result.getRequest()); if (ClearSightNativeEngine.getInstance() .getReferenceResult(isBayer) == null) { // reference not yet set Log.d(TAG, "reprocess - setReferenceResult: " + msg.obj); - ClearSightNativeEngine.getInstance().setReferenceResult(isBayer, - (TotalCaptureResult)msg.obj); + ClearSightNativeEngine.getInstance().setReferenceResult(isBayer, result); } checkReprocessDone(); @@ -763,21 +806,29 @@ public class ClearSightImageProcessor { private void processNewReprocessFailure(Message msg) { Log.d(TAG, "processNewReprocessFailure: " + msg.arg1); - boolean isBayer = (msg.arg1 == CAM_TYPE_BAYER); + CaptureFailure failure = (CaptureFailure)msg.obj; + mReprocessingRequests.remove(failure.getRequest()); mReprocessingFrames.delete(msg.arg2); + mHasFailures = true; checkReprocessDone(); } private void checkReprocessDone() { Log.d(TAG, "checkReprocessDone capture done: " + mCaptureDone + ", reproc frames: " + mReprocessingFrames.size()); - if(mCaptureDone && mReprocessingFrames.size() == 0 - && ClearSightNativeEngine.getInstance().getReferenceResult(true) != null - && ClearSightNativeEngine.getInstance().getReferenceResult(false) != null) { - mClearsightRegisterHandler.obtainMessage(MSG_END_CAPTURE).sendToTarget(); - mImageProcessHandler.removeMessages(MSG_NEW_REPROC_RESULT); - mImageProcessHandler.removeMessages(MSG_NEW_REPROC_FAIL); + // If all burst frames and results have been processed + if(mCaptureDone && mReprocessingFrames.size() == 0 && mReprocessingRequests.isEmpty()) { + mClearsightRegisterHandler.obtainMessage(MSG_END_CAPTURE, mHasFailures?1:0, 0).sendToTarget(); + removeMessages(MSG_NEW_REPROC_RESULT); + removeMessages(MSG_NEW_REPROC_FAIL); mCaptureDone = false; + mHasFailures = false; + + // all burst and reproc frames processed. + // remove timeout msg. + removeMessages(MSG_END_CAPTURE); + } else { + kickTimeout(); } } }; @@ -801,8 +852,15 @@ public class ClearSightImageProcessor { registerImage(msg); break; case MSG_END_CAPTURE: - mClearsightProcessHandler.obtainMessage(MSG_START_CAPTURE, - 0, 0, mNamedEntity).sendToTarget(); + // Check if timeout + if(msg.arg2 == 1) { + Log.d(TAG, "ClearsightRegisterHandler - handleTimeout"); + ClearSightNativeEngine.getInstance().reset(); + if(mCallback != null) mCallback.onClearSightFailure(null); + } else { + mClearsightProcessHandler.obtainMessage(MSG_START_CAPTURE, + msg.arg1, 0, mNamedEntity).sendToTarget(); + } break; } } @@ -842,13 +900,18 @@ public class ClearSightImageProcessor { } private void processClearSight(NamedEntity namedEntity) { - boolean clearSightEncode = false; + mImageEncodeHandler.obtainMessage(MSG_START_CAPTURE).sendToTarget(); + + short encodeRequest = 0; long csTs = ClearSightNativeEngine.getInstance().getReferenceImage(true).getTimestamp(); CaptureRequest.Builder csRequest = createEncodeReprocRequest( ClearSightNativeEngine.getInstance().getReferenceResult(true), CAM_TYPE_BAYER); + csRequest.setTag(new Object()); boolean processInit = ClearSightNativeEngine.getInstance().initProcessImage(); - sendReferenceEncodeRequests(); + sendReferenceMonoEncodeRequest(); + sendReferenceBayerEncodeRequest(); + encodeRequest |= ImageEncodeHandler.MASK_BAYER_ENCODE|ImageEncodeHandler.MASK_MONO_ENCODE; ClearSightNativeEngine.getInstance().reset(); if(processInit) { @@ -860,7 +923,7 @@ public class ClearSightImageProcessor { encodeImage.setTimestamp(csTs); if(ClearSightNativeEngine.getInstance().processImage(csImage)) { - clearSightEncode = true; + encodeRequest |= ImageEncodeHandler.MASK_CS_ENCODE; sendReprocessRequest(csRequest, encodeImage, CAM_TYPE_BAYER); } else { csImage = null; @@ -869,17 +932,19 @@ public class ClearSightImageProcessor { } mImageEncodeHandler.obtainMessage(MSG_END_CAPTURE, - clearSightEncode?1:0, 0, namedEntity).sendToTarget(); + encodeRequest, 0, namedEntity).sendToTarget(); } - private void sendReferenceEncodeRequests() { + private void sendReferenceMonoEncodeRequest() { // First Mono CaptureRequest.Builder monoRequest = createEncodeReprocRequest( ClearSightNativeEngine.getInstance().getReferenceResult(false), CAM_TYPE_MONO); sendReprocessRequest(monoRequest, ClearSightNativeEngine.getInstance().getReferenceImage(false), CAM_TYPE_MONO); + } + private void sendReferenceBayerEncodeRequest() { // bayer CaptureRequest.Builder bayerRequest = createEncodeReprocRequest( ClearSightNativeEngine.getInstance().getReferenceResult(true), CAM_TYPE_BAYER); @@ -957,7 +1022,7 @@ public class ClearSightImageProcessor { super.onCaptureFailed(session, request, failure); Log.d(TAG, "encode - onCaptureFailed: " + camType); mImageEncodeHandler.obtainMessage( - MSG_NEW_CAPTURE_RESULT, camType, 1) + MSG_NEW_CAPTURE_FAIL, camType, 0, failure) .sendToTarget(); } }, null); @@ -968,8 +1033,14 @@ public class ClearSightImageProcessor { } private class ImageEncodeHandler extends Handler { - private boolean mClearsightEncode; + static final short MASK_CS_ENCODE = 0x01; + static final short MASK_BAYER_ENCODE = 0x02; + static final short MASK_MONO_ENCODE = 0x04; + + private short mEncodeRequest; + private short mEncodeResults; private boolean mReadyToSave; + private boolean mHasFailure; private Image mMonoImage; private Image mBayerImage; private Image mClearSightImage; @@ -984,15 +1055,20 @@ public class ClearSightImageProcessor { if(isClosing()) return; switch (msg.what) { + case MSG_START_CAPTURE: + Log.d(TAG, "ImageEncodeEvent - START_CAPTURE"); + resetParams(); + break; case MSG_END_CAPTURE: Log.d(TAG, "ImageEncodeEvent - END_CAPTURE"); mNamedEntity = (NamedEntity) msg.obj; - mClearsightEncode = (msg.arg1 == 1); + mEncodeRequest = (short)msg.arg1; mReadyToSave = true; saveMpoImage(); break; case MSG_NEW_IMG: case MSG_NEW_CAPTURE_RESULT: + case MSG_NEW_CAPTURE_FAIL: processNewEvent(msg); saveMpoImage(); break; @@ -1004,38 +1080,59 @@ public class ClearSightImageProcessor { Log.d(TAG, "processNewEncodeEvent - newImg: " + msg.arg1); if(msg.arg1 == CAM_TYPE_MONO) { mMonoImage = (Image)msg.obj; + mEncodeResults |= MASK_MONO_ENCODE; } else if(mBayerImage == null){ mBayerImage = (Image)msg.obj; + mEncodeResults |= MASK_BAYER_ENCODE; } else { mClearSightImage = (Image)msg.obj; + mEncodeResults |= MASK_CS_ENCODE; } - } else if (msg.arg2 == 0) { + } else if (msg.what == MSG_NEW_CAPTURE_RESULT) { Log.d(TAG, "processNewEncodeEvent - newResult: " + msg.arg1); } else { Log.d(TAG, "processNewEncodeEvent - newFailure: " + msg.arg1); + mHasFailure = true; + if(msg.arg1 == CAM_TYPE_MONO) { + mEncodeResults |= MASK_MONO_ENCODE; + } else { + CaptureFailure failure = (CaptureFailure)msg.obj; + if(failure.getRequest().getTag() != null) + mEncodeResults |= MASK_CS_ENCODE; + else + mEncodeResults |= MASK_BAYER_ENCODE; + } } } private void saveMpoImage() { - if(!mReadyToSave || mMonoImage == null || mBayerImage == null - || (mClearsightEncode && mClearSightImage == null)) { + if(!mReadyToSave || mEncodeRequest != mEncodeResults) { Log.d(TAG, "saveMpoImage - 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."); + if(mCallback != null) mCallback.onClearSightFailure(null); + resetParams(); + return; + } + String title = (mNamedEntity == null) ? null : mNamedEntity.title; long date = (mNamedEntity == null) ? -1 : mNamedEntity.date; int width = mBayerImage.getWidth(); int height = mBayerImage.getHeight(); - if(mClearsightEncode) { + 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); @@ -1047,24 +1144,42 @@ public class ClearSightImageProcessor { if(mCallback != null) mCallback.onClearSightFailure(null); } - mMediaSaveService.addMpoImage( - clearSightBytes, - bayerBytes, - getJpegData(mMonoImage), width, height, title, - date, null, orientation, mMediaSavedListener, - mMediaSaveService.getContentResolver(), "jpeg"); - - mBayerImage.close(); - mBayerImage = null; - mMonoImage.close(); - mMonoImage = null; + if(monoBytes == null) { + mMediaSaveService.addImage( + clearSightBytes!=null?clearSightBytes:bayerBytes, 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(); + } + + void resetParams() { + if(mBayerImage != null) { + mBayerImage.close(); + mBayerImage = null; + } + if(mMonoImage != null) { + mMonoImage.close(); + mMonoImage = null; + } if(mClearSightImage != null) { mClearSightImage.close(); mClearSightImage = null; } mNamedEntity = null; mReadyToSave = false; - mClearsightEncode = false; + mHasFailure = false; + mEncodeRequest = 0; + mEncodeResults = 0; } } |