• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
CameraBurstTest()73     CameraBurstTest() : CameraStreamFixture(STREAM_PARAMETERS) {
74         TEST_EXTENSION_FORKING_CONSTRUCTOR;
75 
76         if (HasFatalFailure()) {
77             return;
78         }
79 
80         CreateStream();
81     }
82 
~CameraBurstTest()83     ~CameraBurstTest() {
84         TEST_EXTENSION_FORKING_DESTRUCTOR;
85 
86         if (mDevice.get()) {
87             mDevice->waitUntilDrained();
88         }
89         DeleteStream();
90     }
91 
SetUp()92     virtual void SetUp() {
93         TEST_EXTENSION_FORKING_SET_UP;
94     }
TearDown()95     virtual void TearDown() {
96         TEST_EXTENSION_FORKING_TEAR_DOWN;
97     }
98 
99     /* this assumes the format is YUV420sp or flexible YUV */
TotalBrightness(const CpuConsumer::LockedBuffer & imgBuffer,int * underexposed,int * overexposed) const100     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>
ParseList(const char * src,Vector<T> & list)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 
TEST_F(CameraBurstTest,ManualExposureControl)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  */
TEST_F(CameraBurstTest,VariableBurst)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