cts: Add raw + preview + jpeg CTS test with DNG save.
Bug: 15112503
Change-Id: I98878cbbe625244d4dc617f4391c68342939e3c3
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
index c5e0929..e85d7cc 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -339,8 +339,9 @@
if (format == ImageFormat.JPEG) {
buffer = planes[0].getBuffer();
assertNotNull("Fail to get jpeg ByteBuffer", buffer);
- data = new byte[buffer.capacity()];
+ data = new byte[buffer.remaining()];
buffer.get(data);
+ buffer.rewind();
return data;
}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java
index 7daf859..f50622c 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java
@@ -25,6 +25,8 @@
import android.hardware.camera2.CaptureResult;
import android.location.Location;
import android.location.LocationManager;
+import android.hardware.camera2.DngCreator;
+import android.media.ImageReader;
import android.util.Size;
import android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureListener;
import android.hardware.camera2.cts.CameraTestUtils.SimpleImageReaderListener;
@@ -38,9 +40,11 @@
import android.util.Log;
import android.util.Range;
import android.util.Rational;
+import android.view.Surface;
import com.android.ex.camera2.exceptions.TimeoutRuntimeException;
+import java.io.ByteArrayOutputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -176,8 +180,30 @@
closeImageReader();
}
}
- }
+ }
+
+ /**
+ * Test the full raw capture use case.
+ *
+ * This includes:
+ * - Configuring the camera with a preview, jpeg, and raw output stream.
+ * - Running preview until AE/AF can settle.
+ * - Capturing with a request targeting all three output streams.
+ */
+ public void testFullRawCapture() throws Exception {
+ for (int i = 0; i < mCameraIds.length; i++) {
+ try {
+ Log.i(TAG, "Testing raw capture for Camera " + mCameraIds[i]);
+ openDevice(mCameraIds[i]);
+
+ fullRawCaptureTestByCamera();
+ } finally {
+ closeDevice();
+ closeImageReader();
+ }
+ }
+ }
/**
* Test touch for focus.
* <p>
@@ -625,6 +651,102 @@
}
}
+ private void fullRawCaptureTestByCamera() throws Exception {
+ Size maxPreviewSz = mOrderedPreviewSizes.get(0);
+ Size maxStillSz = mOrderedStillSizes.get(0);
+ Size[] rawSizes = mStaticInfo.getRawOutputSizesChecked();
+ for (Size size : rawSizes) {
+ if (VERBOSE) {
+ Log.v(TAG, "Testing multi capture with size " + size.toString()
+ + ", preview size " + maxPreviewSz);
+ }
+
+ // Prepare raw capture and start preview.
+ CaptureRequest.Builder previewBuilder =
+ mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+ CaptureRequest.Builder multiBuilder =
+ mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+
+ SimpleCaptureListener resultListener = new SimpleCaptureListener();
+ SimpleImageReaderListener jpegListener = new SimpleImageReaderListener();
+ SimpleImageReaderListener rawListener = new SimpleImageReaderListener();
+
+ updatePreviewSurface(maxPreviewSz);
+
+ ImageReader rawReader = null;
+ ImageReader jpegReader = null;
+ try {
+
+ // Create ImageReaders.
+ rawReader = makeImageReader(size,
+ ImageFormat.RAW_SENSOR, MAX_READER_IMAGES, rawListener, mHandler);
+ jpegReader = makeImageReader(maxStillSz,
+ ImageFormat.JPEG, MAX_READER_IMAGES, jpegListener, mHandler);
+
+ // Configure output streams with preview and jpeg streams.
+ List<Surface> outputSurfaces = new ArrayList<Surface>();
+ outputSurfaces.add(rawReader.getSurface());
+ outputSurfaces.add(jpegReader.getSurface());
+ outputSurfaces.add(mPreviewSurface);
+ configureCameraOutputs(mCamera, outputSurfaces, mCameraListener);
+
+ // Configure the requests.
+ previewBuilder.addTarget(mPreviewSurface);
+ multiBuilder.addTarget(mPreviewSurface);
+ multiBuilder.addTarget(rawReader.getSurface());
+ multiBuilder.addTarget(jpegReader.getSurface());
+
+ // Start preview.
+ mCamera.setRepeatingRequest(previewBuilder.build(), null, mHandler);
+
+ // Poor man's 3A, wait 2 seconds for AE/AF (if any) to settle.
+ // TODO: Do proper 3A trigger and lock (see testTakePictureTest).
+ Thread.sleep(3000);
+
+ multiBuilder.set(CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE,
+ CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE_ON);
+ CaptureRequest multiRequest = multiBuilder.build();
+
+ mCamera.capture(multiRequest, resultListener, mHandler);
+
+ CaptureResult result = resultListener.getCaptureResultForRequest(multiRequest,
+ NUM_RESULTS_WAIT_TIMEOUT);
+ Image jpegImage = jpegListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
+ basicValidateJpegImage(jpegImage, maxStillSz);
+ Image rawImage = rawListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
+ validateRaw16Image(rawImage, size);
+
+
+ DngCreator dngCreator = new DngCreator(mStaticInfo.getCharacteristics(), result);
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ dngCreator.writeImage(outputStream, rawImage);
+
+ if (DEBUG) {
+ byte[] rawBuffer = outputStream.toByteArray();
+ String rawFileName =
+ DEBUG_FILE_NAME_BASE + "/raw16_" + TAG + size.toString() +
+ "_cam_" + mCamera.getId() + ".dng";
+ Log.d(TAG, "Dump raw file into " + rawFileName);
+ dumpFile(rawFileName, rawBuffer);
+
+ byte[] jpegBuffer = getDataFromImage(jpegImage);
+ String jpegFileName =
+ DEBUG_FILE_NAME_BASE + "/jpeg_" + TAG + size.toString() +
+ "_cam_" + mCamera.getId() + ".jpg";
+ Log.d(TAG, "Dump jpeg file into " + rawFileName);
+ dumpFile(jpegFileName, jpegBuffer);
+ }
+
+ stopPreview();
+ } finally {
+ closeImageReader(rawReader);
+ closeImageReader(jpegReader);
+ rawReader = null;
+ jpegReader = null;
+ }
+ }
+ }
+
private void verifyRawCaptureResult(CaptureRequest rawRequest,
SimpleCaptureListener resultListener) {
// TODO: validate DNG metadata tags.
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java b/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
index dac1f14..e84d417 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
@@ -68,7 +68,7 @@
private static final String TAG = "SurfaceViewTestCase";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
private static final int WAIT_FOR_SURFACE_CHANGE_TIMEOUT_MS = 1000;
- private static final int MAX_READER_IMAGES = 5;
+ protected static final int MAX_READER_IMAGES = 5;
// TODO: Use internal storage for this to make sure the file is only visible to test.
protected static final String DEBUG_FILE_NAME_BASE =
@@ -392,26 +392,56 @@
ImageReader.OnImageAvailableListener listener) throws Exception {
closeImageReader();
- mReader = ImageReader.newInstance(size.getWidth(), size.getHeight(), format, maxNumImages);
- mReaderSurface = mReader.getSurface();
- mReader.setOnImageAvailableListener(listener, mHandler);
+ ImageReader r = makeImageReader(size, format, maxNumImages, listener,
+ mHandler);
+ mReader = r;
+ mReaderSurface = r.getSurface();
+ }
+
+ /**
+ * Create an {@link ImageReader} object and get the surface.
+ *
+ * @param size The size of this ImageReader to be created.
+ * @param format The format of this ImageReader to be created
+ * @param maxNumImages The max number of images that can be acquired simultaneously.
+ * @param listener The listener used by this ImageReader to notify callbacks.
+ * @param handler The handler to use for any listener callbacks.
+ */
+ protected static ImageReader makeImageReader(Size size, int format,
+ int maxNumImages,
+ ImageReader.OnImageAvailableListener
+ listener,
+ Handler handler) {
+ ImageReader reader = ImageReader.newInstance(size.getWidth(), size.getHeight(), format,
+ maxNumImages);
+ reader.setOnImageAvailableListener(listener, handler);
if (VERBOSE) Log.v(TAG, "Created ImageReader size " + size.toString());
+ return reader;
}
/**
* Close the pending images then close current active {@link ImageReader} object.
*/
protected void closeImageReader() {
- if (mReader != null) {
+ closeImageReader(mReader);
+ mReader = null;
+ mReaderSurface = null;
+ }
+
+ /**
+ * Close pending images and clean up an {@link ImageReader} object.
+ * @param reader an {@link ImageReader} to close.
+ */
+ public static void closeImageReader(ImageReader reader) {
+ if (reader != null) {
try {
// Close all possible pending images first.
- Image image = mReader.acquireLatestImage();
+ Image image = reader.acquireLatestImage();
if (image != null) {
image.close();
}
} finally {
- mReader.close();
- mReader = null;
+ reader.close();
}
}
}