|
|
@ -15,6 +15,8 @@ import android.os.SystemClock;
|
|
|
|
import android.text.TextUtils;
|
|
|
|
import android.text.TextUtils;
|
|
|
|
import android.view.OrientationEventListener;
|
|
|
|
import android.view.OrientationEventListener;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import java.util.HashSet;
|
|
|
|
|
|
|
|
import java.util.Set;
|
|
|
|
import java.util.TreeMap;
|
|
|
|
import java.util.TreeMap;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -134,7 +136,7 @@ public class RawActivity extends AppCompatActivity {
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Tag for the {@link Log}.
|
|
|
|
* Tag for the {@link Log}.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
private static final String TAG = "Camera2RawFragment";
|
|
|
|
private static final String TAG = "RawActivity";
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Camera state: Device is closed.
|
|
|
|
* Camera state: Device is closed.
|
|
|
@ -242,7 +244,7 @@ public class RawActivity extends AppCompatActivity {
|
|
|
|
* A counter for tracking corresponding {@link CaptureRequest}s and {@link CaptureResult}s
|
|
|
|
* A counter for tracking corresponding {@link CaptureRequest}s and {@link CaptureResult}s
|
|
|
|
* across the {@link CameraCaptureSession} capture callbacks.
|
|
|
|
* across the {@link CameraCaptureSession} capture callbacks.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
private final AtomicInteger mRequestCounter = new AtomicInteger();
|
|
|
|
private final AtomicInteger mRequestCounter = new AtomicInteger(1);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* A {@link Semaphore} to prevent the app from exiting before closing the camera.
|
|
|
|
* A {@link Semaphore} to prevent the app from exiting before closing the camera.
|
|
|
@ -275,6 +277,7 @@ public class RawActivity extends AppCompatActivity {
|
|
|
|
|
|
|
|
|
|
|
|
private int mBurstCaptures = 1;
|
|
|
|
private int mBurstCaptures = 1;
|
|
|
|
private List<String> mPathsOfCapture = new ArrayList<>();
|
|
|
|
private List<String> mPathsOfCapture = new ArrayList<>();
|
|
|
|
|
|
|
|
private Set<Integer> mRequestIds = new HashSet<>();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* A {@link CameraCaptureSession } for camera preview.
|
|
|
|
* A {@link CameraCaptureSession } for camera preview.
|
|
|
@ -308,7 +311,7 @@ public class RawActivity extends AppCompatActivity {
|
|
|
|
* captures. This is used to allow us to clean up the {@link ImageReader} when all background
|
|
|
|
* captures. This is used to allow us to clean up the {@link ImageReader} when all background
|
|
|
|
* tasks using its {@link Image}s have completed.
|
|
|
|
* tasks using its {@link Image}s have completed.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
private RefCountedAutoCloseable<ImageReader> mJpegImageReader;
|
|
|
|
// private RefCountedAutoCloseable<ImageReader> mJpegImageReader;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* A reference counted holder wrapping the {@link ImageReader} that handles RAW image captures.
|
|
|
|
* A reference counted holder wrapping the {@link ImageReader} that handles RAW image captures.
|
|
|
@ -330,7 +333,7 @@ public class RawActivity extends AppCompatActivity {
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Request ID to {@link ImageSaver.ImageSaverBuilder} mapping for in-progress JPEG captures.
|
|
|
|
* Request ID to {@link ImageSaver.ImageSaverBuilder} mapping for in-progress JPEG captures.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
private final TreeMap<Integer, ImageSaver.ImageSaverBuilder> mJpegResultQueue = new TreeMap<>();
|
|
|
|
// private final TreeMap<Integer, ImageSaver.ImageSaverBuilder> mJpegResultQueue = new TreeMap<>();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Request ID to {@link ImageSaver.ImageSaverBuilder} mapping for in-progress RAW captures.
|
|
|
|
* Request ID to {@link ImageSaver.ImageSaverBuilder} mapping for in-progress RAW captures.
|
|
|
@ -423,6 +426,7 @@ public class RawActivity extends AppCompatActivity {
|
|
|
|
* This a callback object for the {@link ImageReader}. "onImageAvailable" will be called when a
|
|
|
|
* This a callback object for the {@link ImageReader}. "onImageAvailable" will be called when a
|
|
|
|
* JPEG image is ready to be saved.
|
|
|
|
* JPEG image is ready to be saved.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
private final ImageReader.OnImageAvailableListener mOnJpegImageAvailableListener
|
|
|
|
private final ImageReader.OnImageAvailableListener mOnJpegImageAvailableListener
|
|
|
|
= new ImageReader.OnImageAvailableListener() {
|
|
|
|
= new ImageReader.OnImageAvailableListener() {
|
|
|
|
|
|
|
|
|
|
|
@ -432,6 +436,7 @@ public class RawActivity extends AppCompatActivity {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* This a callback object for the {@link ImageReader}. "onImageAvailable" will be called when a
|
|
|
|
* This a callback object for the {@link ImageReader}. "onImageAvailable" will be called when a
|
|
|
@ -535,24 +540,27 @@ public class RawActivity extends AppCompatActivity {
|
|
|
|
public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request,
|
|
|
|
public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request,
|
|
|
|
long timestamp, long frameNumber) {
|
|
|
|
long timestamp, long frameNumber) {
|
|
|
|
String currentDateTime = generateTimestamp();
|
|
|
|
String currentDateTime = generateTimestamp();
|
|
|
|
|
|
|
|
int requestId = (int) request.getTag();
|
|
|
|
|
|
|
|
|
|
|
|
File rawFile = new File(Environment.
|
|
|
|
File rawFile = new File(Environment.
|
|
|
|
getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
|
|
|
|
getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
|
|
|
|
"RAW_" + currentDateTime + ".dng");
|
|
|
|
"RAW_" + currentDateTime + "_" + requestId + ".dng");
|
|
|
|
|
|
|
|
/*
|
|
|
|
File jpegFile = new File(Environment.
|
|
|
|
File jpegFile = new File(Environment.
|
|
|
|
getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
|
|
|
|
getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
|
|
|
|
"JPEG_" + currentDateTime + ".jpg");
|
|
|
|
"JPEG_" + currentDateTime + ".jpg");
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
// Look up the ImageSaverBuilder for this request and update it with the file name
|
|
|
|
// Look up the ImageSaverBuilder for this request and update it with the file name
|
|
|
|
// based on the capture start time.
|
|
|
|
// based on the capture start time.
|
|
|
|
ImageSaver.ImageSaverBuilder jpegBuilder;
|
|
|
|
// ImageSaver.ImageSaverBuilder jpegBuilder;
|
|
|
|
ImageSaver.ImageSaverBuilder rawBuilder;
|
|
|
|
ImageSaver.ImageSaverBuilder rawBuilder;
|
|
|
|
int requestId = (int) request.getTag();
|
|
|
|
|
|
|
|
synchronized (mCameraStateLock) {
|
|
|
|
synchronized (mCameraStateLock) {
|
|
|
|
jpegBuilder = mJpegResultQueue.get(requestId);
|
|
|
|
// jpegBuilder = mJpegResultQueue.get(requestId);
|
|
|
|
rawBuilder = mRawResultQueue.get(requestId);
|
|
|
|
rawBuilder = mRawResultQueue.get(requestId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (jpegBuilder != null) jpegBuilder.setFile(jpegFile);
|
|
|
|
// if (jpegBuilder != null) jpegBuilder.setFile(jpegFile);
|
|
|
|
if (rawBuilder != null) rawBuilder.setFile(rawFile);
|
|
|
|
if (rawBuilder != null) rawBuilder.setFile(rawFile);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -566,26 +574,38 @@ public class RawActivity extends AppCompatActivity {
|
|
|
|
|
|
|
|
|
|
|
|
// Look up the ImageSaverBuilder for this request and update it with the CaptureResult
|
|
|
|
// Look up the ImageSaverBuilder for this request and update it with the CaptureResult
|
|
|
|
synchronized (mCameraStateLock) {
|
|
|
|
synchronized (mCameraStateLock) {
|
|
|
|
jpegBuilder = mJpegResultQueue.get(requestId);
|
|
|
|
// jpegBuilder = mJpegResultQueue.get(requestId);
|
|
|
|
rawBuilder = mRawResultQueue.get(requestId);
|
|
|
|
rawBuilder = mRawResultQueue.get(requestId);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
if (jpegBuilder != null) {
|
|
|
|
if (jpegBuilder != null) {
|
|
|
|
jpegBuilder.setResult(result);
|
|
|
|
jpegBuilder.setResult(result);
|
|
|
|
sb.append("Saving JPEG as: ");
|
|
|
|
sb.append("Saving JPEG as: ");
|
|
|
|
sb.append(jpegBuilder.getSaveLocation());
|
|
|
|
sb.append(jpegBuilder.getSaveLocation());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*/
|
|
|
|
if (rawBuilder != null) {
|
|
|
|
if (rawBuilder != null) {
|
|
|
|
rawBuilder.setResult(result);
|
|
|
|
rawBuilder.setResult(result);
|
|
|
|
if (jpegBuilder != null) sb.append(", ");
|
|
|
|
// if (jpegBuilder != null) sb.append(", ");
|
|
|
|
sb.append("Saving RAW as: ");
|
|
|
|
sb.append("Saving RAW as: ");
|
|
|
|
sb.append(rawBuilder.getSaveLocation());
|
|
|
|
sb.append(rawBuilder.getSaveLocation());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// If we have all the results necessary, save the image to a file in the background.
|
|
|
|
// If we have all the results necessary, save the image to a file in the background.
|
|
|
|
handleCompletionLocked(requestId, jpegBuilder, mJpegResultQueue);
|
|
|
|
/*
|
|
|
|
handleCompletionLocked(requestId, rawBuilder, mRawResultQueue);
|
|
|
|
if (jpegBuilder != null) {
|
|
|
|
|
|
|
|
handleCompletionLocked(requestId, jpegBuilder, mJpegResultQueue);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (rawBuilder != null) {
|
|
|
|
|
|
|
|
handleCompletionLocked(requestId, rawBuilder, mRawResultQueue);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
finishedCaptureLocked();
|
|
|
|
mRequestIds.remove(Integer.valueOf(requestId));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mRequestIds.isEmpty()) {
|
|
|
|
|
|
|
|
finishedCaptureLocked();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -594,7 +614,7 @@ public class RawActivity extends AppCompatActivity {
|
|
|
|
CaptureFailure failure) {
|
|
|
|
CaptureFailure failure) {
|
|
|
|
int requestId = (int) request.getTag();
|
|
|
|
int requestId = (int) request.getTag();
|
|
|
|
synchronized (mCameraStateLock) {
|
|
|
|
synchronized (mCameraStateLock) {
|
|
|
|
mJpegResultQueue.remove(requestId);
|
|
|
|
// mJpegResultQueue.remove(requestId);
|
|
|
|
mRawResultQueue.remove(requestId);
|
|
|
|
mRawResultQueue.remove(requestId);
|
|
|
|
finishedCaptureLocked();
|
|
|
|
finishedCaptureLocked();
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -786,13 +806,15 @@ public class RawActivity extends AppCompatActivity {
|
|
|
|
// Set up ImageReaders for JPEG and RAW outputs. Place these in a reference
|
|
|
|
// Set up ImageReaders for JPEG and RAW outputs. Place these in a reference
|
|
|
|
// counted wrapper to ensure they are only closed when all background tasks
|
|
|
|
// counted wrapper to ensure they are only closed when all background tasks
|
|
|
|
// using them are finished.
|
|
|
|
// using them are finished.
|
|
|
|
|
|
|
|
/*
|
|
|
|
if (mJpegImageReader == null || mJpegImageReader.getAndRetain() == null) {
|
|
|
|
if (mJpegImageReader == null || mJpegImageReader.getAndRetain() == null) {
|
|
|
|
mJpegImageReader = new RefCountedAutoCloseable<>(
|
|
|
|
mJpegImageReader = new RefCountedAutoCloseable<>(
|
|
|
|
ImageReader.newInstance(largestJpeg.getWidth(),
|
|
|
|
ImageReader.newInstance(largestJpeg.getWidth(),
|
|
|
|
largestJpeg.getHeight(), ImageFormat.JPEG, /*maxImages*/5));
|
|
|
|
largestJpeg.getHeight(), ImageFormat.JPEG, 5));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mJpegImageReader.get().setOnImageAvailableListener(
|
|
|
|
mJpegImageReader.get().setOnImageAvailableListener(
|
|
|
|
mOnJpegImageAvailableListener, mBackgroundHandler);
|
|
|
|
mOnJpegImageAvailableListener, mBackgroundHandler);
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
if (mRawImageReader == null || mRawImageReader.getAndRetain() == null) {
|
|
|
|
if (mRawImageReader == null || mRawImageReader.getAndRetain() == null) {
|
|
|
|
mRawImageReader = new RefCountedAutoCloseable<>(
|
|
|
|
mRawImageReader = new RefCountedAutoCloseable<>(
|
|
|
@ -867,13 +889,16 @@ public class RawActivity extends AppCompatActivity {
|
|
|
|
mCaptureSession = null;
|
|
|
|
mCaptureSession = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (null != mCameraDevice) {
|
|
|
|
if (null != mCameraDevice) {
|
|
|
|
|
|
|
|
Log.d("RAW", "Will call CameraDevice close");
|
|
|
|
mCameraDevice.close();
|
|
|
|
mCameraDevice.close();
|
|
|
|
mCameraDevice = null;
|
|
|
|
mCameraDevice = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
if (null != mJpegImageReader) {
|
|
|
|
if (null != mJpegImageReader) {
|
|
|
|
mJpegImageReader.close();
|
|
|
|
mJpegImageReader.close();
|
|
|
|
mJpegImageReader = null;
|
|
|
|
mJpegImageReader = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*/
|
|
|
|
if (null != mRawImageReader) {
|
|
|
|
if (null != mRawImageReader) {
|
|
|
|
mRawImageReader.close();
|
|
|
|
mRawImageReader.close();
|
|
|
|
mRawImageReader = null;
|
|
|
|
mRawImageReader = null;
|
|
|
@ -934,7 +959,7 @@ public class RawActivity extends AppCompatActivity {
|
|
|
|
|
|
|
|
|
|
|
|
// Here, we create a CameraCaptureSession for camera preview.
|
|
|
|
// Here, we create a CameraCaptureSession for camera preview.
|
|
|
|
mCameraDevice.createCaptureSession(Arrays.asList(surface,
|
|
|
|
mCameraDevice.createCaptureSession(Arrays.asList(surface,
|
|
|
|
mJpegImageReader.get().getSurface(),
|
|
|
|
// mJpegImageReader.get().getSurface(),
|
|
|
|
mRawImageReader.get().getSurface()), new CameraCaptureSession.StateCallback() {
|
|
|
|
mRawImageReader.get().getSurface()), new CameraCaptureSession.StateCallback() {
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public void onConfigured(CameraCaptureSession cameraCaptureSession) {
|
|
|
|
public void onConfigured(CameraCaptureSession cameraCaptureSession) {
|
|
|
@ -1232,7 +1257,10 @@ public class RawActivity extends AppCompatActivity {
|
|
|
|
|
|
|
|
|
|
|
|
for (int idx = 0; idx < mBurstCaptures; idx++) {
|
|
|
|
for (int idx = 0; idx < mBurstCaptures; idx++) {
|
|
|
|
// Set request tag to easily track results in callbacks.
|
|
|
|
// Set request tag to easily track results in callbacks.
|
|
|
|
captureBuilder.setTag(mRequestCounter.getAndIncrement());
|
|
|
|
int requestId = mRequestCounter.getAndIncrement();
|
|
|
|
|
|
|
|
mRequestIds.add(Integer.valueOf(requestId));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
captureBuilder.setTag(requestId);
|
|
|
|
CaptureRequest request = captureBuilder.build();
|
|
|
|
CaptureRequest request = captureBuilder.build();
|
|
|
|
|
|
|
|
|
|
|
|
requests.add(request);
|
|
|
|
requests.add(request);
|
|
|
@ -1432,16 +1460,6 @@ public class RawActivity extends AppCompatActivity {
|
|
|
|
mImage.close();
|
|
|
|
mImage.close();
|
|
|
|
closeOutput(output);
|
|
|
|
closeOutput(output);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (mResult) {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
// ImageDecoder.Source src = ImageDecoder.createSource(mFile);
|
|
|
|
|
|
|
|
// Bitmap bm = ImageDecoder.decodeBitmap(src);
|
|
|
|
|
|
|
|
} catch (Exception ex) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
default: {
|
|
|
|