blob: 6493f041830ab6ba4e94122d5bc713f448aff9ea [file] [log] [blame]
// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "camera3_test/camera3_preview_fixture.h"
#include <unistd.h>
#include <base/bind.h>
#include <base/command_line.h>
#include <base/strings/string_number_conversions.h>
namespace camera3_test {
void Camera3PreviewFixture::SetUp() {
ASSERT_EQ(0, cam_service_.Initialize(
Camera3Service::ProcessStillCaptureResultCallback(),
Camera3Service::ProcessRecordingResultCallback()))
<< "Failed to initialize camera service";
}
void Camera3PreviewFixture::TearDown() {
cam_service_.Destroy();
}
// Test parameters:
// - Camera ID
class Camera3SinglePreviewTest : public Camera3PreviewFixture,
public ::testing::WithParamInterface<int32_t> {
public:
const uint32_t kNumPreviewFrames = 10;
const uint32_t kTimeoutMsPerFrame = 1000;
Camera3SinglePreviewTest()
: Camera3PreviewFixture(std::vector<int>(1, GetParam())),
cam_id_(GetParam()) {}
protected:
int cam_id_;
};
TEST_P(Camera3SinglePreviewTest, Camera3BasicPreviewTest) {
auto resolutions =
cam_service_.GetStaticInfo(cam_id_)->GetSortedOutputResolutions(
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
for (const auto& resolution : resolutions) {
ResolutionInfo jpeg_resolution(0, 0), recording_resolution(0, 0);
ASSERT_EQ(0, cam_service_.StartPreview(cam_id_, resolution, jpeg_resolution,
recording_resolution))
<< "Starting preview fails";
ASSERT_EQ(0, cam_service_.WaitForPreviewFrames(cam_id_, kNumPreviewFrames,
kTimeoutMsPerFrame));
cam_service_.StopPreview(cam_id_);
}
}
// Test parameters:
// - Camera ID
class Camera3FaceDetectionTest : public Camera3PreviewFixture,
public ::testing::WithParamInterface<int32_t> {
public:
const uint32_t kNumPreviewFrames = 20;
const uint32_t kTimeoutMsPerFrame = 1000;
Camera3FaceDetectionTest()
: Camera3PreviewFixture(std::vector<int>(1, GetParam())),
cam_id_(GetParam()),
expected_num_faces_(GetCommandLineFaceDetectNumber()) {}
protected:
void SetUp() override;
void ProcessPreviewResult(int cam_id,
uint32_t frame_number,
ScopedCameraMetadata metadata);
int GetCommandLineFaceDetectNumber() {
std::string switch_value =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
"expected_num_faces");
if (switch_value == "") {
return -1;
}
int value;
if (!base::StringToInt(switch_value, &value)) {
LOG(ERROR) << "Failed to convert " << switch_value << " to int";
return -1;
}
if (value < 0) {
return -1;
}
return value;
}
void CheckNumOfFaces(int num_faces);
int cam_id_;
int expected_num_faces_;
private:
ScopedCameraMetadata result_metadata_;
};
void Camera3FaceDetectionTest::SetUp() {
ASSERT_EQ(0, cam_service_.Initialize(
Camera3Service::ProcessStillCaptureResultCallback(),
Camera3Service::ProcessRecordingResultCallback(),
base::Bind(&Camera3FaceDetectionTest::ProcessPreviewResult,
base::Unretained(this))))
<< "Failed to initialize camera service";
}
void Camera3FaceDetectionTest::ProcessPreviewResult(
int cam_id, uint32_t /*frame_number*/, ScopedCameraMetadata metadata) {
VLOGF_ENTER();
result_metadata_ = std::move(metadata);
}
void Camera3FaceDetectionTest::CheckNumOfFaces(int num_faces) {
ASSERT_NE(nullptr, result_metadata_.get())
<< "Result metadata is unavailable";
camera_metadata_ro_entry_t entry;
int result = find_camera_metadata_ro_entry(
result_metadata_.get(), ANDROID_STATISTICS_FACE_RECTANGLES, &entry);
// Accept no rectangles.
if (num_faces == 0 && result != 0) {
return;
}
ASSERT_EQ(0, result)
<< "Metadata key ANDROID_STATISTICS_FACE_RECTANGLES not found";
EXPECT_EQ(num_faces * 4, entry.count)
<< "Expect face rectangles size " << num_faces * 4 << " but detected "
<< entry.count;
ASSERT_EQ(
0, find_camera_metadata_ro_entry(result_metadata_.get(),
ANDROID_STATISTICS_FACE_SCORES, &entry))
<< "Metadata key ANDROID_STATISTICS_FACE_SCORES not found";
EXPECT_EQ(num_faces, entry.count)
<< "Expect " << num_faces << " faces, but detected " << entry.count
<< " faces";
result_metadata_.reset();
}
TEST_P(Camera3FaceDetectionTest, Detection) {
// Run only if --expected_num_faces argument presented.
if (expected_num_faces_ < 0) {
GTEST_SKIP();
}
auto IsAFSupported = [this]() {
std::vector<uint8_t> available_af_modes;
cam_service_.GetStaticInfo(cam_id_)->GetAvailableAFModes(
&available_af_modes);
uint8_t af_modes[] = {ANDROID_CONTROL_AF_MODE_AUTO,
ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE,
ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO,
ANDROID_CONTROL_AF_MODE_MACRO};
for (const auto& it : af_modes) {
if (std::find(available_af_modes.begin(), available_af_modes.end(), it) !=
available_af_modes.end()) {
return true;
}
}
return false;
};
ASSERT_TRUE(cam_service_.GetStaticInfo(cam_id_)->IsKeyAvailable(
ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES))
<< "NO ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES key in static "
"info";
std::set<uint8_t> face_detect_modes;
ASSERT_EQ(0, cam_service_.GetStaticInfo(cam_id_)->GetAvailableFaceDetectModes(
&face_detect_modes) != 0)
<< "Failed to get face detect modes";
ASSERT_NE(face_detect_modes.find(ANDROID_STATISTICS_FACE_DETECT_MODE_SIMPLE),
face_detect_modes.end())
<< "Can't find ANDROID_STATISTICS_FACE_DETECT_MODE_SIMPLE";
auto resolution =
cam_service_.GetStaticInfo(cam_id_)
->GetSortedOutputResolutions(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)
.back();
ResolutionInfo jpeg_resolution(0, 0), recording_resolution(0, 0);
ASSERT_EQ(0, cam_service_.StartPreview(cam_id_, resolution, jpeg_resolution,
recording_resolution))
<< "Starting preview fails";
// Trigger an auto focus run, and wait for AF locked.
if (IsAFSupported()) {
cam_service_.StartAutoFocus(cam_id_);
ASSERT_EQ(0, cam_service_.WaitForAutoFocusDone(cam_id_))
<< "Wait for auto focus done timed out";
}
// Wait for AWB converged, then lock it.
ASSERT_EQ(0, cam_service_.WaitForAWBConvergedAndLock(cam_id_))
<< "Wait for AWB converged timed out";
// Trigger an AE precapture metering sequence and wait for AE converged.
cam_service_.StartAEPrecapture(cam_id_);
ASSERT_EQ(0, cam_service_.WaitForAEStable(cam_id_))
<< "Wait for AE stable timed out";
// Check there is no face detected before enabling face detection
ASSERT_EQ(0, cam_service_.WaitForPreviewFrames(cam_id_, kNumPreviewFrames,
kTimeoutMsPerFrame));
CheckNumOfFaces(0);
cam_service_.StartFaceDetection(cam_id_);
ASSERT_EQ(0, cam_service_.WaitForPreviewFrames(cam_id_, kNumPreviewFrames,
kTimeoutMsPerFrame));
CheckNumOfFaces(expected_num_faces_);
// Check no face detected after stop face detection
cam_service_.StopFaceDetection(cam_id_);
ASSERT_EQ(0, cam_service_.WaitForPreviewFrames(cam_id_, kNumPreviewFrames,
kTimeoutMsPerFrame));
CheckNumOfFaces(0);
cam_service_.StopPreview(cam_id_);
}
INSTANTIATE_TEST_SUITE_P(
Camera3PreviewTest,
Camera3SinglePreviewTest,
::testing::ValuesIn(Camera3Module().GetTestCameraIds()));
INSTANTIATE_TEST_SUITE_P(
Camera3PreviewTest,
Camera3FaceDetectionTest,
::testing::ValuesIn(Camera3Module().GetTestCameraIds()));
} // namespace camera3_test