Home | History | Annotate | Download | only in camera2
      1 /*
      2  * Copyright (C) 2012 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 #include <gtest/gtest.h>
     18 
     19 #define LOG_TAG "CameraBurstTest"
     20 //#define LOG_NDEBUG 0
     21 #include <utils/Log.h>
     22 #include <utils/Timers.h>
     23 
     24 #include <cmath>
     25 
     26 #include "CameraStreamFixture.h"
     27 #include "TestExtensions.h"
     28 
     29 #define CAMERA_FRAME_TIMEOUT    1000000000LL //nsecs (1 secs)
     30 #define CAMERA_HEAP_COUNT       2 //HALBUG: 1 means registerBuffers fails
     31 #define CAMERA_BURST_DEBUGGING  0
     32 #define CAMERA_FRAME_BURST_COUNT 10
     33 
     34 /* constants for the exposure test */
     35 #define CAMERA_EXPOSURE_DOUBLE  2
     36 #define CAMERA_EXPOSURE_DOUBLING_THRESHOLD 1.0f
     37 #define CAMERA_EXPOSURE_DOUBLING_COUNT 4
     38 #define CAMERA_EXPOSURE_FORMAT CAMERA_STREAM_AUTO_CPU_FORMAT
     39 #define CAMERA_EXPOSURE_STARTING 100000 // 1/10ms, up to 51.2ms with 10 steps
     40 
     41 #define USEC 1000LL        // in ns
     42 #define MSEC 1000000LL     // in ns
     43 #define SEC  1000000000LL  // in ns
     44 
     45 #if CAMERA_BURST_DEBUGGING
     46 #define dout std::cout
     47 #else
     48 #define dout if (0) std::cout
     49 #endif
     50 
     51 #define WARN_UNLESS(condition) (!(condition) ? (std::cerr) : (std::ostream(NULL)) << "Warning: ")
     52 #define WARN_LE(exp, act) WARN_UNLESS((exp) <= (act))
     53 #define WARN_LT(exp, act) WARN_UNLESS((exp) < (act))
     54 #define WARN_GT(exp, act) WARN_UNLESS((exp) > (act))
     55 
     56 using namespace android;
     57 using namespace android::camera2;
     58 
     59 namespace android {
     60 namespace camera2 {
     61 namespace tests {
     62 
     63 static CameraStreamParams STREAM_PARAMETERS = {
     64     /*mFormat*/     CAMERA_EXPOSURE_FORMAT,
     65     /*mHeapCount*/  CAMERA_HEAP_COUNT
     66 };
     67 
     68 class CameraBurstTest
     69     : public ::testing::Test,
     70       public CameraStreamFixture {
     71 
     72 public:
     73     CameraBurstTest() : CameraStreamFixture(STREAM_PARAMETERS) {
     74         TEST_EXTENSION_FORKING_CONSTRUCTOR;
     75 
     76         if (HasFatalFailure()) {
     77             return;
     78         }
     79 
     80         CreateStream();
     81     }
     82 
     83     ~CameraBurstTest() {
     84         TEST_EXTENSION_FORKING_DESTRUCTOR;
     85 
     86         if (mDevice.get()) {
     87             mDevice->waitUntilDrained();
     88         }
     89         DeleteStream();
     90     }
     91 
     92     virtual void SetUp() {
     93         TEST_EXTENSION_FORKING_SET_UP;
     94     }
     95     virtual void TearDown() {
     96         TEST_EXTENSION_FORKING_TEAR_DOWN;
     97     }
     98 
     99     /* this assumes the format is YUV420sp or flexible YUV */
    100     long long TotalBrightness(const CpuConsumer::LockedBuffer& imgBuffer,
    101                               int *underexposed,
    102                               int *overexposed) const {
    103 
    104         const uint8_t* buf = imgBuffer.data;
    105         size_t stride = imgBuffer.stride;
    106 
    107         /* iterate over the Y plane only */
    108         long long acc = 0;
    109 
    110         *underexposed = 0;
    111         *overexposed = 0;
    112 
    113         for (size_t y = 0; y < imgBuffer.height; ++y) {
    114             for (size_t x = 0; x < imgBuffer.width; ++x) {
    115                 const uint8_t p = buf[y * stride + x];
    116 
    117                 if (p == 0) {
    118                     if (underexposed) {
    119                         ++*underexposed;
    120                     }
    121                     continue;
    122                 } else if (p == 255) {
    123                     if (overexposed) {
    124                         ++*overexposed;
    125                     }
    126                     continue;
    127                 }
    128 
    129                 acc += p;
    130             }
    131         }
    132 
    133         return acc;
    134     }
    135 
    136     // Parses a comma-separated string list into a Vector
    137     template<typename T>
    138     void ParseList(const char *src, Vector<T> &list) {
    139         std::istringstream s(src);
    140         while (!s.eof()) {
    141             char c = s.peek();
    142             if (c == ',' || c == ' ') {
    143                 s.ignore(1, EOF);
    144                 continue;
    145             }
    146             T val;
    147             s >> val;
    148             list.push_back(val);
    149         }
    150     }
    151 
    152 };
    153 
    154 TEST_F(CameraBurstTest, ManualExposureControl) {
    155 
    156     TEST_EXTENSION_FORKING_INIT;
    157 
    158     // Range of valid exposure times, in nanoseconds
    159     int64_t minExp, maxExp;
    160     {
    161         camera_metadata_ro_entry exposureTimeRange =
    162             GetStaticEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE);
    163 
    164         ASSERT_EQ(2u, exposureTimeRange.count);
    165         minExp = exposureTimeRange.data.i64[0];
    166         maxExp = exposureTimeRange.data.i64[1];
    167     }
    168 
    169     dout << "Min exposure is " << minExp;
    170     dout << " max exposure is " << maxExp << std::endl;
    171 
    172     // Calculate some set of valid exposure times for each request
    173     int64_t exposures[CAMERA_FRAME_BURST_COUNT];
    174     exposures[0] = CAMERA_EXPOSURE_STARTING;
    175     for (int i = 1; i < CAMERA_FRAME_BURST_COUNT; ++i) {
    176         exposures[i] = exposures[i-1] * CAMERA_EXPOSURE_DOUBLE;
    177     }
    178     // Our calculated exposure times should be in [minExp, maxExp]
    179     EXPECT_LE(minExp, exposures[0])
    180         << "Minimum exposure range is too high, wanted at most "
    181         << exposures[0] << "ns";
    182     EXPECT_GE(maxExp, exposures[CAMERA_FRAME_BURST_COUNT-1])
    183         << "Maximum exposure range is too low, wanted at least "
    184         << exposures[CAMERA_FRAME_BURST_COUNT-1] << "ns";
    185 
    186     // Create a preview request, turning off all 3A
    187     CameraMetadata previewRequest;
    188     ASSERT_EQ(OK, mDevice->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
    189                                                 &previewRequest));
    190     {
    191         Vector<int32_t> outputStreamIds;
    192         outputStreamIds.push(mStreamId);
    193         ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS,
    194                                             outputStreamIds));
    195 
    196         // Disable all 3A routines
    197         uint8_t cmOff = static_cast<uint8_t>(ANDROID_CONTROL_MODE_OFF);
    198         ASSERT_EQ(OK, previewRequest.update(ANDROID_CONTROL_MODE,
    199                                             &cmOff, 1));
    200 
    201         int requestId = 1;
    202         ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_ID,
    203                                             &requestId, 1));
    204 
    205         if (CAMERA_BURST_DEBUGGING) {
    206             int frameCount = 0;
    207             ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_FRAME_COUNT,
    208                                                 &frameCount, 1));
    209         }
    210     }
    211 
    212     if (CAMERA_BURST_DEBUGGING) {
    213         previewRequest.dump(STDOUT_FILENO);
    214     }
    215 
    216     // Submit capture requests
    217     for (int i = 0; i < CAMERA_FRAME_BURST_COUNT; ++i) {
    218         CameraMetadata tmpRequest = previewRequest;
    219         ASSERT_EQ(OK, tmpRequest.update(ANDROID_SENSOR_EXPOSURE_TIME,
    220                                         &exposures[i], 1));
    221         ALOGV("Submitting capture request %d with exposure %lld", i,
    222             exposures[i]);
    223         dout << "Capture request " << i << " exposure is "
    224              << (exposures[i]/1e6f) << std::endl;
    225         ASSERT_EQ(OK, mDevice->capture(tmpRequest));
    226     }
    227 
    228     dout << "Buffer dimensions " << mWidth << "x" << mHeight << std::endl;
    229 
    230     float brightnesses[CAMERA_FRAME_BURST_COUNT];
    231     // Get each frame (metadata) and then the buffer. Calculate brightness.
    232     for (int i = 0; i < CAMERA_FRAME_BURST_COUNT; ++i) {
    233         ALOGV("Reading capture request %d with exposure %lld", i, exposures[i]);
    234         ASSERT_EQ(OK, mDevice->waitForNextFrame(CAMERA_FRAME_TIMEOUT));
    235         ALOGV("Reading capture request-1 %d", i);
    236         CameraMetadata frameMetadata;
    237         ASSERT_EQ(OK, mDevice->getNextFrame(&frameMetadata));
    238         ALOGV("Reading capture request-2 %d", i);
    239 
    240         ASSERT_EQ(OK, mFrameListener->waitForFrame(CAMERA_FRAME_TIMEOUT));
    241         ALOGV("We got the frame now");
    242 
    243         CpuConsumer::LockedBuffer imgBuffer;
    244         ASSERT_EQ(OK, mCpuConsumer->lockNextBuffer(&imgBuffer));
    245 
    246         int underexposed, overexposed;
    247         long long brightness = TotalBrightness(imgBuffer, &underexposed,
    248                                                &overexposed);
    249         float avgBrightness = brightness * 1.0f /
    250                               (mWidth * mHeight - (underexposed + overexposed));
    251         ALOGV("Total brightness for frame %d was %lld (underexposed %d, "
    252               "overexposed %d), avg %f", i, brightness, underexposed,
    253               overexposed, avgBrightness);
    254         dout << "Average brightness (frame " << i << ") was " << avgBrightness
    255              << " (underexposed " << underexposed << ", overexposed "
    256              << overexposed << ")" << std::endl;
    257 
    258         ASSERT_EQ(OK, mCpuConsumer->unlockBuffer(imgBuffer));
    259 
    260         brightnesses[i] = avgBrightness;
    261     }
    262 
    263     // Calculate max consecutive frame exposure doubling
    264     float prev = brightnesses[0];
    265     int doubling_count = 1;
    266     int max_doubling_count = 0;
    267     for (int i = 1; i < CAMERA_FRAME_BURST_COUNT; ++i) {
    268         if (fabs(brightnesses[i] - prev*CAMERA_EXPOSURE_DOUBLE)
    269             <= CAMERA_EXPOSURE_DOUBLING_THRESHOLD) {
    270             doubling_count++;
    271         }
    272         else {
    273             max_doubling_count = std::max(max_doubling_count, doubling_count);
    274             doubling_count = 1;
    275         }
    276         prev = brightnesses[i];
    277     }
    278 
    279     dout << "max doubling count: " << max_doubling_count << std::endl;
    280 
    281     /**
    282      * Make this check warning only, since the brightness calculation is not reliable
    283      * and we have separate test to cover this case. Plus it is pretty subtle to make
    284      * it right without complicating the test too much.
    285      */
    286     WARN_LE(CAMERA_EXPOSURE_DOUBLING_COUNT, max_doubling_count)
    287             << "average brightness should double at least "
    288             << CAMERA_EXPOSURE_DOUBLING_COUNT
    289             << " times over each consecutive frame as the exposure is doubled"
    290             << std::endl;
    291 }
    292 
    293 /**
    294  * This test varies exposure time, frame duration, and sensitivity for a
    295  * burst of captures. It picks values by default, but the selection can be
    296  * overridden with the environment variables
    297  *   CAMERA2_TEST_VARIABLE_BURST_EXPOSURE_TIMES
    298  *   CAMERA2_TEST_VARIABLE_BURST_FRAME_DURATIONS
    299  *   CAMERA2_TEST_VARIABLE_BURST_SENSITIVITIES
    300  * which must all be a list of comma-separated values, and each list must be
    301  * the same length.  In addition, if the environment variable
    302  *   CAMERA2_TEST_VARIABLE_BURST_DUMP_FRAMES
    303  * is set to 1, then the YUV buffers are dumped into files named
    304  *   "camera2_test_variable_burst_frame_NNN.yuv"
    305  *
    306  * For example:
    307  *   $ setenv CAMERA2_TEST_VARIABLE_BURST_EXPOSURE_TIMES 10000000,20000000
    308  *   $ setenv CAMERA2_TEST_VARIABLE_BURST_FRAME_DURATIONS 40000000,40000000
    309  *   $ setenv CAMERA2_TEST_VARIABLE_BURST_SENSITIVITIES 200,100
    310  *   $ setenv CAMERA2_TEST_VARIABLE_BURST_DUMP_FRAMES 1
    311  *   $ /data/nativetest/camera2_test/camera2_test --gtest_filter="*VariableBurst"
    312  */
    313 TEST_F(CameraBurstTest, VariableBurst) {
    314 
    315     TEST_EXTENSION_FORKING_INIT;
    316 
    317     // Bounds for checking frame duration is within range
    318     const nsecs_t DURATION_UPPER_BOUND = 10 * MSEC;
    319     const nsecs_t DURATION_LOWER_BOUND = 20 * MSEC;
    320 
    321     // Threshold for considering two captures to have equivalent exposure value,
    322     // as a ratio of the smaller EV to the larger EV.
    323     const float   EV_MATCH_BOUND = 0.95;
    324     // Bound for two captures with equivalent exp values to have the same
    325     // measured brightness, in 0-255 luminance.
    326     const float   BRIGHTNESS_MATCH_BOUND = 5;
    327 
    328     // Environment variables to look for to override test settings
    329     const char *expEnv         = "CAMERA2_TEST_VARIABLE_BURST_EXPOSURE_TIMES";
    330     const char *durationEnv    = "CAMERA2_TEST_VARIABLE_BURST_FRAME_DURATIONS";
    331     const char *sensitivityEnv = "CAMERA2_TEST_VARIABLE_BURST_SENSITIVITIES";
    332     const char *dumpFrameEnv   = "CAMERA2_TEST_VARIABLE_BURST_DUMP_FRAMES";
    333 
    334     // Range of valid exposure times, in nanoseconds
    335     int64_t minExp = 0, maxExp = 0;
    336     // List of valid sensor sensitivities
    337     Vector<int32_t> sensitivities;
    338     // Range of valid frame durations, in nanoseconds
    339     int64_t minDuration = 0, maxDuration = 0;
    340 
    341     {
    342         camera_metadata_ro_entry exposureTimeRange =
    343             GetStaticEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE);
    344 
    345         EXPECT_EQ(2u, exposureTimeRange.count) << "Bad exposure time range tag."
    346                 "Using default values";
    347         if (exposureTimeRange.count == 2) {
    348             minExp = exposureTimeRange.data.i64[0];
    349             maxExp = exposureTimeRange.data.i64[1];
    350         }
    351 
    352         EXPECT_LT(0, minExp) << "Minimum exposure time is 0";
    353         EXPECT_LT(0, maxExp) << "Maximum exposure time is 0";
    354         EXPECT_LE(minExp, maxExp) << "Minimum exposure is greater than maximum";
    355 
    356         if (minExp == 0) {
    357             minExp = 1 * MSEC; // Fallback minimum exposure time
    358         }
    359 
    360         if (maxExp == 0) {
    361             maxExp = 10 * SEC; // Fallback maximum exposure time
    362         }
    363     }
    364 
    365     camera_metadata_ro_entry hardwareLevel =
    366         GetStaticEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL);
    367     ASSERT_EQ(1u, hardwareLevel.count);
    368     uint8_t level = hardwareLevel.data.u8[0];
    369     ASSERT_GE(level, ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED);
    370     ASSERT_LE(level, ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
    371     if (level == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED) {
    372         const ::testing::TestInfo* const test_info =
    373             ::testing::UnitTest::GetInstance()->current_test_info();
    374         std::cerr << "Skipping test "
    375                   << test_info->test_case_name() << "."
    376                   << test_info->name()
    377                   << " because HAL hardware supported level is limited "
    378                   << std::endl;
    379         return;
    380     }
    381 
    382     dout << "Stream size is " << mWidth << " x " << mHeight << std::endl;
    383     dout << "Valid exposure range is: " <<
    384             minExp << " - " << maxExp << " ns " << std::endl;
    385 
    386     {
    387         camera_metadata_ro_entry sensivityRange =
    388             GetStaticEntry(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE);
    389         EXPECT_EQ(2u, sensivityRange.count) << "No sensitivity range listed."
    390                 "Falling back to default set.";
    391         int32_t minSensitivity = 100;
    392         int32_t maxSensitivity = 800;
    393         if (sensivityRange.count == 2) {
    394             ASSERT_GT(sensivityRange.data.i32[0], 0);
    395             ASSERT_GT(sensivityRange.data.i32[1], 0);
    396             minSensitivity = sensivityRange.data.i32[0];
    397             maxSensitivity = sensivityRange.data.i32[1];
    398         }
    399         int32_t count = (maxSensitivity - minSensitivity + 99) / 100;
    400         sensitivities.push_back(minSensitivity);
    401         for (int i = 1; i < count; i++) {
    402             sensitivities.push_back(minSensitivity + i * 100);
    403         }
    404         sensitivities.push_back(maxSensitivity);
    405     }
    406 
    407     dout << "Available sensitivities: ";
    408     for (size_t i = 0; i < sensitivities.size(); i++) {
    409         dout << sensitivities[i] << " ";
    410     }
    411     dout << std::endl;
    412 
    413     {
    414         camera_metadata_ro_entry availableProcessedSizes =
    415                 GetStaticEntry(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
    416 
    417         camera_metadata_ro_entry availableProcessedMinFrameDurations =
    418                 GetStaticEntry(ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS);
    419 
    420         EXPECT_EQ(availableProcessedSizes.count,
    421                 availableProcessedMinFrameDurations.count * 2) <<
    422                 "The number of minimum frame durations doesn't match the number of "
    423                 "available sizes. Using fallback values";
    424 
    425         if (availableProcessedSizes.count ==
    426                 availableProcessedMinFrameDurations.count * 2) {
    427             bool gotSize = false;
    428             for (size_t i = 0; i < availableProcessedSizes.count; i += 2) {
    429                 if (availableProcessedSizes.data.i32[i] == mWidth &&
    430                         availableProcessedSizes.data.i32[i+1] == mHeight) {
    431                     gotSize = true;
    432                     minDuration = availableProcessedMinFrameDurations.data.i64[i/2];
    433                 }
    434             }
    435             EXPECT_TRUE(gotSize) << "Can't find stream size in list of "
    436                     "available sizes: " << mWidth << ", " << mHeight;
    437         }
    438         if (minDuration == 0) {
    439             minDuration = 1 * SEC / 30; // Fall back to 30 fps as minimum duration
    440         }
    441 
    442         ASSERT_LT(0, minDuration);
    443 
    444         camera_metadata_ro_entry maxFrameDuration =
    445                 GetStaticEntry(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION);
    446 
    447         EXPECT_EQ(1u, maxFrameDuration.count) << "No valid maximum frame duration";
    448 
    449         if (maxFrameDuration.count == 1) {
    450             maxDuration = maxFrameDuration.data.i64[0];
    451         }
    452 
    453         EXPECT_GT(maxDuration, 0) << "Max duration is 0 or not given, using fallback";
    454 
    455         if (maxDuration == 0) {
    456             maxDuration = 10 * SEC; // Fall back to 10 seconds as max duration
    457         }
    458 
    459     }
    460     dout << "Available frame duration range for configured stream size: "
    461          << minDuration << " - " << maxDuration << " ns" << std::endl;
    462 
    463     // Get environment variables if set
    464     const char *expVal = getenv(expEnv);
    465     const char *durationVal = getenv(durationEnv);
    466     const char *sensitivityVal = getenv(sensitivityEnv);
    467 
    468     bool gotExp = (expVal != NULL);
    469     bool gotDuration = (durationVal != NULL);
    470     bool gotSensitivity = (sensitivityVal != NULL);
    471 
    472     // All or none must be provided if using override envs
    473     ASSERT_TRUE( (gotDuration && gotExp && gotSensitivity) ||
    474             (!gotDuration && !gotExp && !gotSensitivity) ) <<
    475             "Incomplete set of environment variable overrides provided";
    476 
    477     Vector<int64_t> expList, durationList;
    478     Vector<int32_t> sensitivityList;
    479     if (gotExp) {
    480         ParseList(expVal, expList);
    481         ParseList(durationVal, durationList);
    482         ParseList(sensitivityVal, sensitivityList);
    483 
    484         ASSERT_TRUE(
    485             (expList.size() == durationList.size()) &&
    486             (durationList.size() == sensitivityList.size())) <<
    487                 "Mismatched sizes in env lists, or parse error";
    488 
    489         dout << "Using burst list from environment with " << expList.size() <<
    490                 " captures" << std::endl;
    491     } else {
    492         // Create a default set of controls based on the available ranges
    493 
    494         int64_t e;
    495         int64_t d;
    496         int32_t s;
    497 
    498         // Exposure ramp
    499 
    500         e = minExp;
    501         d = minDuration;
    502         s = sensitivities[0];
    503         while (e < maxExp) {
    504             expList.push_back(e);
    505             durationList.push_back(d);
    506             sensitivityList.push_back(s);
    507             e = e * 2;
    508         }
    509         e = maxExp;
    510         expList.push_back(e);
    511         durationList.push_back(d);
    512         sensitivityList.push_back(s);
    513 
    514         // Duration ramp
    515 
    516         e = 30 * MSEC;
    517         d = minDuration;
    518         s = sensitivities[0];
    519         while (d < maxDuration) {
    520             // make sure exposure <= frame duration
    521             expList.push_back(e > d ? d : e);
    522             durationList.push_back(d);
    523             sensitivityList.push_back(s);
    524             d = d * 2;
    525         }
    526 
    527         // Sensitivity ramp
    528 
    529         e = 30 * MSEC;
    530         d = 30 * MSEC;
    531         d = d > minDuration ? d : minDuration;
    532         for (size_t i = 0; i < sensitivities.size(); i++) {
    533             expList.push_back(e);
    534             durationList.push_back(d);
    535             sensitivityList.push_back(sensitivities[i]);
    536         }
    537 
    538         // Constant-EV ramp, duration == exposure
    539 
    540         e = 30 * MSEC; // at ISO 100
    541         for (size_t i = 0; i < sensitivities.size(); i++) {
    542             int64_t e_adj = e * 100 / sensitivities[i];
    543             expList.push_back(e_adj);
    544             durationList.push_back(e_adj > minDuration ? e_adj : minDuration);
    545             sensitivityList.push_back(sensitivities[i]);
    546         }
    547 
    548         dout << "Default burst sequence created with " << expList.size() <<
    549                 " entries" << std::endl;
    550     }
    551 
    552     // Validate the list, but warn only
    553     for (size_t i = 0; i < expList.size(); i++) {
    554         EXPECT_GE(maxExp, expList[i])
    555                 << "Capture " << i << " exposure too long: " << expList[i];
    556         EXPECT_LE(minExp, expList[i])
    557                 << "Capture " << i << " exposure too short: " << expList[i];
    558         EXPECT_GE(maxDuration, durationList[i])
    559                 << "Capture " << i << " duration too long: " << durationList[i];
    560         EXPECT_LE(minDuration, durationList[i])
    561                  << "Capture " << i << " duration too short: "  << durationList[i];
    562         bool validSensitivity = false;
    563         for (size_t j = 0; j < sensitivities.size(); j++) {
    564             if (sensitivityList[i] == sensitivities[j]) {
    565                 validSensitivity = true;
    566                 break;
    567             }
    568         }
    569         EXPECT_TRUE(validSensitivity)
    570                 << "Capture " << i << " sensitivity not in list: " << sensitivityList[i];
    571     }
    572 
    573     // Check if debug yuv dumps are requested
    574 
    575     bool dumpFrames = false;
    576     {
    577         const char *frameDumpVal = getenv(dumpFrameEnv);
    578         if (frameDumpVal != NULL) {
    579             if (frameDumpVal[0] == '1') dumpFrames = true;
    580         }
    581     }
    582 
    583     dout << "Dumping YUV frames " <<
    584             (dumpFrames ? "enabled, not checking timing" : "disabled") << std::endl;
    585 
    586     // Create a base preview request, turning off all 3A
    587     CameraMetadata previewRequest;
    588     ASSERT_EQ(OK, mDevice->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
    589                                                 &previewRequest));
    590     {
    591         Vector<int32_t> outputStreamIds;
    592         outputStreamIds.push(mStreamId);
    593         ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS,
    594                                             outputStreamIds));
    595 
    596         // Disable all 3A routines
    597         uint8_t cmOff = static_cast<uint8_t>(ANDROID_CONTROL_MODE_OFF);
    598         ASSERT_EQ(OK, previewRequest.update(ANDROID_CONTROL_MODE,
    599                                             &cmOff, 1));
    600 
    601         int requestId = 1;
    602         ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_ID,
    603                                             &requestId, 1));
    604     }
    605 
    606     // Submit capture requests
    607 
    608     for (size_t i = 0; i < expList.size(); ++i) {
    609         CameraMetadata tmpRequest = previewRequest;
    610         ASSERT_EQ(OK, tmpRequest.update(ANDROID_SENSOR_EXPOSURE_TIME,
    611                                         &expList[i], 1));
    612         ASSERT_EQ(OK, tmpRequest.update(ANDROID_SENSOR_FRAME_DURATION,
    613                                         &durationList[i], 1));
    614         ASSERT_EQ(OK, tmpRequest.update(ANDROID_SENSOR_SENSITIVITY,
    615                                         &sensitivityList[i], 1));
    616         ALOGV("Submitting capture %d with exposure %lld, frame duration %lld, sensitivity %d",
    617                 i, expList[i], durationList[i], sensitivityList[i]);
    618         dout << "Capture request " << i <<
    619                 ": exposure is " << (expList[i]/1e6f) << " ms" <<
    620                 ", frame duration is " << (durationList[i]/1e6f) << " ms" <<
    621                 ", sensitivity is " << sensitivityList[i] <<
    622                 std::endl;
    623         ASSERT_EQ(OK, mDevice->capture(tmpRequest));
    624     }
    625 
    626     Vector<float> brightnesses;
    627     Vector<nsecs_t> captureTimes;
    628     brightnesses.setCapacity(expList.size());
    629     captureTimes.setCapacity(expList.size());
    630 
    631     // Get each frame (metadata) and then the buffer. Calculate brightness.
    632     for (size_t i = 0; i < expList.size(); ++i) {
    633 
    634         ALOGV("Reading request %d", i);
    635         dout << "Waiting for capture " << i << ": " <<
    636                 " exposure " << (expList[i]/1e6f) << " ms," <<
    637                 " frame duration " << (durationList[i]/1e6f) << " ms," <<
    638                 " sensitivity " << sensitivityList[i] <<
    639                 std::endl;
    640 
    641         // Set wait limit based on expected frame duration, or minimum timeout
    642         int64_t waitLimit = CAMERA_FRAME_TIMEOUT;
    643         if (expList[i] * 2 > waitLimit) waitLimit = expList[i] * 2;
    644         if (durationList[i] * 2 > waitLimit) waitLimit = durationList[i] * 2;
    645 
    646         ASSERT_EQ(OK, mDevice->waitForNextFrame(waitLimit));
    647         ALOGV("Reading capture request-1 %d", i);
    648         CameraMetadata frameMetadata;
    649         ASSERT_EQ(OK, mDevice->getNextFrame(&frameMetadata));
    650         ALOGV("Reading capture request-2 %d", i);
    651 
    652         ASSERT_EQ(OK, mFrameListener->waitForFrame(CAMERA_FRAME_TIMEOUT));
    653         ALOGV("We got the frame now");
    654 
    655         captureTimes.push_back(systemTime());
    656 
    657         CpuConsumer::LockedBuffer imgBuffer;
    658         ASSERT_EQ(OK, mCpuConsumer->lockNextBuffer(&imgBuffer));
    659 
    660         int underexposed, overexposed;
    661         float avgBrightness = 0;
    662         long long brightness = TotalBrightness(imgBuffer, &underexposed,
    663                                                &overexposed);
    664         int numValidPixels = mWidth * mHeight - (underexposed + overexposed);
    665         if (numValidPixels != 0) {
    666             avgBrightness = brightness * 1.0f / numValidPixels;
    667         } else if (underexposed < overexposed) {
    668             avgBrightness = 255;
    669         }
    670 
    671         ALOGV("Total brightness for frame %d was %lld (underexposed %d, "
    672               "overexposed %d), avg %f", i, brightness, underexposed,
    673               overexposed, avgBrightness);
    674         dout << "Average brightness (frame " << i << ") was " << avgBrightness
    675              << " (underexposed " << underexposed << ", overexposed "
    676              << overexposed << ")" << std::endl;
    677         brightnesses.push_back(avgBrightness);
    678 
    679         if (i != 0) {
    680             float prevEv = static_cast<float>(expList[i - 1]) * sensitivityList[i - 1];
    681             float currentEv = static_cast<float>(expList[i]) * sensitivityList[i];
    682             float evRatio = (prevEv > currentEv) ? (currentEv / prevEv) :
    683                     (prevEv / currentEv);
    684             if ( evRatio > EV_MATCH_BOUND ) {
    685                 WARN_LT(fabs(brightnesses[i] - brightnesses[i - 1]),
    686                         BRIGHTNESS_MATCH_BOUND) <<
    687                         "Capture brightness different from previous, even though "
    688                         "they have the same EV value. Ev now: " << currentEv <<
    689                         ", previous: " << prevEv << ". Brightness now: " <<
    690                         brightnesses[i] << ", previous: " << brightnesses[i-1] <<
    691                         std::endl;
    692             }
    693             // Only check timing if not saving to disk, since that slows things
    694             // down substantially
    695             if (!dumpFrames) {
    696                 nsecs_t timeDelta = captureTimes[i] - captureTimes[i-1];
    697                 nsecs_t expectedDelta = expList[i] > durationList[i] ?
    698                         expList[i] : durationList[i];
    699                 WARN_LT(timeDelta, expectedDelta + DURATION_UPPER_BOUND) <<
    700                         "Capture took " << timeDelta << " ns to receive, but expected"
    701                         " frame duration was " << expectedDelta << " ns." <<
    702                         std::endl;
    703                 WARN_GT(timeDelta, expectedDelta - DURATION_LOWER_BOUND) <<
    704                         "Capture took " << timeDelta << " ns to receive, but expected"
    705                         " frame duration was " << expectedDelta << " ns." <<
    706                         std::endl;
    707                 dout << "Time delta from previous frame: " << timeDelta / 1e6 <<
    708                         " ms.  Expected " << expectedDelta / 1e6 << " ms" << std::endl;
    709             }
    710         }
    711 
    712         if (dumpFrames) {
    713             String8 dumpName =
    714                     String8::format("/data/local/tmp/camera2_test_variable_burst_frame_%03d.yuv", i);
    715             dout << "  Writing YUV dump to " << dumpName << std::endl;
    716             DumpYuvToFile(dumpName, imgBuffer);
    717         }
    718 
    719         ASSERT_EQ(OK, mCpuConsumer->unlockBuffer(imgBuffer));
    720     }
    721 
    722 }
    723 
    724 }
    725 }
    726 }
    727