blob: de1cfd6fb44bb5247f1c9f53bc3461f1d1ccd3d5 [file] [log] [blame]
Zhijun He8ef01442013-08-13 17:36:17 -07001/*
2 * Copyright (C) 2013 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#define LOG_TAG "CameraMultiStreamTest"
18//#define LOG_NDEBUG 0
19#include "CameraStreamFixture.h"
20#include "TestExtensions.h"
21
22#include <gtest/gtest.h>
23#include <utils/Log.h>
24#include <utils/StrongPointer.h>
25#include <common/CameraDeviceBase.h>
26#include <hardware/hardware.h>
27#include <hardware/camera2.h>
28#include <gui/SurfaceComposerClient.h>
29#include <gui/Surface.h>
30
31#define DEFAULT_FRAME_DURATION 33000000LL // 33ms
32#define CAMERA_HEAP_COUNT 1
33#define CAMERA_EXPOSURE_FORMAT CAMERA_STREAM_AUTO_CPU_FORMAT
34#define CAMERA_DISPLAY_FORMAT HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
35#define CAMERA_MULTI_STREAM_DEBUGGING 0
36#define CAMERA_FRAME_TIMEOUT 1000000000LL // nsecs (1 secs)
37#define PREVIEW_RENDERING_TIME_INTERVAL 200000 // in unit of us, 200ms
Zhijun He914226c2013-09-08 10:56:24 -070038#define TOLERANCE_MARGIN 0.01 // 1% tolerance margin for exposure sanity check.
Zhijun He8ef01442013-08-13 17:36:17 -070039/* constants for display */
40#define DISPLAY_BUFFER_HEIGHT 1024
41#define DISPLAY_BUFFER_WIDTH 1024
42#define DISPLAY_BUFFER_FORMAT PIXEL_FORMAT_RGB_888
43
44// This test intends to test large preview size but less than 1080p.
45#define PREVIEW_WIDTH_CAP 1920
46#define PREVIEW_HEIGHT_CAP 1080
47// This test intends to test small metering burst size that is less than 640x480
48#define METERING_WIDTH_CAP 640
49#define METERING_HEIGHT_CAP 480
50
51#define EXP_WAIT_MULTIPLIER 2
52
53namespace android {
54namespace camera2 {
55namespace tests {
56
57static const CameraStreamParams DEFAULT_STREAM_PARAMETERS = {
58 /*mFormat*/ CAMERA_EXPOSURE_FORMAT,
59 /*mHeapCount*/ CAMERA_HEAP_COUNT
60};
61
62static const CameraStreamParams DISPLAY_STREAM_PARAMETERS = {
63 /*mFormat*/ CAMERA_DISPLAY_FORMAT,
64 /*mHeapCount*/ CAMERA_HEAP_COUNT
65};
66
67class CameraMultiStreamTest
68 : public ::testing::Test,
69 public CameraStreamFixture {
70
71public:
72 CameraMultiStreamTest() : CameraStreamFixture(DEFAULT_STREAM_PARAMETERS) {
73 TEST_EXTENSION_FORKING_CONSTRUCTOR;
74
75 if (HasFatalFailure()) {
76 return;
77 }
78 /**
79 * Don't create default stream, each test is in charge of creating
80 * its own streams.
81 */
82 }
83
84 ~CameraMultiStreamTest() {
85 TEST_EXTENSION_FORKING_DESTRUCTOR;
86 }
87
88 sp<SurfaceComposerClient> mComposerClient;
89 sp<SurfaceControl> mSurfaceControl;
90
91 void CreateOnScreenSurface(sp<ANativeWindow>& surface) {
92 mComposerClient = new SurfaceComposerClient;
93 ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
94
95 mSurfaceControl = mComposerClient->createSurface(
96 String8("CameraMultiStreamTest StreamingImage Surface"),
97 DISPLAY_BUFFER_HEIGHT, DISPLAY_BUFFER_WIDTH,
98 DISPLAY_BUFFER_FORMAT, 0);
99
100 ASSERT_NE((void*)NULL, mSurfaceControl.get());
101 ASSERT_TRUE(mSurfaceControl->isValid());
102
103 SurfaceComposerClient::openGlobalTransaction();
104 ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
105 ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
106 SurfaceComposerClient::closeGlobalTransaction();
107
108 surface = mSurfaceControl->getSurface();
109
110 ASSERT_NE((void*)NULL, surface.get());
111 }
112
113 struct Size {
114 int32_t width;
115 int32_t height;
116 };
117
118 // Select minimal size by number of pixels.
119 void GetMinSize(const int32_t* data, size_t count,
120 Size* min, int32_t* idx) {
121 ASSERT_NE((int32_t*)NULL, data);
122 int32_t minIdx = 0;
123 int32_t minSize = INT_MAX, tempSize;
124 for (size_t i = 0; i < count; i+=2) {
125 tempSize = data[i] * data[i+1];
126 if (minSize > tempSize) {
127 minSize = tempSize;
128 minIdx = i;
129 }
130 }
131 min->width = data[minIdx];
132 min->height = data[minIdx + 1];
133 *idx = minIdx;
134 }
135
136 // Select maximal size by number of pixels.
137 void GetMaxSize(const int32_t* data, size_t count,
138 Size* max, int32_t* idx) {
139 ASSERT_NE((int32_t*)NULL, data);
140 int32_t maxIdx = 0;
141 int32_t maxSize = INT_MIN, tempSize;
142 for (size_t i = 0; i < count; i+=2) {
143 tempSize = data[i] * data[i+1];
144 if (maxSize < tempSize) {
145 maxSize = tempSize;
146 maxIdx = i;
147 }
148 }
149 max->width = data[maxIdx];
150 max->height = data[maxIdx + 1];
151 *idx = maxIdx;
152 }
153
154 // Cap size by number of pixels.
155 Size CapSize(Size cap, Size input) {
156 if (input.width * input.height > cap.width * cap.height) {
157 return cap;
158 }
159 return input;
160 }
161
162 struct CameraStream : public RefBase {
163
164 public:
165 /**
166 * Only initialize the variables here, do the ASSERT check in
167 * SetUp function. To make this stream useful, the SetUp must
168 * be called before using it.
169 */
170 CameraStream(
171 int width,
172 int height,
173 const sp<CameraDeviceBase>& device,
174 CameraStreamParams param, sp<ANativeWindow> surface,
175 bool useCpuConsumer)
176 : mDevice(device),
177 mWidth(width),
178 mHeight(height) {
179 mFormat = param.mFormat;
180 if (useCpuConsumer) {
181 sp<BufferQueue> bq = new BufferQueue();
182 mCpuConsumer = new CpuConsumer(bq, param.mHeapCount);
183 mCpuConsumer->setName(String8(
184 "CameraMultiStreamTest::mCpuConsumer"));
185 mNativeWindow = new Surface(bq);
186 } else {
187 // Render the stream to screen.
188 mCpuConsumer = NULL;
189 mNativeWindow = surface;
190 }
191
192 mFrameListener = new FrameListener();
193 if (mCpuConsumer != 0) {
194 mCpuConsumer->setFrameAvailableListener(mFrameListener);
195 }
196 }
197
198 /**
199 * Finally create camera stream, and do the ASSERT check, since we
200 * can not do it in ctor.
201 */
202 void SetUp() {
203 ASSERT_EQ(OK,
204 mDevice->createStream(mNativeWindow,
205 mWidth, mHeight, mFormat, /*size (for jpegs)*/0,
206 &mStreamId));
207
208 ASSERT_NE(-1, mStreamId);
209 }
210
211 int GetStreamId() { return mStreamId; }
212 sp<CpuConsumer> GetConsumer() { return mCpuConsumer; }
213 sp<FrameListener> GetFrameListener() { return mFrameListener; }
214
215 protected:
216 ~CameraStream() {
217 if (mDevice.get()) {
218 mDevice->waitUntilDrained();
219 mDevice->deleteStream(mStreamId);
220 }
221 // Clear producer before consumer.
222 mNativeWindow.clear();
223 mCpuConsumer.clear();
224 }
225
226 private:
227 sp<FrameListener> mFrameListener;
228 sp<CpuConsumer> mCpuConsumer;
229 sp<ANativeWindow> mNativeWindow;
230 sp<CameraDeviceBase> mDevice;
231 int mStreamId;
232 int mWidth;
233 int mHeight;
234 int mFormat;
235 };
236
237 int64_t GetExposureValue(const CameraMetadata& metaData) {
238 camera_metadata_ro_entry_t entry =
239 metaData.find(ANDROID_SENSOR_EXPOSURE_TIME);
240 EXPECT_EQ(1u, entry.count);
241 if (entry.count == 1) {
242 return entry.data.i64[0];
243 }
244 return -1;
245 }
246
247 int32_t GetSensitivity(const CameraMetadata& metaData) {
248 camera_metadata_ro_entry_t entry =
249 metaData.find(ANDROID_SENSOR_SENSITIVITY);
250 EXPECT_EQ(1u, entry.count);
251 if (entry.count == 1) {
252 return entry.data.i32[0];
253 }
254 return -1;
255 }
256
257 int64_t GetFrameDuration(const CameraMetadata& metaData) {
258 camera_metadata_ro_entry_t entry =
259 metaData.find(ANDROID_SENSOR_FRAME_DURATION);
260 EXPECT_EQ(1u, entry.count);
261 if (entry.count == 1) {
262 return entry.data.i64[0];
263 }
264 return -1;
265 }
266
267 void CreateRequests(CameraMetadata& previewRequest,
268 CameraMetadata& meteringRequest,
269 CameraMetadata& captureRequest,
270 int previewStreamId,
271 int meteringStreamId,
272 int captureStreamId) {
Zhijun He914226c2013-09-08 10:56:24 -0700273 int32_t requestId = 0;
274 Vector<int32_t> previewStreamIds;
275 previewStreamIds.push(previewStreamId);
276 ASSERT_EQ(OK, mDevice->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
277 &previewRequest));
278 ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS,
279 previewStreamIds));
280 ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_ID,
281 &requestId, 1));
Zhijun He8ef01442013-08-13 17:36:17 -0700282
Zhijun He914226c2013-09-08 10:56:24 -0700283 // Create metering request, manual settings
284 // Manual control: Disable 3A, noise reduction, edge sharping
285 uint8_t cmOff = static_cast<uint8_t>(ANDROID_CONTROL_MODE_OFF);
286 uint8_t nrOff = static_cast<uint8_t>(ANDROID_NOISE_REDUCTION_MODE_OFF);
287 uint8_t sharpOff = static_cast<uint8_t>(ANDROID_EDGE_MODE_OFF);
288 Vector<int32_t> meteringStreamIds;
289 meteringStreamIds.push(meteringStreamId);
290 ASSERT_EQ(OK, mDevice->createDefaultRequest(
291 CAMERA2_TEMPLATE_PREVIEW,
292 &meteringRequest));
293 ASSERT_EQ(OK, meteringRequest.update(
294 ANDROID_REQUEST_OUTPUT_STREAMS,
295 meteringStreamIds));
296 ASSERT_EQ(OK, meteringRequest.update(
297 ANDROID_CONTROL_MODE,
298 &cmOff, 1));
299 ASSERT_EQ(OK, meteringRequest.update(
300 ANDROID_NOISE_REDUCTION_MODE,
301 &nrOff, 1));
302 ASSERT_EQ(OK, meteringRequest.update(
303 ANDROID_EDGE_MODE,
304 &sharpOff, 1));
Zhijun He8ef01442013-08-13 17:36:17 -0700305
Zhijun He914226c2013-09-08 10:56:24 -0700306 // Create capture request, manual settings
307 Vector<int32_t> captureStreamIds;
308 captureStreamIds.push(captureStreamId);
309 ASSERT_EQ(OK, mDevice->createDefaultRequest(
310 CAMERA2_TEMPLATE_PREVIEW,
311 &captureRequest));
312 ASSERT_EQ(OK, captureRequest.update(
313 ANDROID_REQUEST_OUTPUT_STREAMS,
314 captureStreamIds));
315 ASSERT_EQ(OK, captureRequest.update(
316 ANDROID_CONTROL_MODE,
317 &cmOff, 1));
318 ASSERT_EQ(OK, captureRequest.update(
319 ANDROID_NOISE_REDUCTION_MODE,
320 &nrOff, 1));
321 ASSERT_EQ(OK, captureRequest.update(
322 ANDROID_EDGE_MODE,
323 &sharpOff, 1));
Zhijun He8ef01442013-08-13 17:36:17 -0700324 }
325
326 sp<CameraStream> CreateStream(
327 int width,
328 int height,
329 const sp<CameraDeviceBase>& device,
330 CameraStreamParams param = DEFAULT_STREAM_PARAMETERS,
331 sp<ANativeWindow> surface = NULL,
332 bool useCpuConsumer = true) {
333 param.mFormat = MapAutoFormat(param.mFormat);
334 return new CameraStream(width, height, device,
335 param, surface, useCpuConsumer);
336 }
337
338 void CaptureBurst(CameraMetadata& request, size_t requestCount,
339 const Vector<int64_t>& exposures,
340 const Vector<int32_t>& sensitivities,
341 const sp<CameraStream>& stream,
Zhijun He914226c2013-09-08 10:56:24 -0700342 int64_t minFrameDuration,
343 int32_t* requestIdStart) {
Zhijun He8ef01442013-08-13 17:36:17 -0700344 ASSERT_EQ(OK, request.update(ANDROID_SENSOR_FRAME_DURATION,
345 &minFrameDuration, 1));
346 // Submit a series of requests with the specified exposure/gain values.
Zhijun He914226c2013-09-08 10:56:24 -0700347 int32_t targetRequestId = *requestIdStart;
Zhijun He8ef01442013-08-13 17:36:17 -0700348 for (size_t i = 0; i < requestCount; i++) {
Zhijun He914226c2013-09-08 10:56:24 -0700349 ASSERT_EQ(OK, request.update(ANDROID_REQUEST_ID, requestIdStart, 1));
350 ASSERT_EQ(OK, request.update(ANDROID_SENSOR_EXPOSURE_TIME, &exposures[i], 1));
351 ASSERT_EQ(OK, request.update(ANDROID_SENSOR_SENSITIVITY, &sensitivities[i], 1));
Zhijun He8ef01442013-08-13 17:36:17 -0700352 ASSERT_EQ(OK, mDevice->capture(request));
Zhijun He914226c2013-09-08 10:56:24 -0700353 ALOGV("Submitting request with: id %d with exposure %lld, sensitivity %d",
354 *requestIdStart, exposures[i], sensitivities[i]);
Zhijun He8ef01442013-08-13 17:36:17 -0700355 if (CAMERA_MULTI_STREAM_DEBUGGING) {
356 request.dump(STDOUT_FILENO);
357 }
Zhijun He914226c2013-09-08 10:56:24 -0700358 (*requestIdStart)++;
Zhijun He8ef01442013-08-13 17:36:17 -0700359 }
360 // Get capture burst results.
361 Vector<nsecs_t> captureBurstTimes;
362 sp<CpuConsumer> consumer = stream->GetConsumer();
363 sp<FrameListener> listener = stream->GetFrameListener();
364
365 // Set wait limit based on expected frame duration.
366 int64_t waitLimit = CAMERA_FRAME_TIMEOUT;
367 for (size_t i = 0; i < requestCount; i++) {
368 ALOGV("Reading request result %d", i);
369
370 /**
371 * Raise the timeout to be at least twice as long as the exposure
372 * time. to avoid a false positive when the timeout is too short.
373 */
374 if ((exposures[i] * EXP_WAIT_MULTIPLIER) > waitLimit) {
375 waitLimit = exposures[i] * EXP_WAIT_MULTIPLIER;
376 }
377
Zhijun He8ef01442013-08-13 17:36:17 -0700378 CameraMetadata frameMetadata;
Zhijun He914226c2013-09-08 10:56:24 -0700379 int32_t resultRequestId;
380 do {
381 ASSERT_EQ(OK, mDevice->waitForNextFrame(waitLimit));
382 ASSERT_EQ(OK, mDevice->getNextFrame(&frameMetadata));
383
384 camera_metadata_entry_t resultEntry = frameMetadata.find(ANDROID_REQUEST_ID);
385 ASSERT_EQ(1u, resultEntry.count);
386 resultRequestId = resultEntry.data.i32[0];
387 if (CAMERA_MULTI_STREAM_DEBUGGING) {
388 std::cout << "capture result req id: " << resultRequestId << std::endl;
389 }
390 } while (resultRequestId != targetRequestId);
391 targetRequestId++;
Zhijun He8ef01442013-08-13 17:36:17 -0700392 ALOGV("Got capture burst result for request %d", i);
Zhijun He914226c2013-09-08 10:56:24 -0700393
Zhijun He8ef01442013-08-13 17:36:17 -0700394 // Validate capture result
395 if (CAMERA_MULTI_STREAM_DEBUGGING) {
396 frameMetadata.dump(STDOUT_FILENO);
397 }
398
399 // TODO: Need revisit it to figure out an accurate margin.
Zhijun He914226c2013-09-08 10:56:24 -0700400 int64_t resultExposure = GetExposureValue(frameMetadata);
401 int32_t resultSensitivity = GetSensitivity(frameMetadata);
402 EXPECT_LE(sensitivities[i] * (1.0 - TOLERANCE_MARGIN), resultSensitivity);
403 EXPECT_GE(sensitivities[i] * (1.0 + TOLERANCE_MARGIN), resultSensitivity);
404 EXPECT_LE(exposures[i] * (1.0 - TOLERANCE_MARGIN), resultExposure);
405 EXPECT_GE(exposures[i] * (1.0 + TOLERANCE_MARGIN), resultExposure);
Zhijun He8ef01442013-08-13 17:36:17 -0700406
407 ASSERT_EQ(OK, listener->waitForFrame(waitLimit));
408 captureBurstTimes.push_back(systemTime());
409 CpuConsumer::LockedBuffer imgBuffer;
410 ASSERT_EQ(OK, consumer->lockNextBuffer(&imgBuffer));
411 ALOGV("Got capture buffer for request %d", i);
412
413 /**
414 * TODO: Validate capture buffer. Current brightness calculation
415 * is too slow, it also doesn't account for saturation effects,
416 * which is quite common since we are going over a significant
417 * range of EVs. we need figure out some reliable way to validate
418 * buffer data.
419 */
420
421 ASSERT_EQ(OK, consumer->unlockBuffer(imgBuffer));
422 if (i > 0) {
423 nsecs_t timeDelta =
424 captureBurstTimes[i] - captureBurstTimes[i-1];
425 EXPECT_GE(timeDelta, exposures[i]);
426 }
427 }
428 }
429
430 /**
431 * Intentionally shadow default CreateStream function from base class,
432 * because we don't want any test in this class to use the default
433 * stream creation function.
434 */
435 void CreateStream() {
436 }
437};
438
439/**
440 * This test adds multiple stream use case test, basically, test 3
441 * streams:
442 *
443 * 1. Preview stream, with large size that is no bigger than 1080p
444 * we render this stream to display and vary the exposure time for
445 * for certain amount of time for visualization purpose.
446 *
447 * 2. Metering stream, with small size that is no bigger than VGA size.
448 * a burst is issued for different exposure times and analog gains
449 * (or analog gain implemented sensitivities) then check if the capture
450 * result metadata matches the request.
451 *
452 * 3. Capture stream, this is basically similar as meterting stream, but
453 * has large size, which is the largest supported JPEG capture size.
454 *
455 * This multiple stream test is to test if HAL supports:
456 *
457 * 1. Multiple streams like above, HAL should support at least 3 streams
458 * concurrently: one preview stream, 2 other YUV stream.
459 *
460 * 2. Manual control(gain/exposure) of mutiple burst capture.
461 */
462TEST_F(CameraMultiStreamTest, MultiBurst) {
463
464 TEST_EXTENSION_FORKING_INIT;
465
466 camera_metadata_ro_entry availableProcessedSizes =
467 GetStaticEntry(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
468 ASSERT_EQ(0u, availableProcessedSizes.count % 2);
469 ASSERT_GE(availableProcessedSizes.count, 2u);
470 camera_metadata_ro_entry availableProcessedMinFrameDurations =
471 GetStaticEntry(ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS);
472 EXPECT_EQ(availableProcessedSizes.count,
473 availableProcessedMinFrameDurations.count * 2);
474
475 camera_metadata_ro_entry availableJpegSizes =
476 GetStaticEntry(ANDROID_SCALER_AVAILABLE_JPEG_SIZES);
477 ASSERT_EQ(0u, availableJpegSizes.count % 2);
478 ASSERT_GE(availableJpegSizes.count, 2u);
479
Zhijun He3bf3b452013-09-18 23:42:12 -0700480 camera_metadata_ro_entry hardwareLevel =
481 GetStaticEntry(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL);
482 ASSERT_EQ(1u, hardwareLevel.count);
483 uint8_t level = hardwareLevel.data.u8[0];
484 ASSERT_GE(level, ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED);
485 ASSERT_LE(level, ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
486 if (level == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED) {
487 const ::testing::TestInfo* const test_info =
488 ::testing::UnitTest::GetInstance()->current_test_info();
489 std::cerr << "Skipping test "
490 << test_info->test_case_name() << "."
491 << test_info->name()
492 << " because HAL hardware supported level is limited "
493 << std::endl;
494 return;
495 }
496
Zhijun He8ef01442013-08-13 17:36:17 -0700497 // Find the right sizes for preview, metering, and capture streams
498 // assumes at least 2 entries in availableProcessedSizes.
499 int64_t minFrameDuration = DEFAULT_FRAME_DURATION;
500 Size processedMinSize, processedMaxSize, jpegMaxSize;
501 const int32_t* data = availableProcessedSizes.data.i32;
502 size_t count = availableProcessedSizes.count;
503
504 int32_t minIdx, maxIdx;
505 GetMinSize(data, count, &processedMinSize, &minIdx);
506 GetMaxSize(data, count, &processedMaxSize, &maxIdx);
507 ALOGV("Found processed max size: %dx%d, min size = %dx%d",
508 processedMaxSize.width, processedMaxSize.height,
509 processedMinSize.width, processedMinSize.height);
510
511 if (availableProcessedSizes.count ==
512 availableProcessedMinFrameDurations.count * 2) {
513 minFrameDuration =
514 availableProcessedMinFrameDurations.data.i64[maxIdx / 2];
515 }
516
517 EXPECT_GT(minFrameDuration, 0);
518
519 if (minFrameDuration <= 0) {
520 minFrameDuration = DEFAULT_FRAME_DURATION;
521 }
522
523 ALOGV("targeted minimal frame duration is: %lldns", minFrameDuration);
524
525 data = &(availableJpegSizes.data.i32[0]);
526 count = availableJpegSizes.count;
527 GetMaxSize(data, count, &jpegMaxSize, &maxIdx);
528 ALOGV("Found Jpeg size max idx = %d", maxIdx);
529
530 // Max Jpeg size should be available in processed sizes. Use it for
531 // YUV capture anyway.
532 EXPECT_EQ(processedMaxSize.width, jpegMaxSize.width);
533 EXPECT_EQ(processedMaxSize.height, jpegMaxSize.height);
534
535 // Cap preview size.
536 Size previewLimit = { PREVIEW_WIDTH_CAP, PREVIEW_HEIGHT_CAP };
537 // FIXME: need make sure the previewLimit is supported by HAL.
538 Size previewSize = CapSize(previewLimit, processedMaxSize);
539 // Cap Metering size.
540 Size meteringLimit = { METERING_WIDTH_CAP, METERING_HEIGHT_CAP };
541 // Cap metering size to VGA (VGA is mandatory by CDD)
542 Size meteringSize = CapSize(meteringLimit, processedMinSize);
543 // Capture stream should be the max size of jpeg sizes.
544 ALOGV("preview size: %dx%d, metering size: %dx%d, capture size: %dx%d",
545 previewSize.width, previewSize.height,
546 meteringSize.width, meteringSize.height,
547 jpegMaxSize.width, jpegMaxSize.height);
548
549 // Create streams
550 // Preview stream: small resolution, render on the screen.
551 sp<CameraStream> previewStream;
552 {
553 sp<ANativeWindow> surface;
554 ASSERT_NO_FATAL_FAILURE(CreateOnScreenSurface(/*out*/surface));
555 previewStream = CreateStream(
556 previewSize.width,
557 previewSize.height,
558 mDevice,
559 DISPLAY_STREAM_PARAMETERS,
560 surface,
561 false);
562 ASSERT_NE((void*)NULL, previewStream.get());
563 ASSERT_NO_FATAL_FAILURE(previewStream->SetUp());
564 }
565 // Metering burst stream: small resolution yuv stream
566 sp<CameraStream> meteringStream =
567 CreateStream(
568 meteringSize.width,
569 meteringSize.height,
570 mDevice);
571 ASSERT_NE((void*)NULL, meteringStream.get());
572 ASSERT_NO_FATAL_FAILURE(meteringStream->SetUp());
573 // Capture burst stream: full resolution yuv stream
574 sp<CameraStream> captureStream =
575 CreateStream(
576 jpegMaxSize.width,
577 jpegMaxSize.height,
578 mDevice);
579 ASSERT_NE((void*)NULL, captureStream.get());
580 ASSERT_NO_FATAL_FAILURE(captureStream->SetUp());
581
582 // Create Preview request.
583 CameraMetadata previewRequest, meteringRequest, captureRequest;
584 ASSERT_NO_FATAL_FAILURE(CreateRequests(previewRequest, meteringRequest,
585 captureRequest, previewStream->GetStreamId(),
586 meteringStream->GetStreamId(), captureStream->GetStreamId()));
587
588 // Start preview
589 if (CAMERA_MULTI_STREAM_DEBUGGING) {
590 previewRequest.dump(STDOUT_FILENO);
591 }
592
593 // Generate exposure and sensitivity lists
594 camera_metadata_ro_entry exposureTimeRange =
595 GetStaticEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE);
596 ASSERT_EQ(exposureTimeRange.count, 2u);
597 int64_t minExp = exposureTimeRange.data.i64[0];
598 int64_t maxExp = exposureTimeRange.data.i64[1];
599 ASSERT_GT(maxExp, minExp);
600
601 camera_metadata_ro_entry sensivityRange =
602 GetStaticEntry(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE);
603 ASSERT_EQ(2u, sensivityRange.count);
604 int32_t minSensitivity = sensivityRange.data.i32[0];
605 int32_t maxSensitivity = sensivityRange.data.i32[1];
606 camera_metadata_ro_entry maxAnalogSenEntry =
607 GetStaticEntry(ANDROID_SENSOR_MAX_ANALOG_SENSITIVITY);
608 EXPECT_EQ(1u, maxAnalogSenEntry.count);
609 int32_t maxAnalogSensitivity = maxAnalogSenEntry.data.i32[0];
610 EXPECT_LE(maxAnalogSensitivity, maxSensitivity);
611 // Only test the sensitivity implemented by analog gain.
612 if (maxAnalogSensitivity > maxSensitivity) {
613 // Fallback to maxSensitity
614 maxAnalogSensitivity = maxSensitivity;
615 }
616
617 // sensitivity list, only include the sensitivities that are implemented
618 // purely by analog gain if possible.
619 Vector<int32_t> sensitivities;
620 Vector<int64_t> exposures;
621 count = (maxAnalogSensitivity - minSensitivity + 99) / 100;
622 sensitivities.push_back(minSensitivity);
623 for (size_t i = 1; i < count; i++) {
624 sensitivities.push_back(minSensitivity + i * 100);
625 }
626 sensitivities.push_back(maxAnalogSensitivity);
627 ALOGV("Sensitivity Range: min=%d, max=%d", minSensitivity,
628 maxAnalogSensitivity);
629 int64_t exp = minExp;
630 while (exp < maxExp) {
631 exposures.push_back(exp);
632 exp *= 2;
633 }
634 // Sweep the exposure value for preview, just for visual inspection purpose.
635 uint8_t cmOff = static_cast<uint8_t>(ANDROID_CONTROL_MODE_OFF);
636 for (size_t i = 0; i < exposures.size(); i++) {
637 ASSERT_EQ(OK, previewRequest.update(
638 ANDROID_CONTROL_MODE,
639 &cmOff, 1));
640 ASSERT_EQ(OK, previewRequest.update(
641 ANDROID_SENSOR_EXPOSURE_TIME,
642 &exposures[i], 1));
643 ALOGV("Submitting preview request %d with exposure %lld",
644 i, exposures[i]);
645
646 ASSERT_EQ(OK, mDevice->setStreamingRequest(previewRequest));
647
648 // Let preview run 200ms on screen for each exposure time.
649 usleep(PREVIEW_RENDERING_TIME_INTERVAL);
650 }
651
652 size_t requestCount = sensitivities.size();
653 if (requestCount > exposures.size()) {
654 requestCount = exposures.size();
655 }
656
Zhijun He914226c2013-09-08 10:56:24 -0700657 // To maintain the request id uniqueness (preview request id is 0), make burst capture start
658 // request id 1 here.
659 int32_t requestIdStart = 1;
Zhijun He8ef01442013-08-13 17:36:17 -0700660 /**
661 * Submit metering request, set default frame duration to minimal possible
662 * value, we want the capture to run as fast as possible. HAL should adjust
663 * the frame duration to minimal necessary value to support the requested
664 * exposure value if exposure is larger than frame duration.
665 */
666 CaptureBurst(meteringRequest, requestCount, exposures, sensitivities,
Zhijun He914226c2013-09-08 10:56:24 -0700667 meteringStream, minFrameDuration, &requestIdStart);
Zhijun He8ef01442013-08-13 17:36:17 -0700668
669 /**
670 * Submit capture request, set default frame duration to minimal possible
671 * value, we want the capture to run as fast as possible. HAL should adjust
672 * the frame duration to minimal necessary value to support the requested
673 * exposure value if exposure is larger than frame duration.
674 */
675 CaptureBurst(captureRequest, requestCount, exposures, sensitivities,
Zhijun He914226c2013-09-08 10:56:24 -0700676 captureStream, minFrameDuration, &requestIdStart);
Zhijun He8ef01442013-08-13 17:36:17 -0700677
678 ASSERT_EQ(OK, mDevice->clearStreamingRequest());
679}
680
681}
682}
683}