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.testcases.Camera2SurfaceViewTestCase; 31 import android.hardware.camera2.params.StreamConfigurationMap; 32 import android.media.Image; 33 import android.util.Log; 34 import android.util.Range; 35 import android.util.Size; 36 37 import java.util.ArrayList; 38 39 /** 40 * Basic tests for burst capture in RAW formats. 41 */ 42 public class BurstCaptureRawTest extends Camera2SurfaceViewTestCase { 43 private static final String TAG = "BurstCaptureRawTest"; 44 private static final int RAW_FORMATS[] = { 45 ImageFormat.RAW10, ImageFormat.RAW12, ImageFormat.RAW_SENSOR }; 46 private static final int NONSTALL_RAW_FORMATS[] = { 47 ImageFormat.RAW10, ImageFormat.RAW12 }; 48 private static final long EXPOSURE_MULTIPLIERS[] = { 49 1, 3, 5 }; 50 private static final int SENSITIVITY_MLTIPLIERS[] = { 51 1, 3, 5 }; 52 private static final int MAX_FRAMES_BURST = 53 EXPOSURE_MULTIPLIERS.length * SENSITIVITY_MLTIPLIERS.length; 54 55 @Override setUp()56 protected void setUp() throws Exception { 57 super.setUp(); 58 } 59 60 @Override tearDown()61 protected void tearDown() throws Exception { 62 super.tearDown(); 63 } 64 65 /** 66 * Verify raw sensor size information is correctly configured. 67 */ testRawSensorSize()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); 75 if (!checkCapability(supportedRawList, RAW_FORMATS)) { 76 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 84 // Check happens in getRawDimensChecked. 85 Size rawSize = mStaticInfo.getRawDimensChecked(); 86 } finally { 87 closeDevice(); 88 } 89 } 90 Log.i(TAG, "End testRawSensorSize"); 91 } 92 93 /** 94 * Round [exposure, gain] down, rather than to the nearest, in RAW 10/16 95 * <p> 96 * Verify the value of metadata (exposure and sensitivity) is rounded down if the request cannot 97 * be honored. 98 * </p> 99 */ testMetadataRoundDown()100 public void testMetadataRoundDown() throws Exception { 101 Log.i(TAG, "Begin testMetadataRoundDown"); 102 103 performTestRoutine(new TestMetaDataRoundDownRoutine(), RAW_FORMATS); 104 105 Log.i(TAG, "End testMetadataRoundDown"); 106 } 107 108 /** 109 * Manual and Auto setting test in RAW formats 110 * <p> 111 * Make sure switching between manual and auto setting would not make the capture results out of 112 * sync. 113 * </p> 114 */ testManualAutoSwitch()115 public void testManualAutoSwitch() throws Exception { 116 Log.i(TAG, "Begin testManualAutoSwitch"); 117 118 performTestRoutine(new TestManualAutoSwitch(), RAW_FORMATS); 119 120 Log.i(TAG, "End testManualAutoSwitch"); 121 } 122 123 /** 124 * Per frame timestamp test in non-stalled RAW formats 125 */ testTimestamp()126 public void testTimestamp() throws Exception { 127 Log.i(TAG, "Begin testTimestamp"); 128 129 performTestRoutine(new TestTimestamp(), NONSTALL_RAW_FORMATS); 130 131 Log.i(TAG, "End testTimestamp"); 132 } 133 134 /* 135 * Below are private infrastructure for all tests 136 */ 137 138 /** 139 * A structure encapsulates all the parameters for setting up preview, and RAW capture. 140 */ 141 class CaptureSetup 142 { CaptureSetup(Size previewCaptureSize, Size rawCaptureSize, CaptureRequest.Builder previewRequestBuilder, CaptureRequest.Builder rawRequestBuilder, SimpleCaptureCallback previewCaptureCallback, SimpleCaptureCallback rawCaptureCallback, SimpleImageReaderListener rawReaderListener)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 } 158 getPreviewCaptureSize()159 public Size getPreviewCaptureSize() 160 { 161 return mPreviewCaptureSize; 162 } 163 getRawCaptureSize()164 public Size getRawCaptureSize() 165 { 166 return mRawCaptureSize; 167 } 168 getPreviewRequestBuilder()169 public CaptureRequest.Builder getPreviewRequestBuilder() 170 { 171 return mPreviewRequestBuilder; 172 } 173 getRawRequestBuilder()174 public CaptureRequest.Builder getRawRequestBuilder() { 175 return mRawRequestBuilder; 176 } 177 getPreviewCaptureCallback()178 public SimpleCaptureCallback getPreviewCaptureCallback() { 179 return mPreviewCaptureCallback; 180 } 181 getRawCaptureCallback()182 public SimpleCaptureCallback getRawCaptureCallback() { 183 return mRawCaptureCallback; 184 } 185 getRawReaderListener()186 public SimpleImageReaderListener getRawReaderListener() { 187 return mRawReaderListener; 188 } 189 190 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 { execute(CaptureRequest.Builder rawBurstBuilder, SimpleCaptureCallback rawCaptureCallback, SimpleImageReaderListener rawReaderListener, int rawFormat)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 execute(CaptureRequest.Builder rawBurstBuilder, SimpleCaptureCallback rawCaptureCallback, SimpleImageReaderListener rawReaderListener, int rawFormat)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); 259 } 260 } 261 } 262 263 /** 264 * Implementation of manual-auto switching test. 265 */ 266 class TestManualAutoSwitch implements TestRoutine 267 { 268 @Override execute(CaptureRequest.Builder rawBurstBuilder, SimpleCaptureCallback rawCaptureCallback, SimpleImageReaderListener rawReaderListener, int rawFormat)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 } 347 } 348 349 /** 350 * 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 execute(Builder rawBurstBuilder, SimpleCaptureCallback rawCaptureCallback, SimpleImageReaderListener rawReaderListener, int rawFormat)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 /** 434 * Check sensor capability prior to the test. 435 * 436 * @return true if the it is has the capability to execute the test. 437 */ checkCapability(ArrayList<Integer> supportedRawList, int[] testedFormats)438 private boolean checkCapability(ArrayList<Integer> supportedRawList, int[] testedFormats) { 439 // make sure the sensor has manual support 440 if (!mStaticInfo.isHardwareLevelAtLeastFull()) { 441 Log.w(TAG, "Full hardware level is not supported"); 442 return false; 443 } 444 445 // get the list of supported RAW format 446 StreamConfigurationMap config = mStaticInfo.getValueFromKeyNonNull( 447 CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 448 449 // check for the RAW support 450 supportedRawList.clear(); 451 for (int rawFormat : testedFormats) { 452 if (!config.isOutputSupportedFor(rawFormat)) { 453 continue; 454 } 455 supportedRawList.add(rawFormat); 456 } 457 458 if (supportedRawList.size() == 0) 459 { 460 Log.w(TAG, "RAW output is not supported!"); 461 return false; 462 } 463 464 return true; 465 } 466 467 /** 468 * Return the sensor format to human readable string. 469 * 470 * @param format Sensor image format. 471 * @return Human readable string. 472 */ imageFormatToString(int format)473 private String imageFormatToString(int format) { 474 switch (format) { 475 case ImageFormat.RAW10: 476 return "RAW10"; 477 case ImageFormat.RAW12: 478 return "RAW12"; 479 case ImageFormat.RAW_SENSOR: 480 return "RAW_SENSOR"; 481 } 482 483 return "Unknown"; 484 } 485 486 /** 487 * Setting up various classes prior to the request, e.g.: capture size, builder, callback and 488 * listener 489 * 490 * @return initialized variables that can be directly fed into prepareCaptureAndStartPreview(). 491 */ initCaptureSetupForPreviewAndRaw()492 private CaptureSetup initCaptureSetupForPreviewAndRaw() throws Exception 493 { 494 // capture size 495 Size previewSize = mOrderedPreviewSizes.get(0); 496 Size rawSize = mStaticInfo.getRawDimensChecked(); 497 498 // builder 499 CaptureRequest.Builder previewCaptureBuilder = mCamera.createCaptureRequest( 500 CameraDevice.TEMPLATE_PREVIEW); 501 CaptureRequest.Builder rawCaptureBuilder = mCamera.createCaptureRequest( 502 CameraDevice.TEMPLATE_STILL_CAPTURE); 503 504 // callback 505 SimpleCaptureCallback previewCaptureCallback = new SimpleCaptureCallback(); 506 SimpleCaptureCallback rawCaptureCallback = new SimpleCaptureCallback(); 507 SimpleImageReaderListener rawReaderListener = new SimpleImageReaderListener(); 508 509 CaptureSetup setup = new CaptureSetup(previewSize, rawSize, previewCaptureBuilder, 510 rawCaptureBuilder, previewCaptureCallback, rawCaptureCallback, rawReaderListener); 511 512 return setup; 513 } 514 515 /** 516 * Construct an array of burst request with manual exposure and sensitivity. 517 * <p> 518 * For each capture request, 3A and post processing (noise reduction, sharpening, etc) will be 519 * turned off. Then exposure and sensitivity value will be configured, which are determined by 520 * EXPOSURE_MULIPLIERS and SENSITIVITY_MULTIPLIERS. 521 * </p> 522 * 523 * @param rawBurstBuilder The builder needs to have targets setup. 524 * @return An array list capture request for burst. 525 */ createBurstRequest(CaptureRequest.Builder rawBurstBuilder)526 private ArrayList<CaptureRequest> createBurstRequest(CaptureRequest.Builder rawBurstBuilder) 527 { 528 return createBurstRequest(rawBurstBuilder, EXPOSURE_MULTIPLIERS, SENSITIVITY_MLTIPLIERS); 529 } 530 createBurstRequest(CaptureRequest.Builder rawBurstBuilder, long[] exposureMultipliers, int[] sensitivityMultipliers)531 private ArrayList<CaptureRequest> createBurstRequest(CaptureRequest.Builder rawBurstBuilder, 532 long[] exposureMultipliers, int[] sensitivityMultipliers) { 533 // set manual mode 534 rawBurstBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF); 535 rawBurstBuilder.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_OFF); 536 rawBurstBuilder.set(CaptureRequest.NOISE_REDUCTION_MODE, 537 CaptureRequest.NOISE_REDUCTION_MODE_OFF); 538 rawBurstBuilder.set(CaptureRequest.EDGE_MODE, CaptureRequest.EDGE_MODE_OFF); 539 // exposure has higher priority over frame duration; therefore the frame readout time: 540 // exposure time + overhead 541 rawBurstBuilder.set(CaptureRequest.SENSOR_FRAME_DURATION, 0L); 542 543 // get the exposure and sensitivity range 544 Range<Long> exposureRangeNs = new Range<Long>(mStaticInfo.getExposureMinimumOrDefault(), 545 mStaticInfo.getExposureMaximumOrDefault()); 546 547 Range<Integer> isoRange = new Range<Integer>(mStaticInfo.getSensitivityMinimumOrDefault(), 548 mStaticInfo.getSensitivityMaximumOrDefault()); 549 550 Log.i(TAG, String.format("Exposure time - max: %d, min: %d.", exposureRangeNs.getUpper(), 551 exposureRangeNs.getLower())); 552 Log.i(TAG, String.format("Sensitivity - max: %d, min: %d.", isoRange.getUpper(), 553 isoRange.getLower())); 554 555 // building burst request 556 int maxFramesBurst = exposureMultipliers.length * sensitivityMultipliers.length; 557 Log.i(TAG, String.format("Setting up burst = %d frames.", maxFramesBurst)); 558 ArrayList<CaptureRequest> rawRequestList = new ArrayList<CaptureRequest>(maxFramesBurst); 559 560 for (int i = 0; i < exposureMultipliers.length; i++) { 561 for (int j = 0; j < sensitivityMultipliers.length; j++) { 562 long desiredExposure = Math.min( 563 exposureRangeNs.getLower() * exposureMultipliers[i], 564 exposureRangeNs.getUpper()); 565 566 int desiredSensitivity = 567 Math.min(isoRange.getLower() * sensitivityMultipliers[j], 568 isoRange.getUpper()); 569 570 rawBurstBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, desiredExposure); 571 rawBurstBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, desiredSensitivity); 572 573 rawRequestList.add(rawBurstBuilder.build()); 574 } 575 } 576 return rawRequestList; 577 } 578 579 /** 580 * Construct an array of burst request with 3A 581 * <p> 582 * For each capture request, 3A and post processing (noise reduction, sharpening, etc) will be 583 * turned on. 584 * </p> 585 * 586 * @param rawBurstBuilder The builder needs to have targets setup. 587 * @return An array list capture request for burst. 588 */ createBurstRequestWith3A( CaptureRequest.Builder rawBurstBuilder)589 private ArrayList<CaptureRequest> createBurstRequestWith3A( 590 CaptureRequest.Builder rawBurstBuilder) 591 { 592 // set 3A mode to simulate regular still capture 593 rawBurstBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON); 594 rawBurstBuilder.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_AUTO); 595 rawBurstBuilder.set(CaptureRequest.NOISE_REDUCTION_MODE, 596 CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY); 597 rawBurstBuilder.set(CaptureRequest.EDGE_MODE, CaptureRequest.EDGE_MODE_HIGH_QUALITY); 598 599 // building burst request 600 Log.i(TAG, String.format("Setting up burst = %d frames.", MAX_FRAMES_BURST)); 601 ArrayList<CaptureRequest> rawRequestList = new ArrayList<CaptureRequest>(MAX_FRAMES_BURST); 602 603 for (int i = 0; i < MAX_FRAMES_BURST; i++) { 604 rawRequestList.add(rawBurstBuilder.build()); 605 } 606 607 return rawRequestList; 608 } 609 610 /** 611 * An utility method to copy capture request builders. This is used for recovery purpose to 612 * reverse the changes we made to the builder. 613 * 614 * @param dst the builder to write into. 615 * @param src the builder that needs to be copied. 616 */ copyBurstRequetBuilder(CaptureRequest.Builder dst, CaptureRequest.Builder src)617 private void copyBurstRequetBuilder(CaptureRequest.Builder dst, CaptureRequest.Builder src) 618 { 619 dst.set(CaptureRequest.CONTROL_AE_MODE, src.get(CaptureRequest.CONTROL_AE_MODE)); 620 dst.set(CaptureRequest.CONTROL_AWB_MODE, src.get(CaptureRequest.CONTROL_AWB_MODE)); 621 dst.set(CaptureRequest.NOISE_REDUCTION_MODE, src.get(CaptureRequest.NOISE_REDUCTION_MODE)); 622 dst.set(CaptureRequest.EDGE_MODE, src.get(CaptureRequest.EDGE_MODE)); 623 dst.set(CaptureRequest.SENSOR_FRAME_DURATION, 624 src.get(CaptureRequest.SENSOR_FRAME_DURATION)); 625 dst.set(CaptureRequest.SENSOR_EXPOSURE_TIME, src.get(CaptureRequest.SENSOR_EXPOSURE_TIME)); 626 dst.set(CaptureRequest.SENSOR_SENSITIVITY, src.get(CaptureRequest.SENSOR_SENSITIVITY)); 627 } 628 629 /** 630 * Draining the image reader and capture callback queue 631 * 632 * @param readerListener Image reader listener needs to be drained. 633 * @param captureCallback Capture callback needs to be drained. 634 * @throws Exception Exception from the queue. 635 */ drainQueues(SimpleImageReaderListener readerListener, SimpleCaptureCallback captureCallback)636 private void drainQueues(SimpleImageReaderListener readerListener, 637 SimpleCaptureCallback captureCallback) throws Exception 638 { 639 for (int i = 0; i < MAX_FRAMES_BURST; i++) { 640 Image image = readerListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS); 641 image.close(); 642 643 CaptureResult result = captureCallback.getCaptureResult( 644 CAPTURE_IMAGE_TIMEOUT_MS); 645 long timestamp = result.get(CaptureResult.SENSOR_TIMESTAMP); 646 Log.d(TAG, String.format("timestamp = %d", timestamp)); 647 } 648 } 649 650 /** 651 * Stop preview and remove the target surfaces inside the CaptureRequest.Builder. 652 * 653 * @param previewBuilder Configured builder for preview. 654 * @param rawBurstBuilder Configured builder for RAW. 655 * @throws Exception Exceptions from stopPreview. 656 */ stopPreviewAndClearSurface(CaptureRequest.Builder previewBuilder, CaptureRequest.Builder rawBurstBuilder)657 private void stopPreviewAndClearSurface(CaptureRequest.Builder previewBuilder, 658 CaptureRequest.Builder rawBurstBuilder) throws Exception 659 { 660 previewBuilder.removeTarget(mPreviewSurface); 661 rawBurstBuilder.removeTarget(mPreviewSurface); 662 rawBurstBuilder.removeTarget(mReaderSurface); 663 664 stopPreview(); 665 } 666 performTestRoutine(TestRoutine routine, int[] testedFormats)667 private void performTestRoutine(TestRoutine routine, int[] testedFormats) throws Exception 668 { 669 final int PREPARE_TIMEOUT_MS = 10000; 670 for (String id : mCameraIds) { 671 try { 672 openDevice(id); 673 674 ArrayList<Integer> supportedRawList = new ArrayList<Integer>(RAW_FORMATS.length); 675 if (!checkCapability(supportedRawList, testedFormats)) { 676 Log.i(TAG, "Capability is not supported on camera " + id 677 + ". Skip the test."); 678 continue; 679 } 680 681 // test each supported RAW format 682 for (int rawFormat : supportedRawList) { 683 Log.i(TAG, "Testing format " + imageFormatToString(rawFormat) + "."); 684 685 // prepare preview and still RAW capture 686 CaptureSetup captureSetup = initCaptureSetupForPreviewAndRaw(); 687 688 Size previewCaptureSize = captureSetup.getPreviewCaptureSize(); 689 Size rawCaptureSize = captureSetup.getRawCaptureSize(); 690 691 CaptureRequest.Builder previewBuilder = captureSetup.getPreviewRequestBuilder(); 692 CaptureRequest.Builder rawBurstBuilder = captureSetup.getRawRequestBuilder(); 693 694 SimpleCaptureCallback previewCaptureCallback = 695 captureSetup.getPreviewCaptureCallback(); 696 SimpleCaptureCallback rawCaptureCallback = captureSetup.getRawCaptureCallback(); 697 SimpleImageReaderListener rawReaderListener = captureSetup 698 .getRawReaderListener(); 699 700 // start preview and prepare RAW capture 701 prepareCaptureAndStartPreview(previewBuilder, rawBurstBuilder, 702 previewCaptureSize, rawCaptureSize, rawFormat, previewCaptureCallback, 703 MAX_FRAMES_BURST, rawReaderListener); 704 705 // Prepare still surface to prevent large allocations slow down capture 706 mSession.prepare(mReaderSurface); 707 mSessionListener.waitForSurfacePrepared( 708 mSession, mReaderSurface, PREPARE_TIMEOUT_MS); 709 710 // execute test routine 711 routine.execute(rawBurstBuilder, rawCaptureCallback, rawReaderListener, 712 rawFormat); 713 714 // clear out the surface and camera session 715 stopPreviewAndClearSurface(previewBuilder, rawBurstBuilder); 716 rawReaderListener.drain(); 717 closeImageReader(); 718 } 719 } finally { 720 closeDevice(); 721 } 722 } 723 } 724 } 725