diff options
author | Zhijun He <zhijunhe@google.com> | 2013-08-19 21:03:22 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-08-19 21:03:22 +0000 |
commit | a7ff78d4edb046cfc106e450ad0733775aa22e22 (patch) | |
tree | b717c5442d15449e1bca1a72e0378f954f6d7690 /tests | |
parent | aaf337dccb23f04ed4a59f2f371326c93cb5c96f (diff) | |
parent | 8ef0144a52df7edfb754efce597e078bc185c57d (diff) | |
download | hardware_libhardware-a7ff78d4edb046cfc106e450ad0733775aa22e22.zip hardware_libhardware-a7ff78d4edb046cfc106e450ad0733775aa22e22.tar.gz hardware_libhardware-a7ff78d4edb046cfc106e450ad0733775aa22e22.tar.bz2 |
Merge "Camera2 Tests: Add multiple stream tests" into klp-dev
Diffstat (limited to 'tests')
-rw-r--r-- | tests/camera2/Android.mk | 1 | ||||
-rw-r--r-- | tests/camera2/CameraMultiStreamTests.cpp | 651 | ||||
-rw-r--r-- | tests/camera2/CameraStreamFixture.h | 1 | ||||
-rw-r--r-- | tests/camera2/camera2.cpp | 4 | ||||
-rw-r--r-- | tests/camera2/camera2_utils.cpp | 1 |
5 files changed, 655 insertions, 3 deletions
diff --git a/tests/camera2/Android.mk b/tests/camera2/Android.mk index 8f2278a..9efac0f 100644 --- a/tests/camera2/Android.mk +++ b/tests/camera2/Android.mk @@ -10,6 +10,7 @@ LOCAL_SRC_FILES:= \ CameraStreamTests.cpp \ CameraFrameTests.cpp \ CameraBurstTests.cpp \ + CameraMultiStreamTests.cpp\ ForkedTests.cpp \ TestForkerEventListener.cpp \ TestSettings.cpp \ diff --git a/tests/camera2/CameraMultiStreamTests.cpp b/tests/camera2/CameraMultiStreamTests.cpp new file mode 100644 index 0000000..679ff4e --- /dev/null +++ b/tests/camera2/CameraMultiStreamTests.cpp @@ -0,0 +1,651 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "CameraMultiStreamTest" +//#define LOG_NDEBUG 0 +#include "CameraStreamFixture.h" +#include "TestExtensions.h" + +#include <gtest/gtest.h> +#include <utils/Log.h> +#include <utils/StrongPointer.h> +#include <common/CameraDeviceBase.h> +#include <hardware/hardware.h> +#include <hardware/camera2.h> +#include <gui/SurfaceComposerClient.h> +#include <gui/Surface.h> + +#define DEFAULT_FRAME_DURATION 33000000LL // 33ms +#define CAMERA_HEAP_COUNT 1 +#define CAMERA_EXPOSURE_FORMAT CAMERA_STREAM_AUTO_CPU_FORMAT +#define CAMERA_DISPLAY_FORMAT HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED +#define CAMERA_MULTI_STREAM_DEBUGGING 0 +#define CAMERA_FRAME_TIMEOUT 1000000000LL // nsecs (1 secs) +#define PREVIEW_RENDERING_TIME_INTERVAL 200000 // in unit of us, 200ms +/* constants for display */ +#define DISPLAY_BUFFER_HEIGHT 1024 +#define DISPLAY_BUFFER_WIDTH 1024 +#define DISPLAY_BUFFER_FORMAT PIXEL_FORMAT_RGB_888 + +// This test intends to test large preview size but less than 1080p. +#define PREVIEW_WIDTH_CAP 1920 +#define PREVIEW_HEIGHT_CAP 1080 +// This test intends to test small metering burst size that is less than 640x480 +#define METERING_WIDTH_CAP 640 +#define METERING_HEIGHT_CAP 480 + +#define EXP_WAIT_MULTIPLIER 2 + +namespace android { +namespace camera2 { +namespace tests { + +static const CameraStreamParams DEFAULT_STREAM_PARAMETERS = { + /*mFormat*/ CAMERA_EXPOSURE_FORMAT, + /*mHeapCount*/ CAMERA_HEAP_COUNT +}; + +static const CameraStreamParams DISPLAY_STREAM_PARAMETERS = { + /*mFormat*/ CAMERA_DISPLAY_FORMAT, + /*mHeapCount*/ CAMERA_HEAP_COUNT +}; + +class CameraMultiStreamTest + : public ::testing::Test, + public CameraStreamFixture { + +public: + CameraMultiStreamTest() : CameraStreamFixture(DEFAULT_STREAM_PARAMETERS) { + TEST_EXTENSION_FORKING_CONSTRUCTOR; + + if (HasFatalFailure()) { + return; + } + /** + * Don't create default stream, each test is in charge of creating + * its own streams. + */ + } + + ~CameraMultiStreamTest() { + TEST_EXTENSION_FORKING_DESTRUCTOR; + } + + sp<SurfaceComposerClient> mComposerClient; + sp<SurfaceControl> mSurfaceControl; + + void CreateOnScreenSurface(sp<ANativeWindow>& surface) { + mComposerClient = new SurfaceComposerClient; + ASSERT_EQ(NO_ERROR, mComposerClient->initCheck()); + + mSurfaceControl = mComposerClient->createSurface( + String8("CameraMultiStreamTest StreamingImage Surface"), + DISPLAY_BUFFER_HEIGHT, DISPLAY_BUFFER_WIDTH, + DISPLAY_BUFFER_FORMAT, 0); + + ASSERT_NE((void*)NULL, mSurfaceControl.get()); + ASSERT_TRUE(mSurfaceControl->isValid()); + + SurfaceComposerClient::openGlobalTransaction(); + ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF)); + ASSERT_EQ(NO_ERROR, mSurfaceControl->show()); + SurfaceComposerClient::closeGlobalTransaction(); + + surface = mSurfaceControl->getSurface(); + + ASSERT_NE((void*)NULL, surface.get()); + } + + struct Size { + int32_t width; + int32_t height; + }; + + // Select minimal size by number of pixels. + void GetMinSize(const int32_t* data, size_t count, + Size* min, int32_t* idx) { + ASSERT_NE((int32_t*)NULL, data); + int32_t minIdx = 0; + int32_t minSize = INT_MAX, tempSize; + for (size_t i = 0; i < count; i+=2) { + tempSize = data[i] * data[i+1]; + if (minSize > tempSize) { + minSize = tempSize; + minIdx = i; + } + } + min->width = data[minIdx]; + min->height = data[minIdx + 1]; + *idx = minIdx; + } + + // Select maximal size by number of pixels. + void GetMaxSize(const int32_t* data, size_t count, + Size* max, int32_t* idx) { + ASSERT_NE((int32_t*)NULL, data); + int32_t maxIdx = 0; + int32_t maxSize = INT_MIN, tempSize; + for (size_t i = 0; i < count; i+=2) { + tempSize = data[i] * data[i+1]; + if (maxSize < tempSize) { + maxSize = tempSize; + maxIdx = i; + } + } + max->width = data[maxIdx]; + max->height = data[maxIdx + 1]; + *idx = maxIdx; + } + + // Cap size by number of pixels. + Size CapSize(Size cap, Size input) { + if (input.width * input.height > cap.width * cap.height) { + return cap; + } + return input; + } + + struct CameraStream : public RefBase { + + public: + /** + * Only initialize the variables here, do the ASSERT check in + * SetUp function. To make this stream useful, the SetUp must + * be called before using it. + */ + CameraStream( + int width, + int height, + const sp<CameraDeviceBase>& device, + CameraStreamParams param, sp<ANativeWindow> surface, + bool useCpuConsumer) + : mDevice(device), + mWidth(width), + mHeight(height) { + mFormat = param.mFormat; + if (useCpuConsumer) { + sp<BufferQueue> bq = new BufferQueue(); + mCpuConsumer = new CpuConsumer(bq, param.mHeapCount); + mCpuConsumer->setName(String8( + "CameraMultiStreamTest::mCpuConsumer")); + mNativeWindow = new Surface(bq); + } else { + // Render the stream to screen. + mCpuConsumer = NULL; + mNativeWindow = surface; + } + + mFrameListener = new FrameListener(); + if (mCpuConsumer != 0) { + mCpuConsumer->setFrameAvailableListener(mFrameListener); + } + } + + /** + * Finally create camera stream, and do the ASSERT check, since we + * can not do it in ctor. + */ + void SetUp() { + ASSERT_EQ(OK, + mDevice->createStream(mNativeWindow, + mWidth, mHeight, mFormat, /*size (for jpegs)*/0, + &mStreamId)); + + ASSERT_NE(-1, mStreamId); + } + + int GetStreamId() { return mStreamId; } + sp<CpuConsumer> GetConsumer() { return mCpuConsumer; } + sp<FrameListener> GetFrameListener() { return mFrameListener; } + + protected: + ~CameraStream() { + if (mDevice.get()) { + mDevice->waitUntilDrained(); + mDevice->deleteStream(mStreamId); + } + // Clear producer before consumer. + mNativeWindow.clear(); + mCpuConsumer.clear(); + } + + private: + sp<FrameListener> mFrameListener; + sp<CpuConsumer> mCpuConsumer; + sp<ANativeWindow> mNativeWindow; + sp<CameraDeviceBase> mDevice; + int mStreamId; + int mWidth; + int mHeight; + int mFormat; + }; + + int64_t GetExposureValue(const CameraMetadata& metaData) { + camera_metadata_ro_entry_t entry = + metaData.find(ANDROID_SENSOR_EXPOSURE_TIME); + EXPECT_EQ(1u, entry.count); + if (entry.count == 1) { + return entry.data.i64[0]; + } + return -1; + } + + int32_t GetSensitivity(const CameraMetadata& metaData) { + camera_metadata_ro_entry_t entry = + metaData.find(ANDROID_SENSOR_SENSITIVITY); + EXPECT_EQ(1u, entry.count); + if (entry.count == 1) { + return entry.data.i32[0]; + } + return -1; + } + + int64_t GetFrameDuration(const CameraMetadata& metaData) { + camera_metadata_ro_entry_t entry = + metaData.find(ANDROID_SENSOR_FRAME_DURATION); + EXPECT_EQ(1u, entry.count); + if (entry.count == 1) { + return entry.data.i64[0]; + } + return -1; + } + + void CreateRequests(CameraMetadata& previewRequest, + CameraMetadata& meteringRequest, + CameraMetadata& captureRequest, + int previewStreamId, + int meteringStreamId, + int captureStreamId) { + int32_t requestId = 1; + Vector<uint8_t> previewStreamIds; + previewStreamIds.push(previewStreamId); + ASSERT_EQ(OK, mDevice->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW, + &previewRequest)); + ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_OUTPUT_STREAMS, + previewStreamIds)); + ASSERT_EQ(OK, previewRequest.update(ANDROID_REQUEST_ID, + &requestId, 1)); + + // Create metering request, manual settings + // Manual control: Disable 3A, noise reduction, edge sharping + uint8_t cmOff = static_cast<uint8_t>(ANDROID_CONTROL_MODE_OFF); + uint8_t nrOff = static_cast<uint8_t>(ANDROID_NOISE_REDUCTION_MODE_OFF); + uint8_t sharpOff = static_cast<uint8_t>(ANDROID_EDGE_MODE_OFF); + Vector<uint8_t> meteringStreamIds; + meteringStreamIds.push(meteringStreamId); + ASSERT_EQ(OK, mDevice->createDefaultRequest( + CAMERA2_TEMPLATE_PREVIEW, + &meteringRequest)); + ASSERT_EQ(OK, meteringRequest.update( + ANDROID_REQUEST_OUTPUT_STREAMS, + meteringStreamIds)); + ASSERT_EQ(OK, meteringRequest.update( + ANDROID_REQUEST_ID, + &requestId, 1)); + ASSERT_EQ(OK, meteringRequest.update( + ANDROID_CONTROL_MODE, + &cmOff, 1)); + ASSERT_EQ(OK, meteringRequest.update( + ANDROID_NOISE_REDUCTION_MODE, + &nrOff, 1)); + ASSERT_EQ(OK, meteringRequest.update( + ANDROID_EDGE_MODE, + &sharpOff, 1)); + + // Create capture request, manual settings + requestId++; + Vector<uint8_t> captureStreamIds; + captureStreamIds.push(captureStreamId); + ASSERT_EQ(OK, mDevice->createDefaultRequest( + CAMERA2_TEMPLATE_PREVIEW, + &captureRequest)); + ASSERT_EQ(OK, captureRequest.update( + ANDROID_REQUEST_OUTPUT_STREAMS, + captureStreamIds)); + ASSERT_EQ(OK, captureRequest.update( + ANDROID_REQUEST_ID, + &requestId, 1)); + ASSERT_EQ(OK, captureRequest.update( + ANDROID_CONTROL_MODE, + &cmOff, 1)); + ASSERT_EQ(OK, captureRequest.update( + ANDROID_NOISE_REDUCTION_MODE, + &nrOff, 1)); + ASSERT_EQ(OK, captureRequest.update( + ANDROID_EDGE_MODE, + &sharpOff, 1)); + } + + sp<CameraStream> CreateStream( + int width, + int height, + const sp<CameraDeviceBase>& device, + CameraStreamParams param = DEFAULT_STREAM_PARAMETERS, + sp<ANativeWindow> surface = NULL, + bool useCpuConsumer = true) { + param.mFormat = MapAutoFormat(param.mFormat); + return new CameraStream(width, height, device, + param, surface, useCpuConsumer); + } + + void CaptureBurst(CameraMetadata& request, size_t requestCount, + const Vector<int64_t>& exposures, + const Vector<int32_t>& sensitivities, + const sp<CameraStream>& stream, + int64_t minFrameDuration) { + ASSERT_EQ(OK, request.update(ANDROID_SENSOR_FRAME_DURATION, + &minFrameDuration, 1)); + // Submit a series of requests with the specified exposure/gain values. + for (size_t i = 0; i < requestCount; i++) { + ASSERT_EQ(OK, request.update(ANDROID_SENSOR_EXPOSURE_TIME, + &exposures[i], 1)); + ASSERT_EQ(OK, request.update(ANDROID_SENSOR_SENSITIVITY, + &sensitivities[i], 1)); + ASSERT_EQ(OK, mDevice->capture(request)); + ALOGV("Submitting capture %d with exposure %lld, sensitivity %d", + i, exposures[i], sensitivities[i]); + if (CAMERA_MULTI_STREAM_DEBUGGING) { + request.dump(STDOUT_FILENO); + } + } + // Get capture burst results. + Vector<nsecs_t> captureBurstTimes; + sp<CpuConsumer> consumer = stream->GetConsumer(); + sp<FrameListener> listener = stream->GetFrameListener(); + + // Set wait limit based on expected frame duration. + int64_t waitLimit = CAMERA_FRAME_TIMEOUT; + for (size_t i = 0; i < requestCount; i++) { + ALOGV("Reading request result %d", i); + + /** + * Raise the timeout to be at least twice as long as the exposure + * time. to avoid a false positive when the timeout is too short. + */ + if ((exposures[i] * EXP_WAIT_MULTIPLIER) > waitLimit) { + waitLimit = exposures[i] * EXP_WAIT_MULTIPLIER; + } + + ASSERT_EQ(OK, mDevice->waitForNextFrame(waitLimit)); + CameraMetadata frameMetadata; + ASSERT_EQ(OK, mDevice->getNextFrame(&frameMetadata)); + ALOGV("Got capture burst result for request %d", i); + // Validate capture result + if (CAMERA_MULTI_STREAM_DEBUGGING) { + frameMetadata.dump(STDOUT_FILENO); + } + + // TODO: Need revisit it to figure out an accurate margin. + EXPECT_EQ(sensitivities[i], GetSensitivity(frameMetadata)); + EXPECT_EQ(exposures[i], GetExposureValue(frameMetadata)); + + ASSERT_EQ(OK, listener->waitForFrame(waitLimit)); + captureBurstTimes.push_back(systemTime()); + CpuConsumer::LockedBuffer imgBuffer; + ASSERT_EQ(OK, consumer->lockNextBuffer(&imgBuffer)); + ALOGV("Got capture buffer for request %d", i); + + /** + * TODO: Validate capture buffer. Current brightness calculation + * is too slow, it also doesn't account for saturation effects, + * which is quite common since we are going over a significant + * range of EVs. we need figure out some reliable way to validate + * buffer data. + */ + + ASSERT_EQ(OK, consumer->unlockBuffer(imgBuffer)); + if (i > 0) { + nsecs_t timeDelta = + captureBurstTimes[i] - captureBurstTimes[i-1]; + EXPECT_GE(timeDelta, exposures[i]); + } + } + } + + /** + * Intentionally shadow default CreateStream function from base class, + * because we don't want any test in this class to use the default + * stream creation function. + */ + void CreateStream() { + } +}; + +/** + * This test adds multiple stream use case test, basically, test 3 + * streams: + * + * 1. Preview stream, with large size that is no bigger than 1080p + * we render this stream to display and vary the exposure time for + * for certain amount of time for visualization purpose. + * + * 2. Metering stream, with small size that is no bigger than VGA size. + * a burst is issued for different exposure times and analog gains + * (or analog gain implemented sensitivities) then check if the capture + * result metadata matches the request. + * + * 3. Capture stream, this is basically similar as meterting stream, but + * has large size, which is the largest supported JPEG capture size. + * + * This multiple stream test is to test if HAL supports: + * + * 1. Multiple streams like above, HAL should support at least 3 streams + * concurrently: one preview stream, 2 other YUV stream. + * + * 2. Manual control(gain/exposure) of mutiple burst capture. + */ +TEST_F(CameraMultiStreamTest, MultiBurst) { + + TEST_EXTENSION_FORKING_INIT; + + camera_metadata_ro_entry availableProcessedSizes = + GetStaticEntry(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES); + ASSERT_EQ(0u, availableProcessedSizes.count % 2); + ASSERT_GE(availableProcessedSizes.count, 2u); + camera_metadata_ro_entry availableProcessedMinFrameDurations = + GetStaticEntry(ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS); + EXPECT_EQ(availableProcessedSizes.count, + availableProcessedMinFrameDurations.count * 2); + + camera_metadata_ro_entry availableJpegSizes = + GetStaticEntry(ANDROID_SCALER_AVAILABLE_JPEG_SIZES); + ASSERT_EQ(0u, availableJpegSizes.count % 2); + ASSERT_GE(availableJpegSizes.count, 2u); + + // Find the right sizes for preview, metering, and capture streams + // assumes at least 2 entries in availableProcessedSizes. + int64_t minFrameDuration = DEFAULT_FRAME_DURATION; + Size processedMinSize, processedMaxSize, jpegMaxSize; + const int32_t* data = availableProcessedSizes.data.i32; + size_t count = availableProcessedSizes.count; + + int32_t minIdx, maxIdx; + GetMinSize(data, count, &processedMinSize, &minIdx); + GetMaxSize(data, count, &processedMaxSize, &maxIdx); + ALOGV("Found processed max size: %dx%d, min size = %dx%d", + processedMaxSize.width, processedMaxSize.height, + processedMinSize.width, processedMinSize.height); + + if (availableProcessedSizes.count == + availableProcessedMinFrameDurations.count * 2) { + minFrameDuration = + availableProcessedMinFrameDurations.data.i64[maxIdx / 2]; + } + + EXPECT_GT(minFrameDuration, 0); + + if (minFrameDuration <= 0) { + minFrameDuration = DEFAULT_FRAME_DURATION; + } + + ALOGV("targeted minimal frame duration is: %lldns", minFrameDuration); + + data = &(availableJpegSizes.data.i32[0]); + count = availableJpegSizes.count; + GetMaxSize(data, count, &jpegMaxSize, &maxIdx); + ALOGV("Found Jpeg size max idx = %d", maxIdx); + + // Max Jpeg size should be available in processed sizes. Use it for + // YUV capture anyway. + EXPECT_EQ(processedMaxSize.width, jpegMaxSize.width); + EXPECT_EQ(processedMaxSize.height, jpegMaxSize.height); + + // Cap preview size. + Size previewLimit = { PREVIEW_WIDTH_CAP, PREVIEW_HEIGHT_CAP }; + // FIXME: need make sure the previewLimit is supported by HAL. + Size previewSize = CapSize(previewLimit, processedMaxSize); + // Cap Metering size. + Size meteringLimit = { METERING_WIDTH_CAP, METERING_HEIGHT_CAP }; + // Cap metering size to VGA (VGA is mandatory by CDD) + Size meteringSize = CapSize(meteringLimit, processedMinSize); + // Capture stream should be the max size of jpeg sizes. + ALOGV("preview size: %dx%d, metering size: %dx%d, capture size: %dx%d", + previewSize.width, previewSize.height, + meteringSize.width, meteringSize.height, + jpegMaxSize.width, jpegMaxSize.height); + + // Create streams + // Preview stream: small resolution, render on the screen. + sp<CameraStream> previewStream; + { + sp<ANativeWindow> surface; + ASSERT_NO_FATAL_FAILURE(CreateOnScreenSurface(/*out*/surface)); + previewStream = CreateStream( + previewSize.width, + previewSize.height, + mDevice, + DISPLAY_STREAM_PARAMETERS, + surface, + false); + ASSERT_NE((void*)NULL, previewStream.get()); + ASSERT_NO_FATAL_FAILURE(previewStream->SetUp()); + } + // Metering burst stream: small resolution yuv stream + sp<CameraStream> meteringStream = + CreateStream( + meteringSize.width, + meteringSize.height, + mDevice); + ASSERT_NE((void*)NULL, meteringStream.get()); + ASSERT_NO_FATAL_FAILURE(meteringStream->SetUp()); + // Capture burst stream: full resolution yuv stream + sp<CameraStream> captureStream = + CreateStream( + jpegMaxSize.width, + jpegMaxSize.height, + mDevice); + ASSERT_NE((void*)NULL, captureStream.get()); + ASSERT_NO_FATAL_FAILURE(captureStream->SetUp()); + + // Create Preview request. + CameraMetadata previewRequest, meteringRequest, captureRequest; + ASSERT_NO_FATAL_FAILURE(CreateRequests(previewRequest, meteringRequest, + captureRequest, previewStream->GetStreamId(), + meteringStream->GetStreamId(), captureStream->GetStreamId())); + + // Start preview + if (CAMERA_MULTI_STREAM_DEBUGGING) { + previewRequest.dump(STDOUT_FILENO); + } + + // Generate exposure and sensitivity lists + camera_metadata_ro_entry exposureTimeRange = + GetStaticEntry(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE); + ASSERT_EQ(exposureTimeRange.count, 2u); + int64_t minExp = exposureTimeRange.data.i64[0]; + int64_t maxExp = exposureTimeRange.data.i64[1]; + ASSERT_GT(maxExp, minExp); + + camera_metadata_ro_entry sensivityRange = + GetStaticEntry(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE); + ASSERT_EQ(2u, sensivityRange.count); + int32_t minSensitivity = sensivityRange.data.i32[0]; + int32_t maxSensitivity = sensivityRange.data.i32[1]; + camera_metadata_ro_entry maxAnalogSenEntry = + GetStaticEntry(ANDROID_SENSOR_MAX_ANALOG_SENSITIVITY); + EXPECT_EQ(1u, maxAnalogSenEntry.count); + int32_t maxAnalogSensitivity = maxAnalogSenEntry.data.i32[0]; + EXPECT_LE(maxAnalogSensitivity, maxSensitivity); + // Only test the sensitivity implemented by analog gain. + if (maxAnalogSensitivity > maxSensitivity) { + // Fallback to maxSensitity + maxAnalogSensitivity = maxSensitivity; + } + + // sensitivity list, only include the sensitivities that are implemented + // purely by analog gain if possible. + Vector<int32_t> sensitivities; + Vector<int64_t> exposures; + count = (maxAnalogSensitivity - minSensitivity + 99) / 100; + sensitivities.push_back(minSensitivity); + for (size_t i = 1; i < count; i++) { + sensitivities.push_back(minSensitivity + i * 100); + } + sensitivities.push_back(maxAnalogSensitivity); + ALOGV("Sensitivity Range: min=%d, max=%d", minSensitivity, + maxAnalogSensitivity); + int64_t exp = minExp; + while (exp < maxExp) { + exposures.push_back(exp); + exp *= 2; + } + // Sweep the exposure value for preview, just for visual inspection purpose. + uint8_t cmOff = static_cast<uint8_t>(ANDROID_CONTROL_MODE_OFF); + for (size_t i = 0; i < exposures.size(); i++) { + ASSERT_EQ(OK, previewRequest.update( + ANDROID_CONTROL_MODE, + &cmOff, 1)); + ASSERT_EQ(OK, previewRequest.update( + ANDROID_SENSOR_EXPOSURE_TIME, + &exposures[i], 1)); + ALOGV("Submitting preview request %d with exposure %lld", + i, exposures[i]); + + ASSERT_EQ(OK, mDevice->setStreamingRequest(previewRequest)); + + // Let preview run 200ms on screen for each exposure time. + usleep(PREVIEW_RENDERING_TIME_INTERVAL); + } + + size_t requestCount = sensitivities.size(); + if (requestCount > exposures.size()) { + requestCount = exposures.size(); + } + + /** + * Submit metering request, set default frame duration to minimal possible + * value, we want the capture to run as fast as possible. HAL should adjust + * the frame duration to minimal necessary value to support the requested + * exposure value if exposure is larger than frame duration. + */ + CaptureBurst(meteringRequest, requestCount, exposures, sensitivities, + meteringStream, minFrameDuration); + + /** + * Submit capture request, set default frame duration to minimal possible + * value, we want the capture to run as fast as possible. HAL should adjust + * the frame duration to minimal necessary value to support the requested + * exposure value if exposure is larger than frame duration. + */ + CaptureBurst(captureRequest, requestCount, exposures, sensitivities, + captureStream, minFrameDuration); + + ASSERT_EQ(OK, mDevice->clearStreamingRequest()); +} + +} +} +} diff --git a/tests/camera2/CameraStreamFixture.h b/tests/camera2/CameraStreamFixture.h index 6b31544..a1f3aae 100644 --- a/tests/camera2/CameraStreamFixture.h +++ b/tests/camera2/CameraStreamFixture.h @@ -93,7 +93,6 @@ private: CameraModuleFixture::SetUp(); - CameraStreamParams p = mParam; sp<CameraDeviceBase> device = mDevice; /* use an arbitrary w,h */ diff --git a/tests/camera2/camera2.cpp b/tests/camera2/camera2.cpp index 17e4792..600d440 100644 --- a/tests/camera2/camera2.cpp +++ b/tests/camera2/camera2.cpp @@ -201,7 +201,8 @@ class Camera2Test: public testing::Test { if (mDevice != NULL) { closeCameraDevice(&mDevice); } - mDevice = openCameraDevice(id); + mId = id; + mDevice = openCameraDevice(mId); ASSERT_TRUE(NULL != mDevice) << "Failed to open camera device"; camera_info info; @@ -334,6 +335,7 @@ class Camera2Test: public testing::Test { TearDownModule(); } + int mId; camera2_device *mDevice; const camera_metadata_t *mStaticInfo; diff --git a/tests/camera2/camera2_utils.cpp b/tests/camera2/camera2_utils.cpp index 76a7233..3c0767a 100644 --- a/tests/camera2/camera2_utils.cpp +++ b/tests/camera2/camera2_utils.cpp @@ -210,7 +210,6 @@ int MetadataQueue::consumer_dequeue(const camera2_request_queue_src_ops_t *q, int MetadataQueue::consumer_free(const camera2_request_queue_src_ops_t *q, camera_metadata_t *old_buffer) { - MetadataQueue *queue = getInstance(q); free_camera_metadata(old_buffer); return OK; } |