1 /* 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 17 package android.hardware.camera2.cts; 18 19 import static android.hardware.camera2.cts.CameraTestUtils.*; 20 21 import android.graphics.ImageFormat; 22 import android.graphics.Rect; 23 import android.hardware.camera2.CameraCharacteristics; 24 import android.hardware.camera2.CameraDevice; 25 import android.hardware.camera2.CaptureRequest; 26 import android.hardware.camera2.CaptureRequest.Builder; 27 import android.hardware.camera2.CaptureResult; 28 import android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureCallback; 29 import android.hardware.camera2.cts.CameraTestUtils.SimpleImageReaderListener; 30 import android.hardware.camera2.cts.helpers.StaticMetadata; 31 import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase; 32 import android.hardware.camera2.params.StreamConfigurationMap; 33 import android.media.Image; 34 import android.util.Log; 35 import android.util.Range; 36 import android.util.Size; 37 38 import java.util.ArrayList; 39 40 import org.junit.Test; 41 42 /** 43 * Basic tests for burst capture in RAW formats. 44 */ 45 public class BurstCaptureRawTest extends Camera2SurfaceViewTestCase { 46 private static final String TAG = "BurstCaptureRawTest"; 47 private static final int RAW_FORMATS[] = { 48 ImageFormat.RAW10, ImageFormat.RAW12, ImageFormat.RAW_SENSOR }; 49 private static final int NONSTALL_RAW_FORMATS[] = { 50 ImageFormat.RAW10, ImageFormat.RAW12 }; 51 private static final long EXPOSURE_MULTIPLIERS[] = { 52 1, 3, 5 }; 53 private static final int SENSITIVITY_MLTIPLIERS[] = { 54 1, 3, 5 }; 55 private static final int MAX_FRAMES_BURST = 56 EXPOSURE_MULTIPLIERS.length * SENSITIVITY_MLTIPLIERS.length; 57 58 @Override 59 public void setUp() throws Exception { 60 super.setUp(); 61 } 62 63 @Override 64 public void tearDown() throws Exception { 65 super.tearDown(); 66 } 67 68 /** 69 * Verify raw sensor size information is correctly configured. 70 */ 71 @Test 72 public void testRawSensorSize() throws Exception { 73 Log.i(TAG, "Begin testRawSensorSize"); 74 for (String id : mCameraIds) { 75 try { 76 ArrayList<Integer> supportedRawList = new ArrayList<Integer>(RAW_FORMATS.length); 77 if (!checkCapability(id, supportedRawList, RAW_FORMATS)) { 78 Log.i(TAG, "Capability is not supported on camera " + id 79 + ". Skip the test."); 80 continue; 81 } 82 83 openDevice(id); 84 Size[] rawSizes = mStaticInfo.getRawOutputSizesChecked(); 85 assertTrue("No capture sizes available for RAW format!", rawSizes.length != 0); 86 87 // Check happens in getRawDimensChecked. 88 Size rawSize = mStaticInfo.getRawDimensChecked(); 89 } finally { 90 closeDevice(); 91 } 92 } 93 Log.i(TAG, "End testRawSensorSize"); 94 } 95 96 /** 97 * Round [exposure, gain] down, rather than to the nearest, in RAW 10/16 98 * <p> 99 * Verify the value of metadata (exposure and sensitivity) is rounded down if the request cannot 100 * be honored. 101 * </p> 102 */ 103 @Test 104 public void testMetadataRoundDown() throws Exception { 105 Log.i(TAG, "Begin testMetadataRoundDown"); 106 107 performTestRoutine(new TestMetaDataRoundDownRoutine(), RAW_FORMATS); 108 109 Log.i(TAG, "End testMetadataRoundDown"); 110 } 111 112 /** 113 * Manual and Auto setting test in RAW formats 114 * <p> 115 * Make sure switching between manual and auto setting would not make the capture results out of 116 * sync. 117 * </p> 118 */ 119 @Test 120 public void testManualAutoSwitch() throws Exception { 121 Log.i(TAG, "Begin testManualAutoSwitch"); 122 123 performTestRoutine(new TestManualAutoSwitch(), RAW_FORMATS); 124 125 Log.i(TAG, "End testManualAutoSwitch"); 126 } 127 128 /** 129 * Per frame timestamp test in non-stalled RAW formats 130 */ 131 @Test 132 public void testTimestamp() throws Exception { 133 Log.i(TAG, "Begin testTimestamp"); 134 135 performTestRoutine(new TestTimestamp(), NONSTALL_RAW_FORMATS); 136 137 Log.i(TAG, "End testTimestamp"); 138 } 139 140 /* 141 * Below are private infrastructure for all tests 142 */ 143 144 /** 145 * A structure encapsulates all the parameters for setting up preview, and RAW capture. 146 */ 147 class CaptureSetup 148 { 149 public CaptureSetup(Size previewCaptureSize, Size rawCaptureSize, 150 CaptureRequest.Builder previewRequestBuilder, 151 CaptureRequest.Builder rawRequestBuilder, 152 SimpleCaptureCallback previewCaptureCallback, 153 SimpleCaptureCallback rawCaptureCallback, 154 SimpleImageReaderListener rawReaderListener) 155 { 156 mPreviewCaptureSize = previewCaptureSize; 157 mRawCaptureSize = rawCaptureSize; 158 mPreviewRequestBuilder = previewRequestBuilder; 159 mRawRequestBuilder = rawRequestBuilder; 160 mPreviewCaptureCallback = previewCaptureCallback; 161 mRawCaptureCallback = rawCaptureCallback; 162 mRawReaderListener = rawReaderListener; 163 } 164 165 public Size getPreviewCaptureSize() 166 { 167 return mPreviewCaptureSize; 168 } 169 170 public Size getRawCaptureSize() 171 { 172 return mRawCaptureSize; 173 } 174 175 public CaptureRequest.Builder getPreviewRequestBuilder() 176 { 177 return mPreviewRequestBuilder; 178 } 179 180 public CaptureRequest.Builder getRawRequestBuilder() { 181 return mRawRequestBuilder; 182 } 183 184 public SimpleCaptureCallback getPreviewCaptureCallback() { 185 return mPreviewCaptureCallback; 186 } 187 188 public SimpleCaptureCallback getRawCaptureCallback() { 189 return mRawCaptureCallback; 190 } 191 192 public SimpleImageReaderListener getRawReaderListener() { 193 return mRawReaderListener; 194 } 195 196 private Size mPreviewCaptureSize; 197 private Size mRawCaptureSize; 198 private CaptureRequest.Builder mPreviewRequestBuilder; 199 private CaptureRequest.Builder mRawRequestBuilder; 200 201 /** all the non-testing requests are sent to here */ 202 private SimpleCaptureCallback mPreviewCaptureCallback; 203 /** all the testing requests are sent to here */ 204 private SimpleCaptureCallback mRawCaptureCallback; 205 /** all the testing framebuffers are sent to here */ 206 private SimpleImageReaderListener mRawReaderListener; 207 } 208 209 /** 210 * Interface for the test routines that are being called by performTestRoutines(). Implement 211 * different test cases in execute(). 212 */ 213 interface TestRoutine { 214 public void execute(CaptureRequest.Builder rawBurstBuilder, 215 SimpleCaptureCallback rawCaptureCallback, 216 SimpleImageReaderListener rawReaderListener, int rawFormat) throws Exception; 217 } 218 219 /** 220 * Implementation of metadata round down test. 221 */ 222 class TestMetaDataRoundDownRoutine implements TestRoutine 223 { 224 @Override 225 public void execute(CaptureRequest.Builder rawBurstBuilder, 226 SimpleCaptureCallback rawCaptureCallback, 227 SimpleImageReaderListener rawReaderListener, int rawFormat) throws Exception 228 { 229 // build burst capture 230 ArrayList<CaptureRequest> rawRequestList = createBurstRequest(rawBurstBuilder); 231 232 // submit captrue 233 Log.i(TAG, "Submitting Burst Request."); 234 mSession.captureBurst(rawRequestList, rawCaptureCallback, mHandler); 235 236 // verify metadata 237 for (int i = 0; i < MAX_FRAMES_BURST; i++) { 238 CaptureResult result = rawCaptureCallback.getCaptureResult( 239 CAPTURE_IMAGE_TIMEOUT_MS); 240 241 long resultExposure = result.get(CaptureResult.SENSOR_EXPOSURE_TIME); 242 int resultSensitivity = result.get(CaptureResult.SENSOR_SENSITIVITY); 243 long desiredExposure = rawRequestList.get(i).get( 244 CaptureRequest.SENSOR_EXPOSURE_TIME); 245 int desiredSensitivity = rawRequestList.get(i).get( 246 CaptureRequest.SENSOR_SENSITIVITY); 247 248 Log.i(TAG, String.format( 249 "Received capture result, exposure = %d, sensitivity = %d. " 250 + "Requested exposure = %d, sensitivity = %d.", 251 resultExposure, 252 resultSensitivity, desiredExposure, desiredSensitivity)); 253 254 mCollector.expectTrue( 255 String.format("Exposure value is greater than requested: " 256 + "requested = %d, result = %d.", 257 desiredExposure, resultExposure), 258 resultExposure <= desiredExposure); 259 260 mCollector.expectTrue( 261 String.format("Sensitivity value is greater than requested: " 262 + "requested = %d, result = %d.", 263 desiredSensitivity, resultSensitivity), 264 resultSensitivity <= desiredSensitivity); 265 } 266 } 267 } 268 269 /** 270 * Implementation of manual-auto switching test. 271 */ 272 class TestManualAutoSwitch implements TestRoutine 273 { 274 @Override 275 public void execute(CaptureRequest.Builder rawBurstBuilder, 276 SimpleCaptureCallback rawCaptureCallback, 277 SimpleImageReaderListener rawReaderListener, int rawFormat) throws Exception 278 { 279 // create a capture request builder to preserve all the original values 280 CaptureRequest.Builder originBuilder = mCamera.createCaptureRequest( 281 CameraDevice.TEMPLATE_STILL_CAPTURE); 282 copyBurstRequetBuilder(originBuilder, rawBurstBuilder); 283 284 // build burst capture 285 ArrayList<CaptureRequest> rawRequestList = createBurstRequest(rawBurstBuilder); 286 287 // submit captrue but ignore 288 mSession.captureBurst(rawRequestList, rawCaptureCallback, mHandler); 289 290 // drain the capture result 291 drainQueues(rawReaderListener, rawCaptureCallback); 292 293 // reset and build capture with 3A 294 copyBurstRequetBuilder(rawBurstBuilder, originBuilder); 295 rawRequestList = createBurstRequestWith3A(rawBurstBuilder); 296 297 // submit captrue but ignore 298 mSession.captureBurst(rawRequestList, rawCaptureCallback, mHandler); 299 300 // drain the capture result 301 drainQueues(rawReaderListener, rawCaptureCallback); 302 303 // reset and rebuild manual raw burst capture 304 copyBurstRequetBuilder(rawBurstBuilder, originBuilder); 305 rawRequestList = createBurstRequest(rawBurstBuilder); 306 307 // submit capture 308 Log.i(TAG, "Submitting Burst Request."); 309 mSession.captureBurst(rawRequestList, rawCaptureCallback, mHandler); 310 311 // verify metadata 312 for (int i = 0; i < MAX_FRAMES_BURST; i++) { 313 CaptureResult result = rawCaptureCallback.getCaptureResult( 314 CAPTURE_IMAGE_TIMEOUT_MS); 315 316 long resultExposure = result.get(CaptureResult.SENSOR_EXPOSURE_TIME); 317 int resultSensitivity = result.get(CaptureResult.SENSOR_SENSITIVITY); 318 int resultEdgeMode = result.get(CaptureResult.EDGE_MODE); 319 int resultNoiseReductionMode = result.get( 320 CaptureResult.NOISE_REDUCTION_MODE); 321 long desiredExposure = rawRequestList.get(i).get( 322 CaptureRequest.SENSOR_EXPOSURE_TIME); 323 int desiredSensitivity = rawRequestList.get(i).get( 324 CaptureRequest.SENSOR_SENSITIVITY); 325 326 Log.i(TAG, String.format( 327 "Received capture result, exposure = %d, sensitivity = %d. " 328 + "Requested exposure = %d, sensitivity = %d.", 329 resultExposure, 330 resultSensitivity, desiredExposure, desiredSensitivity)); 331 332 mCollector.expectTrue(String.format("Edge mode is not turned off."), 333 resultEdgeMode == CaptureRequest.EDGE_MODE_OFF); 334 335 mCollector.expectTrue(String.format("Noise reduction is not turned off."), 336 resultNoiseReductionMode 337 == CaptureRequest.NOISE_REDUCTION_MODE_OFF); 338 339 mCollector.expectTrue( 340 String.format("Exposure value is greater than requested: " 341 + "requested = %d, result = %d.", 342 desiredExposure, resultExposure), 343 resultExposure <= desiredExposure); 344 345 mCollector.expectTrue( 346 String.format("Sensitivity value is greater than requested: " 347 + "requested = %d, result = %d.", 348 desiredSensitivity, resultSensitivity), 349 resultSensitivity <= desiredSensitivity); 350 } 351 352 } 353 } 354 355 /** 356 * Implementation of timestamp test 357 */ 358 class TestTimestamp implements TestRoutine 359 { 360 private final double THRESHOLD = 5000000.0; // 5ms 361 private final long EXPOSURE_MULTIPLIERS_PRIVATE[] = { 362 1, 1, 1 }; 363 private final int SENSITIVITY_MLTIPLIERS_PRIVATE[] = { 364 1, 1, 1 }; 365 private final int MAX_FRAMES_BURST_PRIVATE = 366 EXPOSURE_MULTIPLIERS_PRIVATE.length * SENSITIVITY_MLTIPLIERS_PRIVATE.length; 367 368 @Override 369 public void execute(Builder rawBurstBuilder, SimpleCaptureCallback rawCaptureCallback, 370 SimpleImageReaderListener rawReaderListener, int rawFormat) throws Exception { 371 // prepare some local variables 372 ArrayList<Long> sensorTime = new ArrayList<Long>(MAX_FRAMES_BURST_PRIVATE); 373 374 // build burst capture 375 ArrayList<CaptureRequest> rawRequestList = createBurstRequest(rawBurstBuilder, 376 EXPOSURE_MULTIPLIERS_PRIVATE, SENSITIVITY_MLTIPLIERS_PRIVATE); 377 378 // submit capture while recording timestamp 379 Log.i(TAG, "Submitting Burst Request."); 380 mSession.captureBurst(rawRequestList, rawCaptureCallback, mHandler); 381 382 // receive frames while recording timestamp 383 for (int i = 0; i < MAX_FRAMES_BURST_PRIVATE; i++) { 384 CaptureResult result = rawCaptureCallback.getCaptureResult( 385 CAPTURE_IMAGE_TIMEOUT_MS); 386 long resultExposure = result.get(CaptureResult.SENSOR_EXPOSURE_TIME); 387 int resultSensitivity = result.get(CaptureResult.SENSOR_SENSITIVITY); 388 long resultTimestamp = result.get(CaptureResult.SENSOR_TIMESTAMP); 389 Log.i(TAG, String.format( 390 "Received capture result, exposure = %d, sensitivity = %d, timestamp = %d", 391 resultExposure, resultSensitivity, resultTimestamp)); 392 393 sensorTime.add(resultTimestamp); 394 } 395 396 // compare sensor time and compute the difference 397 ArrayList<Long> deltaList = new ArrayList<Long>(); 398 for (int i = 1; i < MAX_FRAMES_BURST_PRIVATE; i++) 399 { 400 deltaList.add(sensorTime.get(i) - sensorTime.get(i - 1)); 401 } 402 403 // compute the average and standard deviation of the differences 404 double average = 0.0; 405 for (int i = 0; i < deltaList.size(); i++) 406 { 407 average += deltaList.get(i); 408 } 409 average /= deltaList.size(); 410 411 double stddev = 0.0; 412 for (int i = 0; i < deltaList.size(); i++) 413 { 414 double diff = deltaList.get(i) - average; 415 stddev += diff * diff; 416 } 417 stddev = Math.sqrt(stddev / deltaList.size()); 418 419 Log.i(TAG, String.format("average = %.2f, stddev = %.2f", average, stddev)); 420 421 StringBuilder sensorTimestampMessage = new StringBuilder(); 422 for (int i = 0; i < sensorTime.size(); i++) 423 { 424 sensorTimestampMessage.append("frame ["); 425 sensorTimestampMessage.append(i); 426 sensorTimestampMessage.append("] SENSOR_TIMESTAMP = "); 427 sensorTimestampMessage.append(sensorTime.get(i)); 428 sensorTimestampMessage.append("\n"); 429 } 430 431 mCollector.expectLessOrEqual( 432 "The standard deviation of frame interval is larger then threshold: " + 433 String.format("stddev = %.2f, threshold = %.2f.\n", stddev, THRESHOLD) + 434 sensorTimestampMessage.toString(), 435 THRESHOLD, stddev); 436 } 437 } 438 439 /** 440 * Check sensor capability prior to the test. 441 * 442 * @return true if the it is has the capability to execute the test. 443 */ 444 private boolean checkCapability(String id, ArrayList<Integer> supportedRawList, 445 int[] testedFormats) { 446 StaticMetadata staticInfo = mAllStaticInfo.get(id); 447 // make sure the sensor has manual support 448 if (!staticInfo.isHardwareLevelAtLeastFull()) { 449 Log.w(TAG, "Full hardware level is not supported"); 450 return false; 451 } 452 453 // get the list of supported RAW format 454 StreamConfigurationMap config = staticInfo.getValueFromKeyNonNull( 455 CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 456 457 // check for the RAW support 458 supportedRawList.clear(); 459 for (int rawFormat : testedFormats) { 460 if (!config.isOutputSupportedFor(rawFormat)) { 461 continue; 462 } 463 supportedRawList.add(rawFormat); 464 } 465 466 if (supportedRawList.size() == 0) 467 { 468 Log.w(TAG, "RAW output is not supported!"); 469 return false; 470 } 471 472 return true; 473 } 474 475 /** 476 * Return the sensor format to human readable string. 477 * 478 * @param format Sensor image format. 479 * @return Human readable string. 480 */ 481 private String imageFormatToString(int format) { 482 switch (format) { 483 case ImageFormat.RAW10: 484 return "RAW10"; 485 case ImageFormat.RAW12: 486 return "RAW12"; 487 case ImageFormat.RAW_SENSOR: 488 return "RAW_SENSOR"; 489 } 490 491 return "Unknown"; 492 } 493 494 /** 495 * Setting up various classes prior to the request, e.g.: capture size, builder, callback and 496 * listener 497 * 498 * @return initialized variables that can be directly fed into prepareCaptureAndStartPreview(). 499 */ 500 private CaptureSetup initCaptureSetupForPreviewAndRaw() throws Exception 501 { 502 // capture size 503 Size previewSize = mOrderedPreviewSizes.get(0); 504 Size rawSize = mStaticInfo.getRawDimensChecked(); 505 506 // builder 507 CaptureRequest.Builder previewCaptureBuilder = mCamera.createCaptureRequest( 508 CameraDevice.TEMPLATE_PREVIEW); 509 CaptureRequest.Builder rawCaptureBuilder = mCamera.createCaptureRequest( 510 CameraDevice.TEMPLATE_STILL_CAPTURE); 511 512 // callback 513 SimpleCaptureCallback previewCaptureCallback = new SimpleCaptureCallback(); 514 SimpleCaptureCallback rawCaptureCallback = new SimpleCaptureCallback(); 515 SimpleImageReaderListener rawReaderListener = new SimpleImageReaderListener(); 516 517 CaptureSetup setup = new CaptureSetup(previewSize, rawSize, previewCaptureBuilder, 518 rawCaptureBuilder, previewCaptureCallback, rawCaptureCallback, rawReaderListener); 519 520 return setup; 521 } 522 523 /** 524 * Construct an array of burst request with manual exposure and sensitivity. 525 * <p> 526 * For each capture request, 3A and post processing (noise reduction, sharpening, etc) will be 527 * turned off. Then exposure and sensitivity value will be configured, which are determined by 528 * EXPOSURE_MULIPLIERS and SENSITIVITY_MULTIPLIERS. 529 * </p> 530 * 531 * @param rawBurstBuilder The builder needs to have targets setup. 532 * @return An array list capture request for burst. 533 */ 534 private ArrayList<CaptureRequest> createBurstRequest(CaptureRequest.Builder rawBurstBuilder) 535 { 536 return createBurstRequest(rawBurstBuilder, EXPOSURE_MULTIPLIERS, SENSITIVITY_MLTIPLIERS); 537 } 538 539 private ArrayList<CaptureRequest> createBurstRequest(CaptureRequest.Builder rawBurstBuilder, 540 long[] exposureMultipliers, int[] sensitivityMultipliers) { 541 // set manual mode 542 rawBurstBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF); 543 rawBurstBuilder.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_OFF); 544 rawBurstBuilder.set(CaptureRequest.NOISE_REDUCTION_MODE, 545 CaptureRequest.NOISE_REDUCTION_MODE_OFF); 546 rawBurstBuilder.set(CaptureRequest.EDGE_MODE, CaptureRequest.EDGE_MODE_OFF); 547 // exposure has higher priority over frame duration; therefore the frame readout time: 548 // exposure time + overhead 549 rawBurstBuilder.set(CaptureRequest.SENSOR_FRAME_DURATION, 0L); 550 551 // get the exposure and sensitivity range 552 Range<Long> exposureRangeNs = new Range<Long>(mStaticInfo.getExposureMinimumOrDefault(), 553 mStaticInfo.getExposureMaximumOrDefault()); 554 555 Range<Integer> isoRange = new Range<Integer>(mStaticInfo.getSensitivityMinimumOrDefault(), 556 mStaticInfo.getSensitivityMaximumOrDefault()); 557 558 Log.i(TAG, String.format("Exposure time - max: %d, min: %d.", exposureRangeNs.getUpper(), 559 exposureRangeNs.getLower())); 560 Log.i(TAG, String.format("Sensitivity - max: %d, min: %d.", isoRange.getUpper(), 561 isoRange.getLower())); 562 563 // building burst request 564 int maxFramesBurst = exposureMultipliers.length * sensitivityMultipliers.length; 565 Log.i(TAG, String.format("Setting up burst = %d frames.", maxFramesBurst)); 566 ArrayList<CaptureRequest> rawRequestList = new ArrayList<CaptureRequest>(maxFramesBurst); 567 568 for (int i = 0; i < exposureMultipliers.length; i++) { 569 for (int j = 0; j < sensitivityMultipliers.length; j++) { 570 long desiredExposure = Math.min( 571 exposureRangeNs.getLower() * exposureMultipliers[i], 572 exposureRangeNs.getUpper()); 573 574 int desiredSensitivity = 575 Math.min(isoRange.getLower() * sensitivityMultipliers[j], 576 isoRange.getUpper()); 577 578 rawBurstBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, desiredExposure); 579 rawBurstBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, desiredSensitivity); 580 581 rawRequestList.add(rawBurstBuilder.build()); 582 } 583 } 584 return rawRequestList; 585 } 586 587 /** 588 * Construct an array of burst request with 3A 589 * <p> 590 * For each capture request, 3A and post processing (noise reduction, sharpening, etc) will be 591 * turned on. 592 * </p> 593 * 594 * @param rawBurstBuilder The builder needs to have targets setup. 595 * @return An array list capture request for burst. 596 */ 597 private ArrayList<CaptureRequest> createBurstRequestWith3A( 598 CaptureRequest.Builder rawBurstBuilder) 599 { 600 // set 3A mode to simulate regular still capture 601 rawBurstBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON); 602 rawBurstBuilder.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_AUTO); 603 rawBurstBuilder.set(CaptureRequest.NOISE_REDUCTION_MODE, 604 CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY); 605 rawBurstBuilder.set(CaptureRequest.EDGE_MODE, CaptureRequest.EDGE_MODE_HIGH_QUALITY); 606 607 // building burst request 608 Log.i(TAG, String.format("Setting up burst = %d frames.", MAX_FRAMES_BURST)); 609 ArrayList<CaptureRequest> rawRequestList = new ArrayList<CaptureRequest>(MAX_FRAMES_BURST); 610 611 for (int i = 0; i < MAX_FRAMES_BURST; i++) { 612 rawRequestList.add(rawBurstBuilder.build()); 613 } 614 615 return rawRequestList; 616 } 617 618 /** 619 * An utility method to copy capture request builders. This is used for recovery purpose to 620 * reverse the changes we made to the builder. 621 * 622 * @param dst the builder to write into. 623 * @param src the builder that needs to be copied. 624 */ 625 private void copyBurstRequetBuilder(CaptureRequest.Builder dst, CaptureRequest.Builder src) 626 { 627 dst.set(CaptureRequest.CONTROL_AE_MODE, src.get(CaptureRequest.CONTROL_AE_MODE)); 628 dst.set(CaptureRequest.CONTROL_AWB_MODE, src.get(CaptureRequest.CONTROL_AWB_MODE)); 629 dst.set(CaptureRequest.NOISE_REDUCTION_MODE, src.get(CaptureRequest.NOISE_REDUCTION_MODE)); 630 dst.set(CaptureRequest.EDGE_MODE, src.get(CaptureRequest.EDGE_MODE)); 631 dst.set(CaptureRequest.SENSOR_FRAME_DURATION, 632 src.get(CaptureRequest.SENSOR_FRAME_DURATION)); 633 dst.set(CaptureRequest.SENSOR_EXPOSURE_TIME, src.get(CaptureRequest.SENSOR_EXPOSURE_TIME)); 634 dst.set(CaptureRequest.SENSOR_SENSITIVITY, src.get(CaptureRequest.SENSOR_SENSITIVITY)); 635 } 636 637 /** 638 * Draining the image reader and capture callback queue 639 * 640 * @param readerListener Image reader listener needs to be drained. 641 * @param captureCallback Capture callback needs to be drained. 642 * @throws Exception Exception from the queue. 643 */ 644 private void drainQueues(SimpleImageReaderListener readerListener, 645 SimpleCaptureCallback captureCallback) throws Exception 646 { 647 for (int i = 0; i < MAX_FRAMES_BURST; i++) { 648 Image image = readerListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS); 649 image.close(); 650 651 CaptureResult result = captureCallback.getCaptureResult( 652 CAPTURE_IMAGE_TIMEOUT_MS); 653 long timestamp = result.get(CaptureResult.SENSOR_TIMESTAMP); 654 Log.d(TAG, String.format("timestamp = %d", timestamp)); 655 } 656 } 657 658 /** 659 * Stop preview and remove the target surfaces inside the CaptureRequest.Builder. 660 * 661 * @param previewBuilder Configured builder for preview. 662 * @param rawBurstBuilder Configured builder for RAW. 663 * @throws Exception Exceptions from stopPreview. 664 */ 665 private void stopPreviewAndClearSurface(CaptureRequest.Builder previewBuilder, 666 CaptureRequest.Builder rawBurstBuilder) throws Exception 667 { 668 previewBuilder.removeTarget(mPreviewSurface); 669 rawBurstBuilder.removeTarget(mPreviewSurface); 670 rawBurstBuilder.removeTarget(mReaderSurface); 671 672 stopPreview(); 673 } 674 675 private void performTestRoutine(TestRoutine routine, int[] testedFormats) throws Exception 676 { 677 final int PREPARE_TIMEOUT_MS = 10000; 678 for (String id : mCameraIds) { 679 try { 680 ArrayList<Integer> supportedRawList = new ArrayList<Integer>(RAW_FORMATS.length); 681 if (!checkCapability(id, supportedRawList, testedFormats)) { 682 Log.i(TAG, "Capability is not supported on camera " + id 683 + ". Skip the test."); 684 continue; 685 } 686 687 openDevice(id); 688 // test each supported RAW format 689 for (int rawFormat : supportedRawList) { 690 Log.i(TAG, "Testing format " + imageFormatToString(rawFormat) + "."); 691 692 // prepare preview and still RAW capture 693 CaptureSetup captureSetup = initCaptureSetupForPreviewAndRaw(); 694 695 Size previewCaptureSize = captureSetup.getPreviewCaptureSize(); 696 Size rawCaptureSize = captureSetup.getRawCaptureSize(); 697 698 CaptureRequest.Builder previewBuilder = captureSetup.getPreviewRequestBuilder(); 699 CaptureRequest.Builder rawBurstBuilder = captureSetup.getRawRequestBuilder(); 700 701 SimpleCaptureCallback previewCaptureCallback = 702 captureSetup.getPreviewCaptureCallback(); 703 SimpleCaptureCallback rawCaptureCallback = captureSetup.getRawCaptureCallback(); 704 SimpleImageReaderListener rawReaderListener = captureSetup 705 .getRawReaderListener(); 706 707 // start preview and prepare RAW capture 708 prepareCaptureAndStartPreview(previewBuilder, rawBurstBuilder, 709 previewCaptureSize, rawCaptureSize, rawFormat, previewCaptureCallback, 710 MAX_FRAMES_BURST, rawReaderListener); 711 712 // Prepare still surface to prevent large allocations slow down capture 713 mSession.prepare(mReaderSurface); 714 mSessionListener.waitForSurfacePrepared( 715 mSession, mReaderSurface, PREPARE_TIMEOUT_MS); 716 717 // execute test routine 718 routine.execute(rawBurstBuilder, rawCaptureCallback, rawReaderListener, 719 rawFormat); 720 721 // clear out the surface and camera session 722 stopPreviewAndClearSurface(previewBuilder, rawBurstBuilder); 723 rawReaderListener.drain(); 724 closeImageReader(); 725 } 726 } finally { 727 closeDevice(); 728 } 729 } 730 } 731 } 732