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