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