blob: 198c0c1759cf8b8ca30861f8df5fe335f3314dd8 [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>
Sasha Levitskiy0ab4c962014-04-21 14:49:12 -070018#include <inttypes.h>
Igor Murashkinf1b9ae72012-12-07 15:08:35 -080019
20#define LOG_TAG "CameraBurstTest"
21//#define LOG_NDEBUG 0
22#include <utils/Log.h>
Eino-Ville Talvala7d831712013-07-01 18:47:09 -070023#include <utils/Timers.h>
Igor Murashkinf1b9ae72012-12-07 15:08:35 -080024
25#include <cmath>
26
27#include "CameraStreamFixture.h"
28#include "TestExtensions.h"
29
Eino-Ville Talvala7d831712013-07-01 18:47:09 -070030#define CAMERA_FRAME_TIMEOUT 1000000000LL //nsecs (1 secs)
Igor Murashkinf1b9ae72012-12-07 15:08:35 -080031#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
Eino-Ville Talvala4c543a12013-06-25 18:12:19 -070039#define CAMERA_EXPOSURE_FORMAT CAMERA_STREAM_AUTO_CPU_FORMAT
Igor Murashkinf1b9ae72012-12-07 15:08:35 -080040#define CAMERA_EXPOSURE_STARTING 100000 // 1/10ms, up to 51.2ms with 10 steps
41
Eino-Ville Talvala7d831712013-07-01 18:47:09 -070042#define USEC 1000LL // in ns
43#define MSEC 1000000LL // in ns
44#define SEC 1000000000LL // in ns
45
Igor Murashkinf1b9ae72012-12-07 15:08:35 -080046#if CAMERA_BURST_DEBUGGING
47#define dout std::cout
48#else
49#define dout if (0) std::cout
50#endif
51
Bernhard Rosenkränzer1f1d7972014-12-12 22:16:55 +010052#define WARN_UNLESS(condition) if(!(condition)) std::cerr << "Warning: "
Zhijun He60cbb522013-09-18 09:44:19 -070053#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
Igor Murashkinf1b9ae72012-12-07 15:08:35 -080057using namespace android;
58using namespace android::camera2;
59
60namespace android {
61namespace camera2 {
62namespace tests {
63
64static CameraStreamParams STREAM_PARAMETERS = {
Igor Murashkinf1b9ae72012-12-07 15:08:35 -080065 /*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
Eino-Ville Talvala4c543a12013-06-25 18:12:19 -0700100 /* this assumes the format is YUV420sp or flexible YUV */
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800101 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 }
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700136
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
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800153};
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 {
Zhijun Hea1594172013-09-06 15:35:09 -0700192 Vector<int32_t> outputStreamIds;
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800193 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));
Eino-Ville Talvala4c543a12013-06-25 18:12:19 -0700201
202 int requestId = 1;
203 ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_ID,
204 &requestId, 1));
205
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800206 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));
Bernhard Rosenkränzer1f1d7972014-12-12 22:16:55 +0100222 ALOGV("Submitting capture request %d with exposure %" PRId64, i,
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800223 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) {
Bernhard Rosenkränzer1f1d7972014-12-12 22:16:55 +0100234 ALOGV("Reading capture request %d with exposure %" PRId64, i, exposures[i]);
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800235 ASSERT_EQ(OK, mDevice->waitForNextFrame(CAMERA_FRAME_TIMEOUT));
236 ALOGV("Reading capture request-1 %d", i);
Jianing Weif816eea2014-04-10 14:17:57 -0700237 CaptureResult result;
238 ASSERT_EQ(OK, mDevice->getNextResult(&result));
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800239 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
Zhijun He60cbb522013-09-18 09:44:19 -0700282 /**
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;
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800292}
293
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700294/**
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 */
Yin-Chia Yeh8df990b2014-10-31 15:10:11 -0700314TEST_F(CameraBurstTest, VariableBurst) {
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700315
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
Zhijun He3bf3b452013-09-18 23:42:12 -0700366 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
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700383 dout << "Stream size is " << mWidth << " x " << mHeight << std::endl;
384 dout << "Valid exposure range is: " <<
385 minExp << " - " << maxExp << " ns " << std::endl;
386
387 {
Zhijun He7f3ce002013-07-18 17:01:57 -0700388 camera_metadata_ro_entry sensivityRange =
389 GetStaticEntry(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE);
390 EXPECT_EQ(2u, sensivityRange.count) << "No sensitivity range listed."
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700391 "Falling back to default set.";
Zhijun He7f3ce002013-07-18 17:01:57 -0700392 int32_t minSensitivity = 100;
393 int32_t maxSensitivity = 800;
Zhijun He3bf3b452013-09-18 23:42:12 -0700394 if (sensivityRange.count == 2) {
395 ASSERT_GT(sensivityRange.data.i32[0], 0);
396 ASSERT_GT(sensivityRange.data.i32[1], 0);
Zhijun He7f3ce002013-07-18 17:01:57 -0700397 minSensitivity = sensivityRange.data.i32[0];
398 maxSensitivity = sensivityRange.data.i32[1];
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700399 }
Zhijun He7f3ce002013-07-18 17:01:57 -0700400 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);
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700406 }
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 {
Yin-Chia Yeh8df990b2014-10-31 15:10:11 -0700415 if (getDeviceVersion() < CAMERA_DEVICE_API_VERSION_3_2) {
416 camera_metadata_ro_entry availableProcessedSizes =
417 GetStaticEntry(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700418
Yin-Chia Yeh8df990b2014-10-31 15:10:11 -0700419 camera_metadata_ro_entry availableProcessedMinFrameDurations =
420 GetStaticEntry(ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS);
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700421
Yin-Chia Yeh8df990b2014-10-31 15:10:11 -0700422 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";
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700426
Yin-Chia Yeh8df990b2014-10-31 15:10:11 -0700427 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 }
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700436 }
Yin-Chia Yeh8df990b2014-10-31 15:10:11 -0700437 EXPECT_TRUE(gotSize) << "Can't find stream size in list of "
438 "available sizes: " << mWidth << ", " << mHeight;
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700439 }
Yin-Chia Yeh8df990b2014-10-31 15:10:11 -0700440 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);
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700446 }
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700447 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
Zhijun He6e548cf2013-08-08 19:43:24 -0700458 EXPECT_GT(maxDuration, 0) << "Max duration is 0 or not given, using fallback";
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700459
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 {
Zhijun Hea1594172013-09-06 15:35:09 -0700596 Vector<int32_t> outputStreamIds;
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700597 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));
Bernhard Rosenkränzer1f1d7972014-12-12 22:16:55 +0100621 ALOGV("Submitting capture %zu with exposure %" PRId64 ", frame duration %" PRId64 ", sensitivity %d",
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700622 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
Sasha Levitskiy0ab4c962014-04-21 14:49:12 -0700639 ALOGV("Reading request %zu", i);
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700640 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));
Sasha Levitskiy0ab4c962014-04-21 14:49:12 -0700652 ALOGV("Reading capture request-1 %zu", i);
Jianing Weif816eea2014-04-10 14:17:57 -0700653 CaptureResult result;
654 ASSERT_EQ(OK, mDevice->getNextResult(&result));
Sasha Levitskiy0ab4c962014-04-21 14:49:12 -0700655 ALOGV("Reading capture request-2 %zu", i);
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700656
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
Sasha Levitskiy0ab4c962014-04-21 14:49:12 -0700676 ALOGV("Total brightness for frame %zu was %lld (underexposed %d, "
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700677 "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 ) {
Zhijun He60cbb522013-09-18 09:44:19 -0700690 WARN_LT(fabs(brightnesses[i] - brightnesses[i - 1]),
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700691 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: " <<
Zhijun He60cbb522013-09-18 09:44:19 -0700695 brightnesses[i] << ", previous: " << brightnesses[i-1] <<
696 std::endl;
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700697 }
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];
Zhijun He60cbb522013-09-18 09:44:19 -0700704 WARN_LT(timeDelta, expectedDelta + DURATION_UPPER_BOUND) <<
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700705 "Capture took " << timeDelta << " ns to receive, but expected"
Zhijun He60cbb522013-09-18 09:44:19 -0700706 " frame duration was " << expectedDelta << " ns." <<
707 std::endl;
708 WARN_GT(timeDelta, expectedDelta - DURATION_LOWER_BOUND) <<
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700709 "Capture took " << timeDelta << " ns to receive, but expected"
Zhijun He60cbb522013-09-18 09:44:19 -0700710 " frame duration was " << expectedDelta << " ns." <<
711 std::endl;
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700712 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 =
Sasha Levitskiy0ab4c962014-04-21 14:49:12 -0700719 String8::format("/data/local/tmp/camera2_test_variable_burst_frame_%03zu.yuv", i);
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700720 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
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800729}
730}
731}