aboutsummaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/CameraITS/pymodules/its/device.py2
-rw-r--r--apps/CameraITS/service/src/com/android/camera2/its/ItsSerializer.java12
-rw-r--r--apps/CameraITS/service/src/com/android/camera2/its/ItsService.java128
-rw-r--r--apps/CameraITS/service/src/com/android/camera2/its/ItsUtils.java4
-rw-r--r--apps/CameraITS/service/src/com/android/camera2/its/Logt.java39
-rw-r--r--apps/CameraITS/tests/scene1/test_burst_sameness_auto_fullres.py84
-rw-r--r--apps/TestingCamera2/src/com/android/testingcamera2/v1/CameraOps.java1
7 files changed, 200 insertions, 70 deletions
diff --git a/apps/CameraITS/pymodules/its/device.py b/apps/CameraITS/pymodules/its/device.py
index 5a51cc6..cbf579e 100644
--- a/apps/CameraITS/pymodules/its/device.py
+++ b/apps/CameraITS/pymodules/its/device.py
@@ -93,7 +93,7 @@ class ItsSession(object):
def _wait_until_socket_ready(self):
proc = subprocess.Popen(
- self.ADB.split() + ["logcat", "-s", "'ItsService:v'"],
+ self.ADB.split() + ["logcat"],
stdout=subprocess.PIPE)
logcat = proc.stdout
while True:
diff --git a/apps/CameraITS/service/src/com/android/camera2/its/ItsSerializer.java b/apps/CameraITS/service/src/com/android/camera2/its/ItsSerializer.java
index 922e084..4e2530e 100644
--- a/apps/CameraITS/service/src/com/android/camera2/its/ItsSerializer.java
+++ b/apps/CameraITS/service/src/com/android/camera2/its/ItsSerializer.java
@@ -333,7 +333,7 @@ public class ItsSerializer {
} else if (keyType == Float.class) {
// The JSON serializer doesn't handle floating point NaN or Inf.
if (((Float)keyValue).isInfinite() || ((Float)keyValue).isNaN()) {
- Log.w(TAG, "Inf/NaN floating point value serialized: " + keyName);
+ Logt.w(TAG, "Inf/NaN floating point value serialized: " + keyName);
return null;
}
return new MetadataEntry(keyName, keyValue);
@@ -562,7 +562,7 @@ public class ItsSerializer {
// value to the jsonObj when it is detected.
if (entry != null && entry.key != null && entry.value != null
&& entry.value.toString() == null) {
- Log.w(TAG, "Error encountered serializing value for key: " + entry.key);
+ Logt.w(TAG, "Error encountered serializing value for key: " + entry.key);
} else if (entry != null) {
jsonObj.put(entry.key, entry.value);
} else {
@@ -585,7 +585,7 @@ public class ItsSerializer {
public static CaptureRequest.Builder deserialize(CaptureRequest.Builder mdDefault,
JSONObject jsonReq) throws ItsException {
try {
- Log.i(TAG, "Parsing JSON capture request ...");
+ Logt.i(TAG, "Parsing JSON capture request ...");
// Iterate over the CaptureRequest reflected fields.
CaptureRequest.Builder md = mdDefault;
@@ -672,7 +672,7 @@ public class ItsSerializer {
}
}
if (val != null) {
- Log.i(TAG, "Set: "+keyName+" -> "+Arrays.toString(val));
+ Logt.i(TAG, "Set: "+keyName+" -> "+Arrays.toString(val));
md.set(key, val);
jsonReq.remove(keyName);
}
@@ -744,7 +744,7 @@ public class ItsSerializer {
keyName + ", " + keyType);
}
if (val != null) {
- Log.i(TAG, "Set: " + keyName + " -> " + val);
+ Logt.i(TAG, "Set: " + keyName + " -> " + val);
md.set(key ,val);
jsonReq.remove(keyName);
}
@@ -759,7 +759,7 @@ public class ItsSerializer {
throw new ItsException("Invalid JSON key(s): " + jsonReq.toString());
}
- Log.i(TAG, "Parsing JSON capture request completed");
+ Logt.i(TAG, "Parsing JSON capture request completed");
return md;
} catch (java.lang.IllegalAccessException e) {
throw new ItsException("Access error: ", e);
diff --git a/apps/CameraITS/service/src/com/android/camera2/its/ItsService.java b/apps/CameraITS/service/src/com/android/camera2/its/ItsService.java
index 67ffa4a..95fb845 100644
--- a/apps/CameraITS/service/src/com/android/camera2/its/ItsService.java
+++ b/apps/CameraITS/service/src/com/android/camera2/its/ItsService.java
@@ -85,7 +85,7 @@ public class ItsService extends Service implements SensorEventListener {
public static final String TAG = ItsService.class.getSimpleName();
// Timeouts, in seconds.
- public static final int TIMEOUT_CAPTURE = 10;
+ public static final int TIMEOUT_CALLBACK = 3;
public static final int TIMEOUT_3A = 10;
// State transition timeouts, in ms.
@@ -139,6 +139,7 @@ public class ItsService extends Service implements SensorEventListener {
private volatile BlockingQueue<Object[]> mSerializerQueue =
new LinkedBlockingDeque<Object[]>();
+ private AtomicInteger mCountCallbacksRemaining = new AtomicInteger();
private AtomicInteger mCountRawOrDng = new AtomicInteger();
private AtomicInteger mCountRaw10 = new AtomicInteger();
private AtomicInteger mCountJpg = new AtomicInteger();
@@ -169,8 +170,6 @@ public class ItsService extends Service implements SensorEventListener {
private volatile Object mEventLock = new Object();
private volatile boolean mEventsEnabled = false;
- private CountDownLatch mCaptureCallbackLatch;
-
public interface CaptureListener {
void onCaptureAvailable(Image capture);
}
@@ -212,10 +211,10 @@ public class ItsService extends Service implements SensorEventListener {
int cameraId = 0;
String args = intent.getDataString();
if (args != null) {
- Log.i(TAG, String.format("Received intent args: %s", args));
+ Logt.i(TAG, String.format("Received intent args: %s", args));
cameraId = Integer.parseInt(args);
}
- Log.i(TAG, String.format("Opening camera %d", cameraId));
+ Logt.i(TAG, String.format("Opening camera %d", cameraId));
mCameraThread = new HandlerThread("ItsCameraThread");
try {
@@ -266,7 +265,7 @@ public class ItsService extends Service implements SensorEventListener {
mSocketThread = new Thread(mSocketRunnableObj);
mSocketThread.start();
} catch (ItsException e) {
- Log.e(TAG, "Service failed to start: ", e);
+ Logt.e(TAG, "Service failed to start: ", e);
}
return START_STICKY;
}
@@ -291,7 +290,7 @@ public class ItsService extends Service implements SensorEventListener {
throw new ItsException("Failed to close device");
}
} catch (ItsException e) {
- Log.e(TAG, "Script failed: ", e);
+ Logt.e(TAG, "Script failed: ", e);
}
}
@@ -299,7 +298,7 @@ public class ItsService extends Service implements SensorEventListener {
// Use a separate thread to perform JSON serialization (since this can be slow due to
// the reflection).
public void run() {
- Log.i(TAG, "Serializer thread starting");
+ Logt.i(TAG, "Serializer thread starting");
while (true) {
try {
Object objs[] = mSerializerQueue.take();
@@ -331,19 +330,19 @@ public class ItsService extends Service implements SensorEventListener {
throw new ItsException("No tag provided for socket response");
}
mSocketRunnableObj.sendResponse(tag, null, jsonObj, null);
- Log.i(TAG, String.format("Serialized %s", tag));
+ Logt.i(TAG, String.format("Serialized %s", tag));
} catch (org.json.JSONException e) {
- Log.e(TAG, "Error serializing object", e);
+ Logt.e(TAG, "Error serializing object", e);
break;
} catch (ItsException e) {
- Log.e(TAG, "Error serializing object", e);
+ Logt.e(TAG, "Error serializing object", e);
break;
} catch (java.lang.InterruptedException e) {
- Log.e(TAG, "Error serializing object (interrupted)", e);
+ Logt.e(TAG, "Error serializing object (interrupted)", e);
break;
}
}
- Log.i(TAG, "Serializer thread terminated");
+ Logt.i(TAG, "Serializer thread terminated");
}
}
@@ -360,7 +359,7 @@ public class ItsService extends Service implements SensorEventListener {
}
public void run() {
- Log.i(TAG, "Socket writer thread starting");
+ Logt.i(TAG, "Socket writer thread starting");
while (true) {
try {
ByteBuffer b = mSocketWriteQueue.take();
@@ -372,16 +371,16 @@ public class ItsService extends Service implements SensorEventListener {
mOpenSocket.getOutputStream().write(barray);
}
mOpenSocket.getOutputStream().flush();
- Log.i(TAG, String.format("Wrote to socket: %d bytes", b.capacity()));
+ Logt.i(TAG, String.format("Wrote to socket: %d bytes", b.capacity()));
} catch (IOException e) {
- Log.e(TAG, "Error writing to socket", e);
+ Logt.e(TAG, "Error writing to socket", e);
break;
} catch (java.lang.InterruptedException e) {
- Log.e(TAG, "Error writing to socket (interrupted)", e);
+ Logt.e(TAG, "Error writing to socket (interrupted)", e);
break;
}
}
- Log.i(TAG, "Socket writer thread terminated");
+ Logt.i(TAG, "Socket writer thread terminated");
}
}
@@ -398,22 +397,22 @@ public class ItsService extends Service implements SensorEventListener {
private SocketWriteRunnable mSocketWriteRunnable = null;
public void run() {
- Log.i(TAG, "Socket thread starting");
+ Logt.i(TAG, "Socket thread starting");
try {
mSocket = new ServerSocket(SERVERPORT);
} catch (IOException e) {
- Log.e(TAG, "Failed to create socket", e);
+ Logt.e(TAG, "Failed to create socket", e);
}
try {
- Log.i(TAG, "Waiting for client to connect to socket");
+ Logt.i(TAG, "Waiting for client to connect to socket");
mOpenSocket = mSocket.accept();
if (mOpenSocket == null) {
- Log.e(TAG, "Socket connection error");
+ Logt.e(TAG, "Socket connection error");
return;
}
- Log.i(TAG, "Socket connected");
+ Logt.i(TAG, "Socket connected");
} catch (IOException e) {
- Log.e(TAG, "Socket open error: ", e);
+ Logt.e(TAG, "Socket open error: ", e);
return;
}
mSocketThread = new Thread(new SocketWriteRunnable(mOpenSocket));
@@ -423,31 +422,31 @@ public class ItsService extends Service implements SensorEventListener {
BufferedReader input = new BufferedReader(
new InputStreamReader(mOpenSocket.getInputStream()));
if (input == null) {
- Log.e(TAG, "Failed to get socket input stream");
+ Logt.e(TAG, "Failed to get socket input stream");
break;
}
String line = input.readLine();
if (line == null) {
- Log.e(TAG, "Failed to read socket line");
+ Logt.e(TAG, "Failed to read socket line");
break;
}
processSocketCommand(line);
} catch (IOException e) {
- Log.e(TAG, "Socket read error: ", e);
+ Logt.e(TAG, "Socket read error: ", e);
break;
} catch (ItsException e) {
- Log.e(TAG, "Script error: ", e);
+ Logt.e(TAG, "Script error: ", e);
break;
}
}
- Log.i(TAG, "Socket server loop exited");
+ Logt.i(TAG, "Socket server loop exited");
try {
if (mOpenSocket != null) {
mOpenSocket.close();
mOpenSocket = null;
}
} catch (java.io.IOException e) {
- Log.w(TAG, "Exception closing socket");
+ Logt.w(TAG, "Exception closing socket");
}
try {
if (mSocket != null) {
@@ -455,9 +454,9 @@ public class ItsService extends Service implements SensorEventListener {
mSocket = null;
}
} catch (java.io.IOException e) {
- Log.w(TAG, "Exception closing socket");
+ Logt.w(TAG, "Exception closing socket");
}
- Log.i(TAG, "Socket server thread exited");
+ Logt.i(TAG, "Socket server thread exited");
}
public void processSocketCommand(String cmd)
@@ -481,7 +480,7 @@ public class ItsService extends Service implements SensorEventListener {
throw new ItsException("Unknown command: " + cmd);
}
} catch (org.json.JSONException e) {
- Log.e(TAG, "Invalid command: ", e);
+ Logt.e(TAG, "Invalid command: ", e);
}
}
@@ -748,7 +747,7 @@ public class ItsService extends Service implements SensorEventListener {
CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE) == 0) {
// Send a dummy result back for the code that is waiting for this message to see
// that AF has converged.
- Log.i(TAG, "Ignoring request for AF on fixed-focus camera");
+ Logt.i(TAG, "Ignoring request for AF on fixed-focus camera");
mSocketRunnableObj.sendResponse("afResult", "0.0");
doAF = false;
}
@@ -798,7 +797,7 @@ public class ItsService extends Service implements SensorEventListener {
// Trigger AE first.
if (doAE && !triggeredAE) {
- Log.i(TAG, "Triggering AE");
+ Logt.i(TAG, "Triggering AE");
req.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
triggeredAE = true;
@@ -806,7 +805,7 @@ public class ItsService extends Service implements SensorEventListener {
// After AE has converged, trigger AF.
if (doAF && !triggeredAF && (!doAE || (triggeredAE && mConvergedAE))) {
- Log.i(TAG, "Triggering AF");
+ Logt.i(TAG, "Triggering AF");
req.set(CaptureRequest.CONTROL_AF_TRIGGER,
CaptureRequest.CONTROL_AF_TRIGGER_START);
triggeredAF = true;
@@ -817,7 +816,7 @@ public class ItsService extends Service implements SensorEventListener {
mIssuedRequest3A = true;
mSession.capture(req.build(), mCaptureResultListener, mResultHandler);
} else {
- Log.i(TAG, "3A converged");
+ Logt.i(TAG, "3A converged");
break;
}
}
@@ -841,7 +840,7 @@ public class ItsService extends Service implements SensorEventListener {
for (int i = 0; i < len; i++) {
pattern[i] = patternArray.getLong(i);
}
- Log.i(TAG, String.format("Starting vibrator, pattern length %d",len));
+ Logt.i(TAG, String.format("Starting vibrator, pattern length %d",len));
mVibrator.vibrate(pattern, -1);
mSocketRunnableObj.sendResponse("vibrationStarted", "");
} catch (org.json.JSONException e) {
@@ -946,7 +945,7 @@ public class ItsService extends Service implements SensorEventListener {
// sequence of capture requests. There is one callback per image surface, and one
// callback for the CaptureResult, for each capture.
int numCaptures = requests.size();
- mCaptureCallbackLatch = new CountDownLatch(numCaptures * (numSurfaces + 1));
+ mCountCallbacksRemaining.set(numCaptures * (numSurfaces + 1));
} catch (CameraAccessException e) {
throw new ItsException("Error configuring outputs", e);
@@ -969,13 +968,20 @@ public class ItsService extends Service implements SensorEventListener {
}
// Make sure all callbacks have been hit (wait until captures are done).
- try {
- if (!mCaptureCallbackLatch.await(TIMEOUT_CAPTURE, TimeUnit.SECONDS)) {
+ // If no timeouts are received after a timeout, then fail.
+ int currentCount = mCountCallbacksRemaining.get();
+ while (currentCount > 0) {
+ try {
+ Thread.sleep(TIMEOUT_CALLBACK*1000);
+ } catch (InterruptedException e) {
+ throw new ItsException("Timeout failure", e);
+ }
+ int newCount = mCountCallbacksRemaining.get();
+ if (newCount == currentCount) {
throw new ItsException(
- "Timeout hit, but all callbacks not received");
+ "No callback received within timeout");
}
- } catch (InterruptedException e) {
- throw new ItsException("Interrupted: ", e);
+ currentCount = newCount;
}
} catch (android.hardware.camera2.CameraAccessException e) {
throw new ItsException("Access error: ", e);
@@ -1007,24 +1013,25 @@ public class ItsService extends Service implements SensorEventListener {
try {
int format = capture.getFormat();
if (format == ImageFormat.JPEG) {
- Log.i(TAG, "Received JPEG capture");
- ByteBuffer buf = capture.getPlanes()[0].getBuffer();
+ Logt.i(TAG, "Received JPEG capture");
+ byte[] img = ItsUtils.getDataFromImage(capture);
+ ByteBuffer buf = ByteBuffer.wrap(img);
int count = mCountJpg.getAndIncrement();
mSocketRunnableObj.sendResponseCaptureBuffer("jpegImage", buf);
} else if (format == ImageFormat.YUV_420_888) {
- Log.i(TAG, "Received YUV capture");
+ Logt.i(TAG, "Received YUV capture");
byte[] img = ItsUtils.getDataFromImage(capture);
ByteBuffer buf = ByteBuffer.wrap(img);
int count = mCountYuv.getAndIncrement();
mSocketRunnableObj.sendResponseCaptureBuffer("yuvImage", buf);
} else if (format == ImageFormat.RAW10) {
- Log.i(TAG, "Received RAW10 capture");
+ Logt.i(TAG, "Received RAW10 capture");
byte[] img = ItsUtils.getDataFromImage(capture);
ByteBuffer buf = ByteBuffer.wrap(img);
int count = mCountRaw10.getAndIncrement();
mSocketRunnableObj.sendResponseCaptureBuffer("raw10Image", buf);
} else if (format == ImageFormat.RAW_SENSOR) {
- Log.i(TAG, "Received RAW16 capture");
+ Logt.i(TAG, "Received RAW16 capture");
int count = mCountRawOrDng.getAndIncrement();
if (! mCaptureRawIsDng) {
byte[] img = ItsUtils.getDataFromImage(capture);
@@ -1034,7 +1041,7 @@ public class ItsService extends Service implements SensorEventListener {
// Wait until the corresponding capture result is ready.
while (! mThreadExitFlag) {
if (mCaptureResults[count] != null) {
- Log.i(TAG, "Writing capture as DNG");
+ Logt.i(TAG, "Writing capture as DNG");
DngCreator dngCreator = new DngCreator(
mCameraCharacteristics, mCaptureResults[count]);
ByteArrayOutputStream dngStream = new ByteArrayOutputStream();
@@ -1051,15 +1058,15 @@ public class ItsService extends Service implements SensorEventListener {
} else {
throw new ItsException("Unsupported image format: " + format);
}
- mCaptureCallbackLatch.countDown();
+ mCountCallbacksRemaining.decrementAndGet();
} catch (IOException e) {
- Log.e(TAG, "Script error: ", e);
+ Logt.e(TAG, "Script error: ", e);
mThreadExitFlag = true;
} catch (InterruptedException e) {
- Log.e(TAG, "Script error: ", e);
+ Logt.e(TAG, "Script error: ", e);
mThreadExitFlag = true;
} catch (ItsException e) {
- Log.e(TAG, "Script error: ", e);
+ Logt.e(TAG, "Script error: ", e);
mThreadExitFlag = true;
}
}
@@ -1120,7 +1127,7 @@ public class ItsService extends Service implements SensorEventListener {
logMsg.append(String.format(
"foc=%.1f",
result.get(CaptureResult.LENS_FOCUS_DISTANCE)));
- Log.i(TAG, logMsg.toString());
+ Logt.i(TAG, logMsg.toString());
if (result.get(CaptureResult.CONTROL_AE_STATE) != null) {
mConvergedAE = result.get(CaptureResult.CONTROL_AE_STATE) ==
@@ -1170,7 +1177,7 @@ public class ItsService extends Service implements SensorEventListener {
r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(2,2))
));
} else {
- Log.i(TAG, String.format(
+ Logt.i(TAG, String.format(
"AWB converged but NULL color correction values, gains:%b, ccm:%b",
result.get(CaptureResult.COLOR_CORRECTION_GAINS) == null,
result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM) == null));
@@ -1185,13 +1192,13 @@ public class ItsService extends Service implements SensorEventListener {
mCaptureResults[count] = result;
mSocketRunnableObj.sendResponseCaptureResult(mCameraCharacteristics,
request, result, mCaptureReaders);
- mCaptureCallbackLatch.countDown();
+ mCountCallbacksRemaining.decrementAndGet();
}
} catch (ItsException e) {
- Log.e(TAG, "Script error: ", e);
+ Logt.e(TAG, "Script error: ", e);
mThreadExitFlag = true;
} catch (Exception e) {
- Log.e(TAG, "Script error: ", e);
+ Logt.e(TAG, "Script error: ", e);
mThreadExitFlag = true;
}
}
@@ -1199,8 +1206,7 @@ public class ItsService extends Service implements SensorEventListener {
@Override
public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request,
CaptureFailure failure) {
- mCaptureCallbackLatch.countDown();
- Log.e(TAG, "Script error: capture failed");
+ Logt.e(TAG, "Script error: capture failed");
}
};
}
diff --git a/apps/CameraITS/service/src/com/android/camera2/its/ItsUtils.java b/apps/CameraITS/service/src/com/android/camera2/its/ItsUtils.java
index a065326..2193736 100644
--- a/apps/CameraITS/service/src/com/android/camera2/its/ItsUtils.java
+++ b/apps/CameraITS/service/src/com/android/camera2/its/ItsUtils.java
@@ -142,7 +142,7 @@ public class ItsUtils {
return data;
} else if (format == ImageFormat.YUV_420_888 || format == ImageFormat.RAW_SENSOR
|| format == ImageFormat.RAW10) {
- Log.i(TAG, String.format("Reading image, format %d", format));
+ Logt.i(TAG, String.format("Reading image, format %d", format));
int offset = 0;
data = new byte[width * height * ImageFormat.getBitsPerPixel(format) / 8];
byte[] rowData = new byte[planes[0].getRowStride()];
@@ -179,7 +179,7 @@ public class ItsUtils {
}
}
}
- Log.i(TAG, String.format("Done reading image, format %d", format));
+ Logt.i(TAG, String.format("Done reading image, format %d", format));
return data;
} else {
throw new ItsException("Unsupported image format: " + format);
diff --git a/apps/CameraITS/service/src/com/android/camera2/its/Logt.java b/apps/CameraITS/service/src/com/android/camera2/its/Logt.java
new file mode 100644
index 0000000..2fc5399
--- /dev/null
+++ b/apps/CameraITS/service/src/com/android/camera2/its/Logt.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.camera2.its;
+
+import android.util.Log;
+
+public class Logt {
+ public static void i(String tag, String msg) {
+ long t = android.os.SystemClock.elapsedRealtime();
+ Log.i(tag, String.format("[%d] %s", t, msg));
+ }
+ public static void e(String tag, String msg) {
+ long t = android.os.SystemClock.elapsedRealtime();
+ Log.e(tag, String.format("[%d] %s", t, msg));
+ }
+ public static void w(String tag, String msg) {
+ long t = android.os.SystemClock.elapsedRealtime();
+ Log.w(tag, String.format("[%d] %s", t, msg));
+ }
+ public static void e(String tag, String msg, Throwable tr) {
+ long t = android.os.SystemClock.elapsedRealtime();
+ Log.e(tag, String.format("[%d] %s", t, msg), tr);
+ }
+}
+
diff --git a/apps/CameraITS/tests/scene1/test_burst_sameness_auto_fullres.py b/apps/CameraITS/tests/scene1/test_burst_sameness_auto_fullres.py
new file mode 100644
index 0000000..6955ad8
--- /dev/null
+++ b/apps/CameraITS/tests/scene1/test_burst_sameness_auto_fullres.py
@@ -0,0 +1,84 @@
+# Copyright 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import its.image
+import its.device
+import its.objects
+import os.path
+import numpy
+import pylab
+import matplotlib
+import matplotlib.pyplot
+
+def main():
+ """Take long bursts of images and check that they're all identical.
+
+ Assumes a static scene. Can be used to idenfity if there are sporadic
+ frames that are processed differently or have artifacts, or if 3A isn't
+ stable, since this test converges 3A at the start but doesn't lock 3A
+ throughout capture.
+ """
+ NAME = os.path.basename(__file__).split(".")[0]
+
+ BURST_LEN = 6
+ BURSTS = 2
+ FRAMES = BURST_LEN * BURSTS
+
+ DELTA_THRESH = 0.1
+
+ with its.device.ItsSession() as cam:
+
+ # Capture at full resolution.
+ props = cam.get_camera_properties()
+ req = its.objects.auto_capture_request()
+ w,h = its.objects.get_available_output_sizes("yuv", props)[0]
+
+ # Converge 3A prior to capture.
+ cam.do_3a()
+
+ # Capture bursts of YUV shots.
+ # Build a 4D array, which is an array of all RGB images.
+ imgs = numpy.empty([FRAMES,h,w,3])
+ for j in range(BURSTS):
+ caps = cam.do_capture([req]*BURST_LEN)
+ for i,cap in enumerate(caps):
+ n = j*BURST_LEN + i
+ imgs[n] = its.image.convert_capture_to_rgb_image(cap)
+
+ # Dump all images.
+ print "Dumping images"
+ for i in range(FRAMES):
+ its.image.write_image(imgs[i], "%s_frame%03d.jpg"%(NAME,i))
+
+ # The mean image.
+ img_mean = imgs.mean(0)
+ its.image.write_image(img_mean, "%s_mean.jpg"%(NAME))
+
+ # Compute the deltas of each image from the mean image; this test
+ # passes if none of the deltas are large.
+ print "Computing frame differences"
+ delta_maxes = []
+ for i in range(FRAMES):
+ deltas = (imgs[i] - img_mean).reshape(h*w*3)
+ delta_max_pos = numpy.max(deltas)
+ delta_max_neg = numpy.min(deltas)
+ delta_maxes.append(max(abs(delta_max_pos), abs(delta_max_neg)))
+ max_delta_max = max(delta_maxes)
+ print "Frame %d has largest diff %f" % (
+ delta_maxes.index(max_delta_max), max_delta_max)
+ assert(max_delta_max < DELTA_THRESH)
+
+if __name__ == '__main__':
+ main()
+
diff --git a/apps/TestingCamera2/src/com/android/testingcamera2/v1/CameraOps.java b/apps/TestingCamera2/src/com/android/testingcamera2/v1/CameraOps.java
index c8011c5..1b015b0 100644
--- a/apps/TestingCamera2/src/com/android/testingcamera2/v1/CameraOps.java
+++ b/apps/TestingCamera2/src/com/android/testingcamera2/v1/CameraOps.java
@@ -390,6 +390,7 @@ public class CameraOps {
CaptureRequest.Builder captureBuilder =
mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+ captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientationHint());
captureBuilder.addTarget(mCaptureReader.getSurface());