Merge "Camera: Add sensor sensitivity burst test"
This commit is contained in:
commit
2e8bcf7a30
1 changed files with 160 additions and 0 deletions
|
@ -116,6 +116,7 @@ const int64_t kAutoFocusTimeoutSec = 5;
|
||||||
const int64_t kTorchTimeoutSec = 1;
|
const int64_t kTorchTimeoutSec = 1;
|
||||||
const int64_t kEmptyFlushTimeoutMSec = 200;
|
const int64_t kEmptyFlushTimeoutMSec = 200;
|
||||||
const char kDumpOutput[] = "/dev/null";
|
const char kDumpOutput[] = "/dev/null";
|
||||||
|
const uint32_t kBurstFrameCount = 10;
|
||||||
|
|
||||||
struct AvailableStream {
|
struct AvailableStream {
|
||||||
int32_t width;
|
int32_t width;
|
||||||
|
@ -719,6 +720,20 @@ protected:
|
||||||
// return from HAL but framework.
|
// return from HAL but framework.
|
||||||
::android::Vector<StreamBuffer> resultOutputBuffers;
|
::android::Vector<StreamBuffer> resultOutputBuffers;
|
||||||
|
|
||||||
|
InFlightRequest() :
|
||||||
|
shutterTimestamp(0),
|
||||||
|
errorCodeValid(false),
|
||||||
|
errorCode(ErrorCode::ERROR_BUFFER),
|
||||||
|
usePartialResult(false),
|
||||||
|
numPartialResults(0),
|
||||||
|
resultQueue(nullptr),
|
||||||
|
haveResultMetadata(false),
|
||||||
|
numBuffersLeft(0),
|
||||||
|
frameNumber(0),
|
||||||
|
partialResultCount(0),
|
||||||
|
errorStreamId(-1),
|
||||||
|
hasInputBuffer(false) {}
|
||||||
|
|
||||||
InFlightRequest(ssize_t numBuffers, bool hasInput,
|
InFlightRequest(ssize_t numBuffers, bool hasInput,
|
||||||
bool partialResults, uint32_t partialCount,
|
bool partialResults, uint32_t partialCount,
|
||||||
std::shared_ptr<ResultMetadataQueue> queue = nullptr) :
|
std::shared_ptr<ResultMetadataQueue> queue = nullptr) :
|
||||||
|
@ -3547,6 +3562,151 @@ TEST_F(CameraHidlTest, processMultiCaptureRequestPreview) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate and verify a burst containing alternating sensor sensitivity values
|
||||||
|
TEST_F(CameraHidlTest, processCaptureRequestBurstISO) {
|
||||||
|
hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
|
||||||
|
AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
|
||||||
|
static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
|
||||||
|
uint64_t bufferId = 1;
|
||||||
|
uint32_t frameNumber = 1;
|
||||||
|
::android::hardware::hidl_vec<uint8_t> settings;
|
||||||
|
|
||||||
|
for (const auto& name : cameraDeviceNames) {
|
||||||
|
int deviceVersion = getCameraDeviceVersion(name, mProviderType);
|
||||||
|
if (deviceVersion == CAMERA_DEVICE_API_VERSION_1_0) {
|
||||||
|
continue;
|
||||||
|
} else if (deviceVersion <= 0) {
|
||||||
|
ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
|
||||||
|
ADD_FAILURE();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
camera_metadata_t* staticMetaBuffer;
|
||||||
|
Return<void> ret;
|
||||||
|
sp<ICameraDeviceSession> session;
|
||||||
|
openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMetaBuffer /*out*/);
|
||||||
|
::android::hardware::camera::common::V1_0::helper::CameraMetadata staticMeta(
|
||||||
|
staticMetaBuffer);
|
||||||
|
|
||||||
|
camera_metadata_entry_t hwLevel = staticMeta.find(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL);
|
||||||
|
ASSERT_TRUE(0 < hwLevel.count);
|
||||||
|
if (ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED == hwLevel.data.u8[0]) {
|
||||||
|
//Limited devices can skip this test
|
||||||
|
ret = session->close();
|
||||||
|
ASSERT_TRUE(ret.isOk());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
camera_metadata_entry_t isoRange = staticMeta.find(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE);
|
||||||
|
ASSERT_EQ(isoRange.count, 2u);
|
||||||
|
|
||||||
|
ret = session->close();
|
||||||
|
ASSERT_TRUE(ret.isOk());
|
||||||
|
|
||||||
|
bool supportsPartialResults = false;
|
||||||
|
uint32_t partialResultCount = 0;
|
||||||
|
V3_2::Stream previewStream;
|
||||||
|
HalStreamConfiguration halStreamConfig;
|
||||||
|
configurePreviewStream(name, deviceVersion, mProvider, &previewThreshold,
|
||||||
|
&session /*out*/, &previewStream /*out*/, &halStreamConfig /*out*/,
|
||||||
|
&supportsPartialResults /*out*/, &partialResultCount /*out*/);
|
||||||
|
std::shared_ptr<ResultMetadataQueue> resultQueue;
|
||||||
|
|
||||||
|
auto resultQueueRet = session->getCaptureResultMetadataQueue(
|
||||||
|
[&resultQueue](const auto& descriptor) {
|
||||||
|
resultQueue = std::make_shared<ResultMetadataQueue>(descriptor);
|
||||||
|
if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
|
||||||
|
ALOGE("%s: HAL returns empty result metadata fmq,"
|
||||||
|
" not use it", __func__);
|
||||||
|
resultQueue = nullptr;
|
||||||
|
// Don't use the queue onwards.
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ASSERT_TRUE(resultQueueRet.isOk());
|
||||||
|
ASSERT_NE(nullptr, resultQueue);
|
||||||
|
|
||||||
|
ret = session->constructDefaultRequestSettings(RequestTemplate::PREVIEW,
|
||||||
|
[&](auto status, const auto& req) {
|
||||||
|
ASSERT_EQ(Status::OK, status);
|
||||||
|
settings = req; });
|
||||||
|
ASSERT_TRUE(ret.isOk());
|
||||||
|
|
||||||
|
::android::hardware::camera::common::V1_0::helper::CameraMetadata requestMeta;
|
||||||
|
StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr, nullptr};
|
||||||
|
sp<GraphicBuffer> buffers[kBurstFrameCount];
|
||||||
|
StreamBuffer outputBuffers[kBurstFrameCount];
|
||||||
|
CaptureRequest requests[kBurstFrameCount];
|
||||||
|
InFlightRequest inflightReqs[kBurstFrameCount];
|
||||||
|
int32_t isoValues[kBurstFrameCount];
|
||||||
|
hidl_vec<uint8_t> requestSettings[kBurstFrameCount];
|
||||||
|
for (uint32_t i = 0; i < kBurstFrameCount; i++) {
|
||||||
|
std::unique_lock<std::mutex> l(mLock);
|
||||||
|
|
||||||
|
isoValues[i] = ((i % 2) == 0) ? isoRange.data.i32[0] : isoRange.data.i32[1];
|
||||||
|
buffers[i] = new GraphicBuffer( previewStream.width, previewStream.height,
|
||||||
|
static_cast<int32_t>(halStreamConfig.streams[0].overrideFormat), 1,
|
||||||
|
android_convertGralloc1To0Usage( halStreamConfig.streams[0].producerUsage,
|
||||||
|
halStreamConfig.streams[0].consumerUsage));
|
||||||
|
ASSERT_NE(nullptr, buffers[i].get());
|
||||||
|
|
||||||
|
outputBuffers[i] = {halStreamConfig.streams[0].id, bufferId + i,
|
||||||
|
hidl_handle( buffers[i]->getNativeBuffer()->handle), BufferStatus::OK, nullptr,
|
||||||
|
nullptr};
|
||||||
|
requestMeta.append(reinterpret_cast<camera_metadata_t *> (settings.data()));
|
||||||
|
|
||||||
|
// Disable all 3A routines
|
||||||
|
uint8_t mode = static_cast<uint8_t>(ANDROID_CONTROL_MODE_OFF);
|
||||||
|
ASSERT_EQ(::android::OK, requestMeta.update(ANDROID_CONTROL_MODE, &mode, 1));
|
||||||
|
ASSERT_EQ(::android::OK, requestMeta.update(ANDROID_SENSOR_SENSITIVITY, &isoValues[i],
|
||||||
|
1));
|
||||||
|
camera_metadata_t *metaBuffer = requestMeta.release();
|
||||||
|
requestSettings[i].setToExternal(reinterpret_cast<uint8_t *> (metaBuffer),
|
||||||
|
get_camera_metadata_size(metaBuffer), true);
|
||||||
|
|
||||||
|
requests[i] = {frameNumber + i, 0 /* fmqSettingsSize */, requestSettings[i],
|
||||||
|
emptyInputBuffer, {outputBuffers[i]}};
|
||||||
|
|
||||||
|
inflightReqs[i] = {1, false, supportsPartialResults, partialResultCount, resultQueue};
|
||||||
|
mInflightMap.add(frameNumber + i, &inflightReqs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status status = Status::INTERNAL_ERROR;
|
||||||
|
uint32_t numRequestProcessed = 0;
|
||||||
|
hidl_vec<BufferCache> cachesToRemove;
|
||||||
|
hidl_vec<CaptureRequest> burstRequest;
|
||||||
|
burstRequest.setToExternal(requests, kBurstFrameCount);
|
||||||
|
Return<void> returnStatus = session->processCaptureRequest(burstRequest, cachesToRemove,
|
||||||
|
[&status, &numRequestProcessed] (auto s, uint32_t n) {
|
||||||
|
status = s;
|
||||||
|
numRequestProcessed = n;
|
||||||
|
});
|
||||||
|
ASSERT_TRUE(returnStatus.isOk());
|
||||||
|
ASSERT_EQ(Status::OK, status);
|
||||||
|
ASSERT_EQ(numRequestProcessed, kBurstFrameCount);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < kBurstFrameCount; i++) {
|
||||||
|
std::unique_lock<std::mutex> l(mLock);
|
||||||
|
while (!inflightReqs[i].errorCodeValid && ((0 < inflightReqs[i].numBuffersLeft) ||
|
||||||
|
(!inflightReqs[i].haveResultMetadata))) {
|
||||||
|
auto timeout = std::chrono::system_clock::now() +
|
||||||
|
std::chrono::seconds(kStreamBufferTimeoutSec);
|
||||||
|
ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_FALSE(inflightReqs[i].errorCodeValid);
|
||||||
|
ASSERT_NE(inflightReqs[i].resultOutputBuffers.size(), 0u);
|
||||||
|
ASSERT_EQ(previewStream.id, inflightReqs[i].resultOutputBuffers[0].streamId);
|
||||||
|
ASSERT_FALSE(inflightReqs[i].collectedResult.isEmpty());
|
||||||
|
ASSERT_TRUE(inflightReqs[i].collectedResult.exists(ANDROID_SENSOR_SENSITIVITY));
|
||||||
|
camera_metadata_entry_t isoResult = inflightReqs[i].collectedResult.find(
|
||||||
|
ANDROID_SENSOR_SENSITIVITY);
|
||||||
|
ASSERT_TRUE(isoResult.data.i32[0] == isoValues[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = session->close();
|
||||||
|
ASSERT_TRUE(ret.isOk());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Test whether an incorrect capture request with missing settings will
|
// Test whether an incorrect capture request with missing settings will
|
||||||
// be reported correctly.
|
// be reported correctly.
|
||||||
TEST_F(CameraHidlTest, processCaptureRequestInvalidSinglePreview) {
|
TEST_F(CameraHidlTest, processCaptureRequestInvalidSinglePreview) {
|
||||||
|
|
Loading…
Reference in a new issue