blob: 47fcb3e8c4e8b77d6dd7e40a3ee28b6064cbd777 [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
Zhijun He60cbb522013-09-18 09:44:19 -070051#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
Igor Murashkinf1b9ae72012-12-07 15:08:35 -080056using namespace android;
57using namespace android::camera2;
58
59namespace android {
60namespace camera2 {
61namespace tests {
62
63static CameraStreamParams STREAM_PARAMETERS = {
Igor Murashkinf1b9ae72012-12-07 15:08:35 -080064 /*mFormat*/ CAMERA_EXPOSURE_FORMAT,
65 /*mHeapCount*/ CAMERA_HEAP_COUNT
66};
67
68class CameraBurstTest
69 : public ::testing::Test,
70 public CameraStreamFixture {
71
72public:
73 CameraBurstTest() : CameraStreamFixture(STREAM_PARAMETERS) {
74 TEST_EXTENSION_FORKING_CONSTRUCTOR;
75
76 if (HasFatalFailure()) {
77 return;
78 }
79
80 CreateStream();
81 }
82
83 ~CameraBurstTest() {
84 TEST_EXTENSION_FORKING_DESTRUCTOR;
85
86 if (mDevice.get()) {
87 mDevice->waitUntilDrained();
88 }
89 DeleteStream();
90 }
91
92 virtual void SetUp() {
93 TEST_EXTENSION_FORKING_SET_UP;
94 }
95 virtual void TearDown() {
96 TEST_EXTENSION_FORKING_TEAR_DOWN;
97 }
98
Eino-Ville Talvala4c543a12013-06-25 18:12:19 -070099 /* this assumes the format is YUV420sp or flexible YUV */
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800100 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 }
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700135
136 // Parses a comma-separated string list into a Vector
137 template<typename T>
138 void ParseList(const char *src, Vector<T> &list) {
139 std::istringstream s(src);
140 while (!s.eof()) {
141 char c = s.peek();
142 if (c == ',' || c == ' ') {
143 s.ignore(1, EOF);
144 continue;
145 }
146 T val;
147 s >> val;
148 list.push_back(val);
149 }
150 }
151
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800152};
153
154TEST_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 {
Zhijun Hea1594172013-09-06 15:35:09 -0700191 Vector<int32_t> outputStreamIds;
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800192 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));
Eino-Ville Talvala4c543a12013-06-25 18:12:19 -0700200
201 int requestId = 1;
202 ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_ID,
203 &requestId, 1));
204
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800205 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
Zhijun He60cbb522013-09-18 09:44:19 -0700281 /**
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;
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800291}
292
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700293/**
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 */
313TEST_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 dout << "Stream size is " << mWidth << " x " << mHeight << std::endl;
366 dout << "Valid exposure range is: " <<
367 minExp << " - " << maxExp << " ns " << std::endl;
368
369 {
Zhijun He7f3ce002013-07-18 17:01:57 -0700370 camera_metadata_ro_entry sensivityRange =
371 GetStaticEntry(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE);
372 EXPECT_EQ(2u, sensivityRange.count) << "No sensitivity range listed."
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700373 "Falling back to default set.";
Zhijun He7f3ce002013-07-18 17:01:57 -0700374 int32_t minSensitivity = 100;
375 int32_t maxSensitivity = 800;
376 if (sensivityRange.count >= 2) {
377 minSensitivity = sensivityRange.data.i32[0];
378 maxSensitivity = sensivityRange.data.i32[1];
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700379 }
Zhijun He7f3ce002013-07-18 17:01:57 -0700380 int32_t count = (maxSensitivity - minSensitivity + 99) / 100;
381 sensitivities.push_back(minSensitivity);
382 for (int i = 1; i < count; i++) {
383 sensitivities.push_back(minSensitivity + i * 100);
384 }
385 sensitivities.push_back(maxSensitivity);
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700386 }
387
388 dout << "Available sensitivities: ";
389 for (size_t i = 0; i < sensitivities.size(); i++) {
390 dout << sensitivities[i] << " ";
391 }
392 dout << std::endl;
393
394 {
395 camera_metadata_ro_entry availableProcessedSizes =
396 GetStaticEntry(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
397
398 camera_metadata_ro_entry availableProcessedMinFrameDurations =
399 GetStaticEntry(ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS);
400
401 EXPECT_EQ(availableProcessedSizes.count,
402 availableProcessedMinFrameDurations.count * 2) <<
403 "The number of minimum frame durations doesn't match the number of "
404 "available sizes. Using fallback values";
405
406 if (availableProcessedSizes.count ==
407 availableProcessedMinFrameDurations.count * 2) {
408 bool gotSize = false;
409 for (size_t i = 0; i < availableProcessedSizes.count; i += 2) {
410 if (availableProcessedSizes.data.i32[i] == mWidth &&
411 availableProcessedSizes.data.i32[i+1] == mHeight) {
412 gotSize = true;
413 minDuration = availableProcessedMinFrameDurations.data.i64[i/2];
414 }
415 }
416 EXPECT_TRUE(gotSize) << "Can't find stream size in list of "
417 "available sizes: " << mWidth << ", " << mHeight;
418 }
419 if (minDuration == 0) {
420 minDuration = 1 * SEC / 30; // Fall back to 30 fps as minimum duration
421 }
422
423 ASSERT_LT(0, minDuration);
424
425 camera_metadata_ro_entry maxFrameDuration =
426 GetStaticEntry(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION);
427
428 EXPECT_EQ(1u, maxFrameDuration.count) << "No valid maximum frame duration";
429
430 if (maxFrameDuration.count == 1) {
431 maxDuration = maxFrameDuration.data.i64[0];
432 }
433
Zhijun He6e548cf2013-08-08 19:43:24 -0700434 EXPECT_GT(maxDuration, 0) << "Max duration is 0 or not given, using fallback";
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700435
436 if (maxDuration == 0) {
437 maxDuration = 10 * SEC; // Fall back to 10 seconds as max duration
438 }
439
440 }
441 dout << "Available frame duration range for configured stream size: "
442 << minDuration << " - " << maxDuration << " ns" << std::endl;
443
444 // Get environment variables if set
445 const char *expVal = getenv(expEnv);
446 const char *durationVal = getenv(durationEnv);
447 const char *sensitivityVal = getenv(sensitivityEnv);
448
449 bool gotExp = (expVal != NULL);
450 bool gotDuration = (durationVal != NULL);
451 bool gotSensitivity = (sensitivityVal != NULL);
452
453 // All or none must be provided if using override envs
454 ASSERT_TRUE( (gotDuration && gotExp && gotSensitivity) ||
455 (!gotDuration && !gotExp && !gotSensitivity) ) <<
456 "Incomplete set of environment variable overrides provided";
457
458 Vector<int64_t> expList, durationList;
459 Vector<int32_t> sensitivityList;
460 if (gotExp) {
461 ParseList(expVal, expList);
462 ParseList(durationVal, durationList);
463 ParseList(sensitivityVal, sensitivityList);
464
465 ASSERT_TRUE(
466 (expList.size() == durationList.size()) &&
467 (durationList.size() == sensitivityList.size())) <<
468 "Mismatched sizes in env lists, or parse error";
469
470 dout << "Using burst list from environment with " << expList.size() <<
471 " captures" << std::endl;
472 } else {
473 // Create a default set of controls based on the available ranges
474
475 int64_t e;
476 int64_t d;
477 int32_t s;
478
479 // Exposure ramp
480
481 e = minExp;
482 d = minDuration;
483 s = sensitivities[0];
484 while (e < maxExp) {
485 expList.push_back(e);
486 durationList.push_back(d);
487 sensitivityList.push_back(s);
488 e = e * 2;
489 }
490 e = maxExp;
491 expList.push_back(e);
492 durationList.push_back(d);
493 sensitivityList.push_back(s);
494
495 // Duration ramp
496
497 e = 30 * MSEC;
498 d = minDuration;
499 s = sensitivities[0];
500 while (d < maxDuration) {
501 // make sure exposure <= frame duration
502 expList.push_back(e > d ? d : e);
503 durationList.push_back(d);
504 sensitivityList.push_back(s);
505 d = d * 2;
506 }
507
508 // Sensitivity ramp
509
510 e = 30 * MSEC;
511 d = 30 * MSEC;
512 d = d > minDuration ? d : minDuration;
513 for (size_t i = 0; i < sensitivities.size(); i++) {
514 expList.push_back(e);
515 durationList.push_back(d);
516 sensitivityList.push_back(sensitivities[i]);
517 }
518
519 // Constant-EV ramp, duration == exposure
520
521 e = 30 * MSEC; // at ISO 100
522 for (size_t i = 0; i < sensitivities.size(); i++) {
523 int64_t e_adj = e * 100 / sensitivities[i];
524 expList.push_back(e_adj);
525 durationList.push_back(e_adj > minDuration ? e_adj : minDuration);
526 sensitivityList.push_back(sensitivities[i]);
527 }
528
529 dout << "Default burst sequence created with " << expList.size() <<
530 " entries" << std::endl;
531 }
532
533 // Validate the list, but warn only
534 for (size_t i = 0; i < expList.size(); i++) {
535 EXPECT_GE(maxExp, expList[i])
536 << "Capture " << i << " exposure too long: " << expList[i];
537 EXPECT_LE(minExp, expList[i])
538 << "Capture " << i << " exposure too short: " << expList[i];
539 EXPECT_GE(maxDuration, durationList[i])
540 << "Capture " << i << " duration too long: " << durationList[i];
541 EXPECT_LE(minDuration, durationList[i])
542 << "Capture " << i << " duration too short: " << durationList[i];
543 bool validSensitivity = false;
544 for (size_t j = 0; j < sensitivities.size(); j++) {
545 if (sensitivityList[i] == sensitivities[j]) {
546 validSensitivity = true;
547 break;
548 }
549 }
550 EXPECT_TRUE(validSensitivity)
551 << "Capture " << i << " sensitivity not in list: " << sensitivityList[i];
552 }
553
554 // Check if debug yuv dumps are requested
555
556 bool dumpFrames = false;
557 {
558 const char *frameDumpVal = getenv(dumpFrameEnv);
559 if (frameDumpVal != NULL) {
560 if (frameDumpVal[0] == '1') dumpFrames = true;
561 }
562 }
563
564 dout << "Dumping YUV frames " <<
565 (dumpFrames ? "enabled, not checking timing" : "disabled") << std::endl;
566
567 // Create a base preview request, turning off all 3A
568 CameraMetadata previewRequest;
569 ASSERT_EQ(OK, mDevice->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
570 &previewRequest));
571 {
Zhijun Hea1594172013-09-06 15:35:09 -0700572 Vector<int32_t> outputStreamIds;
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700573 outputStreamIds.push(mStreamId);
574 ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS,
575 outputStreamIds));
576
577 // Disable all 3A routines
578 uint8_t cmOff = static_cast<uint8_t>(ANDROID_CONTROL_MODE_OFF);
579 ASSERT_EQ(OK, previewRequest.update(ANDROID_CONTROL_MODE,
580 &cmOff, 1));
581
582 int requestId = 1;
583 ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_ID,
584 &requestId, 1));
585 }
586
587 // Submit capture requests
588
589 for (size_t i = 0; i < expList.size(); ++i) {
590 CameraMetadata tmpRequest = previewRequest;
591 ASSERT_EQ(OK, tmpRequest.update(ANDROID_SENSOR_EXPOSURE_TIME,
592 &expList[i], 1));
593 ASSERT_EQ(OK, tmpRequest.update(ANDROID_SENSOR_FRAME_DURATION,
594 &durationList[i], 1));
595 ASSERT_EQ(OK, tmpRequest.update(ANDROID_SENSOR_SENSITIVITY,
596 &sensitivityList[i], 1));
597 ALOGV("Submitting capture %d with exposure %lld, frame duration %lld, sensitivity %d",
598 i, expList[i], durationList[i], sensitivityList[i]);
599 dout << "Capture request " << i <<
600 ": exposure is " << (expList[i]/1e6f) << " ms" <<
601 ", frame duration is " << (durationList[i]/1e6f) << " ms" <<
602 ", sensitivity is " << sensitivityList[i] <<
603 std::endl;
604 ASSERT_EQ(OK, mDevice->capture(tmpRequest));
605 }
606
607 Vector<float> brightnesses;
608 Vector<nsecs_t> captureTimes;
609 brightnesses.setCapacity(expList.size());
610 captureTimes.setCapacity(expList.size());
611
612 // Get each frame (metadata) and then the buffer. Calculate brightness.
613 for (size_t i = 0; i < expList.size(); ++i) {
614
615 ALOGV("Reading request %d", i);
616 dout << "Waiting for capture " << i << ": " <<
617 " exposure " << (expList[i]/1e6f) << " ms," <<
618 " frame duration " << (durationList[i]/1e6f) << " ms," <<
619 " sensitivity " << sensitivityList[i] <<
620 std::endl;
621
622 // Set wait limit based on expected frame duration, or minimum timeout
623 int64_t waitLimit = CAMERA_FRAME_TIMEOUT;
624 if (expList[i] * 2 > waitLimit) waitLimit = expList[i] * 2;
625 if (durationList[i] * 2 > waitLimit) waitLimit = durationList[i] * 2;
626
627 ASSERT_EQ(OK, mDevice->waitForNextFrame(waitLimit));
628 ALOGV("Reading capture request-1 %d", i);
629 CameraMetadata frameMetadata;
630 ASSERT_EQ(OK, mDevice->getNextFrame(&frameMetadata));
631 ALOGV("Reading capture request-2 %d", i);
632
633 ASSERT_EQ(OK, mFrameListener->waitForFrame(CAMERA_FRAME_TIMEOUT));
634 ALOGV("We got the frame now");
635
636 captureTimes.push_back(systemTime());
637
638 CpuConsumer::LockedBuffer imgBuffer;
639 ASSERT_EQ(OK, mCpuConsumer->lockNextBuffer(&imgBuffer));
640
641 int underexposed, overexposed;
642 float avgBrightness = 0;
643 long long brightness = TotalBrightness(imgBuffer, &underexposed,
644 &overexposed);
645 int numValidPixels = mWidth * mHeight - (underexposed + overexposed);
646 if (numValidPixels != 0) {
647 avgBrightness = brightness * 1.0f / numValidPixels;
648 } else if (underexposed < overexposed) {
649 avgBrightness = 255;
650 }
651
652 ALOGV("Total brightness for frame %d was %lld (underexposed %d, "
653 "overexposed %d), avg %f", i, brightness, underexposed,
654 overexposed, avgBrightness);
655 dout << "Average brightness (frame " << i << ") was " << avgBrightness
656 << " (underexposed " << underexposed << ", overexposed "
657 << overexposed << ")" << std::endl;
658 brightnesses.push_back(avgBrightness);
659
660 if (i != 0) {
661 float prevEv = static_cast<float>(expList[i - 1]) * sensitivityList[i - 1];
662 float currentEv = static_cast<float>(expList[i]) * sensitivityList[i];
663 float evRatio = (prevEv > currentEv) ? (currentEv / prevEv) :
664 (prevEv / currentEv);
665 if ( evRatio > EV_MATCH_BOUND ) {
Zhijun He60cbb522013-09-18 09:44:19 -0700666 WARN_LT(fabs(brightnesses[i] - brightnesses[i - 1]),
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700667 BRIGHTNESS_MATCH_BOUND) <<
668 "Capture brightness different from previous, even though "
669 "they have the same EV value. Ev now: " << currentEv <<
670 ", previous: " << prevEv << ". Brightness now: " <<
Zhijun He60cbb522013-09-18 09:44:19 -0700671 brightnesses[i] << ", previous: " << brightnesses[i-1] <<
672 std::endl;
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700673 }
674 // Only check timing if not saving to disk, since that slows things
675 // down substantially
676 if (!dumpFrames) {
677 nsecs_t timeDelta = captureTimes[i] - captureTimes[i-1];
678 nsecs_t expectedDelta = expList[i] > durationList[i] ?
679 expList[i] : durationList[i];
Zhijun He60cbb522013-09-18 09:44:19 -0700680 WARN_LT(timeDelta, expectedDelta + DURATION_UPPER_BOUND) <<
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700681 "Capture took " << timeDelta << " ns to receive, but expected"
Zhijun He60cbb522013-09-18 09:44:19 -0700682 " frame duration was " << expectedDelta << " ns." <<
683 std::endl;
684 WARN_GT(timeDelta, expectedDelta - DURATION_LOWER_BOUND) <<
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700685 "Capture took " << timeDelta << " ns to receive, but expected"
Zhijun He60cbb522013-09-18 09:44:19 -0700686 " frame duration was " << expectedDelta << " ns." <<
687 std::endl;
Eino-Ville Talvala7d831712013-07-01 18:47:09 -0700688 dout << "Time delta from previous frame: " << timeDelta / 1e6 <<
689 " ms. Expected " << expectedDelta / 1e6 << " ms" << std::endl;
690 }
691 }
692
693 if (dumpFrames) {
694 String8 dumpName =
695 String8::format("/data/local/tmp/camera2_test_variable_burst_frame_%03d.yuv", i);
696 dout << " Writing YUV dump to " << dumpName << std::endl;
697 DumpYuvToFile(dumpName, imgBuffer);
698 }
699
700 ASSERT_EQ(OK, mCpuConsumer->unlockBuffer(imgBuffer));
701 }
702
703}
704
Igor Murashkinf1b9ae72012-12-07 15:08:35 -0800705}
706}
707}