blob: 75de9c0eac16e7f96e7ddb2cc9ff0564a3098f2f [file] [log] [blame]
yuntatsai14b28892014-12-08 13:07:50 -08001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.hardware.camera2.cts;
18
yuntatsai14b28892014-12-08 13:07:50 -080019import static android.hardware.camera2.cts.CameraTestUtils.*;
20
21import android.graphics.ImageFormat;
22import android.graphics.Rect;
23import android.hardware.camera2.CameraCharacteristics;
24import android.hardware.camera2.CameraDevice;
25import android.hardware.camera2.CaptureRequest;
yuntatsai279eaa52015-01-16 14:55:58 -080026import android.hardware.camera2.CaptureRequest.Builder;
yuntatsai14b28892014-12-08 13:07:50 -080027import android.hardware.camera2.CaptureResult;
28import android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureCallback;
29import android.hardware.camera2.cts.CameraTestUtils.SimpleImageReaderListener;
30import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
31import android.hardware.camera2.params.StreamConfigurationMap;
yuntatsaia9fc32a2014-12-12 14:52:30 -080032import android.media.Image;
yuntatsai14b28892014-12-08 13:07:50 -080033import android.util.Log;
34import android.util.Range;
35import android.util.Size;
36
37import java.util.ArrayList;
38
39/**
Yin-Chia Yehd14701c2015-06-05 15:52:41 -070040 * Basic tests for burst capture in RAW formats.
yuntatsai14b28892014-12-08 13:07:50 -080041 */
42public class BurstCaptureRawTest extends Camera2SurfaceViewTestCase {
43 private static final String TAG = "BurstCaptureRawTest";
44 private static final int RAW_FORMATS[] = {
Yin-Chia Yehd14701c2015-06-05 15:52:41 -070045 ImageFormat.RAW10, ImageFormat.RAW12, ImageFormat.RAW_SENSOR };
46 private static final int NONSTALL_RAW_FORMATS[] = {
47 ImageFormat.RAW10, ImageFormat.RAW12 };
yuntatsai14b28892014-12-08 13:07:50 -080048 private static final long EXPOSURE_MULTIPLIERS[] = {
yuntatsaia9fc32a2014-12-12 14:52:30 -080049 1, 3, 5 };
yuntatsai14b28892014-12-08 13:07:50 -080050 private static final int SENSITIVITY_MLTIPLIERS[] = {
yuntatsaia9fc32a2014-12-12 14:52:30 -080051 1, 3, 5 };
yuntatsai14b28892014-12-08 13:07:50 -080052 private static final int MAX_FRAMES_BURST =
53 EXPOSURE_MULTIPLIERS.length * SENSITIVITY_MLTIPLIERS.length;
54
55 @Override
56 protected void setUp() throws Exception {
57 super.setUp();
58 }
59
60 @Override
61 protected void tearDown() throws Exception {
62 super.tearDown();
63 }
64
65 /**
66 * Verify raw sensor size information is correctly configured.
67 */
68 public void testRawSensorSize() throws Exception {
69 Log.i(TAG, "Begin testRawSensorSize");
70 for (String id : mCameraIds) {
71 try {
72 openDevice(id);
73
74 ArrayList<Integer> supportedRawList = new ArrayList<Integer>(RAW_FORMATS.length);
Yin-Chia Yehd14701c2015-06-05 15:52:41 -070075 if (!checkCapability(supportedRawList, RAW_FORMATS)) {
yuntatsai14b28892014-12-08 13:07:50 -080076 Log.i(TAG, "Capability is not supported on camera " + id
77 + ". Skip the test.");
78 continue;
79 }
80
81 Size[] rawSizes = mStaticInfo.getRawOutputSizesChecked();
82 assertTrue("No capture sizes available for RAW format!", rawSizes.length != 0);
83
Yin-Chia Yeh347d83a2015-08-08 14:24:39 -070084 // Check happens in getRawDimensChecked.
85 Size rawSize = mStaticInfo.getRawDimensChecked();
yuntatsai14b28892014-12-08 13:07:50 -080086 } finally {
87 closeDevice();
88 }
89 }
90 Log.i(TAG, "End testRawSensorSize");
91 }
92
93 /**
yuntatsaia9fc32a2014-12-12 14:52:30 -080094 * Round [exposure, gain] down, rather than to the nearest, in RAW 10/16
95 * <p>
yuntatsai14b28892014-12-08 13:07:50 -080096 * Verify the value of metadata (exposure and sensitivity) is rounded down if the request cannot
97 * be honored.
yuntatsaia9fc32a2014-12-12 14:52:30 -080098 * </p>
yuntatsai14b28892014-12-08 13:07:50 -080099 */
100 public void testMetadataRoundDown() throws Exception {
101 Log.i(TAG, "Begin testMetadataRoundDown");
yuntatsai14b28892014-12-08 13:07:50 -0800102
Yin-Chia Yehd14701c2015-06-05 15:52:41 -0700103 performTestRoutine(new TestMetaDataRoundDownRoutine(), RAW_FORMATS);
yuntatsai14b28892014-12-08 13:07:50 -0800104
yuntatsaia9fc32a2014-12-12 14:52:30 -0800105 Log.i(TAG, "End testMetadataRoundDown");
106 }
yuntatsai14b28892014-12-08 13:07:50 -0800107
yuntatsaia9fc32a2014-12-12 14:52:30 -0800108 /**
Yin-Chia Yehd14701c2015-06-05 15:52:41 -0700109 * Manual and Auto setting test in RAW formats
yuntatsaia9fc32a2014-12-12 14:52:30 -0800110 * <p>
111 * Make sure switching between manual and auto setting would not make the capture results out of
112 * sync.
113 * </p>
114 */
115 public void testManualAutoSwitch() throws Exception {
116 Log.i(TAG, "Begin testManualAutoSwitch");
yuntatsai14b28892014-12-08 13:07:50 -0800117
Yin-Chia Yehd14701c2015-06-05 15:52:41 -0700118 performTestRoutine(new TestManualAutoSwitch(), RAW_FORMATS);
yuntatsai14b28892014-12-08 13:07:50 -0800119
yuntatsaia9fc32a2014-12-12 14:52:30 -0800120 Log.i(TAG, "End testManualAutoSwitch");
121 }
yuntatsai14b28892014-12-08 13:07:50 -0800122
yuntatsai279eaa52015-01-16 14:55:58 -0800123 /**
Yin-Chia Yehd14701c2015-06-05 15:52:41 -0700124 * Per frame timestamp test in non-stalled RAW formats
yuntatsai279eaa52015-01-16 14:55:58 -0800125 */
126 public void testTimestamp() throws Exception {
127 Log.i(TAG, "Begin testTimestamp");
128
Yin-Chia Yehd14701c2015-06-05 15:52:41 -0700129 performTestRoutine(new TestTimestamp(), NONSTALL_RAW_FORMATS);
yuntatsai279eaa52015-01-16 14:55:58 -0800130
131 Log.i(TAG, "End testTimestamp");
132 }
133
yuntatsaia9fc32a2014-12-12 14:52:30 -0800134 /*
135 * Below are private infrastructure for all tests
136 */
yuntatsai14b28892014-12-08 13:07:50 -0800137
yuntatsaia9fc32a2014-12-12 14:52:30 -0800138 /**
139 * A structure encapsulates all the parameters for setting up preview, and RAW capture.
140 */
141 class CaptureSetup
142 {
143 public CaptureSetup(Size previewCaptureSize, Size rawCaptureSize,
144 CaptureRequest.Builder previewRequestBuilder,
145 CaptureRequest.Builder rawRequestBuilder,
146 SimpleCaptureCallback previewCaptureCallback,
147 SimpleCaptureCallback rawCaptureCallback,
148 SimpleImageReaderListener rawReaderListener)
149 {
150 mPreviewCaptureSize = previewCaptureSize;
151 mRawCaptureSize = rawCaptureSize;
152 mPreviewRequestBuilder = previewRequestBuilder;
153 mRawRequestBuilder = rawRequestBuilder;
154 mPreviewCaptureCallback = previewCaptureCallback;
155 mRawCaptureCallback = rawCaptureCallback;
156 mRawReaderListener = rawReaderListener;
157 }
yuntatsai14b28892014-12-08 13:07:50 -0800158
yuntatsaia9fc32a2014-12-12 14:52:30 -0800159 public Size getPreviewCaptureSize()
160 {
161 return mPreviewCaptureSize;
162 }
yuntatsai14b28892014-12-08 13:07:50 -0800163
yuntatsaia9fc32a2014-12-12 14:52:30 -0800164 public Size getRawCaptureSize()
165 {
166 return mRawCaptureSize;
167 }
yuntatsai14b28892014-12-08 13:07:50 -0800168
yuntatsaia9fc32a2014-12-12 14:52:30 -0800169 public CaptureRequest.Builder getPreviewRequestBuilder()
170 {
171 return mPreviewRequestBuilder;
172 }
yuntatsai14b28892014-12-08 13:07:50 -0800173
yuntatsaia9fc32a2014-12-12 14:52:30 -0800174 public CaptureRequest.Builder getRawRequestBuilder() {
175 return mRawRequestBuilder;
176 }
yuntatsai14b28892014-12-08 13:07:50 -0800177
yuntatsaia9fc32a2014-12-12 14:52:30 -0800178 public SimpleCaptureCallback getPreviewCaptureCallback() {
179 return mPreviewCaptureCallback;
180 }
yuntatsai14b28892014-12-08 13:07:50 -0800181
yuntatsaia9fc32a2014-12-12 14:52:30 -0800182 public SimpleCaptureCallback getRawCaptureCallback() {
183 return mRawCaptureCallback;
184 }
yuntatsai14b28892014-12-08 13:07:50 -0800185
yuntatsaia9fc32a2014-12-12 14:52:30 -0800186 public SimpleImageReaderListener getRawReaderListener() {
187 return mRawReaderListener;
188 }
yuntatsai14b28892014-12-08 13:07:50 -0800189
yuntatsaia9fc32a2014-12-12 14:52:30 -0800190 private Size mPreviewCaptureSize;
191 private Size mRawCaptureSize;
192 private CaptureRequest.Builder mPreviewRequestBuilder;
193 private CaptureRequest.Builder mRawRequestBuilder;
194
195 /** all the non-testing requests are sent to here */
196 private SimpleCaptureCallback mPreviewCaptureCallback;
197 /** all the testing requests are sent to here */
198 private SimpleCaptureCallback mRawCaptureCallback;
199 /** all the testing framebuffers are sent to here */
200 private SimpleImageReaderListener mRawReaderListener;
201 }
202
203 /**
204 * Interface for the test routines that are being called by performTestRoutines(). Implement
205 * different test cases in execute().
206 */
207 interface TestRoutine {
208 public void execute(CaptureRequest.Builder rawBurstBuilder,
209 SimpleCaptureCallback rawCaptureCallback,
210 SimpleImageReaderListener rawReaderListener, int rawFormat) throws Exception;
211 }
212
213 /**
214 * Implementation of metadata round down test.
215 */
216 class TestMetaDataRoundDownRoutine implements TestRoutine
217 {
218 @Override
219 public void execute(CaptureRequest.Builder rawBurstBuilder,
220 SimpleCaptureCallback rawCaptureCallback,
221 SimpleImageReaderListener rawReaderListener, int rawFormat) throws Exception
222 {
223 // build burst capture
224 ArrayList<CaptureRequest> rawRequestList = createBurstRequest(rawBurstBuilder);
225
226 // submit captrue
227 Log.i(TAG, "Submitting Burst Request.");
228 mSession.captureBurst(rawRequestList, rawCaptureCallback, mHandler);
229
230 // verify metadata
231 for (int i = 0; i < MAX_FRAMES_BURST; i++) {
232 CaptureResult result = rawCaptureCallback.getCaptureResult(
233 CAPTURE_IMAGE_TIMEOUT_MS);
234
235 long resultExposure = result.get(CaptureResult.SENSOR_EXPOSURE_TIME);
236 int resultSensitivity = result.get(CaptureResult.SENSOR_SENSITIVITY);
237 long desiredExposure = rawRequestList.get(i).get(
238 CaptureRequest.SENSOR_EXPOSURE_TIME);
239 int desiredSensitivity = rawRequestList.get(i).get(
240 CaptureRequest.SENSOR_SENSITIVITY);
241
242 Log.i(TAG, String.format(
243 "Received capture result, exposure = %d, sensitivity = %d. "
244 + "Requested exposure = %d, sensitivity = %d.",
245 resultExposure,
246 resultSensitivity, desiredExposure, desiredSensitivity));
247
248 mCollector.expectTrue(
249 String.format("Exposure value is greater than requested: "
250 + "requested = %d, result = %d.",
251 desiredExposure, resultExposure),
252 resultExposure <= desiredExposure);
253
254 mCollector.expectTrue(
255 String.format("Sensitivity value is greater than requested: "
256 + "requested = %d, result = %d.",
257 desiredSensitivity, resultSensitivity),
258 resultSensitivity <= desiredSensitivity);
yuntatsai14b28892014-12-08 13:07:50 -0800259 }
260 }
yuntatsaia9fc32a2014-12-12 14:52:30 -0800261 }
262
263 /**
264 * Implementation of manual-auto switching test.
265 */
266 class TestManualAutoSwitch implements TestRoutine
267 {
268 @Override
269 public void execute(CaptureRequest.Builder rawBurstBuilder,
270 SimpleCaptureCallback rawCaptureCallback,
271 SimpleImageReaderListener rawReaderListener, int rawFormat) throws Exception
272 {
273 // create a capture request builder to preserve all the original values
274 CaptureRequest.Builder originBuilder = mCamera.createCaptureRequest(
275 CameraDevice.TEMPLATE_STILL_CAPTURE);
276 copyBurstRequetBuilder(originBuilder, rawBurstBuilder);
277
278 // build burst capture
279 ArrayList<CaptureRequest> rawRequestList = createBurstRequest(rawBurstBuilder);
280
281 // submit captrue but ignore
282 mSession.captureBurst(rawRequestList, rawCaptureCallback, mHandler);
283
284 // drain the capture result
285 drainQueues(rawReaderListener, rawCaptureCallback);
286
287 // reset and build capture with 3A
288 copyBurstRequetBuilder(rawBurstBuilder, originBuilder);
289 rawRequestList = createBurstRequestWith3A(rawBurstBuilder);
290
291 // submit captrue but ignore
292 mSession.captureBurst(rawRequestList, rawCaptureCallback, mHandler);
293
294 // drain the capture result
295 drainQueues(rawReaderListener, rawCaptureCallback);
296
297 // reset and rebuild manual raw burst capture
298 copyBurstRequetBuilder(rawBurstBuilder, originBuilder);
299 rawRequestList = createBurstRequest(rawBurstBuilder);
300
301 // submit capture
302 Log.i(TAG, "Submitting Burst Request.");
303 mSession.captureBurst(rawRequestList, rawCaptureCallback, mHandler);
304
305 // verify metadata
306 for (int i = 0; i < MAX_FRAMES_BURST; i++) {
307 CaptureResult result = rawCaptureCallback.getCaptureResult(
308 CAPTURE_IMAGE_TIMEOUT_MS);
309
310 long resultExposure = result.get(CaptureResult.SENSOR_EXPOSURE_TIME);
311 int resultSensitivity = result.get(CaptureResult.SENSOR_SENSITIVITY);
312 int resultEdgeMode = result.get(CaptureResult.EDGE_MODE);
313 int resultNoiseReductionMode = result.get(
314 CaptureResult.NOISE_REDUCTION_MODE);
315 long desiredExposure = rawRequestList.get(i).get(
316 CaptureRequest.SENSOR_EXPOSURE_TIME);
317 int desiredSensitivity = rawRequestList.get(i).get(
318 CaptureRequest.SENSOR_SENSITIVITY);
319
320 Log.i(TAG, String.format(
321 "Received capture result, exposure = %d, sensitivity = %d. "
322 + "Requested exposure = %d, sensitivity = %d.",
323 resultExposure,
324 resultSensitivity, desiredExposure, desiredSensitivity));
325
326 mCollector.expectTrue(String.format("Edge mode is not turned off."),
327 resultEdgeMode == CaptureRequest.EDGE_MODE_OFF);
328
329 mCollector.expectTrue(String.format("Noise reduction is not turned off."),
330 resultNoiseReductionMode
331 == CaptureRequest.NOISE_REDUCTION_MODE_OFF);
332
333 mCollector.expectTrue(
334 String.format("Exposure value is greater than requested: "
335 + "requested = %d, result = %d.",
336 desiredExposure, resultExposure),
337 resultExposure <= desiredExposure);
338
339 mCollector.expectTrue(
340 String.format("Sensitivity value is greater than requested: "
341 + "requested = %d, result = %d.",
342 desiredSensitivity, resultSensitivity),
343 resultSensitivity <= desiredSensitivity);
344 }
345
346 }
yuntatsai14b28892014-12-08 13:07:50 -0800347 }
348
349 /**
yuntatsai279eaa52015-01-16 14:55:58 -0800350 * Implementation of timestamp test
351 */
352 class TestTimestamp implements TestRoutine
353 {
354 private final double THRESHOLD = 5000000.0; // 5ms
355 private final long EXPOSURE_MULTIPLIERS_PRIVATE[] = {
356 1, 1, 1 };
357 private final int SENSITIVITY_MLTIPLIERS_PRIVATE[] = {
358 1, 1, 1 };
359 private final int MAX_FRAMES_BURST_PRIVATE =
360 EXPOSURE_MULTIPLIERS_PRIVATE.length * SENSITIVITY_MLTIPLIERS_PRIVATE.length;
361
362 @Override
363 public void execute(Builder rawBurstBuilder, SimpleCaptureCallback rawCaptureCallback,
364 SimpleImageReaderListener rawReaderListener, int rawFormat) throws Exception {
365 // prepare some local variables
366 ArrayList<Long> sensorTime = new ArrayList<Long>(MAX_FRAMES_BURST_PRIVATE);
367
368 // build burst capture
369 ArrayList<CaptureRequest> rawRequestList = createBurstRequest(rawBurstBuilder,
370 EXPOSURE_MULTIPLIERS_PRIVATE, SENSITIVITY_MLTIPLIERS_PRIVATE);
371
372 // submit capture while recording timestamp
373 Log.i(TAG, "Submitting Burst Request.");
374 mSession.captureBurst(rawRequestList, rawCaptureCallback, mHandler);
375
376 // receive frames while recording timestamp
377 for (int i = 0; i < MAX_FRAMES_BURST_PRIVATE; i++) {
378 CaptureResult result = rawCaptureCallback.getCaptureResult(
379 CAPTURE_IMAGE_TIMEOUT_MS);
380 long resultExposure = result.get(CaptureResult.SENSOR_EXPOSURE_TIME);
381 int resultSensitivity = result.get(CaptureResult.SENSOR_SENSITIVITY);
382 long resultTimestamp = result.get(CaptureResult.SENSOR_TIMESTAMP);
383 Log.i(TAG, String.format(
384 "Received capture result, exposure = %d, sensitivity = %d, timestamp = %d",
385 resultExposure, resultSensitivity, resultTimestamp));
386
387 sensorTime.add(resultTimestamp);
388 }
389
390 // compare sensor time and compute the difference
391 ArrayList<Long> deltaList = new ArrayList<Long>();
392 for (int i = 1; i < MAX_FRAMES_BURST_PRIVATE; i++)
393 {
394 deltaList.add(sensorTime.get(i) - sensorTime.get(i - 1));
395 }
396
397 // compute the average and standard deviation of the differences
398 double average = 0.0;
399 for (int i = 0; i < deltaList.size(); i++)
400 {
401 average += deltaList.get(i);
402 }
403 average /= deltaList.size();
404
405 double stddev = 0.0;
406 for (int i = 0; i < deltaList.size(); i++)
407 {
408 double diff = deltaList.get(i) - average;
409 stddev += diff * diff;
410 }
411 stddev = Math.sqrt(stddev / deltaList.size());
412
413 Log.i(TAG, String.format("average = %.2f, stddev = %.2f", average, stddev));
414
415 StringBuilder sensorTimestampMessage = new StringBuilder();
416 for (int i = 0; i < sensorTime.size(); i++)
417 {
418 sensorTimestampMessage.append("frame [");
419 sensorTimestampMessage.append(i);
420 sensorTimestampMessage.append("] SENSOR_TIMESTAMP = ");
421 sensorTimestampMessage.append(sensorTime.get(i));
422 sensorTimestampMessage.append("\n");
423 }
424
425 mCollector.expectLessOrEqual(
426 "The standard deviation of frame interval is larger then threshold: " +
427 String.format("stddev = %.2f, threshold = %.2f.\n", stddev, THRESHOLD) +
428 sensorTimestampMessage.toString(),
429 THRESHOLD, stddev);
430 }
431 }
432
433 /**
yuntatsai14b28892014-12-08 13:07:50 -0800434 * Check sensor capability prior to the test.
435 *
436 * @return true if the it is has the capability to execute the test.
437 */
Yin-Chia Yehd14701c2015-06-05 15:52:41 -0700438 private boolean checkCapability(ArrayList<Integer> supportedRawList, int[] testedFormats) {
yuntatsai14b28892014-12-08 13:07:50 -0800439 // make sure the sensor has manual support
440 if (!mStaticInfo.isCapabilitySupported(
441 CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)) {
442 Log.w(TAG, "Full hardware level is not supported");
443 return false;
444 }
445
446 // get the list of supported RAW format
447 StreamConfigurationMap config = mStaticInfo.getValueFromKeyNonNull(
448 CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
449
450 // check for the RAW support
451 supportedRawList.clear();
Yin-Chia Yehd14701c2015-06-05 15:52:41 -0700452 for (int rawFormat : testedFormats) {
yuntatsai14b28892014-12-08 13:07:50 -0800453 if (!config.isOutputSupportedFor(rawFormat)) {
454 continue;
455 }
456 supportedRawList.add(rawFormat);
457 }
458
459 if (supportedRawList.size() == 0)
460 {
461 Log.w(TAG, "RAW output is not supported!");
462 return false;
463 }
464
465 return true;
466 }
467
468 /**
469 * Return the sensor format to human readable string.
yuntatsaia9fc32a2014-12-12 14:52:30 -0800470 *
yuntatsai14b28892014-12-08 13:07:50 -0800471 * @param format Sensor image format.
472 * @return Human readable string.
473 */
474 private String imageFormatToString(int format) {
475 switch (format) {
476 case ImageFormat.RAW10:
477 return "RAW10";
Yin-Chia Yehd14701c2015-06-05 15:52:41 -0700478 case ImageFormat.RAW12:
479 return "RAW12";
yuntatsai14b28892014-12-08 13:07:50 -0800480 case ImageFormat.RAW_SENSOR:
481 return "RAW_SENSOR";
482 }
483
484 return "Unknown";
485 }
486
487 /**
yuntatsaia9fc32a2014-12-12 14:52:30 -0800488 * Setting up various classes prior to the request, e.g.: capture size, builder, callback and
489 * listener
490 *
491 * @return initialized variables that can be directly fed into prepareCaptureAndStartPreview().
492 */
493 private CaptureSetup initCaptureSetupForPreviewAndRaw() throws Exception
494 {
495 // capture size
496 Size previewSize = mOrderedPreviewSizes.get(0);
Yin-Chia Yeh347d83a2015-08-08 14:24:39 -0700497 Size rawSize = mStaticInfo.getRawDimensChecked();
yuntatsaia9fc32a2014-12-12 14:52:30 -0800498
499 // builder
500 CaptureRequest.Builder previewCaptureBuilder = mCamera.createCaptureRequest(
501 CameraDevice.TEMPLATE_PREVIEW);
502 CaptureRequest.Builder rawCaptureBuilder = mCamera.createCaptureRequest(
503 CameraDevice.TEMPLATE_STILL_CAPTURE);
504
505 // callback
506 SimpleCaptureCallback previewCaptureCallback = new SimpleCaptureCallback();
507 SimpleCaptureCallback rawCaptureCallback = new SimpleCaptureCallback();
508 SimpleImageReaderListener rawReaderListener = new SimpleImageReaderListener();
509
510 CaptureSetup setup = new CaptureSetup(previewSize, rawSize, previewCaptureBuilder,
511 rawCaptureBuilder, previewCaptureCallback, rawCaptureCallback, rawReaderListener);
512
513 return setup;
514 }
515
516 /**
517 * Construct an array of burst request with manual exposure and sensitivity.
yuntatsai14b28892014-12-08 13:07:50 -0800518 * <p>
yuntatsaia9fc32a2014-12-12 14:52:30 -0800519 * For each capture request, 3A and post processing (noise reduction, sharpening, etc) will be
520 * turned off. Then exposure and sensitivity value will be configured, which are determined by
521 * EXPOSURE_MULIPLIERS and SENSITIVITY_MULTIPLIERS.
yuntatsai14b28892014-12-08 13:07:50 -0800522 * </p>
yuntatsaia9fc32a2014-12-12 14:52:30 -0800523 *
yuntatsai14b28892014-12-08 13:07:50 -0800524 * @param rawBurstBuilder The builder needs to have targets setup.
525 * @return An array list capture request for burst.
526 */
yuntatsai279eaa52015-01-16 14:55:58 -0800527 private ArrayList<CaptureRequest> createBurstRequest(CaptureRequest.Builder rawBurstBuilder)
528 {
529 return createBurstRequest(rawBurstBuilder, EXPOSURE_MULTIPLIERS, SENSITIVITY_MLTIPLIERS);
530 }
531
532 private ArrayList<CaptureRequest> createBurstRequest(CaptureRequest.Builder rawBurstBuilder,
533 long[] exposureMultipliers, int[] sensitivityMultipliers) {
yuntatsai14b28892014-12-08 13:07:50 -0800534 // set manual mode
535 rawBurstBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
536 rawBurstBuilder.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_OFF);
537 rawBurstBuilder.set(CaptureRequest.NOISE_REDUCTION_MODE,
538 CaptureRequest.NOISE_REDUCTION_MODE_OFF);
539 rawBurstBuilder.set(CaptureRequest.EDGE_MODE, CaptureRequest.EDGE_MODE_OFF);
540 // exposure has higher priority over frame duration; therefore the frame readout time:
541 // exposure time + overhead
542 rawBurstBuilder.set(CaptureRequest.SENSOR_FRAME_DURATION, 0L);
543
544 // get the exposure and sensitivity range
545 Range<Long> exposureRangeNs = new Range<Long>(mStaticInfo.getExposureMinimumOrDefault(),
546 mStaticInfo.getExposureMaximumOrDefault());
547
548 Range<Integer> isoRange = new Range<Integer>(mStaticInfo.getSensitivityMinimumOrDefault(),
549 mStaticInfo.getSensitivityMaximumOrDefault());
550
551 Log.i(TAG, String.format("Exposure time - max: %d, min: %d.", exposureRangeNs.getUpper(),
552 exposureRangeNs.getLower()));
553 Log.i(TAG, String.format("Sensitivity - max: %d, min: %d.", isoRange.getUpper(),
554 isoRange.getLower()));
555
556 // building burst request
yuntatsai279eaa52015-01-16 14:55:58 -0800557 int maxFramesBurst = exposureMultipliers.length * sensitivityMultipliers.length;
558 Log.i(TAG, String.format("Setting up burst = %d frames.", maxFramesBurst));
559 ArrayList<CaptureRequest> rawRequestList = new ArrayList<CaptureRequest>(maxFramesBurst);
yuntatsai14b28892014-12-08 13:07:50 -0800560
yuntatsai279eaa52015-01-16 14:55:58 -0800561 for (int i = 0; i < exposureMultipliers.length; i++) {
562 for (int j = 0; j < sensitivityMultipliers.length; j++) {
yuntatsai14b28892014-12-08 13:07:50 -0800563 long desiredExposure = Math.min(
yuntatsai279eaa52015-01-16 14:55:58 -0800564 exposureRangeNs.getLower() * exposureMultipliers[i],
yuntatsai14b28892014-12-08 13:07:50 -0800565 exposureRangeNs.getUpper());
566
567 int desiredSensitivity =
yuntatsai279eaa52015-01-16 14:55:58 -0800568 Math.min(isoRange.getLower() * sensitivityMultipliers[j],
yuntatsai14b28892014-12-08 13:07:50 -0800569 isoRange.getUpper());
570
571 rawBurstBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, desiredExposure);
572 rawBurstBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, desiredSensitivity);
573
574 rawRequestList.add(rawBurstBuilder.build());
575 }
576 }
577 return rawRequestList;
578 }
579
580 /**
yuntatsaia9fc32a2014-12-12 14:52:30 -0800581 * Construct an array of burst request with 3A
582 * <p>
583 * For each capture request, 3A and post processing (noise reduction, sharpening, etc) will be
584 * turned on.
585 * </p>
586 *
587 * @param rawBurstBuilder The builder needs to have targets setup.
588 * @return An array list capture request for burst.
589 */
590 private ArrayList<CaptureRequest> createBurstRequestWith3A(
591 CaptureRequest.Builder rawBurstBuilder)
592 {
593 // set 3A mode to simulate regular still capture
594 rawBurstBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
595 rawBurstBuilder.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_AUTO);
596 rawBurstBuilder.set(CaptureRequest.NOISE_REDUCTION_MODE,
597 CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY);
598 rawBurstBuilder.set(CaptureRequest.EDGE_MODE, CaptureRequest.EDGE_MODE_HIGH_QUALITY);
599
600 // building burst request
601 Log.i(TAG, String.format("Setting up burst = %d frames.", MAX_FRAMES_BURST));
602 ArrayList<CaptureRequest> rawRequestList = new ArrayList<CaptureRequest>(MAX_FRAMES_BURST);
603
604 for (int i = 0; i < MAX_FRAMES_BURST; i++) {
605 rawRequestList.add(rawBurstBuilder.build());
606 }
607
608 return rawRequestList;
609 }
610
611 /**
612 * An utility method to copy capture request builders. This is used for recovery purpose to
613 * reverse the changes we made to the builder.
614 *
615 * @param dst the builder to write into.
616 * @param src the builder that needs to be copied.
617 */
618 private void copyBurstRequetBuilder(CaptureRequest.Builder dst, CaptureRequest.Builder src)
619 {
620 dst.set(CaptureRequest.CONTROL_AE_MODE, src.get(CaptureRequest.CONTROL_AE_MODE));
621 dst.set(CaptureRequest.CONTROL_AWB_MODE, src.get(CaptureRequest.CONTROL_AWB_MODE));
622 dst.set(CaptureRequest.NOISE_REDUCTION_MODE, src.get(CaptureRequest.NOISE_REDUCTION_MODE));
623 dst.set(CaptureRequest.EDGE_MODE, src.get(CaptureRequest.EDGE_MODE));
624 dst.set(CaptureRequest.SENSOR_FRAME_DURATION,
625 src.get(CaptureRequest.SENSOR_FRAME_DURATION));
626 dst.set(CaptureRequest.SENSOR_EXPOSURE_TIME, src.get(CaptureRequest.SENSOR_EXPOSURE_TIME));
627 dst.set(CaptureRequest.SENSOR_SENSITIVITY, src.get(CaptureRequest.SENSOR_SENSITIVITY));
628 }
629
630 /**
631 * Draining the image reader and capture callback queue
632 *
633 * @param readerListener Image reader listener needs to be drained.
634 * @param captureCallback Capture callback needs to be drained.
635 * @throws Exception Exception from the queue.
636 */
637 private void drainQueues(SimpleImageReaderListener readerListener,
638 SimpleCaptureCallback captureCallback) throws Exception
639 {
640 for (int i = 0; i < MAX_FRAMES_BURST; i++) {
641 Image image = readerListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
642 image.close();
643
644 CaptureResult result = captureCallback.getCaptureResult(
645 CAPTURE_IMAGE_TIMEOUT_MS);
646 long timestamp = result.get(CaptureResult.SENSOR_TIMESTAMP);
647 Log.d(TAG, String.format("timestamp = %d", timestamp));
648 }
649 }
650
651 /**
yuntatsai14b28892014-12-08 13:07:50 -0800652 * Stop preview and remove the target surfaces inside the CaptureRequest.Builder.
653 *
654 * @param previewBuilder Configured builder for preview.
655 * @param rawBurstBuilder Configured builder for RAW.
yuntatsaia9fc32a2014-12-12 14:52:30 -0800656 * @throws Exception Exceptions from stopPreview.
yuntatsai14b28892014-12-08 13:07:50 -0800657 */
658 private void stopPreviewAndClearSurface(CaptureRequest.Builder previewBuilder,
659 CaptureRequest.Builder rawBurstBuilder) throws Exception
660 {
661 previewBuilder.removeTarget(mPreviewSurface);
662 rawBurstBuilder.removeTarget(mPreviewSurface);
663 rawBurstBuilder.removeTarget(mReaderSurface);
664
665 stopPreview();
666 }
yuntatsaia9fc32a2014-12-12 14:52:30 -0800667
Yin-Chia Yehd14701c2015-06-05 15:52:41 -0700668 private void performTestRoutine(TestRoutine routine, int[] testedFormats) throws Exception
yuntatsaia9fc32a2014-12-12 14:52:30 -0800669 {
Yin-Chia Yehd14701c2015-06-05 15:52:41 -0700670 final int PREPARE_TIMEOUT_MS = 10000;
yuntatsaia9fc32a2014-12-12 14:52:30 -0800671 for (String id : mCameraIds) {
672 try {
673 openDevice(id);
674
675 ArrayList<Integer> supportedRawList = new ArrayList<Integer>(RAW_FORMATS.length);
Yin-Chia Yehd14701c2015-06-05 15:52:41 -0700676 if (!checkCapability(supportedRawList, testedFormats)) {
yuntatsaia9fc32a2014-12-12 14:52:30 -0800677 Log.i(TAG, "Capability is not supported on camera " + id
678 + ". Skip the test.");
679 continue;
680 }
681
682 // test each supported RAW format
683 for (int rawFormat : supportedRawList) {
684 Log.i(TAG, "Testing format " + imageFormatToString(rawFormat) + ".");
685
686 // prepare preview and still RAW capture
687 CaptureSetup captureSetup = initCaptureSetupForPreviewAndRaw();
688
689 Size previewCaptureSize = captureSetup.getPreviewCaptureSize();
690 Size rawCaptureSize = captureSetup.getRawCaptureSize();
691
692 CaptureRequest.Builder previewBuilder = captureSetup.getPreviewRequestBuilder();
693 CaptureRequest.Builder rawBurstBuilder = captureSetup.getRawRequestBuilder();
694
695 SimpleCaptureCallback previewCaptureCallback =
696 captureSetup.getPreviewCaptureCallback();
697 SimpleCaptureCallback rawCaptureCallback = captureSetup.getRawCaptureCallback();
698 SimpleImageReaderListener rawReaderListener = captureSetup
699 .getRawReaderListener();
700
701 // start preview and prepare RAW capture
702 prepareCaptureAndStartPreview(previewBuilder, rawBurstBuilder,
703 previewCaptureSize, rawCaptureSize, rawFormat, previewCaptureCallback,
704 MAX_FRAMES_BURST, rawReaderListener);
705
Yin-Chia Yehd14701c2015-06-05 15:52:41 -0700706 // Prepare still surface to prevent large allocations slow down capture
707 mSession.prepare(mReaderSurface);
708 mSessionListener.waitForSurfacePrepared(
709 mSession, mReaderSurface, PREPARE_TIMEOUT_MS);
710
yuntatsaia9fc32a2014-12-12 14:52:30 -0800711 // execute test routine
712 routine.execute(rawBurstBuilder, rawCaptureCallback, rawReaderListener,
713 rawFormat);
714
715 // clear out the surface and camera session
716 stopPreviewAndClearSurface(previewBuilder, rawBurstBuilder);
717 closeImageReader();
718 }
719 } finally {
720 closeDevice();
721 }
722 }
723 }
yuntatsai14b28892014-12-08 13:07:50 -0800724}